refactor sshkey_sign() and sshkey_verify()
authordjm <djm@openbsd.org>
Fri, 28 Oct 2022 00:43:08 +0000 (00:43 +0000)
committerdjm <djm@openbsd.org>
Fri, 28 Oct 2022 00:43:08 +0000 (00:43 +0000)
feedback/ok markus@

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

index 233b6fc..5c3ecd2 100644 (file)
@@ -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.
  *
@@ -209,9 +209,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;
@@ -277,28 +279,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) {
@@ -320,7 +323,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;
@@ -331,18 +334,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;
@@ -356,7 +359,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);
@@ -375,6 +378,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 5f26395..0858003 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.
@@ -179,13 +179,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];
@@ -203,14 +203,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;
@@ -272,11 +272,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;
        }
@@ -288,11 +288,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 */
@@ -326,7 +326,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;
@@ -355,7 +355,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);
@@ -371,6 +371,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 709870e..df680de 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.
@@ -180,15 +180,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;
 
@@ -202,13 +204,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;
        }
@@ -217,7 +219,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;
@@ -239,36 +241,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) {
@@ -290,11 +293,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;
        }
@@ -304,11 +307,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;
@@ -324,7 +327,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);
@@ -341,6 +344,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 777d033..92ac429 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.
  *
@@ -92,10 +92,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;
@@ -120,10 +120,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 ||
@@ -154,7 +154,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;
@@ -228,6 +228,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 d0dcea0..7d1e8b2 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>
  *
@@ -101,9 +101,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;
@@ -158,10 +160,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;
@@ -174,11 +177,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)
@@ -195,23 +198,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;
        }
@@ -238,6 +241,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 e979541..9652513 100644 (file)
@@ -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>
  *
@@ -321,14 +321,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;
 
@@ -337,10 +339,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;
@@ -353,7 +355,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)
@@ -364,7 +366,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;
        }
@@ -402,15 +404,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;
 
@@ -471,15 +474,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);
@@ -617,6 +620,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 18fee08..ebde4c5 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.
@@ -135,9 +135,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;
@@ -209,10 +211,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;
@@ -226,14 +229,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)
@@ -250,23 +253,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;
        }
@@ -292,6 +295,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 bc5e258..34bb7d2 100644 (file)
@@ -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.
@@ -2009,6 +2009,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;
@@ -2016,43 +2017,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;
-       case KEY_ECDSA_CERT:
-       case KEY_ECDSA:
-               r = ssh_ecdsa_sign(key, sigp, lenp, data, datalen, compat);
-               break;
-       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;
@@ -2069,41 +2047,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);
-       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);
-       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 9feefc1..f8eeed5 100644 (file)
@@ -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.
@@ -169,6 +169,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 {
@@ -315,41 +321,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
 
 #ifndef WITH_OPENSSL