openssl/openssl
With AES-CCM ciphers, initializing an EVP_CIPHER_CTX with key and nonce seperately results in an error on fetching tag
Chiusa
#23.302 aperta il 14 gen 2024
branch: 3.0branch: 3.1branch: 3.2branch: masterhelp wantedtriaged: bug
Metriche repository
- Star
- (30.157 stelle)
- Metriche merge PR
- (Metriche PR in attesa)
Descrizione
Here's a basic reproducer:
#include <stdbool.h>
#include <string.h>
#include <openssl/err.h>
#include <openssl/evp.h>
void openssl_assert(char *op, bool ok) {
if (!ok) {
printf("%s failed:\n", op);
ERR_print_errors_fp(stdout);
exit(1);
}
}
int main() {
uint8_t key[16] = {0};
uint8_t nonce[12] = {0};
char *msg = "happy birthday to me";
size_t tag_len = 16;
EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
openssl_assert("EVP_CIPHER_CTX_new", ctx != NULL);
int res = EVP_EncryptInit_ex(ctx, EVP_aes_128_ccm(), NULL, key, NULL);
openssl_assert("EVP_EncryptInit_ex(cipher, key)", res == 1);
res = EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, sizeof(nonce), NULL);
openssl_assert("EVP_CIPHER_CTX_ctrl(EVP_CTRL_AEAD_SET_IVLEN)", res == 1);
res = EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, tag_len, NULL);
openssl_assert("EVP_CIPHER_CTX_ctrl(EVP_CTRL_AEAD_SET_TAG)", res == 1);
res = EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, nonce);
openssl_assert("EVP_EncryptInit_ex(nonce)", res == 1);
int zero = 0;
res = EVP_CipherUpdate(ctx, NULL, &zero, NULL, strlen(msg));
openssl_assert("EVP_CipherUpdate(data_len)", res == 1);
size_t ciphertext_len = strlen(msg) + tag_len;
uint8_t *ciphertext = calloc(1, ciphertext_len);
int written = 0;
res = EVP_CipherUpdate(ctx, ciphertext, &written, (const unsigned char *)msg,
strlen(msg));
openssl_assert("EVP_CipherUpdate(msg)", res == 1);
openssl_assert("EVP_CipherUpdate(msg)", written == strlen(msg));
uint8_t final_block[1] = {0};
res = EVP_CipherFinal(ctx, final_block, &written);
openssl_assert("EVP_CipherFinal(msg)", res == 1);
openssl_assert("EVP_CipherFinal(msg)", written == 0);
res = EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, tag_len,
ciphertext + strlen(msg));
openssl_assert("EVP_CIPHER_CTX_ctrl(EVP_CTRL_AEAD_GET_TAG)", res == 1);
}
If you change EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, nonce) to be EVP_EncryptInit_ex(ctx, NULL, NULL, key, nonce) (that is, to provide the key for a second time), then it will pass.
For all other ciphers, it works to pass key and nonce in separate calls to EVP_EncryptInit_ex, so I believe this is a bug. Further, the fact that this error happens on fetching the tag and provides no error stack makes it appear to be a bug.