Annotation of src/usr.bin/ssh/ssh-pkcs11-client.c, Revision 1.19
1.19 ! djm 1: /* $OpenBSD: ssh-pkcs11-client.c,v 1.18 2023/07/19 14:03:45 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.19 ! djm 406: }
! 407:
! 408: /*
! 409: * Make a private PKCS#11-backed certificate by grafting a previously-loaded
! 410: * PKCS#11 private key and a public certificate key.
! 411: */
! 412: int
! 413: pkcs11_make_cert(const struct sshkey *priv,
! 414: const struct sshkey *certpub, struct sshkey **certprivp)
! 415: {
! 416: struct helper *helper = NULL;
! 417: struct sshkey *ret;
! 418: int r;
! 419:
! 420: debug3_f("private key type %s cert type %s", sshkey_type(priv),
! 421: sshkey_type(certpub));
! 422: *certprivp = NULL;
! 423: if (!sshkey_is_cert(certpub) || sshkey_is_cert(priv) ||
! 424: !sshkey_equal_public(priv, certpub)) {
! 425: error_f("private key %s doesn't match cert %s",
! 426: sshkey_type(priv), sshkey_type(certpub));
! 427: return SSH_ERR_INVALID_ARGUMENT;
! 428: }
! 429: *certprivp = NULL;
! 430: if (priv->type == KEY_RSA) {
! 431: if ((helper = helper_by_rsa(priv->rsa)) == NULL ||
! 432: helper->fd == -1)
! 433: fatal_f("no helper for PKCS11 RSA key");
! 434: if ((r = sshkey_from_private(priv, &ret)) != 0)
! 435: fatal_fr(r, "copy key");
! 436: RSA_set_method(ret->rsa, helper->rsa_meth);
! 437: if (helper->nrsa++ >= INT_MAX)
! 438: fatal_f("RSA refcount error");
! 439: } else if (priv->type == KEY_ECDSA) {
! 440: if ((helper = helper_by_ec(priv->ecdsa)) == NULL ||
! 441: helper->fd == -1)
! 442: fatal_f("no helper for PKCS11 EC key");
! 443: if ((r = sshkey_from_private(priv, &ret)) != 0)
! 444: fatal_fr(r, "copy key");
! 445: EC_KEY_set_method(ret->ecdsa, helper->ec_meth);
! 446: if (helper->nec++ >= INT_MAX)
! 447: fatal_f("EC refcount error");
! 448: } else
! 449: fatal_f("unknown key type %s", sshkey_type(priv));
! 450:
! 451: ret->flags |= SSHKEY_FLAG_EXT;
! 452: if ((r = sshkey_to_certified(ret)) != 0 ||
! 453: (r = sshkey_cert_copy(certpub, ret)) != 0)
! 454: fatal_fr(r, "graft certificate");
! 455: debug3_f("provider %s remaining keys: %zu RSA %zu ECDSA",
! 456: helper->path, helper->nrsa, helper->nec);
! 457: /* success */
! 458: *certprivp = ret;
! 459: return 0;
1.12 djm 460: }
461:
1.1 markus 462: static int
1.18 djm 463: pkcs11_start_helper_methods(struct helper *helper)
1.1 markus 464: {
1.18 djm 465: int (*ec_init)(EC_KEY *key);
466: int (*ec_copy)(EC_KEY *dest, const EC_KEY *src);
467: int (*ec_set_group)(EC_KEY *key, const EC_GROUP *grp);
468: int (*ec_set_private)(EC_KEY *key, const BIGNUM *priv_key);
469: int (*ec_set_public)(EC_KEY *key, const EC_POINT *pub_key);
470: int (*ec_sign)(int, const unsigned char *, int, unsigned char *,
471: unsigned int *, const BIGNUM *, const BIGNUM *, EC_KEY *) = NULL;
472: RSA_METHOD *rsa_meth;
473: EC_KEY_METHOD *ec_meth;
1.12 djm 474:
1.18 djm 475: if ((ec_meth = EC_KEY_METHOD_new(EC_KEY_OpenSSL())) == NULL)
476: return -1;
477: EC_KEY_METHOD_get_sign(ec_meth, &ec_sign, NULL, NULL);
478: EC_KEY_METHOD_set_sign(ec_meth, ec_sign, NULL, ecdsa_do_sign);
479: EC_KEY_METHOD_get_init(ec_meth, &ec_init, &helper->ec_finish,
480: &ec_copy, &ec_set_group, &ec_set_private, &ec_set_public);
481: EC_KEY_METHOD_set_init(ec_meth, ec_init, ecdsa_do_finish,
482: ec_copy, ec_set_group, ec_set_private, ec_set_public);
1.1 markus 483:
1.18 djm 484: if ((rsa_meth = RSA_meth_dup(RSA_get_default_method())) == NULL)
1.17 djm 485: fatal_f("RSA_meth_dup failed");
1.18 djm 486: helper->rsa_finish = RSA_meth_get_finish(rsa_meth);
487: if (!RSA_meth_set1_name(rsa_meth, "ssh-pkcs11-helper") ||
488: !RSA_meth_set_priv_enc(rsa_meth, rsa_encrypt) ||
489: !RSA_meth_set_finish(rsa_meth, rsa_finish))
1.17 djm 490: fatal_f("failed to prepare method");
1.12 djm 491:
1.18 djm 492: helper->ec_meth = ec_meth;
493: helper->rsa_meth = rsa_meth;
494: return 0;
1.1 markus 495: }
496:
1.18 djm 497: static struct helper *
498: pkcs11_start_helper(const char *path)
1.1 markus 499: {
500: int pair[2];
1.18 djm 501: char *prog, *verbosity = NULL;
502: struct helper *helper;
503: pid_t pid;
504:
505: if (nhelpers >= INT_MAX)
506: fatal_f("too many helpers");
507: debug3_f("start helper for %s", path);
508: if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1) {
509: error_f("socketpair: %s", strerror(errno));
510: return NULL;
1.12 djm 511: }
1.18 djm 512: helper = xcalloc(1, sizeof(*helper));
513: if (pkcs11_start_helper_methods(helper) == -1) {
514: error_f("pkcs11_start_helper_methods failed");
515: goto fail;
1.1 markus 516: }
517: if ((pid = fork()) == -1) {
1.18 djm 518: error_f("fork: %s", strerror(errno));
519: fail:
520: close(pair[0]);
521: close(pair[1]);
522: RSA_meth_free(helper->rsa_meth);
523: EC_KEY_METHOD_free(helper->ec_meth);
524: free(helper);
525: return NULL;
1.1 markus 526: } else if (pid == 0) {
527: if ((dup2(pair[1], STDIN_FILENO) == -1) ||
528: (dup2(pair[1], STDOUT_FILENO) == -1)) {
529: fprintf(stderr, "dup2: %s\n", strerror(errno));
530: _exit(1);
531: }
532: close(pair[0]);
533: close(pair[1]);
1.18 djm 534: prog = getenv("SSH_PKCS11_HELPER");
535: if (prog == NULL || strlen(prog) == 0)
536: prog = _PATH_SSH_PKCS11_HELPER;
537: if (log_level_get() >= SYSLOG_LEVEL_DEBUG1)
538: verbosity = "-vvv";
539: debug_f("starting %s %s", prog,
1.15 djm 540: verbosity == NULL ? "" : verbosity);
1.18 djm 541: execlp(prog, prog, verbosity, (char *)NULL);
542: fprintf(stderr, "exec: %s: %s\n", prog, strerror(errno));
1.1 markus 543: _exit(1);
544: }
545: close(pair[1]);
1.18 djm 546: helper->fd = pair[0];
547: helper->path = xstrdup(path);
548: helper->pid = pid;
549: debug3_f("helper %zu for \"%s\" on fd %d pid %ld", nhelpers,
550: helper->path, helper->fd, (long)helper->pid);
551: helpers = xrecallocarray(helpers, nhelpers,
552: nhelpers + 1, sizeof(*helpers));
553: helpers[nhelpers++] = helper;
554: return helper;
1.1 markus 555: }
556:
557: int
1.16 djm 558: pkcs11_add_provider(char *name, char *pin, struct sshkey ***keysp,
559: char ***labelsp)
1.1 markus 560: {
1.7 markus 561: struct sshkey *k;
1.12 djm 562: int r, type;
1.1 markus 563: u_char *blob;
1.16 djm 564: char *label;
1.9 markus 565: size_t blen;
566: u_int nkeys, i;
567: struct sshbuf *msg;
1.18 djm 568: struct helper *helper;
1.1 markus 569:
1.18 djm 570: if ((helper = helper_by_provider(name)) == NULL &&
571: (helper = pkcs11_start_helper(name)) == NULL)
572: return -1;
1.1 markus 573:
1.9 markus 574: if ((msg = sshbuf_new()) == NULL)
1.17 djm 575: fatal_f("sshbuf_new failed");
1.9 markus 576: if ((r = sshbuf_put_u8(msg, SSH_AGENTC_ADD_SMARTCARD_KEY)) != 0 ||
577: (r = sshbuf_put_cstring(msg, name)) != 0 ||
578: (r = sshbuf_put_cstring(msg, pin)) != 0)
1.17 djm 579: fatal_fr(r, "compose");
1.18 djm 580: send_msg(helper->fd, msg);
1.9 markus 581: sshbuf_reset(msg);
582:
1.18 djm 583: type = recv_msg(helper->fd, msg);
1.12 djm 584: if (type == SSH2_AGENT_IDENTITIES_ANSWER) {
1.9 markus 585: if ((r = sshbuf_get_u32(msg, &nkeys)) != 0)
1.17 djm 586: fatal_fr(r, "parse nkeys");
1.9 markus 587: *keysp = xcalloc(nkeys, sizeof(struct sshkey *));
1.16 djm 588: if (labelsp)
589: *labelsp = xcalloc(nkeys, sizeof(char *));
1.1 markus 590: for (i = 0; i < nkeys; i++) {
1.9 markus 591: /* XXX clean up properly instead of fatal() */
592: if ((r = sshbuf_get_string(msg, &blob, &blen)) != 0 ||
1.16 djm 593: (r = sshbuf_get_cstring(msg, &label, NULL)) != 0)
1.17 djm 594: fatal_fr(r, "parse key");
1.9 markus 595: if ((r = sshkey_from_blob(blob, blen, &k)) != 0)
1.17 djm 596: fatal_fr(r, "decode key");
1.18 djm 597: wrap_key(helper, k);
1.1 markus 598: (*keysp)[i] = k;
1.16 djm 599: if (labelsp)
600: (*labelsp)[i] = label;
601: else
602: free(label);
1.4 djm 603: free(blob);
1.1 markus 604: }
1.12 djm 605: } else if (type == SSH2_AGENT_FAILURE) {
606: if ((r = sshbuf_get_u32(msg, &nkeys)) != 0)
607: nkeys = -1;
1.1 markus 608: } else {
609: nkeys = -1;
610: }
1.9 markus 611: sshbuf_free(msg);
1.1 markus 612: return (nkeys);
613: }
614:
615: int
616: pkcs11_del_provider(char *name)
617: {
1.18 djm 618: struct helper *helper;
1.1 markus 619:
1.18 djm 620: /*
621: * ssh-agent deletes keys before calling this, so the helper entry
622: * should be gone before we get here.
623: */
624: debug3_f("delete %s", name);
625: if ((helper = helper_by_provider(name)) != NULL)
626: helper_terminate(helper);
627: return 0;
1.1 markus 628: }