2 * Copyright (c) 2018-2021 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.
10 decode_string(const cbor_item_t *item, void *arg)
12 fido_str_array_t *a = arg;
13 const size_t i = a->len;
15 /* keep ptr[x] and len consistent */
16 if (cbor_string_copy(item, &a->ptr[i]) < 0) {
17 fido_log_debug("%s: cbor_string_copy", __func__);
27 decode_string_array(const cbor_item_t *item, fido_str_array_t *v)
32 if (cbor_isa_array(item) == false ||
33 cbor_array_is_definite(item) == false) {
34 fido_log_debug("%s: cbor type", __func__);
38 v->ptr = calloc(cbor_array_size(item), sizeof(char *));
42 if (cbor_array_iter(item, v, decode_string) < 0) {
43 fido_log_debug("%s: decode_string", __func__);
51 decode_aaguid(const cbor_item_t *item, unsigned char *aaguid, size_t aaguid_len)
53 if (cbor_isa_bytestring(item) == false ||
54 cbor_bytestring_is_definite(item) == false ||
55 cbor_bytestring_length(item) != aaguid_len) {
56 fido_log_debug("%s: cbor type", __func__);
60 memcpy(aaguid, cbor_bytestring_handle(item), aaguid_len);
66 decode_option(const cbor_item_t *key, const cbor_item_t *val, void *arg)
68 fido_opt_array_t *o = arg;
69 const size_t i = o->len;
71 if (cbor_isa_float_ctrl(val) == false ||
72 cbor_float_get_width(val) != CBOR_FLOAT_0 ||
73 cbor_is_bool(val) == false) {
74 fido_log_debug("%s: cbor type", __func__);
75 return (0); /* ignore */
78 if (cbor_string_copy(key, &o->name[i]) < 0) {
79 fido_log_debug("%s: cbor_string_copy", __func__);
80 return (0); /* ignore */
83 /* keep name/value and len consistent */
84 o->value[i] = cbor_ctrl_value(val) == CBOR_CTRL_TRUE;
91 decode_options(const cbor_item_t *item, fido_opt_array_t *o)
97 if (cbor_isa_map(item) == false ||
98 cbor_map_is_definite(item) == false) {
99 fido_log_debug("%s: cbor type", __func__);
103 o->name = calloc(cbor_map_size(item), sizeof(char *));
104 o->value = calloc(cbor_map_size(item), sizeof(bool));
105 if (o->name == NULL || o->value == NULL)
108 return (cbor_map_iter(item, o, decode_option));
112 decode_protocol(const cbor_item_t *item, void *arg)
114 fido_byte_array_t *p = arg;
115 const size_t i = p->len;
117 if (cbor_isa_uint(item) == false ||
118 cbor_int_get_width(item) != CBOR_INT_8) {
119 fido_log_debug("%s: cbor type", __func__);
123 /* keep ptr[x] and len consistent */
124 p->ptr[i] = cbor_get_uint8(item);
131 decode_protocols(const cbor_item_t *item, fido_byte_array_t *p)
136 if (cbor_isa_array(item) == false ||
137 cbor_array_is_definite(item) == false) {
138 fido_log_debug("%s: cbor type", __func__);
142 p->ptr = calloc(cbor_array_size(item), sizeof(uint8_t));
146 if (cbor_array_iter(item, p, decode_protocol) < 0) {
147 fido_log_debug("%s: decode_protocol", __func__);
155 decode_algorithm_entry(const cbor_item_t *key, const cbor_item_t *val,
158 fido_algo_t *alg = arg;
162 if (cbor_string_copy(key, &name) < 0) {
163 fido_log_debug("%s: cbor type", __func__);
168 if (!strcmp(name, "alg")) {
169 if (cbor_isa_negint(val) == false ||
170 cbor_get_int(val) > INT_MAX || alg->cose != 0) {
171 fido_log_debug("%s: alg", __func__);
174 alg->cose = -(int)cbor_get_int(val) - 1;
175 } else if (!strcmp(name, "type")) {
176 if (cbor_string_copy(val, &alg->type) < 0) {
177 fido_log_debug("%s: type", __func__);
190 free_algo(fido_algo_t *a)
198 decode_algorithm(const cbor_item_t *item, void *arg)
200 fido_algo_array_t *aa = arg;
201 const size_t i = aa->len;
203 if (cbor_isa_map(item) == false ||
204 cbor_map_is_definite(item) == false) {
205 fido_log_debug("%s: cbor type", __func__);
209 memset(&aa->ptr[i], 0, sizeof(aa->ptr[i]));
211 if (cbor_map_iter(item, &aa->ptr[i], decode_algorithm_entry) < 0) {
212 fido_log_debug("%s: decode_algorithm_entry", __func__);
213 free_algo(&aa->ptr[i]);
217 /* keep ptr[x] and len consistent */
224 decode_algorithms(const cbor_item_t *item, fido_algo_array_t *aa)
229 if (cbor_isa_array(item) == false ||
230 cbor_array_is_definite(item) == false) {
231 fido_log_debug("%s: cbor type", __func__);
235 aa->ptr = calloc(cbor_array_size(item), sizeof(fido_algo_t));
239 if (cbor_array_iter(item, aa, decode_algorithm) < 0) {
240 fido_log_debug("%s: decode_algorithm", __func__);
248 parse_reply_element(const cbor_item_t *key, const cbor_item_t *val, void *arg)
250 fido_cbor_info_t *ci = arg;
252 if (cbor_isa_uint(key) == false ||
253 cbor_int_get_width(key) != CBOR_INT_8) {
254 fido_log_debug("%s: cbor type", __func__);
255 return (0); /* ignore */
258 switch (cbor_get_uint8(key)) {
259 case 1: /* versions */
260 return (decode_string_array(val, &ci->versions));
261 case 2: /* extensions */
262 return (decode_string_array(val, &ci->extensions));
264 return (decode_aaguid(val, ci->aaguid, sizeof(ci->aaguid)));
265 case 4: /* options */
266 return (decode_options(val, &ci->options));
267 case 5: /* maxMsgSize */
268 return (cbor_decode_uint64(val, &ci->maxmsgsiz));
269 case 6: /* pinProtocols */
270 return (decode_protocols(val, &ci->protocols));
271 case 7: /* maxCredentialCountInList */
272 return (cbor_decode_uint64(val, &ci->maxcredcntlst));
273 case 8: /* maxCredentialIdLength */
274 return (cbor_decode_uint64(val, &ci->maxcredidlen));
275 case 9: /* transports */
276 return (decode_string_array(val, &ci->transports));
277 case 10: /* algorithms */
278 return (decode_algorithms(val, &ci->algorithms));
279 case 14: /* fwVersion */
280 return (cbor_decode_uint64(val, &ci->fwversion));
281 case 15: /* maxCredBlobLen */
282 return (cbor_decode_uint64(val, &ci->maxcredbloblen));
283 default: /* ignore */
284 fido_log_debug("%s: cbor type", __func__);
290 fido_dev_get_cbor_info_tx(fido_dev_t *dev)
292 const unsigned char cbor[] = { CTAP_CBOR_GETINFO };
294 fido_log_debug("%s: dev=%p", __func__, (void *)dev);
296 if (fido_tx(dev, CTAP_CMD_CBOR, cbor, sizeof(cbor)) < 0) {
297 fido_log_debug("%s: fido_tx", __func__);
298 return (FIDO_ERR_TX);
305 fido_dev_get_cbor_info_rx(fido_dev_t *dev, fido_cbor_info_t *ci, int ms)
307 unsigned char reply[FIDO_MAXMSG];
310 fido_log_debug("%s: dev=%p, ci=%p, ms=%d", __func__, (void *)dev,
313 fido_cbor_info_reset(ci);
315 if ((reply_len = fido_rx(dev, CTAP_CMD_CBOR, &reply, sizeof(reply),
317 fido_log_debug("%s: fido_rx", __func__);
318 return (FIDO_ERR_RX);
321 return (cbor_parse_reply(reply, (size_t)reply_len, ci,
322 parse_reply_element));
326 fido_dev_get_cbor_info_wait(fido_dev_t *dev, fido_cbor_info_t *ci, int ms)
331 if (dev->flags & FIDO_DEV_WINHELLO)
332 return (fido_winhello_get_cbor_info(dev, ci));
334 if ((r = fido_dev_get_cbor_info_tx(dev)) != FIDO_OK ||
335 (r = fido_dev_get_cbor_info_rx(dev, ci, ms)) != FIDO_OK)
342 fido_dev_get_cbor_info(fido_dev_t *dev, fido_cbor_info_t *ci)
344 return (fido_dev_get_cbor_info_wait(dev, ci, -1));
348 * get/set functions for fido_cbor_info_t; always at the end of the file
352 fido_cbor_info_new(void)
354 return (calloc(1, sizeof(fido_cbor_info_t)));
358 free_str_array(fido_str_array_t *sa)
360 for (size_t i = 0; i < sa->len; i++)
369 free_opt_array(fido_opt_array_t *oa)
371 for (size_t i = 0; i < oa->len; i++)
381 free_byte_array(fido_byte_array_t *ba)
390 free_algo_array(fido_algo_array_t *aa)
392 for (size_t i = 0; i < aa->len; i++)
393 free_algo(&aa->ptr[i]);
401 fido_cbor_info_reset(fido_cbor_info_t *ci)
403 free_str_array(&ci->versions);
404 free_str_array(&ci->extensions);
405 free_str_array(&ci->transports);
406 free_opt_array(&ci->options);
407 free_byte_array(&ci->protocols);
408 free_algo_array(&ci->algorithms);
412 fido_cbor_info_free(fido_cbor_info_t **ci_p)
414 fido_cbor_info_t *ci;
416 if (ci_p == NULL || (ci = *ci_p) == NULL)
418 fido_cbor_info_reset(ci);
424 fido_cbor_info_versions_ptr(const fido_cbor_info_t *ci)
426 return (ci->versions.ptr);
430 fido_cbor_info_versions_len(const fido_cbor_info_t *ci)
432 return (ci->versions.len);
436 fido_cbor_info_extensions_ptr(const fido_cbor_info_t *ci)
438 return (ci->extensions.ptr);
442 fido_cbor_info_extensions_len(const fido_cbor_info_t *ci)
444 return (ci->extensions.len);
448 fido_cbor_info_transports_ptr(const fido_cbor_info_t *ci)
450 return (ci->transports.ptr);
454 fido_cbor_info_transports_len(const fido_cbor_info_t *ci)
456 return (ci->transports.len);
459 const unsigned char *
460 fido_cbor_info_aaguid_ptr(const fido_cbor_info_t *ci)
466 fido_cbor_info_aaguid_len(const fido_cbor_info_t *ci)
468 return (sizeof(ci->aaguid));
472 fido_cbor_info_options_name_ptr(const fido_cbor_info_t *ci)
474 return (ci->options.name);
478 fido_cbor_info_options_value_ptr(const fido_cbor_info_t *ci)
480 return (ci->options.value);
484 fido_cbor_info_options_len(const fido_cbor_info_t *ci)
486 return (ci->options.len);
490 fido_cbor_info_maxcredbloblen(const fido_cbor_info_t *ci)
492 return (ci->maxcredbloblen);
496 fido_cbor_info_maxmsgsiz(const fido_cbor_info_t *ci)
498 return (ci->maxmsgsiz);
502 fido_cbor_info_maxcredcntlst(const fido_cbor_info_t *ci)
504 return (ci->maxcredcntlst);
508 fido_cbor_info_maxcredidlen(const fido_cbor_info_t *ci)
510 return (ci->maxcredidlen);
514 fido_cbor_info_fwversion(const fido_cbor_info_t *ci)
516 return (ci->fwversion);
520 fido_cbor_info_protocols_ptr(const fido_cbor_info_t *ci)
522 return (ci->protocols.ptr);
526 fido_cbor_info_protocols_len(const fido_cbor_info_t *ci)
528 return (ci->protocols.len);
532 fido_cbor_info_algorithm_count(const fido_cbor_info_t *ci)
534 return (ci->algorithms.len);
538 fido_cbor_info_algorithm_type(const fido_cbor_info_t *ci, size_t idx)
540 if (idx >= ci->algorithms.len)
543 return (ci->algorithms.ptr[idx].type);
547 fido_cbor_info_algorithm_cose(const fido_cbor_info_t *ci, size_t idx)
549 if (idx >= ci->algorithms.len)
552 return (ci->algorithms.ptr[idx].cose);