xref: /freebsd/contrib/libfido2/src/info.c (revision 2ccfa855)
10afa8e06SEd Maste /*
2*2ccfa855SEd Maste  * Copyright (c) 2018-2022 Yubico AB. All rights reserved.
30afa8e06SEd Maste  * Use of this source code is governed by a BSD-style
40afa8e06SEd Maste  * license that can be found in the LICENSE file.
5*2ccfa855SEd Maste  * SPDX-License-Identifier: BSD-2-Clause
60afa8e06SEd Maste  */
70afa8e06SEd Maste 
80afa8e06SEd Maste #include "fido.h"
90afa8e06SEd Maste 
100afa8e06SEd Maste static int
decode_string(const cbor_item_t * item,void * arg)110afa8e06SEd Maste decode_string(const cbor_item_t *item, void *arg)
120afa8e06SEd Maste {
130afa8e06SEd Maste 	fido_str_array_t	*a = arg;
140afa8e06SEd Maste 	const size_t		 i = a->len;
150afa8e06SEd Maste 
160afa8e06SEd Maste 	/* keep ptr[x] and len consistent */
170afa8e06SEd Maste 	if (cbor_string_copy(item, &a->ptr[i]) < 0) {
180afa8e06SEd Maste 		fido_log_debug("%s: cbor_string_copy", __func__);
190afa8e06SEd Maste 		return (-1);
200afa8e06SEd Maste 	}
210afa8e06SEd Maste 
220afa8e06SEd Maste 	a->len++;
230afa8e06SEd Maste 
240afa8e06SEd Maste 	return (0);
250afa8e06SEd Maste }
260afa8e06SEd Maste 
270afa8e06SEd Maste static int
decode_string_array(const cbor_item_t * item,fido_str_array_t * v)280afa8e06SEd Maste decode_string_array(const cbor_item_t *item, fido_str_array_t *v)
290afa8e06SEd Maste {
300afa8e06SEd Maste 	v->ptr = NULL;
310afa8e06SEd Maste 	v->len = 0;
320afa8e06SEd Maste 
330afa8e06SEd Maste 	if (cbor_isa_array(item) == false ||
340afa8e06SEd Maste 	    cbor_array_is_definite(item) == false) {
350afa8e06SEd Maste 		fido_log_debug("%s: cbor type", __func__);
360afa8e06SEd Maste 		return (-1);
370afa8e06SEd Maste 	}
380afa8e06SEd Maste 
390afa8e06SEd Maste 	v->ptr = calloc(cbor_array_size(item), sizeof(char *));
400afa8e06SEd Maste 	if (v->ptr == NULL)
410afa8e06SEd Maste 		return (-1);
420afa8e06SEd Maste 
430afa8e06SEd Maste 	if (cbor_array_iter(item, v, decode_string) < 0) {
440afa8e06SEd Maste 		fido_log_debug("%s: decode_string", __func__);
450afa8e06SEd Maste 		return (-1);
460afa8e06SEd Maste 	}
470afa8e06SEd Maste 
480afa8e06SEd Maste 	return (0);
490afa8e06SEd Maste }
500afa8e06SEd Maste 
510afa8e06SEd Maste static int
decode_aaguid(const cbor_item_t * item,unsigned char * aaguid,size_t aaguid_len)520afa8e06SEd Maste decode_aaguid(const cbor_item_t *item, unsigned char *aaguid, size_t aaguid_len)
530afa8e06SEd Maste {
540afa8e06SEd Maste 	if (cbor_isa_bytestring(item) == false ||
550afa8e06SEd Maste 	    cbor_bytestring_is_definite(item) == false ||
560afa8e06SEd Maste 	    cbor_bytestring_length(item) != aaguid_len) {
570afa8e06SEd Maste 		fido_log_debug("%s: cbor type", __func__);
580afa8e06SEd Maste 		return (-1);
590afa8e06SEd Maste 	}
600afa8e06SEd Maste 
610afa8e06SEd Maste 	memcpy(aaguid, cbor_bytestring_handle(item), aaguid_len);
620afa8e06SEd Maste 
630afa8e06SEd Maste 	return (0);
640afa8e06SEd Maste }
650afa8e06SEd Maste 
660afa8e06SEd Maste static int
decode_option(const cbor_item_t * key,const cbor_item_t * val,void * arg)670afa8e06SEd Maste decode_option(const cbor_item_t *key, const cbor_item_t *val, void *arg)
680afa8e06SEd Maste {
690afa8e06SEd Maste 	fido_opt_array_t	*o = arg;
700afa8e06SEd Maste 	const size_t		 i = o->len;
710afa8e06SEd Maste 
72*2ccfa855SEd Maste 	if (cbor_decode_bool(val, NULL) < 0) {
73*2ccfa855SEd Maste 		fido_log_debug("%s: cbor_decode_bool", __func__);
740afa8e06SEd Maste 		return (0); /* ignore */
750afa8e06SEd Maste 	}
760afa8e06SEd Maste 
770afa8e06SEd Maste 	if (cbor_string_copy(key, &o->name[i]) < 0) {
780afa8e06SEd Maste 		fido_log_debug("%s: cbor_string_copy", __func__);
790afa8e06SEd Maste 		return (0); /* ignore */
800afa8e06SEd Maste 	}
810afa8e06SEd Maste 
820afa8e06SEd Maste 	/* keep name/value and len consistent */
830afa8e06SEd Maste 	o->value[i] = cbor_ctrl_value(val) == CBOR_CTRL_TRUE;
840afa8e06SEd Maste 	o->len++;
850afa8e06SEd Maste 
860afa8e06SEd Maste 	return (0);
870afa8e06SEd Maste }
880afa8e06SEd Maste 
890afa8e06SEd Maste static int
decode_options(const cbor_item_t * item,fido_opt_array_t * o)900afa8e06SEd Maste decode_options(const cbor_item_t *item, fido_opt_array_t *o)
910afa8e06SEd Maste {
920afa8e06SEd Maste 	o->name = NULL;
930afa8e06SEd Maste 	o->value = NULL;
940afa8e06SEd Maste 	o->len = 0;
950afa8e06SEd Maste 
960afa8e06SEd Maste 	if (cbor_isa_map(item) == false ||
970afa8e06SEd Maste 	    cbor_map_is_definite(item) == false) {
980afa8e06SEd Maste 		fido_log_debug("%s: cbor type", __func__);
990afa8e06SEd Maste 		return (-1);
1000afa8e06SEd Maste 	}
1010afa8e06SEd Maste 
1020afa8e06SEd Maste 	o->name = calloc(cbor_map_size(item), sizeof(char *));
1030afa8e06SEd Maste 	o->value = calloc(cbor_map_size(item), sizeof(bool));
1040afa8e06SEd Maste 	if (o->name == NULL || o->value == NULL)
1050afa8e06SEd Maste 		return (-1);
1060afa8e06SEd Maste 
1070afa8e06SEd Maste 	return (cbor_map_iter(item, o, decode_option));
1080afa8e06SEd Maste }
1090afa8e06SEd Maste 
1100afa8e06SEd Maste static int
decode_protocol(const cbor_item_t * item,void * arg)1110afa8e06SEd Maste decode_protocol(const cbor_item_t *item, void *arg)
1120afa8e06SEd Maste {
1130afa8e06SEd Maste 	fido_byte_array_t	*p = arg;
1140afa8e06SEd Maste 	const size_t		 i = p->len;
1150afa8e06SEd Maste 
1160afa8e06SEd Maste 	if (cbor_isa_uint(item) == false ||
1170afa8e06SEd Maste 	    cbor_int_get_width(item) != CBOR_INT_8) {
1180afa8e06SEd Maste 		fido_log_debug("%s: cbor type", __func__);
1190afa8e06SEd Maste 		return (-1);
1200afa8e06SEd Maste 	}
1210afa8e06SEd Maste 
1220afa8e06SEd Maste 	/* keep ptr[x] and len consistent */
1230afa8e06SEd Maste 	p->ptr[i] = cbor_get_uint8(item);
1240afa8e06SEd Maste 	p->len++;
1250afa8e06SEd Maste 
1260afa8e06SEd Maste 	return (0);
1270afa8e06SEd Maste }
1280afa8e06SEd Maste 
1290afa8e06SEd Maste static int
decode_protocols(const cbor_item_t * item,fido_byte_array_t * p)1300afa8e06SEd Maste decode_protocols(const cbor_item_t *item, fido_byte_array_t *p)
1310afa8e06SEd Maste {
1320afa8e06SEd Maste 	p->ptr = NULL;
1330afa8e06SEd Maste 	p->len = 0;
1340afa8e06SEd Maste 
1350afa8e06SEd Maste 	if (cbor_isa_array(item) == false ||
1360afa8e06SEd Maste 	    cbor_array_is_definite(item) == false) {
1370afa8e06SEd Maste 		fido_log_debug("%s: cbor type", __func__);
1380afa8e06SEd Maste 		return (-1);
1390afa8e06SEd Maste 	}
1400afa8e06SEd Maste 
1410afa8e06SEd Maste 	p->ptr = calloc(cbor_array_size(item), sizeof(uint8_t));
1420afa8e06SEd Maste 	if (p->ptr == NULL)
1430afa8e06SEd Maste 		return (-1);
1440afa8e06SEd Maste 
1450afa8e06SEd Maste 	if (cbor_array_iter(item, p, decode_protocol) < 0) {
1460afa8e06SEd Maste 		fido_log_debug("%s: decode_protocol", __func__);
1470afa8e06SEd Maste 		return (-1);
1480afa8e06SEd Maste 	}
1490afa8e06SEd Maste 
1500afa8e06SEd Maste 	return (0);
1510afa8e06SEd Maste }
1520afa8e06SEd Maste 
1530afa8e06SEd Maste static int
decode_algorithm_entry(const cbor_item_t * key,const cbor_item_t * val,void * arg)1540afa8e06SEd Maste decode_algorithm_entry(const cbor_item_t *key, const cbor_item_t *val,
1550afa8e06SEd Maste     void *arg)
1560afa8e06SEd Maste {
1570afa8e06SEd Maste 	fido_algo_t *alg = arg;
1580afa8e06SEd Maste 	char *name = NULL;
1590afa8e06SEd Maste 	int ok = -1;
1600afa8e06SEd Maste 
1610afa8e06SEd Maste 	if (cbor_string_copy(key, &name) < 0) {
1620afa8e06SEd Maste 		fido_log_debug("%s: cbor type", __func__);
1630afa8e06SEd Maste 		ok = 0; /* ignore */
1640afa8e06SEd Maste 		goto out;
1650afa8e06SEd Maste 	}
1660afa8e06SEd Maste 
1670afa8e06SEd Maste 	if (!strcmp(name, "alg")) {
1680afa8e06SEd Maste 		if (cbor_isa_negint(val) == false ||
1690afa8e06SEd Maste 		    cbor_get_int(val) > INT_MAX || alg->cose != 0) {
1700afa8e06SEd Maste 			fido_log_debug("%s: alg", __func__);
1710afa8e06SEd Maste 			goto out;
1720afa8e06SEd Maste 		}
1730afa8e06SEd Maste 		alg->cose = -(int)cbor_get_int(val) - 1;
1740afa8e06SEd Maste 	} else if (!strcmp(name, "type")) {
1750afa8e06SEd Maste 		if (cbor_string_copy(val, &alg->type) < 0) {
1760afa8e06SEd Maste 			fido_log_debug("%s: type", __func__);
1770afa8e06SEd Maste 			goto out;
1780afa8e06SEd Maste 		}
1790afa8e06SEd Maste 	}
1800afa8e06SEd Maste 
1810afa8e06SEd Maste 	ok = 0;
1820afa8e06SEd Maste out:
1830afa8e06SEd Maste 	free(name);
1840afa8e06SEd Maste 
1850afa8e06SEd Maste 	return (ok);
1860afa8e06SEd Maste }
1870afa8e06SEd Maste 
1880afa8e06SEd Maste static int
decode_algorithm(const cbor_item_t * item,void * arg)1890afa8e06SEd Maste decode_algorithm(const cbor_item_t *item, void *arg)
1900afa8e06SEd Maste {
1910afa8e06SEd Maste 	fido_algo_array_t *aa = arg;
1920afa8e06SEd Maste 	const size_t i = aa->len;
1930afa8e06SEd Maste 
1940afa8e06SEd Maste 	if (cbor_isa_map(item) == false ||
1950afa8e06SEd Maste 	    cbor_map_is_definite(item) == false) {
1960afa8e06SEd Maste 		fido_log_debug("%s: cbor type", __func__);
1970afa8e06SEd Maste 		return (-1);
1980afa8e06SEd Maste 	}
1990afa8e06SEd Maste 
2000afa8e06SEd Maste 	memset(&aa->ptr[i], 0, sizeof(aa->ptr[i]));
2010afa8e06SEd Maste 
2020afa8e06SEd Maste 	if (cbor_map_iter(item, &aa->ptr[i], decode_algorithm_entry) < 0) {
2030afa8e06SEd Maste 		fido_log_debug("%s: decode_algorithm_entry", __func__);
204f540a430SEd Maste 		fido_algo_free(&aa->ptr[i]);
2050afa8e06SEd Maste 		return (-1);
2060afa8e06SEd Maste 	}
2070afa8e06SEd Maste 
2080afa8e06SEd Maste 	/* keep ptr[x] and len consistent */
2090afa8e06SEd Maste 	aa->len++;
2100afa8e06SEd Maste 
2110afa8e06SEd Maste 	return (0);
2120afa8e06SEd Maste }
2130afa8e06SEd Maste 
2140afa8e06SEd Maste static int
decode_algorithms(const cbor_item_t * item,fido_algo_array_t * aa)2150afa8e06SEd Maste decode_algorithms(const cbor_item_t *item, fido_algo_array_t *aa)
2160afa8e06SEd Maste {
2170afa8e06SEd Maste 	aa->ptr = NULL;
2180afa8e06SEd Maste 	aa->len = 0;
2190afa8e06SEd Maste 
2200afa8e06SEd Maste 	if (cbor_isa_array(item) == false ||
2210afa8e06SEd Maste 	    cbor_array_is_definite(item) == false) {
2220afa8e06SEd Maste 		fido_log_debug("%s: cbor type", __func__);
2230afa8e06SEd Maste 		return (-1);
2240afa8e06SEd Maste 	}
2250afa8e06SEd Maste 
2260afa8e06SEd Maste 	aa->ptr = calloc(cbor_array_size(item), sizeof(fido_algo_t));
2270afa8e06SEd Maste 	if (aa->ptr == NULL)
2280afa8e06SEd Maste 		return (-1);
2290afa8e06SEd Maste 
2300afa8e06SEd Maste 	if (cbor_array_iter(item, aa, decode_algorithm) < 0) {
2310afa8e06SEd Maste 		fido_log_debug("%s: decode_algorithm", __func__);
2320afa8e06SEd Maste 		return (-1);
2330afa8e06SEd Maste 	}
2340afa8e06SEd Maste 
2350afa8e06SEd Maste 	return (0);
2360afa8e06SEd Maste }
2370afa8e06SEd Maste 
2380afa8e06SEd Maste static int
decode_cert(const cbor_item_t * key,const cbor_item_t * val,void * arg)239*2ccfa855SEd Maste decode_cert(const cbor_item_t *key, const cbor_item_t *val, void *arg)
240*2ccfa855SEd Maste {
241*2ccfa855SEd Maste 	fido_cert_array_t	*c = arg;
242*2ccfa855SEd Maste 	const size_t		 i = c->len;
243*2ccfa855SEd Maste 
244*2ccfa855SEd Maste 	if (cbor_is_int(val) == false) {
245*2ccfa855SEd Maste 		fido_log_debug("%s: cbor_is_int", __func__);
246*2ccfa855SEd Maste 		return (0); /* ignore */
247*2ccfa855SEd Maste 	}
248*2ccfa855SEd Maste 
249*2ccfa855SEd Maste 	if (cbor_string_copy(key, &c->name[i]) < 0) {
250*2ccfa855SEd Maste 		fido_log_debug("%s: cbor_string_copy", __func__);
251*2ccfa855SEd Maste 		return (0); /* ignore */
252*2ccfa855SEd Maste 	}
253*2ccfa855SEd Maste 
254*2ccfa855SEd Maste 	/* keep name/value and len consistent */
255*2ccfa855SEd Maste 	c->value[i] = cbor_get_int(val);
256*2ccfa855SEd Maste 	c->len++;
257*2ccfa855SEd Maste 
258*2ccfa855SEd Maste 	return (0);
259*2ccfa855SEd Maste }
260*2ccfa855SEd Maste 
261*2ccfa855SEd Maste static int
decode_certs(const cbor_item_t * item,fido_cert_array_t * c)262*2ccfa855SEd Maste decode_certs(const cbor_item_t *item, fido_cert_array_t *c)
263*2ccfa855SEd Maste {
264*2ccfa855SEd Maste 	c->name = NULL;
265*2ccfa855SEd Maste 	c->value = NULL;
266*2ccfa855SEd Maste 	c->len = 0;
267*2ccfa855SEd Maste 
268*2ccfa855SEd Maste 	if (cbor_isa_map(item) == false ||
269*2ccfa855SEd Maste 	    cbor_map_is_definite(item) == false) {
270*2ccfa855SEd Maste 		fido_log_debug("%s: cbor type", __func__);
271*2ccfa855SEd Maste 		return (-1);
272*2ccfa855SEd Maste 	}
273*2ccfa855SEd Maste 
274*2ccfa855SEd Maste 	c->name = calloc(cbor_map_size(item), sizeof(char *));
275*2ccfa855SEd Maste 	c->value = calloc(cbor_map_size(item), sizeof(uint64_t));
276*2ccfa855SEd Maste 	if (c->name == NULL || c->value == NULL)
277*2ccfa855SEd Maste 		return (-1);
278*2ccfa855SEd Maste 
279*2ccfa855SEd Maste 	return (cbor_map_iter(item, c, decode_cert));
280*2ccfa855SEd Maste }
281*2ccfa855SEd Maste 
282*2ccfa855SEd Maste static int
parse_reply_element(const cbor_item_t * key,const cbor_item_t * val,void * arg)2830afa8e06SEd Maste parse_reply_element(const cbor_item_t *key, const cbor_item_t *val, void *arg)
2840afa8e06SEd Maste {
2850afa8e06SEd Maste 	fido_cbor_info_t *ci = arg;
286*2ccfa855SEd Maste 	uint64_t x;
2870afa8e06SEd Maste 
2880afa8e06SEd Maste 	if (cbor_isa_uint(key) == false ||
2890afa8e06SEd Maste 	    cbor_int_get_width(key) != CBOR_INT_8) {
2900afa8e06SEd Maste 		fido_log_debug("%s: cbor type", __func__);
2910afa8e06SEd Maste 		return (0); /* ignore */
2920afa8e06SEd Maste 	}
2930afa8e06SEd Maste 
2940afa8e06SEd Maste 	switch (cbor_get_uint8(key)) {
2950afa8e06SEd Maste 	case 1: /* versions */
2960afa8e06SEd Maste 		return (decode_string_array(val, &ci->versions));
2970afa8e06SEd Maste 	case 2: /* extensions */
2980afa8e06SEd Maste 		return (decode_string_array(val, &ci->extensions));
2990afa8e06SEd Maste 	case 3: /* aaguid */
3000afa8e06SEd Maste 		return (decode_aaguid(val, ci->aaguid, sizeof(ci->aaguid)));
3010afa8e06SEd Maste 	case 4: /* options */
3020afa8e06SEd Maste 		return (decode_options(val, &ci->options));
3030afa8e06SEd Maste 	case 5: /* maxMsgSize */
3040afa8e06SEd Maste 		return (cbor_decode_uint64(val, &ci->maxmsgsiz));
3050afa8e06SEd Maste 	case 6: /* pinProtocols */
3060afa8e06SEd Maste 		return (decode_protocols(val, &ci->protocols));
3070afa8e06SEd Maste 	case 7: /* maxCredentialCountInList */
3080afa8e06SEd Maste 		return (cbor_decode_uint64(val, &ci->maxcredcntlst));
3090afa8e06SEd Maste 	case 8: /* maxCredentialIdLength */
3100afa8e06SEd Maste 		return (cbor_decode_uint64(val, &ci->maxcredidlen));
3110afa8e06SEd Maste 	case 9: /* transports */
3120afa8e06SEd Maste 		return (decode_string_array(val, &ci->transports));
3130afa8e06SEd Maste 	case 10: /* algorithms */
3140afa8e06SEd Maste 		return (decode_algorithms(val, &ci->algorithms));
315*2ccfa855SEd Maste 	case 11: /* maxSerializedLargeBlobArray */
316*2ccfa855SEd Maste 		return (cbor_decode_uint64(val, &ci->maxlargeblob));
317*2ccfa855SEd Maste 	case 12: /* forcePINChange */
318*2ccfa855SEd Maste 		return (cbor_decode_bool(val, &ci->new_pin_reqd));
319*2ccfa855SEd Maste 	case 13: /* minPINLength */
320*2ccfa855SEd Maste 		return (cbor_decode_uint64(val, &ci->minpinlen));
3210afa8e06SEd Maste 	case 14: /* fwVersion */
3220afa8e06SEd Maste 		return (cbor_decode_uint64(val, &ci->fwversion));
3230afa8e06SEd Maste 	case 15: /* maxCredBlobLen */
3240afa8e06SEd Maste 		return (cbor_decode_uint64(val, &ci->maxcredbloblen));
325*2ccfa855SEd Maste 	case 16: /* maxRPIDsForSetMinPINLength */
326*2ccfa855SEd Maste 		return (cbor_decode_uint64(val, &ci->maxrpid_minlen));
327*2ccfa855SEd Maste 	case 17: /* preferredPlatformUvAttempts */
328*2ccfa855SEd Maste 		return (cbor_decode_uint64(val, &ci->uv_attempts));
329*2ccfa855SEd Maste 	case 18: /* uvModality */
330*2ccfa855SEd Maste 		return (cbor_decode_uint64(val, &ci->uv_modality));
331*2ccfa855SEd Maste 	case 19: /* certifications */
332*2ccfa855SEd Maste 		return (decode_certs(val, &ci->certs));
333*2ccfa855SEd Maste 	case 20: /* remainingDiscoverableCredentials */
334*2ccfa855SEd Maste 		if (cbor_decode_uint64(val, &x) < 0 || x > INT64_MAX) {
335*2ccfa855SEd Maste 			fido_log_debug("%s: cbor_decode_uint64", __func__);
336*2ccfa855SEd Maste 			return (-1);
337*2ccfa855SEd Maste 		}
338*2ccfa855SEd Maste 		ci->rk_remaining = (int64_t)x;
339*2ccfa855SEd Maste 		return (0);
3400afa8e06SEd Maste 	default: /* ignore */
341*2ccfa855SEd Maste 		fido_log_debug("%s: cbor type: 0x%02x", __func__, cbor_get_uint8(key));
3420afa8e06SEd Maste 		return (0);
3430afa8e06SEd Maste 	}
3440afa8e06SEd Maste }
3450afa8e06SEd Maste 
3460afa8e06SEd Maste static int
fido_dev_get_cbor_info_tx(fido_dev_t * dev,int * ms)347f540a430SEd Maste fido_dev_get_cbor_info_tx(fido_dev_t *dev, int *ms)
3480afa8e06SEd Maste {
3490afa8e06SEd Maste 	const unsigned char cbor[] = { CTAP_CBOR_GETINFO };
3500afa8e06SEd Maste 
3510afa8e06SEd Maste 	fido_log_debug("%s: dev=%p", __func__, (void *)dev);
3520afa8e06SEd Maste 
353f540a430SEd Maste 	if (fido_tx(dev, CTAP_CMD_CBOR, cbor, sizeof(cbor), ms) < 0) {
3540afa8e06SEd Maste 		fido_log_debug("%s: fido_tx", __func__);
3550afa8e06SEd Maste 		return (FIDO_ERR_TX);
3560afa8e06SEd Maste 	}
3570afa8e06SEd Maste 
3580afa8e06SEd Maste 	return (FIDO_OK);
3590afa8e06SEd Maste }
3600afa8e06SEd Maste 
3610afa8e06SEd Maste static int
fido_dev_get_cbor_info_rx(fido_dev_t * dev,fido_cbor_info_t * ci,int * ms)362f540a430SEd Maste fido_dev_get_cbor_info_rx(fido_dev_t *dev, fido_cbor_info_t *ci, int *ms)
3630afa8e06SEd Maste {
364*2ccfa855SEd Maste 	unsigned char	*msg;
365*2ccfa855SEd Maste 	int		 msglen;
366*2ccfa855SEd Maste 	int		 r;
3670afa8e06SEd Maste 
3680afa8e06SEd Maste 	fido_log_debug("%s: dev=%p, ci=%p, ms=%d", __func__, (void *)dev,
369f540a430SEd Maste 	    (void *)ci, *ms);
3700afa8e06SEd Maste 
3710afa8e06SEd Maste 	fido_cbor_info_reset(ci);
3720afa8e06SEd Maste 
373*2ccfa855SEd Maste 	if ((msg = malloc(FIDO_MAXMSG)) == NULL) {
374*2ccfa855SEd Maste 		r = FIDO_ERR_INTERNAL;
375*2ccfa855SEd Maste 		goto out;
3760afa8e06SEd Maste 	}
3770afa8e06SEd Maste 
378*2ccfa855SEd Maste 	if ((msglen = fido_rx(dev, CTAP_CMD_CBOR, msg, FIDO_MAXMSG, ms)) < 0) {
379*2ccfa855SEd Maste 		fido_log_debug("%s: fido_rx", __func__);
380*2ccfa855SEd Maste 		r = FIDO_ERR_RX;
381*2ccfa855SEd Maste 		goto out;
382*2ccfa855SEd Maste 	}
383*2ccfa855SEd Maste 
384*2ccfa855SEd Maste 	r = cbor_parse_reply(msg, (size_t)msglen, ci, parse_reply_element);
385*2ccfa855SEd Maste out:
386*2ccfa855SEd Maste 	freezero(msg, FIDO_MAXMSG);
387*2ccfa855SEd Maste 
388*2ccfa855SEd Maste 	return (r);
3890afa8e06SEd Maste }
3900afa8e06SEd Maste 
3910afa8e06SEd Maste int
fido_dev_get_cbor_info_wait(fido_dev_t * dev,fido_cbor_info_t * ci,int * ms)392f540a430SEd Maste fido_dev_get_cbor_info_wait(fido_dev_t *dev, fido_cbor_info_t *ci, int *ms)
3930afa8e06SEd Maste {
3940afa8e06SEd Maste 	int r;
3950afa8e06SEd Maste 
3960afa8e06SEd Maste #ifdef USE_WINHELLO
3970afa8e06SEd Maste 	if (dev->flags & FIDO_DEV_WINHELLO)
3980afa8e06SEd Maste 		return (fido_winhello_get_cbor_info(dev, ci));
3990afa8e06SEd Maste #endif
400f540a430SEd Maste 	if ((r = fido_dev_get_cbor_info_tx(dev, ms)) != FIDO_OK ||
4010afa8e06SEd Maste 	    (r = fido_dev_get_cbor_info_rx(dev, ci, ms)) != FIDO_OK)
4020afa8e06SEd Maste 		return (r);
4030afa8e06SEd Maste 
4040afa8e06SEd Maste 	return (FIDO_OK);
4050afa8e06SEd Maste }
4060afa8e06SEd Maste 
4070afa8e06SEd Maste int
fido_dev_get_cbor_info(fido_dev_t * dev,fido_cbor_info_t * ci)4080afa8e06SEd Maste fido_dev_get_cbor_info(fido_dev_t *dev, fido_cbor_info_t *ci)
4090afa8e06SEd Maste {
410f540a430SEd Maste 	int ms = dev->timeout_ms;
411f540a430SEd Maste 
412f540a430SEd Maste 	return (fido_dev_get_cbor_info_wait(dev, ci, &ms));
4130afa8e06SEd Maste }
4140afa8e06SEd Maste 
4150afa8e06SEd Maste /*
4160afa8e06SEd Maste  * get/set functions for fido_cbor_info_t; always at the end of the file
4170afa8e06SEd Maste  */
4180afa8e06SEd Maste 
4190afa8e06SEd Maste fido_cbor_info_t *
fido_cbor_info_new(void)4200afa8e06SEd Maste fido_cbor_info_new(void)
4210afa8e06SEd Maste {
422*2ccfa855SEd Maste 	fido_cbor_info_t *ci;
423*2ccfa855SEd Maste 
424*2ccfa855SEd Maste 	if ((ci = calloc(1, sizeof(fido_cbor_info_t))) == NULL)
425*2ccfa855SEd Maste 		return (NULL);
426*2ccfa855SEd Maste 
427*2ccfa855SEd Maste 	fido_cbor_info_reset(ci);
428*2ccfa855SEd Maste 
429*2ccfa855SEd Maste 	return (ci);
4300afa8e06SEd Maste }
4310afa8e06SEd Maste 
4320afa8e06SEd Maste void
fido_cbor_info_reset(fido_cbor_info_t * ci)4330afa8e06SEd Maste fido_cbor_info_reset(fido_cbor_info_t *ci)
4340afa8e06SEd Maste {
435f540a430SEd Maste 	fido_str_array_free(&ci->versions);
436f540a430SEd Maste 	fido_str_array_free(&ci->extensions);
437f540a430SEd Maste 	fido_str_array_free(&ci->transports);
438f540a430SEd Maste 	fido_opt_array_free(&ci->options);
439f540a430SEd Maste 	fido_byte_array_free(&ci->protocols);
440f540a430SEd Maste 	fido_algo_array_free(&ci->algorithms);
441*2ccfa855SEd Maste 	fido_cert_array_free(&ci->certs);
442*2ccfa855SEd Maste 	ci->rk_remaining = -1;
4430afa8e06SEd Maste }
4440afa8e06SEd Maste 
4450afa8e06SEd Maste void
fido_cbor_info_free(fido_cbor_info_t ** ci_p)4460afa8e06SEd Maste fido_cbor_info_free(fido_cbor_info_t **ci_p)
4470afa8e06SEd Maste {
4480afa8e06SEd Maste 	fido_cbor_info_t *ci;
4490afa8e06SEd Maste 
4500afa8e06SEd Maste 	if (ci_p == NULL || (ci = *ci_p) ==  NULL)
4510afa8e06SEd Maste 		return;
4520afa8e06SEd Maste 	fido_cbor_info_reset(ci);
4530afa8e06SEd Maste 	free(ci);
4540afa8e06SEd Maste 	*ci_p = NULL;
4550afa8e06SEd Maste }
4560afa8e06SEd Maste 
4570afa8e06SEd Maste char **
fido_cbor_info_versions_ptr(const fido_cbor_info_t * ci)4580afa8e06SEd Maste fido_cbor_info_versions_ptr(const fido_cbor_info_t *ci)
4590afa8e06SEd Maste {
4600afa8e06SEd Maste 	return (ci->versions.ptr);
4610afa8e06SEd Maste }
4620afa8e06SEd Maste 
4630afa8e06SEd Maste size_t
fido_cbor_info_versions_len(const fido_cbor_info_t * ci)4640afa8e06SEd Maste fido_cbor_info_versions_len(const fido_cbor_info_t *ci)
4650afa8e06SEd Maste {
4660afa8e06SEd Maste 	return (ci->versions.len);
4670afa8e06SEd Maste }
4680afa8e06SEd Maste 
4690afa8e06SEd Maste char **
fido_cbor_info_extensions_ptr(const fido_cbor_info_t * ci)4700afa8e06SEd Maste fido_cbor_info_extensions_ptr(const fido_cbor_info_t *ci)
4710afa8e06SEd Maste {
4720afa8e06SEd Maste 	return (ci->extensions.ptr);
4730afa8e06SEd Maste }
4740afa8e06SEd Maste 
4750afa8e06SEd Maste size_t
fido_cbor_info_extensions_len(const fido_cbor_info_t * ci)4760afa8e06SEd Maste fido_cbor_info_extensions_len(const fido_cbor_info_t *ci)
4770afa8e06SEd Maste {
4780afa8e06SEd Maste 	return (ci->extensions.len);
4790afa8e06SEd Maste }
4800afa8e06SEd Maste 
4810afa8e06SEd Maste char **
fido_cbor_info_transports_ptr(const fido_cbor_info_t * ci)4820afa8e06SEd Maste fido_cbor_info_transports_ptr(const fido_cbor_info_t *ci)
4830afa8e06SEd Maste {
4840afa8e06SEd Maste 	return (ci->transports.ptr);
4850afa8e06SEd Maste }
4860afa8e06SEd Maste 
4870afa8e06SEd Maste size_t
fido_cbor_info_transports_len(const fido_cbor_info_t * ci)4880afa8e06SEd Maste fido_cbor_info_transports_len(const fido_cbor_info_t *ci)
4890afa8e06SEd Maste {
4900afa8e06SEd Maste 	return (ci->transports.len);
4910afa8e06SEd Maste }
4920afa8e06SEd Maste 
4930afa8e06SEd Maste const unsigned char *
fido_cbor_info_aaguid_ptr(const fido_cbor_info_t * ci)4940afa8e06SEd Maste fido_cbor_info_aaguid_ptr(const fido_cbor_info_t *ci)
4950afa8e06SEd Maste {
4960afa8e06SEd Maste 	return (ci->aaguid);
4970afa8e06SEd Maste }
4980afa8e06SEd Maste 
4990afa8e06SEd Maste size_t
fido_cbor_info_aaguid_len(const fido_cbor_info_t * ci)5000afa8e06SEd Maste fido_cbor_info_aaguid_len(const fido_cbor_info_t *ci)
5010afa8e06SEd Maste {
5020afa8e06SEd Maste 	return (sizeof(ci->aaguid));
5030afa8e06SEd Maste }
5040afa8e06SEd Maste 
5050afa8e06SEd Maste char **
fido_cbor_info_options_name_ptr(const fido_cbor_info_t * ci)5060afa8e06SEd Maste fido_cbor_info_options_name_ptr(const fido_cbor_info_t *ci)
5070afa8e06SEd Maste {
5080afa8e06SEd Maste 	return (ci->options.name);
5090afa8e06SEd Maste }
5100afa8e06SEd Maste 
5110afa8e06SEd Maste const bool *
fido_cbor_info_options_value_ptr(const fido_cbor_info_t * ci)5120afa8e06SEd Maste fido_cbor_info_options_value_ptr(const fido_cbor_info_t *ci)
5130afa8e06SEd Maste {
5140afa8e06SEd Maste 	return (ci->options.value);
5150afa8e06SEd Maste }
5160afa8e06SEd Maste 
5170afa8e06SEd Maste size_t
fido_cbor_info_options_len(const fido_cbor_info_t * ci)5180afa8e06SEd Maste fido_cbor_info_options_len(const fido_cbor_info_t *ci)
5190afa8e06SEd Maste {
5200afa8e06SEd Maste 	return (ci->options.len);
5210afa8e06SEd Maste }
5220afa8e06SEd Maste 
5230afa8e06SEd Maste uint64_t
fido_cbor_info_maxcredbloblen(const fido_cbor_info_t * ci)5240afa8e06SEd Maste fido_cbor_info_maxcredbloblen(const fido_cbor_info_t *ci)
5250afa8e06SEd Maste {
5260afa8e06SEd Maste 	return (ci->maxcredbloblen);
5270afa8e06SEd Maste }
5280afa8e06SEd Maste 
5290afa8e06SEd Maste uint64_t
fido_cbor_info_maxmsgsiz(const fido_cbor_info_t * ci)5300afa8e06SEd Maste fido_cbor_info_maxmsgsiz(const fido_cbor_info_t *ci)
5310afa8e06SEd Maste {
5320afa8e06SEd Maste 	return (ci->maxmsgsiz);
5330afa8e06SEd Maste }
5340afa8e06SEd Maste 
5350afa8e06SEd Maste uint64_t
fido_cbor_info_maxcredcntlst(const fido_cbor_info_t * ci)5360afa8e06SEd Maste fido_cbor_info_maxcredcntlst(const fido_cbor_info_t *ci)
5370afa8e06SEd Maste {
5380afa8e06SEd Maste 	return (ci->maxcredcntlst);
5390afa8e06SEd Maste }
5400afa8e06SEd Maste 
5410afa8e06SEd Maste uint64_t
fido_cbor_info_maxcredidlen(const fido_cbor_info_t * ci)5420afa8e06SEd Maste fido_cbor_info_maxcredidlen(const fido_cbor_info_t *ci)
5430afa8e06SEd Maste {
5440afa8e06SEd Maste 	return (ci->maxcredidlen);
5450afa8e06SEd Maste }
5460afa8e06SEd Maste 
5470afa8e06SEd Maste uint64_t
fido_cbor_info_maxlargeblob(const fido_cbor_info_t * ci)548*2ccfa855SEd Maste fido_cbor_info_maxlargeblob(const fido_cbor_info_t *ci)
549*2ccfa855SEd Maste {
550*2ccfa855SEd Maste 	return (ci->maxlargeblob);
551*2ccfa855SEd Maste }
552*2ccfa855SEd Maste 
553*2ccfa855SEd Maste uint64_t
fido_cbor_info_fwversion(const fido_cbor_info_t * ci)5540afa8e06SEd Maste fido_cbor_info_fwversion(const fido_cbor_info_t *ci)
5550afa8e06SEd Maste {
5560afa8e06SEd Maste 	return (ci->fwversion);
5570afa8e06SEd Maste }
5580afa8e06SEd Maste 
559*2ccfa855SEd Maste uint64_t
fido_cbor_info_minpinlen(const fido_cbor_info_t * ci)560*2ccfa855SEd Maste fido_cbor_info_minpinlen(const fido_cbor_info_t *ci)
561*2ccfa855SEd Maste {
562*2ccfa855SEd Maste 	return (ci->minpinlen);
563*2ccfa855SEd Maste }
564*2ccfa855SEd Maste 
565*2ccfa855SEd Maste uint64_t
fido_cbor_info_maxrpid_minpinlen(const fido_cbor_info_t * ci)566*2ccfa855SEd Maste fido_cbor_info_maxrpid_minpinlen(const fido_cbor_info_t *ci)
567*2ccfa855SEd Maste {
568*2ccfa855SEd Maste 	return (ci->maxrpid_minlen);
569*2ccfa855SEd Maste }
570*2ccfa855SEd Maste 
571*2ccfa855SEd Maste uint64_t
fido_cbor_info_uv_attempts(const fido_cbor_info_t * ci)572*2ccfa855SEd Maste fido_cbor_info_uv_attempts(const fido_cbor_info_t *ci)
573*2ccfa855SEd Maste {
574*2ccfa855SEd Maste 	return (ci->uv_attempts);
575*2ccfa855SEd Maste }
576*2ccfa855SEd Maste 
577*2ccfa855SEd Maste uint64_t
fido_cbor_info_uv_modality(const fido_cbor_info_t * ci)578*2ccfa855SEd Maste fido_cbor_info_uv_modality(const fido_cbor_info_t *ci)
579*2ccfa855SEd Maste {
580*2ccfa855SEd Maste 	return (ci->uv_modality);
581*2ccfa855SEd Maste }
582*2ccfa855SEd Maste 
583*2ccfa855SEd Maste int64_t
fido_cbor_info_rk_remaining(const fido_cbor_info_t * ci)584*2ccfa855SEd Maste fido_cbor_info_rk_remaining(const fido_cbor_info_t *ci)
585*2ccfa855SEd Maste {
586*2ccfa855SEd Maste 	return (ci->rk_remaining);
587*2ccfa855SEd Maste }
588*2ccfa855SEd Maste 
5890afa8e06SEd Maste const uint8_t *
fido_cbor_info_protocols_ptr(const fido_cbor_info_t * ci)5900afa8e06SEd Maste fido_cbor_info_protocols_ptr(const fido_cbor_info_t *ci)
5910afa8e06SEd Maste {
5920afa8e06SEd Maste 	return (ci->protocols.ptr);
5930afa8e06SEd Maste }
5940afa8e06SEd Maste 
5950afa8e06SEd Maste size_t
fido_cbor_info_protocols_len(const fido_cbor_info_t * ci)5960afa8e06SEd Maste fido_cbor_info_protocols_len(const fido_cbor_info_t *ci)
5970afa8e06SEd Maste {
5980afa8e06SEd Maste 	return (ci->protocols.len);
5990afa8e06SEd Maste }
6000afa8e06SEd Maste 
6010afa8e06SEd Maste size_t
fido_cbor_info_algorithm_count(const fido_cbor_info_t * ci)6020afa8e06SEd Maste fido_cbor_info_algorithm_count(const fido_cbor_info_t *ci)
6030afa8e06SEd Maste {
6040afa8e06SEd Maste 	return (ci->algorithms.len);
6050afa8e06SEd Maste }
6060afa8e06SEd Maste 
6070afa8e06SEd Maste const char *
fido_cbor_info_algorithm_type(const fido_cbor_info_t * ci,size_t idx)6080afa8e06SEd Maste fido_cbor_info_algorithm_type(const fido_cbor_info_t *ci, size_t idx)
6090afa8e06SEd Maste {
6100afa8e06SEd Maste 	if (idx >= ci->algorithms.len)
6110afa8e06SEd Maste 		return (NULL);
6120afa8e06SEd Maste 
6130afa8e06SEd Maste 	return (ci->algorithms.ptr[idx].type);
6140afa8e06SEd Maste }
6150afa8e06SEd Maste 
6160afa8e06SEd Maste int
fido_cbor_info_algorithm_cose(const fido_cbor_info_t * ci,size_t idx)6170afa8e06SEd Maste fido_cbor_info_algorithm_cose(const fido_cbor_info_t *ci, size_t idx)
6180afa8e06SEd Maste {
6190afa8e06SEd Maste 	if (idx >= ci->algorithms.len)
6200afa8e06SEd Maste 		return (0);
6210afa8e06SEd Maste 
6220afa8e06SEd Maste 	return (ci->algorithms.ptr[idx].cose);
6230afa8e06SEd Maste }
624*2ccfa855SEd Maste 
625*2ccfa855SEd Maste bool
fido_cbor_info_new_pin_required(const fido_cbor_info_t * ci)626*2ccfa855SEd Maste fido_cbor_info_new_pin_required(const fido_cbor_info_t *ci)
627*2ccfa855SEd Maste {
628*2ccfa855SEd Maste 	return (ci->new_pin_reqd);
629*2ccfa855SEd Maste }
630*2ccfa855SEd Maste 
631*2ccfa855SEd Maste char **
fido_cbor_info_certs_name_ptr(const fido_cbor_info_t * ci)632*2ccfa855SEd Maste fido_cbor_info_certs_name_ptr(const fido_cbor_info_t *ci)
633*2ccfa855SEd Maste {
634*2ccfa855SEd Maste 	return (ci->certs.name);
635*2ccfa855SEd Maste }
636*2ccfa855SEd Maste 
637*2ccfa855SEd Maste const uint64_t *
fido_cbor_info_certs_value_ptr(const fido_cbor_info_t * ci)638*2ccfa855SEd Maste fido_cbor_info_certs_value_ptr(const fido_cbor_info_t *ci)
639*2ccfa855SEd Maste {
640*2ccfa855SEd Maste 	return (ci->certs.value);
641*2ccfa855SEd Maste }
642*2ccfa855SEd Maste 
643*2ccfa855SEd Maste size_t
fido_cbor_info_certs_len(const fido_cbor_info_t * ci)644*2ccfa855SEd Maste fido_cbor_info_certs_len(const fido_cbor_info_t *ci)
645*2ccfa855SEd Maste {
646*2ccfa855SEd Maste 	return (ci->certs.len);
647*2ccfa855SEd Maste }
648