]> git.ipfire.org Git - thirdparty/openssh-portable.git/commitdiff
upstream: refactor sshkey_sign() and sshkey_verify()
authordjm@openbsd.org <djm@openbsd.org>
Fri, 28 Oct 2022 00:43:08 +0000 (00:43 +0000)
committerDamien Miller <djm@mindrot.org>
Fri, 28 Oct 2022 01:47:00 +0000 (12:47 +1100)
feedback/ok markus@

OpenBSD-Commit-ID: 368e662c128c99d05cc043b1308d2b6c71a4d3cc

ssh-dss.c
ssh-ecdsa-sk.c
ssh-ecdsa.c
ssh-ed25519-sk.c
ssh-ed25519.c
ssh-rsa.c
ssh-xmss.c
sshkey.c
sshkey.h

index baf3cfb1b96aab6f5f0777f96bfb73614f89f7a6..58c66c7daad9822810d3847870c631f32a5e1ee1 100644 (file)
--- a/ssh-dss.c
+++ b/ssh-dss.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-dss.c,v 1.45 2022/10/28 00:41:52 djm Exp $ */
+/* $OpenBSD: ssh-dss.c,v 1.46 2022/10/28 00:43:08 djm Exp $ */
 /*
  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
  *
@@ -217,9 +217,11 @@ ssh_dss_deserialize_public(const char *ktype, struct sshbuf *b,
        return ret;
 }
 
-int
-ssh_dss_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
-    const u_char *data, size_t datalen, u_int compat)
+static int
+ssh_dss_sign(struct sshkey *key,
+    u_char **sigp, size_t *lenp,
+    const u_char *data, size_t datalen,
+    const char *alg, const char *sk_provider, const char *sk_pin, u_int compat)
 {
        DSA_SIG *sig = NULL;
        const BIGNUM *sig_r, *sig_s;
@@ -285,28 +287,29 @@ ssh_dss_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
        return ret;
 }
 
-int
+static int
 ssh_dss_verify(const struct sshkey *key,
-    const u_char *signature, size_t signaturelen,
-    const u_char *data, size_t datalen, u_int compat)
+    const u_char *sig, size_t siglen,
+    const u_char *data, size_t dlen, const char *alg, u_int compat,
+    struct sshkey_sig_details **detailsp)
 {
-       DSA_SIG *sig = NULL;
+       DSA_SIG *dsig = NULL;
        BIGNUM *sig_r = NULL, *sig_s = NULL;
        u_char digest[SSH_DIGEST_MAX_LENGTH], *sigblob = NULL;
-       size_t len, dlen = ssh_digest_bytes(SSH_DIGEST_SHA1);
+       size_t len, hlen = ssh_digest_bytes(SSH_DIGEST_SHA1);
        int ret = SSH_ERR_INTERNAL_ERROR;
        struct sshbuf *b = NULL;
        char *ktype = NULL;
 
        if (key == NULL || key->dsa == NULL ||
            sshkey_type_plain(key->type) != KEY_DSA ||
-           signature == NULL || signaturelen == 0)
+           sig == NULL || siglen == 0)
                return SSH_ERR_INVALID_ARGUMENT;
-       if (dlen == 0)
+       if (hlen == 0)
                return SSH_ERR_INTERNAL_ERROR;
 
        /* fetch signature */
