xref: /openssh-portable/sk-usbhid.c (revision b969072c)
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 	if (skvcnt == 1) {
371 		sk = skv[0];
372 		skv[0] = NULL;
373 		goto out;
374 	}
375 	sk = NULL;
376 	for (i = 0; i < skvcnt; i++) {
377 		if (sk_try(skv[i], application, key_handle,
378 		    key_handle_len) == 0) {
379 			sk = skv[i];
380 			skv[i] = NULL;
381 			skdebug(__func__, "found key in %s", sk->path);
382 			break;
383 		}
384 	}
385  out:
386 	sk_closev(skv, skvcnt);
387 	return sk;
388 }
389 
390 static struct sk_usbhid *
391 sk_select_by_touch(const fido_dev_info_t *devlist, size_t ndevs)
392 {
393 	struct sk_usbhid **skv, *sk;
394 	struct timeval tv_start, tv_now, tv_delta;
395 	size_t skvcnt, idx;
396 	int touch, ms_remain;
397 
398 #ifndef HAVE_FIDO_DEV_GET_TOUCH_STATUS
399 	skdebug(__func__, "libfido2 version does not support a feature needed for multiple tokens. Please upgrade to >=1.5.0");
400 	return NULL;
401 #endif
402 
403 	if ((skv = sk_openv(devlist, ndevs, &skvcnt)) == NULL) {
404 		skdebug(__func__, "sk_openv failed");
405 		return NULL;
406 	}
407 	sk = NULL;
408 	if (skvcnt < 2) {
409 		if (skvcnt == 1) {
410 			/* single candidate */
411 			sk = skv[0];
412 			skv[0] = NULL;
413 		}
414 		goto out;
415 	}
416 	if (sk_touch_begin(skv, skvcnt) == -1) {
417 		skdebug(__func__, "sk_touch_begin failed");
418 		goto out;
419 	}
420 	monotime_tv(&tv_start);
421 	do {
422 		if (sk_touch_poll(skv, skvcnt, &touch, &idx) == -1) {
423 			skdebug(__func__, "sk_touch_poll failed");
424 			goto out;
425 		}
426 		if (touch) {
427 			sk = skv[idx];
428 			skv[idx] = NULL;
429 			goto out;
430 		}
431 		monotime_tv(&tv_now);
432 		timersub(&tv_now, &tv_start, &tv_delta);
433 		ms_remain = SELECT_MS - tv_delta.tv_sec * 1000 -
434 		    tv_delta.tv_usec / 1000;
435 	} while (ms_remain >= FIDO_POLL_MS);
436 	skdebug(__func__, "timeout");
437 out:
438 	sk_closev(skv, skvcnt);
439 	return sk;
440 }
441 
442 static struct sk_usbhid *
443 sk_probe(const char *application, const uint8_t *key_handle,
444     size_t key_handle_len)
445 {
446 	struct sk_usbhid *sk;
447 	fido_dev_info_t *devlist;
448 	size_t ndevs;
449 	int r;
450 
451 	if ((devlist = fido_dev_info_new(MAX_FIDO_DEVICES)) == NULL) {
452 		skdebug(__func__, "fido_dev_info_new failed");
453 		return NULL;
454 	}
455 	if ((r = fido_dev_info_manifest(devlist, MAX_FIDO_DEVICES,
456 	    &ndevs)) != FIDO_OK) {
457 		skdebug(__func__, "fido_dev_info_manifest failed: %s",
458 		    fido_strerr(r));
459 		fido_dev_info_free(&devlist, MAX_FIDO_DEVICES);
460 		return NULL;
461 	}
462 	skdebug(__func__, "%zu device(s) detected", ndevs);
463 	if (ndevs == 0) {
464 		sk = NULL;
465 	} else if (application != NULL && key_handle != NULL) {
466 		skdebug(__func__, "selecting sk by cred");
467 		sk = sk_select_by_cred(devlist, ndevs, application, key_handle,
468 		    key_handle_len);
469 	} else {
470 		skdebug(__func__, "selecting sk by touch");
471 		sk = sk_select_by_touch(devlist, ndevs);
472 	}
473 	fido_dev_info_free(&devlist, MAX_FIDO_DEVICES);
474 	return sk;
475 }
476 
477 #ifdef WITH_OPENSSL
478 /*
479  * The key returned via fido_cred_pubkey_ptr() is in affine coordinates,
480  * but the API expects a SEC1 octet string.
481  */
482 static int
483 pack_public_key_ecdsa(const fido_cred_t *cred,
484     struct sk_enroll_response *response)
485 {
486 	const uint8_t *ptr;
487 	BIGNUM *x = NULL, *y = NULL;
488 	EC_POINT *q = NULL;
489 	EC_GROUP *g = NULL;
490 	int ret = -1;
491 
492 	response->public_key = NULL;
493 	response->public_key_len = 0;
494 
495 	if ((x = BN_new()) == NULL ||
496 	    (y = BN_new()) == NULL ||
497 	    (g = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1)) == NULL ||
498 	    (q = EC_POINT_new(g)) == NULL) {
499 		skdebug(__func__, "libcrypto setup failed");
500 		goto out;
501 	}
502 	if ((ptr = fido_cred_pubkey_ptr(cred)) == NULL) {
503 		skdebug(__func__, "fido_cred_pubkey_ptr failed");
504 		goto out;
505 	}
506 	if (fido_cred_pubkey_len(cred) != 64) {
507 		skdebug(__func__, "bad fido_cred_pubkey_len %zu",
508 		    fido_cred_pubkey_len(cred));
509 		goto out;
510 	}
511 
512 	if (BN_bin2bn(ptr, 32, x) == NULL ||
513 	    BN_bin2bn(ptr + 32, 32, y) == NULL) {
514 		skdebug(__func__, "BN_bin2bn failed");
515 		goto out;
516 	}
517 	if (EC_POINT_set_affine_coordinates_GFp(g, q, x, y, NULL) != 1) {
518 		skdebug(__func__, "EC_POINT_set_affine_coordinates_GFp failed");
519 		goto out;
520 	}
521 	response->public_key_len = EC_POINT_point2oct(g, q,
522 	    POINT_CONVERSION_UNCOMPRESSED, NULL, 0, NULL);
523 	if (response->public_key_len == 0 || response->public_key_len > 2048) {
524 		skdebug(__func__, "bad pubkey length %zu",
525 		    response->public_key_len);
526 		goto out;
527 	}
528 	if ((response->public_key = malloc(response->public_key_len)) == NULL) {
529 		skdebug(__func__, "malloc pubkey failed");
530 		goto out;
531 	}
532 	if (EC_POINT_point2oct(g, q, POINT_CONVERSION_UNCOMPRESSED,
533 	    response->public_key, response->public_key_len, NULL) == 0) {
534 		skdebug(__func__, "EC_POINT_point2oct failed");
535 		goto out;
536 	}
537 	/* success */
538 	ret = 0;
539  out:
540 	if (ret != 0 && response->public_key != NULL) {
541 		memset(response->public_key, 0, response->public_key_len);
542 		free(response->public_key);
543 		response->public_key = NULL;
544 	}
545 	EC_POINT_free(q);
546 	EC_GROUP_free(g);
547 	BN_clear_free(x);
548 	BN_clear_free(y);
549 	return ret;
550 }
551 #endif /* WITH_OPENSSL */
552 
553 static int
554 pack_public_key_ed25519(const fido_cred_t *cred,
555     struct sk_enroll_response *response)
556 {
557 	const uint8_t *ptr;
558 	size_t len;
559 	int ret = -1;
560 
561 	response->public_key = NULL;
562 	response->public_key_len = 0;
563 
564 	if ((len = fido_cred_pubkey_len(cred)) != 32) {
565 		skdebug(__func__, "bad fido_cred_pubkey_len len %zu", len);
566 		goto out;
567 	}
568 	if ((ptr = fido_cred_pubkey_ptr(cred)) == NULL) {
569 		skdebug(__func__, "fido_cred_pubkey_ptr failed");
570 		goto out;
571 	}
572 	response->public_key_len = len;
573 	if ((response->public_key = malloc(response->public_key_len)) == NULL) {
574 		skdebug(__func__, "malloc pubkey failed");
575 		goto out;
576 	}
577 	memcpy(response->public_key, ptr, len);
578 	ret = 0;
579  out:
580 	if (ret != 0)
581 		free(response->public_key);
582 	return ret;
583 }
584 
585 static int
586 pack_public_key(uint32_t alg, const fido_cred_t *cred,
587     struct sk_enroll_response *response)
588 {
589 	switch(alg) {
590 #ifdef WITH_OPENSSL
591 	case SSH_SK_ECDSA:
592 		return pack_public_key_ecdsa(cred, response);
593 #endif /* WITH_OPENSSL */
594 	case SSH_SK_ED25519:
595 		return pack_public_key_ed25519(cred, response);
596 	default:
597 		return -1;
598 	}
599 }
600 
601 static int
602 fidoerr_to_skerr(int fidoerr)
603 {
604 	switch (fidoerr) {
605 	case FIDO_ERR_UNSUPPORTED_OPTION:
606 	case FIDO_ERR_UNSUPPORTED_ALGORITHM:
607 		return SSH_SK_ERR_UNSUPPORTED;
608 	case FIDO_ERR_PIN_REQUIRED:
609 	case FIDO_ERR_PIN_INVALID:
610 		return SSH_SK_ERR_PIN_REQUIRED;
611 	default:
612 		return -1;
613 	}
614 }
615 
616 static int
617 check_enroll_options(struct sk_option **options, char **devicep,
618     uint8_t *user_id, size_t user_id_len)
619 {
620 	size_t i;
621 
622 	if (options == NULL)
623 		return 0;
624 	for (i = 0; options[i] != NULL; i++) {
625 		if (strcmp(options[i]->name, "device") == 0) {
626 			if ((*devicep = strdup(options[i]->value)) == NULL) {
627 				skdebug(__func__, "strdup device failed");
628 				return -1;
629 			}
630 			skdebug(__func__, "requested device %s", *devicep);
631 		} else if (strcmp(options[i]->name, "user") == 0) {
632 			if (strlcpy(user_id, options[i]->value, user_id_len) >=
633 			    user_id_len) {
634 				skdebug(__func__, "user too long");
635 				return -1;
636 			}
637 			skdebug(__func__, "requested user %s",
638 			    (char *)user_id);
639 		} else {
640 			skdebug(__func__, "requested unsupported option %s",
641 			    options[i]->name);
642 			if (options[i]->required) {
643 				skdebug(__func__, "unknown required option");
644 				return -1;
645 			}
646 		}
647 	}
648 	return 0;
649 }
650 
651 int
652 sk_enroll(uint32_t alg, const uint8_t *challenge, size_t challenge_len,
653     const char *application, uint8_t flags, const char *pin,
654     struct sk_option **options, struct sk_enroll_response **enroll_response)
655 {
656 	fido_cred_t *cred = NULL;
657 	const uint8_t *ptr;
658 	uint8_t user_id[32];
659 	struct sk_usbhid *sk = NULL;
660 	struct sk_enroll_response *response = NULL;
661 	size_t len;
662 	int credprot;
663 	int cose_alg;
664 	int ret = SSH_SK_ERR_GENERAL;
665 	int r;
666 	char *device = NULL;
667 
668 	fido_init(SSH_FIDO_INIT_ARG);
669 
670 	if (enroll_response == NULL) {
671 		skdebug(__func__, "enroll_response == NULL");
672 		goto out;
673 	}
674 	*enroll_response = NULL;
675 	memset(user_id, 0, sizeof(user_id));
676 	if (check_enroll_options(options, &device, user_id,
677 	    sizeof(user_id)) != 0)
678 		goto out; /* error already logged */
679 
680 	switch(alg) {
681 #ifdef WITH_OPENSSL
682 	case SSH_SK_ECDSA:
683 		cose_alg = COSE_ES256;
684 		break;
685 #endif /* WITH_OPENSSL */
686 	case SSH_SK_ED25519:
687 		cose_alg = COSE_EDDSA;
688 		break;
689 	default:
690 		skdebug(__func__, "unsupported key type %d", alg);
691 		goto out;
692 	}
693 	if (device != NULL)
694 		sk = sk_open(device);
695 	else
696 		sk = sk_probe(NULL, NULL, 0);
697 	if (sk == NULL) {
698 		skdebug(__func__, "failed to find sk");
699 		goto out;
700 	}
701 	skdebug(__func__, "using device %s", sk->path);
702 	if ((cred = fido_cred_new()) == NULL) {
703 		skdebug(__func__, "fido_cred_new failed");
704 		goto out;
705 	}
706 	if ((r = fido_cred_set_type(cred, cose_alg)) != FIDO_OK) {
707 		skdebug(__func__, "fido_cred_set_type: %s", fido_strerr(r));
708 		goto out;
709 	}
710 	if ((r = fido_cred_set_clientdata_hash(cred, challenge,
711 	    challenge_len)) != FIDO_OK) {
712 		skdebug(__func__, "fido_cred_set_clientdata_hash: %s",
713 		    fido_strerr(r));
714 		goto out;
715 	}
716 	if ((r = fido_cred_set_rk(cred, (flags & SSH_SK_RESIDENT_KEY) != 0 ?
717 	    FIDO_OPT_TRUE : FIDO_OPT_OMIT)) != FIDO_OK) {
718 		skdebug(__func__, "fido_cred_set_rk: %s", fido_strerr(r));
719 		goto out;
720 	}
721 	if ((r = fido_cred_set_user(cred, user_id, sizeof(user_id),
722 	    "openssh", "openssh", NULL)) != FIDO_OK) {
723 		skdebug(__func__, "fido_cred_set_user: %s", fido_strerr(r));
724 		goto out;
725 	}
726 	if ((r = fido_cred_set_rp(cred, application, NULL)) != FIDO_OK) {
727 		skdebug(__func__, "fido_cred_set_rp: %s", fido_strerr(r));
728 		goto out;
729 	}
730 	if ((flags & (SSH_SK_RESIDENT_KEY|SSH_SK_USER_VERIFICATION_REQD)) != 0) {
731 #ifndef HAVE_FIDO_DEV_SUPPORTS_CRED_PROT
732 		skdebug(__func__, "libfido2 version does not support a feature required for this operation. Please upgrade to >=1.5.0");
733 		ret = SSH_SK_ERR_UNSUPPORTED;
734 		goto out;
735 #endif
736 		if (!fido_dev_supports_cred_prot(sk->dev)) {
737 			skdebug(__func__, "%s does not support credprot, "
738 			    "refusing to create unprotected "
739 			    "resident/verify-required key", sk->path);
740 			ret = SSH_SK_ERR_UNSUPPORTED;
741 			goto out;
742 		}
743 		if ((flags & SSH_SK_USER_VERIFICATION_REQD))
744 			credprot = FIDO_CRED_PROT_UV_REQUIRED;
745 		else
746 			credprot = FIDO_CRED_PROT_UV_OPTIONAL_WITH_ID;
747 
748 		if ((r = fido_cred_set_prot(cred, credprot)) != FIDO_OK) {
749 			skdebug(__func__, "fido_cred_set_prot: %s",
750 			    fido_strerr(r));
751 			ret = fidoerr_to_skerr(r);
752 			goto out;
753 		}
754 	}
755 	if ((r = fido_dev_make_cred(sk->dev, cred, pin)) != FIDO_OK) {
756 		skdebug(__func__, "fido_dev_make_cred: %s", fido_strerr(r));
757 		ret = fidoerr_to_skerr(r);
758 		goto out;
759 	}
760 	if (fido_cred_x5c_ptr(cred) != NULL) {
761 		if ((r = fido_cred_verify(cred)) != FIDO_OK) {
762 			skdebug(__func__, "fido_cred_verify: %s",
763 			    fido_strerr(r));
764 			goto out;
765 		}
766 	} else {
767 		skdebug(__func__, "self-attested credential");
768 		if ((r = fido_cred_verify_self(cred)) != FIDO_OK) {
769 			skdebug(__func__, "fido_cred_verify_self: %s",
770 			    fido_strerr(r));
771 			goto out;
772 		}
773 	}
774 	if ((response = calloc(1, sizeof(*response))) == NULL) {
775 		skdebug(__func__, "calloc response failed");
776 		goto out;
777 	}
778 	if (pack_public_key(alg, cred, response) != 0) {
779 		skdebug(__func__, "pack_public_key failed");
780 		goto out;
781 	}
782 	if ((ptr = fido_cred_id_ptr(cred)) != NULL) {
783 		len = fido_cred_id_len(cred);
784 		if ((response->key_handle = calloc(1, len)) == NULL) {
785 			skdebug(__func__, "calloc key handle failed");
786 			goto out;
787 		}
788 		memcpy(response->key_handle, ptr, len);
789 		response->key_handle_len = len;
790 	}
791 	if ((ptr = fido_cred_sig_ptr(cred)) != NULL) {
792 		len = fido_cred_sig_len(cred);
793 		if ((response->signature = calloc(1, len)) == NULL) {
794 			skdebug(__func__, "calloc signature failed");
795 			goto out;
796 		}
797 		memcpy(response->signature, ptr, len);
798 		response->signature_len = len;
799 	}
800 	if ((ptr = fido_cred_x5c_ptr(cred)) != NULL) {
801 		len = fido_cred_x5c_len(cred);
802 		debug3("%s: attestation cert len=%zu", __func__, len);
803 		if ((response->attestation_cert = calloc(1, len)) == NULL) {
804 			skdebug(__func__, "calloc attestation cert failed");
805 			goto out;
806 		}
807 		memcpy(response->attestation_cert, ptr, len);
808 		response->attestation_cert_len = len;
809 	}
810 	*enroll_response = response;
811 	response = NULL;
812 	ret = 0;
813  out:
814 	free(device);
815 	if (response != NULL) {
816 		free(response->public_key);
817 		free(response->key_handle);
818 		free(response->signature);
819 		free(response->attestation_cert);
820 		free(response);
821 	}
822 	sk_close(sk);
823 	fido_cred_free(&cred);
824 	return ret;
825 }
826 
827 #ifdef WITH_OPENSSL
828 static int
829 pack_sig_ecdsa(fido_assert_t *assert, struct sk_sign_response *response)
830 {
831 	ECDSA_SIG *sig = NULL;
832 	const BIGNUM *sig_r, *sig_s;
833 	const unsigned char *cp;
834 	size_t sig_len;
835 	int ret = -1;
836 
837 	cp = fido_assert_sig_ptr(assert, 0);
838 	sig_len = fido_assert_sig_len(assert, 0);
839 	if ((sig = d2i_ECDSA_SIG(NULL, &cp, sig_len)) == NULL) {
840 		skdebug(__func__, "d2i_ECDSA_SIG failed");
841 		goto out;
842 	}
843 	ECDSA_SIG_get0(sig, &sig_r, &sig_s);
844 	response->sig_r_len = BN_num_bytes(sig_r);
845 	response->sig_s_len = BN_num_bytes(sig_s);
846 	if ((response->sig_r = calloc(1, response->sig_r_len)) == NULL ||
847 	    (response->sig_s = calloc(1, response->sig_s_len)) == NULL) {
848 		skdebug(__func__, "calloc signature failed");
849 		goto out;
850 	}
851 	BN_bn2bin(sig_r, response->sig_r);
852 	BN_bn2bin(sig_s, response->sig_s);
853 	ret = 0;
854  out:
855 	ECDSA_SIG_free(sig);
856 	if (ret != 0) {
857 		free(response->sig_r);
858 		free(response->sig_s);
859 		response->sig_r = NULL;
860 		response->sig_s = NULL;
861 	}
862 	return ret;
863 }
864 #endif /* WITH_OPENSSL */
865 
866 static int
867 pack_sig_ed25519(fido_assert_t *assert, struct sk_sign_response *response)
868 {
869 	const unsigned char *ptr;
870 	size_t len;
871 	int ret = -1;
872 
873 	ptr = fido_assert_sig_ptr(assert, 0);
874 	len = fido_assert_sig_len(assert, 0);
875 	if (len != 64) {
876 		skdebug(__func__, "bad length %zu", len);
877 		goto out;
878 	}
879 	response->sig_r_len = len;
880 	if ((response->sig_r = calloc(1, response->sig_r_len)) == NULL) {
881 		skdebug(__func__, "calloc signature failed");
882 		goto out;
883 	}
884 	memcpy(response->sig_r, ptr, len);
885 	ret = 0;
886  out:
887 	if (ret != 0) {
888 		free(response->sig_r);
889 		response->sig_r = NULL;
890 	}
891 	return ret;
892 }
893 
894 static int
895 pack_sig(uint32_t  alg, fido_assert_t *assert,
896     struct sk_sign_response *response)
897 {
898 	switch(alg) {
899 #ifdef WITH_OPENSSL
900 	case SSH_SK_ECDSA:
901 		return pack_sig_ecdsa(assert, response);
902 #endif /* WITH_OPENSSL */
903 	case SSH_SK_ED25519:
904 		return pack_sig_ed25519(assert, response);
905 	default:
906 		return -1;
907 	}
908 }
909 
910 /* Checks sk_options for sk_sign() and sk_load_resident_keys() */
911 static int
912 check_sign_load_resident_options(struct sk_option **options, char **devicep)
913 {
914 	size_t i;
915 
916 	if (options == NULL)
917 		return 0;
918 	for (i = 0; options[i] != NULL; i++) {
919 		if (strcmp(options[i]->name, "device") == 0) {
920 			if ((*devicep = strdup(options[i]->value)) == NULL) {
921 				skdebug(__func__, "strdup device failed");
922 				return -1;
923 			}
924 			skdebug(__func__, "requested device %s", *devicep);
925 		} else {
926 			skdebug(__func__, "requested unsupported option %s",
927 			    options[i]->name);
928 			if (options[i]->required) {
929 				skdebug(__func__, "unknown required option");
930 				return -1;
931 			}
932 		}
933 	}
934 	return 0;
935 }
936 
937 int
938 sk_sign(uint32_t alg, const uint8_t *data, size_t datalen,
939     const char *application,
940     const uint8_t *key_handle, size_t key_handle_len,
941     uint8_t flags, const char *pin, struct sk_option **options,
942     struct sk_sign_response **sign_response)
943 {
944 	fido_assert_t *assert = NULL;
945 	char *device = NULL;
946 	struct sk_usbhid *sk = NULL;
947 	struct sk_sign_response *response = NULL;
948 	uint8_t message[32];
949 	int ret = SSH_SK_ERR_GENERAL;
950 	int r;
951 
952 	fido_init(SSH_FIDO_INIT_ARG);
953 
954 	if (sign_response == NULL) {
955 		skdebug(__func__, "sign_response == NULL");
956 		goto out;
957 	}
958 	*sign_response = NULL;
959 	if (check_sign_load_resident_options(options, &device) != 0)
960 		goto out; /* error already logged */
961 	/* hash data to be signed before it goes to the security key */
962 	if ((r = sha256_mem(data, datalen, message, sizeof(message))) != 0) {
963 		skdebug(__func__, "hash message failed");
964 		goto out;
965 	}
966 	if (device != NULL)
967 		sk = sk_open(device);
968 	else if (pin != NULL || (flags & SSH_SK_USER_VERIFICATION_REQD))
969 		sk = sk_probe(NULL, NULL, 0);
970 	else
971 		sk = sk_probe(application, key_handle, key_handle_len);
972 	if (sk == NULL) {
973 		skdebug(__func__, "failed to find sk");
974 		goto out;
975 	}
976 	if ((assert = fido_assert_new()) == NULL) {
977 		skdebug(__func__, "fido_assert_new failed");
978 		goto out;
979 	}
980 	if ((r = fido_assert_set_clientdata_hash(assert, message,
981 	    sizeof(message))) != FIDO_OK) {
982 		skdebug(__func__, "fido_assert_set_clientdata_hash: %s",
983 		    fido_strerr(r));
984 		goto out;
985 	}
986 	if ((r = fido_assert_set_rp(assert, application)) != FIDO_OK) {
987 		skdebug(__func__, "fido_assert_set_rp: %s", fido_strerr(r));
988 		goto out;
989 	}
990 	if ((r = fido_assert_allow_cred(assert, key_handle,
991 	    key_handle_len)) != FIDO_OK) {
992 		skdebug(__func__, "fido_assert_allow_cred: %s", fido_strerr(r));
993 		goto out;
994 	}
995 	if ((r = fido_assert_set_up(assert,
996 	    (flags & SSH_SK_USER_PRESENCE_REQD) ?
997 	    FIDO_OPT_TRUE : FIDO_OPT_FALSE)) != FIDO_OK) {
998 		skdebug(__func__, "fido_assert_set_up: %s", fido_strerr(r));
999 		goto out;
1000 	}
1001 	if (pin == NULL && (flags & SSH_SK_USER_VERIFICATION_REQD) &&
1002 	    (r = fido_assert_set_uv(assert, FIDO_OPT_TRUE)) != FIDO_OK) {
1003 		skdebug(__func__, "fido_assert_set_uv: %s", fido_strerr(r));
1004 		ret = FIDO_ERR_PIN_REQUIRED;
1005 		goto out;
1006 	}
1007 	if ((r = fido_dev_get_assert(sk->dev, assert, pin)) != FIDO_OK) {
1008 		skdebug(__func__, "fido_dev_get_assert: %s", fido_strerr(r));
1009 		ret = fidoerr_to_skerr(r);
1010 		goto out;
1011 	}
1012 	if ((response = calloc(1, sizeof(*response))) == NULL) {
1013 		skdebug(__func__, "calloc response failed");
1014 		goto out;
1015 	}
1016 	response->flags = fido_assert_flags(assert, 0);
1017 	response->counter = fido_assert_sigcount(assert, 0);
1018 	if (pack_sig(alg, assert, response) != 0) {
1019 		skdebug(__func__, "pack_sig failed");
1020 		goto out;
1021 	}
1022 	*sign_response = response;
1023 	response = NULL;
1024 	ret = 0;
1025  out:
1026 	explicit_bzero(message, sizeof(message));
1027 	free(device);
1028 	if (response != NULL) {
1029 		free(response->sig_r);
1030 		free(response->sig_s);
1031 		free(response);
1032 	}
1033 	sk_close(sk);
1034 	fido_assert_free(&assert);
1035 	return ret;
1036 }
1037 
1038 static int
1039 read_rks(struct sk_usbhid *sk, const char *pin,
1040     struct sk_resident_key ***rksp, size_t *nrksp)
1041 {
1042 	int ret = SSH_SK_ERR_GENERAL, r = -1;
1043 	fido_credman_metadata_t *metadata = NULL;
1044 	fido_credman_rp_t *rp = NULL;
1045 	fido_credman_rk_t *rk = NULL;
1046 	size_t i, j, nrp, nrk;
1047 	const fido_cred_t *cred;
1048 	struct sk_resident_key *srk = NULL, **tmp;
1049 
1050 	if (pin == NULL) {
1051 		skdebug(__func__, "no PIN specified");
1052 		ret = SSH_SK_ERR_PIN_REQUIRED;
1053 		goto out;
1054 	}
1055 	if ((metadata = fido_credman_metadata_new()) == NULL) {
1056 		skdebug(__func__, "alloc failed");
1057 		goto out;
1058 	}
1059 
1060 	if ((r = fido_credman_get_dev_metadata(sk->dev, metadata, pin)) != 0) {
1061 		if (r == FIDO_ERR_INVALID_COMMAND) {
1062 			skdebug(__func__, "device %s does not support "
1063 			    "resident keys", sk->path);
1064 			ret = 0;
1065 			goto out;
1066 		}
1067 		skdebug(__func__, "get metadata for %s failed: %s",
1068 		    sk->path, fido_strerr(r));
1069 		ret = fidoerr_to_skerr(r);
1070 		goto out;
1071 	}
1072 	skdebug(__func__, "existing %llu, remaining %llu",
1073 	    (unsigned long long)fido_credman_rk_existing(metadata),
1074 	    (unsigned long long)fido_credman_rk_remaining(metadata));
1075 	if ((rp = fido_credman_rp_new()) == NULL) {
1076 		skdebug(__func__, "alloc rp failed");
1077 		goto out;
1078 	}
1079 	if ((r = fido_credman_get_dev_rp(sk->dev, rp, pin)) != 0) {
1080 		skdebug(__func__, "get RPs for %s failed: %s",
1081 		    sk->path, fido_strerr(r));
1082 		goto out;
1083 	}
1084 	nrp = fido_credman_rp_count(rp);
1085 	skdebug(__func__, "Device %s has resident keys for %zu RPs",
1086 	    sk->path, nrp);
1087 
1088 	/* Iterate over RP IDs that have resident keys */
1089 	for (i = 0; i < nrp; i++) {
1090 		skdebug(__func__, "rp %zu: name=\"%s\" id=\"%s\" hashlen=%zu",
1091 		    i, fido_credman_rp_name(rp, i), fido_credman_rp_id(rp, i),
1092 		    fido_credman_rp_id_hash_len(rp, i));
1093 
1094 		/* Skip non-SSH RP IDs */
1095 		if (strncasecmp(fido_credman_rp_id(rp, i), "ssh:", 4) != 0)
1096 			continue;
1097 
1098 		fido_credman_rk_free(&rk);
1099 		if ((rk = fido_credman_rk_new()) == NULL) {
1100 			skdebug(__func__, "alloc rk failed");
1101 			goto out;
1102 		}
1103 		if ((r = fido_credman_get_dev_rk(sk->dev,
1104 		    fido_credman_rp_id(rp, i), rk, pin)) != 0) {
1105 			skdebug(__func__, "get RKs for %s slot %zu failed: %s",
1106 			    sk->path, i, fido_strerr(r));
1107 			goto out;
1108 		}
1109 		nrk = fido_credman_rk_count(rk);
1110 		skdebug(__func__, "RP \"%s\" has %zu resident keys",
1111 		    fido_credman_rp_id(rp, i), nrk);
1112 
1113 		/* Iterate over resident keys for this RP ID */
1114 		for (j = 0; j < nrk; j++) {
1115 			if ((cred = fido_credman_rk(rk, j)) == NULL) {
1116 				skdebug(__func__, "no RK in slot %zu", j);
1117 				continue;
1118 			}
1119 			skdebug(__func__, "Device %s RP \"%s\" slot %zu: "
1120 			    "type %d flags 0x%02x prot 0x%02x", sk->path,
1121 			    fido_credman_rp_id(rp, i), j, fido_cred_type(cred),
1122 			    fido_cred_flags(cred), fido_cred_prot(cred));
1123 
1124 			/* build response entry */
1125 			if ((srk = calloc(1, sizeof(*srk))) == NULL ||
1126 			    (srk->key.key_handle = calloc(1,
1127 			    fido_cred_id_len(cred))) == NULL ||
1128 			    (srk->application = strdup(fido_credman_rp_id(rp,
1129 			    i))) == NULL) {
1130 				skdebug(__func__, "alloc sk_resident_key");
1131 				goto out;
1132 			}
1133 
1134 			srk->key.key_handle_len = fido_cred_id_len(cred);
1135 			memcpy(srk->key.key_handle, fido_cred_id_ptr(cred),
1136 			    srk->key.key_handle_len);
1137 
1138 			switch (fido_cred_type(cred)) {
1139 			case COSE_ES256:
1140 				srk->alg = SSH_SK_ECDSA;
1141 				break;
1142 			case COSE_EDDSA:
1143 				srk->alg = SSH_SK_ED25519;
1144 				break;
1145 			default:
1146 				skdebug(__func__, "unsupported key type %d",
1147 				    fido_cred_type(cred));
1148 				goto out; /* XXX free rk and continue */
1149 			}
1150 
1151 			if (fido_cred_prot(cred) == FIDO_CRED_PROT_UV_REQUIRED)
1152 				srk->flags |=  SSH_SK_USER_VERIFICATION_REQD;
1153 
1154 			if ((r = pack_public_key(srk->alg, cred,
1155 			    &srk->key)) != 0) {
1156 				skdebug(__func__, "pack public key failed");
1157 				goto out;
1158 			}
1159 			/* append */
1160 			if ((tmp = recallocarray(*rksp, *nrksp, (*nrksp) + 1,
1161 			    sizeof(**rksp))) == NULL) {
1162 				skdebug(__func__, "alloc rksp");
1163 				goto out;
1164 			}
1165 			*rksp = tmp;
1166 			(*rksp)[(*nrksp)++] = srk;
1167 			srk = NULL;
1168 		}
1169 	}
1170 	/* Success */
1171 	ret = 0;
1172  out:
1173 	if (srk != NULL) {
1174 		free(srk->application);
1175 		freezero(srk->key.public_key, srk->key.public_key_len);
1176 		freezero(srk->key.key_handle, srk->key.key_handle_len);
1177 		freezero(srk, sizeof(*srk));
1178 	}
1179 	fido_credman_rp_free(&rp);
1180 	fido_credman_rk_free(&rk);
1181 	fido_credman_metadata_free(&metadata);
1182 	return ret;
1183 }
1184 
1185 int
1186 sk_load_resident_keys(const char *pin, struct sk_option **options,
1187     struct sk_resident_key ***rksp, size_t *nrksp)
1188 {
1189 	int ret = SSH_SK_ERR_GENERAL, r = -1;
1190 	size_t i, nrks = 0;
1191 	struct sk_resident_key **rks = NULL;
1192 	struct sk_usbhid *sk = NULL;
1193 	char *device = NULL;
1194 
1195 	*rksp = NULL;
1196 	*nrksp = 0;
1197 
1198 	fido_init(SSH_FIDO_INIT_ARG);
1199 
1200 	if (check_sign_load_resident_options(options, &device) != 0)
1201 		goto out; /* error already logged */
1202 	if (device != NULL)
1203 		sk = sk_open(device);
1204 	else
1205 		sk = sk_probe(NULL, NULL, 0);
1206 	if (sk == NULL) {
1207 		skdebug(__func__, "failed to find sk");
1208 		goto out;
1209 	}
1210 	skdebug(__func__, "trying %s", sk->path);
1211 	if ((r = read_rks(sk, pin, &rks, &nrks)) != 0) {
1212 		skdebug(__func__, "read_rks failed for %s", sk->path);
1213 		ret = r;
1214 		goto out;
1215 	}
1216 	/* success, unless we have no keys but a specific error */
1217 	if (nrks > 0 || ret == SSH_SK_ERR_GENERAL)
1218 		ret = 0;
1219 	*rksp = rks;
1220 	*nrksp = nrks;
1221 	rks = NULL;
1222 	nrks = 0;
1223  out:
1224 	sk_close(sk);
1225 	for (i = 0; i < nrks; i++) {
1226 		free(rks[i]->application);
1227 		freezero(rks[i]->key.public_key, rks[i]->key.public_key_len);
1228 		freezero(rks[i]->key.key_handle, rks[i]->key.key_handle_len);
1229 		freezero(rks[i], sizeof(*rks[i]));
1230 	}
1231 	free(rks);
1232 	return ret;
1233 }
1234 
1235 #endif /* ENABLE_SK_INTERNAL */
1236