[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.7

1.7     ! markus      1: /* $OpenBSD: ssh-sk.c,v 1.6 2019/11/12 19:31:45 markus 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:
                     59: static void
                     60: sshsk_free(struct sshsk_provider *p)
                     61: {
                     62:        if (p == NULL)
                     63:                return;
                     64:        free(p->path);
                     65:        if (p->dlhandle != NULL)
                     66:                dlclose(p->dlhandle);
                     67:        free(p);
                     68: }
                     69:
                     70: static struct sshsk_provider *
                     71: sshsk_open(const char *path)
                     72: {
                     73:        struct sshsk_provider *ret = NULL;
                     74:        uint32_t version;
                     75:
                     76:        if ((ret = calloc(1, sizeof(*ret))) == NULL) {
                     77:                error("%s: calloc failed", __func__);
                     78:                return NULL;
                     79:        }
                     80:        if ((ret->path = strdup(path)) == NULL) {
                     81:                error("%s: strdup failed", __func__);
                     82:                goto fail;
                     83:        }
                     84:        if ((ret->dlhandle = dlopen(path, RTLD_NOW)) == NULL) {
                     85:                error("Security key provider %s dlopen failed: %s",
                     86:                    path, dlerror());
                     87:                goto fail;
                     88:        }
                     89:        if ((ret->sk_api_version = dlsym(ret->dlhandle,
                     90:            "sk_api_version")) == NULL) {
                     91:                error("Security key provider %s dlsym(sk_api_version) "
                     92:                    "failed: %s", path, dlerror());
                     93:                goto fail;
                     94:        }
                     95:        version = ret->sk_api_version();
                     96:        debug("%s: provider %s implements version 0x%08lx", __func__,
                     97:            ret->path, (u_long)version);
                     98:        if ((version & SSH_SK_VERSION_MAJOR_MASK) != SSH_SK_VERSION_MAJOR) {
                     99:                error("Security key provider %s implements unsupported version "
                    100:                    "0x%08lx (supported: 0x%08lx)", path, (u_long)version,
                    101:                    (u_long)SSH_SK_VERSION_MAJOR);
                    102:                goto fail;
                    103:        }
                    104:        if ((ret->sk_enroll = dlsym(ret->dlhandle, "sk_enroll")) == NULL) {
                    105:                error("Security key  provider %s dlsym(sk_enroll) "
                    106:                    "failed: %s", path, dlerror());
                    107:                goto fail;
                    108:        }
                    109:        if ((ret->sk_sign = dlsym(ret->dlhandle, "sk_sign")) == NULL) {
                    110:                error("Security key provider %s dlsym(sk_sign) failed: %s",
                    111:                    path, dlerror());
                    112:                goto fail;
                    113:        }
                    114:        /* success */
                    115:        return ret;
                    116: fail:
                    117:        sshsk_free(ret);
                    118:        return NULL;
                    119: }
                    120:
                    121: static void
                    122: sshsk_free_enroll_response(struct sk_enroll_response *r)
                    123: {
                    124:        if (r == NULL)
                    125:                return;
                    126:        freezero(r->key_handle, r->key_handle_len);
                    127:        freezero(r->public_key, r->public_key_len);
                    128:        freezero(r->signature, r->signature_len);
                    129:        freezero(r->attestation_cert, r->attestation_cert_len);
                    130:        freezero(r, sizeof(*r));
                    131: };
                    132:
                    133: static void
                    134: sshsk_free_sign_response(struct sk_sign_response *r)
                    135: {
                    136:        if (r == NULL)
                    137:                return;
                    138:        freezero(r->sig_r, r->sig_r_len);
                    139:        freezero(r->sig_s, r->sig_s_len);
                    140:        freezero(r, sizeof(*r));
                    141: };
                    142:
