openssl: EVP_DigestSign fails when called second time in 3.2.0
I need sign series of message with EdDSA. I create EVP_PKEY from a private key, then initialize EVP_MD_CTX using EVP_DigestSignInit and then call EVP_DigestSign multiple times for each message. It worked fine in 3.1.0 and EVP_DigestSign fails when called second time in 3.2.0. See the code below, I’m trying to sign and verify result using a test vector from RFC 8032. It’s successive after the first call and fails after the second call.
```
#include <cassert>
#include <inttypes.h>
#include <string.h>
#include <openssl/evp.h>
int main ()
{
// ED25519 test vector TEST 1024 from RFC 8032
uint8_t key[32], msg[1024], sig[64];
BIGNUM * input = BN_new();
BN_hex2bn(&input, "f5e5767cf153319517630f226876b86c8160cc583bc013744c6bf255f5cc0ee5");
BN_bn2bin(input, key);
BN_hex2bn(&input,
"08b8b2b733424243760fe426a4b54908632110a66c2f6591eabd3345e3e4eb98"
"fa6e264bf09efe12ee50f8f54e9f77b1e355f6c50544e23fb1433ddf73be84d8"
"79de7c0046dc4996d9e773f4bc9efe5738829adb26c81b37c93a1b270b20329d"
"658675fc6ea534e0810a4432826bf58c941efb65d57a338bbd2e26640f89ffbc"
"1a858efcb8550ee3a5e1998bd177e93a7363c344fe6b199ee5d02e82d522c4fe"
"ba15452f80288a821a579116ec6dad2b3b310da903401aa62100ab5d1a36553e"
"06203b33890cc9b832f79ef80560ccb9a39ce767967ed628c6ad573cb116dbef"
"efd75499da96bd68a8a97b928a8bbc103b6621fcde2beca1231d206be6cd9ec7"
"aff6f6c94fcd7204ed3455c68c83f4a41da4af2b74ef5c53f1d8ac70bdcb7ed1"
"85ce81bd84359d44254d95629e9855a94a7c1958d1f8ada5d0532ed8a5aa3fb2"
"d17ba70eb6248e594e1a2297acbbb39d502f1a8c6eb6f1ce22b3de1a1f40cc24"
"554119a831a9aad6079cad88425de6bde1a9187ebb6092cf67bf2b13fd65f270"
"88d78b7e883c8759d2c4f5c65adb7553878ad575f9fad878e80a0c9ba63bcbcc"
"2732e69485bbc9c90bfbd62481d9089beccf80cfe2df16a2cf65bd92dd597b07"
"07e0917af48bbb75fed413d238f5555a7a569d80c3414a8d0859dc65a46128ba"
"b27af87a71314f318c782b23ebfe808b82b0ce26401d2e22f04d83d1255dc51a"
"ddd3b75a2b1ae0784504df543af8969be3ea7082ff7fc9888c144da2af58429e"
"c96031dbcad3dad9af0dcbaaaf268cb8fcffead94f3c7ca495e056a9b47acdb7"
"51fb73e666c6c655ade8297297d07ad1ba5e43f1bca32301651339e22904cc8c"
"42f58c30c04aafdb038dda0847dd988dcda6f3bfd15c4b4c4525004aa06eeff8"
"ca61783aacec57fb3d1f92b0fe2fd1a85f6724517b65e614ad6808d6f6ee34df"
"f7310fdc82aebfd904b01e1dc54b2927094b2db68d6f903b68401adebf5a7e08"
"d78ff4ef5d63653a65040cf9bfd4aca7984a74d37145986780fc0b16ac451649"
"de6188a7dbdf191f64b5fc5e2ab47b57f7f7276cd419c17a3ca8e1b939ae49e4"
"88acba6b965610b5480109c8b17b80e1b7b750dfc7598d5d5011fd2dcc5600a3"
"2ef5b52a1ecc820e308aa342721aac0943bf6686b64b2579376504ccc493d97e"
"6aed3fb0f9cd71a43dd497f01f17c0e2cb3797aa2a2f256656168e6c496afc5f"
"b93246f6b1116398a346f1a641f3b041e989f7914f90cc2c7fff357876e506b5"
"0d334ba77c225bc307ba537152f3f1610e4eafe595f6d9d90d11faa933a15ef1"
"369546868a7f3a45a96768d40fd9d03412c091c6315cf4fde7cb68606937380d"
"b2eaaa707b4c4185c32eddcdd306705e4dc1ffc872eeee475a64dfac86aba41c"
"0618983f8741c5ef68d3a101e8a3b8cac60c905c15fc910840b94c00a0b9d0"
);
BN_bn2bin(input, msg);
BN_hex2bn(&input,
"0aab4c900501b3e24d7cdf4663326a3a87df5e4843b2cbdb67cbf6e460fec350"
"aa5371b1508f9f4528ecea23c436d94b5e8fcd4f681e30a6ac00a9704a188a03");
BN_bn2bin(input, sig);
EVP_PKEY * pkey = EVP_PKEY_new_raw_private_key (EVP_PKEY_ED25519, NULL, key, 32);
assert (pkey != NULL);
EVP_MD_CTX * ctx = EVP_MD_CTX_create ();
assert (ctx != NULL);
assert (EVP_DigestSignInit (ctx, NULL, NULL, NULL, pkey));
// try to sign and compare with expected signature
size_t l = 64; uint8_t s[64];
assert (EVP_DigestSign (ctx, s, &l, msg, 1023));
assert (memcmp (s, sig, 64) == 0);
// success
// try again
assert (EVP_DigestSign (ctx, s, &l, msg, 1023));
// failed
}
```
About this issue
- Original URL
- State: closed
- Created 6 months ago
- Comments: 23 (18 by maintainers)
Commits related to this issue
- community/i2pd: upgrade to 2.50.0 Add version constraint openssl-dev<3.2.0 due to https://github.com/openssl/openssl/issues/23075 — committed to alpinelinux/aports by deleted user 6 months ago
- Update Documentation for EVP_DigestSign, EVP_DigestVerify. Fixes #23075 In OpenSSL 3.2 EVP_DigestSign and EVP_DigestVerify were changed so that a flag is set once these functions do a one-shot sign ... — committed to slontis/openssl by slontis 4 months ago
- Update Documentation for EVP_DigestSign, EVP_DigestVerify. Fixes #23075 In OpenSSL 3.2 EVP_DigestSign and EVP_DigestVerify were changed so that a flag is set once these functions do a one-shot sign ... — committed to openssl/openssl by slontis 4 months ago
- Update Documentation for EVP_DigestSign, EVP_DigestVerify. Fixes #23075 In OpenSSL 3.2 EVP_DigestSign and EVP_DigestVerify were changed so that a flag is set once these functions do a one-shot sign ... — committed to openssl/openssl by slontis 4 months ago
- Update Documentation for EVP_DigestSign, EVP_DigestVerify. Fixes #23075 In OpenSSL 3.2 EVP_DigestSign and EVP_DigestVerify were changed so that a flag is set once these functions do a one-shot sign ... — committed to olszomal/openssl by slontis 4 months ago
Understood, but it was totally undefined behavior, so a hard choice should be made in this case.
@slontis Yeah I am of the opinion that initialization should always be required.
Although OpenSSL internal default provider can cope with reuse in some cases, that is not a given for all providers (and some will probably not be able to), nor for all signature schemes that could be added in the future.
I do not believe the Init() function to be such an overhead that would warrant keeping an ambiguous behavior, if performance is an issue I would rather focus on optimizing the Init() function so that it has as low re-init overhead as possible within specific provider implementations rather than leaving ambiguous and potentially unsafe behavior available.
I guess the semantics of EVP_DigestSign could be change to transparently call a re-init internally, I am not sure it is worth it though, it will complicate the code and cause double calls to provider init functions in the default case, which may fail to work with current providers.