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