I am trying to write a set of basic encrypt and decrypt functions in C using OpenSSL and I am losing the last block of my plain text when decrypting. I think it’s probably a padding issue but I am not sure how to diagnose it since I can’t seem to get any information out of the OpenSSL call as to why it’s returning an incorrect length.
At the moment EVP_DecryptUpdate
returns a length of 32 when I think it should return 48. Additionally to this even though the length value passed to EVP_DecryptFinal_ex
is 32 if your array is 49 long or any other size that is not a multiple of 16 it will return a value indicating there was an error.
#include <openssl/conf.h>
int ecb_encrypt(unsigned char *plain_bytes, unsigned char *key, unsigned char *cipher_bytes, size_t plain_bytes_len, size_t *cipher_bytes_len) {
if(!(ctx = EVP_CIPHER_CTX_new()))
if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_128_ecb(), NULL, key, NULL))
if(1 != EVP_EncryptUpdate(ctx, cipher_bytes, &len, plain_bytes, plain_bytes_len))
if(1 != EVP_EncryptFinal_ex(ctx, cipher_bytes + *cipher_bytes_len, &len))
EVP_CIPHER_CTX_free(ctx);
int ecb_decrypt(unsigned char *cipher_bytes, unsigned char *key, unsigned char *plain_bytes, size_t cipher_bytes_len, size_t *plain_bytes_len) {
if(!(ctx = EVP_CIPHER_CTX_new()))
if(1 != EVP_DecryptInit_ex(ctx, EVP_aes_128_ecb(), NULL, key, NULL))
if(1 != EVP_DecryptUpdate(ctx, plain_bytes, &len, cipher_bytes, cipher_bytes_len))
printf("len = %dn", len);
printf("plain_bytes_len = %lun", *plain_bytes_len);
if(1 != EVP_DecryptFinal_ex(ctx, plain_bytes + *plain_bytes_len, &len))
EVP_CIPHER_CTX_free(ctx);
unsigned char plain_text[] = "AAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCC";
unsigned char key[] = "YELLOW SUBMARINE";
unsigned char cipher_bytes[48];
size_t cipher_bytes_len = 0;
ecb_encrypt(plain_text, key, (unsigned char *) &cipher_bytes, 48, &cipher_bytes_len);
printf("cipher_bytes_len = %lun", cipher_bytes_len);
size_t plain_bytes_len = 0;
unsigned char plain_bytes[cipher_bytes_len];
ecb_decrypt(cipher_bytes, key, (unsigned char *) &plain_bytes, cipher_bytes_len, &plain_bytes_len);
printf("plain_bytes_len = %lun", plain_bytes_len);
for(size_t i = 0; i < plain_bytes_len; i++){
printf("%c", plain_bytes[i]);
<code>#include <stdio.h>
#include <string.h>
#include <openssl/conf.h>
#include <openssl/evp.h>
#include <openssl/err.h>
int ecb_encrypt(unsigned char *plain_bytes, unsigned char *key, unsigned char *cipher_bytes, size_t plain_bytes_len, size_t *cipher_bytes_len) {
EVP_CIPHER_CTX *ctx;
int len = 0;
if(!(ctx = EVP_CIPHER_CTX_new()))
return 4;
if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_128_ecb(), NULL, key, NULL))
return 5;
if(1 != EVP_EncryptUpdate(ctx, cipher_bytes, &len, plain_bytes, plain_bytes_len))
return 6;
*cipher_bytes_len = len;
if(1 != EVP_EncryptFinal_ex(ctx, cipher_bytes + *cipher_bytes_len, &len))
return 7;
EVP_CIPHER_CTX_free(ctx);
return 0;
}
int ecb_decrypt(unsigned char *cipher_bytes, unsigned char *key, unsigned char *plain_bytes, size_t cipher_bytes_len, size_t *plain_bytes_len) {
EVP_CIPHER_CTX *ctx;
int len = 0;
if(!(ctx = EVP_CIPHER_CTX_new()))
return 4;
if(1 != EVP_DecryptInit_ex(ctx, EVP_aes_128_ecb(), NULL, key, NULL))
return 5;
if(1 != EVP_DecryptUpdate(ctx, plain_bytes, &len, cipher_bytes, cipher_bytes_len))
return 6;
*plain_bytes_len = len;
printf("len = %dn", len);
printf("plain_bytes_len = %lun", *plain_bytes_len);
if(1 != EVP_DecryptFinal_ex(ctx, plain_bytes + *plain_bytes_len, &len))
return 7;
EVP_CIPHER_CTX_free(ctx);
return 0;
}
int main() {
unsigned char plain_text[] = "AAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCC";
unsigned char key[] = "YELLOW SUBMARINE";
unsigned char cipher_bytes[48];
size_t cipher_bytes_len = 0;
ecb_encrypt(plain_text, key, (unsigned char *) &cipher_bytes, 48, &cipher_bytes_len);
printf("cipher_bytes_len = %lun", cipher_bytes_len);
//decrypt
size_t plain_bytes_len = 0;
unsigned char plain_bytes[cipher_bytes_len];
ecb_decrypt(cipher_bytes, key, (unsigned char *) &plain_bytes, cipher_bytes_len, &plain_bytes_len);
printf("plain_bytes_len = %lun", plain_bytes_len);
for(size_t i = 0; i < plain_bytes_len; i++){
printf("%c", plain_bytes[i]);
}
return 0;
}
</code>
#include <stdio.h>
#include <string.h>
#include <openssl/conf.h>
#include <openssl/evp.h>
#include <openssl/err.h>
int ecb_encrypt(unsigned char *plain_bytes, unsigned char *key, unsigned char *cipher_bytes, size_t plain_bytes_len, size_t *cipher_bytes_len) {
EVP_CIPHER_CTX *ctx;
int len = 0;
if(!(ctx = EVP_CIPHER_CTX_new()))
return 4;
if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_128_ecb(), NULL, key, NULL))
return 5;
if(1 != EVP_EncryptUpdate(ctx, cipher_bytes, &len, plain_bytes, plain_bytes_len))
return 6;
*cipher_bytes_len = len;
if(1 != EVP_EncryptFinal_ex(ctx, cipher_bytes + *cipher_bytes_len, &len))
return 7;
EVP_CIPHER_CTX_free(ctx);
return 0;
}
int ecb_decrypt(unsigned char *cipher_bytes, unsigned char *key, unsigned char *plain_bytes, size_t cipher_bytes_len, size_t *plain_bytes_len) {
EVP_CIPHER_CTX *ctx;
int len = 0;
if(!(ctx = EVP_CIPHER_CTX_new()))
return 4;
if(1 != EVP_DecryptInit_ex(ctx, EVP_aes_128_ecb(), NULL, key, NULL))
return 5;
if(1 != EVP_DecryptUpdate(ctx, plain_bytes, &len, cipher_bytes, cipher_bytes_len))
return 6;
*plain_bytes_len = len;
printf("len = %dn", len);
printf("plain_bytes_len = %lun", *plain_bytes_len);
if(1 != EVP_DecryptFinal_ex(ctx, plain_bytes + *plain_bytes_len, &len))
return 7;
EVP_CIPHER_CTX_free(ctx);
return 0;
}
int main() {
unsigned char plain_text[] = "AAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCC";
unsigned char key[] = "YELLOW SUBMARINE";
unsigned char cipher_bytes[48];
size_t cipher_bytes_len = 0;
ecb_encrypt(plain_text, key, (unsigned char *) &cipher_bytes, 48, &cipher_bytes_len);
printf("cipher_bytes_len = %lun", cipher_bytes_len);
//decrypt
size_t plain_bytes_len = 0;
unsigned char plain_bytes[cipher_bytes_len];
ecb_decrypt(cipher_bytes, key, (unsigned char *) &plain_bytes, cipher_bytes_len, &plain_bytes_len);
printf("plain_bytes_len = %lun", plain_bytes_len);
for(size_t i = 0; i < plain_bytes_len; i++){
printf("%c", plain_bytes[i]);
}
return 0;
}
Basically I am losing my C’s and I am not sure why it’s getting the length wrong.
Output:
<code>cipher_bytes_len = 48
AAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBcipher_bytes_len = 48
AAAAAAAAAAAAAAAABBBBBBBBBBBBBBB
<code>cipher_bytes_len = 48
len = 32
plain_bytes_len = 32
plain_bytes_len = 32
AAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBcipher_bytes_len = 48
len = 32
plain_bytes_len = 32
plain_bytes_len = 32
AAAAAAAAAAAAAAAABBBBBBBBBBBBBBB
</code>
cipher_bytes_len = 48
len = 32
plain_bytes_len = 32
plain_bytes_len = 32
AAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBcipher_bytes_len = 48
len = 32
plain_bytes_len = 32
plain_bytes_len = 32
AAAAAAAAAAAAAAAABBBBBBBBBBBBBBB