1.2       markus    143: /* Assemble key from response */
                    144: static int
                    145: sshsk_ecdsa_assemble(struct sk_enroll_response *resp, struct sshkey **keyp)
                    146: {
                    147:        struct sshkey *key = NULL;
                    148:        struct sshbuf *b = NULL;
                    149:        EC_POINT *q = NULL;
                    150:        int r;
                    151:
                    152:        *keyp = NULL;
                    153:        if ((key = sshkey_new(KEY_ECDSA_SK)) == NULL) {
                    154:                error("%s: sshkey_new failed", __func__);
                    155:                r = SSH_ERR_ALLOC_FAIL;
                    156:                goto out;
                    157:        }
                    158:        key->ecdsa_nid = NID_X9_62_prime256v1;
                    159:        if ((key->ecdsa = EC_KEY_new_by_curve_name(key->ecdsa_nid)) == NULL ||
                    160:            (q = EC_POINT_new(EC_KEY_get0_group(key->ecdsa))) == NULL ||
                    161:            (b = sshbuf_new()) == NULL) {
                    162:                error("%s: allocation failed", __func__);
                    163:                r = SSH_ERR_ALLOC_FAIL;
                    164:                goto out;
                    165:        }
                    166:        if ((r = sshbuf_put_string(b,
                    167:            resp->public_key, resp->public_key_len)) != 0) {
                    168:                error("%s: buffer error: %s", __func__, ssh_err(r));
                    169:                goto out;
                    170:        }
                    171:        if ((r = sshbuf_get_ec(b, q, EC_KEY_get0_group(key->ecdsa))) != 0) {
                    172:                error("%s: parse key: %s", __func__, ssh_err(r));
                    173:                r = SSH_ERR_INVALID_FORMAT;
                    174:                goto out;
                    175:        }
                    176:        if (sshkey_ec_validate_public(EC_KEY_get0_group(key->ecdsa), q) != 0) {
                    177:                error("Security key returned invalid ECDSA key");
                    178:                r = SSH_ERR_KEY_INVALID_EC_VALUE;
                    179:                goto out;
                    180:        }
                    181:        if (EC_KEY_set_public_key(key->ecdsa, q) != 1) {
                    182:                /* XXX assume it is a allocation error */
                    183:                error("%s: allocation failed", __func__);
                    184:                r = SSH_ERR_ALLOC_FAIL;
                    185:                goto out;
                    186:        }
                    187:        /* success */
                    188:        *keyp = key;
                    189:        key = NULL; /* transferred */
                    190:        r = 0;
                    191:  out:
                    192:        EC_POINT_free(q);
                    193:        sshkey_free(key);
                    194:        sshbuf_free(b);
                    195:        return r;
                    196: }
                    197:
1.6       markus    198: static int
                    199: sshsk_ed25519_assemble(struct sk_enroll_response *resp, struct sshkey **keyp)
                    200: {
                    201:        struct sshkey *key = NULL;
                    202:        int r;
                    203:
                    204:        *keyp = NULL;
                    205:        if (resp->public_key_len != ED25519_PK_SZ) {
                    206:                error("%s: invalid size: %zu", __func__, resp->public_key_len);
                    207:                r = SSH_ERR_INVALID_FORMAT;
                    208:                goto out;
                    209:        }
                    210:        if ((key = sshkey_new(KEY_ED25519_SK)) == NULL) {
                    211:                error("%s: sshkey_new failed", __func__);
                    212:                r = SSH_ERR_ALLOC_FAIL;
                    213:                goto out;
                    214:        }
                    215:        if ((key->ed25519_pk = malloc(ED25519_PK_SZ)) == NULL) {
                    216:                error("%s: malloc failed", __func__);
                    217:                r = SSH_ERR_ALLOC_FAIL;
                    218:                goto out;
                    219:        }
                    220:        memcpy(key->ed25519_pk, resp->public_key, ED25519_PK_SZ);
                    221:        /* success */
                    222:        *keyp = key;
                    223:        key = NULL; /* transferred */
                    224:        r = 0;
                    225:  out:
                    226:        sshkey_free(key);
                    227:        return r;
                    228: }
                    229:
