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

Annotation of src/usr.bin/ssh/ssh-sk.c, Revision 1.14

1.14    ! djm         1: /* $OpenBSD: ssh-sk.c,v 1.13 2019/11/16 22:42:30 djm Exp $ */
1.1       djm         2: /*
                      3:  * Copyright (c) 2019 Google LLC
                      4:  *
                      5:  * Permission to use, copy, modify, and distribute this software for any
                      6:  * purpose with or without fee is hereby granted, provided that the above
                      7:  * copyright notice and this permission notice appear in all copies.
                      8:  *
                      9:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
                     10:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     11:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
                     12:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     13:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
                     14:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
                     15:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     16:  */
                     17:
                     18: /* #define DEBUG_SK 1 */
                     19:
                     20: #include <dlfcn.h>
                     21: #include <stddef.h>
                     22: #include <stdint.h>
                     23: #include <string.h>
                     24: #include <stdio.h>
                     25:
                     26: #include <openssl/objects.h>
                     27: #include <openssl/ec.h>
                     28:
                     29: #include "log.h"
                     30: #include "misc.h"
                     31: #include "sshbuf.h"
                     32: #include "sshkey.h"
                     33: #include "ssherr.h"
                     34: #include "digest.h"
                     35:
                     36: #include "ssh-sk.h"
                     37: #include "sk-api.h"
1.6       markus     38: #include "crypto_api.h"
1.1       djm        39:
                     40: struct sshsk_provider {
                     41:        char *path;
                     42:        void *dlhandle;
                     43:
                     44:        /* Return the version of the middleware API */
                     45:        uint32_t (*sk_api_version)(void);
                     46:
                     47:        /* Enroll a U2F key (private key generation) */
1.7       markus     48:        int (*sk_enroll)(int alg, const uint8_t *challenge,
                     49:            size_t challenge_len, const char *application, uint8_t flags,
1.1       djm        50:            struct sk_enroll_response **enroll_response);
                     51:
                     52:        /* Sign a challenge */
1.7       markus     53:        int (*sk_sign)(int alg, const uint8_t *message, size_t message_len,
1.1       djm        54:            const char *application,
                     55:            const uint8_t *key_handle, size_t key_handle_len,
                     56:            uint8_t flags, struct sk_sign_response **sign_response);
                     57: };
                     58:
1.12      djm        59: /* Built-in version */
                     60: int ssh_sk_enroll(int alg, const uint8_t *challenge,
                     61:     size_t challenge_len, const char *application, uint8_t flags,
                     62:     struct sk_enroll_response **enroll_response);
                     63: int ssh_sk_sign(int alg, const uint8_t *message, size_t message_len,
                     64:     const char *application,
                     65:     const uint8_t *key_handle, size_t key_handle_len,
                     66:     uint8_t flags, struct sk_sign_response **sign_response);
                     67:
1.1       djm        68: static void
                     69: sshsk_free(struct sshsk_provider *p)
                     70: {
                     71:        if (p == NULL)
                     72:                return;
                     73:        free(p->path);
                     74:        if (p->dlhandle != NULL)
                     75:                dlclose(p->dlhandle);
                     76:        free(p);
                     77: }
                     78:
                     79: static struct sshsk_provider *
                     80: sshsk_open(const char *path)
                     81: {
                     82:        struct sshsk_provider *ret = NULL;
                     83:        uint32_t version;
                     84:
                     85:        if ((ret = calloc(1, sizeof(*ret))) == NULL) {
                     86:                error("%s: calloc failed", __func__);
                     87:                return NULL;
                     88:        }
                     89:        if ((ret->path = strdup(path)) == NULL) {
                     90:                error("%s: strdup failed", __func__);
                     91:                goto fail;
1.12      djm        92:        }
                     93:        /* Skip the rest if we're using the linked in middleware */
                     94:        if (strcasecmp(ret->path, "internal") == 0) {
                     95:                ret->sk_enroll = ssh_sk_enroll;
                     96:                ret->sk_sign = ssh_sk_sign;
                     97:                return ret;
1.1       djm        98:        }
                     99:        if ((ret->dlhandle = dlopen(path, RTLD_NOW)) == NULL) {
                    100:                error("Security key provider %s dlopen failed: %s",
                    101:                    path, dlerror());
                    102:                goto fail;
                    103:        }
                    104:        if ((ret->sk_api_version = dlsym(ret->dlhandle,
                    105:            "sk_api_version")) == NULL) {
                    106:                error("Security key provider %s dlsym(sk_api_version) "
                    107:                    "failed: %s", path, dlerror());
                    108:                goto fail;
                    109:        }
                    110:        version = ret->sk_api_version();
                    111:        debug("%s: provider %s implements version 0x%08lx", __func__,
                    112:            ret->path, (u_long)version);
                    113:        if ((version & SSH_SK_VERSION_MAJOR_MASK) != SSH_SK_VERSION_MAJOR) {
                    114:                error("Security key provider %s implements unsupported version "
                    115:                    "0x%08lx (supported: 0x%08lx)", path, (u_long)version,
                    116:                    (u_long)SSH_SK_VERSION_MAJOR);
                    117:                goto fail;
                    118:        }
                    119:        if ((ret->sk_enroll = dlsym(ret->dlhandle, "sk_enroll")) == NULL) {
                    120:                error("Security key  provider %s dlsym(sk_enroll) "
                    121:                    "failed: %s", path, dlerror());
                    122:                goto fail;
                    123:        }
                    124:        if ((ret->sk_sign = dlsym(ret->dlhandle, "sk_sign")) == NULL) {
                    125:                error("Security key provider %s dlsym(sk_sign) failed: %s",
                    126:                    path, dlerror());
                    127:                goto fail;
                    128:        }
                    129:        /* success */
                    130:        return ret;
                    131: fail:
                    132:        sshsk_free(ret);
                    133:        return NULL;
                    134: }
                    135:
                    136: static void
                    137: sshsk_free_enroll_response(struct sk_enroll_response *r)
                    138: {
                    139:        if (r == NULL)
                    140:                return;
                    141:        freezero(r->key_handle, r->key_handle_len);
                    142:        freezero(r->public_key, r->public_key_len);
                    143:        freezero(r->signature, r->signature_len);
                    144:        freezero(r->attestation_cert, r->attestation_cert_len);
                    145:        freezero(r, sizeof(*r));
                    146: };
                    147:
                    148: static void
                    149: sshsk_free_sign_response(struct sk_sign_response *r)
                    150: {
                    151:        if (r == NULL)
                    152:                return;
                    153:        freezero(r->sig_r, r->sig_r_len);
                    154:        freezero(r->sig_s, r->sig_s_len);
                    155:        freezero(r, sizeof(*r));
                    156: };
                    157:
1.2       markus    158: /* Assemble key from response */
                    159: static int
                    160: sshsk_ecdsa_assemble(struct sk_enroll_response *resp, struct sshkey **keyp)
                    161: {
                    162:        struct sshkey *key = NULL;
                    163:        struct sshbuf *b = NULL;
                    164:        EC_POINT *q = NULL;
                    165:        int r;
                    166:
                    167:        *keyp = NULL;
                    168:        if ((key = sshkey_new(KEY_ECDSA_SK)) == NULL) {
                    169:                error("%s: sshkey_new failed", __func__);
                    170:                r = SSH_ERR_ALLOC_FAIL;
                    171:                goto out;
                    172:        }
                    173:        key->ecdsa_nid = NID_X9_62_prime256v1;
                    174:        if ((key->ecdsa = EC_KEY_new_by_curve_name(key->ecdsa_nid)) == NULL ||
                    175:            (q = EC_POINT_new(EC_KEY_get0_group(key->ecdsa))) == NULL ||
                    176:            (b = sshbuf_new()) == NULL) {
                    177:                error("%s: allocation failed", __func__);
                    178:                r = SSH_ERR_ALLOC_FAIL;
                    179:                goto out;
                    180:        }
                    181:        if ((r = sshbuf_put_string(b,
                    182:            resp->public_key, resp->public_key_len)) != 0) {
                    183:                error("%s: buffer error: %s", __func__, ssh_err(r));
                    184:                goto out;
                    185:        }
                    186:        if ((r = sshbuf_get_ec(b, q, EC_KEY_get0_group(key->ecdsa))) != 0) {
                    187:                error("%s: parse key: %s", __func__, ssh_err(r));
                    188:                r = SSH_ERR_INVALID_FORMAT;
                    189:                goto out;
                    190:        }
                    191:        if (sshkey_ec_validate_public(EC_KEY_get0_group(key->ecdsa), q) != 0) {
                    192:                error("Security key returned invalid ECDSA key");
                    193:                r = SSH_ERR_KEY_INVALID_EC_VALUE;
                    194:                goto out;
                    195:        }
                    196:        if (EC_KEY_set_public_key(key->ecdsa, q) != 1) {
                    197:                /* XXX assume it is a allocation error */
                    198:                error("%s: allocation failed", __func__);
                    199:                r = SSH_ERR_ALLOC_FAIL;
                    200:                goto out;
                    201:        }
                    202:        /* success */
                    203:        *keyp = key;
                    204:        key = NULL; /* transferred */
                    205:        r = 0;
                    206:  out:
                    207:        EC_POINT_free(q);
                    208:        sshkey_free(key);
                    209:        sshbuf_free(b);
                    210:        return r;
                    211: }
                    212:
