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