kokke/tiny-AES-c

Corrupted 16bytes after decrypting AES-128 CBC

bgolab opened this issue · 5 comments

Hi,
I just started using the tiny-AES-c library so I am very new to this lib.

Just taken json file encrypted by one device and wanted to decrypt it using your library:
uint8_t token[16]={ 0x6d, 0x4e, 0xda, 0x3e, 0x38, 0xdf, 0xa3, 0xa0, 0x07, 0xe2, 0xec, 0xd7, 0x69, 0x52, 0x5f, 0x6c };

key: 6d4eda3e38dfa3a007e2ecd769525f6c
iv: 41e6d65a2876f96ad2e2feab33ab384f

packet="65 2a c9 9d c5 85 04 f3 9c 0e 2e 5b e9 c1 f4 8f d4 ae 28 43 a0 a8 24 09 0f 9d 2a 40 55 c1 aa 63 c2 33 2f 21 53 d7 f2 92 09 8e f8 ee f3 fe 0e 74 e1 ad 71 45 04 34 e8 4e b4 a3 63 7f e8 41 6d 71 a2 60 99 04 2f 30 88 e6 f0 f8 6e ce d6 3e e8 6f 67 0d 6d 14 28 24 ae 5e f6 9c 34 3c 6f 07 de 07";

and got the output:
Buffer(hex):
2c7bba0bafad89f299b86d82d45eefe431382c31372c33392c3230382c226175746f222c352c31382c323834342c6e756c6c2c3335312c6e756c6c2c6e756c6c2c333530302c226f6666225d2c226964223a317d0c0c0c0c0c0c0c0c0c0c0c0c
Buffer(ascii):
,{<0b><89><99>m<82>^18,17,39,208,"auto",5,18,2844,null,351,null,null,3500,"off"],"id":1}<0c><0c><0c><0c><0c><0c><0c><0c><0c><0c><0c><0c>

