xref: /freebsd-src/contrib/libfido2/src/authkey.c (revision 2ccfa855b2fc331819953e3de1b1c15ce5b95a7e)
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
parse_authkey(const cbor_item_t * key,const cbor_item_t * val,void * arg)110afa8e06SEd Maste parse_authkey(const cbor_item_t *key, const cbor_item_t *val, void *arg)
120afa8e06SEd Maste {
130afa8e06SEd Maste 	es256_pk_t *authkey = arg;
140afa8e06SEd Maste 
150afa8e06SEd Maste 	if (cbor_isa_uint(key) == false ||
160afa8e06SEd Maste 	    cbor_int_get_width(key) != CBOR_INT_8 ||
170afa8e06SEd Maste 	    cbor_get_uint8(key) != 1) {
180afa8e06SEd Maste 		fido_log_debug("%s: cbor type", __func__);
190afa8e06SEd Maste 		return (0); /* ignore */
200afa8e06SEd Maste 	}
210afa8e06SEd Maste 
220afa8e06SEd Maste 	return (es256_pk_decode(val, authkey));
230afa8e06SEd Maste }
240afa8e06SEd Maste 
250afa8e06SEd Maste static int
fido_dev_authkey_tx(fido_dev_t * dev,int * ms)26f540a430SEd Maste fido_dev_authkey_tx(fido_dev_t *dev, int *ms)
270afa8e06SEd Maste {
280afa8e06SEd Maste 	fido_blob_t	 f;
290afa8e06SEd Maste 	cbor_item_t	*argv[2];
300afa8e06SEd Maste 	int		 r;
310afa8e06SEd Maste 
320afa8e06SEd Maste 	fido_log_debug("%s: dev=%p", __func__, (void *)dev);
330afa8e06SEd Maste 
340afa8e06SEd Maste 	memset(&f, 0, sizeof(f));
350afa8e06SEd Maste 	memset(argv, 0, sizeof(argv));
360afa8e06SEd Maste 
370afa8e06SEd Maste 	/* add command parameters */
380afa8e06SEd Maste 	if ((argv[0] = cbor_encode_pin_opt(dev)) == NULL ||
390afa8e06SEd Maste 	    (argv[1] = cbor_build_uint8(2)) == NULL) {
400afa8e06SEd Maste 		fido_log_debug("%s: cbor_build", __func__);
410afa8e06SEd Maste 		r = FIDO_ERR_INTERNAL;
420afa8e06SEd Maste 		goto fail;
430afa8e06SEd Maste 	}
440afa8e06SEd Maste 
450afa8e06SEd Maste 	/* frame and transmit */
460afa8e06SEd Maste 	if (cbor_build_frame(CTAP_CBOR_CLIENT_PIN, argv, nitems(argv),
47f540a430SEd Maste 	    &f) < 0 || fido_tx(dev, CTAP_CMD_CBOR, f.ptr, f.len, ms) < 0) {
480afa8e06SEd Maste 		fido_log_debug("%s: fido_tx", __func__);
490afa8e06SEd Maste 		r = FIDO_ERR_TX;
500afa8e06SEd Maste 		goto fail;
510afa8e06SEd Maste 	}
520afa8e06SEd Maste 
530afa8e06SEd Maste 	r = FIDO_OK;
540afa8e06SEd Maste fail:
550afa8e06SEd Maste 	cbor_vector_free(argv, nitems(argv));
560afa8e06SEd Maste 	free(f.ptr);
570afa8e06SEd Maste 
580afa8e06SEd Maste 	return (r);
590afa8e06SEd Maste }
600afa8e06SEd Maste 
610afa8e06SEd Maste static int
fido_dev_authkey_rx(fido_dev_t * dev,es256_pk_t * authkey,int * ms)62f540a430SEd Maste fido_dev_authkey_rx(fido_dev_t *dev, es256_pk_t *authkey, int *ms)
630afa8e06SEd Maste {
64*2ccfa855SEd Maste 	unsigned char	*msg;
65*2ccfa855SEd Maste 	int		 msglen;
66*2ccfa855SEd Maste 	int		 r;
670afa8e06SEd Maste 
680afa8e06SEd Maste 	fido_log_debug("%s: dev=%p, authkey=%p, ms=%d", __func__, (void *)dev,
69f540a430SEd Maste 	    (void *)authkey, *ms);
700afa8e06SEd Maste 
710afa8e06SEd Maste 	memset(authkey, 0, sizeof(*authkey));
720afa8e06SEd Maste 
73*2ccfa855SEd Maste 	if ((msg = malloc(FIDO_MAXMSG)) == NULL) {
74*2ccfa855SEd Maste 		r = FIDO_ERR_INTERNAL;
75*2ccfa855SEd Maste 		goto out;
760afa8e06SEd Maste 	}
770afa8e06SEd Maste 
78*2ccfa855SEd Maste 	if ((msglen = fido_rx(dev, CTAP_CMD_CBOR, msg, FIDO_MAXMSG, ms)) < 0) {
79*2ccfa855SEd Maste 		fido_log_debug("%s: fido_rx", __func__);
80*2ccfa855SEd Maste 		r = FIDO_ERR_RX;
81*2ccfa855SEd Maste 		goto out;
82*2ccfa855SEd Maste 	}
83*2ccfa855SEd Maste 
84*2ccfa855SEd Maste 	r = cbor_parse_reply(msg, (size_t)msglen, authkey, parse_authkey);
85*2ccfa855SEd Maste out:
86*2ccfa855SEd Maste 	freezero(msg, FIDO_MAXMSG);
87*2ccfa855SEd Maste 
88*2ccfa855SEd Maste 	return (r);
890afa8e06SEd Maste }
900afa8e06SEd Maste 
910afa8e06SEd Maste static int
fido_dev_authkey_wait(fido_dev_t * dev,es256_pk_t * authkey,int * ms)92f540a430SEd Maste fido_dev_authkey_wait(fido_dev_t *dev, es256_pk_t *authkey, int *ms)
930afa8e06SEd Maste {
940afa8e06SEd Maste 	int r;
950afa8e06SEd Maste 
96f540a430SEd Maste 	if ((r = fido_dev_authkey_tx(dev, ms)) != FIDO_OK ||
970afa8e06SEd Maste 	    (r = fido_dev_authkey_rx(dev, authkey, ms)) != FIDO_OK)
980afa8e06SEd Maste 		return (r);
990afa8e06SEd Maste 
1000afa8e06SEd Maste 	return (FIDO_OK);
1010afa8e06SEd Maste }
1020afa8e06SEd Maste 
1030afa8e06SEd Maste int
fido_dev_authkey(fido_dev_t * dev,es256_pk_t * authkey,int * ms)104f540a430SEd Maste fido_dev_authkey(fido_dev_t *dev, es256_pk_t *authkey, int *ms)
1050afa8e06SEd Maste {
106f540a430SEd Maste 	return (fido_dev_authkey_wait(dev, authkey, ms));
1070afa8e06SEd Maste }
108