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