So the padding is fine. The beginning of the json data is is corrupted.
This part is corrupted:
{'result': ['on',

Looks like impossible - it looks like the first 16 bytes were overriten ....

Any suggestion are welcome.
Thanks,
Bogdan

My code snippets using your library:
`#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <ctype.h>

// Enable ECB, CTR and CBC mode. Can be done before including aes.h or at compile-time. E.g. with GCC by using the -D flag: gcc -c aes.c -DCBC=0 -DCTR=1 -DECB=1
#define CBC 1
#include "aes.h"

static int test_encrypt_cbc(void);
static int test_decrypt_cbc(uint8_t *key, uint8_t *iv, uint8_t *in, uint32_t insize);
void md5(uint8_t *initial_msg, size_t initial_len, uint8_t *md5);

// prints string as hex
static void phex(uint8_t* str, int len){
unsigned char i;
for (i = 0; i < len; ++i) printf("%.2x", str[i]);
printf("\n");
}

// prints string as ascii
static void pascii(uint8_t* str, int len){
unsigned char i;
for (i = 0; i < len; ++i){
if((str[i]>=32)&&(str[i]<=127)){
printf("%c", str[i]);
}
else{
printf("<%.2x>", str[i]);
}
}
printf("\n");
}

void removeWS(char *s, char d){
int k;
for(k=0;k<strlen(s);k++){
if(isspace(
(s+k))){ continue; }
d=(s+k);
d++;
}
*d='\0';
}

void str2hex(char *s, uint8_t *h){
int k;
char b[5]={'0','x','0','0','\0'};
int num;

for(k=0;k<strlen(s)/2;k++){
	b[2]=s[2*k];
	b[3]=s[2*k+1];
	sscanf(b, "%x", &num);
	*(h+k)=num;
}

}

// "token":"6d4eda3e38dfa3a007e2ecd769525f6c"
// Key = MD5(Token)
// IV = MD5(MD5(Key) + Token)

#define LENGTH 16
int main(void){
int k, insize;
uint8_t md5h[16]={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };

char *packet;
char d[1000];
uint8_t in[1000];

// purifier data
uint8_t token[LENGTH]={ 0x6d, 0x4e, 0xda, 0x3e, 0x38, 0xdf, 0xa3, 0xa0, 0x07, 0xe2, 0xec, 0xd7, 0x69, 0x52, 0x5f, 0x6c };
uint8_t key[LENGTH]={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
uint8_t iv[LENGTH]={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
uint8_t tmp[LENGTH]={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };

// Key = MD5(Token)
md5(token, LENGTH, md5h);
for(k=0;k<LENGTH;k++){ key[k]=md5h[k]; }

// IV  = MD5(MD5(Key) + Token)
md5(key, LENGTH, md5h);
for(k=0;k<LENGTH;k++){ tmp[k]=md5h[k]+token[k]; }
md5(tmp, LENGTH, md5h);
for(k=0;k<LENGTH;k++){ iv[k]=md5h[k]; }
printf("iv: ");
phex(iv, 16);

printf("\nTesting AES128\n\n");
packet="9c 70 b3 23 ff fd 46 74 a4 67 67 74 50 5a 15 2f 2b c4 ed 98 2e 4b 12 d3 c2 a1 44 36 ac 43 6e 8f 7e 3e 79 68 ac c5 60 cc 47 25 73 fa ee 30 cf da 68 d4 82 4f 0d 6c 7e 99 10 79 6e 41 7a bc 5c 43 49 0d 51 7a 31 35 a6 24 32 35 c4 19 93 12 ef 7a 77 19 33 f8 78 95 e0 e4 23 4a 7f cd e9 cc 99 7c 84 79 b1 e3 06 8b da 8e 9b 6b ec b5 c0 31 01 97 44 96 1b 37 02 21 6c 00 94 c3 11 99 f0 5a 4b d1 cf 46 30 78 7e 85 21 ee 34 e2 00 d3 d2 fd de 31 fb f9 6b 05 2e bf 8a b4 e4 80 b7 0e 43 03 5e 25 9d 2a 59 a6 52 ef 42 82 51 54 e2 21 f4 36 41 97 0b f6 d7 8e a9 83 6c 08 c1 99 df 47 89 8a 6f 7e 82 90 cc 88 81 72 e6 b2 db 80 af 8b e2 1a be 5f f2 6e 61 60 97 62 50 a4 18 a3 f4 04 71 f4 6f 07 33 02 68 e8 60 e3 51 5a d4 32 e9 96 4a 4c 0f 36";
removeWS(packet, d);
str2hex(d, in);
insize=strlen(d)/2;
test_decrypt_cbc(key, iv, in, insize);

packet="65 2a c9 9d c5 85 04 f3 9c 0e 2e 5b e9 c1 f4 8f d4 ae 28 43 a0 a8 24 09 0f 9d 2a 40 55 c1 aa 63 c2 33 2f 21 53 d7 f2 92 09 8e f8 ee f3 fe 0e 74 e1 ad 71 45 04 34 e8 4e b4 a3 63 7f e8 41 6d 71 a2 60 99 04 2f 30 88 e6 f0 f8 6e ce d6 3e e8 6f 67 0d 6d 14 28 24 ae 5e f6 9c 34 3c 6f 07 de 07";
removeWS(packet, d);
str2hex(d, in);
insize=strlen(d)/2;
printf("packet:");
phex(in, insize);
printf("insize: %d\n\r", insize);
test_decrypt_cbc(key, iv, in, insize);

//test_encrypt_cbc();
return 0;

}

static int test_decrypt_cbc(uint8_t *key, uint8_t *iv, uint8_t *in, uint32_t insize){
struct AES_ctx ctx;
AES_init_ctx_iv(&ctx, key, iv);
AES_CBC_decrypt_buffer(&ctx, in, insize);

printf("CBC decryption\n\r");
printf("\n\r");
printf("Buffer(hex):\n\r");
phex(in, insize);
printf("Buffer(ascii):\n\r");
pascii(in, insize);
return(0);

}`

Topic closed. I had an error in IV calculation. Funny results: only 16 bytes were affected.

kokke commented

Hi @bgolab and thanks for your update,

I would generally expect all code to work as advertised, since I have done a lot of testing, and the project gets a fair share of field-usage. I'm glad you updated this issue, to let me know I needn't worry :)

I had an error in IV calculation. Funny results: only 16 bytes were affected.

I have a comment on this:

IV selection for CBC-mode is critical, as the initial entropy depends very much on the first block (128 bit / 16 byte). The IV for the second block is the output of the first block. See this diagram from wikipedia:

CBC mode of operation

If another IV only permutes the first 16 bytes, that sounds to me like it has a low entropy?

Yes, you are right. I studied this later a little bit. And this is known behavior.

I am sorry for bothering your. Your API is fine. I am embedding it now in my home automation project (MI Purifier controller based on STM32 ARM + ESP8266).

kokke commented

No need to apologize :)

I am happy you got everything working as expected 👍