Line | Count | Source |
1 | | /* |
2 | | * Copyright (c) 2018-2026 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 | | #include "fido.h" |
9 | | |
10 | | static int |
11 | | decode_string(const cbor_item_t *item, void *arg) |
12 | 694k | { |
13 | 694k | fido_str_array_t *a = arg; |
14 | 694k | const size_t i = a->len; |
15 | | |
16 | | /* keep ptr[x] and len consistent */ |
17 | 694k | if (cbor_string_copy(item, &a->ptr[i]) < 0) { |
18 | 907 | fido_log_debug("%s: cbor_string_copy", __func__); |
19 | 907 | return (-1); |
20 | 907 | } |
21 | | |
22 | 693k | a->len++; |
23 | | |
24 | 693k | return (0); |
25 | 694k | } |
26 | | |
27 | | static int |
28 | | decode_string_array(const cbor_item_t *item, fido_str_array_t *v) |
29 | 222k | { |
30 | 222k | v->ptr = NULL; |
31 | 222k | v->len = 0; |
32 | | |
33 | 222k | if (cbor_isa_array(item) == false || |
34 | 222k | cbor_array_is_definite(item) == false) { |
35 | 151 | fido_log_debug("%s: cbor type", __func__); |
36 | 151 | return (-1); |
37 | 151 | } |
38 | | |
39 | 222k | v->ptr = calloc(cbor_array_size(item), sizeof(char *)); |
40 | 222k | if (v->ptr == NULL) |
41 | 67 | return (-1); |
42 | | |
43 | 222k | if (cbor_array_iter(item, v, decode_string) < 0) { |
44 | 953 | fido_log_debug("%s: decode_string", __func__); |
45 | 953 | return (-1); |
46 | 953 | } |
47 | | |
48 | 221k | return (0); |
49 | 222k | } |
50 | | |
51 | | static int |
52 | | decode_aaguid(const cbor_item_t *item, unsigned char *aaguid, size_t aaguid_len) |
53 | 77.2k | { |
54 | 77.2k | if (cbor_isa_bytestring(item) == false || |
55 | 77.2k | cbor_bytestring_is_definite(item) == false || |
56 | 77.2k | cbor_bytestring_length(item) != aaguid_len) { |
57 | 473 | fido_log_debug("%s: cbor type", __func__); |
58 | 473 | return (-1); |
59 | 473 | } |
60 | | |
61 | 76.8k | memcpy(aaguid, cbor_bytestring_handle(item), aaguid_len); |
62 | | |
63 | 76.8k | return (0); |
64 | 77.2k | } |
65 | | |
66 | | static int |
67 | | decode_option(const cbor_item_t *key, const cbor_item_t *val, void *arg) |
68 | 611k | { |
69 | 611k | fido_opt_array_t *o = arg; |
70 | 611k | const size_t i = o->len; |
71 | | |
72 | 611k | if (cbor_decode_bool(val, NULL) < 0) { |
73 | 26.6k | fido_log_debug("%s: cbor_decode_bool", __func__); |
74 | 26.6k | return (0); /* ignore */ |
75 | 26.6k | } |
76 | | |
77 | 584k | if (cbor_string_copy(key, &o->name[i]) < 0) { |
78 | 1.87k | fido_log_debug("%s: cbor_string_copy", __func__); |
79 | 1.87k | return (0); /* ignore */ |
80 | 1.87k | } |
81 | | |
82 | | /* keep name/value and len consistent */ |
83 | 582k | o->value[i] = cbor_ctrl_value(val) == CBOR_CTRL_TRUE; |
84 | 582k | o->len++; |
85 | | |
86 | 582k | return (0); |
87 | 584k | } |
88 | | |
89 | | static int |
90 | | decode_options(const cbor_item_t *item, fido_opt_array_t *o) |
91 | 74.2k | { |
92 | 74.2k | o->name = NULL; |
93 | 74.2k | o->value = NULL; |
94 | 74.2k | o->len = 0; |
95 | | |
96 | 74.2k | if (cbor_isa_map(item) == false || |
97 | 74.2k | cbor_map_is_definite(item) == false) { |
98 | 114 | fido_log_debug("%s: cbor type", __func__); |
99 | 114 | return (-1); |
100 | 114 | } |
101 | | |
102 | 74.1k | o->name = calloc(cbor_map_size(item), sizeof(char *)); |
103 | 74.1k | o->value = calloc(cbor_map_size(item), sizeof(bool)); |
104 | 74.1k | if (o->name == NULL || o->value == NULL) |
105 | 113 | return (-1); |
106 | | |
107 | 74.0k | return (cbor_map_iter(item, o, decode_option)); |
108 | 74.1k | } |
109 | | |
110 | | static int |
111 | | decode_byte_array_item(const cbor_item_t *item, void *arg) |
112 | 185k | { |
113 | 185k | fido_byte_array_t *p = arg; |
114 | 185k | const size_t i = p->len; |
115 | | |
116 | 185k | if (cbor_isa_uint(item) == false || |
117 | 185k | cbor_int_get_width(item) != CBOR_INT_8) { |
118 | 199 | fido_log_debug("%s: cbor type", __func__); |
119 | 199 | return (-1); |
120 | 199 | } |
121 | | |
122 | | /* keep ptr[x] and len consistent */ |
123 | 185k | p->ptr[i] = cbor_get_uint8(item); |
124 | 185k | p->len++; |
125 | | |
126 | 185k | return (0); |
127 | 185k | } |
128 | | |
129 | | static int |
130 | | decode_byte_array(const cbor_item_t *item, fido_byte_array_t *p) |
131 | 91.0k | { |
132 | 91.0k | p->ptr = NULL; |
133 | 91.0k | p->len = 0; |
134 | | |
135 | 91.0k | if (cbor_isa_array(item) == false || |
136 | 91.0k | cbor_array_is_definite(item) == false) { |
137 | 108 | fido_log_debug("%s: cbor type", __func__); |
138 | 108 | return (-1); |
139 | 108 | } |
140 | | |
141 | 90.9k | p->ptr = calloc(cbor_array_size(item), sizeof(uint8_t)); |
142 | 90.9k | if (p->ptr == NULL) |
143 | 83 | return (-1); |
144 | | |
145 | 90.8k | if (cbor_array_iter(item, p, decode_byte_array_item) < 0) { |
146 | 224 | fido_log_debug("%s: decode_byte_array_item", __func__); |
147 | 224 | return (-1); |
148 | 224 | } |
149 | | |
150 | 90.6k | return (0); |
151 | 90.8k | } |
152 | | |
153 | | static int |
154 | | decode_algorithm_entry(const cbor_item_t *key, const cbor_item_t *val, |
155 | | void *arg) |
156 | 278k | { |
157 | 278k | fido_algo_t *alg = arg; |
158 | 278k | char *name = NULL; |
159 | 278k | int ok = -1; |
160 | | |
161 | 278k | if (cbor_string_copy(key, &name) < 0) { |
162 | 3.72k | fido_log_debug("%s: cbor type", __func__); |
163 | 3.72k | ok = 0; /* ignore */ |
164 | 3.72k | goto out; |
165 | 3.72k | } |
166 | | |
167 | 275k | if (!strcmp(name, "alg")) { |
168 | 124k | if (cbor_isa_negint(val) == false || |
169 | 124k | cbor_get_int(val) > INT_MAX || alg->cose != 0) { |
170 | 1.00k | fido_log_debug("%s: alg", __func__); |
171 | 1.00k | goto out; |
172 | 1.00k | } |
173 | 123k | alg->cose = -(int)cbor_get_int(val) - 1; |
174 | 150k | } else if (!strcmp(name, "type")) { |
175 | 113k | if (cbor_string_copy(val, &alg->type) < 0) { |
176 | 185 | fido_log_debug("%s: type", __func__); |
177 | 185 | goto out; |
178 | 185 | } |
179 | 113k | } |
180 | | |
181 | 273k | ok = 0; |
182 | 278k | out: |
183 | 278k | free(name); |
184 | | |
185 | 278k | return (ok); |
186 | 273k | } |
187 | | |
188 | | static int |
189 | | decode_algorithm(const cbor_item_t *item, void *arg) |
190 | 152k | { |
191 | 152k | fido_algo_array_t *aa = arg; |
192 | 152k | const size_t i = aa->len; |
193 | | |
194 | 152k | if (cbor_isa_map(item) == false || |
195 | 152k | cbor_map_is_definite(item) == false) { |
196 | 1.13k | fido_log_debug("%s: cbor type", __func__); |
197 | 1.13k | return (-1); |
198 | 1.13k | } |
199 | | |
200 | 151k | memset(&aa->ptr[i], 0, sizeof(aa->ptr[i])); |
201 | | |
202 | 151k | if (cbor_map_iter(item, &aa->ptr[i], decode_algorithm_entry) < 0) { |
203 | 2.26k | fido_log_debug("%s: decode_algorithm_entry", __func__); |
204 | 2.26k | fido_algo_free(&aa->ptr[i]); |
205 | 2.26k | return (-1); |
206 | 2.26k | } |
207 | | |
208 | | /* keep ptr[x] and len consistent */ |
209 | 148k | aa->len++; |
210 | | |
211 | 148k | return (0); |
212 | 151k | } |
213 | | |
214 | | static int |
215 | | decode_algorithms(const cbor_item_t *item, fido_algo_array_t *aa) |
216 | 63.5k | { |
217 | 63.5k | aa->ptr = NULL; |
218 | 63.5k | aa->len = 0; |
219 | | |
220 | 63.5k | if (cbor_isa_array(item) == false || |
221 | 63.5k | cbor_array_is_definite(item) == false) { |
222 | 120 | fido_log_debug("%s: cbor type", __func__); |
223 | 120 | return (-1); |
224 | 120 | } |
225 | | |
226 | 63.4k | aa->ptr = calloc(cbor_array_size(item), sizeof(fido_algo_t)); |
227 | 63.4k | if (aa->ptr == NULL) |
228 | 48 | return (-1); |
229 | | |
230 | 63.3k | if (cbor_array_iter(item, aa, decode_algorithm) < 0) { |
231 | 3.41k | fido_log_debug("%s: decode_algorithm", __func__); |
232 | 3.41k | return (-1); |
233 | 3.41k | } |
234 | | |
235 | 59.9k | return (0); |
236 | 63.3k | } |
237 | | |
238 | | static int |
239 | | decode_cert(const cbor_item_t *key, const cbor_item_t *val, void *arg) |
240 | 26.4k | { |
241 | 26.4k | fido_cert_array_t *c = arg; |
242 | 26.4k | const size_t i = c->len; |
243 | | |
244 | 26.4k | if (cbor_is_int(val) == false) { |
245 | 6.62k | fido_log_debug("%s: cbor_is_int", __func__); |
246 | 6.62k | return (0); /* ignore */ |
247 | 6.62k | } |
248 | | |
249 | 19.8k | if (cbor_string_copy(key, &c->name[i]) < 0) { |
250 | 1.49k | fido_log_debug("%s: cbor_string_copy", __func__); |
251 | 1.49k | return (0); /* ignore */ |
252 | 1.49k | } |
253 | | |
254 | | /* keep name/value and len consistent */ |
255 | 18.3k | c->value[i] = cbor_get_int(val); |
256 | 18.3k | c->len++; |
257 | | |
258 | 18.3k | return (0); |
259 | 19.8k | } |
260 | | |
261 | | static int |
262 | | decode_certs(const cbor_item_t *item, fido_cert_array_t *c) |
263 | 6.15k | { |
264 | 6.15k | c->name = NULL; |
265 | 6.15k | c->value = NULL; |
266 | 6.15k | c->len = 0; |
267 | | |
268 | 6.15k | if (cbor_isa_map(item) == false || |
269 | 6.15k | cbor_map_is_definite(item) == false) { |
270 | 109 | fido_log_debug("%s: cbor type", __func__); |
271 | 109 | return (-1); |
272 | 109 | } |
273 | | |
274 | 6.04k | c->name = calloc(cbor_map_size(item), sizeof(char *)); |
275 | 6.04k | c->value = calloc(cbor_map_size(item), sizeof(uint64_t)); |
276 | 6.04k | if (c->name == NULL || c->value == NULL) |
277 | 86 | return (-1); |
278 | | |
279 | 5.96k | return (cbor_map_iter(item, c, decode_cert)); |
280 | 6.04k | } |
281 | | |
282 | | static int |
283 | | parse_reply_element(const cbor_item_t *key, const cbor_item_t *val, void *arg) |
284 | 1.07M | { |
285 | 1.07M | fido_cbor_info_t *ci = arg; |
286 | 1.07M | uint64_t x; |
287 | 1.07M | bool b; |
288 | | |
289 | 1.07M | if (cbor_isa_uint(key) == false || |
290 | 1.07M | cbor_int_get_width(key) != CBOR_INT_8) { |
291 | 17.6k | fido_log_debug("%s: cbor type", __func__); |
292 | 17.6k | return (0); /* ignore */ |
293 | 17.6k | } |
294 | | |
295 | 1.06M | switch (cbor_get_uint8(key)) { |
296 | 75.7k | case 1: /* versions */ |
297 | 75.7k | return (decode_string_array(val, &ci->versions)); |
298 | 80.9k | case 2: /* extensions */ |
299 | 80.9k | return (decode_string_array(val, &ci->extensions)); |
300 | 77.2k | case 3: /* aaguid */ |
301 | 77.2k | return (decode_aaguid(val, ci->aaguid, sizeof(ci->aaguid))); |
302 | 74.2k | case 4: /* options */ |
303 | 74.2k | return (decode_options(val, &ci->options)); |
304 | 73.6k | case 5: /* maxMsgSize */ |
305 | 73.6k | return (cbor_decode_uint64(val, &ci->maxmsgsiz)); |
306 | 73.8k | case 6: /* pinProtocols */ |
307 | 73.8k | return (decode_byte_array(val, &ci->protocols)); |
308 | 70.4k | case 7: /* maxCredentialCountInList */ |
309 | 70.4k | return (cbor_decode_uint64(val, &ci->maxcredcntlst)); |
310 | 68.9k | case 8: /* maxCredentialIdLength */ |
311 | 68.9k | return (cbor_decode_uint64(val, &ci->maxcredidlen)); |
312 | 30.4k | case 9: /* transports */ |
313 | 30.4k | return (decode_string_array(val, &ci->transports)); |
314 | 63.5k | case 10: /* algorithms */ |
315 | 63.5k | return (decode_algorithms(val, &ci->algorithms)); |
316 | 24.6k | case 11: /* maxSerializedLargeBlobArray */ |
317 | 24.6k | return (cbor_decode_uint64(val, &ci->maxlargeblob)); |
318 | 24.6k | case 12: /* forcePINChange */ |
319 | 24.6k | return (cbor_decode_bool(val, &ci->new_pin_reqd)); |
320 | 28.2k | case 13: /* minPINLength */ |
321 | 28.2k | return (cbor_decode_uint64(val, &ci->minpinlen)); |
322 | 28.7k | case 14: /* fwVersion */ |
323 | 28.7k | return (cbor_decode_uint64(val, &ci->fwversion)); |
324 | 25.0k | case 15: /* maxCredBlobLen */ |
325 | 25.0k | return (cbor_decode_uint64(val, &ci->maxcredbloblen)); |
326 | 24.6k | case 16: /* maxRPIDsForSetMinPINLength */ |
327 | 24.6k | return (cbor_decode_uint64(val, &ci->maxrpid_minlen)); |
328 | 6.66k | case 17: /* preferredPlatformUvAttempts */ |
329 | 6.66k | return (cbor_decode_uint64(val, &ci->uv_attempts)); |
330 | 6.56k | case 18: /* uvModality */ |
331 | 6.56k | return (cbor_decode_uint64(val, &ci->uv_modality)); |
332 | 6.15k | case 19: /* certifications */ |
333 | 6.15k | return (decode_certs(val, &ci->certs)); |
334 | 26.0k | case 20: /* remainingDiscoverableCredentials */ |
335 | 26.0k | if (cbor_decode_uint64(val, &x) < 0 || x > INT64_MAX) { |
336 | 244 | fido_log_debug("%s: cbor_decode_uint64", __func__); |
337 | 244 | return (-1); |
338 | 244 | } |
339 | 25.7k | ci->rk_remaining = (int64_t)x; |
340 | 25.7k | return (0); |
341 | 17.9k | case 22: /* attestationFormats */ |
342 | 17.9k | return (decode_string_array(val, &ci->attfmts)); |
343 | 1.74k | case 23: /* uvCountSinceLastPinEntry */ |
344 | 1.74k | if (cbor_decode_uint64(val, &x) < 0 || x > INT64_MAX) { |
345 | 247 | fido_log_debug("%s: cbor_decode_uint64", __func__); |
346 | 247 | return (-1); |
347 | 247 | } |
348 | 1.49k | ci->uv_since_pin = (int64_t)x; |
349 | 1.49k | return (0); |
350 | 17.8k | case 24: /* longTouchForReset */ |
351 | 17.8k | return (cbor_decode_bool(val, &ci->long_reset)); |
352 | 17.9k | case 25: /* encIdentifier */ |
353 | 17.9k | return (fido_blob_decode(val, &ci->encid)); |
354 | 17.7k | case 26: /* transportsForReset */ |
355 | 17.7k | return (decode_string_array(val, &ci->rsttransports)); |
356 | 17.6k | case 27: /* pinComplexityPolicy */ |
357 | 17.6k | if (cbor_decode_bool(val, &b) < 0) { |
358 | 102 | fido_log_debug("%s: cbor_decode_bool", __func__); |
359 | 102 | return (-1); |
360 | 102 | } |
361 | 17.5k | ci->pinpolicy = b; |
362 | 17.5k | return (0); |
363 | 17.4k | case 28: /* pinComplexityPolicyUrl */ |
364 | 17.4k | return (fido_blob_decode(val, &ci->pinpolicyurl)); |
365 | 17.4k | case 29: /* maxPINLength */ |
366 | 17.4k | return (cbor_decode_uint64(val, &ci->maxpinlen)); |
367 | 17.4k | case 30: /* encCredStoreState */ |
368 | 17.4k | return (fido_blob_decode(val, &ci->encstate)); |
369 | 17.1k | case 31: /* authenticatorConfigCommands */ |
370 | 17.1k | return (decode_byte_array(val, &ci->cfgcmds)); |
371 | 9.20k | default: /* ignore */ |
372 | 9.20k | fido_log_debug("%s: cbor type: 0x%02x", __func__, cbor_get_uint8(key)); |
373 | 9.20k | return (0); |
374 | 1.06M | } |
375 | 1.06M | } |
376 | | |
377 | | static int |
378 | | fido_dev_get_cbor_info_tx(fido_dev_t *dev, int *ms) |
379 | 237k | { |
380 | 237k | const unsigned char cbor[] = { CTAP_CBOR_GETINFO }; |
381 | | |
382 | 237k | fido_log_debug("%s: dev=%p", __func__, (void *)dev); |
383 | | |
384 | 237k | if (fido_tx(dev, CTAP_CMD_CBOR, cbor, sizeof(cbor), ms) < 0) { |
385 | 2.64k | fido_log_debug("%s: fido_tx", __func__); |
386 | 2.64k | return (FIDO_ERR_TX); |
387 | 2.64k | } |
388 | | |
389 | 234k | return (FIDO_OK); |
390 | 237k | } |
391 | | |
392 | | static int |
393 | | fido_dev_get_cbor_info_rx(fido_dev_t *dev, fido_cbor_info_t *ci, int *ms) |
394 | 234k | { |
395 | 234k | unsigned char *msg; |
396 | 234k | int msglen; |
397 | 234k | int r; |
398 | | |
399 | 234k | fido_log_debug("%s: dev=%p, ci=%p, ms=%d", __func__, (void *)dev, |
400 | 234k | (void *)ci, *ms); |
401 | | |
402 | 234k | fido_cbor_info_reset(ci); |
403 | | |
404 | 234k | if ((msg = malloc(FIDO_MAXMSG)) == NULL) { |
405 | 596 | r = FIDO_ERR_INTERNAL; |
406 | 596 | goto out; |
407 | 596 | } |
408 | | |
409 | 234k | if ((msglen = fido_rx(dev, CTAP_CMD_CBOR, msg, FIDO_MAXMSG, ms)) < 0) { |
410 | 54.9k | fido_log_debug("%s: fido_rx", __func__); |
411 | 54.9k | r = FIDO_ERR_RX; |
412 | 54.9k | goto out; |
413 | 54.9k | } |
414 | | |
415 | 179k | r = cbor_parse_reply(msg, (size_t)msglen, ci, parse_reply_element); |
416 | 234k | out: |
417 | 234k | freezero(msg, FIDO_MAXMSG); |
418 | | |
419 | 234k | return (r); |
420 | 179k | } |
421 | | |
422 | | int |
423 | | fido_dev_get_cbor_info_wait(fido_dev_t *dev, fido_cbor_info_t *ci, int *ms) |
424 | 237k | { |
425 | 237k | int r; |
426 | | |
427 | | #ifdef USE_WINHELLO |
428 | | if (dev->flags & FIDO_DEV_WINHELLO) |
429 | | return (fido_winhello_get_cbor_info(dev, ci)); |
430 | | #endif |
431 | 237k | if ((r = fido_dev_get_cbor_info_tx(dev, ms)) != FIDO_OK || |
432 | 237k | (r = fido_dev_get_cbor_info_rx(dev, ci, ms)) != FIDO_OK) |
433 | 164k | return (r); |
434 | | |
435 | 73.1k | return (FIDO_OK); |
436 | 237k | } |
437 | | |
438 | | int |
439 | | fido_dev_get_cbor_info(fido_dev_t *dev, fido_cbor_info_t *ci) |
440 | 5.05k | { |
441 | 5.05k | int ms = dev->timeout_ms; |
442 | | |
443 | 5.05k | return (fido_dev_get_cbor_info_wait(dev, ci, &ms)); |
444 | 5.05k | } |
445 | | |
446 | | /* |
447 | | * get/set functions for fido_cbor_info_t; always at the end of the file |
448 | | */ |
449 | | |
450 | | fido_cbor_info_t * |
451 | | fido_cbor_info_new(void) |
452 | 238k | { |
453 | 238k | fido_cbor_info_t *ci; |
454 | | |
455 | 238k | if ((ci = calloc(1, sizeof(fido_cbor_info_t))) == NULL) |
456 | 682 | return (NULL); |
457 | | |
458 | 237k | fido_cbor_info_reset(ci); |
459 | | |
460 | 237k | return (ci); |
461 | 238k | } |
462 | | |
463 | | void |
464 | | fido_cbor_info_reset(fido_cbor_info_t *ci) |
465 | 709k | { |
466 | 709k | fido_str_array_free(&ci->versions); |
467 | 709k | fido_str_array_free(&ci->extensions); |
468 | 709k | fido_str_array_free(&ci->transports); |
469 | 709k | fido_str_array_free(&ci->attfmts); |
470 | 709k | fido_str_array_free(&ci->rsttransports); |
471 | 709k | fido_opt_array_free(&ci->options); |
472 | 709k | fido_byte_array_free(&ci->protocols); |
473 | 709k | fido_byte_array_free(&ci->cfgcmds); |
474 | 709k | fido_algo_array_free(&ci->algorithms); |
475 | 709k | fido_cert_array_free(&ci->certs); |
476 | 709k | fido_blob_reset(&ci->encid); |
477 | 709k | fido_blob_reset(&ci->id); |
478 | 709k | fido_blob_reset(&ci->pinpolicyurl); |
479 | 709k | fido_blob_reset(&ci->encstate); |
480 | 709k | fido_blob_reset(&ci->state); |
481 | 709k | ci->rk_remaining = -1; |
482 | 709k | ci->uv_since_pin = -1; |
483 | 709k | ci->pinpolicy = -1; |
484 | 709k | } |
485 | | |
486 | | void |
487 | | fido_cbor_info_free(fido_cbor_info_t **ci_p) |
488 | 665k | { |
489 | 665k | fido_cbor_info_t *ci; |
490 | | |
491 | 665k | if (ci_p == NULL || (ci = *ci_p) == NULL) |
492 | 428k | return; |
493 | 237k | fido_cbor_info_reset(ci); |
494 | 237k | free(ci); |
495 | 237k | *ci_p = NULL; |
496 | 237k | } |
497 | | |
498 | | char ** |
499 | | fido_cbor_info_versions_ptr(const fido_cbor_info_t *ci) |
500 | 8.53k | { |
501 | 8.53k | return (ci->versions.ptr); |
502 | 8.53k | } |
503 | | |
504 | | size_t |
505 | | fido_cbor_info_versions_len(const fido_cbor_info_t *ci) |
506 | 13.5k | { |
507 | 13.5k | return (ci->versions.len); |
508 | 13.5k | } |
509 | | |
510 | | char ** |
511 | | fido_cbor_info_extensions_ptr(const fido_cbor_info_t *ci) |
512 | 81.3k | { |
513 | 81.3k | return (ci->extensions.ptr); |
514 | 81.3k | } |
515 | | |
516 | | size_t |
517 | | fido_cbor_info_extensions_len(const fido_cbor_info_t *ci) |
518 | 86.3k | { |
519 | 86.3k | return (ci->extensions.len); |
520 | 86.3k | } |
521 | | |
522 | | char ** |
523 | | fido_cbor_info_transports_ptr(const fido_cbor_info_t *ci) |
524 | 4.19k | { |
525 | 4.19k | return (ci->transports.ptr); |
526 | 4.19k | } |
527 | | |
528 | | size_t |
529 | | fido_cbor_info_transports_len(const fido_cbor_info_t *ci) |
530 | 9.24k | { |
531 | 9.24k | return (ci->transports.len); |
532 | 9.24k | } |
533 | | |
534 | | const unsigned char * |
535 | | fido_cbor_info_aaguid_ptr(const fido_cbor_info_t *ci) |
536 | 5.05k | { |
537 | 5.05k | return (ci->aaguid); |
538 | 5.05k | } |
539 | | |
540 | | size_t |
541 | | fido_cbor_info_aaguid_len(const fido_cbor_info_t *ci) |
542 | 5.05k | { |
543 | 5.05k | return (sizeof(ci->aaguid)); |
544 | 5.05k | } |
545 | | |
546 | | const unsigned char * |
547 | | fido_cbor_info_encid_ptr(const fido_cbor_info_t *ci) |
548 | 5.05k | { |
549 | 5.05k | return (ci->encid.ptr); |
550 | 5.05k | } |
551 | | |
552 | | size_t |
553 | | fido_cbor_info_encid_len(const fido_cbor_info_t *ci) |
554 | 5.05k | { |
555 | 5.05k | return (ci->encid.len); |
556 | 5.05k | } |
557 | | |
558 | | const unsigned char * |
559 | | fido_cbor_info_id_ptr(const fido_cbor_info_t *ci) |
560 | 5.05k | { |
561 | 5.05k | return (ci->id.ptr); |
562 | 5.05k | } |
563 | | |
564 | | size_t |
565 | | fido_cbor_info_id_len(const fido_cbor_info_t *ci) |
566 | 5.05k | { |
567 | 5.05k | return (ci->id.len); |
568 | 5.05k | } |
569 | | |
570 | | const unsigned char * |
571 | | fido_cbor_info_encstate_ptr(const fido_cbor_info_t *ci) |
572 | 5.05k | { |
573 | 5.05k | return (ci->encstate.ptr); |
574 | 5.05k | } |
575 | | |
576 | | size_t |
577 | | fido_cbor_info_encstate_len(const fido_cbor_info_t *ci) |
578 | 5.05k | { |
579 | 5.05k | return (ci->encstate.len); |
580 | 5.05k | } |
581 | | |
582 | | const unsigned char * |
583 | | fido_cbor_info_state_ptr(const fido_cbor_info_t *ci) |
584 | 5.05k | { |
585 | 5.05k | return (ci->state.ptr); |
586 | 5.05k | } |
587 | | |
588 | | size_t |
589 | | fido_cbor_info_state_len(const fido_cbor_info_t *ci) |
590 | 5.05k | { |
591 | 5.05k | return (ci->state.len); |
592 | 5.05k | } |
593 | | |
594 | | char ** |
595 | | fido_cbor_info_options_name_ptr(const fido_cbor_info_t *ci) |
596 | 86.1k | { |
597 | 86.1k | return (ci->options.name); |
598 | 86.1k | } |
599 | | |
600 | | const bool * |
601 | | fido_cbor_info_options_value_ptr(const fido_cbor_info_t *ci) |
602 | 86.1k | { |
603 | 86.1k | return (ci->options.value); |
604 | 86.1k | } |
605 | | |
606 | | size_t |
607 | | fido_cbor_info_options_len(const fido_cbor_info_t *ci) |
608 | 91.1k | { |
609 | 91.1k | return (ci->options.len); |
610 | 91.1k | } |
611 | | |
612 | | uint64_t |
613 | | fido_cbor_info_maxcredbloblen(const fido_cbor_info_t *ci) |
614 | 5.05k | { |
615 | 5.05k | return (ci->maxcredbloblen); |
616 | 5.05k | } |
617 | | |
618 | | uint64_t |
619 | | fido_cbor_info_maxmsgsiz(const fido_cbor_info_t *ci) |
620 | 77.1k | { |
621 | 77.1k | return (ci->maxmsgsiz); |
622 | 77.1k | } |
623 | | |
624 | | uint64_t |
625 | | fido_cbor_info_maxcredcntlst(const fido_cbor_info_t *ci) |
626 | 5.05k | { |
627 | 5.05k | return (ci->maxcredcntlst); |
628 | 5.05k | } |
629 | | |
630 | | uint64_t |
631 | | fido_cbor_info_maxcredidlen(const fido_cbor_info_t *ci) |
632 | 5.05k | { |
633 | 5.05k | return (ci->maxcredidlen); |
634 | 5.05k | } |
635 | | |
636 | | uint64_t |
637 | | fido_cbor_info_maxlargeblob(const fido_cbor_info_t *ci) |
638 | 5.05k | { |
639 | 5.05k | return (ci->maxlargeblob); |
640 | 5.05k | } |
641 | | |
642 | | uint64_t |
643 | | fido_cbor_info_fwversion(const fido_cbor_info_t *ci) |
644 | 5.05k | { |
645 | 5.05k | return (ci->fwversion); |
646 | 5.05k | } |
647 | | |
648 | | uint64_t |
649 | | fido_cbor_info_minpinlen(const fido_cbor_info_t *ci) |
650 | 5.05k | { |
651 | 5.05k | return (ci->minpinlen); |
652 | 5.05k | } |
653 | | |
654 | | uint64_t |
655 | | fido_cbor_info_maxrpid_minpinlen(const fido_cbor_info_t *ci) |
656 | 5.05k | { |
657 | 5.05k | return (ci->maxrpid_minlen); |
658 | 5.05k | } |
659 | | |
660 | | uint64_t |
661 | | fido_cbor_info_uv_attempts(const fido_cbor_info_t *ci) |
662 | 5.05k | { |
663 | 5.05k | return (ci->uv_attempts); |
664 | 5.05k | } |
665 | | |
666 | | int64_t |
667 | | fido_cbor_info_uv_count_since_pin(const fido_cbor_info_t *ci) |
668 | 5.05k | { |
669 | 5.05k | return (ci->uv_since_pin); |
670 | 5.05k | } |
671 | | |
672 | | uint64_t |
673 | | fido_cbor_info_uv_modality(const fido_cbor_info_t *ci) |
674 | 5.05k | { |
675 | 5.05k | return (ci->uv_modality); |
676 | 5.05k | } |
677 | | |
678 | | int64_t |
679 | | fido_cbor_info_rk_remaining(const fido_cbor_info_t *ci) |
680 | 5.05k | { |
681 | 5.05k | return (ci->rk_remaining); |
682 | 5.05k | } |
683 | | |
684 | | const uint8_t * |
685 | | fido_cbor_info_protocols_ptr(const fido_cbor_info_t *ci) |
686 | 77.1k | { |
687 | 77.1k | return (ci->protocols.ptr); |
688 | 77.1k | } |
689 | | |
690 | | size_t |
691 | | fido_cbor_info_protocols_len(const fido_cbor_info_t *ci) |
692 | 77.1k | { |
693 | 77.1k | return (ci->protocols.len); |
694 | 77.1k | } |
695 | | |
696 | | size_t |
697 | | fido_cbor_info_algorithm_count(const fido_cbor_info_t *ci) |
698 | 13.5k | { |
699 | 13.5k | return (ci->algorithms.len); |
700 | 13.5k | } |
701 | | |
702 | | const char * |
703 | | fido_cbor_info_algorithm_type(const fido_cbor_info_t *ci, size_t idx) |
704 | 8.48k | { |
705 | 8.48k | if (idx >= ci->algorithms.len) |
706 | 5.05k | return (NULL); |
707 | | |
708 | 3.42k | return (ci->algorithms.ptr[idx].type); |
709 | 8.48k | } |
710 | | |
711 | | int |
712 | | fido_cbor_info_algorithm_cose(const fido_cbor_info_t *ci, size_t idx) |
713 | 8.48k | { |
714 | 8.48k | if (idx >= ci->algorithms.len) |
715 | 5.05k | return (0); |
716 | | |
717 | 3.42k | return (ci->algorithms.ptr[idx].cose); |
718 | 8.48k | } |
719 | | |
720 | | bool |
721 | | fido_cbor_info_new_pin_required(const fido_cbor_info_t *ci) |
722 | 5.05k | { |
723 | 5.05k | return (ci->new_pin_reqd); |
724 | 5.05k | } |
725 | | |
726 | | bool |
727 | | fido_cbor_info_long_touch_reset(const fido_cbor_info_t *ci) |
728 | 5.05k | { |
729 | 5.05k | return (ci->long_reset); |
730 | 5.05k | } |
731 | | |
732 | | char ** |
733 | | fido_cbor_info_certs_name_ptr(const fido_cbor_info_t *ci) |
734 | 475 | { |
735 | 475 | return (ci->certs.name); |
736 | 475 | } |
737 | | |
738 | | const uint64_t * |
739 | | fido_cbor_info_certs_value_ptr(const fido_cbor_info_t *ci) |
740 | 475 | { |
741 | 475 | return (ci->certs.value); |
742 | 475 | } |
743 | | |
744 | | size_t |
745 | | fido_cbor_info_certs_len(const fido_cbor_info_t *ci) |
746 | 5.52k | { |
747 | 5.52k | return (ci->certs.len); |
748 | 5.52k | } |
749 | | |
750 | | char ** |
751 | | fido_cbor_info_attfmts_ptr(const fido_cbor_info_t *ci) |
752 | 808 | { |
753 | 808 | return (ci->attfmts.ptr); |
754 | 808 | } |
755 | | |
756 | | size_t |
757 | | fido_cbor_info_attfmts_len(const fido_cbor_info_t *ci) |
758 | 5.86k | { |
759 | 5.86k | return (ci->attfmts.len); |
760 | 5.86k | } |
761 | | |
762 | | char ** |
763 | | fido_cbor_info_reset_transports_ptr(const fido_cbor_info_t *ci) |
764 | 1.47k | { |
765 | 1.47k | return (ci->rsttransports.ptr); |
766 | 1.47k | } |
767 | | |
768 | | size_t |
769 | | fido_cbor_info_reset_transports_len(const fido_cbor_info_t *ci) |
770 | 6.52k | { |
771 | 6.52k | return (ci->rsttransports.len); |
772 | 6.52k | } |
773 | | |
774 | | int |
775 | | fido_cbor_info_pin_policy(const fido_cbor_info_t *ci) |
776 | 5.05k | { |
777 | 5.05k | return (ci->pinpolicy); |
778 | 5.05k | } |
779 | | |
780 | | const unsigned char* |
781 | | fido_cbor_info_pin_policy_url_ptr(const fido_cbor_info_t *ci) |
782 | 5.05k | { |
783 | 5.05k | return (ci->pinpolicyurl.ptr); |
784 | 5.05k | } |
785 | | |
786 | | size_t |
787 | | fido_cbor_info_pin_policy_url_len(const fido_cbor_info_t *ci) |
788 | 5.05k | { |
789 | 5.05k | return (ci->pinpolicyurl.len); |
790 | 5.05k | } |
791 | | |
792 | | uint64_t |
793 | | fido_cbor_info_maxpinlen(const fido_cbor_info_t *ci) |
794 | 5.05k | { |
795 | 5.05k | return (ci->maxpinlen); |
796 | 5.05k | } |
797 | | |
798 | | const uint8_t * |
799 | | fido_cbor_info_cfgcmds_ptr(const fido_cbor_info_t *ci) |
800 | 5.05k | { |
801 | 5.05k | return (ci->cfgcmds.ptr); |
802 | 5.05k | } |
803 | | |
804 | | size_t |
805 | | fido_cbor_info_cfgcmds_len(const fido_cbor_info_t *ci) |
806 | 5.05k | { |
807 | 5.05k | return (ci->cfgcmds.len); |
808 | 5.05k | } |
809 | | |
810 | | static int |
811 | | decrypt(const fido_blob_t *secret, const char *info, const fido_blob_t *in, |
812 | | fido_blob_t *out) |
813 | 1.40k | { |
814 | 1.40k | fido_blob_t key; |
815 | 1.40k | unsigned char keybuf[16]; |
816 | 1.40k | int r = FIDO_ERR_INTERNAL; |
817 | | |
818 | 1.40k | key.ptr = keybuf; |
819 | 1.40k | key.len = sizeof(keybuf); |
820 | | |
821 | 1.40k | fido_blob_reset(out); |
822 | | |
823 | 1.40k | if (hkdf_sha256(key.ptr, key.len, info, secret) != 0) { |
824 | 28 | fido_log_debug("%s: hkdf_sha256", __func__); |
825 | 28 | goto fail; |
826 | 28 | } |
827 | 1.38k | if (aes128_cbc_dec(&key, in, out) != 0) { |
828 | 119 | fido_log_debug("%s: aes128_cbc_dec", __func__); |
829 | 119 | goto fail; |
830 | 119 | } |
831 | | |
832 | 1.26k | r = FIDO_OK; |
833 | 1.40k | fail: |
834 | 1.40k | explicit_bzero(key.ptr, key.len); |
835 | | |
836 | 1.40k | return r; |
837 | 1.26k | } |
838 | | |
839 | | int |
840 | | fido_cbor_info_decrypt(fido_cbor_info_t *ci, const unsigned char *ppuat, |
841 | | size_t ppuat_len) |
842 | 5.05k | { |
843 | 5.05k | fido_blob_t secret; |
844 | 5.05k | int r; |
845 | | |
846 | 5.05k | memset(&secret, 0, sizeof(secret)); |
847 | | |
848 | 5.05k | if (fido_blob_set(&secret, ppuat, ppuat_len) != 0) { |
849 | 784 | fido_log_debug("%s: fido_blob_set", __func__); |
850 | 784 | r = FIDO_ERR_INTERNAL; |
851 | 784 | goto fail; |
852 | 784 | } |
853 | | |
854 | 4.27k | if (!fido_blob_is_empty(&ci->encid) && (r = decrypt(&secret, |
855 | 801 | "encIdentifier", &ci->encid, &ci->id)) != FIDO_OK) { |
856 | 117 | fido_log_debug("%s: encIdentifier", __func__); |
857 | 117 | goto fail; |
858 | 117 | } |
859 | | |
860 | 4.15k | if (!fido_blob_is_empty(&ci->encstate) && (r = decrypt(&secret, |
861 | 607 | "encCredStoreState", &ci->encstate, &ci->state)) != FIDO_OK) { |
862 | 30 | fido_log_debug("%s: encIdentifier", __func__); |
863 | 30 | goto fail; |
864 | 30 | } |
865 | | |
866 | 4.12k | r = FIDO_OK; |
867 | 5.05k | fail: |
868 | 5.05k | fido_blob_reset(&secret); |
869 | | |
870 | 5.05k | return r; |
871 | 4.12k | } |