summaryrefslogtreecommitdiffstats
path: root/ssh-ecdsa-sk.c
diff options
context:
space:
mode:
Diffstat (limited to 'ssh-ecdsa-sk.c')
-rw-r--r--ssh-ecdsa-sk.c49
1 files changed, 37 insertions, 12 deletions
diff --git a/ssh-ecdsa-sk.c b/ssh-ecdsa-sk.c
index 5dcd3c1..27ddf90 100644
--- a/ssh-ecdsa-sk.c
+++ b/ssh-ecdsa-sk.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-ecdsa-sk.c,v 1.18 2023/03/08 04:43:12 guenther Exp $ */
+/* $OpenBSD: ssh-ecdsa-sk.c,v 1.19 2024/08/15 00:51:51 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
* Copyright (c) 2010 Damien Miller. All rights reserved.
@@ -237,11 +237,13 @@ ssh_ecdsa_sk_verify(const struct sshkey *key,
struct sshkey_sig_details **detailsp)
{
ECDSA_SIG *esig = NULL;
+ EVP_MD_CTX *md_ctx = NULL;
BIGNUM *sig_r = NULL, *sig_s = NULL;
u_char sig_flags;
- u_char msghash[32], apphash[32], sighash[32];
+ u_char msghash[32], apphash[32];
u_int sig_counter;
- int is_webauthn = 0, ret = SSH_ERR_INTERNAL_ERROR;
+ u_char *sigb = NULL, *cp;
+ int is_webauthn = 0, ret = SSH_ERR_INTERNAL_ERROR, len = 0;
struct sshbuf *b = NULL, *sigbuf = NULL, *original_signed = NULL;
struct sshbuf *webauthn_wrapper = NULL, *webauthn_exts = NULL;
char *ktype = NULL, *webauthn_origin = NULL;
@@ -252,7 +254,7 @@ ssh_ecdsa_sk_verify(const struct sshkey *key,
if (detailsp != NULL)
*detailsp = NULL;
- if (key == NULL || key->ecdsa == NULL ||
+ if (key == NULL || key->pkey == NULL ||
sshkey_type_plain(key->type) != KEY_ECDSA_SK ||
sig == NULL || siglen == 0)
return SSH_ERR_INVALID_ARGUMENT;
@@ -363,21 +365,43 @@ ssh_ecdsa_sk_verify(const struct sshkey *key,
(ret = sshbuf_putb(original_signed, webauthn_exts)) != 0 ||
(ret = sshbuf_put(original_signed, msghash, sizeof(msghash))) != 0)
goto out;
- /* Signature is over H(original_signed) */
- if ((ret = ssh_digest_buffer(SSH_DIGEST_SHA256, original_signed,
- sighash, sizeof(sighash))) != 0)
- goto out;
details->sk_counter = sig_counter;
details->sk_flags = sig_flags;
#ifdef DEBUG_SK
fprintf(stderr, "%s: signed buf:\n", __func__);
sshbuf_dump(original_signed, stderr);
- fprintf(stderr, "%s: signed hash:\n", __func__);
- sshbuf_dump_data(sighash, sizeof(sighash), stderr);
#endif
+ if ((md_ctx = EVP_MD_CTX_new()) == NULL) {
+ ret = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ if ((len = i2d_ECDSA_SIG(esig, NULL)) <= 0) {
+ len = 0;
+ ret = SSH_ERR_LIBCRYPTO_ERROR;
+ goto out;
+ }
+ if ((sigb = calloc(1, len)) == NULL) {
+ ret = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ cp = sigb; /* ASN1_item_i2d increments the pointer past the object */
+ if (i2d_ECDSA_SIG(esig, &cp) != len) {
+ ret = SSH_ERR_LIBCRYPTO_ERROR;
+ goto out;
+ }
+#ifdef DEBUG_SK
+ fprintf(stderr, "%s: signed hash:\n", __func__);
+ sshbuf_dump_data(sigb, len, stderr);
+#endif
/* Verify it */
- switch (ECDSA_do_verify(sighash, sizeof(sighash), esig, key->ecdsa)) {
+ if (EVP_DigestVerifyInit(md_ctx, NULL, EVP_sha256(), NULL,
+ key->pkey) != 1) {
+ ret = SSH_ERR_LIBCRYPTO_ERROR;
+ goto out;
+ }
+ switch (EVP_DigestVerify(md_ctx, sigb, len,
+ sshbuf_ptr(original_signed), sshbuf_len(original_signed))) {
case 1:
ret = 0;
break;
@@ -397,7 +421,6 @@ ssh_ecdsa_sk_verify(const struct sshkey *key,
explicit_bzero(&sig_flags, sizeof(sig_flags));
explicit_bzero(&sig_counter, sizeof(sig_counter));
explicit_bzero(msghash, sizeof(msghash));
- explicit_bzero(sighash, sizeof(msghash));
explicit_bzero(apphash, sizeof(apphash));
sshkey_sig_details_free(details);
sshbuf_free(webauthn_wrapper);
@@ -410,6 +433,8 @@ ssh_ecdsa_sk_verify(const struct sshkey *key,
BN_clear_free(sig_r);
BN_clear_free(sig_s);
free(ktype);
+ freezero(sigb, len);
+ EVP_MD_CTX_free(md_ctx);
return ret;
}