xref: /openbsd-src/lib/libfido2/src/cbor.c (revision 99fd087599a8791921855f21bd7e36130f39aadc)
1 /*
2  * Copyright (c) 2018 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  */
6 
7 #include <openssl/evp.h>
8 #include <openssl/hmac.h>
9 #include <openssl/sha.h>
10 
11 #include <string.h>
12 #include "fido.h"
13 
14 static int
15 check_key_type(cbor_item_t *item)
16 {
17 	if (item->type == CBOR_TYPE_UINT || item->type == CBOR_TYPE_NEGINT ||
18 	    item->type == CBOR_TYPE_STRING)
19 		return (0);
20 
21 	fido_log_debug("%s: invalid type: %d", __func__, item->type);
22 
23 	return (-1);
24 }
25 
26 /*
27  * Validate CTAP2 canonical CBOR encoding rules for maps.
28  */
29 static int
30 ctap_check_cbor(cbor_item_t *prev, cbor_item_t *curr)
31 {
32 	size_t	curr_len;
33 	size_t	prev_len;
34 
35 	if (check_key_type(prev) < 0 || check_key_type(curr) < 0)
36 		return (-1);
37 
38 	if (prev->type != curr->type) {
39 		if (prev->type < curr->type)
40 			return (0);
41 		fido_log_debug("%s: unsorted types", __func__);
42 		return (-1);
43 	}
44 
45 	if (curr->type == CBOR_TYPE_UINT || curr->type == CBOR_TYPE_NEGINT) {
46 		if (cbor_int_get_width(curr) >= cbor_int_get_width(prev) &&
47 		    cbor_get_int(curr) > cbor_get_int(prev))
48 			return (0);
49 	} else {
50 		curr_len = cbor_string_length(curr);
51 		prev_len = cbor_string_length(prev);
52 
53 		if (curr_len > prev_len || (curr_len == prev_len &&
54 		    memcmp(cbor_string_handle(prev), cbor_string_handle(curr),
55 		    curr_len) < 0))
56 			return (0);
57 	}
58 
59 	fido_log_debug("%s: invalid cbor", __func__);
60 
61 	return (-1);
62 }
63 
64 int
65 cbor_map_iter(const cbor_item_t *item, void *arg, int(*f)(const cbor_item_t *,
66     const cbor_item_t *, void *))
67 {
68 	struct cbor_pair	*v;
69 	size_t			 n;
70 
71 	if ((v = cbor_map_handle(item)) == NULL) {
72 		fido_log_debug("%s: cbor_map_handle", __func__);
73 		return (-1);
74 	}
75 
76 	n = cbor_map_size(item);
77 
78 	for (size_t i = 0; i < n; i++) {
79 		if (v[i].key == NULL || v[i].value == NULL) {
80 			fido_log_debug("%s: key=%p, value=%p for i=%zu",
81 			    __func__, (void *)v[i].key, (void *)v[i].value, i);
82 			return (-1);
83 		}
84 		if (i && ctap_check_cbor(v[i - 1].key, v[i].key) < 0) {
85 			fido_log_debug("%s: ctap_check_cbor", __func__);
86 			return (-1);
87 		}
88 		if (f(v[i].key, v[i].value, arg) < 0) {
89 			fido_log_debug("%s: iterator < 0 on i=%zu", __func__,
90 			    i);
91 			return (-1);
92 		}
93 	}
94 
95 	return (0);
96 }
97 
98 int
99 cbor_array_iter(const cbor_item_t *item, void *arg, int(*f)(const cbor_item_t *,
100     void *))
101 {
102 	cbor_item_t	**v;
103 	size_t		  n;
104 
105 	if ((v = cbor_array_handle(item)) == NULL) {
106 		fido_log_debug("%s: cbor_array_handle", __func__);
107 		return (-1);
108 	}
109 
110 	n = cbor_array_size(item);
111 
112 	for (size_t i = 0; i < n; i++)
113 		if (v[i] == NULL || f(v[i], arg) < 0) {
114 			fido_log_debug("%s: iterator < 0 on i=%zu,%p",
115 			    __func__, i, (void *)v[i]);
116 			return (-1);
117 		}
118 
119 	return (0);
120 }
121 
122 int
123 cbor_parse_reply(const unsigned char *blob, size_t blob_len, void *arg,
124     int(*parser)(const cbor_item_t *, const cbor_item_t *, void *))
125 {
126 	cbor_item_t		*item = NULL;
127 	struct cbor_load_result	 cbor;
128 	int			 r;
129 
130 	if (blob_len < 1) {
131 		fido_log_debug("%s: blob_len=%zu", __func__, blob_len);
132 		r = FIDO_ERR_RX;
133 		goto fail;
134 	}
135 
136 	if (blob[0] != FIDO_OK) {
137 		fido_log_debug("%s: blob[0]=0x%02x", __func__, blob[0]);
138 		r = blob[0];
139 		goto fail;
140 	}
141 
142 	if ((item = cbor_load(blob + 1, blob_len - 1, &cbor)) == NULL) {
143 		fido_log_debug("%s: cbor_load", __func__);
144 		r = FIDO_ERR_RX_NOT_CBOR;
145 		goto fail;
146 	}
147 
148 	if (cbor_isa_map(item) == false ||
149 	    cbor_map_is_definite(item) == false) {
150 		fido_log_debug("%s: cbor type", __func__);
151 		r = FIDO_ERR_RX_INVALID_CBOR;
152 		goto fail;
153 	}
154 
155 	if (cbor_map_iter(item, arg, parser) < 0) {
156 		fido_log_debug("%s: cbor_map_iter", __func__);
157 		r = FIDO_ERR_RX_INVALID_CBOR;
158 		goto fail;
159 	}
160 
161 	r = FIDO_OK;
162 fail:
163 	if (item != NULL)
164 		cbor_decref(&item);
165 
166 	return (r);
167 }
168 
169 void
170 cbor_vector_free(cbor_item_t **item, size_t len)
171 {
172 	for (size_t i = 0; i < len; i++)
173 		if (item[i] != NULL)
174 			cbor_decref(&item[i]);
175 }
176 
177 int
178 cbor_bytestring_copy(const cbor_item_t *item, unsigned char **buf, size_t *len)
179 {
180 	if (*buf != NULL || *len != 0) {
181 		fido_log_debug("%s: dup", __func__);
182 		return (-1);
183 	}
184 
185 	if (cbor_isa_bytestring(item) == false ||
186 	    cbor_bytestring_is_definite(item) == false) {
187 		fido_log_debug("%s: cbor type", __func__);
188 		return (-1);
189 	}
190 
191 	*len = cbor_bytestring_length(item);
192 	if ((*buf = malloc(*len)) == NULL) {
193 		*len = 0;
194 		return (-1);
195 	}
196 
197 	memcpy(*buf, cbor_bytestring_handle(item), *len);
198 
199 	return (0);
200 }
201 
202 int
203 cbor_string_copy(const cbor_item_t *item, char **str)
204 {
205 	size_t len;
206 
207 	if (*str != NULL) {
208 		fido_log_debug("%s: dup", __func__);
209 		return (-1);
210 	}
211 
212 	if (cbor_isa_string(item) == false ||
213 	    cbor_string_is_definite(item) == false) {
214 		fido_log_debug("%s: cbor type", __func__);
215 		return (-1);
216 	}
217 
218 	if ((len = cbor_string_length(item)) == SIZE_MAX ||
219 	    (*str = malloc(len + 1)) == NULL)
220 		return (-1);
221 
222 	memcpy(*str, cbor_string_handle(item), len);
223 	(*str)[len] = '\0';
224 
225 	return (0);
226 }
227 
228 int
229 cbor_add_bytestring(cbor_item_t *item, const char *key,
230     const unsigned char *value, size_t value_len)
231 {
232 	struct cbor_pair pair;
233 	int ok = -1;
234 
235 	memset(&pair, 0, sizeof(pair));
236 
237 	if ((pair.key = cbor_build_string(key)) == NULL ||
238 	    (pair.value = cbor_build_bytestring(value, value_len)) == NULL) {
239 		fido_log_debug("%s: cbor_build", __func__);
240 		goto fail;
241 	}
242 
243 	if (!cbor_map_add(item, pair)) {
244 		fido_log_debug("%s: cbor_map_add", __func__);
245 		goto fail;
246 	}
247 
248 	ok = 0;
249 fail:
250 	if (pair.key)
251 		cbor_decref(&pair.key);
252 	if (pair.value)
253 		cbor_decref(&pair.value);
254 
255 	return (ok);
256 }
257 
258 int
259 cbor_add_string(cbor_item_t *item, const char *key, const char *value)
260 {
261 	struct cbor_pair pair;
262 	int ok = -1;
263 
264 	memset(&pair, 0, sizeof(pair));
265 
266 	if ((pair.key = cbor_build_string(key)) == NULL ||
267 	    (pair.value = cbor_build_string(value)) == NULL) {
268 		fido_log_debug("%s: cbor_build", __func__);
269 		goto fail;
270 	}
271 
272 	if (!cbor_map_add(item, pair)) {
273 		fido_log_debug("%s: cbor_map_add", __func__);
274 		goto fail;
275 	}
276 
277 	ok = 0;
278 fail:
279 	if (pair.key)
280 		cbor_decref(&pair.key);
281 	if (pair.value)
282 		cbor_decref(&pair.value);
283 
284 	return (ok);
285 }
286 
287 int
288 cbor_add_bool(cbor_item_t *item, const char *key, fido_opt_t value)
289 {
290 	struct cbor_pair pair;
291 	int ok = -1;
292 
293 	memset(&pair, 0, sizeof(pair));
294 
295 	if ((pair.key = cbor_build_string(key)) == NULL ||
296 	    (pair.value = cbor_build_bool(value == FIDO_OPT_TRUE)) == NULL) {
297 		fido_log_debug("%s: cbor_build", __func__);
298 		goto fail;
299 	}
300 
301 	if (!cbor_map_add(item, pair)) {
302 		fido_log_debug("%s: cbor_map_add", __func__);
303 		goto fail;
304 	}
305 
306 	ok = 0;
307 fail:
308 	if (pair.key)
309 		cbor_decref(&pair.key);
310 	if (pair.value)
311 		cbor_decref(&pair.value);
312 
313 	return (ok);
314 }
315 
316 static int
317 cbor_add_uint8(cbor_item_t *item, const char *key, uint8_t value)
318 {
319 	struct cbor_pair pair;
320 	int ok = -1;
321 
322 	memset(&pair, 0, sizeof(pair));
323 
324 	if ((pair.key = cbor_build_string(key)) == NULL ||
325 	    (pair.value = cbor_build_uint8(value)) == NULL) {
326 		fido_log_debug("%s: cbor_build", __func__);
327 		goto fail;
328 	}
329 
330 	if (!cbor_map_add(item, pair)) {
331 		fido_log_debug("%s: cbor_map_add", __func__);
332 		goto fail;
333 	}
334 
335 	ok = 0;
336 fail:
337 	if (pair.key)
338 		cbor_decref(&pair.key);
339 	if (pair.value)
340 		cbor_decref(&pair.value);
341 
342 	return (ok);
343 }
344 
345 static int
346 cbor_add_arg(cbor_item_t *item, uint8_t n, cbor_item_t *arg)
347 {
348 	struct cbor_pair pair;
349 	int ok = -1;
350 
351 	memset(&pair, 0, sizeof(pair));
352 
353 	if (arg == NULL)
354 		return (0); /* empty argument */
355 
356 	if ((pair.key = cbor_build_uint8(n)) == NULL) {
357 		fido_log_debug("%s: cbor_build", __func__);
358 		goto fail;
359 	}
360 
361 	pair.value = arg;
362 
363 	if (!cbor_map_add(item, pair)) {
364 		fido_log_debug("%s: cbor_map_add", __func__);
365 		goto fail;
366 	}
367 
368 	ok = 0;
369 fail:
370 	if (pair.key)
371 		cbor_decref(&pair.key);
372 
373 	return (ok);
374 }
375 
376 cbor_item_t *
377 cbor_flatten_vector(cbor_item_t *argv[], size_t argc)
378 {
379 	cbor_item_t	*map;
380 	uint8_t		 i;
381 
382 	if (argc > UINT8_MAX - 1)
383 		return (NULL);
384 
385 	if ((map = cbor_new_definite_map(argc)) == NULL)
386 		return (NULL);
387 
388 	for (i = 0; i < argc; i++)
389 		if (cbor_add_arg(map, i + 1, argv[i]) < 0)
390 			break;
391 
392 	if (i != argc) {
393 		cbor_decref(&map);
394 		map = NULL;
395 	}
396 
397 	return (map);
398 }
399 
400 int
401 cbor_build_frame(uint8_t cmd, cbor_item_t *argv[], size_t argc, fido_blob_t *f)
402 {
403 	cbor_item_t	*flat = NULL;
404 	unsigned char	*cbor = NULL;
405 	size_t		 cbor_len;
406 	size_t		 cbor_alloc_len;
407 	int		 ok = -1;
408 
409 	if ((flat = cbor_flatten_vector(argv, argc)) == NULL)
410 		goto fail;
411 
412 	cbor_len = cbor_serialize_alloc(flat, &cbor, &cbor_alloc_len);
413 	if (cbor_len == 0 || cbor_len == SIZE_MAX) {
414 		fido_log_debug("%s: cbor_len=%zu", __func__, cbor_len);
415 		goto fail;
416 	}
417 
418 	if ((f->ptr = malloc(cbor_len + 1)) == NULL)
419 		goto fail;
420 
421 	f->len = cbor_len + 1;
422 	f->ptr[0] = cmd;
423 	memcpy(f->ptr + 1, cbor, f->len - 1);
424 
425 	ok = 0;
426 fail:
427 	if (flat != NULL)
428 		cbor_decref(&flat);
429 
430 	free(cbor);
431 
432 	return (ok);
433 }
434 
435 cbor_item_t *
436 cbor_encode_rp_entity(const fido_rp_t *rp)
437 {
438 	cbor_item_t *item = NULL;
439 
440 	if ((item = cbor_new_definite_map(2)) == NULL)
441 		return (NULL);
442 
443 	if ((rp->id && cbor_add_string(item, "id", rp->id) < 0) ||
444 	    (rp->name && cbor_add_string(item, "name", rp->name) < 0)) {
445 		cbor_decref(&item);
446 		return (NULL);
447 	}
448 
449 	return (item);
450 }
451 
452 cbor_item_t *
453 cbor_encode_user_entity(const fido_user_t *user)
454 {
455 	cbor_item_t		*item = NULL;
456 	const fido_blob_t	*id = &user->id;
457 	const char		*display = user->display_name;
458 
459 	if ((item = cbor_new_definite_map(4)) == NULL)
460 		return (NULL);
461 
462 	if ((id->ptr && cbor_add_bytestring(item, "id", id->ptr, id->len) < 0) ||
463 	    (user->icon && cbor_add_string(item, "icon", user->icon) < 0) ||
464 	    (user->name && cbor_add_string(item, "name", user->name) < 0) ||
465 	    (display && cbor_add_string(item, "displayName", display) < 0)) {
466 		cbor_decref(&item);
467 		return (NULL);
468 	}
469 
470 	return (item);
471 }
472 
473 cbor_item_t *
474 cbor_encode_pubkey_param(int cose_alg)
475 {
476 	cbor_item_t		*item = NULL;
477 	cbor_item_t		*body = NULL;
478 	struct cbor_pair	 alg;
479 	int			 ok = -1;
480 
481 	memset(&alg, 0, sizeof(alg));
482 
483 	if ((item = cbor_new_definite_array(1)) == NULL ||
484 	    (body = cbor_new_definite_map(2)) == NULL ||
485 	    cose_alg > -1 || cose_alg < INT16_MIN)
486 		goto fail;
487 
488 	alg.key = cbor_build_string("alg");
489 
490 	if (-cose_alg - 1 > UINT8_MAX)
491 		alg.value = cbor_build_negint16((uint16_t)(-cose_alg - 1));
492 	else
493 		alg.value = cbor_build_negint8((uint8_t)(-cose_alg - 1));
494 
495 	if (alg.key == NULL || alg.value == NULL) {
496 		fido_log_debug("%s: cbor_build", __func__);
497 		goto fail;
498 	}
499 
500 	if (cbor_map_add(body, alg) == false ||
501 	    cbor_add_string(body, "type", "public-key") < 0 ||
502 	    cbor_array_push(item, body) == false)
503 		goto fail;
504 
505 	ok  = 0;
506 fail:
507 	if (ok < 0) {
508 		if (item != NULL) {
509 			cbor_decref(&item);
510 			item = NULL;
511 		}
512 	}
513 
514 	if (body != NULL)
515 		cbor_decref(&body);
516 	if (alg.key != NULL)
517 		cbor_decref(&alg.key);
518 	if (alg.value != NULL)
519 		cbor_decref(&alg.value);
520 
521 	return (item);
522 }
523 
524 cbor_item_t *
525 cbor_encode_pubkey(const fido_blob_t *pubkey)
526 {
527 	cbor_item_t *cbor_key = NULL;
528 
529 	if ((cbor_key = cbor_new_definite_map(2)) == NULL ||
530 	    cbor_add_bytestring(cbor_key, "id", pubkey->ptr, pubkey->len) < 0 ||
531 	    cbor_add_string(cbor_key, "type", "public-key") < 0) {
532 		if (cbor_key)
533 			cbor_decref(&cbor_key);
534 		return (NULL);
535 	}
536 
537 	return (cbor_key);
538 }
539 
540 cbor_item_t *
541 cbor_encode_pubkey_list(const fido_blob_array_t *list)
542 {
543 	cbor_item_t	*array = NULL;
544 	cbor_item_t	*key = NULL;
545 
546 	if ((array = cbor_new_definite_array(list->len)) == NULL)
547 		goto fail;
548 
549 	for (size_t i = 0; i < list->len; i++) {
550 		if ((key = cbor_encode_pubkey(&list->ptr[i])) == NULL ||
551 		    cbor_array_push(array, key) == false)
552 			goto fail;
553 		cbor_decref(&key);
554 	}
555 
556 	return (array);
557 fail:
558 	if (key != NULL)
559 		cbor_decref(&key);
560 	if (array != NULL)
561 		cbor_decref(&array);
562 
563 	return (NULL);
564 }
565 
566 cbor_item_t *
567 cbor_encode_extensions(const fido_cred_ext_t *ext)
568 {
569 	cbor_item_t *item = NULL;
570 	size_t size = 0;
571 
572 	if (ext->mask & FIDO_EXT_HMAC_SECRET)
573 		size++;
574 	if (ext->mask & FIDO_EXT_CRED_PROTECT)
575 		size++;
576 	if (size == 0 || (item = cbor_new_definite_map(size)) == NULL)
577 		return (NULL);
578 
579 	if (ext->mask & FIDO_EXT_HMAC_SECRET) {
580 		if (cbor_add_bool(item, "hmac-secret", FIDO_OPT_TRUE) < 0) {
581 			cbor_decref(&item);
582 			return (NULL);
583 		}
584 	}
585 	if (ext->mask & FIDO_EXT_CRED_PROTECT) {
586 		if (cbor_add_uint8(item, "credProtect", ext->prot) < 0) {
587 			cbor_decref(&item);
588 			return (NULL);
589 		}
590 	}
591 
592 	return (item);
593 }
594 
595 cbor_item_t *
596 cbor_encode_options(fido_opt_t rk, fido_opt_t uv)
597 {
598 	cbor_item_t *item = NULL;
599 
600 	if ((item = cbor_new_definite_map(2)) == NULL)
601 		return (NULL);
602 
603 	if ((rk != FIDO_OPT_OMIT && cbor_add_bool(item, "rk", rk) < 0) ||
604 	    (uv != FIDO_OPT_OMIT && cbor_add_bool(item, "uv", uv) < 0)) {
605 		cbor_decref(&item);
606 		return (NULL);
607 	}
608 
609 	return (item);
610 }
611 
612 cbor_item_t *
613 cbor_encode_assert_options(fido_opt_t up, fido_opt_t uv)
614 {
615 	cbor_item_t *item = NULL;
616 
617 	if ((item = cbor_new_definite_map(2)) == NULL)
618 		return (NULL);
619 
620 	if ((up != FIDO_OPT_OMIT && cbor_add_bool(item, "up", up) < 0) ||
621 	    (uv != FIDO_OPT_OMIT && cbor_add_bool(item, "uv", uv) < 0)) {
622 		cbor_decref(&item);
623 		return (NULL);
624 	}
625 
626 	return (item);
627 }
628 
629 cbor_item_t *
630 cbor_encode_pin_auth(const fido_blob_t *hmac_key, const fido_blob_t *data)
631 {
632 	const EVP_MD	*md = NULL;
633 	unsigned char	 dgst[SHA256_DIGEST_LENGTH];
634 	unsigned int	 dgst_len;
635 
636 	if ((md = EVP_sha256()) == NULL || HMAC(md, hmac_key->ptr,
637 	    (int)hmac_key->len, data->ptr, (int)data->len, dgst,
638 	    &dgst_len) == NULL || dgst_len != SHA256_DIGEST_LENGTH)
639 		return (NULL);
640 
641 	return (cbor_build_bytestring(dgst, 16));
642 }
643 
644 cbor_item_t *
645 cbor_encode_pin_opt(void)
646 {
647 	return (cbor_build_uint8(1));
648 }
649 
650 cbor_item_t *
651 cbor_encode_pin_enc(const fido_blob_t *key, const fido_blob_t *pin)
652 {
653 	fido_blob_t	 pe;
654 	cbor_item_t	*item = NULL;
655 
656 	if (aes256_cbc_enc(key, pin, &pe) < 0)
657 		return (NULL);
658 
659 	item = cbor_build_bytestring(pe.ptr, pe.len);
660 	free(pe.ptr);
661 
662 	return (item);
663 }
664 
665 static int
666 sha256(const unsigned char *data, size_t data_len, fido_blob_t *digest)
667 {
668 	if ((digest->ptr = calloc(1, SHA256_DIGEST_LENGTH)) == NULL)
669 		return (-1);
670 
671 	digest->len = SHA256_DIGEST_LENGTH;
672 
673 	if (SHA256(data, data_len, digest->ptr) != digest->ptr) {
674 		free(digest->ptr);
675 		digest->ptr = NULL;
676 		digest->len = 0;
677 		return (-1);
678 	}
679 
680 	return (0);
681 }
682 
683 cbor_item_t *
684 cbor_encode_change_pin_auth(const fido_blob_t *key, const fido_blob_t *new_pin,
685     const fido_blob_t *pin)
686 {
687 	unsigned char	 dgst[SHA256_DIGEST_LENGTH];
688 	unsigned int	 dgst_len;
689 	cbor_item_t	*item = NULL;
690 	const EVP_MD	*md = NULL;
691 #if OPENSSL_VERSION_NUMBER < 0x10100000L
692 	HMAC_CTX	 ctx;
693 #else
694 	HMAC_CTX	*ctx = NULL;
695 #endif
696 	fido_blob_t	*npe = NULL; /* new pin, encrypted */
697 	fido_blob_t	*ph = NULL;  /* pin hash */
698 	fido_blob_t	*phe = NULL; /* pin hash, encrypted */
699 	int		 ok = -1;
700 
701 	if ((npe = fido_blob_new()) == NULL ||
702 	    (ph = fido_blob_new()) == NULL ||
703 	    (phe = fido_blob_new()) == NULL)
704 		goto fail;
705 
706 	if (aes256_cbc_enc(key, new_pin, npe) < 0) {
707 		fido_log_debug("%s: aes256_cbc_enc 1", __func__);
708 		goto fail;
709 	}
710 
711 	if (sha256(pin->ptr, pin->len, ph) < 0 || ph->len < 16) {
712 		fido_log_debug("%s: sha256", __func__);
713 		goto fail;
714 	}
715 
716 	ph->len = 16; /* first 16 bytes */
717 
718 	if (aes256_cbc_enc(key, ph, phe) < 0) {
719 		fido_log_debug("%s: aes256_cbc_enc 2", __func__);
720 		goto fail;
721 	}
722 
723 #if OPENSSL_VERSION_NUMBER < 0x10100000L
724 	HMAC_CTX_init(&ctx);
725 
726 	if ((md = EVP_sha256()) == NULL ||
727 	    HMAC_Init_ex(&ctx, key->ptr, (int)key->len, md, NULL) == 0 ||
728 	    HMAC_Update(&ctx, npe->ptr, (int)npe->len) == 0 ||
729 	    HMAC_Update(&ctx, phe->ptr, (int)phe->len) == 0 ||
730 	    HMAC_Final(&ctx, dgst, &dgst_len) == 0 || dgst_len != 32) {
731 		fido_log_debug("%s: HMAC", __func__);
732 		goto fail;
733 	}
734 #else
735 	if ((ctx = HMAC_CTX_new()) == NULL ||
736 	    (md = EVP_sha256())  == NULL ||
737 	    HMAC_Init_ex(ctx, key->ptr, (int)key->len, md, NULL) == 0 ||
738 	    HMAC_Update(ctx, npe->ptr, (int)npe->len) == 0 ||
739 	    HMAC_Update(ctx, phe->ptr, (int)phe->len) == 0 ||
740 	    HMAC_Final(ctx, dgst, &dgst_len) == 0 || dgst_len != 32) {
741 		fido_log_debug("%s: HMAC", __func__);
742 		goto fail;
743 	}
744 #endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */
745 
746 	if ((item = cbor_build_bytestring(dgst, 16)) == NULL) {
747 		fido_log_debug("%s: cbor_build_bytestring", __func__);
748 		goto fail;
749 	}
750 
751 	ok = 0;
752 fail:
753 	fido_blob_free(&npe);
754 	fido_blob_free(&ph);
755 	fido_blob_free(&phe);
756 
757 #if OPENSSL_VERSION_NUMBER >= 0x10100000L
758 	if (ctx != NULL)
759 		HMAC_CTX_free(ctx);
760 #endif
761 
762 	if (ok < 0) {
763 		if (item != NULL) {
764 			cbor_decref(&item);
765 			item = NULL;
766 		}
767 	}
768 
769 	return (item);
770 }
771 
772 cbor_item_t *
773 cbor_encode_set_pin_auth(const fido_blob_t *key, const fido_blob_t *pin)
774 {
775 	const EVP_MD	*md = NULL;
776 	unsigned char	 dgst[SHA256_DIGEST_LENGTH];
777 	unsigned int	 dgst_len;
778 	cbor_item_t	*item = NULL;
779 	fido_blob_t	*pe = NULL;
780 
781 	if ((pe = fido_blob_new()) == NULL)
782 		goto fail;
783 
784 	if (aes256_cbc_enc(key, pin, pe) < 0) {
785 		fido_log_debug("%s: aes256_cbc_enc", __func__);
786 		goto fail;
787 	}
788 
789 	if ((md = EVP_sha256()) == NULL || key->len != 32 || HMAC(md, key->ptr,
790 	    (int)key->len, pe->ptr, (int)pe->len, dgst, &dgst_len) == NULL ||
791 	    dgst_len != SHA256_DIGEST_LENGTH) {
792 		fido_log_debug("%s: HMAC", __func__);
793 		goto fail;
794 	}
795 
796 	item = cbor_build_bytestring(dgst, 16);
797 fail:
798 	fido_blob_free(&pe);
799 
800 	return (item);
801 }
802 
803 cbor_item_t *
804 cbor_encode_pin_hash_enc(const fido_blob_t *shared, const fido_blob_t *pin)
805 {
806 	cbor_item_t	*item = NULL;
807 	fido_blob_t	*ph = NULL;
808 	fido_blob_t	*phe = NULL;
809 
810 	if ((ph = fido_blob_new()) == NULL || (phe = fido_blob_new()) == NULL)
811 		goto fail;
812 
813 	if (sha256(pin->ptr, pin->len, ph) < 0 || ph->len < 16) {
814 		fido_log_debug("%s: SHA256", __func__);
815 		goto fail;
816 	}
817 
818 	ph->len = 16; /* first 16 bytes */
819 
820 	if (aes256_cbc_enc(shared, ph, phe) < 0) {
821 		fido_log_debug("%s: aes256_cbc_enc", __func__);
822 		goto fail;
823 	}
824 
825 	item = cbor_build_bytestring(phe->ptr, phe->len);
826 fail:
827 	fido_blob_free(&ph);
828 	fido_blob_free(&phe);
829 
830 	return (item);
831 }
832 
833 cbor_item_t *
834 cbor_encode_hmac_secret_param(const fido_blob_t *ecdh, const es256_pk_t *pk,
835     const fido_blob_t *hmac_salt)
836 {
837 	cbor_item_t		*item = NULL;
838 	cbor_item_t		*param = NULL;
839 	cbor_item_t		*argv[3];
840 	struct cbor_pair	 pair;
841 
842 	memset(argv, 0, sizeof(argv));
843 	memset(&pair, 0, sizeof(pair));
844 
845 	if (ecdh == NULL || pk == NULL || hmac_salt->ptr == NULL) {
846 		fido_log_debug("%s: ecdh=%p, pk=%p, hmac_salt->ptr=%p",
847 		    __func__, (const void *)ecdh, (const void *)pk,
848 		    (const void *)hmac_salt->ptr);
849 		goto fail;
850 	}
851 
852 	if (hmac_salt->len != 32 && hmac_salt->len != 64) {
853 		fido_log_debug("%s: hmac_salt->len=%zu", __func__,
854 		    hmac_salt->len);
855 		goto fail;
856 	}
857 
858 	/* XXX not pin, but salt */
859 	if ((argv[0] = es256_pk_encode(pk, 1)) == NULL ||
860 	    (argv[1] = cbor_encode_pin_enc(ecdh, hmac_salt)) == NULL ||
861 	    (argv[2] = cbor_encode_set_pin_auth(ecdh, hmac_salt)) == NULL) {
862 		fido_log_debug("%s: cbor encode", __func__);
863 		goto fail;
864 	}
865 
866 	if ((param = cbor_flatten_vector(argv, 3)) == NULL) {
867 		fido_log_debug("%s: cbor_flatten_vector", __func__);
868 		goto fail;
869 	}
870 
871 	if ((item = cbor_new_definite_map(1)) == NULL) {
872 		fido_log_debug("%s: cbor_new_definite_map", __func__);
873 		goto fail;
874 	}
875 
876 	if ((pair.key = cbor_build_string("hmac-secret")) == NULL) {
877 		fido_log_debug("%s: cbor_build", __func__);
878 		goto fail;
879 	}
880 
881 	pair.value = param;
882 
883 	if (!cbor_map_add(item, pair)) {
884 		fido_log_debug("%s: cbor_map_add", __func__);
885 		cbor_decref(&item);
886 		item = NULL;
887 		goto fail;
888 	}
889 
890 fail:
891 	for (size_t i = 0; i < 3; i++)
892 		if (argv[i] != NULL)
893 			cbor_decref(&argv[i]);
894 
895 	if (param != NULL)
896 		cbor_decref(&param);
897 	if (pair.key != NULL)
898 		cbor_decref(&pair.key);
899 
900 	return (item);
901 }
902 
903 int
904 cbor_decode_fmt(const cbor_item_t *item, char **fmt)
905 {
906 	char	*type = NULL;
907 
908 	if (cbor_string_copy(item, &type) < 0) {
909 		fido_log_debug("%s: cbor_string_copy", __func__);
910 		return (-1);
911 	}
912 
913 	if (strcmp(type, "packed") && strcmp(type, "fido-u2f")) {
914 		fido_log_debug("%s: type=%s", __func__, type);
915 		free(type);
916 		return (-1);
917 	}
918 
919 	*fmt = type;
920 
921 	return (0);
922 }
923 
924 struct cose_key {
925 	int kty;
926 	int alg;
927 	int crv;
928 };
929 
930 static int
931 find_cose_alg(const cbor_item_t *key, const cbor_item_t *val, void *arg)
932 {
933 	struct cose_key *cose_key = arg;
934 
935 	if (cbor_isa_uint(key) == true &&
936 	    cbor_int_get_width(key) == CBOR_INT_8) {
937 		switch (cbor_get_uint8(key)) {
938 		case 1:
939 			if (cbor_isa_uint(val) == false ||
940 			    cbor_get_int(val) > INT_MAX || cose_key->kty != 0) {
941 				fido_log_debug("%s: kty", __func__);
942 				return (-1);
943 			}
944 
945 			cose_key->kty = (int)cbor_get_int(val);
946 
947 			break;
948 		case 3:
949 			if (cbor_isa_negint(val) == false ||
950 			    cbor_get_int(val) > INT_MAX || cose_key->alg != 0) {
951 				fido_log_debug("%s: alg", __func__);
952 				return (-1);
953 			}
954 
955 			cose_key->alg = -(int)cbor_get_int(val) - 1;
956 
957 			break;
958 		}
959 	} else if (cbor_isa_negint(key) == true &&
960 	    cbor_int_get_width(key) == CBOR_INT_8) {
961 		if (cbor_get_uint8(key) == 0) {
962 			/* get crv if not rsa, otherwise ignore */
963 			if (cbor_isa_uint(val) == true &&
964 			    cbor_get_int(val) <= INT_MAX &&
965 			    cose_key->crv == 0)
966 				cose_key->crv = (int)cbor_get_int(val);
967 		}
968 	}
969 
970 	return (0);
971 }
972 
973 static int
974 get_cose_alg(const cbor_item_t *item, int *cose_alg)
975 {
976 	struct cose_key cose_key;
977 
978 	memset(&cose_key, 0, sizeof(cose_key));
979 
980 	*cose_alg = 0;
981 
982 	if (cbor_isa_map(item) == false ||
983 	    cbor_map_is_definite(item) == false ||
984 	    cbor_map_iter(item, &cose_key, find_cose_alg) < 0) {
985 		fido_log_debug("%s: cbor type", __func__);
986 		return (-1);
987 	}
988 
989 	switch (cose_key.alg) {
990 	case COSE_ES256:
991 		if (cose_key.kty != COSE_KTY_EC2 ||
992 		    cose_key.crv != COSE_P256) {
993 			fido_log_debug("%s: invalid kty/crv", __func__);
994 			return (-1);
995 		}
996 
997 		break;
998 	case COSE_EDDSA:
999 		if (cose_key.kty != COSE_KTY_OKP ||
1000 		    cose_key.crv != COSE_ED25519) {
1001 			fido_log_debug("%s: invalid kty/crv", __func__);
1002 			return (-1);
1003 		}
1004 
1005 		break;
1006 	case COSE_RS256:
1007 		if (cose_key.kty != COSE_KTY_RSA) {
1008 			fido_log_debug("%s: invalid kty/crv", __func__);
1009 			return (-1);
1010 		}
1011 
1012 		break;
1013 	default:
1014 		fido_log_debug("%s: unknown alg %d", __func__, cose_key.alg);
1015 
1016 		return (-1);
1017 	}
1018 
1019 	*cose_alg = cose_key.alg;
1020 
1021 	return (0);
1022 }
1023 
1024 int
1025 cbor_decode_pubkey(const cbor_item_t *item, int *type, void *key)
1026 {
1027 	if (get_cose_alg(item, type) < 0) {
1028 		fido_log_debug("%s: get_cose_alg", __func__);
1029 		return (-1);
1030 	}
1031 
1032 	switch (*type) {
1033 	case COSE_ES256:
1034 		if (es256_pk_decode(item, key) < 0) {
1035 			fido_log_debug("%s: es256_pk_decode", __func__);
1036 			return (-1);
1037 		}
1038 		break;
1039 	case COSE_RS256:
1040 		if (rs256_pk_decode(item, key) < 0) {
1041 			fido_log_debug("%s: rs256_pk_decode", __func__);
1042 			return (-1);
1043 		}
1044 		break;
1045 	case COSE_EDDSA:
1046 		if (eddsa_pk_decode(item, key) < 0) {
1047 			fido_log_debug("%s: eddsa_pk_decode", __func__);
1048 			return (-1);
1049 		}
1050 		break;
1051 	default:
1052 		fido_log_debug("%s: invalid cose_alg %d", __func__, *type);
1053 		return (-1);
1054 	}
1055 
1056 	return (0);
1057 }
1058 
1059 static int
1060 decode_attcred(const unsigned char **buf, size_t *len, int cose_alg,
1061     fido_attcred_t *attcred)
1062 {
1063 	cbor_item_t		*item = NULL;
1064 	struct cbor_load_result	 cbor;
1065 	uint16_t		 id_len;
1066 	int			 ok = -1;
1067 
1068 	fido_log_debug("%s: buf=%p, len=%zu", __func__, (const void *)*buf,
1069 	    *len);
1070 
1071 	if (fido_buf_read(buf, len, &attcred->aaguid,
1072 	    sizeof(attcred->aaguid)) < 0) {
1073 		fido_log_debug("%s: fido_buf_read aaguid", __func__);
1074 		return (-1);
1075 	}
1076 
1077 	if (fido_buf_read(buf, len, &id_len, sizeof(id_len)) < 0) {
1078 		fido_log_debug("%s: fido_buf_read id_len", __func__);
1079 		return (-1);
1080 	}
1081 
1082 	attcred->id.len = (size_t)be16toh(id_len);
1083 	if ((attcred->id.ptr = malloc(attcred->id.len)) == NULL)
1084 		return (-1);
1085 
1086 	fido_log_debug("%s: attcred->id.len=%zu", __func__, attcred->id.len);
1087 
1088 	if (fido_buf_read(buf, len, attcred->id.ptr, attcred->id.len) < 0) {
1089 		fido_log_debug("%s: fido_buf_read id", __func__);
1090 		return (-1);
1091 	}
1092 
1093 	if ((item = cbor_load(*buf, *len, &cbor)) == NULL) {
1094 		fido_log_debug("%s: cbor_load", __func__);
1095 		fido_log_xxd(*buf, *len);
1096 		goto fail;
1097 	}
1098 
1099 	if (cbor_decode_pubkey(item, &attcred->type, &attcred->pubkey) < 0) {
1100 		fido_log_debug("%s: cbor_decode_pubkey", __func__);
1101 		goto fail;
1102 	}
1103 
1104 	if (attcred->type != cose_alg) {
1105 		fido_log_debug("%s: cose_alg mismatch (%d != %d)", __func__,
1106 		    attcred->type, cose_alg);
1107 		goto fail;
1108 	}
1109 
1110 	*buf += cbor.read;
1111 	*len -= cbor.read;
1112 
1113 	ok = 0;
1114 fail:
1115 	if (item != NULL)
1116 		cbor_decref(&item);
1117 
1118 	return (ok);
1119 }
1120 
1121 static int
1122 decode_extension(const cbor_item_t *key, const cbor_item_t *val, void *arg)
1123 {
1124 	fido_cred_ext_t	*authdata_ext = arg;
1125 	char		*type = NULL;
1126 	int		 ok = -1;
1127 
1128 	if (cbor_string_copy(key, &type) < 0) {
1129 		fido_log_debug("%s: cbor type", __func__);
1130 		ok = 0; /* ignore */
1131 		goto out;
1132 	}
1133 
1134 	if (strcmp(type, "hmac-secret") == 0) {
1135 		if (cbor_isa_float_ctrl(val) == false ||
1136 		    cbor_float_get_width(val) != CBOR_FLOAT_0 ||
1137 		    cbor_is_bool(val) == false) {
1138 			fido_log_debug("%s: cbor type", __func__);
1139 			goto out;
1140 		}
1141 		if (cbor_ctrl_value(val) == CBOR_CTRL_TRUE)
1142 			authdata_ext->mask |= FIDO_EXT_HMAC_SECRET;
1143 	} else if (strcmp(type, "credProtect") == 0) {
1144 		if (cbor_isa_uint(val) == false ||
1145 		    cbor_int_get_width(val) != CBOR_INT_8) {
1146 			fido_log_debug("%s: cbor type", __func__);
1147 			goto out;
1148 		}
1149 		authdata_ext->mask |= FIDO_EXT_CRED_PROTECT;
1150 		authdata_ext->prot = cbor_get_uint8(val);
1151 	}
1152 
1153 	ok = 0;
1154 out:
1155 	free(type);
1156 
1157 	return (ok);
1158 }
1159 
1160 static int
1161 decode_extensions(const unsigned char **buf, size_t *len,
1162     fido_cred_ext_t *authdata_ext)
1163 {
1164 	cbor_item_t		*item = NULL;
1165 	struct cbor_load_result	 cbor;
1166 	int			 ok = -1;
1167 
1168 	fido_log_debug("%s: buf=%p, len=%zu", __func__, (const void *)*buf,
1169 	    *len);
1170 	fido_log_xxd(*buf, *len);
1171 
1172 	memset(authdata_ext, 0, sizeof(*authdata_ext));
1173 
1174 	if ((item = cbor_load(*buf, *len, &cbor)) == NULL) {
1175 		fido_log_debug("%s: cbor_load", __func__);
1176 		fido_log_xxd(*buf, *len);
1177 		goto fail;
1178 	}
1179 
1180 	if (cbor_isa_map(item) == false ||
1181 	    cbor_map_is_definite(item) == false ||
1182 	    cbor_map_iter(item, authdata_ext, decode_extension) < 0) {
1183 		fido_log_debug("%s: cbor type", __func__);
1184 		goto fail;
1185 	}
1186 
1187 	*buf += cbor.read;
1188 	*len -= cbor.read;
1189 
1190 	ok = 0;
1191 fail:
1192 	if (item != NULL)
1193 		cbor_decref(&item);
1194 
1195 	return (ok);
1196 }
1197 
1198 static int
1199 decode_hmac_secret_aux(const cbor_item_t *key, const cbor_item_t *val, void *arg)
1200 {
1201 	fido_blob_t	*out = arg;
1202 	char		*type = NULL;
1203 	int		 ok = -1;
1204 
1205 	if (cbor_string_copy(key, &type) < 0 || strcmp(type, "hmac-secret")) {
1206 		fido_log_debug("%s: cbor type", __func__);
1207 		ok = 0; /* ignore */
1208 		goto out;
1209 	}
1210 
1211 	ok = cbor_bytestring_copy(val, &out->ptr, &out->len);
1212 out:
1213 	free(type);
1214 
1215 	return (ok);
1216 }
1217 
1218 static int
1219 decode_hmac_secret(const unsigned char **buf, size_t *len, fido_blob_t *out)
1220 {
1221 	cbor_item_t		*item = NULL;
1222 	struct cbor_load_result	 cbor;
1223 	int			 ok = -1;
1224 
1225 	fido_log_debug("%s: buf=%p, len=%zu", __func__, (const void *)*buf,
1226 	    *len);
1227 
1228 	if ((item = cbor_load(*buf, *len, &cbor)) == NULL) {
1229 		fido_log_debug("%s: cbor_load", __func__);
1230 		fido_log_xxd(*buf, *len);
1231 		goto fail;
1232 	}
1233 
1234 	if (cbor_isa_map(item) == false ||
1235 	    cbor_map_is_definite(item) == false ||
1236 	    cbor_map_size(item) != 1 ||
1237 	    cbor_map_iter(item, out, decode_hmac_secret_aux) < 0) {
1238 		fido_log_debug("%s: cbor type", __func__);
1239 		goto fail;
1240 	}
1241 
1242 	*buf += cbor.read;
1243 	*len -= cbor.read;
1244 
1245 	ok = 0;
1246 fail:
1247 	if (item != NULL)
1248 		cbor_decref(&item);
1249 
1250 	return (ok);
1251 }
1252 
1253 int
1254 cbor_decode_cred_authdata(const cbor_item_t *item, int cose_alg,
1255     fido_blob_t *authdata_cbor, fido_authdata_t *authdata,
1256     fido_attcred_t *attcred, fido_cred_ext_t *authdata_ext)
1257 {
1258 	const unsigned char	*buf = NULL;
1259 	size_t			 len;
1260 	size_t			 alloc_len;
1261 
1262 	if (cbor_isa_bytestring(item) == false ||
1263 	    cbor_bytestring_is_definite(item) == false) {
1264 		fido_log_debug("%s: cbor type", __func__);
1265 		return (-1);
1266 	}
1267 
1268 	if (authdata_cbor->ptr != NULL ||
1269 	    (authdata_cbor->len = cbor_serialize_alloc(item,
1270 	    &authdata_cbor->ptr, &alloc_len)) == 0) {
1271 		fido_log_debug("%s: cbor_serialize_alloc", __func__);
1272 		return (-1);
1273 	}
1274 
1275 	buf = cbor_bytestring_handle(item);
1276 	len = cbor_bytestring_length(item);
1277 
1278 	fido_log_debug("%s: buf=%p, len=%zu", __func__, (const void *)buf, len);
1279 	fido_log_xxd(buf, len);
1280 
1281 	if (fido_buf_read(&buf, &len, authdata, sizeof(*authdata)) < 0) {
1282 		fido_log_debug("%s: fido_buf_read", __func__);
1283 		return (-1);
1284 	}
1285 
1286 	authdata->sigcount = be32toh(authdata->sigcount);
1287 
1288 	if (attcred != NULL) {
1289 		if ((authdata->flags & CTAP_AUTHDATA_ATT_CRED) == 0 ||
1290 		    decode_attcred(&buf, &len, cose_alg, attcred) < 0)
1291 			return (-1);
1292 	}
1293 
1294 	if (authdata_ext != NULL) {
1295 		if ((authdata->flags & CTAP_AUTHDATA_EXT_DATA) != 0 &&
1296 		    decode_extensions(&buf, &len, authdata_ext) < 0)
1297 			return (-1);
1298 	}
1299 
1300 	/* XXX we should probably ensure that len == 0 at this point */
1301 
1302 	return (FIDO_OK);
1303 }
1304 
1305 int
1306 cbor_decode_assert_authdata(const cbor_item_t *item, fido_blob_t *authdata_cbor,
1307     fido_authdata_t *authdata, int *authdata_ext, fido_blob_t *hmac_secret_enc)
1308 {
1309 	const unsigned char	*buf = NULL;
1310 	size_t			 len;
1311 	size_t			 alloc_len;
1312 
1313 	if (cbor_isa_bytestring(item) == false ||
1314 	    cbor_bytestring_is_definite(item) == false) {
1315 		fido_log_debug("%s: cbor type", __func__);
1316 		return (-1);
1317 	}
1318 
1319 	if (authdata_cbor->ptr != NULL ||
1320 	    (authdata_cbor->len = cbor_serialize_alloc(item,
1321 	    &authdata_cbor->ptr, &alloc_len)) == 0) {
1322 		fido_log_debug("%s: cbor_serialize_alloc", __func__);
1323 		return (-1);
1324 	}
1325 
1326 	buf = cbor_bytestring_handle(item);
1327 	len = cbor_bytestring_length(item);
1328 
1329 	fido_log_debug("%s: buf=%p, len=%zu", __func__, (const void *)buf, len);
1330 
1331 	if (fido_buf_read(&buf, &len, authdata, sizeof(*authdata)) < 0) {
1332 		fido_log_debug("%s: fido_buf_read", __func__);
1333 		return (-1);
1334 	}
1335 
1336 	authdata->sigcount = be32toh(authdata->sigcount);
1337 
1338 	*authdata_ext = 0;
1339 	if ((authdata->flags & CTAP_AUTHDATA_EXT_DATA) != 0) {
1340 		/* XXX semantic leap: extensions -> hmac_secret */
1341 		if (decode_hmac_secret(&buf, &len, hmac_secret_enc) < 0) {
1342 			fido_log_debug("%s: decode_hmac_secret", __func__);
1343 			return (-1);
1344 		}
1345 		*authdata_ext = FIDO_EXT_HMAC_SECRET;
1346 	}
1347 
1348 	/* XXX we should probably ensure that len == 0 at this point */
1349 
1350 	return (FIDO_OK);
1351 }
1352 
1353 static int
1354 decode_x5c(const cbor_item_t *item, void *arg)
1355 {
1356 	fido_blob_t *x5c = arg;
1357 
1358 	if (x5c->len)
1359 		return (0); /* ignore */
1360 
1361 	return (cbor_bytestring_copy(item, &x5c->ptr, &x5c->len));
1362 }
1363 
1364 static int
1365 decode_attstmt_entry(const cbor_item_t *key, const cbor_item_t *val, void *arg)
1366 {
1367 	fido_attstmt_t	*attstmt = arg;
1368 	char		*name = NULL;
1369 	int		 ok = -1;
1370 
1371 	if (cbor_string_copy(key, &name) < 0) {
1372 		fido_log_debug("%s: cbor type", __func__);
1373 		ok = 0; /* ignore */
1374 		goto out;
1375 	}
1376 
1377 	if (!strcmp(name, "alg")) {
1378 		if (cbor_isa_negint(val) == false ||
1379 		    cbor_int_get_width(val) != CBOR_INT_8 ||
1380 		    cbor_get_uint8(val) != -COSE_ES256 - 1) {
1381 			fido_log_debug("%s: alg", __func__);
1382 			goto out;
1383 		}
1384 	} else if (!strcmp(name, "sig")) {
1385 		if (cbor_bytestring_copy(val, &attstmt->sig.ptr,
1386 		    &attstmt->sig.len) < 0) {
1387 			fido_log_debug("%s: sig", __func__);
1388 			goto out;
1389 		}
1390 	} else if (!strcmp(name, "x5c")) {
1391 		if (cbor_isa_array(val) == false ||
1392 		    cbor_array_is_definite(val) == false ||
1393 		    cbor_array_iter(val, &attstmt->x5c, decode_x5c) < 0) {
1394 			fido_log_debug("%s: x5c", __func__);
1395 			goto out;
1396 		}
1397 	}
1398 
1399 	ok = 0;
1400 out:
1401 	free(name);
1402 
1403 	return (ok);
1404 }
1405 
1406 int
1407 cbor_decode_attstmt(const cbor_item_t *item, fido_attstmt_t *attstmt)
1408 {
1409 	if (cbor_isa_map(item) == false ||
1410 	    cbor_map_is_definite(item) == false ||
1411 	    cbor_map_iter(item, attstmt, decode_attstmt_entry) < 0) {
1412 		fido_log_debug("%s: cbor type", __func__);
1413 		return (-1);
1414 	}
1415 
1416 	return (0);
1417 }
1418 
1419 int
1420 cbor_decode_uint64(const cbor_item_t *item, uint64_t *n)
1421 {
1422 	if (cbor_isa_uint(item) == false) {
1423 		fido_log_debug("%s: cbor type", __func__);
1424 		return (-1);
1425 	}
1426 
1427 	*n = cbor_get_int(item);
1428 
1429 	return (0);
1430 }
1431 
1432 static int
1433 decode_cred_id_entry(const cbor_item_t *key, const cbor_item_t *val, void *arg)
1434 {
1435 	fido_blob_t	*id = arg;
1436 	char		*name = NULL;
1437 	int		 ok = -1;
1438 
1439 	if (cbor_string_copy(key, &name) < 0) {
1440 		fido_log_debug("%s: cbor type", __func__);
1441 		ok = 0; /* ignore */
1442 		goto out;
1443 	}
1444 
1445 	if (!strcmp(name, "id"))
1446 		if (cbor_bytestring_copy(val, &id->ptr, &id->len) < 0) {
1447 			fido_log_debug("%s: cbor_bytestring_copy", __func__);
1448 			goto out;
1449 		}
1450 
1451 	ok = 0;
1452 out:
1453 	free(name);
1454 
1455 	return (ok);
1456 }
1457 
1458 int
1459 cbor_decode_cred_id(const cbor_item_t *item, fido_blob_t *id)
1460 {
1461 	if (cbor_isa_map(item) == false ||
1462 	    cbor_map_is_definite(item) == false ||
1463 	    cbor_map_iter(item, id, decode_cred_id_entry) < 0) {
1464 		fido_log_debug("%s: cbor type", __func__);
1465 		return (-1);
1466 	}
1467 
1468 	return (0);
1469 }
1470 
1471 static int
1472 decode_user_entry(const cbor_item_t *key, const cbor_item_t *val, void *arg)
1473 {
1474 	fido_user_t	*user = arg;
1475 	char		*name = NULL;
1476 	int		 ok = -1;
1477 
1478 	if (cbor_string_copy(key, &name) < 0) {
1479 		fido_log_debug("%s: cbor type", __func__);
1480 		ok = 0; /* ignore */
1481 		goto out;
1482 	}
1483 
1484 	if (!strcmp(name, "icon")) {
1485 		if (cbor_string_copy(val, &user->icon) < 0) {
1486 			fido_log_debug("%s: icon", __func__);
1487 			goto out;
1488 		}
1489 	} else if (!strcmp(name, "name")) {
1490 		if (cbor_string_copy(val, &user->name) < 0) {
1491 			fido_log_debug("%s: name", __func__);
1492 			goto out;
1493 		}
1494 	} else if (!strcmp(name, "displayName")) {
1495 		if (cbor_string_copy(val, &user->display_name) < 0) {
1496 			fido_log_debug("%s: display_name", __func__);
1497 			goto out;
1498 		}
1499 	} else if (!strcmp(name, "id")) {
1500 		if (cbor_bytestring_copy(val, &user->id.ptr, &user->id.len) < 0) {
1501 			fido_log_debug("%s: id", __func__);
1502 			goto out;
1503 		}
1504 	}
1505 
1506 	ok = 0;
1507 out:
1508 	free(name);
1509 
1510 	return (ok);
1511 }
1512 
1513 int
1514 cbor_decode_user(const cbor_item_t *item, fido_user_t *user)
1515 {
1516 	if (cbor_isa_map(item) == false ||
1517 	    cbor_map_is_definite(item) == false ||
1518 	    cbor_map_iter(item, user, decode_user_entry) < 0) {
1519 		fido_log_debug("%s: cbor type", __func__);
1520 		return (-1);
1521 	}
1522 
1523 	return (0);
1524 }
1525 
1526 static int
1527 decode_rp_entity_entry(const cbor_item_t *key, const cbor_item_t *val,
1528     void *arg)
1529 {
1530 	fido_rp_t	*rp = arg;
1531 	char		*name = NULL;
1532 	int		 ok = -1;
1533 
1534 	if (cbor_string_copy(key, &name) < 0) {
1535 		fido_log_debug("%s: cbor type", __func__);
1536 		ok = 0; /* ignore */
1537 		goto out;
1538 	}
1539 
1540 	if (!strcmp(name, "id")) {
1541 		if (cbor_string_copy(val, &rp->id) < 0) {
1542 			fido_log_debug("%s: id", __func__);
1543 			goto out;
1544 		}
1545 	} else if (!strcmp(name, "name")) {
1546 		if (cbor_string_copy(val, &rp->name) < 0) {
1547 			fido_log_debug("%s: name", __func__);
1548 			goto out;
1549 		}
1550 	}
1551 
1552 	ok = 0;
1553 out:
1554 	free(name);
1555 
1556 	return (ok);
1557 }
1558 
1559 int
1560 cbor_decode_rp_entity(const cbor_item_t *item, fido_rp_t *rp)
1561 {
1562 	if (cbor_isa_map(item) == false ||
1563 	    cbor_map_is_definite(item) == false ||
1564 	    cbor_map_iter(item, rp, decode_rp_entity_entry) < 0) {
1565 		fido_log_debug("%s: cbor type", __func__);
1566 		return (-1);
1567 	}
1568 
1569 	return (0);
1570 }
1571