From c5c174fa0f01100d43ec027c8a3574d6df9cb319 Mon Sep 17 00:00:00 2001 From: djm Date: Fri, 28 Oct 2022 00:43:08 +0000 Subject: [PATCH] refactor sshkey_sign() and sshkey_verify() feedback/ok markus@ --- usr.bin/ssh/ssh-dss.c | 39 +++++++++-------- usr.bin/ssh/ssh-ecdsa-sk.c | 28 +++++++------ usr.bin/ssh/ssh-ecdsa.c | 53 ++++++++++++----------- usr.bin/ssh/ssh-ed25519-sk.c | 16 +++---- usr.bin/ssh/ssh-ed25519.c | 33 ++++++++------- usr.bin/ssh/ssh-rsa.c | 37 +++++++++------- usr.bin/ssh/ssh-xmss.c | 33 ++++++++------- usr.bin/ssh/sshkey.c | 81 ++++++++---------------------------- usr.bin/ssh/sshkey.h | 43 ++++--------------- 9 files changed, 158 insertions(+), 205 deletions(-) diff --git a/usr.bin/ssh/ssh-dss.c b/usr.bin/ssh/ssh-dss.c index 233b6fca965..5c3ecd2ac85 100644 --- a/usr.bin/ssh/ssh-dss.c +++ b/usr.bin/ssh/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. * @@ -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 = { diff --git a/usr.bin/ssh/ssh-ecdsa-sk.c b/usr.bin/ssh/ssh-ecdsa-sk.c index 5f263957c27..08580037f31 100644 --- a/usr.bin/ssh/ssh-ecdsa-sk.c +++ b/usr.bin/ssh/ssh-ecdsa-sk.c @@ -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 = { diff --git a/usr.bin/ssh/ssh-ecdsa.c b/usr.bin/ssh/ssh-ecdsa.c index 709870e8c69..df680de8a40 100644 --- a/usr.bin/ssh/ssh-ecdsa.c +++ b/usr.bin/ssh/ssh-ecdsa.c @@ -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 = { diff --git a/usr.bin/ssh/ssh-ed25519-sk.c b/usr.bin/ssh/ssh-ed25519-sk.c index 777d033fad6..92ac4295269 100644 --- a/usr.bin/ssh/ssh-ed25519-sk.c +++ b/usr.bin/ssh/ssh-ed25519-sk.c @@ -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 = { diff --git a/usr.bin/ssh/ssh-ed25519.c b/usr.bin/ssh/ssh-ed25519.c index d0dcea02058..7d1e8b2ae14 100644 --- a/usr.bin/ssh/ssh-ed25519.c +++ b/usr.bin/ssh/ssh-ed25519.c @@ -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 * @@ -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 = { diff --git a/usr.bin/ssh/ssh-rsa.c b/usr.bin/ssh/ssh-rsa.c index e979541a77a..96525133875 100644 --- a/usr.bin/ssh/ssh-rsa.c +++ b/usr.bin/ssh/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 * @@ -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 = { diff --git a/usr.bin/ssh/ssh-xmss.c b/usr.bin/ssh/ssh-xmss.c index 18fee086be0..ebde4c5d450 100644 --- a/usr.bin/ssh/ssh-xmss.c +++ b/usr.bin/ssh/ssh-xmss.c @@ -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 = { diff --git a/usr.bin/ssh/sshkey.c b/usr.bin/ssh/sshkey.c index bc5e258bf24..34bb7d2ee99 100644 --- a/usr.bin/ssh/sshkey.c +++ b/usr.bin/ssh/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. @@ -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 */ diff --git a/usr.bin/ssh/sshkey.h b/usr.bin/ssh/sshkey.h index 9feefc1d2b3..f8eeed56973 100644 --- a/usr.bin/ssh/sshkey.h +++ b/usr.bin/ssh/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. @@ -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 -- 2.20.1