xref: /freebsd/contrib/libfido2/src/info.c (revision 0afa8e06)
1*0afa8e06SEd Maste /*
2*0afa8e06SEd Maste  * Copyright (c) 2018-2021 Yubico AB. All rights reserved.
3*0afa8e06SEd Maste  * Use of this source code is governed by a BSD-style
4*0afa8e06SEd Maste  * license that can be found in the LICENSE file.
5*0afa8e06SEd Maste  */
6*0afa8e06SEd Maste 
7*0afa8e06SEd Maste #include "fido.h"
8*0afa8e06SEd Maste 
9*0afa8e06SEd Maste static int
10*0afa8e06SEd Maste decode_string(const cbor_item_t *item, void *arg)
11*0afa8e06SEd Maste {
12*0afa8e06SEd Maste 	fido_str_array_t	*a = arg;
13*0afa8e06SEd Maste 	const size_t		 i = a->len;
14*0afa8e06SEd Maste 
15*0afa8e06SEd Maste 	/* keep ptr[x] and len consistent */
16*0afa8e06SEd Maste 	if (cbor_string_copy(item, &a->ptr[i]) < 0) {
17*0afa8e06SEd Maste 		fido_log_debug("%s: cbor_string_copy", __func__);
18*0afa8e06SEd Maste 		return (-1);
19*0afa8e06SEd Maste 	}
20*0afa8e06SEd Maste 
21*0afa8e06SEd Maste 	a->len++;
22*0afa8e06SEd Maste 
23*0afa8e06SEd Maste 	return (0);
24*0afa8e06SEd Maste }
25*0afa8e06SEd Maste 
26*0afa8e06SEd Maste static int
27*0afa8e06SEd Maste decode_string_array(const cbor_item_t *item, fido_str_array_t *v)
28*0afa8e06SEd Maste {
29*0afa8e06SEd Maste 	v->ptr = NULL;
30*0afa8e06SEd Maste 	v->len = 0;
31*0afa8e06SEd Maste 
32*0afa8e06SEd Maste 	if (cbor_isa_array(item) == false ||
33*0afa8e06SEd Maste 	    cbor_array_is_definite(item) == false) {
34*0afa8e06SEd Maste 		fido_log_debug("%s: cbor type", __func__);
35*0afa8e06SEd Maste 		return (-1);
36*0afa8e06SEd Maste 	}
37*0afa8e06SEd Maste 
38*0afa8e06SEd Maste 	v->ptr = calloc(cbor_array_size(item), sizeof(char *));
39*0afa8e06SEd Maste 	if (v->ptr == NULL)
40*0afa8e06SEd Maste 		return (-1);
41*0afa8e06SEd Maste 
42*0afa8e06SEd Maste 	if (cbor_array_iter(item, v, decode_string) < 0) {
43*0afa8e06SEd Maste 		fido_log_debug("%s: decode_string", __func__);
44*0afa8e06SEd Maste 		return (-1);
45*0afa8e06SEd Maste 	}
46*0afa8e06SEd Maste 
47*0afa8e06SEd Maste 	return (0);
48*0afa8e06SEd Maste }
49*0afa8e06SEd Maste 
50*0afa8e06SEd Maste static int
51*0afa8e06SEd Maste decode_aaguid(const cbor_item_t *item, unsigned char *aaguid, size_t aaguid_len)
52*0afa8e06SEd Maste {
53*0afa8e06SEd Maste 	if (cbor_isa_bytestring(item) == false ||
54*0afa8e06SEd Maste 	    cbor_bytestring_is_definite(item) == false ||
55*0afa8e06SEd Maste 	    cbor_bytestring_length(item) != aaguid_len) {
56*0afa8e06SEd Maste 		fido_log_debug("%s: cbor type", __func__);
57*0afa8e06SEd Maste 		return (-1);
58*0afa8e06SEd Maste 	}
59*0afa8e06SEd Maste 
60*0afa8e06SEd Maste 	memcpy(aaguid, cbor_bytestring_handle(item), aaguid_len);
61*0afa8e06SEd Maste 
62*0afa8e06SEd Maste 	return (0);
63*0afa8e06SEd Maste }
64*0afa8e06SEd Maste 
65*0afa8e06SEd Maste static int
66*0afa8e06SEd Maste decode_option(const cbor_item_t *key, const cbor_item_t *val, void *arg)
67*0afa8e06SEd Maste {
68*0afa8e06SEd Maste 	fido_opt_array_t	*o = arg;
69*0afa8e06SEd Maste 	const size_t		 i = o->len;
70*0afa8e06SEd Maste 
71*0afa8e06SEd Maste 	if (cbor_isa_float_ctrl(val) == false ||
72*0afa8e06SEd Maste 	    cbor_float_get_width(val) != CBOR_FLOAT_0 ||
73*0afa8e06SEd Maste 	    cbor_is_bool(val) == false) {
74*0afa8e06SEd Maste 		fido_log_debug("%s: cbor type", __func__);
75*0afa8e06SEd Maste 		return (0); /* ignore */
76*0afa8e06SEd Maste 	}
77*0afa8e06SEd Maste 
78*0afa8e06SEd Maste 	if (cbor_string_copy(key, &o->name[i]) < 0) {
79*0afa8e06SEd Maste 		fido_log_debug("%s: cbor_string_copy", __func__);
80*0afa8e06SEd Maste 		return (0); /* ignore */
81*0afa8e06SEd Maste 	}
82*0afa8e06SEd Maste 
83*0afa8e06SEd Maste 	/* keep name/value and len consistent */
84*0afa8e06SEd Maste 	o->value[i] = cbor_ctrl_value(val) == CBOR_CTRL_TRUE;
85*0afa8e06SEd Maste 	o->len++;
86*0afa8e06SEd Maste 
87*0afa8e06SEd Maste 	return (0);
88*0afa8e06SEd Maste }
89*0afa8e06SEd Maste 
90*0afa8e06SEd Maste static int
91*0afa8e06SEd Maste decode_options(const cbor_item_t *item, fido_opt_array_t *o)
92*0afa8e06SEd Maste {
93*0afa8e06SEd Maste 	o->name = NULL;
94*0afa8e06SEd Maste 	o->value = NULL;
95*0afa8e06SEd Maste 	o->len = 0;
96*0afa8e06SEd Maste 
97*0afa8e06SEd Maste 	if (cbor_isa_map(item) == false ||
98*0afa8e06SEd Maste 	    cbor_map_is_definite(item) == false) {
99*0afa8e06SEd Maste 		fido_log_debug("%s: cbor type", __func__);
100*0afa8e06SEd Maste 		return (-1);
101*0afa8e06SEd Maste 	}
102*0afa8e06SEd Maste 
103*0afa8e06SEd Maste 	o->name = calloc(cbor_map_size(item), sizeof(char *));
104*0afa8e06SEd Maste 	o->value = calloc(cbor_map_size(item), sizeof(bool));
105*0afa8e06SEd Maste 	if (o->name == NULL || o->value == NULL)
106*0afa8e06SEd Maste 		return (-1);
107*0afa8e06SEd Maste 
108*0afa8e06SEd Maste 	return (cbor_map_iter(item, o, decode_option));
109*0afa8e06SEd Maste }
110*0afa8e06SEd Maste 
111*0afa8e06SEd Maste static int
112*0afa8e06SEd Maste decode_protocol(const cbor_item_t *item, void *arg)
113*0afa8e06SEd Maste {
114*0afa8e06SEd Maste 	fido_byte_array_t	*p = arg;
115*0afa8e06SEd Maste 	const size_t		 i = p->len;
116*0afa8e06SEd Maste 
117*0afa8e06SEd Maste 	if (cbor_isa_uint(item) == false ||
118*0afa8e06SEd Maste 	    cbor_int_get_width(item) != CBOR_INT_8) {
119*0afa8e06SEd Maste 		fido_log_debug("%s: cbor type", __func__);
120*0afa8e06SEd Maste 		return (-1);
121*0afa8e06SEd Maste 	}
122*0afa8e06SEd Maste 
123*0afa8e06SEd Maste 	/* keep ptr[x] and len consistent */
124*0afa8e06SEd Maste 	p->ptr[i] = cbor_get_uint8(item);
125*0afa8e06SEd Maste 	p->len++;
126*0afa8e06SEd Maste 
127*0afa8e06SEd Maste 	return (0);
128*0afa8e06SEd Maste }
129*0afa8e06SEd Maste 
130*0afa8e06SEd Maste static int
131*0afa8e06SEd Maste decode_protocols(const cbor_item_t *item, fido_byte_array_t *p)
132*0afa8e06SEd Maste {
133*0afa8e06SEd Maste 	p->ptr = NULL;
134*0afa8e06SEd Maste 	p->len = 0;
135*0afa8e06SEd Maste 
136*0afa8e06SEd Maste 	if (cbor_isa_array(item) == false ||
137*0afa8e06SEd Maste 	    cbor_array_is_definite(item) == false) {
138*0afa8e06SEd Maste 		fido_log_debug("%s: cbor type", __func__);
139*0afa8e06SEd Maste 		return (-1);
140*0afa8e06SEd Maste 	}
141*0afa8e06SEd Maste 
142*0afa8e06SEd Maste 	p->ptr = calloc(cbor_array_size(item), sizeof(uint8_t));
143*0afa8e06SEd Maste 	if (p->ptr == NULL)
144*0afa8e06SEd Maste 		return (-1);
145*0afa8e06SEd Maste 
146*0afa8e06SEd Maste 	if (cbor_array_iter(item, p, decode_protocol) < 0) {
147*0afa8e06SEd Maste 		fido_log_debug("%s: decode_protocol", __func__);
148*0afa8e06SEd Maste 		return (-1);
149*0afa8e06SEd Maste 	}
150*0afa8e06SEd Maste 
151*0afa8e06SEd Maste 	return (0);
152*0afa8e06SEd Maste }
153*0afa8e06SEd Maste 
154*0afa8e06SEd Maste static int
155*0afa8e06SEd Maste decode_algorithm_entry(const cbor_item_t *key, const cbor_item_t *val,
156*0afa8e06SEd Maste     void *arg)
157*0afa8e06SEd Maste {
158*0afa8e06SEd Maste 	fido_algo_t *alg = arg;
159*0afa8e06SEd Maste 	char *name = NULL;
160*0afa8e06SEd Maste 	int ok = -1;
161*0afa8e06SEd Maste 
162*0afa8e06SEd Maste 	if (cbor_string_copy(key, &name) < 0) {
163*0afa8e06SEd Maste 		fido_log_debug("%s: cbor type", __func__);
164*0afa8e06SEd Maste 		ok = 0; /* ignore */
165*0afa8e06SEd Maste 		goto out;
166*0afa8e06SEd Maste 	}
167*0afa8e06SEd Maste 
168*0afa8e06SEd Maste 	if (!strcmp(name, "alg")) {
169*0afa8e06SEd Maste 		if (cbor_isa_negint(val) == false ||
170*0afa8e06SEd Maste 		    cbor_get_int(val) > INT_MAX || alg->cose != 0) {
171*0afa8e06SEd Maste 			fido_log_debug("%s: alg", __func__);
172*0afa8e06SEd Maste 			goto out;
173*0afa8e06SEd Maste 		}
174*0afa8e06SEd Maste 		alg->cose = -(int)cbor_get_int(val) - 1;
175*0afa8e06SEd Maste 	} else if (!strcmp(name, "type")) {
176*0afa8e06SEd Maste 		if (cbor_string_copy(val, &alg->type) < 0) {
177*0afa8e06SEd Maste 			fido_log_debug("%s: type", __func__);
178*0afa8e06SEd Maste 			goto out;
179*0afa8e06SEd Maste 		}
180*0afa8e06SEd Maste 	}
181*0afa8e06SEd Maste 
182*0afa8e06SEd Maste 	ok = 0;
183*0afa8e06SEd Maste out:
184*0afa8e06SEd Maste 	free(name);
185*0afa8e06SEd Maste 
186*0afa8e06SEd Maste 	return (ok);
187*0afa8e06SEd Maste }
188*0afa8e06SEd Maste 
189*0afa8e06SEd Maste static void
190*0afa8e06SEd Maste free_algo(fido_algo_t *a)
191*0afa8e06SEd Maste {
192*0afa8e06SEd Maste 	free(a->type);
193*0afa8e06SEd Maste 	a->type = NULL;
194*0afa8e06SEd Maste 	a->cose = 0;
195*0afa8e06SEd Maste }
196*0afa8e06SEd Maste 
197*0afa8e06SEd Maste static int
198*0afa8e06SEd Maste decode_algorithm(const cbor_item_t *item, void *arg)
199*0afa8e06SEd Maste {
200*0afa8e06SEd Maste 	fido_algo_array_t *aa = arg;
201*0afa8e06SEd Maste 	const size_t i = aa->len;
202*0afa8e06SEd Maste 
203*0afa8e06SEd Maste 	if (cbor_isa_map(item) == false ||
204*0afa8e06SEd Maste 	    cbor_map_is_definite(item) == false) {
205*0afa8e06SEd Maste 		fido_log_debug("%s: cbor type", __func__);
206*0afa8e06SEd Maste 		return (-1);
207*0afa8e06SEd Maste 	}
208*0afa8e06SEd Maste 
209*0afa8e06SEd Maste 	memset(&aa->ptr[i], 0, sizeof(aa->ptr[i]));
210*0afa8e06SEd Maste 
211*0afa8e06SEd Maste 	if (cbor_map_iter(item, &aa->ptr[i], decode_algorithm_entry) < 0) {
212*0afa8e06SEd Maste 		fido_log_debug("%s: decode_algorithm_entry", __func__);
213*0afa8e06SEd Maste 		free_algo(&aa->ptr[i]);
214*0afa8e06SEd Maste 		return (-1);
215*0afa8e06SEd Maste 	}
216*0afa8e06SEd Maste 
217*0afa8e06SEd Maste 	/* keep ptr[x] and len consistent */
218*0afa8e06SEd Maste 	aa->len++;
219*0afa8e06SEd Maste 
220*0afa8e06SEd Maste 	return (0);
221*0afa8e06SEd Maste }
222*0afa8e06SEd Maste 
223*0afa8e06SEd Maste static int
224*0afa8e06SEd Maste decode_algorithms(const cbor_item_t *item, fido_algo_array_t *aa)
225*0afa8e06SEd Maste {
226*0afa8e06SEd Maste 	aa->ptr = NULL;
227*0afa8e06SEd Maste 	aa->len = 0;
228*0afa8e06SEd Maste 
229*0afa8e06SEd Maste 	if (cbor_isa_array(item) == false ||
230*0afa8e06SEd Maste 	    cbor_array_is_definite(item) == false) {
231*0afa8e06SEd Maste 		fido_log_debug("%s: cbor type", __func__);
232*0afa8e06SEd Maste 		return (-1);
233*0afa8e06SEd Maste 	}
234*0afa8e06SEd Maste 
235*0afa8e06SEd Maste 	aa->ptr = calloc(cbor_array_size(item), sizeof(fido_algo_t));
236*0afa8e06SEd Maste 	if (aa->ptr == NULL)
237*0afa8e06SEd Maste 		return (-1);
238*0afa8e06SEd Maste 
239*0afa8e06SEd Maste 	if (cbor_array_iter(item, aa, decode_algorithm) < 0) {
240*0afa8e06SEd Maste 		fido_log_debug("%s: decode_algorithm", __func__);
241*0afa8e06SEd Maste 		return (-1);
242*0afa8e06SEd Maste 	}
243*0afa8e06SEd Maste 
244*0afa8e06SEd Maste 	return (0);
245*0afa8e06SEd Maste }
246*0afa8e06SEd Maste 
247*0afa8e06SEd Maste static int
248*0afa8e06SEd Maste parse_reply_element(const cbor_item_t *key, const cbor_item_t *val, void *arg)
249*0afa8e06SEd Maste {
250*0afa8e06SEd Maste 	fido_cbor_info_t *ci = arg;
251*0afa8e06SEd Maste 
252*0afa8e06SEd Maste 	if (cbor_isa_uint(key) == false ||
253*0afa8e06SEd Maste 	    cbor_int_get_width(key) != CBOR_INT_8) {
254*0afa8e06SEd Maste 		fido_log_debug("%s: cbor type", __func__);
255*0afa8e06SEd Maste 		return (0); /* ignore */
256*0afa8e06SEd Maste 	}
257*0afa8e06SEd Maste 
258*0afa8e06SEd Maste 	switch (cbor_get_uint8(key)) {
259*0afa8e06SEd Maste 	case 1: /* versions */
260*0afa8e06SEd Maste 		return (decode_string_array(val, &ci->versions));
261*0afa8e06SEd Maste 	case 2: /* extensions */
262*0afa8e06SEd Maste 		return (decode_string_array(val, &ci->extensions));
263*0afa8e06SEd Maste 	case 3: /* aaguid */
264*0afa8e06SEd Maste 		return (decode_aaguid(val, ci->aaguid, sizeof(ci->aaguid)));
265*0afa8e06SEd Maste 	case 4: /* options */
266*0afa8e06SEd Maste 		return (decode_options(val, &ci->options));
267*0afa8e06SEd Maste 	case 5: /* maxMsgSize */
268*0afa8e06SEd Maste 		return (cbor_decode_uint64(val, &ci->maxmsgsiz));
269*0afa8e06SEd Maste 	case 6: /* pinProtocols */
270*0afa8e06SEd Maste 		return (decode_protocols(val, &ci->protocols));
271*0afa8e06SEd Maste 	case 7: /* maxCredentialCountInList */
272*0afa8e06SEd Maste 		return (cbor_decode_uint64(val, &ci->maxcredcntlst));
273*0afa8e06SEd Maste 	case 8: /* maxCredentialIdLength */
274*0afa8e06SEd Maste 		return (cbor_decode_uint64(val, &ci->maxcredidlen));
275*0afa8e06SEd Maste 	case 9: /* transports */
276*0afa8e06SEd Maste 		return (decode_string_array(val, &ci->transports));
277*0afa8e06SEd Maste 	case 10: /* algorithms */
278*0afa8e06SEd Maste 		return (decode_algorithms(val, &ci->algorithms));
279*0afa8e06SEd Maste 	case 14: /* fwVersion */
280*0afa8e06SEd Maste 		return (cbor_decode_uint64(val, &ci->fwversion));
281*0afa8e06SEd Maste 	case 15: /* maxCredBlobLen */
282*0afa8e06SEd Maste 		return (cbor_decode_uint64(val, &ci->maxcredbloblen));
283*0afa8e06SEd Maste 	default: /* ignore */
284*0afa8e06SEd Maste 		fido_log_debug("%s: cbor type", __func__);
285*0afa8e06SEd Maste 		return (0);
286*0afa8e06SEd Maste 	}
287*0afa8e06SEd Maste }
288*0afa8e06SEd Maste 
289*0afa8e06SEd Maste static int
290*0afa8e06SEd Maste fido_dev_get_cbor_info_tx(fido_dev_t *dev)
291*0afa8e06SEd Maste {
292*0afa8e06SEd Maste 	const unsigned char cbor[] = { CTAP_CBOR_GETINFO };
293*0afa8e06SEd Maste 
294*0afa8e06SEd Maste 	fido_log_debug("%s: dev=%p", __func__, (void *)dev);
295*0afa8e06SEd Maste 
296*0afa8e06SEd Maste 	if (fido_tx(dev, CTAP_CMD_CBOR, cbor, sizeof(cbor)) < 0) {
297*0afa8e06SEd Maste 		fido_log_debug("%s: fido_tx", __func__);
298*0afa8e06SEd Maste 		return (FIDO_ERR_TX);
299*0afa8e06SEd Maste 	}
300*0afa8e06SEd Maste 
301*0afa8e06SEd Maste 	return (FIDO_OK);
302*0afa8e06SEd Maste }
303*0afa8e06SEd Maste 
304*0afa8e06SEd Maste static int
305*0afa8e06SEd Maste fido_dev_get_cbor_info_rx(fido_dev_t *dev, fido_cbor_info_t *ci, int ms)
306*0afa8e06SEd Maste {
307*0afa8e06SEd Maste 	unsigned char	reply[FIDO_MAXMSG];
308*0afa8e06SEd Maste 	int		reply_len;
309*0afa8e06SEd Maste 
310*0afa8e06SEd Maste 	fido_log_debug("%s: dev=%p, ci=%p, ms=%d", __func__, (void *)dev,
311*0afa8e06SEd Maste 	    (void *)ci, ms);
312*0afa8e06SEd Maste 
313*0afa8e06SEd Maste 	fido_cbor_info_reset(ci);
314*0afa8e06SEd Maste 
315*0afa8e06SEd Maste 	if ((reply_len = fido_rx(dev, CTAP_CMD_CBOR, &reply, sizeof(reply),
316*0afa8e06SEd Maste 	    ms)) < 0) {
317*0afa8e06SEd Maste 		fido_log_debug("%s: fido_rx", __func__);
318*0afa8e06SEd Maste 		return (FIDO_ERR_RX);
319*0afa8e06SEd Maste 	}
320*0afa8e06SEd Maste 
321*0afa8e06SEd Maste 	return (cbor_parse_reply(reply, (size_t)reply_len, ci,
322*0afa8e06SEd Maste 	    parse_reply_element));
323*0afa8e06SEd Maste }
324*0afa8e06SEd Maste 
325*0afa8e06SEd Maste int
326*0afa8e06SEd Maste fido_dev_get_cbor_info_wait(fido_dev_t *dev, fido_cbor_info_t *ci, int ms)
327*0afa8e06SEd Maste {
328*0afa8e06SEd Maste 	int r;
329*0afa8e06SEd Maste 
330*0afa8e06SEd Maste #ifdef USE_WINHELLO
331*0afa8e06SEd Maste 	if (dev->flags & FIDO_DEV_WINHELLO)
332*0afa8e06SEd Maste 		return (fido_winhello_get_cbor_info(dev, ci));
333*0afa8e06SEd Maste #endif
334*0afa8e06SEd Maste 	if ((r = fido_dev_get_cbor_info_tx(dev)) != FIDO_OK ||
335*0afa8e06SEd Maste 	    (r = fido_dev_get_cbor_info_rx(dev, ci, ms)) != FIDO_OK)
336*0afa8e06SEd Maste 		return (r);
337*0afa8e06SEd Maste 
338*0afa8e06SEd Maste 	return (FIDO_OK);
339*0afa8e06SEd Maste }
340*0afa8e06SEd Maste 
341*0afa8e06SEd Maste int
342*0afa8e06SEd Maste fido_dev_get_cbor_info(fido_dev_t *dev, fido_cbor_info_t *ci)
343*0afa8e06SEd Maste {
344*0afa8e06SEd Maste 	return (fido_dev_get_cbor_info_wait(dev, ci, -1));
345*0afa8e06SEd Maste }
346*0afa8e06SEd Maste 
347*0afa8e06SEd Maste /*
348*0afa8e06SEd Maste  * get/set functions for fido_cbor_info_t; always at the end of the file
349*0afa8e06SEd Maste  */
350*0afa8e06SEd Maste 
351*0afa8e06SEd Maste fido_cbor_info_t *
352*0afa8e06SEd Maste fido_cbor_info_new(void)
353*0afa8e06SEd Maste {
354*0afa8e06SEd Maste 	return (calloc(1, sizeof(fido_cbor_info_t)));
355*0afa8e06SEd Maste }
356*0afa8e06SEd Maste 
357*0afa8e06SEd Maste static void
358*0afa8e06SEd Maste free_str_array(fido_str_array_t *sa)
359*0afa8e06SEd Maste {
360*0afa8e06SEd Maste 	for (size_t i = 0; i < sa->len; i++)
361*0afa8e06SEd Maste 		free(sa->ptr[i]);
362*0afa8e06SEd Maste 
363*0afa8e06SEd Maste 	free(sa->ptr);
364*0afa8e06SEd Maste 	sa->ptr = NULL;
365*0afa8e06SEd Maste 	sa->len = 0;
366*0afa8e06SEd Maste }
367*0afa8e06SEd Maste 
368*0afa8e06SEd Maste static void
369*0afa8e06SEd Maste free_opt_array(fido_opt_array_t *oa)
370*0afa8e06SEd Maste {
371*0afa8e06SEd Maste 	for (size_t i = 0; i < oa->len; i++)
372*0afa8e06SEd Maste 		free(oa->name[i]);
373*0afa8e06SEd Maste 
374*0afa8e06SEd Maste 	free(oa->name);
375*0afa8e06SEd Maste 	free(oa->value);
376*0afa8e06SEd Maste 	oa->name = NULL;
377*0afa8e06SEd Maste 	oa->value = NULL;
378*0afa8e06SEd Maste }
379*0afa8e06SEd Maste 
380*0afa8e06SEd Maste static void
381*0afa8e06SEd Maste free_byte_array(fido_byte_array_t *ba)
382*0afa8e06SEd Maste {
383*0afa8e06SEd Maste 	free(ba->ptr);
384*0afa8e06SEd Maste 
385*0afa8e06SEd Maste 	ba->ptr = NULL;
386*0afa8e06SEd Maste 	ba->len = 0;
387*0afa8e06SEd Maste }
388*0afa8e06SEd Maste 
389*0afa8e06SEd Maste static void
390*0afa8e06SEd Maste free_algo_array(fido_algo_array_t *aa)
391*0afa8e06SEd Maste {
392*0afa8e06SEd Maste 	for (size_t i = 0; i < aa->len; i++)
393*0afa8e06SEd Maste 		free_algo(&aa->ptr[i]);
394*0afa8e06SEd Maste 
395*0afa8e06SEd Maste 	free(aa->ptr);
396*0afa8e06SEd Maste 	aa->ptr = NULL;
397*0afa8e06SEd Maste 	aa->len = 0;
398*0afa8e06SEd Maste }
399*0afa8e06SEd Maste 
400*0afa8e06SEd Maste void
401*0afa8e06SEd Maste fido_cbor_info_reset(fido_cbor_info_t *ci)
402*0afa8e06SEd Maste {
403*0afa8e06SEd Maste 	free_str_array(&ci->versions);
404*0afa8e06SEd Maste 	free_str_array(&ci->extensions);
405*0afa8e06SEd Maste 	free_str_array(&ci->transports);
406*0afa8e06SEd Maste 	free_opt_array(&ci->options);
407*0afa8e06SEd Maste 	free_byte_array(&ci->protocols);
408*0afa8e06SEd Maste 	free_algo_array(&ci->algorithms);
409*0afa8e06SEd Maste }
410*0afa8e06SEd Maste 
411*0afa8e06SEd Maste void
412*0afa8e06SEd Maste fido_cbor_info_free(fido_cbor_info_t **ci_p)
413*0afa8e06SEd Maste {
414*0afa8e06SEd Maste 	fido_cbor_info_t *ci;
415*0afa8e06SEd Maste 
416*0afa8e06SEd Maste 	if (ci_p == NULL || (ci = *ci_p) ==  NULL)
417*0afa8e06SEd Maste 		return;
418*0afa8e06SEd Maste 	fido_cbor_info_reset(ci);
419*0afa8e06SEd Maste 	free(ci);
420*0afa8e06SEd Maste 	*ci_p = NULL;
421*0afa8e06SEd Maste }
422*0afa8e06SEd Maste 
423*0afa8e06SEd Maste char **
424*0afa8e06SEd Maste fido_cbor_info_versions_ptr(const fido_cbor_info_t *ci)
425*0afa8e06SEd Maste {
426*0afa8e06SEd Maste 	return (ci->versions.ptr);
427*0afa8e06SEd Maste }
428*0afa8e06SEd Maste 
429*0afa8e06SEd Maste size_t
430*0afa8e06SEd Maste fido_cbor_info_versions_len(const fido_cbor_info_t *ci)
431*0afa8e06SEd Maste {
432*0afa8e06SEd Maste 	return (ci->versions.len);
433*0afa8e06SEd Maste }
434*0afa8e06SEd Maste 
435*0afa8e06SEd Maste char **
436*0afa8e06SEd Maste fido_cbor_info_extensions_ptr(const fido_cbor_info_t *ci)
437*0afa8e06SEd Maste {
438*0afa8e06SEd Maste 	return (ci->extensions.ptr);
439*0afa8e06SEd Maste }
440*0afa8e06SEd Maste 
441*0afa8e06SEd Maste size_t
442*0afa8e06SEd Maste fido_cbor_info_extensions_len(const fido_cbor_info_t *ci)
443*0afa8e06SEd Maste {
444*0afa8e06SEd Maste 	return (ci->extensions.len);
445*0afa8e06SEd Maste }
446*0afa8e06SEd Maste 
447*0afa8e06SEd Maste char **
448*0afa8e06SEd Maste fido_cbor_info_transports_ptr(const fido_cbor_info_t *ci)
449*0afa8e06SEd Maste {
450*0afa8e06SEd Maste 	return (ci->transports.ptr);
451*0afa8e06SEd Maste }
452*0afa8e06SEd Maste 
453*0afa8e06SEd Maste size_t
454*0afa8e06SEd Maste fido_cbor_info_transports_len(const fido_cbor_info_t *ci)
455*0afa8e06SEd Maste {
456*0afa8e06SEd Maste 	return (ci->transports.len);
457*0afa8e06SEd Maste }
458*0afa8e06SEd Maste 
459*0afa8e06SEd Maste const unsigned char *
460*0afa8e06SEd Maste fido_cbor_info_aaguid_ptr(const fido_cbor_info_t *ci)
461*0afa8e06SEd Maste {
462*0afa8e06SEd Maste 	return (ci->aaguid);
463*0afa8e06SEd Maste }
464*0afa8e06SEd Maste 
465*0afa8e06SEd Maste size_t
466*0afa8e06SEd Maste fido_cbor_info_aaguid_len(const fido_cbor_info_t *ci)
467*0afa8e06SEd Maste {
468*0afa8e06SEd Maste 	return (sizeof(ci->aaguid));
469*0afa8e06SEd Maste }
470*0afa8e06SEd Maste 
471*0afa8e06SEd Maste char **
472*0afa8e06SEd Maste fido_cbor_info_options_name_ptr(const fido_cbor_info_t *ci)
473*0afa8e06SEd Maste {
474*0afa8e06SEd Maste 	return (ci->options.name);
475*0afa8e06SEd Maste }
476*0afa8e06SEd Maste 
477*0afa8e06SEd Maste const bool *
478*0afa8e06SEd Maste fido_cbor_info_options_value_ptr(const fido_cbor_info_t *ci)
479*0afa8e06SEd Maste {
480*0afa8e06SEd Maste 	return (ci->options.value);
481*0afa8e06SEd Maste }
482*0afa8e06SEd Maste 
483*0afa8e06SEd Maste size_t
484*0afa8e06SEd Maste fido_cbor_info_options_len(const fido_cbor_info_t *ci)
485*0afa8e06SEd Maste {
486*0afa8e06SEd Maste 	return (ci->options.len);
487*0afa8e06SEd Maste }
488*0afa8e06SEd Maste 
489*0afa8e06SEd Maste uint64_t
490*0afa8e06SEd Maste fido_cbor_info_maxcredbloblen(const fido_cbor_info_t *ci)
491*0afa8e06SEd Maste {
492*0afa8e06SEd Maste 	return (ci->maxcredbloblen);
493*0afa8e06SEd Maste }
494*0afa8e06SEd Maste 
495*0afa8e06SEd Maste uint64_t
496*0afa8e06SEd Maste fido_cbor_info_maxmsgsiz(const fido_cbor_info_t *ci)
497*0afa8e06SEd Maste {
498*0afa8e06SEd Maste 	return (ci->maxmsgsiz);
499*0afa8e06SEd Maste }
500*0afa8e06SEd Maste 
501*0afa8e06SEd Maste uint64_t
502*0afa8e06SEd Maste fido_cbor_info_maxcredcntlst(const fido_cbor_info_t *ci)
503*0afa8e06SEd Maste {
504*0afa8e06SEd Maste 	return (ci->maxcredcntlst);
505*0afa8e06SEd Maste }
506*0afa8e06SEd Maste 
507*0afa8e06SEd Maste uint64_t
508*0afa8e06SEd Maste fido_cbor_info_maxcredidlen(const fido_cbor_info_t *ci)
509*0afa8e06SEd Maste {
510*0afa8e06SEd Maste 	return (ci->maxcredidlen);
511*0afa8e06SEd Maste }
512*0afa8e06SEd Maste 
513*0afa8e06SEd Maste uint64_t
514*0afa8e06SEd Maste fido_cbor_info_fwversion(const fido_cbor_info_t *ci)
515*0afa8e06SEd Maste {
516*0afa8e06SEd Maste 	return (ci->fwversion);
517*0afa8e06SEd Maste }
518*0afa8e06SEd Maste 
519*0afa8e06SEd Maste const uint8_t *
520*0afa8e06SEd Maste fido_cbor_info_protocols_ptr(const fido_cbor_info_t *ci)
521*0afa8e06SEd Maste {
522*0afa8e06SEd Maste 	return (ci->protocols.ptr);
523*0afa8e06SEd Maste }
524*0afa8e06SEd Maste 
525*0afa8e06SEd Maste size_t
526*0afa8e06SEd Maste fido_cbor_info_protocols_len(const fido_cbor_info_t *ci)
527*0afa8e06SEd Maste {
528*0afa8e06SEd Maste 	return (ci->protocols.len);
529*0afa8e06SEd Maste }
530*0afa8e06SEd Maste 
531*0afa8e06SEd Maste size_t
532*0afa8e06SEd Maste fido_cbor_info_algorithm_count(const fido_cbor_info_t *ci)
533*0afa8e06SEd Maste {
534*0afa8e06SEd Maste 	return (ci->algorithms.len);
535*0afa8e06SEd Maste }
536*0afa8e06SEd Maste 
537*0afa8e06SEd Maste const char *
538*0afa8e06SEd Maste fido_cbor_info_algorithm_type(const fido_cbor_info_t *ci, size_t idx)
539*0afa8e06SEd Maste {
540*0afa8e06SEd Maste 	if (idx >= ci->algorithms.len)
541*0afa8e06SEd Maste 		return (NULL);
542*0afa8e06SEd Maste 
543*0afa8e06SEd Maste 	return (ci->algorithms.ptr[idx].type);
544*0afa8e06SEd Maste }
545*0afa8e06SEd Maste 
546*0afa8e06SEd Maste int
547*0afa8e06SEd Maste fido_cbor_info_algorithm_cose(const fido_cbor_info_t *ci, size_t idx)
548*0afa8e06SEd Maste {
549*0afa8e06SEd Maste 	if (idx >= ci->algorithms.len)
550*0afa8e06SEd Maste 		return (0);
551*0afa8e06SEd Maste 
552*0afa8e06SEd Maste 	return (ci->algorithms.ptr[idx].cose);
553*0afa8e06SEd Maste }
554