Search code examples
copenssl

Concatenate unsigned char * inside a loop


I'm using the library OpenSSL for encrypting through AES. Since AES is a block cipher, I need to split the data in chunks of 16 bytes. Thus, if I want to recover the message, I need to unite the chunks at the end of the program.

This is my code:

#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <openssl/aes.h>

char key[] = "secretkey123";

int main() {
    unsigned char text_slice[128];
    unsigned char enc_slice[128];
    unsigned char dec_slice[128];
    
    unsigned char in[160];
    
    unsigned char enc_out[160] = "";
    unsigned char dec_out[160] = "";
    
    int i;
    int k = 10;
    for (i = 0; i < 16 * k; i++) {
        in[i] = 'A' + (rand() % 26);
    }
    in[160] = '\0';
    printf("IN:%s\n", in);
    
    AES_KEY enc_key, dec_key;
    
    AES_set_encrypt_key(key, 128, &enc_key);
    
    AES_set_decrypt_key(key, 128, &dec_key);
    
    for (i = 0; i < k; i++) {
        text_slice[0] = '\0';
        enc_slice[0] = "\0";
        dec_slice[0] = "\0";
        memcpy(&text_slice[0], &in[15 * i], 15);
        text_slice[16] = "\0";
        printf("TEXT SLICE: %s \n", text_slice);
        AES_encrypt(text_slice, enc_slice, &enc_key);
        memcpy(&enc_out[16 * i], &enc_slice[0], 16);
    }
    printf("ENC:%s\n", enc_out);
    for (i = 0; i < k; i++) {
        text_slice[0] = '\0';
        enc_slice[0] = "\0";
        dec_slice[0] = "\0";
        memcpy(enc_slice, &enc_out[16 * i], 16);
        enc_slice[16] = "\0";
    
        AES_decrypt(enc_slice, dec_slice, &dec_key);
        printf("Dec slice:%s \n", dec_slice);
        memcpy(&dec_out[16 * i], &dec_slice[0], 16);
    }
    printf("DEC OUT:%s\n", dec_out);
    
    return 0;
}

The output of the program is the following:

IN:NWLRBBMQBHCDARZOWKKYHIDDQSCDXRJMOWFRXSJYBLDBEFSARCBYNECDYGGXXPKLORELLNMPAPQFWKHOPKMCOQHNWNKUEWHSQMGBBUQCLJJIVSWMDKQTBXIXMVTRRBLJPTNSNFWZQFJMAFADRRWSOFSBCNUVQHFF
TEXT SLICE: NWLRBBMQBHCDARZ 
TEXT SLICE: OWKKYHIDDQSCDXR 
TEXT SLICE: JMOWFRXSJYBLDBE 
TEXT SLICE: FSARCBYNECDYGGX 
TEXT SLICE: XPKLORELLNMPAPQ 
TEXT SLICE: FWKHOPKMCOQHNWN 
TEXT SLICE: KUEWHSQMGBBUQCL 
TEXT SLICE: JJIVSWMDKQTBXIX 
TEXT SLICE: MVTRRBLJPTNSNFW 
TEXT SLICE: ZQFJMAFADRRWSOF 
ENC:j�Q���
𢨫�7֡���*n���R  ��m7�zI#4��=v�#�(��V7��ח9.R�q����:C�%��_��!q��(��l��j�3�1�h��
Dec slice:NWLRBBMQBHCDARZ 
Dec slice:OWKKYHIDDQSCDXR 
Dec slice:JMOWFRXSJYBLDBE 
Dec slice:FSARCBYNECDYGGX 
Dec slice:XPKLORELLNMPAPQ 
Dec slice:FWKHOPKMCOQHNWN 
Dec slice:KUEWHSQMGBBUQCL 
Dec slice:JJIVSWMDKQTBXIX 
Dec slice:MVTRRBLJPTNSNFW 
Dec slice:ZQFJMAFADRRWSOF 
DEC OUT:NWLRBBMQBHCDARZ

While dec_slice works as expected, dec_out just get a copy of the memory of the first chunk. What is more surprising for me, is that enc_out performs correctly when following the same logic as dec_out. What am I missing?


Solution

  • The key must have at least 16 bytes since you pass a number of bits equal to 128 in:

    AES_set_encrypt_key(key, 128, &enc_key);
    AES_set_decrypt_key(key, 128, &dec_key);
    

    You have undefined behavior here:

        in[160] = '\0';
    

    These lines don't make sense:

        enc_slice[0] = "\0";
        dec_slice[0] = "\0";
        text_slice[16] = "\0";
        enc_slice[16] = "\0";
    

    Why do you encode chunks of 15 characters instead of 16?

        memcpy(&text_slice[0], &in[15 * i], 15);
    

    Here is a modified version:

    #include <string.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <openssl/aes.h>
    
    char key[] = "secretkey1234567";
    
    int main() {
        unsigned char text_slice[128];
        unsigned char enc_slice[128];
        unsigned char dec_slice[128];
        unsigned char in[160];
        unsigned char enc_out[160];
        unsigned char dec_out[160];
        
        int i, k = 10;
        for (i = 0; i < 16 * k; i++) {
            in[i] = 'A' + (rand() % 26);
        }
        printf("IN: \"%.160s\"\n", (char *)in);
        
        AES_KEY enc_key, dec_key;
        AES_set_encrypt_key(key, 128, &enc_key);
        AES_set_decrypt_key(key, 128, &dec_key);
        
        for (i = 0; i < k; i++) {
            memcpy(text_slice, &in[16 * i], 16);
            printf("TEXT SLICE: %.16s\n", (char *)text_slice);
            AES_encrypt(text_slice, enc_slice, &enc_key);
            memcpy(&enc_out[16 * i], enc_slice, 16);
        }
        printf("ENC:");
        for (i = 0; i < 16 * k; i++) {
           printf(" %02X\n", enc_out[i]);
        }
        printf("\n");
        for (i = 0; i < k; i++) {
            memcpy(enc_slice, &enc_out[16 * i], 16);
            AES_decrypt(enc_slice, dec_slice, &dec_key);
            printf("Dec slice: %.16s \n", (char *)dec_slice);
            memcpy(&dec_out[16 * i], dec_slice, 16);
        }
        printf("DEC OUT: \"%.160s\"\n", (char *)dec_out);
        return 0;
    }