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