1.6       markus    213: static int
                    214: sshsk_ed25519_assemble(struct sk_enroll_response *resp, struct sshkey **keyp)
                    215: {
                    216:        struct sshkey *key = NULL;
                    217:        int r;
                    218:
                    219:        *keyp = NULL;
                    220:        if (resp->public_key_len != ED25519_PK_SZ) {
                    221:                error("%s: invalid size: %zu", __func__, resp->public_key_len);
                    222:                r = SSH_ERR_INVALID_FORMAT;
                    223:                goto out;
                    224:        }
                    225:        if ((key = sshkey_new(KEY_ED25519_SK)) == NULL) {
                    226:                error("%s: sshkey_new failed", __func__);
                    227:                r = SSH_ERR_ALLOC_FAIL;
                    228:                goto out;
                    229:        }
                    230:        if ((key->ed25519_pk = malloc(ED25519_PK_SZ)) == NULL) {
                    231:                error("%s: malloc failed", __func__);
                    232:                r = SSH_ERR_ALLOC_FAIL;
                    233:                goto out;
                    234:        }
                    235:        memcpy(key->ed25519_pk, resp->public_key, ED25519_PK_SZ);
                    236:        /* success */
                    237:        *keyp = key;
                    238:        key = NULL; /* transferred */
                    239:        r = 0;
                    240:  out:
                    241:        sshkey_free(key);
                    242:        return r;
                    243: }
                    244:
