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