summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ssh-dss.c39
-rw-r--r--ssh-ecdsa-sk.c28
-rw-r--r--ssh-ecdsa.c53
-rw-r--r--ssh-ed25519-sk.c16
-rw-r--r--ssh-ed25519.c33
-rw-r--r--ssh-rsa.c37
-rw-r--r--ssh-xmss.c33
-rw-r--r--sshkey.c85
-rw-r--r--sshkey.h43
9 files changed, 158 insertions, 209 deletions
diff --git a/ssh-dss.c b/ssh-dss.c
index baf3cfb1..58c66c7d 100644
--- a/ssh-dss.c
+++ b/ssh-dss.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-dss.c,v 1.45 2022/10/28 00:41:52 djm Exp $ */
+/* $OpenBSD: ssh-dss.c,v 1.46 2022/10/28 00:43:08 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
@@ -217,9 +217,11 @@ ssh_dss_deserialize_public(const char *ktype, struct sshbuf *b,
return ret;
}
-int
-ssh_dss_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
- const u_char *data, size_t datalen, u_int compat)
+static int
+ssh_dss_sign(struct sshkey *key,
+ u_char **sigp, size_t *lenp,
+ const u_char *data, size_t datalen,
+ const char *alg, const char *sk_provider, const char *sk_pin, u_int compat)
{
DSA_SIG *sig = NULL;
const BIGNUM *sig_r, *sig_s;
@@ -285,28 +287,29 @@ ssh_dss_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
return ret;
}
-int
+static int
ssh_dss_verify(const struct sshkey *key,
- const u_char *signature, size_t signaturelen,
- const u_char *data, size_t datalen, u_int compat)
+ const u_char *sig, size_t siglen,
+ const u_char *data, size_t dlen, const char *alg, u_int compat,
+ struct sshkey_sig_details **detailsp)
{
- DSA_SIG *sig = NULL;
+ DSA_SIG *dsig = NULL;
BIGNUM *sig_r = NULL, *sig_s = NULL;
u_char digest[SSH_DIGEST_MAX_LENGTH], *sigblob = NULL;
- size_t len, dlen = ssh_digest_bytes(SSH_DIGEST_SHA1);
+ size_t len, hlen = ssh_digest_bytes(SSH_DIGEST_SHA1);
int ret = SSH_ERR_INTERNAL_ERROR;
struct sshbuf *b = NULL;
char *ktype = NULL;
if (key == NULL || key->dsa == NULL ||
sshkey_type_plain(key->type) != KEY_DSA ||
- signature == NULL || signaturelen == 0)
+ sig == NULL || siglen == 0)
return SSH_ERR_INVALID_ARGUMENT;
- if (dlen == 0)
+ if (hlen == 0)
return SSH_ERR_INTERNAL_ERROR;
/* fetch signature */
- if ((b = sshbuf_from(signature, signaturelen)) == NULL)
+ if ((b = sshbuf_from(sig, siglen)) == NULL)
return SSH_ERR_ALLOC_FAIL;
if (sshbuf_get_cstring(b, &ktype, NULL) != 0 ||
sshbuf_get_string(b, &sigblob, &len) != 0) {
@@ -328,7 +331,7 @@ ssh_dss_verify(const struct sshkey *key,
}
/* parse signature */
- if ((sig = DSA_SIG_new()) == NULL ||
+ if ((dsig = DSA_SIG_new()) == NULL ||
(sig_r = BN_new()) == NULL ||
(sig_s = BN_new()) == NULL) {
ret = SSH_ERR_ALLOC_FAIL;
@@ -339,18 +342,18 @@ ssh_dss_verify(const struct sshkey *key,
ret = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
- if (!DSA_SIG_set0(sig, sig_r, sig_s)) {
+ if (!DSA_SIG_set0(dsig, sig_r, sig_s)) {
ret = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
sig_r = sig_s = NULL; /* transferred */
/* sha1 the data */
- if ((ret = ssh_digest_memory(SSH_DIGEST_SHA1, data, datalen,
+ if ((ret = ssh_digest_memory(SSH_DIGEST_SHA1, data, dlen,
digest, sizeof(digest))) != 0)
goto out;
- switch (DSA_do_verify(digest, dlen, sig, key->dsa)) {
+ switch (DSA_do_verify(digest, hlen, dsig, key->dsa)) {
case 1:
ret = 0;
break;
@@ -364,7 +367,7 @@ ssh_dss_verify(const struct sshkey *key,
out:
explicit_bzero(digest, sizeof(digest));
- DSA_SIG_free(sig);
+ DSA_SIG_free(dsig);
BN_clear_free(sig_r);
BN_clear_free(sig_s);
sshbuf_free(b);
@@ -383,6 +386,8 @@ static const struct sshkey_impl_funcs sshkey_dss_funcs = {
/* .ssh_deserialize_public = */ ssh_dss_deserialize_public,
/* .generate = */ ssh_dss_generate,
/* .copy_public = */ ssh_dss_copy_public,
+ /* .sign = */ ssh_dss_sign,
+ /* .verify = */ ssh_dss_verify,
};
const struct sshkey_impl sshkey_dss_impl = {
diff --git a/ssh-ecdsa-sk.c b/ssh-ecdsa-sk.c
index cb8bcef1..6e08d869 100644
--- a/ssh-ecdsa-sk.c
+++ b/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.
@@ -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 = {
diff --git a/ssh-ecdsa.c b/ssh-ecdsa.c
index e584cb79..a7b1b7b2 100644
--- a/ssh-ecdsa.c
+++ b/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.
@@ -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 = {
diff --git a/ssh-ed25519-sk.c b/ssh-ed25519-sk.c
index eba835d9..1eef5424 100644
--- a/ssh-ed25519-sk.c
+++ b/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.
*
@@ -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 = {
diff --git a/ssh-ed25519.c b/ssh-ed25519.c
index 1556641d..8e6fabed 100644
--- a/ssh-ed25519.c
+++ b/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 <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 = {
diff --git a/ssh-rsa.c b/ssh-rsa.c
index cbea0d29..07620a8d 100644
--- a/ssh-rsa.c
+++ b/ssh-rsa.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-rsa.c,v 1.74 2022/10/28 00:41:52 djm Exp $ */
+/* $OpenBSD: ssh-rsa.c,v 1.75 2022/10/28 00:43:08 djm Exp $ */
/*
* Copyright (c) 2000, 2003 Markus Friedl <markus@openbsd.org>
*
@@ -328,14 +328,16 @@ ssh_rsa_complete_crt_parameters(struct sshkey *key, const BIGNUM *iqmp)
}
/* RSASSA-PKCS1-v1_5 (PKCS #1 v2.0 signature) with SHA1 */
-int
-ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
- const u_char *data, size_t datalen, const char *alg_ident)
+static int
+ssh_rsa_sign(struct sshkey *key,
+ u_char **sigp, size_t *lenp,
+ const u_char *data, size_t datalen,
+ const char *alg, const char *sk_provider, const char *sk_pin, u_int compat)
{
const BIGNUM *rsa_n;
u_char digest[SSH_DIGEST_MAX_LENGTH], *sig = NULL;
size_t slen = 0;
- u_int dlen, len;
+ u_int hlen, len;
int nid, hash_alg, ret = SSH_ERR_INTERNAL_ERROR;
struct sshbuf *b = NULL;
@@ -344,10 +346,10 @@ ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
if (sigp != NULL)
*sigp = NULL;
- if (alg_ident == NULL || strlen(alg_ident) == 0)
+ if (alg == NULL || strlen(alg) == 0)
hash_alg = SSH_DIGEST_SHA1;
else
- hash_alg = rsa_hash_id_from_keyname(alg_ident);
+ hash_alg = rsa_hash_id_from_keyname(alg);
if (key == NULL || key->rsa == NULL || hash_alg == -1 ||
sshkey_type_plain(key->type) != KEY_RSA)
return SSH_ERR_INVALID_ARGUMENT;
@@ -360,7 +362,7 @@ ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
/* hash the data */
nid = rsa_hash_alg_nid(hash_alg);
- if ((dlen = ssh_digest_bytes(hash_alg)) == 0)
+ if ((hlen = ssh_digest_bytes(hash_alg)) == 0)
return SSH_ERR_INTERNAL_ERROR;
if ((ret = ssh_digest_memory(hash_alg, data, datalen,
digest, sizeof(digest))) != 0)
@@ -371,7 +373,7 @@ ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
goto out;
}
- if (RSA_sign(nid, digest, dlen, sig, &len, key->rsa) != 1) {
+ if (RSA_sign(nid, digest, hlen, sig, &len, key->rsa) != 1) {
ret = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
@@ -409,15 +411,16 @@ ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
return ret;
}
-int
+static int
ssh_rsa_verify(const struct sshkey *key,
- const u_char *sig, size_t siglen, const u_char *data, size_t datalen,
- const char *alg)
+ const u_char *sig, size_t siglen,
+ const u_char *data, size_t dlen, const char *alg, u_int compat,
+ struct sshkey_sig_details **detailsp)
{
const BIGNUM *rsa_n;
char *sigtype = NULL;
int hash_alg, want_alg, ret = SSH_ERR_INTERNAL_ERROR;
- size_t len = 0, diff, modlen, dlen;
+ size_t len = 0, diff, modlen, hlen;
struct sshbuf *b = NULL;
u_char digest[SSH_DIGEST_MAX_LENGTH], *osigblob, *sigblob = NULL;
@@ -478,15 +481,15 @@ ssh_rsa_verify(const struct sshkey *key,
explicit_bzero(sigblob, diff);
len = modlen;
}
- if ((dlen = ssh_digest_bytes(hash_alg)) == 0) {
+ if ((hlen = ssh_digest_bytes(hash_alg)) == 0) {
ret = SSH_ERR_INTERNAL_ERROR;
goto out;
}
- if ((ret = ssh_digest_memory(hash_alg, data, datalen,
+ if ((ret = ssh_digest_memory(hash_alg, data, dlen,
digest, sizeof(digest))) != 0)
goto out;
- ret = openssh_RSA_verify(hash_alg, digest, dlen, sigblob, len,
+ ret = openssh_RSA_verify(hash_alg, digest, hlen, sigblob, len,
key->rsa);
out:
freezero(sigblob, len);
@@ -624,6 +627,8 @@ static const struct sshkey_impl_funcs sshkey_rsa_funcs = {
/* .ssh_deserialize_public = */ ssh_rsa_deserialize_public,
/* .generate = */ ssh_rsa_generate,
/* .copy_public = */ ssh_rsa_copy_public,
+ /* .sign = */ ssh_rsa_sign,
+ /* .verify = */ ssh_rsa_verify,
};
const struct sshkey_impl sshkey_rsa_impl = {
diff --git a/ssh-xmss.c b/ssh-xmss.c
index 039436b4..2193aaab 100644
--- a/ssh-xmss.c
+++ b/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.
@@ -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 = {
diff --git a/sshkey.c b/sshkey.c
index 69b993b0..00da6bfb 100644
--- a/sshkey.c
+++ b/sshkey.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshkey.c,v 1.129 2022/10/28 00:41:52 djm Exp $ */
+/* $OpenBSD: sshkey.c,v 1.130 2022/10/28 00:43:08 djm Exp $ */
/*
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
* Copyright (c) 2008 Alexander von Gernler. All rights reserved.
@@ -2042,6 +2042,7 @@ sshkey_sign(struct sshkey *key,
{
int was_shielded = sshkey_is_shielded(key);
int r2, r = SSH_ERR_INTERNAL_ERROR;
+ const struct sshkey_impl *impl;
if (sigp != NULL)
*sigp = NULL;
@@ -2049,45 +2050,20 @@ sshkey_sign(struct sshkey *key,
*lenp = 0;
if (datalen > SSH_KEY_MAX_SIGN_DATA_SIZE)
return SSH_ERR_INVALID_ARGUMENT;
+ if ((impl = sshkey_impl_from_key(key)) == NULL)
+ return SSH_ERR_KEY_TYPE_UNKNOWN;
if ((r = sshkey_unshield_private(key)) != 0)
return r;
- switch (key->type) {
-#ifdef WITH_OPENSSL
- case KEY_DSA_CERT:
- case KEY_DSA:
- r = ssh_dss_sign(key, sigp, lenp, data, datalen, compat);
- break;
-# ifdef OPENSSL_HAS_ECC
- case KEY_ECDSA_CERT:
- case KEY_ECDSA:
- r = ssh_ecdsa_sign(key, sigp, lenp, data, datalen, compat);
- break;
-# endif /* OPENSSL_HAS_ECC */
- case KEY_RSA_CERT:
- case KEY_RSA:
- r = ssh_rsa_sign(key, sigp, lenp, data, datalen, alg);
- break;
-#endif /* WITH_OPENSSL */
- case KEY_ED25519:
- case KEY_ED25519_CERT:
- r = ssh_ed25519_sign(key, sigp, lenp, data, datalen, compat);
- break;
- case KEY_ED25519_SK:
- case KEY_ED25519_SK_CERT:
- case KEY_ECDSA_SK_CERT:
- case KEY_ECDSA_SK:
+ if (sshkey_is_sk(key)) {
r = sshsk_sign(sk_provider, key, sigp, lenp, data,
datalen, compat, sk_pin);
- break;
-#ifdef WITH_XMSS
- case KEY_XMSS:
- case KEY_XMSS_CERT:
- r = ssh_xmss_sign(key, sigp, lenp, data, datalen, compat);
- break;
-#endif /* WITH_XMSS */
- default:
- r = SSH_ERR_KEY_TYPE_UNKNOWN;
- break;
+ } else {
+ if (impl->funcs->sign == NULL)
+ r = SSH_ERR_SIGN_ALG_UNSUPPORTED;
+ else {
+ r = impl->funcs->sign(key, sigp, lenp, data, datalen,
+ alg, sk_provider, sk_pin, compat);
+ }
}
if (was_shielded && (r2 = sshkey_shield_private(key)) != 0)
return r2;
@@ -2104,43 +2080,16 @@ sshkey_verify(const struct sshkey *key,
const u_char *data, size_t dlen, const char *alg, u_int compat,
struct sshkey_sig_details **detailsp)
{
+ const struct sshkey_impl *impl;
+
if (detailsp != NULL)
*detailsp = NULL;
if (siglen == 0 || dlen > SSH_KEY_MAX_SIGN_DATA_SIZE)
return SSH_ERR_INVALID_ARGUMENT;
- switch (key->type) {
-#ifdef WITH_OPENSSL
- case KEY_DSA_CERT:
- case KEY_DSA:
- return ssh_dss_verify(key, sig, siglen, data, dlen, compat);
-# ifdef OPENSSL_HAS_ECC
- case KEY_ECDSA_CERT:
- case KEY_ECDSA:
- return ssh_ecdsa_verify(key, sig, siglen, data, dlen, compat);
- case KEY_ECDSA_SK_CERT:
- case KEY_ECDSA_SK:
- return ssh_ecdsa_sk_verify(key, sig, siglen, data, dlen,
- compat, detailsp);
-# endif /* OPENSSL_HAS_ECC */
- case KEY_RSA_CERT:
- case KEY_RSA:
- return ssh_rsa_verify(key, sig, siglen, data, dlen, alg);
-#endif /* WITH_OPENSSL */
- case KEY_ED25519:
- case KEY_ED25519_CERT:
- return ssh_ed25519_verify(key, sig, siglen, data, dlen, compat);
- case KEY_ED25519_SK:
- case KEY_ED25519_SK_CERT:
- return ssh_ed25519_sk_verify(key, sig, siglen, data, dlen,
- compat, detailsp);
-#ifdef WITH_XMSS
- case KEY_XMSS:
- case KEY_XMSS_CERT:
- return ssh_xmss_verify(key, sig, siglen, data, dlen, compat);
-#endif /* WITH_XMSS */
- default:
+ if ((impl = sshkey_impl_from_key(key)) == NULL)
return SSH_ERR_KEY_TYPE_UNKNOWN;
- }
+ return impl->funcs->verify(key, sig, siglen, data, dlen,
+ alg, compat, detailsp);
}
/* Convert a plain key to their _CERT equivalent */
diff --git a/sshkey.h b/sshkey.h
index 5d9e9df3..d740c20b 100644
--- a/sshkey.h
+++ b/sshkey.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshkey.h,v 1.58 2022/10/28 00:41:52 djm Exp $ */
+/* $OpenBSD: sshkey.h,v 1.59 2022/10/28 00:43:08 djm Exp $ */
/*
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
@@ -175,6 +175,12 @@ struct sshkey_impl_funcs {
struct sshkey *);
int (*generate)(struct sshkey *, int); /* optional */
int (*copy_public)(const struct sshkey *, struct sshkey *);
+ int (*sign)(struct sshkey *, u_char **, size_t *,
+ const u_char *, size_t, const char *,
+ const char *, const char *, u_int); /* optional */
+ int (*verify)(const struct sshkey *, const u_char *, size_t,
+ const u_char *, size_t, const char *, u_int,
+ struct sshkey_sig_details **);
};
struct sshkey_impl {
@@ -321,41 +327,6 @@ int sshkey_deserialize_sk(struct sshbuf *b, struct sshkey *key);
#ifdef WITH_OPENSSL
int check_rsa_length(const RSA *rsa); /* XXX remove */
#endif
-
-int ssh_rsa_sign(const struct sshkey *key,
- u_char **sigp, size_t *lenp, const u_char *data, size_t datalen,
- const char *ident);
-int ssh_rsa_verify(const struct sshkey *key,
- const u_char *sig, size_t siglen, const u_char *data, size_t datalen,
- const char *alg);
-int ssh_dss_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
- const u_char *data, size_t datalen, u_int compat);
-int ssh_dss_verify(const struct sshkey *key,
- const u_char *signature, size_t signaturelen,
- const u_char *data, size_t datalen, u_int compat);
-int ssh_ecdsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
- const u_char *data, size_t datalen, u_int compat);
-int ssh_ecdsa_verify(const struct sshkey *key,
- const u_char *signature, size_t signaturelen,
- const u_char *data, size_t datalen, u_int compat);
-int ssh_ecdsa_sk_verify(const struct sshkey *key,
- const u_char *signature, size_t signaturelen,
- const u_char *data, size_t datalen, u_int compat,
- struct sshkey_sig_details **detailsp);
-int ssh_ed25519_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
- const u_char *data, size_t datalen, u_int compat);
-int ssh_ed25519_verify(const struct sshkey *key,
- const u_char *signature, size_t signaturelen,
- const u_char *data, size_t datalen, u_int compat);
-int ssh_ed25519_sk_verify(const struct sshkey *key,
- const u_char *signature, size_t signaturelen,
- const u_char *data, size_t datalen, u_int compat,
- struct sshkey_sig_details **detailsp);
-int ssh_xmss_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
- const u_char *data, size_t datalen, u_int compat);
-int ssh_xmss_verify(const struct sshkey *key,
- const u_char *signature, size_t signaturelen,
- const u_char *data, size_t datalen, u_int compat);
#endif
#if !defined(WITH_OPENSSL)