10afa8e06SEd Maste /* 2*f540a430SEd Maste * Copyright (c) 2019-2021 Yubico AB. All rights reserved. 30afa8e06SEd Maste * Use of this source code is governed by a BSD-style 40afa8e06SEd Maste * license that can be found in the LICENSE file. 50afa8e06SEd Maste */ 60afa8e06SEd Maste 70afa8e06SEd Maste #include <assert.h> 8*f540a430SEd Maste #include <err.h> 90afa8e06SEd Maste #include <fido.h> 100afa8e06SEd Maste #include <string.h> 11*f540a430SEd Maste #include <time.h> 120afa8e06SEd Maste 130afa8e06SEd Maste #include "../fuzz/wiredata_fido2.h" 140afa8e06SEd Maste 150afa8e06SEd Maste #define FAKE_DEV_HANDLE ((void *)0xdeadbeef) 160afa8e06SEd Maste #define REPORT_LEN (64 + 1) 170afa8e06SEd Maste 180afa8e06SEd Maste static uint8_t ctap_nonce[8]; 190afa8e06SEd Maste static uint8_t *wiredata_ptr; 200afa8e06SEd Maste static size_t wiredata_len; 210afa8e06SEd Maste static int initialised; 22*f540a430SEd Maste static long interval_ms; 230afa8e06SEd Maste 240afa8e06SEd Maste static void * 250afa8e06SEd Maste dummy_open(const char *path) 260afa8e06SEd Maste { 270afa8e06SEd Maste (void)path; 280afa8e06SEd Maste 290afa8e06SEd Maste return (FAKE_DEV_HANDLE); 300afa8e06SEd Maste } 310afa8e06SEd Maste 320afa8e06SEd Maste static void 330afa8e06SEd Maste dummy_close(void *handle) 340afa8e06SEd Maste { 350afa8e06SEd Maste assert(handle == FAKE_DEV_HANDLE); 360afa8e06SEd Maste } 370afa8e06SEd Maste 380afa8e06SEd Maste static int 390afa8e06SEd Maste dummy_read(void *handle, unsigned char *ptr, size_t len, int ms) 400afa8e06SEd Maste { 41*f540a430SEd Maste struct timespec tv; 420afa8e06SEd Maste size_t n; 43*f540a430SEd Maste long d; 440afa8e06SEd Maste 450afa8e06SEd Maste assert(handle == FAKE_DEV_HANDLE); 460afa8e06SEd Maste assert(ptr != NULL); 470afa8e06SEd Maste assert(len == REPORT_LEN - 1); 480afa8e06SEd Maste 490afa8e06SEd Maste if (wiredata_ptr == NULL) 500afa8e06SEd Maste return (-1); 510afa8e06SEd Maste 520afa8e06SEd Maste if (!initialised) { 530afa8e06SEd Maste assert(wiredata_len >= REPORT_LEN - 1); 540afa8e06SEd Maste memcpy(&wiredata_ptr[7], &ctap_nonce, sizeof(ctap_nonce)); 550afa8e06SEd Maste initialised = 1; 560afa8e06SEd Maste } 570afa8e06SEd Maste 58*f540a430SEd Maste if (ms >= 0 && ms < interval_ms) 59*f540a430SEd Maste d = ms; 60*f540a430SEd Maste else 61*f540a430SEd Maste d = interval_ms; 62*f540a430SEd Maste 63*f540a430SEd Maste if (d) { 64*f540a430SEd Maste tv.tv_sec = d / 1000; 65*f540a430SEd Maste tv.tv_nsec = (d % 1000) * 1000000; 66*f540a430SEd Maste if (nanosleep(&tv, NULL) == -1) 67*f540a430SEd Maste err(1, "nanosleep"); 68*f540a430SEd Maste } 69*f540a430SEd Maste 70*f540a430SEd Maste if (d != interval_ms) 71*f540a430SEd Maste return (-1); /* timeout */ 72*f540a430SEd Maste 730afa8e06SEd Maste if (wiredata_len < len) 740afa8e06SEd Maste n = wiredata_len; 750afa8e06SEd Maste else 760afa8e06SEd Maste n = len; 770afa8e06SEd Maste 780afa8e06SEd Maste memcpy(ptr, wiredata_ptr, n); 790afa8e06SEd Maste wiredata_ptr += n; 800afa8e06SEd Maste wiredata_len -= n; 810afa8e06SEd Maste 820afa8e06SEd Maste return ((int)n); 830afa8e06SEd Maste } 840afa8e06SEd Maste 850afa8e06SEd Maste static int 860afa8e06SEd Maste dummy_write(void *handle, const unsigned char *ptr, size_t len) 870afa8e06SEd Maste { 88*f540a430SEd Maste struct timespec tv; 89*f540a430SEd Maste 900afa8e06SEd Maste assert(handle == FAKE_DEV_HANDLE); 910afa8e06SEd Maste assert(ptr != NULL); 920afa8e06SEd Maste assert(len == REPORT_LEN); 930afa8e06SEd Maste 940afa8e06SEd Maste if (!initialised) 950afa8e06SEd Maste memcpy(&ctap_nonce, &ptr[8], sizeof(ctap_nonce)); 960afa8e06SEd Maste 97*f540a430SEd Maste if (interval_ms) { 98*f540a430SEd Maste tv.tv_sec = interval_ms / 1000; 99*f540a430SEd Maste tv.tv_nsec = (interval_ms % 1000) * 1000000; 100*f540a430SEd Maste if (nanosleep(&tv, NULL) == -1) 101*f540a430SEd Maste err(1, "nanosleep"); 102*f540a430SEd Maste } 103*f540a430SEd Maste 1040afa8e06SEd Maste return ((int)len); 1050afa8e06SEd Maste } 1060afa8e06SEd Maste 1070afa8e06SEd Maste static uint8_t * 1080afa8e06SEd Maste wiredata_setup(const uint8_t *data, size_t len) 1090afa8e06SEd Maste { 1100afa8e06SEd Maste const uint8_t ctap_init_data[] = { WIREDATA_CTAP_INIT }; 1110afa8e06SEd Maste 1120afa8e06SEd Maste assert(wiredata_ptr == NULL); 1130afa8e06SEd Maste assert(SIZE_MAX - len > sizeof(ctap_init_data)); 1140afa8e06SEd Maste assert((wiredata_ptr = malloc(sizeof(ctap_init_data) + len)) != NULL); 1150afa8e06SEd Maste 1160afa8e06SEd Maste memcpy(wiredata_ptr, ctap_init_data, sizeof(ctap_init_data)); 1170afa8e06SEd Maste 1180afa8e06SEd Maste if (len) 1190afa8e06SEd Maste memcpy(wiredata_ptr + sizeof(ctap_init_data), data, len); 1200afa8e06SEd Maste 1210afa8e06SEd Maste wiredata_len = sizeof(ctap_init_data) + len; 1220afa8e06SEd Maste 1230afa8e06SEd Maste return (wiredata_ptr); 1240afa8e06SEd Maste } 1250afa8e06SEd Maste 1260afa8e06SEd Maste static void 1270afa8e06SEd Maste wiredata_clear(uint8_t **wiredata) 1280afa8e06SEd Maste { 1290afa8e06SEd Maste free(*wiredata); 1300afa8e06SEd Maste *wiredata = NULL; 1310afa8e06SEd Maste wiredata_ptr = NULL; 1320afa8e06SEd Maste wiredata_len = 0; 1330afa8e06SEd Maste initialised = 0; 1340afa8e06SEd Maste } 1350afa8e06SEd Maste 1360afa8e06SEd Maste /* gh#56 */ 1370afa8e06SEd Maste static void 1380afa8e06SEd Maste open_iff_ok(void) 1390afa8e06SEd Maste { 1400afa8e06SEd Maste fido_dev_t *dev = NULL; 1410afa8e06SEd Maste fido_dev_io_t io; 1420afa8e06SEd Maste 1430afa8e06SEd Maste memset(&io, 0, sizeof(io)); 1440afa8e06SEd Maste 1450afa8e06SEd Maste io.open = dummy_open; 1460afa8e06SEd Maste io.close = dummy_close; 1470afa8e06SEd Maste io.read = dummy_read; 1480afa8e06SEd Maste io.write = dummy_write; 1490afa8e06SEd Maste 1500afa8e06SEd Maste assert((dev = fido_dev_new()) != NULL); 1510afa8e06SEd Maste assert(fido_dev_set_io_functions(dev, &io) == FIDO_OK); 1520afa8e06SEd Maste assert(fido_dev_open(dev, "dummy") == FIDO_ERR_RX); 1530afa8e06SEd Maste assert(fido_dev_close(dev) == FIDO_ERR_INVALID_ARGUMENT); 1540afa8e06SEd Maste 1550afa8e06SEd Maste fido_dev_free(&dev); 1560afa8e06SEd Maste } 1570afa8e06SEd Maste 1580afa8e06SEd Maste static void 1590afa8e06SEd Maste reopen(void) 1600afa8e06SEd Maste { 1610afa8e06SEd Maste const uint8_t cbor_info_data[] = { WIREDATA_CTAP_CBOR_INFO }; 1620afa8e06SEd Maste uint8_t *wiredata; 1630afa8e06SEd Maste fido_dev_t *dev = NULL; 1640afa8e06SEd Maste fido_dev_io_t io; 1650afa8e06SEd Maste 1660afa8e06SEd Maste memset(&io, 0, sizeof(io)); 1670afa8e06SEd Maste 1680afa8e06SEd Maste io.open = dummy_open; 1690afa8e06SEd Maste io.close = dummy_close; 1700afa8e06SEd Maste io.read = dummy_read; 1710afa8e06SEd Maste io.write = dummy_write; 1720afa8e06SEd Maste 1730afa8e06SEd Maste wiredata = wiredata_setup(cbor_info_data, sizeof(cbor_info_data)); 1740afa8e06SEd Maste assert((dev = fido_dev_new()) != NULL); 1750afa8e06SEd Maste assert(fido_dev_set_io_functions(dev, &io) == FIDO_OK); 1760afa8e06SEd Maste assert(fido_dev_open(dev, "dummy") == FIDO_OK); 1770afa8e06SEd Maste assert(fido_dev_close(dev) == FIDO_OK); 1780afa8e06SEd Maste wiredata_clear(&wiredata); 1790afa8e06SEd Maste 1800afa8e06SEd Maste wiredata = wiredata_setup(cbor_info_data, sizeof(cbor_info_data)); 1810afa8e06SEd Maste assert(fido_dev_open(dev, "dummy") == FIDO_OK); 1820afa8e06SEd Maste assert(fido_dev_close(dev) == FIDO_OK); 183*f540a430SEd Maste fido_dev_free(&dev); 1840afa8e06SEd Maste wiredata_clear(&wiredata); 1850afa8e06SEd Maste } 1860afa8e06SEd Maste 1870afa8e06SEd Maste static void 1880afa8e06SEd Maste double_open(void) 1890afa8e06SEd Maste { 1900afa8e06SEd Maste const uint8_t cbor_info_data[] = { WIREDATA_CTAP_CBOR_INFO }; 1910afa8e06SEd Maste uint8_t *wiredata; 1920afa8e06SEd Maste fido_dev_t *dev = NULL; 1930afa8e06SEd Maste fido_dev_io_t io; 1940afa8e06SEd Maste 1950afa8e06SEd Maste memset(&io, 0, sizeof(io)); 1960afa8e06SEd Maste 1970afa8e06SEd Maste io.open = dummy_open; 1980afa8e06SEd Maste io.close = dummy_close; 1990afa8e06SEd Maste io.read = dummy_read; 2000afa8e06SEd Maste io.write = dummy_write; 2010afa8e06SEd Maste 2020afa8e06SEd Maste wiredata = wiredata_setup(cbor_info_data, sizeof(cbor_info_data)); 2030afa8e06SEd Maste assert((dev = fido_dev_new()) != NULL); 2040afa8e06SEd Maste assert(fido_dev_set_io_functions(dev, &io) == FIDO_OK); 2050afa8e06SEd Maste assert(fido_dev_open(dev, "dummy") == FIDO_OK); 2060afa8e06SEd Maste assert(fido_dev_open(dev, "dummy") == FIDO_ERR_INVALID_ARGUMENT); 2070afa8e06SEd Maste assert(fido_dev_close(dev) == FIDO_OK); 208*f540a430SEd Maste fido_dev_free(&dev); 209*f540a430SEd Maste wiredata_clear(&wiredata); 210*f540a430SEd Maste } 211*f540a430SEd Maste 212*f540a430SEd Maste static void 213*f540a430SEd Maste double_close(void) 214*f540a430SEd Maste { 215*f540a430SEd Maste const uint8_t cbor_info_data[] = { WIREDATA_CTAP_CBOR_INFO }; 216*f540a430SEd Maste uint8_t *wiredata; 217*f540a430SEd Maste fido_dev_t *dev = NULL; 218*f540a430SEd Maste fido_dev_io_t io; 219*f540a430SEd Maste 220*f540a430SEd Maste memset(&io, 0, sizeof(io)); 221*f540a430SEd Maste 222*f540a430SEd Maste io.open = dummy_open; 223*f540a430SEd Maste io.close = dummy_close; 224*f540a430SEd Maste io.read = dummy_read; 225*f540a430SEd Maste io.write = dummy_write; 226*f540a430SEd Maste 227*f540a430SEd Maste wiredata = wiredata_setup(cbor_info_data, sizeof(cbor_info_data)); 228*f540a430SEd Maste assert((dev = fido_dev_new()) != NULL); 229*f540a430SEd Maste assert(fido_dev_close(dev) == FIDO_ERR_INVALID_ARGUMENT); 230*f540a430SEd Maste assert(fido_dev_set_io_functions(dev, &io) == FIDO_OK); 231*f540a430SEd Maste assert(fido_dev_close(dev) == FIDO_ERR_INVALID_ARGUMENT); 232*f540a430SEd Maste assert(fido_dev_open(dev, "dummy") == FIDO_OK); 233*f540a430SEd Maste assert(fido_dev_close(dev) == FIDO_OK); 234*f540a430SEd Maste assert(fido_dev_close(dev) == FIDO_ERR_INVALID_ARGUMENT); 235*f540a430SEd Maste fido_dev_free(&dev); 2360afa8e06SEd Maste wiredata_clear(&wiredata); 2370afa8e06SEd Maste } 2380afa8e06SEd Maste 2390afa8e06SEd Maste static void 2400afa8e06SEd Maste is_fido2(void) 2410afa8e06SEd Maste { 2420afa8e06SEd Maste const uint8_t cbor_info_data[] = { WIREDATA_CTAP_CBOR_INFO }; 2430afa8e06SEd Maste uint8_t *wiredata; 2440afa8e06SEd Maste fido_dev_t *dev = NULL; 2450afa8e06SEd Maste fido_dev_io_t io; 2460afa8e06SEd Maste 2470afa8e06SEd Maste memset(&io, 0, sizeof(io)); 2480afa8e06SEd Maste 2490afa8e06SEd Maste io.open = dummy_open; 2500afa8e06SEd Maste io.close = dummy_close; 2510afa8e06SEd Maste io.read = dummy_read; 2520afa8e06SEd Maste io.write = dummy_write; 2530afa8e06SEd Maste 2540afa8e06SEd Maste wiredata = wiredata_setup(cbor_info_data, sizeof(cbor_info_data)); 2550afa8e06SEd Maste assert((dev = fido_dev_new()) != NULL); 2560afa8e06SEd Maste assert(fido_dev_set_io_functions(dev, &io) == FIDO_OK); 2570afa8e06SEd Maste assert(fido_dev_open(dev, "dummy") == FIDO_OK); 2580afa8e06SEd Maste assert(fido_dev_is_fido2(dev) == true); 2590afa8e06SEd Maste assert(fido_dev_supports_pin(dev) == true); 2600afa8e06SEd Maste fido_dev_force_u2f(dev); 2610afa8e06SEd Maste assert(fido_dev_is_fido2(dev) == false); 2620afa8e06SEd Maste assert(fido_dev_supports_pin(dev) == false); 2630afa8e06SEd Maste assert(fido_dev_close(dev) == FIDO_OK); 2640afa8e06SEd Maste wiredata_clear(&wiredata); 2650afa8e06SEd Maste 2660afa8e06SEd Maste wiredata = wiredata_setup(NULL, 0); 2670afa8e06SEd Maste assert(fido_dev_open(dev, "dummy") == FIDO_OK); 2680afa8e06SEd Maste assert(fido_dev_is_fido2(dev) == false); 2690afa8e06SEd Maste assert(fido_dev_supports_pin(dev) == false); 2700afa8e06SEd Maste fido_dev_force_fido2(dev); 2710afa8e06SEd Maste assert(fido_dev_is_fido2(dev) == true); 2720afa8e06SEd Maste assert(fido_dev_supports_pin(dev) == false); 2730afa8e06SEd Maste assert(fido_dev_close(dev) == FIDO_OK); 274*f540a430SEd Maste fido_dev_free(&dev); 2750afa8e06SEd Maste wiredata_clear(&wiredata); 2760afa8e06SEd Maste } 2770afa8e06SEd Maste 2780afa8e06SEd Maste static void 2790afa8e06SEd Maste has_pin(void) 2800afa8e06SEd Maste { 2810afa8e06SEd Maste const uint8_t set_pin_data[] = { 2820afa8e06SEd Maste WIREDATA_CTAP_CBOR_INFO, 2830afa8e06SEd Maste WIREDATA_CTAP_CBOR_AUTHKEY, 2840afa8e06SEd Maste WIREDATA_CTAP_CBOR_STATUS, 2850afa8e06SEd Maste WIREDATA_CTAP_CBOR_STATUS 2860afa8e06SEd Maste }; 2870afa8e06SEd Maste uint8_t *wiredata; 2880afa8e06SEd Maste fido_dev_t *dev = NULL; 2890afa8e06SEd Maste fido_dev_io_t io; 2900afa8e06SEd Maste 2910afa8e06SEd Maste memset(&io, 0, sizeof(io)); 2920afa8e06SEd Maste 2930afa8e06SEd Maste io.open = dummy_open; 2940afa8e06SEd Maste io.close = dummy_close; 2950afa8e06SEd Maste io.read = dummy_read; 2960afa8e06SEd Maste io.write = dummy_write; 2970afa8e06SEd Maste 2980afa8e06SEd Maste wiredata = wiredata_setup(set_pin_data, sizeof(set_pin_data)); 2990afa8e06SEd Maste assert((dev = fido_dev_new()) != NULL); 3000afa8e06SEd Maste assert(fido_dev_set_io_functions(dev, &io) == FIDO_OK); 3010afa8e06SEd Maste assert(fido_dev_open(dev, "dummy") == FIDO_OK); 3020afa8e06SEd Maste assert(fido_dev_has_pin(dev) == false); 3030afa8e06SEd Maste assert(fido_dev_set_pin(dev, "top secret", NULL) == FIDO_OK); 3040afa8e06SEd Maste assert(fido_dev_has_pin(dev) == true); 3050afa8e06SEd Maste assert(fido_dev_reset(dev) == FIDO_OK); 3060afa8e06SEd Maste assert(fido_dev_has_pin(dev) == false); 3070afa8e06SEd Maste assert(fido_dev_close(dev) == FIDO_OK); 308*f540a430SEd Maste fido_dev_free(&dev); 3090afa8e06SEd Maste wiredata_clear(&wiredata); 3100afa8e06SEd Maste } 3110afa8e06SEd Maste 312*f540a430SEd Maste static void 313*f540a430SEd Maste timeout_rx(void) 314*f540a430SEd Maste { 315*f540a430SEd Maste const uint8_t timeout_rx_data[] = { 316*f540a430SEd Maste WIREDATA_CTAP_CBOR_INFO, 317*f540a430SEd Maste WIREDATA_CTAP_KEEPALIVE, 318*f540a430SEd Maste WIREDATA_CTAP_KEEPALIVE, 319*f540a430SEd Maste WIREDATA_CTAP_KEEPALIVE, 320*f540a430SEd Maste WIREDATA_CTAP_KEEPALIVE, 321*f540a430SEd Maste WIREDATA_CTAP_KEEPALIVE, 322*f540a430SEd Maste WIREDATA_CTAP_CBOR_STATUS 323*f540a430SEd Maste }; 324*f540a430SEd Maste uint8_t *wiredata; 325*f540a430SEd Maste fido_dev_t *dev = NULL; 326*f540a430SEd Maste fido_dev_io_t io; 327*f540a430SEd Maste 328*f540a430SEd Maste memset(&io, 0, sizeof(io)); 329*f540a430SEd Maste 330*f540a430SEd Maste io.open = dummy_open; 331*f540a430SEd Maste io.close = dummy_close; 332*f540a430SEd Maste io.read = dummy_read; 333*f540a430SEd Maste io.write = dummy_write; 334*f540a430SEd Maste 335*f540a430SEd Maste wiredata = wiredata_setup(timeout_rx_data, sizeof(timeout_rx_data)); 336*f540a430SEd Maste assert((dev = fido_dev_new()) != NULL); 337*f540a430SEd Maste assert(fido_dev_set_io_functions(dev, &io) == FIDO_OK); 338*f540a430SEd Maste assert(fido_dev_open(dev, "dummy") == FIDO_OK); 339*f540a430SEd Maste assert(fido_dev_set_timeout(dev, 3 * 1000) == FIDO_OK); 340*f540a430SEd Maste interval_ms = 1000; 341*f540a430SEd Maste assert(fido_dev_reset(dev) == FIDO_ERR_RX); 342*f540a430SEd Maste assert(fido_dev_close(dev) == FIDO_OK); 343*f540a430SEd Maste fido_dev_free(&dev); 344*f540a430SEd Maste wiredata_clear(&wiredata); 345*f540a430SEd Maste interval_ms = 0; 346*f540a430SEd Maste } 347*f540a430SEd Maste 348*f540a430SEd Maste static void 349*f540a430SEd Maste timeout_ok(void) 350*f540a430SEd Maste { 351*f540a430SEd Maste const uint8_t timeout_ok_data[] = { 352*f540a430SEd Maste WIREDATA_CTAP_CBOR_INFO, 353*f540a430SEd Maste WIREDATA_CTAP_KEEPALIVE, 354*f540a430SEd Maste WIREDATA_CTAP_KEEPALIVE, 355*f540a430SEd Maste WIREDATA_CTAP_KEEPALIVE, 356*f540a430SEd Maste WIREDATA_CTAP_KEEPALIVE, 357*f540a430SEd Maste WIREDATA_CTAP_KEEPALIVE, 358*f540a430SEd Maste WIREDATA_CTAP_CBOR_STATUS 359*f540a430SEd Maste }; 360*f540a430SEd Maste uint8_t *wiredata; 361*f540a430SEd Maste fido_dev_t *dev = NULL; 362*f540a430SEd Maste fido_dev_io_t io; 363*f540a430SEd Maste 364*f540a430SEd Maste memset(&io, 0, sizeof(io)); 365*f540a430SEd Maste 366*f540a430SEd Maste io.open = dummy_open; 367*f540a430SEd Maste io.close = dummy_close; 368*f540a430SEd Maste io.read = dummy_read; 369*f540a430SEd Maste io.write = dummy_write; 370*f540a430SEd Maste 371*f540a430SEd Maste wiredata = wiredata_setup(timeout_ok_data, sizeof(timeout_ok_data)); 372*f540a430SEd Maste assert((dev = fido_dev_new()) != NULL); 373*f540a430SEd Maste assert(fido_dev_set_io_functions(dev, &io) == FIDO_OK); 374*f540a430SEd Maste assert(fido_dev_open(dev, "dummy") == FIDO_OK); 375*f540a430SEd Maste assert(fido_dev_set_timeout(dev, 30 * 1000) == FIDO_OK); 376*f540a430SEd Maste interval_ms = 1000; 377*f540a430SEd Maste assert(fido_dev_reset(dev) == FIDO_OK); 378*f540a430SEd Maste assert(fido_dev_close(dev) == FIDO_OK); 379*f540a430SEd Maste fido_dev_free(&dev); 380*f540a430SEd Maste wiredata_clear(&wiredata); 381*f540a430SEd Maste interval_ms = 0; 382*f540a430SEd Maste } 383*f540a430SEd Maste 384*f540a430SEd Maste static void 385*f540a430SEd Maste timeout_misc(void) 386*f540a430SEd Maste { 387*f540a430SEd Maste fido_dev_t *dev; 388*f540a430SEd Maste 389*f540a430SEd Maste assert((dev = fido_dev_new()) != NULL); 390*f540a430SEd Maste assert(fido_dev_set_timeout(dev, -2) == FIDO_ERR_INVALID_ARGUMENT); 391*f540a430SEd Maste assert(fido_dev_set_timeout(dev, 3 * 1000) == FIDO_OK); 392*f540a430SEd Maste assert(fido_dev_set_timeout(dev, -1) == FIDO_OK); 393*f540a430SEd Maste fido_dev_free(&dev); 394*f540a430SEd Maste } 395*f540a430SEd Maste 3960afa8e06SEd Maste int 3970afa8e06SEd Maste main(void) 3980afa8e06SEd Maste { 3990afa8e06SEd Maste fido_init(0); 4000afa8e06SEd Maste 4010afa8e06SEd Maste open_iff_ok(); 4020afa8e06SEd Maste reopen(); 4030afa8e06SEd Maste double_open(); 404*f540a430SEd Maste double_close(); 4050afa8e06SEd Maste is_fido2(); 4060afa8e06SEd Maste has_pin(); 407*f540a430SEd Maste timeout_rx(); 408*f540a430SEd Maste timeout_ok(); 409*f540a430SEd Maste timeout_misc(); 4100afa8e06SEd Maste 4110afa8e06SEd Maste exit(0); 4120afa8e06SEd Maste } 413