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