Annotation of src/usr.bin/ssh/sk-usbhid.c, Revision 1.5
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;
1.4 deraadt 217: size_t devlist_len = 0, i;
1.1 djm 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:
1.4 deraadt 233: for (i = 0; i < devlist_len; i++) {
1.1 djm 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: int ret = -1;
282:
283: response->public_key = NULL;
284: response->public_key_len = 0;
285:
1.5 ! djm 286: if ((x = BN_new()) == NULL ||
! 287: (y = BN_new()) == NULL ||
1.1 djm 288: (g = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1)) == NULL ||
289: (q = EC_POINT_new(g)) == NULL) {
290: skdebug(__func__, "libcrypto setup failed");
291: goto out;
292: }
293: if ((ptr = fido_cred_pubkey_ptr(cred)) == NULL) {
294: skdebug(__func__, "fido_cred_pubkey_ptr failed");
295: goto out;
296: }
297: if (fido_cred_pubkey_len(cred) != 64) {
298: skdebug(__func__, "bad fido_cred_pubkey_len %zu",
299: fido_cred_pubkey_len(cred));
300: goto out;
301: }
302:
303: if (BN_bin2bn(ptr, 32, x) == NULL ||
304: BN_bin2bn(ptr + 32, 32, y) == NULL) {
305: skdebug(__func__, "BN_bin2bn failed");
306: goto out;
307: }
1.5 ! djm 308: if (EC_POINT_set_affine_coordinates_GFp(g, q, x, y, NULL) != 1) {
1.1 djm 309: skdebug(__func__, "EC_POINT_set_affine_coordinates_GFp failed");
310: goto out;
311: }
312: response->public_key_len = EC_POINT_point2oct(g, q,
1.5 ! djm 313: POINT_CONVERSION_UNCOMPRESSED, NULL, 0, NULL);
1.1 djm 314: if (response->public_key_len == 0 || response->public_key_len > 2048) {
315: skdebug(__func__, "bad pubkey length %zu",
316: response->public_key_len);
317: goto out;
318: }
319: if ((response->public_key = malloc(response->public_key_len)) == NULL) {
320: skdebug(__func__, "malloc pubkey failed");
321: goto out;
322: }
323: if (EC_POINT_point2oct(g, q, POINT_CONVERSION_UNCOMPRESSED,
1.5 ! djm 324: response->public_key, response->public_key_len, NULL) == 0) {
1.1 djm 325: skdebug(__func__, "EC_POINT_point2oct failed");
326: goto out;
327: }
328: /* success */
329: ret = 0;
330: out:
331: if (ret != 0 && response->public_key != NULL) {
332: memset(response->public_key, 0, response->public_key_len);
333: free(response->public_key);
334: response->public_key = NULL;
335: }
336: EC_POINT_free(q);
337: EC_GROUP_free(g);
1.5 ! djm 338: BN_clear_free(x);
! 339: BN_clear_free(y);
1.1 djm 340: return ret;
341: }
342:
343: static int
344: pack_public_key_ed25519(fido_cred_t *cred, struct sk_enroll_response *response)
345: {
346: const uint8_t *ptr;
347: size_t len;
348: int ret = -1;
349:
350: response->public_key = NULL;
351: response->public_key_len = 0;
352:
353: if ((len = fido_cred_pubkey_len(cred)) != 32) {
354: skdebug(__func__, "bad fido_cred_pubkey_len len %zu", len);
355: goto out;
356: }
357: if ((ptr = fido_cred_pubkey_ptr(cred)) == NULL) {
358: skdebug(__func__, "fido_cred_pubkey_ptr failed");
359: goto out;
360: }
361: response->public_key_len = len;
362: if ((response->public_key = malloc(response->public_key_len)) == NULL) {
363: skdebug(__func__, "malloc pubkey failed");
364: goto out;
365: }
366: memcpy(response->public_key, ptr, len);
367: ret = 0;
368: out:
369: if (ret != 0)
370: free(response->public_key);
371: return ret;
372: }
373:
374: static int
375: pack_public_key(int alg, fido_cred_t *cred, struct sk_enroll_response *response)
376: {
377: switch(alg) {
378: case SK_ECDSA:
379: return pack_public_key_ecdsa(cred, response);
380: case SK_ED25519:
381: return pack_public_key_ed25519(cred, response);
382: default:
383: return -1;
384: }
385: }
386:
387: int
388: sk_enroll(int alg, const uint8_t *challenge, size_t challenge_len,
389: const char *application, uint8_t flags,
390: struct sk_enroll_response **enroll_reponse)
391: {
392: fido_cred_t *cred = NULL;
393: fido_dev_t *dev = NULL;
394: const uint8_t *ptr;
395: uint8_t user_id[32];
396: struct sk_enroll_response *response = NULL;
397: size_t len;
398: int cose_alg;
399: int ret = -1;
400: int r;
401: char *device = NULL;
402:
403: (void)flags; /* XXX; unused */
404: #ifdef SK_DEBUG
405: fido_init(FIDO_DEBUG);
406: #endif
407: if (enroll_reponse == NULL) {
408: skdebug(__func__, "enroll_reponse == NULL");
409: goto out;
410: }
411: *enroll_reponse = NULL;
412: switch(alg) {
413: case SK_ECDSA:
414: cose_alg = COSE_ES256;
415: break;
416: case SK_ED25519:
417: cose_alg = COSE_EDDSA;
418: break;
419: default:
420: skdebug(__func__, "unsupported key type %d", alg);
421: goto out;
422: }
423: if ((device = pick_first_device()) == NULL) {
424: skdebug(__func__, "pick_first_device failed");
425: goto out;
426: }
427: skdebug(__func__, "using device %s", device);
428: if ((cred = fido_cred_new()) == NULL) {
429: skdebug(__func__, "fido_cred_new failed");
430: goto out;
431: }
432: memset(user_id, 0, sizeof(user_id));
433: if ((r = fido_cred_set_type(cred, cose_alg)) != FIDO_OK) {
434: skdebug(__func__, "fido_cred_set_type: %s", fido_strerr(r));
435: goto out;
436: }
437: if ((r = fido_cred_set_clientdata_hash(cred, challenge,
438: challenge_len)) != FIDO_OK) {
439: skdebug(__func__, "fido_cred_set_clientdata_hash: %s",
440: fido_strerr(r));
441: goto out;
442: }
443: if ((r = fido_cred_set_user(cred, user_id, sizeof(user_id),
444: "openssh", "openssh", NULL)) != FIDO_OK) {
445: skdebug(__func__, "fido_cred_set_user: %s", fido_strerr(r));
446: goto out;
447: }
448: if ((r = fido_cred_set_rp(cred, application, NULL)) != FIDO_OK) {
449: skdebug(__func__, "fido_cred_set_rp: %s", fido_strerr(r));
450: goto out;
451: }
452: if ((dev = fido_dev_new()) == NULL) {
453: skdebug(__func__, "fido_dev_new failed");
454: goto out;
455: }
456: if ((r = fido_dev_open(dev, device)) != FIDO_OK) {
457: skdebug(__func__, "fido_dev_open: %s", fido_strerr(r));
458: goto out;
459: }
460: if ((r = fido_dev_make_cred(dev, cred, NULL)) != FIDO_OK) {
461: skdebug(__func__, "fido_dev_make_cred: %s", fido_strerr(r));
462: goto out;
463: }
464: if (fido_cred_x5c_ptr(cred) != NULL) {
465: if ((r = fido_cred_verify(cred)) != FIDO_OK) {
466: skdebug(__func__, "fido_cred_verify: %s",
467: fido_strerr(r));
468: goto out;
469: }
470: } else {
471: skdebug(__func__, "self-attested credential");
472: if ((r = fido_cred_verify_self(cred)) != FIDO_OK) {
473: skdebug(__func__, "fido_cred_verify_self: %s",
474: fido_strerr(r));
475: goto out;
476: }
477: }
478: if ((response = calloc(1, sizeof(*response))) == NULL) {
479: skdebug(__func__, "calloc response failed");
480: goto out;
481: }
482: if (pack_public_key(alg, cred, response) != 0) {
483: skdebug(__func__, "pack_public_key failed");
484: goto out;
485: }
486: if ((ptr = fido_cred_id_ptr(cred)) != NULL) {
487: len = fido_cred_id_len(cred);
488: if ((response->key_handle = calloc(1, len)) == NULL) {
489: skdebug(__func__, "calloc key handle failed");
490: goto out;
491: }
492: memcpy(response->key_handle, ptr, len);
493: response->key_handle_len = len;
494: }
495: if ((ptr = fido_cred_sig_ptr(cred)) != NULL) {
496: len = fido_cred_sig_len(cred);
497: if ((response->signature = calloc(1, len)) == NULL) {
498: skdebug(__func__, "calloc signature failed");
499: goto out;
500: }
501: memcpy(response->signature, ptr, len);
502: response->signature_len = len;
503: }
504: if ((ptr = fido_cred_x5c_ptr(cred)) != NULL) {
505: len = fido_cred_x5c_len(cred);
506: if ((response->attestation_cert = calloc(1, len)) == NULL) {
507: skdebug(__func__, "calloc attestation cert failed");
508: goto out;
509: }
510: memcpy(response->attestation_cert, ptr, len);
511: response->attestation_cert_len = len;
512: }
513: *enroll_reponse = response;
514: response = NULL;
515: ret = 0;
516: out:
517: free(device);
518: if (response != NULL) {
519: free(response->public_key);
520: free(response->key_handle);
521: free(response->signature);
522: free(response->attestation_cert);
523: free(response);
524: }
525: if (dev != NULL) {
526: fido_dev_close(dev);
527: fido_dev_free(&dev);
528: }
529: if (cred != NULL) {
530: fido_cred_free(&cred);
531: }
532: return ret;
533: }
534:
535: static int
536: pack_sig_ecdsa(fido_assert_t *assert, struct sk_sign_response *response)
537: {
538: ECDSA_SIG *sig = NULL;
539: const BIGNUM *sig_r, *sig_s;
540: const unsigned char *cp;
541: size_t sig_len;
542: int ret = -1;
543:
544: cp = fido_assert_sig_ptr(assert, 0);
545: sig_len = fido_assert_sig_len(assert, 0);
546: if ((sig = d2i_ECDSA_SIG(NULL, &cp, sig_len)) == NULL) {
547: skdebug(__func__, "d2i_ECDSA_SIG failed");
548: goto out;
549: }
550: ECDSA_SIG_get0(sig, &sig_r, &sig_s);
551: response->sig_r_len = BN_num_bytes(sig_r);
552: response->sig_s_len = BN_num_bytes(sig_s);
553: if ((response->sig_r = calloc(1, response->sig_r_len)) == NULL ||
554: (response->sig_s = calloc(1, response->sig_s_len)) == NULL) {
555: skdebug(__func__, "calloc signature failed");
556: goto out;
557: }
558: BN_bn2bin(sig_r, response->sig_r);
559: BN_bn2bin(sig_s, response->sig_s);
560: ret = 0;
561: out:
562: ECDSA_SIG_free(sig);
563: if (ret != 0) {
564: free(response->sig_r);
565: free(response->sig_s);
566: response->sig_r = NULL;
567: response->sig_s = NULL;
568: }
569: return ret;
570: }
571:
572: static int
573: pack_sig_ed25519(fido_assert_t *assert, struct sk_sign_response *response)
574: {
575: const unsigned char *ptr;
576: size_t len;
577: int ret = -1;
578:
579: ptr = fido_assert_sig_ptr(assert, 0);
580: len = fido_assert_sig_len(assert, 0);
581: if (len != 64) {
582: skdebug(__func__, "bad length %zu", len);
583: goto out;
584: }
585: response->sig_r_len = len;
586: if ((response->sig_r = calloc(1, response->sig_r_len)) == NULL) {
587: skdebug(__func__, "calloc signature failed");
588: goto out;
589: }
590: memcpy(response->sig_r, ptr, len);
591: ret = 0;
592: out:
593: if (ret != 0) {
594: free(response->sig_r);
595: response->sig_r = NULL;
596: }
597: return ret;
598: }
599:
600: static int
601: pack_sig(int alg, fido_assert_t *assert, struct sk_sign_response *response)
602: {
603: switch(alg) {
604: case SK_ECDSA:
605: return pack_sig_ecdsa(assert, response);
606: case SK_ED25519:
607: return pack_sig_ed25519(assert, response);
608: default:
609: return -1;
610: }
611: }
612:
613: int
614: sk_sign(int alg, const uint8_t *message, size_t message_len,
615: const char *application,
616: const uint8_t *key_handle, size_t key_handle_len,
617: uint8_t flags, struct sk_sign_response **sign_response)
618: {
619: fido_assert_t *assert = NULL;
620: fido_dev_t *dev = NULL;
621: struct sk_sign_response *response = NULL;
622: int ret = -1;
623: int r;
624:
625: #ifdef SK_DEBUG
626: fido_init(FIDO_DEBUG);
627: #endif
628:
629: if (sign_response == NULL) {
630: skdebug(__func__, "sign_response == NULL");
631: goto out;
632: }
633: *sign_response = NULL;
634: if ((dev = find_device(message, message_len, application, key_handle,
635: key_handle_len)) == NULL) {
636: skdebug(__func__, "couldn't find device for key handle");
637: goto out;
638: }
639: if ((assert = fido_assert_new()) == NULL) {
640: skdebug(__func__, "fido_assert_new failed");
641: goto out;
642: }
643: if ((r = fido_assert_set_clientdata_hash(assert, message,
644: message_len)) != FIDO_OK) {
645: skdebug(__func__, "fido_assert_set_clientdata_hash: %s",
646: fido_strerr(r));
647: goto out;
648: }
649: if ((r = fido_assert_set_rp(assert, application)) != FIDO_OK) {
650: skdebug(__func__, "fido_assert_set_rp: %s", fido_strerr(r));
651: goto out;
652: }
653: if ((r = fido_assert_allow_cred(assert, key_handle,
654: key_handle_len)) != FIDO_OK) {
655: skdebug(__func__, "fido_assert_allow_cred: %s", fido_strerr(r));
656: goto out;
657: }
658: if ((r = fido_assert_set_up(assert,
659: (flags & SK_USER_PRESENCE_REQD) ?
660: FIDO_OPT_TRUE : FIDO_OPT_FALSE)) != FIDO_OK) {
661: skdebug(__func__, "fido_assert_set_up: %s", fido_strerr(r));
662: goto out;
663: }
664: if ((r = fido_dev_get_assert(dev, assert, NULL)) != FIDO_OK) {
665: skdebug(__func__, "fido_dev_get_assert: %s", fido_strerr(r));
666: goto out;
667: }
668: if ((response = calloc(1, sizeof(*response))) == NULL) {
669: skdebug(__func__, "calloc response failed");
670: goto out;
671: }
672: response->flags = fido_assert_flags(assert, 0);
673: response->counter = fido_assert_sigcount(assert, 0);
674: if (pack_sig(alg, assert, response) != 0) {
675: skdebug(__func__, "pack_sig failed");
676: goto out;
677: }
678: *sign_response = response;
679: response = NULL;
680: ret = 0;
681: out:
682: if (response != NULL) {
683: free(response->sig_r);
684: free(response->sig_s);
685: free(response);
686: }
687: if (dev != NULL) {
688: fido_dev_close(dev);
689: fido_dev_free(&dev);
690: }
691: if (assert != NULL) {
692: fido_assert_free(&assert);
693: }
694: return ret;
695: }