1.1       djm       230: int
1.6       markus    231: sshsk_enroll(int type, const char *provider_path, const char *application,
1.1       djm       232:     uint8_t flags, struct sshbuf *challenge_buf, struct sshkey **keyp,
                    233:     struct sshbuf *attest)
                    234: {
                    235:        struct sshsk_provider *skp = NULL;
                    236:        struct sshkey *key = NULL;
                    237:        u_char randchall[32];
                    238:        const u_char *challenge;
                    239:        size_t challenge_len;
                    240:        struct sk_enroll_response *resp = NULL;
                    241:        int r = SSH_ERR_INTERNAL_ERROR;
1.7     ! markus    242:        int alg;
1.1       djm       243:
                    244:        *keyp = NULL;
                    245:        if (attest)
                    246:                sshbuf_reset(attest);
1.6       markus    247:        switch (type) {
                    248:        case KEY_ECDSA_SK:
1.7     ! markus    249:                alg = SSH_SK_ECDSA;
        !           250:                break;
1.6       markus    251:        case KEY_ED25519_SK:
1.7     ! markus    252:                alg = SSH_SK_ED25519;
1.6       markus    253:                break;
                    254:        default:
                    255:                error("%s: unsupported key type", __func__);
                    256:                r = SSH_ERR_INVALID_ARGUMENT;
                    257:                goto out;
                    258:        }
1.1       djm       259:        if (provider_path == NULL) {
                    260:                error("%s: missing provider", __func__);
                    261:                r = SSH_ERR_INVALID_ARGUMENT;
                    262:                goto out;
                    263:        }
                    264:        if (application == NULL || *application == '\0') {
                    265:                error("%s: missing application", __func__);
                    266:                r = SSH_ERR_INVALID_ARGUMENT;
                    267:                goto out;
                    268:        }
                    269:        if (challenge_buf == NULL) {
                    270:                debug("%s: using random challenge", __func__);
                    271:                arc4random_buf(randchall, sizeof(randchall));
                    272:                challenge = randchall;
                    273:                challenge_len = sizeof(randchall);
                    274:        } else if (sshbuf_len(challenge_buf) == 0) {
                    275:                error("Missing enrollment challenge");
                    276:                r = SSH_ERR_INVALID_ARGUMENT;
                    277:                goto out;
                    278:        } else {
                    279:                challenge = sshbuf_ptr(challenge_buf);
                    280:                challenge_len = sshbuf_len(challenge_buf);
                    281:                debug3("%s: using explicit challenge len=%zd",
                    282:                    __func__, challenge_len);
                    283:        }
                    284:        if ((skp = sshsk_open(provider_path)) == NULL) {
                    285:                r = SSH_ERR_INVALID_FORMAT; /* XXX sshsk_open return code? */
                    286:                goto out;
                    287:        }
                    288:        /* XXX validate flags? */
                    289:        /* enroll key */
1.7     ! markus    290:        if ((r = skp->sk_enroll(alg, challenge, challenge_len, application,
1.1       djm       291:            flags, &resp)) != 0) {
                    292:                error("Security key provider %s returned failure %d",
                    293:                    provider_path, r);
                    294:                r = SSH_ERR_INVALID_FORMAT; /* XXX error codes in API? */
                    295:                goto out;
                    296:        }
                    297:        /* Check response validity */
                    298:        if (resp->public_key == NULL || resp->key_handle == NULL ||
                    299:            resp->signature == NULL || resp->attestation_cert == NULL) {
                    300:                error("%s: sk_enroll response invalid", __func__);
                    301:                r = SSH_ERR_INVALID_FORMAT;
                    302:                goto out;
                    303:        }
1.6       markus    304:        switch (type) {
                    305:        case KEY_ECDSA_SK:
                    306:                if ((r = sshsk_ecdsa_assemble(resp, &key)) != 0)
                    307:                        goto out;
                    308:                break;
                    309:        case KEY_ED25519_SK:
                    310:                if ((r = sshsk_ed25519_assemble(resp, &key)) != 0)
                    311:                        goto out;
                    312:                break;
                    313:        }
1.1       djm       314:        key->sk_flags = flags;
1.2       markus    315:        if ((key->sk_key_handle = sshbuf_new()) == NULL ||
                    316:            (key->sk_reserved = sshbuf_new()) == NULL) {
1.1       djm       317:                error("%s: allocation failed", __func__);
                    318:                r = SSH_ERR_ALLOC_FAIL;
                    319:                goto out;
                    320:        }
                    321:        if ((key->sk_application = strdup(application)) == NULL) {
                    322:                error("%s: strdup application failed", __func__);
                    323:                r = SSH_ERR_ALLOC_FAIL;
                    324:                goto out;
                    325:        }
                    326:        if ((r = sshbuf_put(key->sk_key_handle, resp->key_handle,
                    327:            resp->key_handle_len)) != 0) {
                    328:                error("%s: buffer error: %s", __func__, ssh_err(r));
                    329:                goto out;
                    330:        }
                    331:        /* Optionally fill in the attestation information */
                    332:        if (attest != NULL) {
                    333:                if ((r = sshbuf_put_cstring(attest, "sk-attest-v00")) != 0 ||
                    334:                    (r = sshbuf_put_u32(attest, 1)) != 0 || /* XXX U2F ver */
                    335:                    (r = sshbuf_put_string(attest,
                    336:                    resp->attestation_cert, resp->attestation_cert_len)) != 0 ||
                    337:                    (r = sshbuf_put_string(attest,
                    338:                    resp->signature, resp->signature_len)) != 0 ||
                    339:                    (r = sshbuf_put_u32(attest, flags)) != 0 || /* XXX right? */
                    340:                    (r = sshbuf_put_string(attest, NULL, 0)) != 0) {
                    341:                        error("%s: buffer error: %s", __func__, ssh_err(r));
                    342:                        goto out;
                    343:                }
                    344:        }
                    345:        /* success */
                    346:        *keyp = key;
                    347:        key = NULL; /* transferred */
                    348:        r = 0;
                    349:  out:
                    350:        sshsk_free(skp);
                    351:        sshkey_free(key);
                    352:        sshsk_free_enroll_response(resp);
                    353:        explicit_bzero(randchall, sizeof(randchall));
                    354:        return r;
                    355: }
                    356:
