upstream: refactor sshkey_sign() and sshkey_verify()

feedback/ok markus@

OpenBSD-Commit-ID: 368e662c128c99d05cc043b1308d2b6c71a4d3cc
This commit is contained in:
djm@openbsd.org 2022-10-28 00:43:08 +00:00 committed by Damien Miller
parent a1deb6cdbb
commit 3fbc58bb24
No known key found for this signature in database
9 changed files with 158 additions and 209 deletions

View 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.
*
@ -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 = {

View 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 = {

View 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 = {

View 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 = {

View 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 = {

View 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>
*
@ -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 = {

View 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 = {

View 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.
@ -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 */

View 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.
@ -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)