xref: /openbsd-src/lib/libfido2/src/authkey.c (revision ab19a69ebe1d1275c01611de862453c36b3d15b9)
1d75efeb7Sdjm /*
2d75efeb7Sdjm  * Copyright (c) 2018 Yubico AB. All rights reserved.
3d75efeb7Sdjm  * Use of this source code is governed by a BSD-style
4d75efeb7Sdjm  * license that can be found in the LICENSE file.
5d75efeb7Sdjm  */
6d75efeb7Sdjm 
7d75efeb7Sdjm #include "fido.h"
8d75efeb7Sdjm 
9d75efeb7Sdjm static int
parse_authkey(const cbor_item_t * key,const cbor_item_t * val,void * arg)10d75efeb7Sdjm parse_authkey(const cbor_item_t *key, const cbor_item_t *val, void *arg)
11d75efeb7Sdjm {
12d75efeb7Sdjm 	es256_pk_t *authkey = arg;
13d75efeb7Sdjm 
14d75efeb7Sdjm 	if (cbor_isa_uint(key) == false ||
15d75efeb7Sdjm 	    cbor_int_get_width(key) != CBOR_INT_8 ||
16d75efeb7Sdjm 	    cbor_get_uint8(key) != 1) {
1732a20e26Sdjm 		fido_log_debug("%s: cbor type", __func__);
18d75efeb7Sdjm 		return (0); /* ignore */
19d75efeb7Sdjm 	}
20d75efeb7Sdjm 
21d75efeb7Sdjm 	return (es256_pk_decode(val, authkey));
22d75efeb7Sdjm }
23d75efeb7Sdjm 
24d75efeb7Sdjm static int
fido_dev_authkey_tx(fido_dev_t * dev,int * ms)25*ab19a69eSdjm fido_dev_authkey_tx(fido_dev_t *dev, int *ms)
26d75efeb7Sdjm {
27d75efeb7Sdjm 	fido_blob_t	 f;
28d75efeb7Sdjm 	cbor_item_t	*argv[2];
29d75efeb7Sdjm 	int		 r;
30d75efeb7Sdjm 
3132a20e26Sdjm 	fido_log_debug("%s: dev=%p", __func__, (void *)dev);
32d75efeb7Sdjm 
33d75efeb7Sdjm 	memset(&f, 0, sizeof(f));
34d75efeb7Sdjm 	memset(argv, 0, sizeof(argv));
35d75efeb7Sdjm 
36d75efeb7Sdjm 	/* add command parameters */
37c4a807edSdjm 	if ((argv[0] = cbor_encode_pin_opt(dev)) == NULL ||
38d75efeb7Sdjm 	    (argv[1] = cbor_build_uint8(2)) == NULL) {
3932a20e26Sdjm 		fido_log_debug("%s: cbor_build", __func__);
40d75efeb7Sdjm 		r = FIDO_ERR_INTERNAL;
41d75efeb7Sdjm 		goto fail;
42d75efeb7Sdjm 	}
43d75efeb7Sdjm 
44d75efeb7Sdjm 	/* frame and transmit */
4532a20e26Sdjm 	if (cbor_build_frame(CTAP_CBOR_CLIENT_PIN, argv, nitems(argv),
46*ab19a69eSdjm 	    &f) < 0 || fido_tx(dev, CTAP_CMD_CBOR, f.ptr, f.len, ms) < 0) {
4732a20e26Sdjm 		fido_log_debug("%s: fido_tx", __func__);
48d75efeb7Sdjm 		r = FIDO_ERR_TX;
49d75efeb7Sdjm 		goto fail;
50d75efeb7Sdjm 	}
51d75efeb7Sdjm 
52d75efeb7Sdjm 	r = FIDO_OK;
53d75efeb7Sdjm fail:
54d75efeb7Sdjm 	cbor_vector_free(argv, nitems(argv));
55d75efeb7Sdjm 	free(f.ptr);
56d75efeb7Sdjm 
57d75efeb7Sdjm 	return (r);
58d75efeb7Sdjm }
59d75efeb7Sdjm 
60d75efeb7Sdjm static int
fido_dev_authkey_rx(fido_dev_t * dev,es256_pk_t * authkey,int * ms)61*ab19a69eSdjm fido_dev_authkey_rx(fido_dev_t *dev, es256_pk_t *authkey, int *ms)
62d75efeb7Sdjm {
6332a20e26Sdjm 	unsigned char	reply[FIDO_MAXMSG];
64d75efeb7Sdjm 	int		reply_len;
65d75efeb7Sdjm 
6632a20e26Sdjm 	fido_log_debug("%s: dev=%p, authkey=%p, ms=%d", __func__, (void *)dev,
67*ab19a69eSdjm 	    (void *)authkey, *ms);
68d75efeb7Sdjm 
69d75efeb7Sdjm 	memset(authkey, 0, sizeof(*authkey));
70d75efeb7Sdjm 
7132a20e26Sdjm 	if ((reply_len = fido_rx(dev, CTAP_CMD_CBOR, &reply, sizeof(reply),
7232a20e26Sdjm 	    ms)) < 0) {
7332a20e26Sdjm 		fido_log_debug("%s: fido_rx", __func__);
74d75efeb7Sdjm 		return (FIDO_ERR_RX);
75d75efeb7Sdjm 	}
76d75efeb7Sdjm 
7732a20e26Sdjm 	return (cbor_parse_reply(reply, (size_t)reply_len, authkey,
78d75efeb7Sdjm 	    parse_authkey));
79d75efeb7Sdjm }
80d75efeb7Sdjm 
81d75efeb7Sdjm static int
fido_dev_authkey_wait(fido_dev_t * dev,es256_pk_t * authkey,int * ms)82*ab19a69eSdjm fido_dev_authkey_wait(fido_dev_t *dev, es256_pk_t *authkey, int *ms)
83d75efeb7Sdjm {
84d75efeb7Sdjm 	int r;
85d75efeb7Sdjm 
86*ab19a69eSdjm 	if ((r = fido_dev_authkey_tx(dev, ms)) != FIDO_OK ||
87d75efeb7Sdjm 	    (r = fido_dev_authkey_rx(dev, authkey, ms)) != FIDO_OK)
88d75efeb7Sdjm 		return (r);
89d75efeb7Sdjm 
90d75efeb7Sdjm 	return (FIDO_OK);
91d75efeb7Sdjm }
92d75efeb7Sdjm 
93d75efeb7Sdjm int
fido_dev_authkey(fido_dev_t * dev,es256_pk_t * authkey,int * ms)94*ab19a69eSdjm fido_dev_authkey(fido_dev_t *dev, es256_pk_t *authkey, int *ms)
95d75efeb7Sdjm {
96*ab19a69eSdjm 	return (fido_dev_authkey_wait(dev, authkey, ms));
97d75efeb7Sdjm }
98