1.3       markus    357: static int
                    358: sshsk_ecdsa_inner_sig(struct sk_sign_response *resp, struct sshbuf **retp)
                    359: {
                    360:        struct sshbuf *inner_sig = NULL;
                    361:        int r = SSH_ERR_INTERNAL_ERROR;
                    362:
                    363:        *retp = NULL;
                    364:        if ((inner_sig = sshbuf_new()) == NULL) {
                    365:                r = SSH_ERR_ALLOC_FAIL;
                    366:                goto out;
                    367:        }
                    368:        /* Prepare inner signature object */
                    369:        if ((r = sshbuf_put_bignum2_bytes(inner_sig,
                    370:            resp->sig_r, resp->sig_r_len)) != 0 ||
                    371:            (r = sshbuf_put_bignum2_bytes(inner_sig,
                    372:            resp->sig_s, resp->sig_s_len)) != 0 ||
                    373:            (r = sshbuf_put_u8(inner_sig, resp->flags)) != 0 ||
                    374:            (r = sshbuf_put_u32(inner_sig, resp->counter)) != 0) {
                    375:                debug("%s: buffer error: %s", __func__, ssh_err(r));
                    376:                goto out;
                    377:        }
                    378: #ifdef DEBUG_SK
                    379:        fprintf(stderr, "%s: sig_r:\n", __func__);
                    380:        sshbuf_dump_data(resp->sig_r, resp->sig_r_len, stderr);
                    381:        fprintf(stderr, "%s: sig_s:\n", __func__);
                    382:        sshbuf_dump_data(resp->sig_s, resp->sig_s_len, stderr);
1.5       markus    383: #endif
                    384:        *retp = inner_sig;
                    385:        inner_sig = NULL;
                    386:        r = 0;
                    387: out:
                    388:        sshbuf_free(inner_sig);
                    389:        return r;
                    390: }
                    391:
                    392: static int
                    393: sshsk_ed25519_inner_sig(struct sk_sign_response *resp, struct sshbuf **retp)
                    394: {
                    395:        struct sshbuf *inner_sig = NULL;
                    396:        int r = SSH_ERR_INTERNAL_ERROR;
                    397:
                    398:        *retp = NULL;
                    399:        if ((inner_sig = sshbuf_new()) == NULL) {
                    400:                r = SSH_ERR_ALLOC_FAIL;
                    401:                goto out;
                    402:        }
                    403:        /* Prepare inner signature object */
                    404:        if ((r = sshbuf_put_string(inner_sig,
                    405:            resp->sig_r, resp->sig_r_len)) != 0 ||
                    406:            (r = sshbuf_put_u8(inner_sig, resp->flags)) != 0 ||
                    407:            (r = sshbuf_put_u32(inner_sig, resp->counter)) != 0) {
                    408:                debug("%s: buffer error: %s", __func__, ssh_err(r));
                    409:                goto out;
                    410:        }
                    411: #ifdef DEBUG_SK
                    412:        fprintf(stderr, "%s: sig_r:\n", __func__);
                    413:        sshbuf_dump_data(resp->sig_r, resp->sig_r_len, stderr);
1.3       markus    414: #endif
                    415:        *retp = inner_sig;
                    416:        inner_sig = NULL;
                    417:        r = 0;
                    418: out:
                    419:        sshbuf_free(inner_sig);
                    420:        return r;
                    421: }
                    422:
