Annotation of src/usr.bin/ssh/ssh-pkcs11-client.c, Revision 1.18
1.18 ! djm 1: /* $OpenBSD: ssh-pkcs11-client.c,v 1.17 2020/10/18 11:32:02 djm Exp $ */
1.1 markus 2: /*
3: * Copyright (c) 2010 Markus Friedl. All rights reserved.
1.12 djm 4: * Copyright (c) 2014 Pedro Martelletto. All rights reserved.
1.1 markus 5: *
6: * Permission to use, copy, modify, and distribute this software for any
7: * purpose with or without fee is hereby granted, provided that the above
8: * copyright notice and this permission notice appear in all copies.
9: *
10: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17: */
18:
19: #include <sys/types.h>
20: #include <sys/time.h>
21: #include <sys/socket.h>
22:
23: #include <stdarg.h>
24: #include <string.h>
25: #include <unistd.h>
26: #include <errno.h>
1.18 ! djm 27: #include <limits.h>
1.5 djm 28:
1.12 djm 29: #include <openssl/ecdsa.h>
1.5 djm 30: #include <openssl/rsa.h>
1.1 markus 31:
32: #include "pathnames.h"
33: #include "xmalloc.h"
1.9 markus 34: #include "sshbuf.h"
1.1 markus 35: #include "log.h"
36: #include "misc.h"
1.9 markus 37: #include "sshkey.h"
1.1 markus 38: #include "authfd.h"
39: #include "atomicio.h"
40: #include "ssh-pkcs11.h"
1.9 markus 41: #include "ssherr.h"
1.1 markus 42:
43: /* borrows code from sftp-server and ssh-agent */
44:
1.18 ! djm 45: /*
! 46: * Maintain a list of ssh-pkcs11-helper subprocesses. These may be looked up
! 47: * by provider path or their unique EC/RSA METHOD pointers.
! 48: */
! 49: struct helper {
! 50: char *path;
! 51: pid_t pid;
! 52: int fd;
! 53: RSA_METHOD *rsa_meth;
! 54: EC_KEY_METHOD *ec_meth;
! 55: int (*rsa_finish)(RSA *rsa);
! 56: void (*ec_finish)(EC_KEY *key);
! 57: size_t nrsa, nec; /* number of active keys of each type */
! 58: };
! 59: static struct helper **helpers;
! 60: static size_t nhelpers;
! 61:
! 62: static struct helper *
! 63: helper_by_provider(const char *path)
! 64: {
! 65: size_t i;
! 66:
! 67: for (i = 0; i < nhelpers; i++) {
! 68: if (helpers[i] == NULL || helpers[i]->path == NULL ||
! 69: helpers[i]->fd == -1)
! 70: continue;
! 71: if (strcmp(helpers[i]->path, path) == 0)
! 72: return helpers[i];
! 73: }
! 74: return NULL;
! 75: }
! 76:
! 77: static struct helper *
! 78: helper_by_rsa(const RSA *rsa)
! 79: {
! 80: size_t i;
! 81: const RSA_METHOD *meth;
! 82:
! 83: if ((meth = RSA_get_method(rsa)) == NULL)
! 84: return NULL;
! 85: for (i = 0; i < nhelpers; i++) {
! 86: if (helpers[i] != NULL && helpers[i]->rsa_meth == meth)
! 87: return helpers[i];
! 88: }
! 89: return NULL;
! 90:
! 91: }
! 92:
! 93: static struct helper *
! 94: helper_by_ec(const EC_KEY *ec)
! 95: {
! 96: size_t i;
! 97: const EC_KEY_METHOD *meth;
! 98:
! 99: if ((meth = EC_KEY_get_method(ec)) == NULL)
! 100: return NULL;
! 101: for (i = 0; i < nhelpers; i++) {
! 102: if (helpers[i] != NULL && helpers[i]->ec_meth == meth)
! 103: return helpers[i];
! 104: }
! 105: return NULL;
! 106:
! 107: }
1.1 markus 108:
109: static void
1.18 ! djm 110: helper_free(struct helper *helper)
! 111: {
! 112: size_t i;
! 113: int found = 0;
! 114:
! 115: if (helper == NULL)
! 116: return;
! 117: if (helper->path == NULL || helper->ec_meth == NULL ||
! 118: helper->rsa_meth == NULL)
! 119: fatal_f("inconsistent helper");
! 120: debug3_f("free helper for provider %s", helper->path);
! 121: for (i = 0; i < nhelpers; i++) {
! 122: if (helpers[i] == helper) {
! 123: if (found)
! 124: fatal_f("helper recorded more than once");
! 125: found = 1;
! 126: }
! 127: else if (found)
! 128: helpers[i - 1] = helpers[i];
! 129: }
! 130: if (found) {
! 131: helpers = xrecallocarray(helpers, nhelpers,
! 132: nhelpers - 1, sizeof(*helpers));
! 133: nhelpers--;
! 134: }
! 135: free(helper->path);
! 136: EC_KEY_METHOD_free(helper->ec_meth);
! 137: RSA_meth_free(helper->rsa_meth);
! 138: free(helper);
! 139: }
! 140:
! 141: static void
! 142: helper_terminate(struct helper *helper)
! 143: {
! 144: if (helper == NULL) {
! 145: return;
! 146: } else if (helper->fd == -1) {
! 147: debug3_f("already terminated");
! 148: } else {
! 149: debug3_f("terminating helper for %s; "
! 150: "remaining %zu RSA %zu ECDSA",
! 151: helper->path, helper->nrsa, helper->nec);
! 152: close(helper->fd);
! 153: /* XXX waitpid() */
! 154: helper->fd = -1;
! 155: helper->pid = -1;
! 156: }
! 157: /*
! 158: * Don't delete the helper entry until there are no remaining keys
! 159: * that reference it. Otherwise, any signing operation would call
! 160: * a free'd METHOD pointer and that would be bad.
! 161: */
! 162: if (helper->nrsa == 0 && helper->nec == 0)
! 163: helper_free(helper);
! 164: }
! 165:
! 166: static void
! 167: send_msg(int fd, struct sshbuf *m)
1.1 markus 168: {
169: u_char buf[4];
1.9 markus 170: size_t mlen = sshbuf_len(m);
171: int r;
1.1 markus 172:
1.18 ! djm 173: if (fd == -1)
! 174: return;
1.9 markus 175: POKE_U32(buf, mlen);
1.1 markus 176: if (atomicio(vwrite, fd, buf, 4) != 4 ||
1.10 markus 177: atomicio(vwrite, fd, sshbuf_mutable_ptr(m),
1.9 markus 178: sshbuf_len(m)) != sshbuf_len(m))
1.1 markus 179: error("write to helper failed");
1.9 markus 180: if ((r = sshbuf_consume(m, mlen)) != 0)
1.17 djm 181: fatal_fr(r, "consume");
1.1 markus 182: }
183:
184: static int
1.18 ! djm 185: recv_msg(int fd, struct sshbuf *m)
1.1 markus 186: {
187: u_int l, len;
1.9 markus 188: u_char c, buf[1024];
189: int r;
1.1 markus 190:
1.18 ! djm 191: sshbuf_reset(m);
! 192: if (fd == -1)
! 193: return 0; /* XXX */
1.1 markus 194: if ((len = atomicio(read, fd, buf, 4)) != 4) {
195: error("read from helper failed: %u", len);
196: return (0); /* XXX */
197: }
1.9 markus 198: len = PEEK_U32(buf);
1.1 markus 199: if (len > 256 * 1024)
200: fatal("response too long: %u", len);
201: /* read len bytes into m */
202: while (len > 0) {
203: l = len;
204: if (l > sizeof(buf))
205: l = sizeof(buf);
206: if (atomicio(read, fd, buf, l) != l) {
207: error("response from helper failed.");
208: return (0); /* XXX */
209: }
1.9 markus 210: if ((r = sshbuf_put(m, buf, l)) != 0)
1.17 djm 211: fatal_fr(r, "sshbuf_put");
1.1 markus 212: len -= l;
213: }
1.9 markus 214: if ((r = sshbuf_get_u8(m, &c)) != 0)
1.17 djm 215: fatal_fr(r, "parse type");
1.9 markus 216: return c;
1.1 markus 217: }
218:
219: int
220: pkcs11_init(int interactive)
221: {
1.18 ! djm 222: return 0;
1.1 markus 223: }
224:
225: void
226: pkcs11_terminate(void)
227: {
1.18 ! djm 228: size_t i;
! 229:
! 230: debug3_f("terminating %zu helpers", nhelpers);
! 231: for (i = 0; i < nhelpers; i++)
! 232: helper_terminate(helpers[i]);
1.1 markus 233: }
234:
235: static int
1.12 djm 236: rsa_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa, int padding)
1.1 markus 237: {
1.14 djm 238: struct sshkey *key = NULL;
239: struct sshbuf *msg = NULL;
240: u_char *blob = NULL, *signature = NULL;
1.9 markus 241: size_t blen, slen = 0;
242: int r, ret = -1;
1.18 ! djm 243: struct helper *helper;
1.1 markus 244:
1.18 ! djm 245: if ((helper = helper_by_rsa(rsa)) == NULL || helper->fd == -1)
! 246: fatal_f("no helper for PKCS11 key");
! 247: debug3_f("signing with PKCS11 provider %s", helper->path);
1.1 markus 248: if (padding != RSA_PKCS1_PADDING)
1.14 djm 249: goto fail;
250: key = sshkey_new(KEY_UNSPEC);
251: if (key == NULL) {
1.17 djm 252: error_f("sshkey_new failed");
1.14 djm 253: goto fail;
254: }
255: key->type = KEY_RSA;
256: RSA_up_ref(rsa);
257: key->rsa = rsa;
258: if ((r = sshkey_to_blob(key, &blob, &blen)) != 0) {
1.17 djm 259: error_fr(r, "encode key");
1.14 djm 260: goto fail;
1.9 markus 261: }
262: if ((msg = sshbuf_new()) == NULL)
1.17 djm 263: fatal_f("sshbuf_new failed");
1.9 markus 264: if ((r = sshbuf_put_u8(msg, SSH2_AGENTC_SIGN_REQUEST)) != 0 ||
265: (r = sshbuf_put_string(msg, blob, blen)) != 0 ||
266: (r = sshbuf_put_string(msg, from, flen)) != 0 ||
267: (r = sshbuf_put_u32(msg, 0)) != 0)
1.17 djm 268: fatal_fr(r, "compose");
1.18 ! djm 269: send_msg(helper->fd, msg);
1.9 markus 270: sshbuf_reset(msg);
1.1 markus 271:
1.18 ! djm 272: if (recv_msg(helper->fd, msg) == SSH2_AGENT_SIGN_RESPONSE) {
1.9 markus 273: if ((r = sshbuf_get_string(msg, &signature, &slen)) != 0)
1.17 djm 274: fatal_fr(r, "parse");
1.9 markus 275: if (slen <= (size_t)RSA_size(rsa)) {
1.1 markus 276: memcpy(to, signature, slen);
277: ret = slen;
278: }
1.4 djm 279: free(signature);
1.1 markus 280: }
1.14 djm 281: fail:
282: free(blob);
283: sshkey_free(key);
1.9 markus 284: sshbuf_free(msg);
1.1 markus 285: return (ret);
286: }
287:
1.18 ! djm 288: static int
! 289: rsa_finish(RSA *rsa)
! 290: {
! 291: struct helper *helper;
! 292:
! 293: if ((helper = helper_by_rsa(rsa)) == NULL)
! 294: fatal_f("no helper for PKCS11 key");
! 295: debug3_f("free PKCS11 RSA key for provider %s", helper->path);
! 296: if (helper->rsa_finish != NULL)
! 297: helper->rsa_finish(rsa);
! 298: if (helper->nrsa == 0)
! 299: fatal_f("RSA refcount error");
! 300: helper->nrsa--;
! 301: debug3_f("provider %s remaining keys: %zu RSA %zu ECDSA",
! 302: helper->path, helper->nrsa, helper->nec);
! 303: if (helper->nrsa == 0 && helper->nec == 0)
! 304: helper_terminate(helper);
! 305: return 1;
! 306: }
! 307:
1.12 djm 308: static ECDSA_SIG *
309: ecdsa_do_sign(const unsigned char *dgst, int dgst_len, const BIGNUM *inv,
310: const BIGNUM *rp, EC_KEY *ec)
311: {
1.14 djm 312: struct sshkey *key = NULL;
313: struct sshbuf *msg = NULL;
314: ECDSA_SIG *ret = NULL;
1.12 djm 315: const u_char *cp;
1.14 djm 316: u_char *blob = NULL, *signature = NULL;
1.12 djm 317: size_t blen, slen = 0;
1.14 djm 318: int r, nid;
1.18 ! djm 319: struct helper *helper;
1.12 djm 320:
1.18 ! djm 321: if ((helper = helper_by_ec(ec)) == NULL || helper->fd == -1)
! 322: fatal_f("no helper for PKCS11 key");
! 323: debug3_f("signing with PKCS11 provider %s", helper->path);
1.14 djm 324: nid = sshkey_ecdsa_key_to_nid(ec);
325: if (nid < 0) {
1.17 djm 326: error_f("couldn't get curve nid");
1.14 djm 327: goto fail;
1.12 djm 328: }
1.14 djm 329:
330: key = sshkey_new(KEY_UNSPEC);
331: if (key == NULL) {
1.17 djm 332: error_f("sshkey_new failed");
1.14 djm 333: goto fail;
334: }
335: key->ecdsa = ec;
336: key->ecdsa_nid = nid;
337: key->type = KEY_ECDSA;
338: EC_KEY_up_ref(ec);
339:
340: if ((r = sshkey_to_blob(key, &blob, &blen)) != 0) {
1.17 djm 341: error_fr(r, "encode key");
1.14 djm 342: goto fail;
1.12 djm 343: }
344: if ((msg = sshbuf_new()) == NULL)
1.17 djm 345: fatal_f("sshbuf_new failed");
1.12 djm 346: if ((r = sshbuf_put_u8(msg, SSH2_AGENTC_SIGN_REQUEST)) != 0 ||
347: (r = sshbuf_put_string(msg, blob, blen)) != 0 ||
348: (r = sshbuf_put_string(msg, dgst, dgst_len)) != 0 ||
349: (r = sshbuf_put_u32(msg, 0)) != 0)
1.17 djm 350: fatal_fr(r, "compose");
1.18 ! djm 351: send_msg(helper->fd, msg);
1.12 djm 352: sshbuf_reset(msg);
353:
1.18 ! djm 354: if (recv_msg(helper->fd, msg) == SSH2_AGENT_SIGN_RESPONSE) {
1.12 djm 355: if ((r = sshbuf_get_string(msg, &signature, &slen)) != 0)
1.17 djm 356: fatal_fr(r, "parse");
1.12 djm 357: cp = signature;
358: ret = d2i_ECDSA_SIG(NULL, &cp, slen);
359: free(signature);
360: }
361:
1.14 djm 362: fail:
363: free(blob);
364: sshkey_free(key);
1.12 djm 365: sshbuf_free(msg);
366: return (ret);
367: }
368:
1.18 ! djm 369: static void
! 370: ecdsa_do_finish(EC_KEY *ec)
! 371: {
! 372: struct helper *helper;
! 373:
! 374: if ((helper = helper_by_ec(ec)) == NULL)
! 375: fatal_f("no helper for PKCS11 key");
! 376: debug3_f("free PKCS11 ECDSA key for provider %s", helper->path);
! 377: if (helper->ec_finish != NULL)
! 378: helper->ec_finish(ec);
! 379: if (helper->nec == 0)
! 380: fatal_f("ECDSA refcount error");
! 381: helper->nec--;
! 382: debug3_f("provider %s remaining keys: %zu RSA %zu ECDSA",
! 383: helper->path, helper->nrsa, helper->nec);
! 384: if (helper->nrsa == 0 && helper->nec == 0)
! 385: helper_terminate(helper);
! 386: }
1.12 djm 387:
388: /* redirect private key crypto operations to the ssh-pkcs11-helper */
389: static void
1.18 ! djm 390: wrap_key(struct helper *helper, struct sshkey *k)
1.12 djm 391: {
1.18 ! djm 392: debug3_f("wrap %s for provider %s", sshkey_type(k), helper->path);
! 393: if (k->type == KEY_RSA) {
! 394: RSA_set_method(k->rsa, helper->rsa_meth);
! 395: if (helper->nrsa++ >= INT_MAX)
! 396: fatal_f("RSA refcount error");
! 397: } else if (k->type == KEY_ECDSA) {
! 398: EC_KEY_set_method(k->ecdsa, helper->ec_meth);
! 399: if (helper->nec++ >= INT_MAX)
! 400: fatal_f("EC refcount error");
! 401: } else
1.17 djm 402: fatal_f("unknown key type");
1.18 ! djm 403: k->flags |= SSHKEY_FLAG_EXT;
! 404: debug3_f("provider %s remaining keys: %zu RSA %zu ECDSA",
! 405: helper->path, helper->nrsa, helper->nec);
1.12 djm 406: }
407:
1.1 markus 408: static int
1.18 ! djm 409: pkcs11_start_helper_methods(struct helper *helper)
1.1 markus 410: {
1.18 ! djm 411: int (*ec_init)(EC_KEY *key);
! 412: int (*ec_copy)(EC_KEY *dest, const EC_KEY *src);
! 413: int (*ec_set_group)(EC_KEY *key, const EC_GROUP *grp);
! 414: int (*ec_set_private)(EC_KEY *key, const BIGNUM *priv_key);
! 415: int (*ec_set_public)(EC_KEY *key, const EC_POINT *pub_key);
! 416: int (*ec_sign)(int, const unsigned char *, int, unsigned char *,
! 417: unsigned int *, const BIGNUM *, const BIGNUM *, EC_KEY *) = NULL;
! 418: RSA_METHOD *rsa_meth;
! 419: EC_KEY_METHOD *ec_meth;
1.12 djm 420:
1.18 ! djm 421: if ((ec_meth = EC_KEY_METHOD_new(EC_KEY_OpenSSL())) == NULL)
! 422: return -1;
! 423: EC_KEY_METHOD_get_sign(ec_meth, &ec_sign, NULL, NULL);
! 424: EC_KEY_METHOD_set_sign(ec_meth, ec_sign, NULL, ecdsa_do_sign);
! 425: EC_KEY_METHOD_get_init(ec_meth, &ec_init, &helper->ec_finish,
! 426: &ec_copy, &ec_set_group, &ec_set_private, &ec_set_public);
! 427: EC_KEY_METHOD_set_init(ec_meth, ec_init, ecdsa_do_finish,
! 428: ec_copy, ec_set_group, ec_set_private, ec_set_public);
1.1 markus 429:
1.18 ! djm 430: if ((rsa_meth = RSA_meth_dup(RSA_get_default_method())) == NULL)
1.17 djm 431: fatal_f("RSA_meth_dup failed");
1.18 ! djm 432: helper->rsa_finish = RSA_meth_get_finish(rsa_meth);
! 433: if (!RSA_meth_set1_name(rsa_meth, "ssh-pkcs11-helper") ||
! 434: !RSA_meth_set_priv_enc(rsa_meth, rsa_encrypt) ||
! 435: !RSA_meth_set_finish(rsa_meth, rsa_finish))
1.17 djm 436: fatal_f("failed to prepare method");
1.12 djm 437:
1.18 ! djm 438: helper->ec_meth = ec_meth;
! 439: helper->rsa_meth = rsa_meth;
! 440: return 0;
1.1 markus 441: }
442:
1.18 ! djm 443: static struct helper *
! 444: pkcs11_start_helper(const char *path)
1.1 markus 445: {
446: int pair[2];
1.18 ! djm 447: char *prog, *verbosity = NULL;
! 448: struct helper *helper;
! 449: pid_t pid;
! 450:
! 451: if (nhelpers >= INT_MAX)
! 452: fatal_f("too many helpers");
! 453: debug3_f("start helper for %s", path);
! 454: if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1) {
! 455: error_f("socketpair: %s", strerror(errno));
! 456: return NULL;
1.12 djm 457: }
1.18 ! djm 458: helper = xcalloc(1, sizeof(*helper));
! 459: if (pkcs11_start_helper_methods(helper) == -1) {
! 460: error_f("pkcs11_start_helper_methods failed");
! 461: goto fail;
1.1 markus 462: }
463: if ((pid = fork()) == -1) {
1.18 ! djm 464: error_f("fork: %s", strerror(errno));
! 465: fail:
! 466: close(pair[0]);
! 467: close(pair[1]);
! 468: RSA_meth_free(helper->rsa_meth);
! 469: EC_KEY_METHOD_free(helper->ec_meth);
! 470: free(helper);
! 471: return NULL;
1.1 markus 472: } else if (pid == 0) {
473: if ((dup2(pair[1], STDIN_FILENO) == -1) ||
474: (dup2(pair[1], STDOUT_FILENO) == -1)) {
475: fprintf(stderr, "dup2: %s\n", strerror(errno));
476: _exit(1);
477: }
478: close(pair[0]);
479: close(pair[1]);
1.18 ! djm 480: prog = getenv("SSH_PKCS11_HELPER");
! 481: if (prog == NULL || strlen(prog) == 0)
! 482: prog = _PATH_SSH_PKCS11_HELPER;
! 483: if (log_level_get() >= SYSLOG_LEVEL_DEBUG1)
! 484: verbosity = "-vvv";
! 485: debug_f("starting %s %s", prog,
1.15 djm 486: verbosity == NULL ? "" : verbosity);
1.18 ! djm 487: execlp(prog, prog, verbosity, (char *)NULL);
! 488: fprintf(stderr, "exec: %s: %s\n", prog, strerror(errno));
1.1 markus 489: _exit(1);
490: }
491: close(pair[1]);
1.18 ! djm 492: helper->fd = pair[0];
! 493: helper->path = xstrdup(path);
! 494: helper->pid = pid;
! 495: debug3_f("helper %zu for \"%s\" on fd %d pid %ld", nhelpers,
! 496: helper->path, helper->fd, (long)helper->pid);
! 497: helpers = xrecallocarray(helpers, nhelpers,
! 498: nhelpers + 1, sizeof(*helpers));
! 499: helpers[nhelpers++] = helper;
! 500: return helper;
1.1 markus 501: }
502:
503: int
1.16 djm 504: pkcs11_add_provider(char *name, char *pin, struct sshkey ***keysp,
505: char ***labelsp)
1.1 markus 506: {
1.7 markus 507: struct sshkey *k;
1.12 djm 508: int r, type;
1.1 markus 509: u_char *blob;
1.16 djm 510: char *label;
1.9 markus 511: size_t blen;
512: u_int nkeys, i;
513: struct sshbuf *msg;
1.18 ! djm 514: struct helper *helper;
1.1 markus 515:
1.18 ! djm 516: if ((helper = helper_by_provider(name)) == NULL &&
! 517: (helper = pkcs11_start_helper(name)) == NULL)
! 518: return -1;
1.1 markus 519:
1.9 markus 520: if ((msg = sshbuf_new()) == NULL)
1.17 djm 521: fatal_f("sshbuf_new failed");
1.9 markus 522: if ((r = sshbuf_put_u8(msg, SSH_AGENTC_ADD_SMARTCARD_KEY)) != 0 ||
523: (r = sshbuf_put_cstring(msg, name)) != 0 ||
524: (r = sshbuf_put_cstring(msg, pin)) != 0)
1.17 djm 525: fatal_fr(r, "compose");
1.18 ! djm 526: send_msg(helper->fd, msg);
1.9 markus 527: sshbuf_reset(msg);
528:
1.18 ! djm 529: type = recv_msg(helper->fd, msg);
1.12 djm 530: if (type == SSH2_AGENT_IDENTITIES_ANSWER) {
1.9 markus 531: if ((r = sshbuf_get_u32(msg, &nkeys)) != 0)
1.17 djm 532: fatal_fr(r, "parse nkeys");
1.9 markus 533: *keysp = xcalloc(nkeys, sizeof(struct sshkey *));
1.16 djm 534: if (labelsp)
535: *labelsp = xcalloc(nkeys, sizeof(char *));
1.1 markus 536: for (i = 0; i < nkeys; i++) {
1.9 markus 537: /* XXX clean up properly instead of fatal() */
538: if ((r = sshbuf_get_string(msg, &blob, &blen)) != 0 ||
1.16 djm 539: (r = sshbuf_get_cstring(msg, &label, NULL)) != 0)
1.17 djm 540: fatal_fr(r, "parse key");
1.9 markus 541: if ((r = sshkey_from_blob(blob, blen, &k)) != 0)
1.17 djm 542: fatal_fr(r, "decode key");
1.18 ! djm 543: wrap_key(helper, k);
1.1 markus 544: (*keysp)[i] = k;
1.16 djm 545: if (labelsp)
546: (*labelsp)[i] = label;
547: else
548: free(label);
1.4 djm 549: free(blob);
1.1 markus 550: }
1.12 djm 551: } else if (type == SSH2_AGENT_FAILURE) {
552: if ((r = sshbuf_get_u32(msg, &nkeys)) != 0)
553: nkeys = -1;
1.1 markus 554: } else {
555: nkeys = -1;
556: }
1.9 markus 557: sshbuf_free(msg);
1.1 markus 558: return (nkeys);
559: }
560:
561: int
562: pkcs11_del_provider(char *name)
563: {
1.18 ! djm 564: struct helper *helper;
1.1 markus 565:
1.18 ! djm 566: /*
! 567: * ssh-agent deletes keys before calling this, so the helper entry
! 568: * should be gone before we get here.
! 569: */
! 570: debug3_f("delete %s", name);
! 571: if ((helper = helper_by_provider(name)) != NULL)
! 572: helper_terminate(helper);
! 573: return 0;
1.1 markus 574: }