[BACK]Return to ssh-pkcs11-client.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / ssh

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: }