1.1       djm       245: int
1.6       markus    246: sshsk_enroll(int type, const char *provider_path, const char *application,
1.1       djm       247:     uint8_t flags, struct sshbuf *challenge_buf, struct sshkey **keyp,
                    248:     struct sshbuf *attest)
                    249: {
                    250:        struct sshsk_provider *skp = NULL;
                    251:        struct sshkey *key = NULL;
                    252:        u_char randchall[32];
                    253:        const u_char *challenge;
                    254:        size_t challenge_len;
                    255:        struct sk_enroll_response *resp = NULL;
                    256:        int r = SSH_ERR_INTERNAL_ERROR;
1.7       markus    257:        int alg;
1.1       djm       258:
1.13      djm       259:        debug("%s: provider \"%s\", application \"%s\", flags 0x%02x, "
                    260:            "challenge len %zu", __func__, provider_path, application,
                    261:            flags, challenge_buf == NULL ? 0 : sshbuf_len(challenge_buf));
                    262:
1.1       djm       263:        *keyp = NULL;
                    264:        if (attest)
                    265:                sshbuf_reset(attest);
1.6       markus    266:        switch (type) {
                    267:        case KEY_ECDSA_SK:
1.7       markus    268:                alg = SSH_SK_ECDSA;
                    269:                break;
1.6       markus    270:        case KEY_ED25519_SK:
1.7       markus    271:                alg = SSH_SK_ED25519;
1.6       markus    272:                break;
                    273:        default:
                    274:                error("%s: unsupported key type", __func__);
                    275:                r = SSH_ERR_INVALID_ARGUMENT;
                    276:                goto out;
                    277:        }
1.1       djm       278:        if (provider_path == NULL) {
                    279:                error("%s: missing provider", __func__);
                    280:                r = SSH_ERR_INVALID_ARGUMENT;
                    281:                goto out;
                    282:        }
                    283:        if (application == NULL || *application == '\0') {
                    284:                error("%s: missing application", __func__);
                    285:                r = SSH_ERR_INVALID_ARGUMENT;
                    286:                goto out;
                    287:        }
                    288:        if (challenge_buf == NULL) {
                    289:                debug("%s: using random challenge", __func__);
                    290:                arc4random_buf(randchall, sizeof(randchall));
                    291:                challenge = randchall;
                    292:                challenge_len = sizeof(randchall);
                    293:        } else if (sshbuf_len(challenge_buf) == 0) {
                    294:                error("Missing enrollment challenge");
                    295:                r = SSH_ERR_INVALID_ARGUMENT;
                    296:                goto out;
                    297:        } else {
                    298:                challenge = sshbuf_ptr(challenge_buf);
                    299:                challenge_len = sshbuf_len(challenge_buf);
                    300:                debug3("%s: using explicit challenge len=%zd",
                    301:                    __func__, challenge_len);
                    302:        }
                    303:        if ((skp = sshsk_open(provider_path)) == NULL) {
                    304:                r = SSH_ERR_INVALID_FORMAT; /* XXX sshsk_open return code? */
                    305:                goto out;
                    306:        }
                    307:        /* XXX validate flags? */
                    308:        /* enroll key */
1.7       markus    309:        if ((r = skp->sk_enroll(alg, challenge, challenge_len, application,
1.1       djm       310:            flags, &resp)) != 0) {
                    311:                error("Security key provider %s returned failure %d",
                    312:                    provider_path, r);
                    313:                r = SSH_ERR_INVALID_FORMAT; /* XXX error codes in API? */
                    314:                goto out;
                    315:        }
                    316:        /* Check response validity */
                    317:        if (resp->public_key == NULL || resp->key_handle == NULL ||
1.10      djm       318:            resp->signature == NULL ||
                    319:            (resp->attestation_cert == NULL && resp->attestation_cert_len != 0)) {
1.1       djm       320:                error("%s: sk_enroll response invalid", __func__);
                    321:                r = SSH_ERR_INVALID_FORMAT;
                    322:                goto out;
                    323:        }
1.6       markus    324:        switch (type) {
                    325:        case KEY_ECDSA_SK:
                    326:                if ((r = sshsk_ecdsa_assemble(resp, &key)) != 0)
                    327:                        goto out;
                    328:                break;
                    329:        case KEY_ED25519_SK:
                    330:                if ((r = sshsk_ed25519_assemble(resp, &key)) != 0)
                    331:                        goto out;
                    332:                break;
                    333:        }
1.1       djm       334:        key->sk_flags = flags;
1.2       markus    335:        if ((key->sk_key_handle = sshbuf_new()) == NULL ||
                    336:            (key->sk_reserved = sshbuf_new()) == NULL) {
1.1       djm       337:                error("%s: allocation failed", __func__);
                    338:                r = SSH_ERR_ALLOC_FAIL;
                    339:                goto out;
                    340:        }
                    341:        if ((key->sk_application = strdup(application)) == NULL) {
                    342:                error("%s: strdup application failed", __func__);
                    343:                r = SSH_ERR_ALLOC_FAIL;
                    344:                goto out;
                    345:        }
                    346:        if ((r = sshbuf_put(key->sk_key_handle, resp->key_handle,
                    347:            resp->key_handle_len)) != 0) {
                    348:                error("%s: buffer error: %s", __func__, ssh_err(r));
                    349:                goto out;
                    350:        }
                    351:        /* Optionally fill in the attestation information */
                    352:        if (attest != NULL) {
                    353:                if ((r = sshbuf_put_cstring(attest, "sk-attest-v00")) != 0 ||
                    354:                    (r = sshbuf_put_u32(attest, 1)) != 0 || /* XXX U2F ver */
                    355:                    (r = sshbuf_put_string(attest,
                    356:                    resp->attestation_cert, resp->attestation_cert_len)) != 0 ||
                    357:                    (r = sshbuf_put_string(attest,
                    358:                    resp->signature, resp->signature_len)) != 0 ||
                    359:                    (r = sshbuf_put_u32(attest, flags)) != 0 || /* XXX right? */
                    360:                    (r = sshbuf_put_string(attest, NULL, 0)) != 0) {
                    361:                        error("%s: buffer error: %s", __func__, ssh_err(r));
                    362:                        goto out;
                    363:                }
                    364:        }
                    365:        /* success */
                    366:        *keyp = key;
                    367:        key = NULL; /* transferred */
                    368:        r = 0;
                    369:  out:
                    370:        sshsk_free(skp);
                    371:        sshkey_free(key);
                    372:        sshsk_free_enroll_response(resp);
                    373:        explicit_bzero(randchall, sizeof(randchall));
                    374:        return r;
                    375: }
                    376:
1.3       markus    377: static int
1.9       markus    378: sshsk_ecdsa_sig(struct sk_sign_response *resp, struct sshbuf *sig)
1.3       markus    379: {
                    380:        struct sshbuf *inner_sig = NULL;
                    381:        int r = SSH_ERR_INTERNAL_ERROR;
                    382:
1.8       markus    383:        /* Check response validity */
1.11      markus    384:        if (resp->sig_r == NULL || resp->sig_s == NULL) {
1.8       markus    385:                error("%s: sk_sign response invalid", __func__);
                    386:                r = SSH_ERR_INVALID_FORMAT;
                    387:                goto out;
                    388:        }
1.3       markus    389:        if ((inner_sig = sshbuf_new()) == NULL) {
                    390:                r = SSH_ERR_ALLOC_FAIL;
                    391:                goto out;
                    392:        }
1.9       markus    393:        /* Prepare and append inner signature object */
1.3       markus    394:        if ((r = sshbuf_put_bignum2_bytes(inner_sig,
                    395:            resp->sig_r, resp->sig_r_len)) != 0 ||
                    396:            (r = sshbuf_put_bignum2_bytes(inner_sig,
                    397:            resp->sig_s, resp->sig_s_len)) != 0 ||
                    398:            (r = sshbuf_put_u8(inner_sig, resp->flags)) != 0 ||
                    399:            (r = sshbuf_put_u32(inner_sig, resp->counter)) != 0) {
                    400:                debug("%s: buffer error: %s", __func__, ssh_err(r));
                    401:                goto out;
                    402:        }
1.9       markus    403:        if ((r = sshbuf_put_stringb(sig, inner_sig)) != 0) {
                    404:                debug("%s: buffer error: %s", __func__, ssh_err(r));
                    405:                goto out;
                    406:        }
1.3       markus    407: #ifdef DEBUG_SK
                    408:        fprintf(stderr, "%s: sig_r:\n", __func__);
                    409:        sshbuf_dump_data(resp->sig_r, resp->sig_r_len, stderr);
                    410:        fprintf(stderr, "%s: sig_s:\n", __func__);
                    411:        sshbuf_dump_data(resp->sig_s, resp->sig_s_len, stderr);
1.9       markus    412:        fprintf(stderr, "%s: inner:\n", __func__);
                    413:        sshbuf_dump(inner_sig, stderr);
1.5       markus    414: #endif
                    415:        r = 0;
1.9       markus    416:  out:
1.5       markus    417:        sshbuf_free(inner_sig);
                    418:        return r;
                    419: }
                    420:
                    421: static int
1.9       markus    422: sshsk_ed25519_sig(struct sk_sign_response *resp, struct sshbuf *sig)
1.5       markus    423: {
                    424:        int r = SSH_ERR_INTERNAL_ERROR;
                    425:
1.8       markus    426:        /* Check response validity */
                    427:        if (resp->sig_r == NULL) {
                    428:                error("%s: sk_sign response invalid", __func__);
                    429:                r = SSH_ERR_INVALID_FORMAT;
                    430:                goto out;
                    431:        }
1.9       markus    432:        if ((r = sshbuf_put_string(sig,
1.5       markus    433:            resp->sig_r, resp->sig_r_len)) != 0 ||
1.9       markus    434:            (r = sshbuf_put_u8(sig, resp->flags)) != 0 ||
                    435:            (r = sshbuf_put_u32(sig, resp->counter)) != 0) {
1.5       markus    436:                debug("%s: buffer error: %s", __func__, ssh_err(r));
                    437:                goto out;
                    438:        }
                    439: #ifdef DEBUG_SK
                    440:        fprintf(stderr, "%s: sig_r:\n", __func__);
                    441:        sshbuf_dump_data(resp->sig_r, resp->sig_r_len, stderr);
1.3       markus    442: #endif
                    443:        r = 0;
1.9       markus    444:  out:
                    445:        return 0;
1.3       markus    446: }
                    447:
1.1       djm       448: int
1.4       markus    449: sshsk_sign(const char *provider_path, const struct sshkey *key,
1.1       djm       450:     u_char **sigp, size_t *lenp, const u_char *data, size_t datalen,
                    451:     u_int compat)
                    452: {
                    453:        struct sshsk_provider *skp = NULL;
                    454:        int r = SSH_ERR_INTERNAL_ERROR;
1.7       markus    455:        int type, alg;
1.1       djm       456:        struct sk_sign_response *resp = NULL;
                    457:        struct sshbuf *inner_sig = NULL, *sig = NULL;
                    458:        uint8_t message[32];
1.13      djm       459:
1.14    ! djm       460:        debug("%s: provider \"%s\", key %s, flags 0x%02x", __func__,
1.13      djm       461:            provider_path, sshkey_type(key), key->sk_flags);
1.1       djm       462:
                    463:        if (sigp != NULL)
                    464:                *sigp = NULL;
                    465:        if (lenp != NULL)
                    466:                *lenp = 0;
1.5       markus    467:        type = sshkey_type_plain(key->type);
                    468:        switch (type) {
                    469:        case KEY_ECDSA_SK:
1.7       markus    470:                alg = SSH_SK_ECDSA;
                    471:                break;
1.5       markus    472:        case KEY_ED25519_SK:
1.7       markus    473:                alg = SSH_SK_ED25519;
1.5       markus    474:                break;
                    475:        default:
                    476:                return SSH_ERR_INVALID_ARGUMENT;
                    477:        }
1.1       djm       478:        if (provider_path == NULL ||
                    479:            key->sk_key_handle == NULL ||
                    480:            key->sk_application == NULL || *key->sk_application == '\0') {
                    481:                r = SSH_ERR_INVALID_ARGUMENT;
                    482:                goto out;
                    483:        }
                    484:        if ((skp = sshsk_open(provider_path)) == NULL) {
                    485:                r = SSH_ERR_INVALID_FORMAT; /* XXX sshsk_open return code? */
                    486:                goto out;
                    487:        }
                    488:
                    489:        /* hash data to be signed before it goes to the security key */
                    490:        if ((r = ssh_digest_memory(SSH_DIGEST_SHA256, data, datalen,
                    491:            message, sizeof(message))) != 0) {
                    492:                error("%s: hash application failed: %s", __func__, ssh_err(r));
                    493:                r = SSH_ERR_INTERNAL_ERROR;
                    494:                goto out;
                    495:        }
1.7       markus    496:        if ((r = skp->sk_sign(alg, message, sizeof(message),
1.1       djm       497:            key->sk_application,
                    498:            sshbuf_ptr(key->sk_key_handle), sshbuf_len(key->sk_key_handle),
                    499:            key->sk_flags, &resp)) != 0) {
                    500:                debug("%s: sk_sign failed with code %d", __func__, r);
                    501:                goto out;
                    502:        }
1.9       markus    503:        /* Assemble signature */
                    504:        if ((sig = sshbuf_new()) == NULL) {
                    505:                r = SSH_ERR_ALLOC_FAIL;
                    506:                goto out;
                    507:        }
                    508:        if ((r = sshbuf_put_cstring(sig, sshkey_ssh_name_plain(key))) != 0) {
                    509:                debug("%s: buffer error (outer): %s", __func__, ssh_err(r));
                    510:                goto out;
                    511:        }
1.5       markus    512:        switch (type) {
                    513:        case KEY_ECDSA_SK:
1.9       markus    514:                if ((r = sshsk_ecdsa_sig(resp, sig)) != 0)
1.5       markus    515:                        goto out;
                    516:                break;
                    517:        case KEY_ED25519_SK:
1.9       markus    518:                if ((r = sshsk_ed25519_sig(resp, sig)) != 0)
1.5       markus    519:                        goto out;
                    520:                break;
                    521:        }
1.1       djm       522: #ifdef DEBUG_SK
1.5       markus    523:        fprintf(stderr, "%s: sig_flags = 0x%02x, sig_counter = %u\n",
                    524:            __func__, resp->flags, resp->counter);
1.1       djm       525:        fprintf(stderr, "%s: hashed message:\n", __func__);
                    526:        sshbuf_dump_data(message, sizeof(message), stderr);
                    527:        fprintf(stderr, "%s: sigbuf:\n", __func__);
                    528:        sshbuf_dump(sig, stderr);
                    529: #endif
                    530:        if (sigp != NULL) {
                    531:                if ((*sigp = malloc(sshbuf_len(sig))) == NULL) {
                    532:                        r = SSH_ERR_ALLOC_FAIL;
                    533:                        goto out;
                    534:                }
                    535:                memcpy(*sigp, sshbuf_ptr(sig), sshbuf_len(sig));
                    536:        }
                    537:        if (lenp != NULL)
                    538:                *lenp = sshbuf_len(sig);
                    539:        /* success */
                    540:        r = 0;
                    541:  out:
                    542:        explicit_bzero(message, sizeof(message));
                    543:        sshsk_free(skp);
                    544:        sshsk_free_sign_response(resp);
                    545:        sshbuf_free(sig);
                    546:        sshbuf_free(inner_sig);
                    547:        return r;
                    548: }