xref: /openbsd/usr.bin/ssh/sk-usbhid.c (revision 097a140d)
1 /* $OpenBSD: sk-usbhid.c,v 1.29 2021/02/18 02:15:07 djm Exp $ */
2 /*
3  * Copyright (c) 2019 Markus Friedl
4  * Copyright (c) 2020 Pedro Martelletto
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include <stdint.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <stdio.h>
23 #include <stddef.h>
24 #include <stdarg.h>
25 #include <sha2.h>
26 #include <time.h>
27 
28 #ifdef WITH_OPENSSL
29 #include <openssl/opensslv.h>
30 #include <openssl/crypto.h>
31 #include <openssl/bn.h>
32 #include <openssl/ec.h>
33 #include <openssl/ecdsa.h>
34 #include <openssl/evp.h>
35 #endif /* WITH_OPENSSL */
36 
37 #include <fido.h>
38 #include <fido/credman.h>
39 
40 #ifndef SK_STANDALONE
41 # include "log.h"
42 # include "xmalloc.h"
43 # include "misc.h"
44 /*
45  * If building as part of OpenSSH, then rename exported functions.
46  * This must be done before including sk-api.h.
47  */
48 # define sk_api_version		ssh_sk_api_version
49 # define sk_enroll		ssh_sk_enroll
50 # define sk_sign		ssh_sk_sign
51 # define sk_load_resident_keys	ssh_sk_load_resident_keys
52 #endif /* !SK_STANDALONE */
53 
54 #include "sk-api.h"
55 
56 /* #define SK_DEBUG 1 */
57 
58 #ifdef SK_DEBUG
59 #define SSH_FIDO_INIT_ARG	FIDO_DEBUG
60 #else
61 #define SSH_FIDO_INIT_ARG	0
62 #endif
63 
64 #define MAX_FIDO_DEVICES	8
65 #define FIDO_POLL_MS		50
66 #define SELECT_MS		15000
67 #define POLL_SLEEP_NS		200000000
68 
69 /* Compatibility with OpenSSH 1.0.x */
70 #if (OPENSSL_VERSION_NUMBER < 0x10100000L)
71 #define ECDSA_SIG_get0(sig, pr, ps) \
72 	do { \
73 		(*pr) = sig->r; \
74 		(*ps) = sig->s; \
75 	} while (0)
76 #endif
77 
78 struct sk_usbhid {
79 	fido_dev_t *dev;
80 	char *path;
81 };
82 
83 /* Return the version of the middleware API */
84 uint32_t sk_api_version(void);
85 
86 /* Enroll a U2F key (private key generation) */
87 int sk_enroll(uint32_t alg, const uint8_t *challenge, size_t challenge_len,
88     const char *application, uint8_t flags, const char *pin,
89     struct sk_option **options, struct sk_enroll_response **enroll_response);
90 
91 /* Sign a challenge */
92 int sk_sign(uint32_t alg, const uint8_t *data, size_t data_len,
93     const char *application, const uint8_t *key_handle, size_t key_handle_len,
94     uint8_t flags, const char *pin, struct sk_option **options,
95     struct sk_sign_response **sign_response);
96 
97 /* Load resident keys */
98 int sk_load_resident_keys(const char *pin, struct sk_option **options,
99     struct sk_resident_key ***rks, size_t *nrks);
100 
101 static void skdebug(const char *func, const char *fmt, ...)
102     __attribute__((__format__ (printf, 2, 3)));
103 
104 static void
105 skdebug(const char *func, const char *fmt, ...)
106 {
107 #if !defined(SK_STANDALONE)
108 	char *msg;
109 	va_list ap;
110 
111 	va_start(ap, fmt);
112 	xvasprintf(&msg, fmt, ap);
113 	va_end(ap);
114 	debug("%s: %s", func, msg);
115 	free(msg);
116 #elif defined(SK_DEBUG)
117 	va_list ap;
118 
119 	va_start(ap, fmt);
120 	fprintf(stderr, "%s: ", func);
121 	vfprintf(stderr, fmt, ap);
122 	fputc('\n', stderr);
123 	va_end(ap);
124 #else
125 	(void)func; /* XXX */
126 	(void)fmt; /* XXX */
127 #endif
128 }
129 
130 uint32_t
131 sk_api_version(void)
132 {
133 	return SSH_SK_VERSION_MAJOR;
134 }
135 
136 static struct sk_usbhid *
137 sk_open(const char *path)
138 {
139 	struct sk_usbhid *sk;
140 	int r;
141 
142 	if (path == NULL) {
143 		skdebug(__func__, "path == NULL");
144 		return NULL;
145 	}
146 	if ((sk = calloc(1, sizeof(*sk))) == NULL) {
147 		skdebug(__func__, "calloc sk failed");
148 		return NULL;
149 	}
150 	if ((sk->path = strdup(path)) == NULL) {
151 		skdebug(__func__, "strdup path failed");
152 		free(sk);
153 		return NULL;
154 	}
155 	if ((sk->dev = fido_dev_new()) == NULL) {
156 		skdebug(__func__, "fido_dev_new failed");
157 		free(sk->path);
158 		free(sk);
159 		return NULL;
160 	}
161 	if ((r = fido_dev_open(sk->dev, sk->path)) != FIDO_OK) {
162 		skdebug(__func__, "fido_dev_open %s failed: %s", sk->path,
163 		    fido_strerr(r));
164 		fido_dev_free(&sk->dev);
165 		free(sk->path);
166 		free(sk);
167 		return NULL;
168 	}
169 	return sk;
170 }
171 
172 static void
173 sk_close(struct sk_usbhid *sk)
174 {
175 	if (sk == NULL)
176 		return;
177 	fido_dev_cancel(sk->dev); /* cancel any pending operation */
178 	fido_dev_close(sk->dev);
179 	fido_dev_free(&sk->dev);
180 	free(sk->path);
181 	free(sk);
182 }
183 
184 static struct sk_usbhid **
185 sk_openv(const fido_dev_info_t *devlist, size_t ndevs, size_t *nopen)
186 {
187 	const fido_dev_info_t *di;
188 	struct sk_usbhid **skv;
189 	size_t i;
190 
191 	*nopen = 0;
192 	if ((skv = calloc(ndevs, sizeof(*skv))) == NULL) {
193 		skdebug(__func__, "calloc skv failed");
194 		return NULL;
195 	}
196 	for (i = 0; i < ndevs; i++) {
197 		if ((di = fido_dev_info_ptr(devlist, i)) == NULL)
198 			skdebug(__func__, "fido_dev_info_ptr failed");
199 		else if ((skv[*nopen] = sk_open(fido_dev_info_path(di))) == NULL)
200 			skdebug(__func__, "sk_open failed");
201 		else
202 			(*nopen)++;
203 	}
204 	if (*nopen == 0) {
205 		for (i = 0; i < ndevs; i++)
206 			sk_close(skv[i]);
207 		free(skv);
208 		skv = NULL;
209 	}
210 
211 	return skv;
212 }
213 
214 static void
215 sk_closev(struct sk_usbhid **skv, size_t nsk)
216 {
217 	size_t i;
218 
219 	for (i = 0; i < nsk; i++)
220 		sk_close(skv[i]);
221 	free(skv);
222 }
223 
224 static int
225 sk_touch_begin(struct sk_usbhid **skv, size_t nsk)
226 {
227 	size_t i, ok = 0;
228 	int r;
229 
230 	for (i = 0; i < nsk; i++)
231 		if ((r = fido_dev_get_touch_begin(skv[i]->dev)) != FIDO_OK)
232 			skdebug(__func__, "fido_dev_get_touch_begin %s failed:"
233 			    " %s", skv[i]->path, fido_strerr(r));
234 		else
235 			ok++;
236 
237 	return ok ? 0 : -1;
238 }
239 
240 static int
241 sk_touch_poll(struct sk_usbhid **skv, size_t nsk, int *touch, size_t *idx)
242 {
243 	struct timespec ts_pause;
244 	size_t npoll, i;
245 	int r;
246 
247 	ts_pause.tv_sec = 0;
248 	ts_pause.tv_nsec = POLL_SLEEP_NS;
249 	nanosleep(&ts_pause, NULL);
250 	npoll = nsk;
251 	for (i = 0; i < nsk; i++) {
252 		if (skv[i] == NULL)
253 			continue; /* device discarded */
254 		skdebug(__func__, "polling %s", skv[i]->path);
255 		if ((r = fido_dev_get_touch_status(skv[i]->dev, touch,
256 		    FIDO_POLL_MS)) != FIDO_OK) {
257 			skdebug(__func__, "fido_dev_get_touch_status %s: %s",
258 			    skv[i]->path, fido_strerr(r));
259 			sk_close(skv[i]); /* discard device */
260 			skv[i] = NULL;
261 			if (--npoll == 0) {
262 				skdebug(__func__, "no device left to poll");
263 				return -1;
264 			}
265 		} else if (*touch) {
266 			*idx = i;
267 			return 0;
268 		}
269 	}
270 	*touch = 0;
271 	return 0;
272 }
273 
274 /* Calculate SHA256(m) */
275 static int
276 sha256_mem(const void *m, size_t mlen, u_char *d, size_t dlen)
277 {
278 #ifdef WITH_OPENSSL
279 	u_int mdlen;
280 #endif
281 
282 	if (dlen != 32)
283 		return -1;
284 #ifdef WITH_OPENSSL
285 	mdlen = dlen;
286 	if (!EVP_Digest(m, mlen, d, &mdlen, EVP_sha256(), NULL))
287 		return -1;
288 #else
289 	SHA256Data(m, mlen, d);
290 #endif
291 	return 0;
292 }
293 
294 /* Check if the specified key handle exists on a given sk. */
295 static int
296 sk_try(const struct sk_usbhid *sk, const char *application,
297     const uint8_t *key_handle, size_t key_handle_len)
298 {
299 	fido_assert_t *assert = NULL;
300 	/* generate an invalid signature on FIDO2 tokens */
301 	const char *data = "";
302 	uint8_t message[32];
303 	int r = FIDO_ERR_INTERNAL;
304 
305 	if (sha256_mem(data, strlen(data), message, sizeof(message)) != 0) {
306 		skdebug(__func__, "hash message failed");
307 		goto out;
308 	}
309 	if ((assert = fido_assert_new()) == NULL) {
310 		skdebug(__func__, "fido_assert_new failed");
311 		goto out;
312 	}
313 	if ((r = fido_assert_set_clientdata_hash(assert, message,
314 	    sizeof(message))) != FIDO_OK) {
315 		skdebug(__func__, "fido_assert_set_clientdata_hash: %s",
316 		    fido_strerr(r));
317 		goto out;
318 	}
319 	if ((r = fido_assert_set_rp(assert, application)) != FIDO_OK) {
320 		skdebug(__func__, "fido_assert_set_rp: %s", fido_strerr(r));
321 		goto out;
322 	}
323 	if ((r = fido_assert_allow_cred(assert, key_handle,
324 	    key_handle_len)) != FIDO_OK) {
325 		skdebug(__func__, "fido_assert_allow_cred: %s", fido_strerr(r));
326 		goto out;
327 	}
328 	if ((r = fido_assert_set_up(assert, FIDO_OPT_FALSE)) != FIDO_OK) {
329 		skdebug(__func__, "fido_assert_up: %s", fido_strerr(r));
330 		goto out;
331 	}
332 	r = fido_dev_get_assert(sk->dev, assert, NULL);
333 	skdebug(__func__, "fido_dev_get_assert: %s", fido_strerr(r));
334 	if (r == FIDO_ERR_USER_PRESENCE_REQUIRED) {
335 		/* U2F tokens may return this */
336 		r = FIDO_OK;
337 	}
338  out:
339 	fido_assert_free(&assert);
340 
341 	return r != FIDO_OK ? -1 : 0;
342 }
343 
344 static struct sk_usbhid *
345 sk_select_by_cred(const fido_dev_info_t *devlist, size_t ndevs,
346     const char *application, const uint8_t *key_handle, size_t key_handle_len)
347 {
348 	struct sk_usbhid **skv, *sk;
349 	size_t skvcnt, i;
350 
351 	if ((skv = sk_openv(devlist, ndevs, &skvcnt)) == NULL) {
352 		skdebug(__func__, "sk_openv failed");
353 		return NULL;
354 	}
355 	if (skvcnt == 1) {
356 		sk = skv[0];
357 		skv[0] = NULL;
358 		goto out;
359 	}
360 	sk = NULL;
361 	for (i = 0; i < skvcnt; i++) {
362 		if (sk_try(skv[i], application, key_handle,
363 		    key_handle_len) == 0) {
364 			sk = skv[i];
365 			skv[i] = NULL;
366 			skdebug(__func__, "found key in %s", sk->path);
367 			break;
368 		}
369 	}
370  out:
371 	sk_closev(skv, skvcnt);
372 	return sk;
373 }
374 
375 static struct sk_usbhid *
376 sk_select_by_touch(const fido_dev_info_t *devlist, size_t ndevs)
377 {
378 	struct sk_usbhid **skv, *sk;
379 	struct timeval tv_start, tv_now, tv_delta;
380 	size_t skvcnt, idx;
381 	int touch, ms_remain;
382 
383 	if ((skv = sk_openv(devlist, ndevs, &skvcnt)) == NULL) {
384 		skdebug(__func__, "sk_openv failed");
385 		return NULL;
386 	}
387 	sk = NULL;
388 	if (skvcnt < 2) {
389 		if (skvcnt == 1) {
390 			/* single candidate */
391 			sk = skv[0];
392 			skv[0] = NULL;
393 		}
394 		goto out;
395 	}
396 	if (sk_touch_begin(skv, skvcnt) == -1) {
397 		skdebug(__func__, "sk_touch_begin failed");
398 		goto out;
399 	}
400 	monotime_tv(&tv_start);
401 	do {
402 		if (sk_touch_poll(skv, skvcnt, &touch, &idx) == -1) {
403 			skdebug(__func__, "sk_touch_poll failed");
404 			goto out;
405 		}
406 		if (touch) {
407 			sk = skv[idx];
408 			skv[idx] = NULL;
409 			goto out;
410 		}
411 		monotime_tv(&tv_now);
412 		timersub(&tv_now, &tv_start, &tv_delta);
413 		ms_remain = SELECT_MS - tv_delta.tv_sec * 1000 -
414 		    tv_delta.tv_usec / 1000;
415 	} while (ms_remain >= FIDO_POLL_MS);
416 	skdebug(__func__, "timeout");
417 out:
418 	sk_closev(skv, skvcnt);
419 	return sk;
420 }
421 
422 static struct sk_usbhid *
423 sk_probe(const char *application, const uint8_t *key_handle,
424     size_t key_handle_len)
425 {
426 	struct sk_usbhid *sk;
427 	fido_dev_info_t *devlist;
428 	size_t ndevs;
429 	int r;
430 
431 	if ((devlist = fido_dev_info_new(MAX_FIDO_DEVICES)) == NULL) {
432 		skdebug(__func__, "fido_dev_info_new failed");
433 		return NULL;
434 	}
435 	if ((r = fido_dev_info_manifest(devlist, MAX_FIDO_DEVICES,
436 	    &ndevs)) != FIDO_OK) {
437 		skdebug(__func__, "fido_dev_info_manifest failed: %s",
438 		    fido_strerr(r));
439 		fido_dev_info_free(&devlist, MAX_FIDO_DEVICES);
440 		return NULL;
441 	}
442 	skdebug(__func__, "%zu device(s) detected", ndevs);
443 	if (ndevs == 0) {
444 		sk = NULL;
445 	} else if (application != NULL && key_handle != NULL) {
446 		skdebug(__func__, "selecting sk by cred");
447 		sk = sk_select_by_cred(devlist, ndevs, application, key_handle,
448 		    key_handle_len);
449 	} else {
450 		skdebug(__func__, "selecting sk by touch");
451 		sk = sk_select_by_touch(devlist, ndevs);
452 	}
453 	fido_dev_info_free(&devlist, MAX_FIDO_DEVICES);
454 	return sk;
455 }
456 
457 #ifdef WITH_OPENSSL
458 /*
459  * The key returned via fido_cred_pubkey_ptr() is in affine coordinates,
460  * but the API expects a SEC1 octet string.
461  */
462 static int
463 pack_public_key_ecdsa(const fido_cred_t *cred,
464     struct sk_enroll_response *response)
465 {
466 	const uint8_t *ptr;
467 	BIGNUM *x = NULL, *y = NULL;
468 	EC_POINT *q = NULL;
469 	EC_GROUP *g = NULL;
470 	int ret = -1;
471 
472 	response->public_key = NULL;
473 	response->public_key_len = 0;
474 
475 	if ((x = BN_new()) == NULL ||
476 	    (y = BN_new()) == NULL ||
477 	    (g = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1)) == NULL ||
478 	    (q = EC_POINT_new(g)) == NULL) {
479 		skdebug(__func__, "libcrypto setup failed");
480 		goto out;
481 	}
482 	if ((ptr = fido_cred_pubkey_ptr(cred)) == NULL) {
483 		skdebug(__func__, "fido_cred_pubkey_ptr failed");
484 		goto out;
485 	}
486 	if (fido_cred_pubkey_len(cred) != 64) {
487 		skdebug(__func__, "bad fido_cred_pubkey_len %zu",
488 		    fido_cred_pubkey_len(cred));
489 		goto out;
490 	}
491 
492 	if (BN_bin2bn(ptr, 32, x) == NULL ||
493 	    BN_bin2bn(ptr + 32, 32, y) == NULL) {
494 		skdebug(__func__, "BN_bin2bn failed");
495 		goto out;
496 	}
497 	if (EC_POINT_set_affine_coordinates_GFp(g, q, x, y, NULL) != 1) {
498 		skdebug(__func__, "EC_POINT_set_affine_coordinates_GFp failed");
499 		goto out;
500 	}
501 	response->public_key_len = EC_POINT_point2oct(g, q,
502 	    POINT_CONVERSION_UNCOMPRESSED, NULL, 0, NULL);
503 	if (response->public_key_len == 0 || response->public_key_len > 2048) {
504 		skdebug(__func__, "bad pubkey length %zu",
505 		    response->public_key_len);
506 		goto out;
507 	}
508 	if ((response->public_key = malloc(response->public_key_len)) == NULL) {
509 		skdebug(__func__, "malloc pubkey failed");
510 		goto out;
511 	}
512 	if (EC_POINT_point2oct(g, q, POINT_CONVERSION_UNCOMPRESSED,
513 	    response->public_key, response->public_key_len, NULL) == 0) {
514 		skdebug(__func__, "EC_POINT_point2oct failed");
515 		goto out;
516 	}
517 	/* success */
518 	ret = 0;
519  out:
520 	if (ret != 0 && response->public_key != NULL) {
521 		memset(response->public_key, 0, response->public_key_len);
522 		free(response->public_key);
523 		response->public_key = NULL;
524 	}
525 	EC_POINT_free(q);
526 	EC_GROUP_free(g);
527 	BN_clear_free(x);
528 	BN_clear_free(y);
529 	return ret;
530 }
531 #endif /* WITH_OPENSSL */
532 
533 static int
534 pack_public_key_ed25519(const fido_cred_t *cred,
535     struct sk_enroll_response *response)
536 {
537 	const uint8_t *ptr;
538 	size_t len;
539 	int ret = -1;
540 
541 	response->public_key = NULL;
542 	response->public_key_len = 0;
543 
544 	if ((len = fido_cred_pubkey_len(cred)) != 32) {
545 		skdebug(__func__, "bad fido_cred_pubkey_len len %zu", len);
546 		goto out;
547 	}
548 	if ((ptr = fido_cred_pubkey_ptr(cred)) == NULL) {
549 		skdebug(__func__, "fido_cred_pubkey_ptr failed");
550 		goto out;
551 	}
552 	response->public_key_len = len;
553 	if ((response->public_key = malloc(response->public_key_len)) == NULL) {
554 		skdebug(__func__, "malloc pubkey failed");
555 		goto out;
556 	}
557 	memcpy(response->public_key, ptr, len);
558 	ret = 0;
559  out:
560 	if (ret != 0)
561 		free(response->public_key);
562 	return ret;
563 }
564 
565 static int
566 pack_public_key(uint32_t alg, const fido_cred_t *cred,
567     struct sk_enroll_response *response)
568 {
569 	switch(alg) {
570 #ifdef WITH_OPENSSL
571 	case SSH_SK_ECDSA:
572 		return pack_public_key_ecdsa(cred, response);
573 #endif /* WITH_OPENSSL */
574 	case SSH_SK_ED25519:
575 		return pack_public_key_ed25519(cred, response);
576 	default:
577 		return -1;
578 	}
579 }
580 
581 static int
582 fidoerr_to_skerr(int fidoerr)
583 {
584 	switch (fidoerr) {
585 	case FIDO_ERR_UNSUPPORTED_OPTION:
586 	case FIDO_ERR_UNSUPPORTED_ALGORITHM:
587 		return SSH_SK_ERR_UNSUPPORTED;
588 	case FIDO_ERR_PIN_REQUIRED:
589 	case FIDO_ERR_PIN_INVALID:
590 		return SSH_SK_ERR_PIN_REQUIRED;
591 	default:
592 		return -1;
593 	}
594 }
595 
596 static int
597 check_enroll_options(struct sk_option **options, char **devicep,
598     uint8_t *user_id, size_t user_id_len)
599 {
600 	size_t i;
601 
602 	if (options == NULL)
603 		return 0;
604 	for (i = 0; options[i] != NULL; i++) {
605 		if (strcmp(options[i]->name, "device") == 0) {
606 			if ((*devicep = strdup(options[i]->value)) == NULL) {
607 				skdebug(__func__, "strdup device failed");
608 				return -1;
609 			}
610 			skdebug(__func__, "requested device %s", *devicep);
611 		} else if (strcmp(options[i]->name, "user") == 0) {
612 			if (strlcpy(user_id, options[i]->value, user_id_len) >=
613 			    user_id_len) {
614 				skdebug(__func__, "user too long");
615 				return -1;
616 			}
617 			skdebug(__func__, "requested user %s",
618 			    (char *)user_id);
619 		} else {
620 			skdebug(__func__, "requested unsupported option %s",
621 			    options[i]->name);
622 			if (options[i]->required) {
623 				skdebug(__func__, "unknown required option");
624 				return -1;
625 			}
626 		}
627 	}
628 	return 0;
629 }
630 
631 int
632 sk_enroll(uint32_t alg, const uint8_t *challenge, size_t challenge_len,
633     const char *application, uint8_t flags, const char *pin,
634     struct sk_option **options, struct sk_enroll_response **enroll_response)
635 {
636 	fido_cred_t *cred = NULL;
637 	const uint8_t *ptr;
638 	uint8_t user_id[32];
639 	struct sk_usbhid *sk = NULL;
640 	struct sk_enroll_response *response = NULL;
641 	size_t len;
642 	int credprot;
643 	int cose_alg;
644 	int ret = SSH_SK_ERR_GENERAL;
645 	int r;
646 	char *device = NULL;
647 
648 	fido_init(SSH_FIDO_INIT_ARG);
649 
650 	if (enroll_response == NULL) {
651 		skdebug(__func__, "enroll_response == NULL");
652 		goto out;
653 	}
654 	*enroll_response = NULL;
655 	memset(user_id, 0, sizeof(user_id));
656 	if (check_enroll_options(options, &device, user_id,
657 	    sizeof(user_id)) != 0)
658 		goto out; /* error already logged */
659 
660 	switch(alg) {
661 #ifdef WITH_OPENSSL
662 	case SSH_SK_ECDSA:
663 		cose_alg = COSE_ES256;
664 		break;
665 #endif /* WITH_OPENSSL */
666 	case SSH_SK_ED25519:
667 		cose_alg = COSE_EDDSA;
668 		break;
669 	default:
670 		skdebug(__func__, "unsupported key type %d", alg);
671 		goto out;
672 	}
673 	if (device != NULL)
674 		sk = sk_open(device);
675 	else
676 		sk = sk_probe(NULL, NULL, 0);
677 	if (sk == NULL) {
678 		skdebug(__func__, "failed to find sk");
679 		goto out;
680 	}
681 	skdebug(__func__, "using device %s", sk->path);
682 	if ((cred = fido_cred_new()) == NULL) {
683 		skdebug(__func__, "fido_cred_new failed");
684 		goto out;
685 	}
686 	if ((r = fido_cred_set_type(cred, cose_alg)) != FIDO_OK) {
687 		skdebug(__func__, "fido_cred_set_type: %s", fido_strerr(r));
688 		goto out;
689 	}
690 	if ((r = fido_cred_set_clientdata_hash(cred, challenge,
691 	    challenge_len)) != FIDO_OK) {
692 		skdebug(__func__, "fido_cred_set_clientdata_hash: %s",
693 		    fido_strerr(r));
694 		goto out;
695 	}
696 	if ((r = fido_cred_set_rk(cred, (flags & SSH_SK_RESIDENT_KEY) != 0 ?
697 	    FIDO_OPT_TRUE : FIDO_OPT_OMIT)) != FIDO_OK) {
698 		skdebug(__func__, "fido_cred_set_rk: %s", fido_strerr(r));
699 		goto out;
700 	}
701 	if ((r = fido_cred_set_user(cred, user_id, sizeof(user_id),
702 	    "openssh", "openssh", NULL)) != FIDO_OK) {
703 		skdebug(__func__, "fido_cred_set_user: %s", fido_strerr(r));
704 		goto out;
705 	}
706 	if ((r = fido_cred_set_rp(cred, application, NULL)) != FIDO_OK) {
707 		skdebug(__func__, "fido_cred_set_rp: %s", fido_strerr(r));
708 		goto out;
709 	}
710 	if ((flags & (SSH_SK_RESIDENT_KEY|SSH_SK_USER_VERIFICATION_REQD)) != 0) {
711 		if (!fido_dev_supports_cred_prot(sk->dev)) {
712 			skdebug(__func__, "%s does not support credprot, "
713 			    "refusing to create unprotected "
714 			    "resident/verify-required key", sk->path);
715 			ret = SSH_SK_ERR_UNSUPPORTED;
716 			goto out;
717 		}
718 		if ((flags & SSH_SK_USER_VERIFICATION_REQD))
719 			credprot = FIDO_CRED_PROT_UV_REQUIRED;
720 		else
721 			credprot = FIDO_CRED_PROT_UV_OPTIONAL_WITH_ID;
722 
723 		if ((r = fido_cred_set_prot(cred, credprot)) != FIDO_OK) {
724 			skdebug(__func__, "fido_cred_set_prot: %s",
725 			    fido_strerr(r));
726 			ret = fidoerr_to_skerr(r);
727 			goto out;
728 		}
729 	}
730 	if ((r = fido_dev_make_cred(sk->dev, cred, pin)) != FIDO_OK) {
731 		skdebug(__func__, "fido_dev_make_cred: %s", fido_strerr(r));
732 		ret = fidoerr_to_skerr(r);
733 		goto out;
734 	}
735 	if (fido_cred_x5c_ptr(cred) != NULL) {
736 		if ((r = fido_cred_verify(cred)) != FIDO_OK) {
737 			skdebug(__func__, "fido_cred_verify: %s",
738 			    fido_strerr(r));
739 			goto out;
740 		}
741 	} else {
742 		skdebug(__func__, "self-attested credential");
743 		if ((r = fido_cred_verify_self(cred)) != FIDO_OK) {
744 			skdebug(__func__, "fido_cred_verify_self: %s",
745 			    fido_strerr(r));
746 			goto out;
747 		}
748 	}
749 	if ((response = calloc(1, sizeof(*response))) == NULL) {
750 		skdebug(__func__, "calloc response failed");
751 		goto out;
752 	}
753 	if (pack_public_key(alg, cred, response) != 0) {
754 		skdebug(__func__, "pack_public_key failed");
755 		goto out;
756 	}
757 	if ((ptr = fido_cred_id_ptr(cred)) != NULL) {
758 		len = fido_cred_id_len(cred);
759 		if ((response->key_handle = calloc(1, len)) == NULL) {
760 			skdebug(__func__, "calloc key handle failed");
761 			goto out;
762 		}
763 		memcpy(response->key_handle, ptr, len);
764 		response->key_handle_len = len;
765 	}
766 	if ((ptr = fido_cred_sig_ptr(cred)) != NULL) {
767 		len = fido_cred_sig_len(cred);
768 		if ((response->signature = calloc(1, len)) == NULL) {
769 			skdebug(__func__, "calloc signature failed");
770 			goto out;
771 		}
772 		memcpy(response->signature, ptr, len);
773 		response->signature_len = len;
774 	}
775 	if ((ptr = fido_cred_x5c_ptr(cred)) != NULL) {
776 		len = fido_cred_x5c_len(cred);
777 		skdebug(__func__, "attestation cert len=%zu", len);
778 		if ((response->attestation_cert = calloc(1, len)) == NULL) {
779 			skdebug(__func__, "calloc attestation cert failed");
780 			goto out;
781 		}
782 		memcpy(response->attestation_cert, ptr, len);
783 		response->attestation_cert_len = len;
784 	}
785 	if ((ptr = fido_cred_authdata_ptr(cred)) != NULL) {
786 		len = fido_cred_authdata_len(cred);
787 		skdebug(__func__, "authdata len=%zu", len);
788 		if ((response->authdata = calloc(1, len)) == NULL) {
789 			skdebug(__func__, "calloc authdata failed");
790 			goto out;
791 		}
792 		memcpy(response->authdata, ptr, len);
793 		response->authdata_len = len;
794 	}
795 	*enroll_response = response;
796 	response = NULL;
797 	ret = 0;
798  out:
799 	free(device);
800 	if (response != NULL) {
801 		free(response->public_key);
802 		free(response->key_handle);
803 		free(response->signature);
804 		free(response->attestation_cert);
805 		free(response->authdata);
806 		free(response);
807 	}
808 	sk_close(sk);
809 	fido_cred_free(&cred);
810 	return ret;
811 }
812 
813 #ifdef WITH_OPENSSL
814 static int
815 pack_sig_ecdsa(fido_assert_t *assert, struct sk_sign_response *response)
816 {
817 	ECDSA_SIG *sig = NULL;
818 	const BIGNUM *sig_r, *sig_s;
819 	const unsigned char *cp;
820 	size_t sig_len;
821 	int ret = -1;
822 
823 	cp = fido_assert_sig_ptr(assert, 0);
824 	sig_len = fido_assert_sig_len(assert, 0);
825 	if ((sig = d2i_ECDSA_SIG(NULL, &cp, sig_len)) == NULL) {
826 		skdebug(__func__, "d2i_ECDSA_SIG failed");
827 		goto out;
828 	}
829 	ECDSA_SIG_get0(sig, &sig_r, &sig_s);
830 	response->sig_r_len = BN_num_bytes(sig_r);
831 	response->sig_s_len = BN_num_bytes(sig_s);
832 	if ((response->sig_r = calloc(1, response->sig_r_len)) == NULL ||
833 	    (response->sig_s = calloc(1, response->sig_s_len)) == NULL) {
834 		skdebug(__func__, "calloc signature failed");
835 		goto out;
836 	}
837 	BN_bn2bin(sig_r, response->sig_r);
838 	BN_bn2bin(sig_s, response->sig_s);
839 	ret = 0;
840  out:
841 	ECDSA_SIG_free(sig);
842 	if (ret != 0) {
843 		free(response->sig_r);
844 		free(response->sig_s);
845 		response->sig_r = NULL;
846 		response->sig_s = NULL;
847 	}
848 	return ret;
849 }
850 #endif /* WITH_OPENSSL */
851 
852 static int
853 pack_sig_ed25519(fido_assert_t *assert, struct sk_sign_response *response)
854 {
855 	const unsigned char *ptr;
856 	size_t len;
857 	int ret = -1;
858 
859 	ptr = fido_assert_sig_ptr(assert, 0);
860 	len = fido_assert_sig_len(assert, 0);
861 	if (len != 64) {
862 		skdebug(__func__, "bad length %zu", len);
863 		goto out;
864 	}
865 	response->sig_r_len = len;
866 	if ((response->sig_r = calloc(1, response->sig_r_len)) == NULL) {
867 		skdebug(__func__, "calloc signature failed");
868 		goto out;
869 	}
870 	memcpy(response->sig_r, ptr, len);
871 	ret = 0;
872  out:
873 	if (ret != 0) {
874 		free(response->sig_r);
875 		response->sig_r = NULL;
876 	}
877 	return ret;
878 }
879 
880 static int
881 pack_sig(uint32_t  alg, fido_assert_t *assert,
882     struct sk_sign_response *response)
883 {
884 	switch(alg) {
885 #ifdef WITH_OPENSSL
886 	case SSH_SK_ECDSA:
887 		return pack_sig_ecdsa(assert, response);
888 #endif /* WITH_OPENSSL */
889 	case SSH_SK_ED25519:
890 		return pack_sig_ed25519(assert, response);
891 	default:
892 		return -1;
893 	}
894 }
895 
896 /* Checks sk_options for sk_sign() and sk_load_resident_keys() */
897 static int
898 check_sign_load_resident_options(struct sk_option **options, char **devicep)
899 {
900 	size_t i;
901 
902 	if (options == NULL)
903 		return 0;
904 	for (i = 0; options[i] != NULL; i++) {
905 		if (strcmp(options[i]->name, "device") == 0) {
906 			if ((*devicep = strdup(options[i]->value)) == NULL) {
907 				skdebug(__func__, "strdup device failed");
908 				return -1;
909 			}
910 			skdebug(__func__, "requested device %s", *devicep);
911 		} else {
912 			skdebug(__func__, "requested unsupported option %s",
913 			    options[i]->name);
914 			if (options[i]->required) {
915 				skdebug(__func__, "unknown required option");
916 				return -1;
917 			}
918 		}
919 	}
920 	return 0;
921 }
922 
923 int
924 sk_sign(uint32_t alg, const uint8_t *data, size_t datalen,
925     const char *application,
926     const uint8_t *key_handle, size_t key_handle_len,
927     uint8_t flags, const char *pin, struct sk_option **options,
928     struct sk_sign_response **sign_response)
929 {
930 	fido_assert_t *assert = NULL;
931 	char *device = NULL;
932 	struct sk_usbhid *sk = NULL;
933 	struct sk_sign_response *response = NULL;
934 	uint8_t message[32];
935 	int ret = SSH_SK_ERR_GENERAL;
936 	int r;
937 
938 	fido_init(SSH_FIDO_INIT_ARG);
939 
940 	if (sign_response == NULL) {
941 		skdebug(__func__, "sign_response == NULL");
942 		goto out;
943 	}
944 	*sign_response = NULL;
945 	if (check_sign_load_resident_options(options, &device) != 0)
946 		goto out; /* error already logged */
947 	/* hash data to be signed before it goes to the security key */
948 	if ((r = sha256_mem(data, datalen, message, sizeof(message))) != 0) {
949 		skdebug(__func__, "hash message failed");
950 		goto out;
951 	}
952 	if (device != NULL)
953 		sk = sk_open(device);
954 	else if (pin != NULL || (flags & SSH_SK_USER_VERIFICATION_REQD))
955 		sk = sk_probe(NULL, NULL, 0);
956 	else
957 		sk = sk_probe(application, key_handle, key_handle_len);
958 	if (sk == NULL) {
959 		skdebug(__func__, "failed to find sk");
960 		goto out;
961 	}
962 	if ((assert = fido_assert_new()) == NULL) {
963 		skdebug(__func__, "fido_assert_new failed");
964 		goto out;
965 	}
966 	if ((r = fido_assert_set_clientdata_hash(assert, message,
967 	    sizeof(message))) != FIDO_OK) {
968 		skdebug(__func__, "fido_assert_set_clientdata_hash: %s",
969 		    fido_strerr(r));
970 		goto out;
971 	}
972 	if ((r = fido_assert_set_rp(assert, application)) != FIDO_OK) {
973 		skdebug(__func__, "fido_assert_set_rp: %s", fido_strerr(r));
974 		goto out;
975 	}
976 	if ((r = fido_assert_allow_cred(assert, key_handle,
977 	    key_handle_len)) != FIDO_OK) {
978 		skdebug(__func__, "fido_assert_allow_cred: %s", fido_strerr(r));
979 		goto out;
980 	}
981 	if ((r = fido_assert_set_up(assert,
982 	    (flags & SSH_SK_USER_PRESENCE_REQD) ?
983 	    FIDO_OPT_TRUE : FIDO_OPT_FALSE)) != FIDO_OK) {
984 		skdebug(__func__, "fido_assert_set_up: %s", fido_strerr(r));
985 		goto out;
986 	}
987 	if (pin == NULL && (flags & SSH_SK_USER_VERIFICATION_REQD) &&
988 	    (r = fido_assert_set_uv(assert, FIDO_OPT_TRUE)) != FIDO_OK) {
989 		skdebug(__func__, "fido_assert_set_uv: %s", fido_strerr(r));
990 		ret = FIDO_ERR_PIN_REQUIRED;
991 		goto out;
992 	}
993 	if ((r = fido_dev_get_assert(sk->dev, assert, pin)) != FIDO_OK) {
994 		skdebug(__func__, "fido_dev_get_assert: %s", fido_strerr(r));
995 		ret = fidoerr_to_skerr(r);
996 		goto out;
997 	}
998 	if ((response = calloc(1, sizeof(*response))) == NULL) {
999 		skdebug(__func__, "calloc response failed");
1000 		goto out;
1001 	}
1002 	response->flags = fido_assert_flags(assert, 0);
1003 	response->counter = fido_assert_sigcount(assert, 0);
1004 	if (pack_sig(alg, assert, response) != 0) {
1005 		skdebug(__func__, "pack_sig failed");
1006 		goto out;
1007 	}
1008 	*sign_response = response;
1009 	response = NULL;
1010 	ret = 0;
1011  out:
1012 	explicit_bzero(message, sizeof(message));
1013 	free(device);
1014 	if (response != NULL) {
1015 		free(response->sig_r);
1016 		free(response->sig_s);
1017 		free(response);
1018 	}
1019 	sk_close(sk);
1020 	fido_assert_free(&assert);
1021 	return ret;
1022 }
1023 
1024 static int
1025 read_rks(struct sk_usbhid *sk, const char *pin,
1026     struct sk_resident_key ***rksp, size_t *nrksp)
1027 {
1028 	int ret = SSH_SK_ERR_GENERAL, r = -1;
1029 	fido_credman_metadata_t *metadata = NULL;
1030 	fido_credman_rp_t *rp = NULL;
1031 	fido_credman_rk_t *rk = NULL;
1032 	size_t i, j, nrp, nrk;
1033 	const fido_cred_t *cred;
1034 	struct sk_resident_key *srk = NULL, **tmp;
1035 
1036 	if (pin == NULL) {
1037 		skdebug(__func__, "no PIN specified");
1038 		ret = SSH_SK_ERR_PIN_REQUIRED;
1039 		goto out;
1040 	}
1041 	if ((metadata = fido_credman_metadata_new()) == NULL) {
1042 		skdebug(__func__, "alloc failed");
1043 		goto out;
1044 	}
1045 
1046 	if ((r = fido_credman_get_dev_metadata(sk->dev, metadata, pin)) != 0) {
1047 		if (r == FIDO_ERR_INVALID_COMMAND) {
1048 			skdebug(__func__, "device %s does not support "
1049 			    "resident keys", sk->path);
1050 			ret = 0;
1051 			goto out;
1052 		}
1053 		skdebug(__func__, "get metadata for %s failed: %s",
1054 		    sk->path, fido_strerr(r));
1055 		ret = fidoerr_to_skerr(r);
1056 		goto out;
1057 	}
1058 	skdebug(__func__, "existing %llu, remaining %llu",
1059 	    (unsigned long long)fido_credman_rk_existing(metadata),
1060 	    (unsigned long long)fido_credman_rk_remaining(metadata));
1061 	if ((rp = fido_credman_rp_new()) == NULL) {
1062 		skdebug(__func__, "alloc rp failed");
1063 		goto out;
1064 	}
1065 	if ((r = fido_credman_get_dev_rp(sk->dev, rp, pin)) != 0) {
1066 		skdebug(__func__, "get RPs for %s failed: %s",
1067 		    sk->path, fido_strerr(r));
1068 		goto out;
1069 	}
1070 	nrp = fido_credman_rp_count(rp);
1071 	skdebug(__func__, "Device %s has resident keys for %zu RPs",
1072 	    sk->path, nrp);
1073 
1074 	/* Iterate over RP IDs that have resident keys */
1075 	for (i = 0; i < nrp; i++) {
1076 		skdebug(__func__, "rp %zu: name=\"%s\" id=\"%s\" hashlen=%zu",
1077 		    i, fido_credman_rp_name(rp, i), fido_credman_rp_id(rp, i),
1078 		    fido_credman_rp_id_hash_len(rp, i));
1079 
1080 		/* Skip non-SSH RP IDs */
1081 		if (strncasecmp(fido_credman_rp_id(rp, i), "ssh:", 4) != 0)
1082 			continue;
1083 
1084 		fido_credman_rk_free(&rk);
1085 		if ((rk = fido_credman_rk_new()) == NULL) {
1086 			skdebug(__func__, "alloc rk failed");
1087 			goto out;
1088 		}
1089 		if ((r = fido_credman_get_dev_rk(sk->dev,
1090 		    fido_credman_rp_id(rp, i), rk, pin)) != 0) {
1091 			skdebug(__func__, "get RKs for %s slot %zu failed: %s",
1092 			    sk->path, i, fido_strerr(r));
1093 			goto out;
1094 		}
1095 		nrk = fido_credman_rk_count(rk);
1096 		skdebug(__func__, "RP \"%s\" has %zu resident keys",
1097 		    fido_credman_rp_id(rp, i), nrk);
1098 
1099 		/* Iterate over resident keys for this RP ID */
1100 		for (j = 0; j < nrk; j++) {
1101 			if ((cred = fido_credman_rk(rk, j)) == NULL) {
1102 				skdebug(__func__, "no RK in slot %zu", j);
1103 				continue;
1104 			}
1105 			skdebug(__func__, "Device %s RP \"%s\" slot %zu: "
1106 			    "type %d flags 0x%02x prot 0x%02x", sk->path,
1107 			    fido_credman_rp_id(rp, i), j, fido_cred_type(cred),
1108 			    fido_cred_flags(cred), fido_cred_prot(cred));
1109 
1110 			/* build response entry */
1111 			if ((srk = calloc(1, sizeof(*srk))) == NULL ||
1112 			    (srk->key.key_handle = calloc(1,
1113 			    fido_cred_id_len(cred))) == NULL ||
1114 			    (srk->application = strdup(fido_credman_rp_id(rp,
1115 			    i))) == NULL) {
1116 				skdebug(__func__, "alloc sk_resident_key");
1117 				goto out;
1118 			}
1119 
1120 			srk->key.key_handle_len = fido_cred_id_len(cred);
1121 			memcpy(srk->key.key_handle, fido_cred_id_ptr(cred),
1122 			    srk->key.key_handle_len);
1123 
1124 			switch (fido_cred_type(cred)) {
1125 			case COSE_ES256:
1126 				srk->alg = SSH_SK_ECDSA;
1127 				break;
1128 			case COSE_EDDSA:
1129 				srk->alg = SSH_SK_ED25519;
1130 				break;
1131 			default:
1132 				skdebug(__func__, "unsupported key type %d",
1133 				    fido_cred_type(cred));
1134 				goto out; /* XXX free rk and continue */
1135 			}
1136 
1137 			if (fido_cred_prot(cred) == FIDO_CRED_PROT_UV_REQUIRED)
1138 				srk->flags |=  SSH_SK_USER_VERIFICATION_REQD;
1139 
1140 			if ((r = pack_public_key(srk->alg, cred,
1141 			    &srk->key)) != 0) {
1142 				skdebug(__func__, "pack public key failed");
1143 				goto out;
1144 			}
1145 			/* append */
1146 			if ((tmp = recallocarray(*rksp, *nrksp, (*nrksp) + 1,
1147 			    sizeof(**rksp))) == NULL) {
1148 				skdebug(__func__, "alloc rksp");
1149 				goto out;
1150 			}
1151 			*rksp = tmp;
1152 			(*rksp)[(*nrksp)++] = srk;
1153 			srk = NULL;
1154 		}
1155 	}
1156 	/* Success */
1157 	ret = 0;
1158  out:
1159 	if (srk != NULL) {
1160 		free(srk->application);
1161 		freezero(srk->key.public_key, srk->key.public_key_len);
1162 		freezero(srk->key.key_handle, srk->key.key_handle_len);
1163 		freezero(srk, sizeof(*srk));
1164 	}
1165 	fido_credman_rp_free(&rp);
1166 	fido_credman_rk_free(&rk);
1167 	fido_credman_metadata_free(&metadata);
1168 	return ret;
1169 }
1170 
1171 int
1172 sk_load_resident_keys(const char *pin, struct sk_option **options,
1173     struct sk_resident_key ***rksp, size_t *nrksp)
1174 {
1175 	int ret = SSH_SK_ERR_GENERAL, r = -1;
1176 	size_t i, nrks = 0;
1177 	struct sk_resident_key **rks = NULL;
1178 	struct sk_usbhid *sk = NULL;
1179 	char *device = NULL;
1180 
1181 	*rksp = NULL;
1182 	*nrksp = 0;
1183 
1184 	fido_init(SSH_FIDO_INIT_ARG);
1185 
1186 	if (check_sign_load_resident_options(options, &device) != 0)
1187 		goto out; /* error already logged */
1188 	if (device != NULL)
1189 		sk = sk_open(device);
1190 	else
1191 		sk = sk_probe(NULL, NULL, 0);
1192 	if (sk == NULL) {
1193 		skdebug(__func__, "failed to find sk");
1194 		goto out;
1195 	}
1196 	skdebug(__func__, "trying %s", sk->path);
1197 	if ((r = read_rks(sk, pin, &rks, &nrks)) != 0) {
1198 		skdebug(__func__, "read_rks failed for %s", sk->path);
1199 		ret = r;
1200 		goto out;
1201 	}
1202 	/* success, unless we have no keys but a specific error */
1203 	if (nrks > 0 || ret == SSH_SK_ERR_GENERAL)
1204 		ret = 0;
1205 	*rksp = rks;
1206 	*nrksp = nrks;
1207 	rks = NULL;
1208 	nrks = 0;
1209  out:
1210 	sk_close(sk);
1211 	for (i = 0; i < nrks; i++) {
1212 		free(rks[i]->application);
1213 		freezero(rks[i]->key.public_key, rks[i]->key.public_key_len);
1214 		freezero(rks[i]->key.key_handle, rks[i]->key.key_handle_len);
1215 		freezero(rks[i], sizeof(*rks[i]));
1216 	}
1217 	free(rks);
1218 	return ret;
1219 }
1220 
1221