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