Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/libfido2/regress/dev.c
39483 views
1
/*
2
* Copyright (c) 2019-2022 Yubico AB. All rights reserved.
3
* Use of this source code is governed by a BSD-style
4
* license that can be found in the LICENSE file.
5
* SPDX-License-Identifier: BSD-2-Clause
6
*/
7
8
#undef NDEBUG
9
10
#include <assert.h>
11
#include <string.h>
12
#include <time.h>
13
14
#define _FIDO_INTERNAL
15
16
#include <fido.h>
17
18
#include "../fuzz/wiredata_fido2.h"
19
20
#define REPORT_LEN (64 + 1)
21
22
static uint8_t ctap_nonce[8];
23
static uint8_t *wiredata_ptr;
24
static size_t wiredata_len;
25
static int fake_dev_handle;
26
static int initialised;
27
static long interval_ms;
28
29
#if defined(_MSC_VER)
30
static int
31
nanosleep(const struct timespec *rqtp, struct timespec *rmtp)
32
{
33
if (rmtp != NULL) {
34
errno = EINVAL;
35
return (-1);
36
}
37
38
Sleep((DWORD)(rqtp->tv_sec * 1000) + (DWORD)(rqtp->tv_nsec / 1000000));
39
40
return (0);
41
}
42
#endif
43
44
static void *
45
dummy_open(const char *path)
46
{
47
(void)path;
48
49
return (&fake_dev_handle);
50
}
51
52
static void
53
dummy_close(void *handle)
54
{
55
assert(handle == &fake_dev_handle);
56
}
57
58
static int
59
dummy_read(void *handle, unsigned char *ptr, size_t len, int ms)
60
{
61
struct timespec tv;
62
size_t n;
63
long d;
64
65
assert(handle == &fake_dev_handle);
66
assert(ptr != NULL);
67
assert(len == REPORT_LEN - 1);
68
69
if (wiredata_ptr == NULL)
70
return (-1);
71
72
if (!initialised) {
73
assert(wiredata_len >= REPORT_LEN - 1);
74
memcpy(&wiredata_ptr[7], &ctap_nonce, sizeof(ctap_nonce));
75
initialised = 1;
76
}
77
78
if (ms >= 0 && ms < interval_ms)
79
d = ms;
80
else
81
d = interval_ms;
82
83
if (d) {
84
tv.tv_sec = d / 1000;
85
tv.tv_nsec = (d % 1000) * 1000000;
86
if (nanosleep(&tv, NULL) == -1)
87
err(1, "nanosleep");
88
}
89
90
if (d != interval_ms)
91
return (-1); /* timeout */
92
93
if (wiredata_len < len)
94
n = wiredata_len;
95
else
96
n = len;
97
98
memcpy(ptr, wiredata_ptr, n);
99
wiredata_ptr += n;
100
wiredata_len -= n;
101
102
return ((int)n);
103
}
104
105
static int
106
dummy_write(void *handle, const unsigned char *ptr, size_t len)
107
{
108
struct timespec tv;
109
110
assert(handle == &fake_dev_handle);
111
assert(ptr != NULL);
112
assert(len == REPORT_LEN);
113
114
if (!initialised)
115
memcpy(&ctap_nonce, &ptr[8], sizeof(ctap_nonce));
116
117
if (interval_ms) {
118
tv.tv_sec = interval_ms / 1000;
119
tv.tv_nsec = (interval_ms % 1000) * 1000000;
120
if (nanosleep(&tv, NULL) == -1)
121
err(1, "nanosleep");
122
}
123
124
return ((int)len);
125
}
126
127
static uint8_t *
128
wiredata_setup(const uint8_t *data, size_t len)
129
{
130
const uint8_t ctap_init_data[] = { WIREDATA_CTAP_INIT };
131
132
assert(wiredata_ptr == NULL);
133
assert(SIZE_MAX - len > sizeof(ctap_init_data));
134
assert((wiredata_ptr = malloc(sizeof(ctap_init_data) + len)) != NULL);
135
136
#if defined(_MSC_VER)
137
#pragma warning(push)
138
#pragma warning(disable:6386)
139
#endif
140
memcpy(wiredata_ptr, ctap_init_data, sizeof(ctap_init_data));
141
#if defined(_MSC_VER)
142
#pragma warning(pop)
143
#endif
144
145
if (len)
146
memcpy(wiredata_ptr + sizeof(ctap_init_data), data, len);
147
148
wiredata_len = sizeof(ctap_init_data) + len;
149
150
return (wiredata_ptr);
151
}
152
153
static void
154
wiredata_clear(uint8_t **wiredata)
155
{
156
free(*wiredata);
157
*wiredata = NULL;
158
wiredata_ptr = NULL;
159
wiredata_len = 0;
160
initialised = 0;
161
}
162
163
/* gh#56 */
164
static void
165
open_iff_ok(void)
166
{
167
fido_dev_t *dev = NULL;
168
fido_dev_io_t io;
169
170
memset(&io, 0, sizeof(io));
171
172
io.open = dummy_open;
173
io.close = dummy_close;
174
io.read = dummy_read;
175
io.write = dummy_write;
176
177
assert((dev = fido_dev_new()) != NULL);
178
assert(fido_dev_set_io_functions(dev, &io) == FIDO_OK);
179
assert(fido_dev_open(dev, "dummy") == FIDO_ERR_RX);
180
assert(fido_dev_close(dev) == FIDO_ERR_INVALID_ARGUMENT);
181
182
fido_dev_free(&dev);
183
}
184
185
static void
186
reopen(void)
187
{
188
const uint8_t cbor_info_data[] = { WIREDATA_CTAP_CBOR_INFO };
189
uint8_t *wiredata;
190
fido_dev_t *dev = NULL;
191
fido_dev_io_t io;
192
193
memset(&io, 0, sizeof(io));
194
195
io.open = dummy_open;
196
io.close = dummy_close;
197
io.read = dummy_read;
198
io.write = dummy_write;
199
200
wiredata = wiredata_setup(cbor_info_data, sizeof(cbor_info_data));
201
assert((dev = fido_dev_new()) != NULL);
202
assert(fido_dev_set_io_functions(dev, &io) == FIDO_OK);
203
assert(fido_dev_open(dev, "dummy") == FIDO_OK);
204
assert(fido_dev_close(dev) == FIDO_OK);
205
wiredata_clear(&wiredata);
206
207
wiredata = wiredata_setup(cbor_info_data, sizeof(cbor_info_data));
208
assert(fido_dev_open(dev, "dummy") == FIDO_OK);
209
assert(fido_dev_close(dev) == FIDO_OK);
210
fido_dev_free(&dev);
211
wiredata_clear(&wiredata);
212
}
213
214
static void
215
double_open(void)
216
{
217
const uint8_t cbor_info_data[] = { WIREDATA_CTAP_CBOR_INFO };
218
uint8_t *wiredata;
219
fido_dev_t *dev = NULL;
220
fido_dev_io_t io;
221
222
memset(&io, 0, sizeof(io));
223
224
io.open = dummy_open;
225
io.close = dummy_close;
226
io.read = dummy_read;
227
io.write = dummy_write;
228
229
wiredata = wiredata_setup(cbor_info_data, sizeof(cbor_info_data));
230
assert((dev = fido_dev_new()) != NULL);
231
assert(fido_dev_set_io_functions(dev, &io) == FIDO_OK);
232
assert(fido_dev_open(dev, "dummy") == FIDO_OK);
233
assert(fido_dev_open(dev, "dummy") == FIDO_ERR_INVALID_ARGUMENT);
234
assert(fido_dev_close(dev) == FIDO_OK);
235
fido_dev_free(&dev);
236
wiredata_clear(&wiredata);
237
}
238
239
static void
240
double_close(void)
241
{
242
const uint8_t cbor_info_data[] = { WIREDATA_CTAP_CBOR_INFO };
243
uint8_t *wiredata;
244
fido_dev_t *dev = NULL;
245
fido_dev_io_t io;
246
247
memset(&io, 0, sizeof(io));
248
249
io.open = dummy_open;
250
io.close = dummy_close;
251
io.read = dummy_read;
252
io.write = dummy_write;
253
254
wiredata = wiredata_setup(cbor_info_data, sizeof(cbor_info_data));
255
assert((dev = fido_dev_new()) != NULL);
256
assert(fido_dev_close(dev) == FIDO_ERR_INVALID_ARGUMENT);
257
assert(fido_dev_set_io_functions(dev, &io) == FIDO_OK);
258
assert(fido_dev_close(dev) == FIDO_ERR_INVALID_ARGUMENT);
259
assert(fido_dev_open(dev, "dummy") == FIDO_OK);
260
assert(fido_dev_close(dev) == FIDO_OK);
261
assert(fido_dev_close(dev) == FIDO_ERR_INVALID_ARGUMENT);
262
fido_dev_free(&dev);
263
wiredata_clear(&wiredata);
264
}
265
266
static void
267
is_fido2(void)
268
{
269
const uint8_t cbor_info_data[] = { WIREDATA_CTAP_CBOR_INFO };
270
uint8_t *wiredata;
271
fido_dev_t *dev = NULL;
272
fido_dev_io_t io;
273
274
memset(&io, 0, sizeof(io));
275
276
io.open = dummy_open;
277
io.close = dummy_close;
278
io.read = dummy_read;
279
io.write = dummy_write;
280
281
wiredata = wiredata_setup(cbor_info_data, sizeof(cbor_info_data));
282
assert((dev = fido_dev_new()) != NULL);
283
assert(fido_dev_set_io_functions(dev, &io) == FIDO_OK);
284
assert(fido_dev_open(dev, "dummy") == FIDO_OK);
285
assert(fido_dev_is_fido2(dev) == true);
286
assert(fido_dev_supports_pin(dev) == true);
287
fido_dev_force_u2f(dev);
288
assert(fido_dev_is_fido2(dev) == false);
289
assert(fido_dev_supports_pin(dev) == false);
290
assert(fido_dev_close(dev) == FIDO_OK);
291
wiredata_clear(&wiredata);
292
293
wiredata = wiredata_setup(NULL, 0);
294
assert(fido_dev_open(dev, "dummy") == FIDO_OK);
295
assert(fido_dev_is_fido2(dev) == false);
296
assert(fido_dev_supports_pin(dev) == false);
297
fido_dev_force_fido2(dev);
298
assert(fido_dev_is_fido2(dev) == true);
299
assert(fido_dev_supports_pin(dev) == false);
300
assert(fido_dev_close(dev) == FIDO_OK);
301
fido_dev_free(&dev);
302
wiredata_clear(&wiredata);
303
}
304
305
static void
306
has_pin(void)
307
{
308
const uint8_t set_pin_data[] = {
309
WIREDATA_CTAP_CBOR_INFO,
310
WIREDATA_CTAP_CBOR_AUTHKEY,
311
WIREDATA_CTAP_CBOR_STATUS,
312
WIREDATA_CTAP_CBOR_STATUS
313
};
314
uint8_t *wiredata;
315
fido_dev_t *dev = NULL;
316
fido_dev_io_t io;
317
318
memset(&io, 0, sizeof(io));
319
320
io.open = dummy_open;
321
io.close = dummy_close;
322
io.read = dummy_read;
323
io.write = dummy_write;
324
325
wiredata = wiredata_setup(set_pin_data, sizeof(set_pin_data));
326
assert((dev = fido_dev_new()) != NULL);
327
assert(fido_dev_set_io_functions(dev, &io) == FIDO_OK);
328
assert(fido_dev_open(dev, "dummy") == FIDO_OK);
329
assert(fido_dev_has_pin(dev) == false);
330
assert(fido_dev_set_pin(dev, "top secret", NULL) == FIDO_OK);
331
assert(fido_dev_has_pin(dev) == true);
332
assert(fido_dev_reset(dev) == FIDO_OK);
333
assert(fido_dev_has_pin(dev) == false);
334
assert(fido_dev_close(dev) == FIDO_OK);
335
fido_dev_free(&dev);
336
wiredata_clear(&wiredata);
337
}
338
339
static void
340
timeout_rx(void)
341
{
342
const uint8_t timeout_rx_data[] = {
343
WIREDATA_CTAP_CBOR_INFO,
344
WIREDATA_CTAP_KEEPALIVE,
345
WIREDATA_CTAP_KEEPALIVE,
346
WIREDATA_CTAP_KEEPALIVE,
347
WIREDATA_CTAP_KEEPALIVE,
348
WIREDATA_CTAP_KEEPALIVE,
349
WIREDATA_CTAP_CBOR_STATUS
350
};
351
uint8_t *wiredata;
352
fido_dev_t *dev = NULL;
353
fido_dev_io_t io;
354
355
memset(&io, 0, sizeof(io));
356
357
io.open = dummy_open;
358
io.close = dummy_close;
359
io.read = dummy_read;
360
io.write = dummy_write;
361
362
wiredata = wiredata_setup(timeout_rx_data, sizeof(timeout_rx_data));
363
assert((dev = fido_dev_new()) != NULL);
364
assert(fido_dev_set_io_functions(dev, &io) == FIDO_OK);
365
assert(fido_dev_open(dev, "dummy") == FIDO_OK);
366
assert(fido_dev_set_timeout(dev, 3 * 1000) == FIDO_OK);
367
interval_ms = 1000;
368
assert(fido_dev_reset(dev) == FIDO_ERR_RX);
369
assert(fido_dev_close(dev) == FIDO_OK);
370
fido_dev_free(&dev);
371
wiredata_clear(&wiredata);
372
interval_ms = 0;
373
}
374
375
static void
376
timeout_ok(void)
377
{
378
const uint8_t timeout_ok_data[] = {
379
WIREDATA_CTAP_CBOR_INFO,
380
WIREDATA_CTAP_KEEPALIVE,
381
WIREDATA_CTAP_KEEPALIVE,
382
WIREDATA_CTAP_KEEPALIVE,
383
WIREDATA_CTAP_KEEPALIVE,
384
WIREDATA_CTAP_KEEPALIVE,
385
WIREDATA_CTAP_CBOR_STATUS
386
};
387
uint8_t *wiredata;
388
fido_dev_t *dev = NULL;
389
fido_dev_io_t io;
390
391
memset(&io, 0, sizeof(io));
392
393
io.open = dummy_open;
394
io.close = dummy_close;
395
io.read = dummy_read;
396
io.write = dummy_write;
397
398
wiredata = wiredata_setup(timeout_ok_data, sizeof(timeout_ok_data));
399
assert((dev = fido_dev_new()) != NULL);
400
assert(fido_dev_set_io_functions(dev, &io) == FIDO_OK);
401
assert(fido_dev_open(dev, "dummy") == FIDO_OK);
402
assert(fido_dev_set_timeout(dev, 30 * 1000) == FIDO_OK);
403
interval_ms = 1000;
404
assert(fido_dev_reset(dev) == FIDO_OK);
405
assert(fido_dev_close(dev) == FIDO_OK);
406
fido_dev_free(&dev);
407
wiredata_clear(&wiredata);
408
interval_ms = 0;
409
}
410
411
static void
412
timeout_misc(void)
413
{
414
fido_dev_t *dev;
415
416
assert((dev = fido_dev_new()) != NULL);
417
assert(fido_dev_set_timeout(dev, -2) == FIDO_ERR_INVALID_ARGUMENT);
418
assert(fido_dev_set_timeout(dev, 3 * 1000) == FIDO_OK);
419
assert(fido_dev_set_timeout(dev, -1) == FIDO_OK);
420
fido_dev_free(&dev);
421
}
422
423
int
424
main(void)
425
{
426
fido_init(0);
427
428
open_iff_ok();
429
reopen();
430
double_open();
431
double_close();
432
is_fido2();
433
has_pin();
434
timeout_rx();
435
timeout_ok();
436
timeout_misc();
437
438
exit(0);
439
}
440
441