1.1       djm       423: int
1.4       markus    424: sshsk_sign(const char *provider_path, const struct sshkey *key,
1.1       djm       425:     u_char **sigp, size_t *lenp, const u_char *data, size_t datalen,
                    426:     u_int compat)
                    427: {
                    428:        struct sshsk_provider *skp = NULL;
                    429:        int r = SSH_ERR_INTERNAL_ERROR;
1.7     ! markus    430:        int type, alg;
1.1       djm       431:        struct sk_sign_response *resp = NULL;
                    432:        struct sshbuf *inner_sig = NULL, *sig = NULL;
                    433:        uint8_t message[32];
                    434:
                    435:        if (sigp != NULL)
                    436:                *sigp = NULL;
                    437:        if (lenp != NULL)
                    438:                *lenp = 0;
1.5       markus    439:        type = sshkey_type_plain(key->type);
                    440:        switch (type) {
                    441:        case KEY_ECDSA_SK:
1.7     ! markus    442:                alg = SSH_SK_ECDSA;
        !           443:                break;
1.5       markus    444:        case KEY_ED25519_SK:
1.7     ! markus    445:                alg = SSH_SK_ED25519;
1.5       markus    446:                break;
                    447:        default:
                    448:                return SSH_ERR_INVALID_ARGUMENT;
                    449:        }
1.1       djm       450:        if (provider_path == NULL ||
                    451:            key->sk_key_handle == NULL ||
                    452:            key->sk_application == NULL || *key->sk_application == '\0') {
                    453:                r = SSH_ERR_INVALID_ARGUMENT;
                    454:                goto out;
                    455:        }
                    456:        if ((skp = sshsk_open(provider_path)) == NULL) {
                    457:                r = SSH_ERR_INVALID_FORMAT; /* XXX sshsk_open return code? */
                    458:                goto out;
                    459:        }
                    460:
                    461:        /* hash data to be signed before it goes to the security key */
                    462:        if ((r = ssh_digest_memory(SSH_DIGEST_SHA256, data, datalen,
                    463:            message, sizeof(message))) != 0) {
                    464:                error("%s: hash application failed: %s", __func__, ssh_err(r));
                    465:                r = SSH_ERR_INTERNAL_ERROR;
                    466:                goto out;
                    467:        }
1.7     ! markus    468:        if ((r = skp->sk_sign(alg, message, sizeof(message),
1.1       djm       469:            key->sk_application,
                    470:            sshbuf_ptr(key->sk_key_handle), sshbuf_len(key->sk_key_handle),
                    471:            key->sk_flags, &resp)) != 0) {
                    472:                debug("%s: sk_sign failed with code %d", __func__, r);
                    473:                goto out;
                    474:        }
1.3       markus    475:        /* Prepare inner signature object */
1.5       markus    476:        switch (type) {
                    477:        case KEY_ECDSA_SK:
                    478:                if ((r = sshsk_ecdsa_inner_sig(resp, &inner_sig)) != 0)
                    479:                        goto out;
                    480:                break;
                    481:        case KEY_ED25519_SK:
                    482:                if ((r = sshsk_ed25519_inner_sig(resp, &inner_sig)) != 0)
                    483:                        goto out;
                    484:                break;
                    485:        }
1.3       markus    486:        /* Assemble outer signature */
                    487:        if ((sig = sshbuf_new()) == NULL) {
1.1       djm       488:                r = SSH_ERR_ALLOC_FAIL;
                    489:                goto out;
                    490:        }
                    491:        if ((r = sshbuf_put_cstring(sig, sshkey_ssh_name_plain(key))) != 0 ||
                    492:            (r = sshbuf_put_stringb(sig, inner_sig)) != 0) {
                    493:                debug("%s: buffer error (outer): %s", __func__, ssh_err(r));
                    494:                goto out;
                    495:        }
                    496: #ifdef DEBUG_SK
1.5       markus    497:        fprintf(stderr, "%s: sig_flags = 0x%02x, sig_counter = %u\n",
                    498:            __func__, resp->flags, resp->counter);
1.1       djm       499:        fprintf(stderr, "%s: hashed message:\n", __func__);
                    500:        sshbuf_dump_data(message, sizeof(message), stderr);
                    501:        fprintf(stderr, "%s: inner:\n", __func__);
                    502:        sshbuf_dump(inner_sig, stderr);
                    503:        fprintf(stderr, "%s: sigbuf:\n", __func__);
                    504:        sshbuf_dump(sig, stderr);
                    505: #endif
                    506:        if (sigp != NULL) {
                    507:                if ((*sigp = malloc(sshbuf_len(sig))) == NULL) {
                    508:                        r = SSH_ERR_ALLOC_FAIL;
                    509:                        goto out;
                    510:                }
                    511:                memcpy(*sigp, sshbuf_ptr(sig), sshbuf_len(sig));
                    512:        }
                    513:        if (lenp != NULL)
                    514:                *lenp = sshbuf_len(sig);
                    515:        /* success */
                    516:        r = 0;
                    517:  out:
                    518:        explicit_bzero(message, sizeof(message));
                    519:        sshsk_free(skp);
                    520:        sshsk_free_sign_response(resp);
                    521:        sshbuf_free(sig);
                    522:        sshbuf_free(inner_sig);
                    523:        return r;
                    524: }