openssl: Re-initialising an EVP_CIPHER_CTX does not work as expected
With AES-128-CTR (and quite possibly other ciphers, but I didn’t test it), re-initialising the EVP_CIPHER_CTX does not give the results we would expect. Consider this reproducer:
#include <openssl/evp.h>
#include <stdio.h>
int main(void)
{
EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
unsigned char out[4];
unsigned char in[4] = {
0x0f, 0x0e, 0x0d, 0x0c
};
unsigned char key1[16] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
0x0c, 0x0d, 0x0e, 0x0f
};
unsigned char iv[16] = {
0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04,
0x03, 0x02, 0x01, 0x00
};
int ret = 1, outl = 0;
size_t i;
if (!EVP_EncryptInit_ex(ctx, EVP_aes_128_ctr(), NULL, key1, iv))
goto err;
if (!EVP_EncryptUpdate(ctx, out, &outl, in, sizeof(in)))
goto err;
if (outl != 4)
goto err;
outl = 0;
printf("First data block is:\n");
for (i = 0; i < sizeof(out); i++)
printf("%02X ", out[i]);
printf("\n");
if (!EVP_EncryptInit_ex(ctx, NULL, NULL, key1, iv))
goto err;
if (!EVP_EncryptUpdate(ctx, out, &outl, in, sizeof(in)))
goto err;
if (outl != 4)
goto err;
printf("Second data block is:\n");
for (i = 0; i < sizeof(out); i++)
printf("%02X ", out[i]);
printf("\n");
ret = 0;
err:
if (ret)
printf("Error\n");
else
printf("Success\n");
return ret;
}
When I run this code against 1.1.1 I get this output:
First data block is:
2F A7 F4 9E
Second data block is:
2F A7 F4 9E
Success
This is as expected. We have reset the key and IV and run the same encryption again. Therefore we would expect to see the same output. When I run this against master I get this:
First data block is:
2F A7 F4 9E
Second data block is:
BB 42 56 E4
Success
So the same encryption with the same key and IV gives different results in the re-initialised case.
About this issue
- Original URL
- State: closed
- Created 4 years ago
- Comments: 18 (18 by maintainers)
Commits related to this issue
- Fix provider cipher reinit issue Calling Init()/Update() and then Init()/Update() again gave a different result when using the same key and iv. Cipher modes that were using ctx->num were not resettin... — committed to slontis/openssl by slontis 4 years ago
- Fix provider cipher reinit issue Calling Init()/Update() and then Init()/Update() again gave a different result when using the same key and iv. Cipher modes that were using ctx->num were not resettin... — committed to slontis/openssl by slontis 4 years ago
- squash! test/drbgtest: improve the reseed after fork test (add the following text to the commit message) The analysis of #12377 (see [1]) showed that due to an error in the resetting of the AES-CTR ... — committed to mspncp/openssl by mspncp 4 years ago
- test/drbgtest: improve the reseed after fork test Issue #12377 demonstrated that it is not sufficient to verify that after a fork a reseeding is triggered in the child. This commit enhances the test ... — committed to mspncp/openssl by mspncp 4 years ago
- test/drbgtest: improve the reseed after fork test Issue #12377 demonstrated that it is not sufficient to verify that after a fork a reseeding is triggered in the child. This commit enhances the test ... — committed to openssl/openssl by mspncp 4 years ago
Are there currently a set of tests that are run on every cipher provider? If so, there should be a test to prevent other providers from making this mistake. If not, it would be a good thing to add a set of tests that every provider needs to pass. (Commenting as reporter of #12377)