xref: /freebsd/contrib/libfido2/regress/dev.c (revision 2ccfa855b2fc331819953e3de1b1c15ce5b95a7e)
10afa8e06SEd Maste /*
2*2ccfa855SEd Maste  * Copyright (c) 2019-2022 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.
5*2ccfa855SEd Maste  * SPDX-License-Identifier: BSD-2-Clause
60afa8e06SEd Maste  */
70afa8e06SEd Maste 
8*2ccfa855SEd Maste #undef NDEBUG
9*2ccfa855SEd Maste 
100afa8e06SEd Maste #include <assert.h>
110afa8e06SEd Maste #include <string.h>
12f540a430SEd Maste #include <time.h>
130afa8e06SEd Maste 
14*2ccfa855SEd Maste #define _FIDO_INTERNAL
15*2ccfa855SEd Maste 
16*2ccfa855SEd Maste #include <fido.h>
17*2ccfa855SEd Maste 
180afa8e06SEd Maste #include "../fuzz/wiredata_fido2.h"
190afa8e06SEd Maste 
200afa8e06SEd Maste #define REPORT_LEN	(64 + 1)
210afa8e06SEd Maste 
220afa8e06SEd Maste static uint8_t	 ctap_nonce[8];
230afa8e06SEd Maste static uint8_t	*wiredata_ptr;
240afa8e06SEd Maste static size_t	 wiredata_len;
25*2ccfa855SEd Maste static int	 fake_dev_handle;
260afa8e06SEd Maste static int	 initialised;
27f540a430SEd Maste static long	 interval_ms;
280afa8e06SEd Maste 
29*2ccfa855SEd Maste #if defined(_MSC_VER)
30*2ccfa855SEd Maste static int
nanosleep(const struct timespec * rqtp,struct timespec * rmtp)31*2ccfa855SEd Maste nanosleep(const struct timespec *rqtp, struct timespec *rmtp)
32*2ccfa855SEd Maste {
33*2ccfa855SEd Maste 	if (rmtp != NULL) {
34*2ccfa855SEd Maste 		errno = EINVAL;
35*2ccfa855SEd Maste 		return (-1);
36*2ccfa855SEd Maste 	}
37*2ccfa855SEd Maste 
38*2ccfa855SEd Maste 	Sleep((DWORD)(rqtp->tv_sec * 1000) + (DWORD)(rqtp->tv_nsec / 1000000));
39*2ccfa855SEd Maste 
40*2ccfa855SEd Maste 	return (0);
41*2ccfa855SEd Maste }
42*2ccfa855SEd Maste #endif
43*2ccfa855SEd Maste 
440afa8e06SEd Maste static void *
dummy_open(const char * path)450afa8e06SEd Maste dummy_open(const char *path)
460afa8e06SEd Maste {
470afa8e06SEd Maste 	(void)path;
480afa8e06SEd Maste 
49*2ccfa855SEd Maste 	return (&fake_dev_handle);
500afa8e06SEd Maste }
510afa8e06SEd Maste 
520afa8e06SEd Maste static void
dummy_close(void * handle)530afa8e06SEd Maste dummy_close(void *handle)
540afa8e06SEd Maste {
55*2ccfa855SEd Maste 	assert(handle == &fake_dev_handle);
560afa8e06SEd Maste }
570afa8e06SEd Maste 
580afa8e06SEd Maste static int
dummy_read(void * handle,unsigned char * ptr,size_t len,int ms)590afa8e06SEd Maste dummy_read(void *handle, unsigned char *ptr, size_t len, int ms)
600afa8e06SEd Maste {
61f540a430SEd Maste 	struct timespec tv;
620afa8e06SEd Maste 	size_t		n;
63f540a430SEd Maste 	long		d;
640afa8e06SEd Maste 
65*2ccfa855SEd Maste 	assert(handle == &fake_dev_handle);
660afa8e06SEd Maste 	assert(ptr != NULL);
670afa8e06SEd Maste 	assert(len == REPORT_LEN - 1);
680afa8e06SEd Maste 
690afa8e06SEd Maste 	if (wiredata_ptr == NULL)
700afa8e06SEd Maste 		return (-1);
710afa8e06SEd Maste 
720afa8e06SEd Maste 	if (!initialised) {
730afa8e06SEd Maste 		assert(wiredata_len >= REPORT_LEN - 1);
740afa8e06SEd Maste 		memcpy(&wiredata_ptr[7], &ctap_nonce, sizeof(ctap_nonce));
750afa8e06SEd Maste 		initialised = 1;
760afa8e06SEd Maste 	}
770afa8e06SEd Maste 
78f540a430SEd Maste 	if (ms >= 0 && ms < interval_ms)
79f540a430SEd Maste 		d = ms;
80f540a430SEd Maste 	else
81f540a430SEd Maste 		d = interval_ms;
82f540a430SEd Maste 
83f540a430SEd Maste 	if (d) {
84f540a430SEd Maste 		tv.tv_sec = d / 1000;
85f540a430SEd Maste 		tv.tv_nsec = (d % 1000) * 1000000;
86f540a430SEd Maste 		if (nanosleep(&tv, NULL) == -1)
87f540a430SEd Maste 			err(1, "nanosleep");
88f540a430SEd Maste 	}
89f540a430SEd Maste 
90f540a430SEd Maste 	if (d != interval_ms)
91f540a430SEd Maste 		return (-1); /* timeout */
92f540a430SEd Maste 
930afa8e06SEd Maste 	if (wiredata_len < len)
940afa8e06SEd Maste 		n = wiredata_len;
950afa8e06SEd Maste 	else
960afa8e06SEd Maste 		n = len;
970afa8e06SEd Maste 
980afa8e06SEd Maste 	memcpy(ptr, wiredata_ptr, n);
990afa8e06SEd Maste 	wiredata_ptr += n;
1000afa8e06SEd Maste 	wiredata_len -= n;
1010afa8e06SEd Maste 
1020afa8e06SEd Maste 	return ((int)n);
1030afa8e06SEd Maste }
1040afa8e06SEd Maste 
1050afa8e06SEd Maste static int
dummy_write(void * handle,const unsigned char * ptr,size_t len)1060afa8e06SEd Maste dummy_write(void *handle, const unsigned char *ptr, size_t len)
1070afa8e06SEd Maste {
108f540a430SEd Maste 	struct timespec tv;
109f540a430SEd Maste 
110*2ccfa855SEd Maste 	assert(handle == &fake_dev_handle);
1110afa8e06SEd Maste 	assert(ptr != NULL);
1120afa8e06SEd Maste 	assert(len == REPORT_LEN);
1130afa8e06SEd Maste 
1140afa8e06SEd Maste 	if (!initialised)
1150afa8e06SEd Maste 		memcpy(&ctap_nonce, &ptr[8], sizeof(ctap_nonce));
1160afa8e06SEd Maste 
117f540a430SEd Maste 	if (interval_ms) {
118f540a430SEd Maste 		tv.tv_sec = interval_ms / 1000;
119f540a430SEd Maste 		tv.tv_nsec = (interval_ms % 1000) * 1000000;
120f540a430SEd Maste 		if (nanosleep(&tv, NULL) == -1)
121f540a430SEd Maste 			err(1, "nanosleep");
122f540a430SEd Maste 	}
123f540a430SEd Maste 
1240afa8e06SEd Maste 	return ((int)len);
1250afa8e06SEd Maste }
1260afa8e06SEd Maste 
1270afa8e06SEd Maste static uint8_t *
wiredata_setup(const uint8_t * data,size_t len)1280afa8e06SEd Maste wiredata_setup(const uint8_t *data, size_t len)
1290afa8e06SEd Maste {
1300afa8e06SEd Maste 	const uint8_t ctap_init_data[] = { WIREDATA_CTAP_INIT };
1310afa8e06SEd Maste 
1320afa8e06SEd Maste 	assert(wiredata_ptr == NULL);
1330afa8e06SEd Maste 	assert(SIZE_MAX - len > sizeof(ctap_init_data));
1340afa8e06SEd Maste 	assert((wiredata_ptr = malloc(sizeof(ctap_init_data) + len)) != NULL);
1350afa8e06SEd Maste 
136*2ccfa855SEd Maste #if defined(_MSC_VER)
137*2ccfa855SEd Maste #pragma warning(push)
138*2ccfa855SEd Maste #pragma warning(disable:6386)
139*2ccfa855SEd Maste #endif
1400afa8e06SEd Maste 	memcpy(wiredata_ptr, ctap_init_data, sizeof(ctap_init_data));
141*2ccfa855SEd Maste #if defined(_MSC_VER)
142*2ccfa855SEd Maste #pragma warning(pop)
143*2ccfa855SEd Maste #endif
1440afa8e06SEd Maste 
1450afa8e06SEd Maste 	if (len)
1460afa8e06SEd Maste 		memcpy(wiredata_ptr + sizeof(ctap_init_data), data, len);
1470afa8e06SEd Maste 
1480afa8e06SEd Maste 	wiredata_len = sizeof(ctap_init_data) + len;
1490afa8e06SEd Maste 
1500afa8e06SEd Maste 	return (wiredata_ptr);
1510afa8e06SEd Maste }
1520afa8e06SEd Maste 
1530afa8e06SEd Maste static void
wiredata_clear(uint8_t ** wiredata)1540afa8e06SEd Maste wiredata_clear(uint8_t **wiredata)
1550afa8e06SEd Maste {
1560afa8e06SEd Maste 	free(*wiredata);
1570afa8e06SEd Maste 	*wiredata = NULL;
1580afa8e06SEd Maste 	wiredata_ptr = NULL;
1590afa8e06SEd Maste 	wiredata_len = 0;
1600afa8e06SEd Maste 	initialised = 0;
1610afa8e06SEd Maste }
1620afa8e06SEd Maste 
1630afa8e06SEd Maste /* gh#56 */
1640afa8e06SEd Maste static void
open_iff_ok(void)1650afa8e06SEd Maste open_iff_ok(void)
1660afa8e06SEd Maste {
1670afa8e06SEd Maste 	fido_dev_t	*dev = NULL;
1680afa8e06SEd Maste 	fido_dev_io_t	 io;
1690afa8e06SEd Maste 
1700afa8e06SEd Maste 	memset(&io, 0, sizeof(io));
1710afa8e06SEd Maste 
1720afa8e06SEd Maste 	io.open = dummy_open;
1730afa8e06SEd Maste 	io.close = dummy_close;
1740afa8e06SEd Maste 	io.read = dummy_read;
1750afa8e06SEd Maste 	io.write = dummy_write;
1760afa8e06SEd Maste 
1770afa8e06SEd Maste 	assert((dev = fido_dev_new()) != NULL);
1780afa8e06SEd Maste 	assert(fido_dev_set_io_functions(dev, &io) == FIDO_OK);
1790afa8e06SEd Maste 	assert(fido_dev_open(dev, "dummy") == FIDO_ERR_RX);
1800afa8e06SEd Maste 	assert(fido_dev_close(dev) == FIDO_ERR_INVALID_ARGUMENT);
1810afa8e06SEd Maste 
1820afa8e06SEd Maste 	fido_dev_free(&dev);
1830afa8e06SEd Maste }
1840afa8e06SEd Maste 
1850afa8e06SEd Maste static void
reopen(void)1860afa8e06SEd Maste reopen(void)
1870afa8e06SEd Maste {
1880afa8e06SEd Maste 	const uint8_t	 cbor_info_data[] = { WIREDATA_CTAP_CBOR_INFO };
1890afa8e06SEd Maste 	uint8_t		*wiredata;
1900afa8e06SEd Maste 	fido_dev_t	*dev = NULL;
1910afa8e06SEd Maste 	fido_dev_io_t	 io;
1920afa8e06SEd Maste 
1930afa8e06SEd Maste 	memset(&io, 0, sizeof(io));
1940afa8e06SEd Maste 
1950afa8e06SEd Maste 	io.open = dummy_open;
1960afa8e06SEd Maste 	io.close = dummy_close;
1970afa8e06SEd Maste 	io.read = dummy_read;
1980afa8e06SEd Maste 	io.write = dummy_write;
1990afa8e06SEd Maste 
2000afa8e06SEd Maste 	wiredata = wiredata_setup(cbor_info_data, sizeof(cbor_info_data));
2010afa8e06SEd Maste 	assert((dev = fido_dev_new()) != NULL);
2020afa8e06SEd Maste 	assert(fido_dev_set_io_functions(dev, &io) == FIDO_OK);
2030afa8e06SEd Maste 	assert(fido_dev_open(dev, "dummy") == FIDO_OK);
2040afa8e06SEd Maste 	assert(fido_dev_close(dev) == FIDO_OK);
2050afa8e06SEd Maste 	wiredata_clear(&wiredata);
2060afa8e06SEd Maste 
2070afa8e06SEd Maste 	wiredata = wiredata_setup(cbor_info_data, sizeof(cbor_info_data));
2080afa8e06SEd Maste 	assert(fido_dev_open(dev, "dummy") == FIDO_OK);
2090afa8e06SEd Maste 	assert(fido_dev_close(dev) == FIDO_OK);
210f540a430SEd Maste 	fido_dev_free(&dev);
2110afa8e06SEd Maste 	wiredata_clear(&wiredata);
2120afa8e06SEd Maste }
2130afa8e06SEd Maste 
2140afa8e06SEd Maste static void
double_open(void)2150afa8e06SEd Maste double_open(void)
2160afa8e06SEd Maste {
2170afa8e06SEd Maste 	const uint8_t	 cbor_info_data[] = { WIREDATA_CTAP_CBOR_INFO };
2180afa8e06SEd Maste 	uint8_t		*wiredata;
2190afa8e06SEd Maste 	fido_dev_t	*dev = NULL;
2200afa8e06SEd Maste 	fido_dev_io_t	 io;
2210afa8e06SEd Maste 
2220afa8e06SEd Maste 	memset(&io, 0, sizeof(io));
2230afa8e06SEd Maste 
2240afa8e06SEd Maste 	io.open = dummy_open;
2250afa8e06SEd Maste 	io.close = dummy_close;
2260afa8e06SEd Maste 	io.read = dummy_read;
2270afa8e06SEd Maste 	io.write = dummy_write;
2280afa8e06SEd Maste 
2290afa8e06SEd Maste 	wiredata = wiredata_setup(cbor_info_data, sizeof(cbor_info_data));
2300afa8e06SEd Maste 	assert((dev = fido_dev_new()) != NULL);
2310afa8e06SEd Maste 	assert(fido_dev_set_io_functions(dev, &io) == FIDO_OK);
2320afa8e06SEd Maste 	assert(fido_dev_open(dev, "dummy") == FIDO_OK);
2330afa8e06SEd Maste 	assert(fido_dev_open(dev, "dummy") == FIDO_ERR_INVALID_ARGUMENT);
2340afa8e06SEd Maste 	assert(fido_dev_close(dev) == FIDO_OK);
235f540a430SEd Maste 	fido_dev_free(&dev);
236f540a430SEd Maste 	wiredata_clear(&wiredata);
237f540a430SEd Maste }
238f540a430SEd Maste 
239f540a430SEd Maste static void
double_close(void)240f540a430SEd Maste double_close(void)
241f540a430SEd Maste {
242f540a430SEd Maste 	const uint8_t	 cbor_info_data[] = { WIREDATA_CTAP_CBOR_INFO };
243f540a430SEd Maste 	uint8_t		*wiredata;
244f540a430SEd Maste 	fido_dev_t	*dev = NULL;
245f540a430SEd Maste 	fido_dev_io_t	 io;
246f540a430SEd Maste 
247f540a430SEd Maste 	memset(&io, 0, sizeof(io));
248f540a430SEd Maste 
249f540a430SEd Maste 	io.open = dummy_open;
250f540a430SEd Maste 	io.close = dummy_close;
251f540a430SEd Maste 	io.read = dummy_read;
252f540a430SEd Maste 	io.write = dummy_write;
253f540a430SEd Maste 
254f540a430SEd Maste 	wiredata = wiredata_setup(cbor_info_data, sizeof(cbor_info_data));
255f540a430SEd Maste 	assert((dev = fido_dev_new()) != NULL);
256f540a430SEd Maste 	assert(fido_dev_close(dev) == FIDO_ERR_INVALID_ARGUMENT);
257f540a430SEd Maste 	assert(fido_dev_set_io_functions(dev, &io) == FIDO_OK);
258f540a430SEd Maste 	assert(fido_dev_close(dev) == FIDO_ERR_INVALID_ARGUMENT);
259f540a430SEd Maste 	assert(fido_dev_open(dev, "dummy") == FIDO_OK);
260f540a430SEd Maste 	assert(fido_dev_close(dev) == FIDO_OK);
261f540a430SEd Maste 	assert(fido_dev_close(dev) == FIDO_ERR_INVALID_ARGUMENT);
262f540a430SEd Maste 	fido_dev_free(&dev);
2630afa8e06SEd Maste 	wiredata_clear(&wiredata);
2640afa8e06SEd Maste }
2650afa8e06SEd Maste 
2660afa8e06SEd Maste static void
is_fido2(void)2670afa8e06SEd Maste is_fido2(void)
2680afa8e06SEd Maste {
2690afa8e06SEd Maste 	const uint8_t	 cbor_info_data[] = { WIREDATA_CTAP_CBOR_INFO };
2700afa8e06SEd Maste 	uint8_t		*wiredata;
2710afa8e06SEd Maste 	fido_dev_t	*dev = NULL;
2720afa8e06SEd Maste 	fido_dev_io_t	 io;
2730afa8e06SEd Maste 
2740afa8e06SEd Maste 	memset(&io, 0, sizeof(io));
2750afa8e06SEd Maste 
2760afa8e06SEd Maste 	io.open = dummy_open;
2770afa8e06SEd Maste 	io.close = dummy_close;
2780afa8e06SEd Maste 	io.read = dummy_read;
2790afa8e06SEd Maste 	io.write = dummy_write;
2800afa8e06SEd Maste 
2810afa8e06SEd Maste 	wiredata = wiredata_setup(cbor_info_data, sizeof(cbor_info_data));
2820afa8e06SEd Maste 	assert((dev = fido_dev_new()) != NULL);
2830afa8e06SEd Maste 	assert(fido_dev_set_io_functions(dev, &io) == FIDO_OK);
2840afa8e06SEd Maste 	assert(fido_dev_open(dev, "dummy") == FIDO_OK);
2850afa8e06SEd Maste 	assert(fido_dev_is_fido2(dev) == true);
2860afa8e06SEd Maste 	assert(fido_dev_supports_pin(dev) == true);
2870afa8e06SEd Maste 	fido_dev_force_u2f(dev);
2880afa8e06SEd Maste 	assert(fido_dev_is_fido2(dev) == false);
2890afa8e06SEd Maste 	assert(fido_dev_supports_pin(dev) == false);
2900afa8e06SEd Maste 	assert(fido_dev_close(dev) == FIDO_OK);
2910afa8e06SEd Maste 	wiredata_clear(&wiredata);
2920afa8e06SEd Maste 
2930afa8e06SEd Maste 	wiredata = wiredata_setup(NULL, 0);
2940afa8e06SEd Maste 	assert(fido_dev_open(dev, "dummy") == FIDO_OK);
2950afa8e06SEd Maste 	assert(fido_dev_is_fido2(dev) == false);
2960afa8e06SEd Maste 	assert(fido_dev_supports_pin(dev) == false);
2970afa8e06SEd Maste 	fido_dev_force_fido2(dev);
2980afa8e06SEd Maste 	assert(fido_dev_is_fido2(dev) == true);
2990afa8e06SEd Maste 	assert(fido_dev_supports_pin(dev) == false);
3000afa8e06SEd Maste 	assert(fido_dev_close(dev) == FIDO_OK);
301f540a430SEd Maste 	fido_dev_free(&dev);
3020afa8e06SEd Maste 	wiredata_clear(&wiredata);
3030afa8e06SEd Maste }
3040afa8e06SEd Maste 
3050afa8e06SEd Maste static void
has_pin(void)3060afa8e06SEd Maste has_pin(void)
3070afa8e06SEd Maste {
3080afa8e06SEd Maste 	const uint8_t	 set_pin_data[] = {
3090afa8e06SEd Maste 			    WIREDATA_CTAP_CBOR_INFO,
3100afa8e06SEd Maste 			    WIREDATA_CTAP_CBOR_AUTHKEY,
3110afa8e06SEd Maste 			    WIREDATA_CTAP_CBOR_STATUS,
3120afa8e06SEd Maste 			    WIREDATA_CTAP_CBOR_STATUS
3130afa8e06SEd Maste 			 };
3140afa8e06SEd Maste 	uint8_t		*wiredata;
3150afa8e06SEd Maste 	fido_dev_t	*dev = NULL;
3160afa8e06SEd Maste 	fido_dev_io_t	 io;
3170afa8e06SEd Maste 
3180afa8e06SEd Maste 	memset(&io, 0, sizeof(io));
3190afa8e06SEd Maste 
3200afa8e06SEd Maste 	io.open = dummy_open;
3210afa8e06SEd Maste 	io.close = dummy_close;
3220afa8e06SEd Maste 	io.read = dummy_read;
3230afa8e06SEd Maste 	io.write = dummy_write;
3240afa8e06SEd Maste 
3250afa8e06SEd Maste 	wiredata = wiredata_setup(set_pin_data, sizeof(set_pin_data));
3260afa8e06SEd Maste 	assert((dev = fido_dev_new()) != NULL);
3270afa8e06SEd Maste 	assert(fido_dev_set_io_functions(dev, &io) == FIDO_OK);
3280afa8e06SEd Maste 	assert(fido_dev_open(dev, "dummy") == FIDO_OK);
3290afa8e06SEd Maste 	assert(fido_dev_has_pin(dev) == false);
3300afa8e06SEd Maste 	assert(fido_dev_set_pin(dev, "top secret", NULL) == FIDO_OK);
3310afa8e06SEd Maste 	assert(fido_dev_has_pin(dev) == true);
3320afa8e06SEd Maste 	assert(fido_dev_reset(dev) == FIDO_OK);
3330afa8e06SEd Maste 	assert(fido_dev_has_pin(dev) == false);
3340afa8e06SEd Maste 	assert(fido_dev_close(dev) == FIDO_OK);
335f540a430SEd Maste 	fido_dev_free(&dev);
3360afa8e06SEd Maste 	wiredata_clear(&wiredata);
3370afa8e06SEd Maste }
3380afa8e06SEd Maste 
339f540a430SEd Maste static void
timeout_rx(void)340f540a430SEd Maste timeout_rx(void)
341f540a430SEd Maste {
342f540a430SEd Maste 	const uint8_t	 timeout_rx_data[] = {
343f540a430SEd Maste 			    WIREDATA_CTAP_CBOR_INFO,
344f540a430SEd Maste 			    WIREDATA_CTAP_KEEPALIVE,
345f540a430SEd Maste 			    WIREDATA_CTAP_KEEPALIVE,
346f540a430SEd Maste 			    WIREDATA_CTAP_KEEPALIVE,
347f540a430SEd Maste 			    WIREDATA_CTAP_KEEPALIVE,
348f540a430SEd Maste 			    WIREDATA_CTAP_KEEPALIVE,
349f540a430SEd Maste 			    WIREDATA_CTAP_CBOR_STATUS
350f540a430SEd Maste 			 };
351f540a430SEd Maste 	uint8_t		*wiredata;
352f540a430SEd Maste 	fido_dev_t	*dev = NULL;
353f540a430SEd Maste 	fido_dev_io_t	 io;
354f540a430SEd Maste 
355f540a430SEd Maste 	memset(&io, 0, sizeof(io));
356f540a430SEd Maste 
357f540a430SEd Maste 	io.open = dummy_open;
358f540a430SEd Maste 	io.close = dummy_close;
359f540a430SEd Maste 	io.read = dummy_read;
360f540a430SEd Maste 	io.write = dummy_write;
361f540a430SEd Maste 
362f540a430SEd Maste 	wiredata = wiredata_setup(timeout_rx_data, sizeof(timeout_rx_data));
363f540a430SEd Maste 	assert((dev = fido_dev_new()) != NULL);
364f540a430SEd Maste 	assert(fido_dev_set_io_functions(dev, &io) == FIDO_OK);
365f540a430SEd Maste 	assert(fido_dev_open(dev, "dummy") == FIDO_OK);
366f540a430SEd Maste 	assert(fido_dev_set_timeout(dev, 3 * 1000) == FIDO_OK);
367f540a430SEd Maste 	interval_ms = 1000;
368f540a430SEd Maste 	assert(fido_dev_reset(dev) == FIDO_ERR_RX);
369f540a430SEd Maste 	assert(fido_dev_close(dev) == FIDO_OK);
370f540a430SEd Maste 	fido_dev_free(&dev);
371f540a430SEd Maste 	wiredata_clear(&wiredata);
372f540a430SEd Maste 	interval_ms = 0;
373f540a430SEd Maste }
374f540a430SEd Maste 
375f540a430SEd Maste static void
timeout_ok(void)376f540a430SEd Maste timeout_ok(void)
377f540a430SEd Maste {
378f540a430SEd Maste 	const uint8_t	 timeout_ok_data[] = {
379f540a430SEd Maste 			    WIREDATA_CTAP_CBOR_INFO,
380f540a430SEd Maste 			    WIREDATA_CTAP_KEEPALIVE,
381f540a430SEd Maste 			    WIREDATA_CTAP_KEEPALIVE,
382f540a430SEd Maste 			    WIREDATA_CTAP_KEEPALIVE,
383f540a430SEd Maste 			    WIREDATA_CTAP_KEEPALIVE,
384f540a430SEd Maste 			    WIREDATA_CTAP_KEEPALIVE,
385f540a430SEd Maste 			    WIREDATA_CTAP_CBOR_STATUS
386f540a430SEd Maste 			 };
387f540a430SEd Maste 	uint8_t		*wiredata;
388f540a430SEd Maste 	fido_dev_t	*dev = NULL;
389f540a430SEd Maste 	fido_dev_io_t	 io;
390f540a430SEd Maste 
391f540a430SEd Maste 	memset(&io, 0, sizeof(io));
392f540a430SEd Maste 
393f540a430SEd Maste 	io.open = dummy_open;
394f540a430SEd Maste 	io.close = dummy_close;
395f540a430SEd Maste 	io.read = dummy_read;
396f540a430SEd Maste 	io.write = dummy_write;
397f540a430SEd Maste 
398f540a430SEd Maste 	wiredata = wiredata_setup(timeout_ok_data, sizeof(timeout_ok_data));
399f540a430SEd Maste 	assert((dev = fido_dev_new()) != NULL);
400f540a430SEd Maste 	assert(fido_dev_set_io_functions(dev, &io) == FIDO_OK);
401f540a430SEd Maste 	assert(fido_dev_open(dev, "dummy") == FIDO_OK);
402f540a430SEd Maste 	assert(fido_dev_set_timeout(dev, 30 * 1000) == FIDO_OK);
403f540a430SEd Maste 	interval_ms = 1000;
404f540a430SEd Maste 	assert(fido_dev_reset(dev) == FIDO_OK);
405f540a430SEd Maste 	assert(fido_dev_close(dev) == FIDO_OK);
406f540a430SEd Maste 	fido_dev_free(&dev);
407f540a430SEd Maste 	wiredata_clear(&wiredata);
408f540a430SEd Maste 	interval_ms = 0;
409f540a430SEd Maste }
410f540a430SEd Maste 
411f540a430SEd Maste static void
timeout_misc(void)412f540a430SEd Maste timeout_misc(void)
413f540a430SEd Maste {
414f540a430SEd Maste 	fido_dev_t *dev;
415f540a430SEd Maste 
416f540a430SEd Maste 	assert((dev = fido_dev_new()) != NULL);
417f540a430SEd Maste 	assert(fido_dev_set_timeout(dev, -2) == FIDO_ERR_INVALID_ARGUMENT);
418f540a430SEd Maste 	assert(fido_dev_set_timeout(dev, 3 * 1000) == FIDO_OK);
419f540a430SEd Maste 	assert(fido_dev_set_timeout(dev, -1) == FIDO_OK);
420f540a430SEd Maste 	fido_dev_free(&dev);
421f540a430SEd Maste }
422f540a430SEd Maste 
4230afa8e06SEd Maste int
main(void)4240afa8e06SEd Maste main(void)
4250afa8e06SEd Maste {
4260afa8e06SEd Maste 	fido_init(0);
4270afa8e06SEd Maste 
4280afa8e06SEd Maste 	open_iff_ok();
4290afa8e06SEd Maste 	reopen();
4300afa8e06SEd Maste 	double_open();
431f540a430SEd Maste 	double_close();
4320afa8e06SEd Maste 	is_fido2();
4330afa8e06SEd Maste 	has_pin();
434f540a430SEd Maste 	timeout_rx();
435f540a430SEd Maste 	timeout_ok();
436f540a430SEd Maste 	timeout_misc();
4370afa8e06SEd Maste 
4380afa8e06SEd Maste 	exit(0);
4390afa8e06SEd Maste }
440