diff options
author | Bernd Edlinger <bernd.edlinger@hotmail.de> | 2024-02-08 22:21:55 +0100 |
---|---|---|
committer | Tomas Mraz <tomas@openssl.org> | 2024-04-02 17:48:11 +0200 |
commit | be4717602dbd387ef4de6ab0a2311881fe31a67a (patch) | |
tree | b37981455bb4dc0807b02e225d9c3a81692d2dde /crypto | |
parent | 996ccb5b1cdc4e041cad871a77126348810ba2f5 (diff) |
Fix handling of NULL sig parameter in ECDSA_sign and similar
The problem is, that it almost works to pass sig=NULL to the
ECDSA_sign, ECDSA_sign_ex and DSA_sign, to compute the necessary
space for the resulting signature.
But since the ECDSA signature is non-deterministic
(except when ECDSA_sign_setup/ECDSA_sign_ex are used)
the resulting length may be different when the API is called again.
This can easily cause random memory corruption.
Several internal APIs had the same issue, but since they are
never called with sig=NULL, it is better to make them return an
error in that case, instead of making the code more complex.
Reviewed-by: Dmitry Belyavskiy <beldmit@gmail.com>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/23529)
(cherry picked from commit 1fa2bf9b1885d2e87524421fea5041d40149cffa)
Diffstat (limited to 'crypto')
-rw-r--r-- | crypto/dsa/dsa_sign.c | 7 | ||||
-rw-r--r-- | crypto/ec/ecdsa_ossl.c | 5 | ||||
-rw-r--r-- | crypto/sm2/sm2_sign.c | 7 |
3 files changed, 17 insertions, 2 deletions
diff --git a/crypto/dsa/dsa_sign.c b/crypto/dsa/dsa_sign.c index b806e7e655..190aca8ad9 100644 --- a/crypto/dsa/dsa_sign.c +++ b/crypto/dsa/dsa_sign.c @@ -157,6 +157,11 @@ int ossl_dsa_sign_int(int type, const unsigned char *dgst, int dlen, { DSA_SIG *s; + if (sig == NULL) { + *siglen = DSA_size(dsa); + return 1; + } + /* legacy case uses the method table */ if (dsa->libctx == NULL || dsa->meth != DSA_get_default_method()) s = DSA_do_sign(dgst, dlen, dsa); @@ -167,7 +172,7 @@ int ossl_dsa_sign_int(int type, const unsigned char *dgst, int dlen, *siglen = 0; return 0; } - *siglen = i2d_DSA_SIG(s, sig != NULL ? &sig : NULL); + *siglen = i2d_DSA_SIG(s, &sig); DSA_SIG_free(s); return 1; } diff --git a/crypto/ec/ecdsa_ossl.c b/crypto/ec/ecdsa_ossl.c index 0da33799e4..d7bd427e1b 100644 --- a/crypto/ec/ecdsa_ossl.c +++ b/crypto/ec/ecdsa_ossl.c @@ -77,6 +77,11 @@ int ossl_ecdsa_sign(int type, const unsigned char *dgst, int dlen, { ECDSA_SIG *s; + if (sig == NULL && (kinv == NULL || r == NULL)) { + *siglen = ECDSA_size(eckey); + return 1; + } + s = ECDSA_do_sign_ex(dgst, dlen, kinv, r, eckey); if (s == NULL) { *siglen = 0; diff --git a/crypto/sm2/sm2_sign.c b/crypto/sm2/sm2_sign.c index ca76128a24..1b3ca94d6e 100644 --- a/crypto/sm2/sm2_sign.c +++ b/crypto/sm2/sm2_sign.c @@ -450,6 +450,11 @@ int ossl_sm2_internal_sign(const unsigned char *dgst, int dgstlen, int sigleni; int ret = -1; + if (sig == NULL) { + ERR_raise(ERR_LIB_SM2, ERR_R_PASSED_NULL_PARAMETER); + goto done; + } + e = BN_bin2bn(dgst, dgstlen, NULL); if (e == NULL) { ERR_raise(ERR_LIB_SM2, ERR_R_BN_LIB); @@ -462,7 +467,7 @@ int ossl_sm2_internal_sign(const unsigned char *dgst, int dgstlen, goto done; } - sigleni = i2d_ECDSA_SIG(s, sig != NULL ? &sig : NULL); + sigleni = i2d_ECDSA_SIG(s, &sig); if (sigleni < 0) { ERR_raise(ERR_LIB_SM2, ERR_R_INTERNAL_ERROR); goto done; |