This is an automated archive.
The original was posted on /r/openssl by /u/inigmati1 on 2023-07-15 07:49:33+00:00.
I am trying to decrypt 64byte data encrypted using aes_256_gcm() algorithm using Openssl library in C. General process is initialise context, initialising EVP decrypt API, setting up IV, calling EVP Decrypt updates, then setting up TAG using EVP_CIPHER_CTX_ctrl() and finally, finalising the decryption. Yet, after checking up everything, segmentation fault occurs when execution reaches at EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, sizeof(tag), tag);
. Even using "strlen" or manual size in place of "sizeof(tag)" has no change in be the behaviour. Please correct me what's going wrong.
N.B. 1: I am not setting up AAD whilst encrypting the plaintext. Even if I used AAD with passing NULL values, no effect at all.
N.B. 2: Signature verification is okay. If tried to decrypt same string in logic written in Typescript, it works fine.
I am not sure where I am getting wrong.
Here's the C code.
int aes_decrypt(const unsigned char *ciphertext, size_t ciphertext_len, char *key,
char *iv, unsigned char *plaintext, unsigned char *tag)
{
if (tag == NULL)
{
fprintf(stderr, "Error: tag is NULL.\n");
return 0;
}
if (strlen(tag) < TAG_SIZE)
{
fprintf(stderr, "Error: tag is smaller than TAG_SIZE.\n");
return 0;
}
//key derivation fuction works fine.
unsigned char kdfResult[32];
pbkdf2((char *)key, (const unsigned char *)iv, strlen((const char *)iv), 100000, 32, kdfResult);
int ivbytelen;
unsigned char *ivByteArray = hex_string_to_bytes(iv, &ivbytelen);
EVP_CIPHER_CTX *ctx;
int len;
int plaintext_len;
int result;
if (!(ctx = EVP_CIPHER_CTX_new()))
{
fprintf(stderr, "Error creating EVP_CIPHER_CTX.\n");
return 0;
}
if (1 != EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL))
{
fprintf(stderr, "Error setting cipher type and mode.\n");
EVP_CIPHER_CTX_free(ctx);
return 0;
}
int ret = EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, IV_SIZE, NULL);
if (ret != 1) {
EVP_CIPHER_CTX_free(ctx);
fprintf(stderr, "Error setting ivg.\n");
return 0;
}
if (1 != EVP_DecryptInit_ex(ctx, NULL, NULL, kdfResult, ivByteArray))
{
fprintf(stderr, "Error setting key and IV.\n");
EVP_CIPHER_CTX_free(ctx);
return 0;
}
EVP_DecryptUpdate(ctx, NULL, &len, NULL, 16);
if (1 != EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len))
{
fprintf(stderr, "Error decrypting ciphertext.\n");
EVP_CIPHER_CTX_free(ctx);
return 0;
}
//Once control reaches at this point, segmentation fault occurs
if (1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, strlen(tag), tag))
{
fprintf(stderr, "Error setting authentication tag.\n");
EVP_CIPHER_CTX_free(ctx);
return 0;
}
plaintext_len = len;
result = EVP_DecryptFinal_ex(ctx, plaintext + len, &len);
EVP_CIPHER_CTX_free(ctx);
if (result > 0)
{
plaintext_len += len;
return plaintext_len;
}
else
{
fprintf(stderr, "Error finalizing decryption.\n");
return -1;
}
}
for setting tag length, i tried strlen and passing size manually. Nothing worked.
EDIT:
Encryption data used in hex format (ofcourse I formatted it into byte array before passing it for AES decryption).
ciphertext: "71cba06a6c1918a2d1712d4317211efed7f1c8120109c0931a081194ba18c696b6daeaea71fa3d354dcfca4794c7bde8ff269c42178754796b9b2b4c0ba2682d"
tag: "3decb85890fff4aa1feae4c7abbe570f"
iv: "5b7733889cea3f33af2d3819"
key: "b1ea1f8a27990fdf7053935db78e923d751db61217fda864c14faf1e34d01159"
As was requested, here's the pbkdf2() implementation:
void pbkdf2(const char *password, const unsigned char *salt, int salt_len, int iterations, int key_len, unsigned char *derived_key)
{
if (PKCS5_PBKDF2_HMAC(password, strlen(password), salt, salt_len, iterations, EVP_sha256(), key_len, derived_key) != 1)
{
fprintf(stderr, "Failed to derive key\n");
}
}