xref: /freebsd/contrib/libfido2/regress/dev.c (revision febb0da5bf4bc99828ebede7abcb039514ac367a)
1 /*
2  * Copyright (c) 2019-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 
14 #define _FIDO_INTERNAL
15 
16 #include <fido.h>
17 
18 #include "../fuzz/wiredata_fido2.h"
19 #include "extern.h"
20 
21 /* gh#56 */
22 static void
open_iff_ok(void)23 open_iff_ok(void)
24 {
25 	fido_dev_t	*dev = NULL;
26 
27 	assert((dev = fido_dev_new()) != NULL);
28 	setup_dummy_io(dev);
29 	assert(fido_dev_open(dev, "dummy") == FIDO_ERR_RX);
30 	assert(fido_dev_close(dev) == FIDO_ERR_INVALID_ARGUMENT);
31 
32 	fido_dev_free(&dev);
33 }
34 
35 static void
reopen(void)36 reopen(void)
37 {
38 	const uint8_t	 cbor_info_data[] = { WIREDATA_CTAP_CBOR_INFO };
39 	uint8_t		*wiredata;
40 	fido_dev_t	*dev = NULL;
41 
42 	wiredata = wiredata_setup(cbor_info_data, sizeof(cbor_info_data));
43 	assert((dev = fido_dev_new()) != NULL);
44 	setup_dummy_io(dev);
45 	assert(fido_dev_open(dev, "dummy") == FIDO_OK);
46 	assert(fido_dev_close(dev) == FIDO_OK);
47 	wiredata_clear(&wiredata);
48 
49 	wiredata = wiredata_setup(cbor_info_data, sizeof(cbor_info_data));
50 	assert(fido_dev_open(dev, "dummy") == FIDO_OK);
51 	assert(fido_dev_close(dev) == FIDO_OK);
52 	fido_dev_free(&dev);
53 	wiredata_clear(&wiredata);
54 }
55 
56 static void
double_open(void)57 double_open(void)
58 {
59 	const uint8_t	 cbor_info_data[] = { WIREDATA_CTAP_CBOR_INFO };
60 	uint8_t		*wiredata;
61 	fido_dev_t	*dev = NULL;
62 
63 	wiredata = wiredata_setup(cbor_info_data, sizeof(cbor_info_data));
64 	assert((dev = fido_dev_new()) != NULL);
65 	setup_dummy_io(dev);
66 	assert(fido_dev_open(dev, "dummy") == FIDO_OK);
67 	assert(fido_dev_open(dev, "dummy") == FIDO_ERR_INVALID_ARGUMENT);
68 	assert(fido_dev_close(dev) == FIDO_OK);
69 	fido_dev_free(&dev);
70 	wiredata_clear(&wiredata);
71 }
72 
73 static void
double_close(void)74 double_close(void)
75 {
76 	const uint8_t	 cbor_info_data[] = { WIREDATA_CTAP_CBOR_INFO };
77 	uint8_t		*wiredata;
78 	fido_dev_t	*dev = NULL;
79 
80 	wiredata = wiredata_setup(cbor_info_data, sizeof(cbor_info_data));
81 	assert((dev = fido_dev_new()) != NULL);
82 	assert(fido_dev_close(dev) == FIDO_ERR_INVALID_ARGUMENT);
83 	setup_dummy_io(dev);
84 	assert(fido_dev_close(dev) == FIDO_ERR_INVALID_ARGUMENT);
85 	assert(fido_dev_open(dev, "dummy") == FIDO_OK);
86 	assert(fido_dev_close(dev) == FIDO_OK);
87 	assert(fido_dev_close(dev) == FIDO_ERR_INVALID_ARGUMENT);
88 	fido_dev_free(&dev);
89 	wiredata_clear(&wiredata);
90 }
91 
92 static void
is_fido2(void)93 is_fido2(void)
94 {
95 	const uint8_t	 cbor_info_data[] = { WIREDATA_CTAP_CBOR_INFO };
96 	uint8_t		*wiredata;
97 	fido_dev_t	*dev = NULL;
98 
99 	wiredata = wiredata_setup(cbor_info_data, sizeof(cbor_info_data));
100 	assert((dev = fido_dev_new()) != NULL);
101 	setup_dummy_io(dev);
102 	assert(fido_dev_open(dev, "dummy") == FIDO_OK);
103 	assert(fido_dev_is_fido2(dev) == true);
104 	assert(fido_dev_supports_pin(dev) == true);
105 	fido_dev_force_u2f(dev);
106 	assert(fido_dev_is_fido2(dev) == false);
107 	assert(fido_dev_supports_pin(dev) == false);
108 	assert(fido_dev_close(dev) == FIDO_OK);
109 	wiredata_clear(&wiredata);
110 
111 	wiredata = wiredata_setup(NULL, 0);
112 	assert(fido_dev_open(dev, "dummy") == FIDO_OK);
113 	assert(fido_dev_is_fido2(dev) == false);
114 	assert(fido_dev_supports_pin(dev) == false);
115 	fido_dev_force_fido2(dev);
116 	assert(fido_dev_is_fido2(dev) == true);
117 	assert(fido_dev_supports_pin(dev) == false);
118 	assert(fido_dev_close(dev) == FIDO_OK);
119 	fido_dev_free(&dev);
120 	wiredata_clear(&wiredata);
121 }
122 
123 static void
has_pin(void)124 has_pin(void)
125 {
126 	const uint8_t	 set_pin_data[] = {
127 			    WIREDATA_CTAP_CBOR_INFO,
128 			    WIREDATA_CTAP_CBOR_AUTHKEY,
129 			    WIREDATA_CTAP_CBOR_STATUS,
130 			    WIREDATA_CTAP_CBOR_STATUS
131 			 };
132 	uint8_t		*wiredata;
133 	fido_dev_t	*dev = NULL;
134 
135 	wiredata = wiredata_setup(set_pin_data, sizeof(set_pin_data));
136 	assert((dev = fido_dev_new()) != NULL);
137 	setup_dummy_io(dev);
138 	assert(fido_dev_open(dev, "dummy") == FIDO_OK);
139 	assert(fido_dev_has_pin(dev) == false);
140 	assert(fido_dev_set_pin(dev, "top secret", NULL) == FIDO_OK);
141 	assert(fido_dev_has_pin(dev) == true);
142 	assert(fido_dev_reset(dev) == FIDO_OK);
143 	assert(fido_dev_has_pin(dev) == false);
144 	assert(fido_dev_close(dev) == FIDO_OK);
145 	fido_dev_free(&dev);
146 	wiredata_clear(&wiredata);
147 }
148 
149 static void
timeout_rx(void)150 timeout_rx(void)
151 {
152 	const uint8_t	 timeout_rx_data[] = {
153 			    WIREDATA_CTAP_CBOR_INFO,
154 			    WIREDATA_CTAP_KEEPALIVE,
155 			    WIREDATA_CTAP_KEEPALIVE,
156 			    WIREDATA_CTAP_KEEPALIVE,
157 			    WIREDATA_CTAP_KEEPALIVE,
158 			    WIREDATA_CTAP_KEEPALIVE,
159 			    WIREDATA_CTAP_CBOR_STATUS
160 			 };
161 	uint8_t		*wiredata;
162 	fido_dev_t	*dev = NULL;
163 
164 	wiredata = wiredata_setup(timeout_rx_data, sizeof(timeout_rx_data));
165 	assert((dev = fido_dev_new()) != NULL);
166 	setup_dummy_io(dev);
167 	assert(fido_dev_open(dev, "dummy") == FIDO_OK);
168 	assert(fido_dev_set_timeout(dev, 3 * 1000) == FIDO_OK);
169 	set_read_interval(1000);
170 	assert(fido_dev_reset(dev) == FIDO_ERR_RX);
171 	assert(fido_dev_close(dev) == FIDO_OK);
172 	fido_dev_free(&dev);
173 	wiredata_clear(&wiredata);
174 	set_read_interval(0);
175 }
176 
177 static void
timeout_ok(void)178 timeout_ok(void)
179 {
180 	const uint8_t	 timeout_ok_data[] = {
181 			    WIREDATA_CTAP_CBOR_INFO,
182 			    WIREDATA_CTAP_KEEPALIVE,
183 			    WIREDATA_CTAP_KEEPALIVE,
184 			    WIREDATA_CTAP_KEEPALIVE,
185 			    WIREDATA_CTAP_KEEPALIVE,
186 			    WIREDATA_CTAP_KEEPALIVE,
187 			    WIREDATA_CTAP_CBOR_STATUS
188 			 };
189 	uint8_t		*wiredata;
190 	fido_dev_t	*dev = NULL;
191 
192 	wiredata = wiredata_setup(timeout_ok_data, sizeof(timeout_ok_data));
193 	assert((dev = fido_dev_new()) != NULL);
194 	setup_dummy_io(dev);
195 	assert(fido_dev_open(dev, "dummy") == FIDO_OK);
196 	assert(fido_dev_set_timeout(dev, 30 * 1000) == FIDO_OK);
197 	set_read_interval(1000);
198 	assert(fido_dev_reset(dev) == FIDO_OK);
199 	assert(fido_dev_close(dev) == FIDO_OK);
200 	fido_dev_free(&dev);
201 	wiredata_clear(&wiredata);
202 	set_read_interval(0);
203 }
204 
205 static void
timeout_misc(void)206 timeout_misc(void)
207 {
208 	fido_dev_t *dev;
209 
210 	assert((dev = fido_dev_new()) != NULL);
211 	assert(fido_dev_set_timeout(dev, -2) == FIDO_ERR_INVALID_ARGUMENT);
212 	assert(fido_dev_set_timeout(dev, 3 * 1000) == FIDO_OK);
213 	assert(fido_dev_set_timeout(dev, -1) == FIDO_OK);
214 	fido_dev_free(&dev);
215 }
216 
217 int
main(void)218 main(void)
219 {
220 	fido_init(0);
221 
222 	open_iff_ok();
223 	reopen();
224 	double_open();
225 	double_close();
226 	is_fido2();
227 	has_pin();
228 	timeout_rx();
229 	timeout_ok();
230 	timeout_misc();
231 
232 	exit(0);
233 }
234