Annotation of src/usr.bin/ssh/sk-usbhid.c, Revision 1.7
1.1 djm 1: /*
2: * Copyright (c) 2019 Markus Friedl
3: *
4: * Permission to use, copy, modify, and distribute this software for any
5: * purpose with or without fee is hereby granted, provided that the above
6: * copyright notice and this permission notice appear in all copies.
7: *
8: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15: */
16:
17: #include <stdint.h>
18: #include <stdlib.h>
19: #include <string.h>
20: #include <stdio.h>
21: #include <stddef.h>
22: #include <stdarg.h>
23:
1.7 ! naddy 24: #ifdef WITH_OPENSSL
1.1 djm 25: #include <openssl/opensslv.h>
26: #include <openssl/crypto.h>
27: #include <openssl/bn.h>
28: #include <openssl/ec.h>
29: #include <openssl/ecdsa.h>
1.7 ! naddy 30: #endif /* WITH_OPENSSL */
1.1 djm 31:
32: #include <fido.h>
33:
34: #ifndef SK_STANDALONE
35: #include "log.h"
36: #include "xmalloc.h"
37: #endif
38:
39: /* #define SK_DEBUG 1 */
40:
41: #define MAX_FIDO_DEVICES 256
42:
43: /* Compatibility with OpenSSH 1.0.x */
44: #if (OPENSSL_VERSION_NUMBER < 0x10100000L)
45: #define ECDSA_SIG_get0(sig, pr, ps) \
46: do { \
47: (*pr) = sig->r; \
48: (*ps) = sig->s; \
49: } while (0)
50: #endif
51:
52: #define SK_VERSION_MAJOR 0x00020000 /* current API version */
53:
54: /* Flags */
55: #define SK_USER_PRESENCE_REQD 0x01
56:
57: /* Algs */
58: #define SK_ECDSA 0x00
59: #define SK_ED25519 0x01
60:
61: struct sk_enroll_response {
62: uint8_t *public_key;
63: size_t public_key_len;
64: uint8_t *key_handle;
65: size_t key_handle_len;
66: uint8_t *signature;
67: size_t signature_len;
68: uint8_t *attestation_cert;
69: size_t attestation_cert_len;
70: };
71:
72: struct sk_sign_response {
73: uint8_t flags;
74: uint32_t counter;
75: uint8_t *sig_r;
76: size_t sig_r_len;
77: uint8_t *sig_s;
78: size_t sig_s_len;
79: };
80:
81: /* If building as part of OpenSSH, then rename exported functions */
82: #if !defined(SK_STANDALONE)
83: #define sk_api_version ssh_sk_api_version
84: #define sk_enroll ssh_sk_enroll
85: #define sk_sign ssh_sk_sign
86: #endif
87:
88: /* Return the version of the middleware API */
89: uint32_t sk_api_version(void);
90:
91: /* Enroll a U2F key (private key generation) */
92: int sk_enroll(int alg, const uint8_t *challenge, size_t challenge_len,
93: const char *application, uint8_t flags,
94: struct sk_enroll_response **enroll_response);
95:
96: /* Sign a challenge */
97: int sk_sign(int alg, const uint8_t *message, size_t message_len,
98: const char *application, const uint8_t *key_handle, size_t key_handle_len,
99: uint8_t flags, struct sk_sign_response **sign_response);
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);
1.2 djm 114: debug("%s: %s", func, msg);
1.1 djm 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 SK_VERSION_MAJOR;
134: }
135:
136: /* Select the first identified FIDO device attached to the system */
137: static char *
138: pick_first_device(void)
139: {
140: char *ret = NULL;
141: fido_dev_info_t *devlist = NULL;
142: size_t olen = 0;
143: int r;
144: const fido_dev_info_t *di;
145:
146: if ((devlist = fido_dev_info_new(1)) == NULL) {
147: skdebug(__func__, "fido_dev_info_new failed");
148: goto out;
149: }
150: if ((r = fido_dev_info_manifest(devlist, 1, &olen)) != FIDO_OK) {
151: skdebug(__func__, "fido_dev_info_manifest failed: %s",
152: fido_strerr(r));
153: goto out;
154: }
155: if (olen != 1) {
156: skdebug(__func__, "fido_dev_info_manifest bad len %zu", olen);
157: goto out;
158: }
159: di = fido_dev_info_ptr(devlist, 0);
160: if ((ret = strdup(fido_dev_info_path(di))) == NULL) {
161: skdebug(__func__, "fido_dev_info_path failed");
162: goto out;
163: }
164: out:
165: fido_dev_info_free(&devlist, 1);
166: return ret;
167: }
168:
169: /* Check if the specified key handle exists on a given device. */
170: static int
171: try_device(fido_dev_t *dev, const uint8_t *message, size_t message_len,
172: const char *application, const uint8_t *key_handle, size_t key_handle_len)
173: {
174: fido_assert_t *assert = NULL;
175: int r = FIDO_ERR_INTERNAL;
176:
177: if ((assert = fido_assert_new()) == NULL) {
178: skdebug(__func__, "fido_assert_new failed");
179: goto out;
180: }
181: if ((r = fido_assert_set_clientdata_hash(assert, message,
182: message_len)) != FIDO_OK) {
183: skdebug(__func__, "fido_assert_set_clientdata_hash: %s",
184: fido_strerr(r));
185: goto out;
186: }
187: if ((r = fido_assert_set_rp(assert, application)) != FIDO_OK) {
188: skdebug(__func__, "fido_assert_set_rp: %s", fido_strerr(r));
189: goto out;
190: }
191: if ((r = fido_assert_allow_cred(assert, key_handle,
192: key_handle_len)) != FIDO_OK) {
193: skdebug(__func__, "fido_assert_allow_cred: %s", fido_strerr(r));
194: goto out;
195: }
196: if ((r = fido_assert_set_up(assert, FIDO_OPT_FALSE)) != FIDO_OK) {
197: skdebug(__func__, "fido_assert_up: %s", fido_strerr(r));
198: goto out;
199: }
200: r = fido_dev_get_assert(dev, assert, NULL);
201: skdebug(__func__, "fido_dev_get_assert: %s", fido_strerr(r));
1.3 djm 202: if (r == FIDO_ERR_USER_PRESENCE_REQUIRED) {
203: /* U2F tokens may return this */
204: r = FIDO_OK;
205: }
1.1 djm 206: out:
207: fido_assert_free(&assert);
208:
209: return r != FIDO_OK ? -1 : 0;
210: }
211:
212: /* Iterate over configured devices looking for a specific key handle */
213: static fido_dev_t *
214: find_device(const uint8_t *message, size_t message_len, const char *application,
215: const uint8_t *key_handle, size_t key_handle_len)
216: {
217: fido_dev_info_t *devlist = NULL;
218: fido_dev_t *dev = NULL;
1.4 deraadt 219: size_t devlist_len = 0, i;
1.1 djm 220: const char *path;
221: int r;
222:
223: if ((devlist = fido_dev_info_new(MAX_FIDO_DEVICES)) == NULL) {
224: skdebug(__func__, "fido_dev_info_new failed");
225: goto out;
226: }
227: if ((r = fido_dev_info_manifest(devlist, MAX_FIDO_DEVICES,
228: &devlist_len)) != FIDO_OK) {
229: skdebug(__func__, "fido_dev_info_manifest: %s", fido_strerr(r));
230: goto out;
231: }
232:
233: skdebug(__func__, "found %zu device(s)", devlist_len);
234:
1.4 deraadt 235: for (i = 0; i < devlist_len; i++) {
1.1 djm 236: const fido_dev_info_t *di = fido_dev_info_ptr(devlist, i);
237:
238: if (di == NULL) {
239: skdebug(__func__, "fido_dev_info_ptr %zu failed", i);
240: continue;
241: }
242: if ((path = fido_dev_info_path(di)) == NULL) {
243: skdebug(__func__, "fido_dev_info_path %zu failed", i);
244: continue;
245: }
246: skdebug(__func__, "trying device %zu: %s", i, path);
247: if ((dev = fido_dev_new()) == NULL) {
248: skdebug(__func__, "fido_dev_new failed");
249: continue;
250: }
251: if ((r = fido_dev_open(dev, path)) != FIDO_OK) {
252: skdebug(__func__, "fido_dev_open failed");
253: fido_dev_free(&dev);
254: continue;
255: }
256: if (try_device(dev, message, message_len, application,
257: key_handle, key_handle_len) == 0) {
258: skdebug(__func__, "found key");
259: break;
260: }
261: fido_dev_close(dev);
262: fido_dev_free(&dev);
263: }
264:
265: out:
266: if (devlist != NULL)
267: fido_dev_info_free(&devlist, MAX_FIDO_DEVICES);
268:
269: return dev;
270: }
271:
1.7 ! naddy 272: #ifdef WITH_OPENSSL
1.1 djm 273: /*
274: * The key returned via fido_cred_pubkey_ptr() is in affine coordinates,
275: * but the API expects a SEC1 octet string.
276: */
277: static int
278: pack_public_key_ecdsa(fido_cred_t *cred, struct sk_enroll_response *response)
279: {
280: const uint8_t *ptr;
281: BIGNUM *x = NULL, *y = NULL;
282: EC_POINT *q = NULL;
283: EC_GROUP *g = NULL;
284: int ret = -1;
285:
286: response->public_key = NULL;
287: response->public_key_len = 0;
288:
1.5 djm 289: if ((x = BN_new()) == NULL ||
290: (y = BN_new()) == NULL ||
1.1 djm 291: (g = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1)) == NULL ||
292: (q = EC_POINT_new(g)) == NULL) {
293: skdebug(__func__, "libcrypto setup failed");
294: goto out;
295: }
296: if ((ptr = fido_cred_pubkey_ptr(cred)) == NULL) {
297: skdebug(__func__, "fido_cred_pubkey_ptr failed");
298: goto out;
299: }
300: if (fido_cred_pubkey_len(cred) != 64) {
301: skdebug(__func__, "bad fido_cred_pubkey_len %zu",
302: fido_cred_pubkey_len(cred));
303: goto out;
304: }
305:
306: if (BN_bin2bn(ptr, 32, x) == NULL ||
307: BN_bin2bn(ptr + 32, 32, y) == NULL) {
308: skdebug(__func__, "BN_bin2bn failed");
309: goto out;
310: }
1.5 djm 311: if (EC_POINT_set_affine_coordinates_GFp(g, q, x, y, NULL) != 1) {
1.1 djm 312: skdebug(__func__, "EC_POINT_set_affine_coordinates_GFp failed");
313: goto out;
314: }
315: response->public_key_len = EC_POINT_point2oct(g, q,
1.5 djm 316: POINT_CONVERSION_UNCOMPRESSED, NULL, 0, NULL);
1.1 djm 317: if (response->public_key_len == 0 || response->public_key_len > 2048) {
318: skdebug(__func__, "bad pubkey length %zu",
319: response->public_key_len);
320: goto out;
321: }
322: if ((response->public_key = malloc(response->public_key_len)) == NULL) {
323: skdebug(__func__, "malloc pubkey failed");
324: goto out;
325: }
326: if (EC_POINT_point2oct(g, q, POINT_CONVERSION_UNCOMPRESSED,
1.5 djm 327: response->public_key, response->public_key_len, NULL) == 0) {
1.1 djm 328: skdebug(__func__, "EC_POINT_point2oct failed");
329: goto out;
330: }
331: /* success */
332: ret = 0;
333: out:
334: if (ret != 0 && response->public_key != NULL) {
335: memset(response->public_key, 0, response->public_key_len);
336: free(response->public_key);
337: response->public_key = NULL;
338: }
339: EC_POINT_free(q);
340: EC_GROUP_free(g);
1.5 djm 341: BN_clear_free(x);
342: BN_clear_free(y);
1.1 djm 343: return ret;
344: }
1.7 ! naddy 345: #endif /* WITH_OPENSSL */
1.1 djm 346:
347: static int
348: pack_public_key_ed25519(fido_cred_t *cred, struct sk_enroll_response *response)
349: {
350: const uint8_t *ptr;
351: size_t len;
352: int ret = -1;
353:
354: response->public_key = NULL;
355: response->public_key_len = 0;
356:
357: if ((len = fido_cred_pubkey_len(cred)) != 32) {
358: skdebug(__func__, "bad fido_cred_pubkey_len len %zu", len);
359: goto out;
360: }
361: if ((ptr = fido_cred_pubkey_ptr(cred)) == NULL) {
362: skdebug(__func__, "fido_cred_pubkey_ptr failed");
363: goto out;
364: }
365: response->public_key_len = len;
366: if ((response->public_key = malloc(response->public_key_len)) == NULL) {
367: skdebug(__func__, "malloc pubkey failed");
368: goto out;
369: }
370: memcpy(response->public_key, ptr, len);
371: ret = 0;
372: out:
373: if (ret != 0)
374: free(response->public_key);
375: return ret;
376: }
377:
378: static int
379: pack_public_key(int alg, fido_cred_t *cred, struct sk_enroll_response *response)
380: {
381: switch(alg) {
1.7 ! naddy 382: #ifdef WITH_OPENSSL
1.1 djm 383: case SK_ECDSA:
384: return pack_public_key_ecdsa(cred, response);
1.7 ! naddy 385: #endif /* WITH_OPENSSL */
1.1 djm 386: case SK_ED25519:
387: return pack_public_key_ed25519(cred, response);
388: default:
389: return -1;
390: }
391: }
392:
393: int
394: sk_enroll(int alg, const uint8_t *challenge, size_t challenge_len,
395: const char *application, uint8_t flags,
1.6 markus 396: struct sk_enroll_response **enroll_response)
1.1 djm 397: {
398: fido_cred_t *cred = NULL;
399: fido_dev_t *dev = NULL;
400: const uint8_t *ptr;
401: uint8_t user_id[32];
402: struct sk_enroll_response *response = NULL;
403: size_t len;
404: int cose_alg;
405: int ret = -1;
406: int r;
407: char *device = NULL;
408:
409: (void)flags; /* XXX; unused */
410: #ifdef SK_DEBUG
411: fido_init(FIDO_DEBUG);
412: #endif
1.6 markus 413: if (enroll_response == NULL) {
414: skdebug(__func__, "enroll_response == NULL");
1.1 djm 415: goto out;
416: }
1.6 markus 417: *enroll_response = NULL;
1.1 djm 418: switch(alg) {
1.7 ! naddy 419: #ifdef WITH_OPENSSL
1.1 djm 420: case SK_ECDSA:
421: cose_alg = COSE_ES256;
422: break;
1.7 ! naddy 423: #endif /* WITH_OPENSSL */
1.1 djm 424: case SK_ED25519:
425: cose_alg = COSE_EDDSA;
426: break;
427: default:
428: skdebug(__func__, "unsupported key type %d", alg);
429: goto out;
430: }
431: if ((device = pick_first_device()) == NULL) {
432: skdebug(__func__, "pick_first_device failed");
433: goto out;
434: }
435: skdebug(__func__, "using device %s", device);
436: if ((cred = fido_cred_new()) == NULL) {
437: skdebug(__func__, "fido_cred_new failed");
438: goto out;
439: }
440: memset(user_id, 0, sizeof(user_id));
441: if ((r = fido_cred_set_type(cred, cose_alg)) != FIDO_OK) {
442: skdebug(__func__, "fido_cred_set_type: %s", fido_strerr(r));
443: goto out;
444: }
445: if ((r = fido_cred_set_clientdata_hash(cred, challenge,
446: challenge_len)) != FIDO_OK) {
447: skdebug(__func__, "fido_cred_set_clientdata_hash: %s",
448: fido_strerr(r));
449: goto out;
450: }
451: if ((r = fido_cred_set_user(cred, user_id, sizeof(user_id),
452: "openssh", "openssh", NULL)) != FIDO_OK) {
453: skdebug(__func__, "fido_cred_set_user: %s", fido_strerr(r));
454: goto out;
455: }
456: if ((r = fido_cred_set_rp(cred, application, NULL)) != FIDO_OK) {
457: skdebug(__func__, "fido_cred_set_rp: %s", fido_strerr(r));
458: goto out;
459: }
460: if ((dev = fido_dev_new()) == NULL) {
461: skdebug(__func__, "fido_dev_new failed");
462: goto out;
463: }
464: if ((r = fido_dev_open(dev, device)) != FIDO_OK) {
465: skdebug(__func__, "fido_dev_open: %s", fido_strerr(r));
466: goto out;
467: }
468: if ((r = fido_dev_make_cred(dev, cred, NULL)) != FIDO_OK) {
469: skdebug(__func__, "fido_dev_make_cred: %s", fido_strerr(r));
470: goto out;
471: }
472: if (fido_cred_x5c_ptr(cred) != NULL) {
473: if ((r = fido_cred_verify(cred)) != FIDO_OK) {
474: skdebug(__func__, "fido_cred_verify: %s",
475: fido_strerr(r));
476: goto out;
477: }
478: } else {
479: skdebug(__func__, "self-attested credential");
480: if ((r = fido_cred_verify_self(cred)) != FIDO_OK) {
481: skdebug(__func__, "fido_cred_verify_self: %s",
482: fido_strerr(r));
483: goto out;
484: }
485: }
486: if ((response = calloc(1, sizeof(*response))) == NULL) {
487: skdebug(__func__, "calloc response failed");
488: goto out;
489: }
490: if (pack_public_key(alg, cred, response) != 0) {
491: skdebug(__func__, "pack_public_key failed");
492: goto out;
493: }
494: if ((ptr = fido_cred_id_ptr(cred)) != NULL) {
495: len = fido_cred_id_len(cred);
496: if ((response->key_handle = calloc(1, len)) == NULL) {
497: skdebug(__func__, "calloc key handle failed");
498: goto out;
499: }
500: memcpy(response->key_handle, ptr, len);
501: response->key_handle_len = len;
502: }
503: if ((ptr = fido_cred_sig_ptr(cred)) != NULL) {
504: len = fido_cred_sig_len(cred);
505: if ((response->signature = calloc(1, len)) == NULL) {
506: skdebug(__func__, "calloc signature failed");
507: goto out;
508: }
509: memcpy(response->signature, ptr, len);
510: response->signature_len = len;
511: }
512: if ((ptr = fido_cred_x5c_ptr(cred)) != NULL) {
513: len = fido_cred_x5c_len(cred);
514: if ((response->attestation_cert = calloc(1, len)) == NULL) {
515: skdebug(__func__, "calloc attestation cert failed");
516: goto out;
517: }
518: memcpy(response->attestation_cert, ptr, len);
519: response->attestation_cert_len = len;
520: }
1.6 markus 521: *enroll_response = response;
1.1 djm 522: response = NULL;
523: ret = 0;
524: out:
525: free(device);
526: if (response != NULL) {
527: free(response->public_key);
528: free(response->key_handle);
529: free(response->signature);
530: free(response->attestation_cert);
531: free(response);
532: }
533: if (dev != NULL) {
534: fido_dev_close(dev);
535: fido_dev_free(&dev);
536: }
537: if (cred != NULL) {
538: fido_cred_free(&cred);
539: }
540: return ret;
541: }
542:
1.7 ! naddy 543: #ifdef WITH_OPENSSL
1.1 djm 544: static int
545: pack_sig_ecdsa(fido_assert_t *assert, struct sk_sign_response *response)
546: {
547: ECDSA_SIG *sig = NULL;
548: const BIGNUM *sig_r, *sig_s;
549: const unsigned char *cp;
550: size_t sig_len;
551: int ret = -1;
552:
553: cp = fido_assert_sig_ptr(assert, 0);
554: sig_len = fido_assert_sig_len(assert, 0);
555: if ((sig = d2i_ECDSA_SIG(NULL, &cp, sig_len)) == NULL) {
556: skdebug(__func__, "d2i_ECDSA_SIG failed");
557: goto out;
558: }
559: ECDSA_SIG_get0(sig, &sig_r, &sig_s);
560: response->sig_r_len = BN_num_bytes(sig_r);
561: response->sig_s_len = BN_num_bytes(sig_s);
562: if ((response->sig_r = calloc(1, response->sig_r_len)) == NULL ||
563: (response->sig_s = calloc(1, response->sig_s_len)) == NULL) {
564: skdebug(__func__, "calloc signature failed");
565: goto out;
566: }
567: BN_bn2bin(sig_r, response->sig_r);
568: BN_bn2bin(sig_s, response->sig_s);
569: ret = 0;
570: out:
571: ECDSA_SIG_free(sig);
572: if (ret != 0) {
573: free(response->sig_r);
574: free(response->sig_s);
575: response->sig_r = NULL;
576: response->sig_s = NULL;
577: }
578: return ret;
579: }
1.7 ! naddy 580: #endif /* WITH_OPENSSL */
1.1 djm 581:
582: static int
583: pack_sig_ed25519(fido_assert_t *assert, struct sk_sign_response *response)
584: {
585: const unsigned char *ptr;
586: size_t len;
587: int ret = -1;
588:
589: ptr = fido_assert_sig_ptr(assert, 0);
590: len = fido_assert_sig_len(assert, 0);
591: if (len != 64) {
592: skdebug(__func__, "bad length %zu", len);
593: goto out;
594: }
595: response->sig_r_len = len;
596: if ((response->sig_r = calloc(1, response->sig_r_len)) == NULL) {
597: skdebug(__func__, "calloc signature failed");
598: goto out;
599: }
600: memcpy(response->sig_r, ptr, len);
601: ret = 0;
602: out:
603: if (ret != 0) {
604: free(response->sig_r);
605: response->sig_r = NULL;
606: }
607: return ret;
608: }
609:
610: static int
611: pack_sig(int alg, fido_assert_t *assert, struct sk_sign_response *response)
612: {
613: switch(alg) {
1.7 ! naddy 614: #ifdef WITH_OPENSSL
1.1 djm 615: case SK_ECDSA:
616: return pack_sig_ecdsa(assert, response);
1.7 ! naddy 617: #endif /* WITH_OPENSSL */
1.1 djm 618: case SK_ED25519:
619: return pack_sig_ed25519(assert, response);
620: default:
621: return -1;
622: }
623: }
624:
625: int
626: sk_sign(int alg, const uint8_t *message, size_t message_len,
627: const char *application,
628: const uint8_t *key_handle, size_t key_handle_len,
629: uint8_t flags, struct sk_sign_response **sign_response)
630: {
631: fido_assert_t *assert = NULL;
632: fido_dev_t *dev = NULL;
633: struct sk_sign_response *response = NULL;
634: int ret = -1;
635: int r;
636:
637: #ifdef SK_DEBUG
638: fido_init(FIDO_DEBUG);
639: #endif
640:
641: if (sign_response == NULL) {
642: skdebug(__func__, "sign_response == NULL");
643: goto out;
644: }
645: *sign_response = NULL;
646: if ((dev = find_device(message, message_len, application, key_handle,
647: key_handle_len)) == NULL) {
648: skdebug(__func__, "couldn't find device for key handle");
649: goto out;
650: }
651: if ((assert = fido_assert_new()) == NULL) {
652: skdebug(__func__, "fido_assert_new failed");
653: goto out;
654: }
655: if ((r = fido_assert_set_clientdata_hash(assert, message,
656: message_len)) != FIDO_OK) {
657: skdebug(__func__, "fido_assert_set_clientdata_hash: %s",
658: fido_strerr(r));
659: goto out;
660: }
661: if ((r = fido_assert_set_rp(assert, application)) != FIDO_OK) {
662: skdebug(__func__, "fido_assert_set_rp: %s", fido_strerr(r));
663: goto out;
664: }
665: if ((r = fido_assert_allow_cred(assert, key_handle,
666: key_handle_len)) != FIDO_OK) {
667: skdebug(__func__, "fido_assert_allow_cred: %s", fido_strerr(r));
668: goto out;
669: }
670: if ((r = fido_assert_set_up(assert,
671: (flags & SK_USER_PRESENCE_REQD) ?
672: FIDO_OPT_TRUE : FIDO_OPT_FALSE)) != FIDO_OK) {
673: skdebug(__func__, "fido_assert_set_up: %s", fido_strerr(r));
674: goto out;
675: }
676: if ((r = fido_dev_get_assert(dev, assert, NULL)) != FIDO_OK) {
677: skdebug(__func__, "fido_dev_get_assert: %s", fido_strerr(r));
678: goto out;
679: }
680: if ((response = calloc(1, sizeof(*response))) == NULL) {
681: skdebug(__func__, "calloc response failed");
682: goto out;
683: }
684: response->flags = fido_assert_flags(assert, 0);
685: response->counter = fido_assert_sigcount(assert, 0);
686: if (pack_sig(alg, assert, response) != 0) {
687: skdebug(__func__, "pack_sig failed");
688: goto out;
689: }
690: *sign_response = response;
691: response = NULL;
692: ret = 0;
693: out:
694: if (response != NULL) {
695: free(response->sig_r);
696: free(response->sig_s);
697: free(response);
698: }
699: if (dev != NULL) {
700: fido_dev_close(dev);
701: fido_dev_free(&dev);
702: }
703: if (assert != NULL) {
704: fido_assert_free(&assert);
705: }
706: return ret;
707: }