xref: /freebsd/contrib/libfido2/regress/mock.c (revision febb0da5bf4bc99828ebede7abcb039514ac367a)
1*febb0da5SEd Maste /*
2*febb0da5SEd Maste  * Copyright (c) 2024 Yubico AB. All rights reserved.
3*febb0da5SEd Maste  * Use of this source code is governed by a BSD-style
4*febb0da5SEd Maste  * license that can be found in the LICENSE file.
5*febb0da5SEd Maste  * SPDX-License-Identifier: BSD-2-Clause
6*febb0da5SEd Maste  */
7*febb0da5SEd Maste 
8*febb0da5SEd Maste #undef NDEBUG
9*febb0da5SEd Maste 
10*febb0da5SEd Maste #include <assert.h>
11*febb0da5SEd Maste #include <string.h>
12*febb0da5SEd Maste #include <time.h>
13*febb0da5SEd Maste #include <stdint.h>
14*febb0da5SEd Maste 
15*febb0da5SEd Maste #define _FIDO_INTERNAL
16*febb0da5SEd Maste #include <fido.h>
17*febb0da5SEd Maste 
18*febb0da5SEd Maste #include "extern.h"
19*febb0da5SEd Maste #include "../fuzz/wiredata_fido2.h"
20*febb0da5SEd Maste 
21*febb0da5SEd Maste #define REPORT_LEN	(64 + 1)
22*febb0da5SEd Maste 
23*febb0da5SEd Maste static uint8_t	 ctap_nonce[8];
24*febb0da5SEd Maste static uint8_t	*wiredata_ptr;
25*febb0da5SEd Maste static size_t	 wiredata_len;
26*febb0da5SEd Maste static int	 fake_dev_handle;
27*febb0da5SEd Maste static int	 initialised;
28*febb0da5SEd Maste static long	 interval_ms;
29*febb0da5SEd Maste 
30*febb0da5SEd Maste #if defined(_MSC_VER)
31*febb0da5SEd Maste static int
nanosleep(const struct timespec * rqtp,struct timespec * rmtp)32*febb0da5SEd Maste nanosleep(const struct timespec *rqtp, struct timespec *rmtp)
33*febb0da5SEd Maste {
34*febb0da5SEd Maste 	if (rmtp != NULL) {
35*febb0da5SEd Maste 		errno = EINVAL;
36*febb0da5SEd Maste 		return (-1);
37*febb0da5SEd Maste 	}
38*febb0da5SEd Maste 
39*febb0da5SEd Maste 	Sleep((DWORD)(rqtp->tv_sec * 1000) + (DWORD)(rqtp->tv_nsec / 1000000));
40*febb0da5SEd Maste 
41*febb0da5SEd Maste 	return (0);
42*febb0da5SEd Maste }
43*febb0da5SEd Maste #endif
44*febb0da5SEd Maste 
45*febb0da5SEd Maste static void *
dummy_open(const char * path)46*febb0da5SEd Maste dummy_open(const char *path)
47*febb0da5SEd Maste {
48*febb0da5SEd Maste 	(void)path;
49*febb0da5SEd Maste 
50*febb0da5SEd Maste 	return (&fake_dev_handle);
51*febb0da5SEd Maste }
52*febb0da5SEd Maste 
53*febb0da5SEd Maste static void
dummy_close(void * handle)54*febb0da5SEd Maste dummy_close(void *handle)
55*febb0da5SEd Maste {
56*febb0da5SEd Maste 	assert(handle == &fake_dev_handle);
57*febb0da5SEd Maste }
58*febb0da5SEd Maste 
59*febb0da5SEd Maste static int
dummy_read(void * handle,unsigned char * ptr,size_t len,int ms)60*febb0da5SEd Maste dummy_read(void *handle, unsigned char *ptr, size_t len, int ms)
61*febb0da5SEd Maste {
62*febb0da5SEd Maste 	struct timespec tv;
63*febb0da5SEd Maste 	size_t		n;
64*febb0da5SEd Maste 	long		d;
65*febb0da5SEd Maste 
66*febb0da5SEd Maste 	assert(handle == &fake_dev_handle);
67*febb0da5SEd Maste 	assert(ptr != NULL);
68*febb0da5SEd Maste 	assert(len == REPORT_LEN - 1);
69*febb0da5SEd Maste 
70*febb0da5SEd Maste 	if (wiredata_ptr == NULL)
71*febb0da5SEd Maste 		return (-1);
72*febb0da5SEd Maste 
73*febb0da5SEd Maste 	if (!initialised) {
74*febb0da5SEd Maste 		assert(wiredata_len >= REPORT_LEN - 1);
75*febb0da5SEd Maste 		memcpy(&wiredata_ptr[7], &ctap_nonce, sizeof(ctap_nonce));
76*febb0da5SEd Maste 		initialised = 1;
77*febb0da5SEd Maste 	}
78*febb0da5SEd Maste 
79*febb0da5SEd Maste 	if (ms >= 0 && ms < interval_ms)
80*febb0da5SEd Maste 		d = ms;
81*febb0da5SEd Maste 	else
82*febb0da5SEd Maste 		d = interval_ms;
83*febb0da5SEd Maste 
84*febb0da5SEd Maste 	if (d) {
85*febb0da5SEd Maste 		tv.tv_sec = d / 1000;
86*febb0da5SEd Maste 		tv.tv_nsec = (d % 1000) * 1000000;
87*febb0da5SEd Maste 		if (nanosleep(&tv, NULL) == -1)
88*febb0da5SEd Maste 			err(1, "nanosleep");
89*febb0da5SEd Maste 	}
90*febb0da5SEd Maste 
91*febb0da5SEd Maste 	if (d != interval_ms)
92*febb0da5SEd Maste 		return (-1); /* timeout */
93*febb0da5SEd Maste 
94*febb0da5SEd Maste 	if (wiredata_len < len)
95*febb0da5SEd Maste 		n = wiredata_len;
96*febb0da5SEd Maste 	else
97*febb0da5SEd Maste 		n = len;
98*febb0da5SEd Maste 
99*febb0da5SEd Maste 	memcpy(ptr, wiredata_ptr, n);
100*febb0da5SEd Maste 	wiredata_ptr += n;
101*febb0da5SEd Maste 	wiredata_len -= n;
102*febb0da5SEd Maste 
103*febb0da5SEd Maste 	return ((int)n);
104*febb0da5SEd Maste }
105*febb0da5SEd Maste 
106*febb0da5SEd Maste static int
dummy_write(void * handle,const unsigned char * ptr,size_t len)107*febb0da5SEd Maste dummy_write(void *handle, const unsigned char *ptr, size_t len)
108*febb0da5SEd Maste {
109*febb0da5SEd Maste 	struct timespec tv;
110*febb0da5SEd Maste 
111*febb0da5SEd Maste 	assert(handle == &fake_dev_handle);
112*febb0da5SEd Maste 	assert(ptr != NULL);
113*febb0da5SEd Maste 	assert(len == REPORT_LEN);
114*febb0da5SEd Maste 
115*febb0da5SEd Maste 	if (!initialised)
116*febb0da5SEd Maste 		memcpy(&ctap_nonce, &ptr[8], sizeof(ctap_nonce));
117*febb0da5SEd Maste 
118*febb0da5SEd Maste 	if (interval_ms) {
119*febb0da5SEd Maste 		tv.tv_sec = interval_ms / 1000;
120*febb0da5SEd Maste 		tv.tv_nsec = (interval_ms % 1000) * 1000000;
121*febb0da5SEd Maste 		if (nanosleep(&tv, NULL) == -1)
122*febb0da5SEd Maste 			err(1, "nanosleep");
123*febb0da5SEd Maste 	}
124*febb0da5SEd Maste 
125*febb0da5SEd Maste 	return ((int)len);
126*febb0da5SEd Maste }
127*febb0da5SEd Maste 
128*febb0da5SEd Maste uint8_t *
wiredata_setup(const uint8_t * data,size_t len)129*febb0da5SEd Maste wiredata_setup(const uint8_t *data, size_t len)
130*febb0da5SEd Maste {
131*febb0da5SEd Maste 	const uint8_t ctap_init_data[] = { WIREDATA_CTAP_INIT };
132*febb0da5SEd Maste 
133*febb0da5SEd Maste 	assert(wiredata_ptr == NULL);
134*febb0da5SEd Maste 	assert(SIZE_MAX - len > sizeof(ctap_init_data));
135*febb0da5SEd Maste 	assert((wiredata_ptr = malloc(sizeof(ctap_init_data) + len)) != NULL);
136*febb0da5SEd Maste 
137*febb0da5SEd Maste #if defined(_MSC_VER)
138*febb0da5SEd Maste #pragma warning(push)
139*febb0da5SEd Maste #pragma warning(disable:6386)
140*febb0da5SEd Maste #endif
141*febb0da5SEd Maste 	memcpy(wiredata_ptr, ctap_init_data, sizeof(ctap_init_data));
142*febb0da5SEd Maste #if defined(_MSC_VER)
143*febb0da5SEd Maste #pragma warning(pop)
144*febb0da5SEd Maste #endif
145*febb0da5SEd Maste 
146*febb0da5SEd Maste 	if (len)
147*febb0da5SEd Maste 		memcpy(wiredata_ptr + sizeof(ctap_init_data), data, len);
148*febb0da5SEd Maste 
149*febb0da5SEd Maste 	wiredata_len = sizeof(ctap_init_data) + len;
150*febb0da5SEd Maste 
151*febb0da5SEd Maste 	return (wiredata_ptr);
152*febb0da5SEd Maste }
153*febb0da5SEd Maste 
154*febb0da5SEd Maste void
wiredata_clear(uint8_t ** wiredata)155*febb0da5SEd Maste wiredata_clear(uint8_t **wiredata)
156*febb0da5SEd Maste {
157*febb0da5SEd Maste 	free(*wiredata);
158*febb0da5SEd Maste 	*wiredata = NULL;
159*febb0da5SEd Maste 	wiredata_ptr = NULL;
160*febb0da5SEd Maste 	wiredata_len = 0;
161*febb0da5SEd Maste 	initialised = 0;
162*febb0da5SEd Maste }
163*febb0da5SEd Maste 
164*febb0da5SEd Maste void
setup_dummy_io(fido_dev_t * dev)165*febb0da5SEd Maste setup_dummy_io(fido_dev_t *dev)
166*febb0da5SEd Maste {
167*febb0da5SEd Maste 	fido_dev_io_t io;
168*febb0da5SEd Maste 
169*febb0da5SEd Maste 	memset(&io, 0, sizeof(io));
170*febb0da5SEd Maste 	io.open = dummy_open;
171*febb0da5SEd Maste 	io.close = dummy_close;
172*febb0da5SEd Maste 	io.read = dummy_read;
173*febb0da5SEd Maste 	io.write = dummy_write;
174*febb0da5SEd Maste 
175*febb0da5SEd Maste 	assert(fido_dev_set_io_functions(dev, &io) == FIDO_OK);
176*febb0da5SEd Maste }
177*febb0da5SEd Maste 
178*febb0da5SEd Maste void
set_read_interval(long ms)179*febb0da5SEd Maste set_read_interval(long ms)
180*febb0da5SEd Maste {
181*febb0da5SEd Maste 	interval_ms = ms;
182*febb0da5SEd Maste }
183