-       if ((b = sshbuf_from(signature, signaturelen)) == NULL)
+       if ((b = sshbuf_from(sig, siglen)) == NULL)
                return SSH_ERR_ALLOC_FAIL;
        if (sshbuf_get_cstring(b, &ktype, NULL) != 0 ||
            sshbuf_get_string(b, &sigblob, &len) != 0) {
@@ -328,7 +331,7 @@ ssh_dss_verify(const struct sshkey *key,
        }
 
        /* parse signature */
-       if ((sig = DSA_SIG_new()) == NULL ||
+       if ((dsig = DSA_SIG_new()) == NULL ||
            (sig_r = BN_new()) == NULL ||
            (sig_s = BN_new()) == NULL) {
                ret = SSH_ERR_ALLOC_FAIL;
@@ -339,18 +342,18 @@ ssh_dss_verify(const struct sshkey *key,
                ret = SSH_ERR_LIBCRYPTO_ERROR;
                goto out;
        }
-       if (!DSA_SIG_set0(sig, sig_r, sig_s)) {
+       if (!DSA_SIG_set0(dsig, sig_r, sig_s)) {
                ret = SSH_ERR_LIBCRYPTO_ERROR;
                goto out;
        }
        sig_r = sig_s = NULL; /* transferred */
 
        /* sha1 the data */
-       if ((ret = ssh_digest_memory(SSH_DIGEST_SHA1, data, datalen,
+       if ((ret = ssh_digest_memory(SSH_DIGEST_SHA1, data, dlen,
            digest, sizeof(digest))) != 0)
                goto out;
 
-       switch (DSA_do_verify(digest, dlen, sig, key->dsa)) {
+       switch (DSA_do_verify(digest, hlen, dsig, key->dsa)) {
        case 1:
                ret = 0;
                break;
@@ -364,7 +367,7 @@ ssh_dss_verify(const struct sshkey *key,
 
  out:
        explicit_bzero(digest, sizeof(digest));
-       DSA_SIG_free(sig);
+       DSA_SIG_free(dsig);
        BN_clear_free(sig_r);
        BN_clear_free(sig_s);
        sshbuf_free(b);
@@ -383,6 +386,8 @@ static const struct sshkey_impl_funcs sshkey_dss_funcs = {
        /* .ssh_deserialize_public = */ ssh_dss_deserialize_public,
        /* .generate = */       ssh_dss_generate,
        /* .copy_public = */    ssh_dss_copy_public,
+       /* .sign = */           ssh_dss_sign,
+       /* .verify = */         ssh_dss_verify,
 };
 
 const struct sshkey_impl sshkey_dss_impl = {
index cb8bcef1e4df7c370f28af8059bde9d6a68065ba..6e08d8696a063ac6a287fc6ace9cea25ddb46724 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-ecdsa-sk.c,v 1.14 2022/10/28 00:41:52 djm Exp $ */
+/* $OpenBSD: ssh-ecdsa-sk.c,v 1.15 2022/10/28 00:43:08 djm Exp $ */
 /*
  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
  * Copyright (c) 2010 Damien Miller.  All rights reserved.
@@ -197,13 +197,13 @@ webauthn_check_prepare_hash(const u_char *data, size_t datalen,
 }
 
 /* ARGSUSED */
-int
+static int
 ssh_ecdsa_sk_verify(const struct sshkey *key,
-    const u_char *signature, size_t signaturelen,
-    const u_char *data, size_t datalen, u_int compat,
+    const u_char *sig, size_t siglen,
+    const u_char *data, size_t dlen, const char *alg, u_int compat,
     struct sshkey_sig_details **detailsp)
 {
-       ECDSA_SIG *sig = NULL;
+       ECDSA_SIG *esig = NULL;
        BIGNUM *sig_r = NULL, *sig_s = NULL;
        u_char sig_flags;
        u_char msghash[32], apphash[32], sighash[32];
@@ -221,14 +221,14 @@ ssh_ecdsa_sk_verify(const struct sshkey *key,
                *detailsp = NULL;
        if (key == NULL || key->ecdsa == NULL ||
            sshkey_type_plain(key->type) != KEY_ECDSA_SK ||
-           signature == NULL || signaturelen == 0)
+           sig == NULL || siglen == 0)
                return SSH_ERR_INVALID_ARGUMENT;
 
        if (key->ecdsa_nid != NID_X9_62_prime256v1)
                return SSH_ERR_INTERNAL_ERROR;
 
        /* fetch signature */
-       if ((b = sshbuf_from(signature, signaturelen)) == NULL)
+       if ((b = sshbuf_from(sig, siglen)) == NULL)
                return SSH_ERR_ALLOC_FAIL;
        if ((details = calloc(1, sizeof(*details))) == NULL) {
                ret = SSH_ERR_ALLOC_FAIL;
@@ -290,11 +290,11 @@ ssh_ecdsa_sk_verify(const struct sshkey *key,
                sshbuf_dump(webauthn_wrapper, stderr);
        }
 #endif
-       if ((sig = ECDSA_SIG_new()) == NULL) {
+       if ((esig = ECDSA_SIG_new()) == NULL) {
                ret = SSH_ERR_ALLOC_FAIL;
                goto out;
        }
-       if (!ECDSA_SIG_set0(sig, sig_r, sig_s)) {
+       if (!ECDSA_SIG_set0(esig, sig_r, sig_s)) {
                ret = SSH_ERR_LIBCRYPTO_ERROR;
                goto out;
        }
@@ -306,11 +306,11 @@ ssh_ecdsa_sk_verify(const struct sshkey *key,
                goto out;
        }
        if (is_webauthn) {
-               if ((ret = webauthn_check_prepare_hash(data, datalen,
+               if ((ret = webauthn_check_prepare_hash(data, dlen,
                    webauthn_origin, webauthn_wrapper, sig_flags, webauthn_exts,
                    msghash, sizeof(msghash))) != 0)
                        goto out;
-       } else if ((ret = ssh_digest_memory(SSH_DIGEST_SHA256, data, datalen,
+       } else if ((ret = ssh_digest_memory(SSH_DIGEST_SHA256, data, dlen,
            msghash, sizeof(msghash))) != 0)
                goto out;
        /* Application value is hashed before signature */
@@ -344,7 +344,7 @@ ssh_ecdsa_sk_verify(const struct sshkey *key,
 #endif
 
        /* Verify it */
-       switch (ECDSA_do_verify(sighash, sizeof(sighash), sig, key->ecdsa)) {
+       switch (ECDSA_do_verify(sighash, sizeof(sighash), esig, key->ecdsa)) {
        case 1:
                ret = 0;
                break;
@@ -373,7 +373,7 @@ ssh_ecdsa_sk_verify(const struct sshkey *key,
        sshbuf_free(original_signed);
        sshbuf_free(sigbuf);
        sshbuf_free(b);
-       ECDSA_SIG_free(sig);
+       ECDSA_SIG_free(esig);
        BN_clear_free(sig_r);
        BN_clear_free(sig_s);
        free(ktype);
@@ -389,6 +389,8 @@ static const struct sshkey_impl_funcs sshkey_ecdsa_sk_funcs = {
        /* .ssh_deserialize_public = */ ssh_ecdsa_sk_deserialize_public,
        /* .generate = */       NULL,
        /* .copy_public = */    ssh_ecdsa_sk_copy_public,
+       /* .sign = */           NULL,
+       /* .verify = */         ssh_ecdsa_sk_verify,
 };
 
 const struct sshkey_impl sshkey_ecdsa_sk_impl = {
index e584cb792e606196f1428da4e3ff1a5f8d6a9b63..a7b1b7b21152ec72df82ed59bb700a5614e205ed 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-ecdsa.c,v 1.22 2022/10/28 00:41:52 djm Exp $ */
+/* $OpenBSD: ssh-ecdsa.c,v 1.23 2022/10/28 00:43:08 djm Exp $ */
 /*
  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
  * Copyright (c) 2010 Damien Miller.  All rights reserved.
@@ -188,15 +188,17 @@ ssh_ecdsa_deserialize_public(const char *ktype, struct sshbuf *b,
 }
 
 /* ARGSUSED */
-int
-ssh_ecdsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
-    const u_char *data, size_t datalen, u_int compat)
+static int
+ssh_ecdsa_sign(struct sshkey *key,
+    u_char **sigp, size_t *lenp,
+    const u_char *data, size_t dlen,
+    const char *alg, const char *sk_provider, const char *sk_pin, u_int compat)
 {
-       ECDSA_SIG *sig = NULL;
+       ECDSA_SIG *esig = NULL;
        const BIGNUM *sig_r, *sig_s;
        int hash_alg;
        u_char digest[SSH_DIGEST_MAX_LENGTH];
-       size_t len, dlen;
+       size_t len, hlen;
        struct sshbuf *b = NULL, *bb = NULL;
        int ret = SSH_ERR_INTERNAL_ERROR;
 
@@ -210,13 +212,13 @@ ssh_ecdsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
                return SSH_ERR_INVALID_ARGUMENT;
 
        if ((hash_alg = sshkey_ec_nid_to_hash_alg(key->ecdsa_nid)) == -1 ||
-           (dlen = ssh_digest_bytes(hash_alg)) == 0)
+           (hlen = ssh_digest_bytes(hash_alg)) == 0)
                return SSH_ERR_INTERNAL_ERROR;
-       if ((ret = ssh_digest_memory(hash_alg, data, datalen,
+       if ((ret = ssh_digest_memory(hash_alg, data, dlen,
            digest, sizeof(digest))) != 0)
                goto out;
 
-       if ((sig = ECDSA_do_sign(digest, dlen, key->ecdsa)) == NULL) {
+       if ((esig = ECDSA_do_sign(digest, hlen, key->ecdsa)) == NULL) {
                ret = SSH_ERR_LIBCRYPTO_ERROR;
                goto out;
        }
@@ -225,7 +227,7 @@ ssh_ecdsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
                ret = SSH_ERR_ALLOC_FAIL;
                goto out;
        }
-       ECDSA_SIG_get0(sig, &sig_r, &sig_s);
+       ECDSA_SIG_get0(esig, &sig_r, &sig_s);
        if ((ret = sshbuf_put_bignum2(bb, sig_r)) != 0 ||
            (ret = sshbuf_put_bignum2(bb, sig_s)) != 0)
                goto out;
@@ -247,36 +249,37 @@ ssh_ecdsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
        explicit_bzero(digest, sizeof(digest));
        sshbuf_free(b);
        sshbuf_free(bb);
-       ECDSA_SIG_free(sig);
+       ECDSA_SIG_free(esig);
        return ret;
 }
 
 /* ARGSUSED */
-int
+static int
 ssh_ecdsa_verify(const struct sshkey *key,
-    const u_char *signature, size_t signaturelen,
-    const u_char *data, size_t datalen, u_int compat)
+    const u_char *sig, size_t siglen,
+    const u_char *data, size_t dlen, const char *alg, u_int compat,
+    struct sshkey_sig_details **detailsp)
 {
-       ECDSA_SIG *sig = NULL;
+       ECDSA_SIG *esig = NULL;
        BIGNUM *sig_r = NULL, *sig_s = NULL;
        int hash_alg;
        u_char digest[SSH_DIGEST_MAX_LENGTH];
-       size_t dlen;
+       size_t hlen;
        int ret = SSH_ERR_INTERNAL_ERROR;
        struct sshbuf *b = NULL, *sigbuf = NULL;
        char *ktype = NULL;
 
        if (key == NULL || key->ecdsa == NULL ||
            sshkey_type_plain(key->type) != KEY_ECDSA ||
-           signature == NULL || signaturelen == 0)
+           sig == NULL || siglen == 0)
                return SSH_ERR_INVALID_ARGUMENT;
 
        if ((hash_alg = sshkey_ec_nid_to_hash_alg(key->ecdsa_nid)) == -1 ||
-           (dlen = ssh_digest_bytes(hash_alg)) == 0)
+           (hlen = ssh_digest_bytes(hash_alg)) == 0)
                return SSH_ERR_INTERNAL_ERROR;
 
        /* fetch signature */
-       if ((b = sshbuf_from(signature, signaturelen)) == NULL)
+       if ((b = sshbuf_from(sig, siglen)) == NULL)
                return SSH_ERR_ALLOC_FAIL;
        if (sshbuf_get_cstring(b, &ktype, NULL) != 0 ||
            sshbuf_froms(b, &sigbuf) != 0) {
@@ -298,11 +301,11 @@ ssh_ecdsa_verify(const struct sshkey *key,
                ret = SSH_ERR_INVALID_FORMAT;
                goto out;
        }
-       if ((sig = ECDSA_SIG_new()) == NULL) {
+       if ((esig = ECDSA_SIG_new()) == NULL) {
                ret = SSH_ERR_ALLOC_FAIL;
                goto out;
        }
-       if (!ECDSA_SIG_set0(sig, sig_r, sig_s)) {
+       if (!ECDSA_SIG_set0(esig, sig_r, sig_s)) {
                ret = SSH_ERR_LIBCRYPTO_ERROR;
                goto out;
        }
@@ -312,11 +315,11 @@ ssh_ecdsa_verify(const struct sshkey *key,
                ret = SSH_ERR_UNEXPECTED_TRAILING_DATA;
                goto out;
        }
-       if ((ret = ssh_digest_memory(hash_alg, data, datalen,
+       if ((ret = ssh_digest_memory(hash_alg, data, dlen,
            digest, sizeof(digest))) != 0)
                goto out;
 
-       switch (ECDSA_do_verify(digest, dlen, sig, key->ecdsa)) {
+       switch (ECDSA_do_verify(digest, hlen, esig, key->ecdsa)) {
        case 1:
                ret = 0;
                break;
@@ -332,7 +335,7 @@ ssh_ecdsa_verify(const struct sshkey *key,
        explicit_bzero(digest, sizeof(digest));
        sshbuf_free(sigbuf);
        sshbuf_free(b);
-       ECDSA_SIG_free(sig);
+       ECDSA_SIG_free(esig);
        BN_clear_free(sig_r);
        BN_clear_free(sig_s);
        free(ktype);
@@ -349,6 +352,8 @@ const struct sshkey_impl_funcs sshkey_ecdsa_funcs = {
        /* .ssh_deserialize_public = */ ssh_ecdsa_deserialize_public,
        /* .generate = */       ssh_ecdsa_generate,
        /* .copy_public = */    ssh_ecdsa_copy_public,
+       /* .sign = */           ssh_ecdsa_sign,
+       /* .verify = */         ssh_ecdsa_verify,
 };
 
 const struct sshkey_impl sshkey_ecdsa_nistp256_impl = {
index eba835d91002c8590c1a3c863a45b94b4d8c6063..1eef5424c2c475ae55ecb7eaeb258da6b13019ba 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-ed25519-sk.c,v 1.12 2022/10/28 00:41:52 djm Exp $ */
+/* $OpenBSD: ssh-ed25519-sk.c,v 1.13 2022/10/28 00:43:08 djm Exp $ */
 /*
  * Copyright (c) 2019 Markus Friedl.  All rights reserved.
  *
@@ -94,10 +94,10 @@ ssh_ed25519_sk_deserialize_public(const char *ktype, struct sshbuf *b,
        return 0;
 }
 
-int
+static int
 ssh_ed25519_sk_verify(const struct sshkey *key,
-    const u_char *signature, size_t signaturelen,
-    const u_char *data, size_t datalen, u_int compat,
+    const u_char *sig, size_t siglen,
+    const u_char *data, size_t dlen, const char *alg, u_int compat,
     struct sshkey_sig_details **detailsp)
 {
        struct sshbuf *b = NULL;
@@ -122,10 +122,10 @@ ssh_ed25519_sk_verify(const struct sshkey *key,
        if (key == NULL ||
            sshkey_type_plain(key->type) != KEY_ED25519_SK ||
            key->ed25519_pk == NULL ||
-           signature == NULL || signaturelen == 0)
+           sig == NULL || siglen == 0)
                return SSH_ERR_INVALID_ARGUMENT;
 
-       if ((b = sshbuf_from(signature, signaturelen)) == NULL)
+       if ((b = sshbuf_from(sig, siglen)) == NULL)
                return SSH_ERR_ALLOC_FAIL;
        if (sshbuf_get_cstring(b, &ktype, NULL) != 0 ||
            sshbuf_get_string_direct(b, &sigblob, &len) != 0 ||
@@ -156,7 +156,7 @@ ssh_ed25519_sk_verify(const struct sshkey *key,
        }
        if (ssh_digest_memory(SSH_DIGEST_SHA256, key->sk_application,
            strlen(key->sk_application), apphash, sizeof(apphash)) != 0 ||
-           ssh_digest_memory(SSH_DIGEST_SHA256, data, datalen,
+           ssh_digest_memory(SSH_DIGEST_SHA256, data, dlen,
            msghash, sizeof(msghash)) != 0) {
                r = SSH_ERR_INVALID_ARGUMENT;
                goto out;
@@ -230,6 +230,8 @@ static const struct sshkey_impl_funcs sshkey_ed25519_sk_funcs = {
        /* .ssh_deserialize_public = */ ssh_ed25519_sk_deserialize_public,
        /* .generate = */       NULL,
        /* .copy_public = */    ssh_ed25519_sk_copy_public,
+       /* .sign = */           NULL,
+       /* .verify = */         ssh_ed25519_sk_verify,
 };
 
 const struct sshkey_impl sshkey_ed25519_sk_impl = {
index 1556641dfc456d51c8a4ce21005b9a160bf879ba..8e6fabed06f5c03e1806696f434cd85ddc42ab2f 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-ed25519.c,v 1.16 2022/10/28 00:41:52 djm Exp $ */
+/* $OpenBSD: ssh-ed25519.c,v 1.17 2022/10/28 00:43:08 djm Exp $ */
 /*
  * Copyright (c) 2013 Markus Friedl <markus@openbsd.org>
  *
@@ -104,9 +104,11 @@ ssh_ed25519_deserialize_public(const char *ktype, struct sshbuf *b,
        return 0;
 }
 
-int
-ssh_ed25519_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
-    const u_char *data, size_t datalen, u_int compat)
+static int
+ssh_ed25519_sign(struct sshkey *key,
+    u_char **sigp, size_t *lenp,
+    const u_char *data, size_t datalen,
+    const char *alg, const char *sk_provider, const char *sk_pin, u_int compat)
 {
        u_char *sig = NULL;
        size_t slen = 0, len;
@@ -161,10 +163,11 @@ ssh_ed25519_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
        return r;
 }
 
-int
+static int
 ssh_ed25519_verify(const struct sshkey *key,
-    const u_char *signature, size_t signaturelen,
-    const u_char *data, size_t datalen, u_int compat)
+    const u_char *sig, size_t siglen,
+    const u_char *data, size_t dlen, const char *alg, u_int compat,
+    struct sshkey_sig_details **detailsp)
 {
        struct sshbuf *b = NULL;
        char *ktype = NULL;
@@ -177,11 +180,11 @@ ssh_ed25519_verify(const struct sshkey *key,
        if (key == NULL ||
            sshkey_type_plain(key->type) != KEY_ED25519 ||
            key->ed25519_pk == NULL ||
-           datalen >= INT_MAX - crypto_sign_ed25519_BYTES ||
-           signature == NULL || signaturelen == 0)
+           dlen >= INT_MAX - crypto_sign_ed25519_BYTES ||
+           sig == NULL || siglen == 0)
                return SSH_ERR_INVALID_ARGUMENT;
 
-       if ((b = sshbuf_from(signature, signaturelen)) == NULL)
+       if ((b = sshbuf_from(sig, siglen)) == NULL)
                return SSH_ERR_ALLOC_FAIL;
        if ((r = sshbuf_get_cstring(b, &ktype, NULL)) != 0 ||
            (r = sshbuf_get_string_direct(b, &sigblob, &len)) != 0)
@@ -198,23 +201,23 @@ ssh_ed25519_verify(const struct sshkey *key,
                r = SSH_ERR_INVALID_FORMAT;
                goto out;
        }
-       if (datalen >= SIZE_MAX - len) {
+       if (dlen >= SIZE_MAX - len) {
                r = SSH_ERR_INVALID_ARGUMENT;
                goto out;
        }
-       smlen = len + datalen;
+       smlen = len + dlen;
        mlen = smlen;
        if ((sm = malloc(smlen)) == NULL || (m = malloc(mlen)) == NULL) {
                r = SSH_ERR_ALLOC_FAIL;
                goto out;
        }
        memcpy(sm, sigblob, len);
-       memcpy(sm+len, data, datalen);
+       memcpy(sm+len, data, dlen);
        if ((ret = crypto_sign_ed25519_open(m, &mlen, sm, smlen,
            key->ed25519_pk)) != 0) {
                debug2_f("crypto_sign_ed25519_open failed: %d", ret);
        }
-       if (ret != 0 || mlen != datalen) {
+       if (ret != 0 || mlen != dlen) {
                r = SSH_ERR_SIGNATURE_INVALID;
                goto out;
        }
@@ -241,6 +244,8 @@ const struct sshkey_impl_funcs sshkey_ed25519_funcs = {
        /* .ssh_deserialize_public = */ ssh_ed25519_deserialize_public,
        /* .generate = */       ssh_ed25519_generate,
        /* .copy_public = */    ssh_ed25519_copy_public,
+       /* .sign = */           ssh_ed25519_sign,
+       /* .verify = */         ssh_ed25519_verify,
 };
 
 const struct sshkey_impl sshkey_ed25519_impl = {
index cbea0d2995f0d3158ac9de631e6851fef437b885..07620a8d657af54146b12f2a928b0f55d2589762 100644 (file)
--- a/ssh-rsa.c
+++ b/ssh-rsa.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-rsa.c,v 1.74 2022/10/28 00:41:52 djm Exp $ */
+/* $OpenBSD: ssh-rsa.c,v 1.75 2022/10/28 00:43:08 djm Exp $ */
 /*
  * Copyright (c) 2000, 2003 Markus Friedl <markus@openbsd.org>
  *
@@ -328,14 +328,16 @@ ssh_rsa_complete_crt_parameters(struct sshkey *key, const BIGNUM *iqmp)
 }
 
 /* RSASSA-PKCS1-v1_5 (PKCS #1 v2.0 signature) with SHA1 */
-int
-ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
-    const u_char *data, size_t datalen, const char *alg_ident)
+static int
+ssh_rsa_sign(struct sshkey *key,
+    u_char **sigp, size_t *lenp,
+    const u_char *data, size_t datalen,
+    const char *alg, const char *sk_provider, const char *sk_pin, u_int compat)
 {
        const BIGNUM *rsa_n;
        u_char digest[SSH_DIGEST_MAX_LENGTH], *sig = NULL;
        size_t slen = 0;
-       u_int dlen, len;
+       u_int hlen, len;
        int nid, hash_alg, ret = SSH_ERR_INTERNAL_ERROR;
        struct sshbuf *b = NULL;
 
@@ -344,10 +346,10 @@ ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
        if (sigp != NULL)
                *sigp = NULL;
 
-       if (alg_ident == NULL || strlen(alg_ident) == 0)
+       if (alg == NULL || strlen(alg) == 0)
                hash_alg = SSH_DIGEST_SHA1;
        else
-               hash_alg = rsa_hash_id_from_keyname(alg_ident);
+               hash_alg = rsa_hash_id_from_keyname(alg);
        if (key == NULL || key->rsa == NULL || hash_alg == -1 ||
            sshkey_type_plain(key->type) != KEY_RSA)
                return SSH_ERR_INVALID_ARGUMENT;
@@ -360,7 +362,7 @@ ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
 
        /* hash the data */
        nid = rsa_hash_alg_nid(hash_alg);
-       if ((dlen = ssh_digest_bytes(hash_alg)) == 0)
+       if ((hlen = ssh_digest_bytes(hash_alg)) == 0)
                return SSH_ERR_INTERNAL_ERROR;
        if ((ret = ssh_digest_memory(hash_alg, data, datalen,
            digest, sizeof(digest))) != 0)
@@ -371,7 +373,7 @@ ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
                goto out;
        }
 
-       if (RSA_sign(nid, digest, dlen, sig, &len, key->rsa) != 1) {
+       if (RSA_sign(nid, digest, hlen, sig, &len, key->rsa) != 1) {
                ret = SSH_ERR_LIBCRYPTO_ERROR;
                goto out;
        }
@@ -409,15 +411,16 @@ ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
        return ret;
 }
 
-int
+static int
 ssh_rsa_verify(const struct sshkey *key,
-    const u_char *sig, size_t siglen, const u_char *data, size_t datalen,
-    const char *alg)
+    const u_char *sig, size_t siglen,
+    const u_char *data, size_t dlen, const char *alg, u_int compat,
+    struct sshkey_sig_details **detailsp)
 {
        const BIGNUM *rsa_n;
        char *sigtype = NULL;
        int hash_alg, want_alg, ret = SSH_ERR_INTERNAL_ERROR;
-       size_t len = 0, diff, modlen, dlen;
+       size_t len = 0, diff, modlen, hlen;
        struct sshbuf *b = NULL;
        u_char digest[SSH_DIGEST_MAX_LENGTH], *osigblob, *sigblob = NULL;
 
@@ -478,15 +481,15 @@ ssh_rsa_verify(const struct sshkey *key,
                explicit_bzero(sigblob, diff);
                len = modlen;
        }
-       if ((dlen = ssh_digest_bytes(hash_alg)) == 0) {
+       if ((hlen = ssh_digest_bytes(hash_alg)) == 0) {
                ret = SSH_ERR_INTERNAL_ERROR;
                goto out;
        }
-       if ((ret = ssh_digest_memory(hash_alg, data, datalen,
+       if ((ret = ssh_digest_memory(hash_alg, data, dlen,
            digest, sizeof(digest))) != 0)
                goto out;
 
-       ret = openssh_RSA_verify(hash_alg, digest, dlen, sigblob, len,
+       ret = openssh_RSA_verify(hash_alg, digest, hlen, sigblob, len,
            key->rsa);
  out:
        freezero(sigblob, len);
@@ -624,6 +627,8 @@ static const struct sshkey_impl_funcs sshkey_rsa_funcs = {
        /* .ssh_deserialize_public = */ ssh_rsa_deserialize_public,
        /* .generate = */       ssh_rsa_generate,
        /* .copy_public = */    ssh_rsa_copy_public,
+       /* .sign = */           ssh_rsa_sign,
+       /* .verify = */         ssh_rsa_verify,
 };
 
 const struct sshkey_impl sshkey_rsa_impl = {
index 039436b43a1c9db321065155c3df7423d0b2dfcc..2193aaab5f1648a682b369f4a3af4d3d6cebdac1 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-xmss.c,v 1.11 2022/10/28 00:41:52 djm Exp $*/
+/* $OpenBSD: ssh-xmss.c,v 1.12 2022/10/28 00:43:08 djm Exp $*/
 /*
  * Copyright (c) 2017 Stefan-Lukas Gazdag.
  * Copyright (c) 2017 Markus Friedl.
@@ -138,9 +138,11 @@ ssh_xmss_deserialize_public(const char *ktype, struct sshbuf *b,
        return ret;
 }
 
-int
-ssh_xmss_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
-    const u_char *data, size_t datalen, u_int compat)
+static int
+ssh_xmss_sign(struct sshkey *key,
+    u_char **sigp, size_t *lenp,
+    const u_char *data, size_t datalen,
+    const char *alg, const char *sk_provider, const char *sk_pin, u_int compat)
 {
        u_char *sig = NULL;
        size_t slen = 0, len = 0, required_siglen;
@@ -212,10 +214,11 @@ ssh_xmss_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
        return r;
 }
 
-int
+static int
 ssh_xmss_verify(const struct sshkey *key,
-    const u_char *signature, size_t signaturelen,
-    const u_char *data, size_t datalen, u_int compat)
+    const u_char *sig, size_t siglen,
+    const u_char *data, size_t dlen, const char *alg, u_int compat,
+    struct sshkey_sig_details **detailsp)
 {
        struct sshbuf *b = NULL;
        char *ktype = NULL;
@@ -229,14 +232,14 @@ ssh_xmss_verify(const struct sshkey *key,
            sshkey_type_plain(key->type) != KEY_XMSS ||
            key->xmss_pk == NULL ||
            sshkey_xmss_params(key) == NULL ||
-           signature == NULL || signaturelen == 0)
+           sig == NULL || siglen == 0)
                return SSH_ERR_INVALID_ARGUMENT;
        if ((r = sshkey_xmss_siglen(key, &required_siglen)) != 0)
                return r;
-       if (datalen >= INT_MAX - required_siglen)
+       if (dlen >= INT_MAX - required_siglen)
                return SSH_ERR_INVALID_ARGUMENT;
 
-       if ((b = sshbuf_from(signature, signaturelen)) == NULL)
+       if ((b = sshbuf_from(sig, siglen)) == NULL)
                return SSH_ERR_ALLOC_FAIL;
        if ((r = sshbuf_get_cstring(b, &ktype, NULL)) != 0 ||
            (r = sshbuf_get_string_direct(b, &sigblob, &len)) != 0)
@@ -253,23 +256,23 @@ ssh_xmss_verify(const struct sshkey *key,
                r = SSH_ERR_INVALID_FORMAT;
                goto out;
        }
-       if (datalen >= SIZE_MAX - len) {
+       if (dlen >= SIZE_MAX - len) {
                r = SSH_ERR_INVALID_ARGUMENT;
                goto out;
        }
-       smlen = len + datalen;
+       smlen = len + dlen;
        mlen = smlen;
        if ((sm = malloc(smlen)) == NULL || (m = malloc(mlen)) == NULL) {
                r = SSH_ERR_ALLOC_FAIL;
                goto out;
        }
        memcpy(sm, sigblob, len);
-       memcpy(sm+len, data, datalen);
+       memcpy(sm+len, data, dlen);
        if ((ret = xmss_sign_open(m, &mlen, sm, smlen,
            key->xmss_pk, sshkey_xmss_params(key))) != 0) {
                debug2_f("xmss_sign_open failed: %d", ret);
        }
-       if (ret != 0 || mlen != datalen) {
+       if (ret != 0 || mlen != dlen) {
                r = SSH_ERR_SIGNATURE_INVALID;
                goto out;
        }
@@ -295,6 +298,8 @@ static const struct sshkey_impl_funcs sshkey_xmss_funcs = {
        /* .ssh_deserialize_public = */ ssh_xmss_deserialize_public,
        /* .generate = */       sshkey_xmss_generate_private_key,
        /* .copy_public = */    ssh_xmss_copy_public,
+       /* .sign = */           ssh_xmss_sign,
+       /* .verify = */         ssh_xmss_verify,
 };
 
 const struct sshkey_impl sshkey_xmss_impl = {
index 69b993b0b0509f465daa8fe04392e1b569e715ea..00da6bfb2288a80ec4e1ab2768ee2c3ec8b9b96d 100644 (file)
--- a/sshkey.c
+++ b/sshkey.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshkey.c,v 1.129 2022/10/28 00:41:52 djm Exp $ */
+/* $OpenBSD: sshkey.c,v 1.130 2022/10/28 00:43:08 djm Exp $ */
 /*
  * Copyright (c) 2000, 2001 Markus Friedl.  All rights reserved.
  * Copyright (c) 2008 Alexander von Gernler.  All rights reserved.
@@ -2042,6 +2042,7 @@ sshkey_sign(struct sshkey *key,
 {
        int was_shielded = sshkey_is_shielded(key);
        int r2, r = SSH_ERR_INTERNAL_ERROR;
+       const struct sshkey_impl *impl;
 
        if (sigp != NULL)
                *sigp = NULL;
@@ -2049,45 +2050,20 @@ sshkey_sign(struct sshkey *key,
                *lenp = 0;
        if (datalen > SSH_KEY_MAX_SIGN_DATA_SIZE)
                return SSH_ERR_INVALID_ARGUMENT;
+       if ((impl = sshkey_impl_from_key(key)) == NULL)
+               return SSH_ERR_KEY_TYPE_UNKNOWN;
        if ((r = sshkey_unshield_private(key)) != 0)
                return r;
-       switch (key->type) {
-#ifdef WITH_OPENSSL
-       case KEY_DSA_CERT:
-       case KEY_DSA:
-               r = ssh_dss_sign(key, sigp, lenp, data, datalen, compat);
-               break;
-# ifdef OPENSSL_HAS_ECC
-       case KEY_ECDSA_CERT:
-       case KEY_ECDSA:
-               r = ssh_ecdsa_sign(key, sigp, lenp, data, datalen, compat);
-               break;
-# endif /* OPENSSL_HAS_ECC */
-       case KEY_RSA_CERT:
-       case KEY_RSA:
-               r = ssh_rsa_sign(key, sigp, lenp, data, datalen, alg);
-               break;
-#endif /* WITH_OPENSSL */
-       case KEY_ED25519:
-       case KEY_ED25519_CERT:
-               r = ssh_ed25519_sign(key, sigp, lenp, data, datalen, compat);
-               break;
-       case KEY_ED25519_SK:
-       case KEY_ED25519_SK_CERT:
-       case KEY_ECDSA_SK_CERT:
-       case KEY_ECDSA_SK:
+       if (sshkey_is_sk(key)) {
                r = sshsk_sign(sk_provider, key, sigp, lenp, data,
                    datalen, compat, sk_pin);
-               break;
-#ifdef WITH_XMSS
-       case KEY_XMSS:
-       case KEY_XMSS_CERT:
-               r = ssh_xmss_sign(key, sigp, lenp, data, datalen, compat);
-               break;
-#endif /* WITH_XMSS */
-       default:
-               r = SSH_ERR_KEY_TYPE_UNKNOWN;
-               break;
+       } else {
+               if (impl->funcs->sign == NULL)
+                       r = SSH_ERR_SIGN_ALG_UNSUPPORTED;
+               else {
+                       r = impl->funcs->sign(key, sigp, lenp, data, datalen,
+                           alg, sk_provider, sk_pin, compat);
+                }
        }
        if (was_shielded && (r2 = sshkey_shield_private(key)) != 0)
                return r2;
@@ -2104,43 +2080,16 @@ sshkey_verify(const struct sshkey *key,
     const u_char *data, size_t dlen, const char *alg, u_int compat,
     struct sshkey_sig_details **detailsp)
 {
+       const struct sshkey_impl *impl;
+
        if (detailsp != NULL)
                *detailsp = NULL;
        if (siglen == 0 || dlen > SSH_KEY_MAX_SIGN_DATA_SIZE)
                return SSH_ERR_INVALID_ARGUMENT;
-       switch (key->type) {
-#ifdef WITH_OPENSSL
-       case KEY_DSA_CERT:
-       case KEY_DSA:
-               return ssh_dss_verify(key, sig, siglen, data, dlen, compat);
-# ifdef OPENSSL_HAS_ECC
-       case KEY_ECDSA_CERT:
-       case KEY_ECDSA:
-               return ssh_ecdsa_verify(key, sig, siglen, data, dlen, compat);
-       case KEY_ECDSA_SK_CERT:
-       case KEY_ECDSA_SK:
-               return ssh_ecdsa_sk_verify(key, sig, siglen, data, dlen,
-                   compat, detailsp);
-# endif /* OPENSSL_HAS_ECC */
-       case KEY_RSA_CERT:
-       case KEY_RSA:
-               return ssh_rsa_verify(key, sig, siglen, data, dlen, alg);
-#endif /* WITH_OPENSSL */
-       case KEY_ED25519:
-       case KEY_ED25519_CERT:
-               return ssh_ed25519_verify(key, sig, siglen, data, dlen, compat);
-       case KEY_ED25519_SK:
-       case KEY_ED25519_SK_CERT:
-               return ssh_ed25519_sk_verify(key, sig, siglen, data, dlen,
-                   compat, detailsp);
-#ifdef WITH_XMSS
-       case KEY_XMSS:
-       case KEY_XMSS_CERT:
-               return ssh_xmss_verify(key, sig, siglen, data, dlen, compat);
-#endif /* WITH_XMSS */
-       default:
+       if ((impl = sshkey_impl_from_key(key)) == NULL)
                return SSH_ERR_KEY_TYPE_UNKNOWN;
-       }
+       return impl->funcs->verify(key, sig, siglen, data, dlen,
+           alg, compat, detailsp);
 }
 
 /* Convert a plain key to their _CERT equivalent */
index 5d9e9df3aa67d6937adcab8221a709f5a60ec0af..d740c20bd1d184b58a06710d516fee75899e5f4c 100644 (file)
--- a/sshkey.h
+++ b/sshkey.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshkey.h,v 1.58 2022/10/28 00:41:52 djm Exp $ */
+/* $OpenBSD: sshkey.h,v 1.59 2022/10/28 00:43:08 djm Exp $ */
 
 /*
  * Copyright (c) 2000, 2001 Markus Friedl.  All rights reserved.
@@ -175,6 +175,12 @@ struct sshkey_impl_funcs {
            struct sshkey *);
        int (*generate)(struct sshkey *, int);  /* optional */
        int (*copy_public)(const struct sshkey *, struct sshkey *);
+       int (*sign)(struct sshkey *, u_char **, size_t *,
+           const u_char *, size_t, const char *,
+           const char *, const char *, u_int); /* optional */
+       int (*verify)(const struct sshkey *, const u_char *, size_t,
+           const u_char *, size_t, const char *, u_int,
+           struct sshkey_sig_details **);
 };
 
 struct sshkey_impl {
@@ -321,41 +327,6 @@ int        sshkey_deserialize_sk(struct sshbuf *b, struct sshkey *key);
 #ifdef WITH_OPENSSL
 int    check_rsa_length(const RSA *rsa); /* XXX remove */
 #endif
-
-int ssh_rsa_sign(const struct sshkey *key,
-    u_char **sigp, size_t *lenp, const u_char *data, size_t datalen,
-    const char *ident);
-int ssh_rsa_verify(const struct sshkey *key,
-    const u_char *sig, size_t siglen, const u_char *data, size_t datalen,
-    const char *alg);
-int ssh_dss_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
-    const u_char *data, size_t datalen, u_int compat);
-int ssh_dss_verify(const struct sshkey *key,
-    const u_char *signature, size_t signaturelen,
-    const u_char *data, size_t datalen, u_int compat);
-int ssh_ecdsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
-    const u_char *data, size_t datalen, u_int compat);
-int ssh_ecdsa_verify(const struct sshkey *key,
-    const u_char *signature, size_t signaturelen,
-    const u_char *data, size_t datalen, u_int compat);
-int ssh_ecdsa_sk_verify(const struct sshkey *key,
-    const u_char *signature, size_t signaturelen,
-    const u_char *data, size_t datalen, u_int compat,
-    struct sshkey_sig_details **detailsp);
-int ssh_ed25519_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
-    const u_char *data, size_t datalen, u_int compat);
-int ssh_ed25519_verify(const struct sshkey *key,
-    const u_char *signature, size_t signaturelen,
-    const u_char *data, size_t datalen, u_int compat);
-int ssh_ed25519_sk_verify(const struct sshkey *key,
-    const u_char *signature, size_t signaturelen,
-    const u_char *data, size_t datalen, u_int compat,
-    struct sshkey_sig_details **detailsp);
-int ssh_xmss_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
-    const u_char *data, size_t datalen, u_int compat);
-int ssh_xmss_verify(const struct sshkey *key,
-    const u_char *signature, size_t signaturelen,
-    const u_char *data, size_t datalen, u_int compat);
 #endif
 
 #if !defined(WITH_OPENSSL)