diff options
author | Alistair Delva <adelva@google.com> | 2020-08-20 16:14:23 -0700 |
---|---|---|
committer | Alistair Delva <adelva@google.com> | 2020-08-20 16:53:18 -0700 |
commit | d9da10d147d633fdb6ec65e17ff4b8447419d83e (patch) | |
tree | 8f93e8fdc2907f141e0924910bfec26669819f0b /ssh-dss.c | |
parent | 22246b08952d746a7cc5a292570636cf4277598f (diff) | |
parent | ecb2c02d994b3e21994f31a70ff911667c262f1f (diff) |
Merge upstream-master into master
Commit ecb2c02d994b3e21994f31a70ff911667c262f1f upstream
This nearly (but not quite) corresponds to V_8_3_P1; subsequent
cherry-picks will correct this.
Bug: 162492243
Change-Id: I3c079d86435b7c25aefff4538dc89a3002b1e25b
Diffstat (limited to 'ssh-dss.c')
-rw-r--r-- | ssh-dss.c | 135 |
1 files changed, 60 insertions, 75 deletions
@@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-dss.c,v 1.32 2014/06/24 01:13:21 djm Exp $ */ +/* $OpenBSD: ssh-dss.c,v 1.39 2020/02/26 13:40:09 jsg Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -43,6 +43,8 @@ #define SSHKEY_INTERNAL #include "sshkey.h" +#include "openbsd-compat/openssl-compat.h" + #define INTBLOB_LEN 20 #define SIGBLOB_LEN (2*INTBLOB_LEN) @@ -51,6 +53,7 @@ ssh_dss_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, const u_char *data, size_t datalen, u_int compat) { DSA_SIG *sig = NULL; + const BIGNUM *sig_r, *sig_s; u_char digest[SSH_DIGEST_MAX_LENGTH], sigblob[SIGBLOB_LEN]; size_t rlen, slen, len, dlen = ssh_digest_bytes(SSH_DIGEST_SHA1); struct sshbuf *b = NULL; @@ -76,54 +79,40 @@ ssh_dss_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, goto out; } - rlen = BN_num_bytes(sig->r); - slen = BN_num_bytes(sig->s); + DSA_SIG_get0(sig, &sig_r, &sig_s); + rlen = BN_num_bytes(sig_r); + slen = BN_num_bytes(sig_s); if (rlen > INTBLOB_LEN || slen > INTBLOB_LEN) { ret = SSH_ERR_INTERNAL_ERROR; goto out; } explicit_bzero(sigblob, SIGBLOB_LEN); - BN_bn2bin(sig->r, sigblob + SIGBLOB_LEN - INTBLOB_LEN - rlen); - BN_bn2bin(sig->s, sigblob + SIGBLOB_LEN - slen); - - if (compat & SSH_BUG_SIGBLOB) { - if (sigp != NULL) { - if ((*sigp = malloc(SIGBLOB_LEN)) == NULL) { - ret = SSH_ERR_ALLOC_FAIL; - goto out; - } - memcpy(*sigp, sigblob, SIGBLOB_LEN); - } - if (lenp != NULL) - *lenp = SIGBLOB_LEN; - ret = 0; - } else { - /* ietf-drafts */ - if ((b = sshbuf_new()) == NULL) { + BN_bn2bin(sig_r, sigblob + SIGBLOB_LEN - INTBLOB_LEN - rlen); + BN_bn2bin(sig_s, sigblob + SIGBLOB_LEN - slen); + + if ((b = sshbuf_new()) == NULL) { + ret = SSH_ERR_ALLOC_FAIL; + goto out; + } + if ((ret = sshbuf_put_cstring(b, "ssh-dss")) != 0 || + (ret = sshbuf_put_string(b, sigblob, SIGBLOB_LEN)) != 0) + goto out; + + len = sshbuf_len(b); + if (sigp != NULL) { + if ((*sigp = malloc(len)) == NULL) { ret = SSH_ERR_ALLOC_FAIL; goto out; } - if ((ret = sshbuf_put_cstring(b, "ssh-dss")) != 0 || - (ret = sshbuf_put_string(b, sigblob, SIGBLOB_LEN)) != 0) - goto out; - len = sshbuf_len(b); - if (sigp != NULL) { - if ((*sigp = malloc(len)) == NULL) { - ret = SSH_ERR_ALLOC_FAIL; - goto out; - } - memcpy(*sigp, sshbuf_ptr(b), len); - } - if (lenp != NULL) - *lenp = len; - ret = 0; + memcpy(*sigp, sshbuf_ptr(b), len); } + if (lenp != NULL) + *lenp = len; + ret = 0; out: explicit_bzero(digest, sizeof(digest)); - if (sig != NULL) - DSA_SIG_free(sig); - if (b != NULL) - sshbuf_free(b); + DSA_SIG_free(sig); + sshbuf_free(b); return ret; } @@ -133,6 +122,7 @@ ssh_dss_verify(const struct sshkey *key, const u_char *data, size_t datalen, u_int compat) { DSA_SIG *sig = 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); int ret = SSH_ERR_INTERNAL_ERROR; @@ -140,34 +130,27 @@ ssh_dss_verify(const struct sshkey *key, char *ktype = NULL; if (key == NULL || key->dsa == NULL || - sshkey_type_plain(key->type) != KEY_DSA) + sshkey_type_plain(key->type) != KEY_DSA || + signature == NULL || signaturelen == 0) return SSH_ERR_INVALID_ARGUMENT; if (dlen == 0) return SSH_ERR_INTERNAL_ERROR; /* fetch signature */ - if (compat & SSH_BUG_SIGBLOB) { - if ((sigblob = malloc(signaturelen)) == NULL) - return SSH_ERR_ALLOC_FAIL; - memcpy(sigblob, signature, signaturelen); - len = signaturelen; - } else { - /* ietf-drafts */ - if ((b = sshbuf_from(signature, signaturelen)) == NULL) - return SSH_ERR_ALLOC_FAIL; - if (sshbuf_get_cstring(b, &ktype, NULL) != 0 || - sshbuf_get_string(b, &sigblob, &len) != 0) { - ret = SSH_ERR_INVALID_FORMAT; - goto out; - } - if (strcmp("ssh-dss", ktype) != 0) { - ret = SSH_ERR_KEY_TYPE_MISMATCH; - goto out; - } - if (sshbuf_len(b) != 0) { - ret = SSH_ERR_UNEXPECTED_TRAILING_DATA; - goto out; - } + if ((b = sshbuf_from(signature, signaturelen)) == NULL) + return SSH_ERR_ALLOC_FAIL; + if (sshbuf_get_cstring(b, &ktype, NULL) != 0 || + sshbuf_get_string(b, &sigblob, &len) != 0) { + ret = SSH_ERR_INVALID_FORMAT; + goto out; + } + if (strcmp("ssh-dss", ktype) != 0) { + ret = SSH_ERR_KEY_TYPE_MISMATCH; + goto out; + } + if (sshbuf_len(b) != 0) { + ret = SSH_ERR_UNEXPECTED_TRAILING_DATA; + goto out; } if (len != SIGBLOB_LEN) { @@ -177,16 +160,21 @@ ssh_dss_verify(const struct sshkey *key, /* parse signature */ if ((sig = DSA_SIG_new()) == NULL || - (sig->r = BN_new()) == NULL || - (sig->s = BN_new()) == NULL) { + (sig_r = BN_new()) == NULL || + (sig_s = BN_new()) == NULL) { ret = SSH_ERR_ALLOC_FAIL; goto out; } - if ((BN_bin2bn(sigblob, INTBLOB_LEN, sig->r) == NULL) || - (BN_bin2bn(sigblob+ INTBLOB_LEN, INTBLOB_LEN, sig->s) == NULL)) { + if ((BN_bin2bn(sigblob, INTBLOB_LEN, sig_r) == NULL) || + (BN_bin2bn(sigblob + INTBLOB_LEN, INTBLOB_LEN, sig_s) == NULL)) { ret = SSH_ERR_LIBCRYPTO_ERROR; goto out; } + if (!DSA_SIG_set0(sig, 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, @@ -207,16 +195,13 @@ ssh_dss_verify(const struct sshkey *key, out: explicit_bzero(digest, sizeof(digest)); - if (sig != NULL) - DSA_SIG_free(sig); - if (b != NULL) - sshbuf_free(b); - if (ktype != NULL) - free(ktype); - if (sigblob != NULL) { - explicit_bzero(sigblob, len); - free(sigblob); - } + DSA_SIG_free(sig); + BN_clear_free(sig_r); + BN_clear_free(sig_s); + sshbuf_free(b); + free(ktype); + if (sigblob != NULL) + freezero(sigblob, len); return ret; } #endif /* WITH_OPENSSL */ |