I have an issue where the encryption process using EVP_SealInit, EVP_SealUpdate, and EVP_SealFinal are working and not returning any failure codes.
Attempting to decipher the message works through EVP_OpenInit and EVP_OpenUpdate, however EVP_OpenFinal fails returning 0. Despite the function returning 0, the fully deciphered text is stored in the output buffer, and the total output length returning from EVP_OpenFinal is identical to the total length returning from EVP_SealFinal.
I was referencing this SO post: OpenSSL RSA: Unable to encrypt/decrypt messages longer than 16 bytes
I believe the OP modified his code with fixes, so I wasn't able to get much help there. Worth noting that my problem is present regardless of message length. 10, 15, and 140 char messages all fail during the EVP_OpenFinal call, but each message was completely stored in the output buffer.
Encryption:
int envelope_seal(EVP_PKEY *pub_key, uint8_t const *plaintext,
int plaintext_len, uint8_t *encrypted_key,
int *encrypted_key_len, uint8_t *iv,
uint8_t *ciphertext)
{
EVP_CIPHER_CTX *ctx = NULL;
int ciphertext_len = 0;
int len = 0;
if (!(ctx = EVP_CIPHER_CTX_new()))
{
handleErrors();
return -1;
}
if (!EVP_SealInit(ctx, EVP_aes_256_gcm(), &encrypted_key,
encrypted_key_len, iv, &pub_key, 1))
{
handleErrors();
return -1;
}
if (!EVP_SealUpdate(ctx, ciphertext + len, &len, plaintext, plaintext_len))
{
handleErrors();
return -1;
}
ciphertext_len += len;
if (!EVP_SealFinal(ctx, ciphertext + ciphertext_len, &len))
{
handleErrors();
return -1;
}
ciphertext_len += len;
EVP_CIPHER_CTX_free(ctx);
return ciphertext_len;
}
Decryption:
int envelope_open(EVP_PKEY *priv_key, uint8_t const *ciphertext,
int ciphertext_len, uint8_t const *encrypted_key, int encrypted_key_len, uint8_t const *iv, uint8_t *plaintext)
{
EVP_CIPHER_CTX *ctx = NULL;
int plaintext_len = 0;
int len = 0;
if (!(ctx = EVP_CIPHER_CTX_new()))
{
handleErrors();
return -1;
}
if (!EVP_OpenInit(ctx, EVP_aes_256_gcm(), encrypted_key,
encrypted_key_len, iv, priv_key))
{
handleErrors();
return -1;
}
if (!EVP_OpenUpdate(ctx, plaintext + plaintext_len, &len, ciphertext, ciphertext_len))
{
handleErrors();
return -1;
}
plaintext_len += len;
if (!EVP_OpenFinal(ctx, plaintext + plaintext_len, &len))
{
handleErrors();
return -1;
}
plaintext_len += len;
EVP_CIPHER_CTX_free(ctx);
return plaintext_len;
}
Error handling:
void handleErrors(void)
{
ERR_print_errors_fp(stderr);
}
Any help to highlight what I may be overlooking would be great, if anyone can highlight the internal differences between OpenUpdate and OpenFinal, that may help as well.
Thanks!