how to encrypt a string in aes waywith mbedtls?

5k Views Asked by At

We all know that mbedtls library is a very lightweight c library. I want to use the library to encrypt a string. So I have a function like this:

aes_encrypt.h:

#ifndef AES_ENCRYPT_H
#define AES_ENCRYPT_H

#define BOOL int
#define TRUE 1
#define FALSE 0

extern const unsigned char key[16];

BOOL ENC_STR(unsigned char *plain, size_t plain_len, 
             unsigned char *cipher, size_t *cipher_len);
#endif

and the implementation:

const unsigned char KEY[16] = { 0x00, 0x01, 0x02, 0x03,
                                0x04, 0x05, 0x06, 0x07, 
                                0x08, 0x09, 0x0A, 0x0B, 
                                0x0C, 0x0D, 0x0F, 0xA0 };

BOOL ENC_STR(unsigned char *plain, size_t plain_len, unsigned char *cipher, size_t *cipher_len)
{
BOOL ret = FALSE;

// Prepare the cipher context
const mbedtls_cipher_info_t *cipher_info;
mbedtls_cipher_context_t cipher_ctx;
mbedtls_cipher_init(&cipher_ctx);

if ((cipher_info = mbedtls_cipher_info_from_type(AES_PARM)) == NULL)
{
    printf("Cipher Info ERR!\n");
    ret = -1;
    goto EXIT;
}

if ( (ret = mbedtls_cipher_setup(&cipher_ctx, cipher_info)) != 0)
{
    printf("Cipher Setup ERR!\n");
    goto EXIT;
}

if ( (ret = mbedtls_cipher_setkey(&cipher_ctx, KEY, cipher_info->key_bitlen, MBEDTLS_ENCRYPT)) != 0)
{
    printf("Cipher SetKey ERR!\n");
    goto EXIT;
}

// if ( (ret = mbedtls_cipher_set_padding_mode(&cipher_ctx, 1)) != 0) {
//     printf("Cipher SetPadding ERR!\n");
//     goto EXIT;
// }


if ( (ret = mbedtls_cipher_reset(&cipher_ctx)) != 0)
{
    printf("Cipher Reset ERR!\n");
    goto EXIT;
}

// encrypt
if ((ret = mbedtls_cipher_update(&cipher_ctx, plain, plain_len, cipher, cipher_len)) != 0) {
    printf("Cipher Update ERR!\n");
    goto EXIT;
}

EXIT:
    if (ret != TRUE) {
        char buf[1024] = {0};
        mbedtls_strerror(ret, buf, 1024);
        printf("Error Msg:\t%s\n", buf);
    }

    mbedtls_cipher_free(&cipher_ctx);
    return ret;
}

I call the function like bellow:

unsigned char *plain = (unsigned char*)"hello world";
size_t plain_len = 12;
unsigned char cipher[128] = {0};
size_t cipher_len = -1;
printf("the encrypt result is:\t%d\n", ENC_STR(plain, plain_len, cipher, &cipher_len));

And I get the err msg like below:

CIPHER - Decryption of block requires a full block

Can anyone help me out and explain what is the meaning of the error message? Thanks.

3

There are 3 best solutions below

2
On

Explanation:

CIPHER - Decryption of block requires a full block
Can anyone help me out and explain what is the meaning of the error message?

AES is a block cipher it means it is implemented to encrypt 128 bit block at the time. Not more, not less.

So if you have source data shorter than a single block, you will need to use some padding to ensure you prolong your data to a required length.

Generally to encrypt data of any length we use mode of operation. There are some which do not require any padding (CTR, CFB, OFB, ..)

Still your encryption will be far from secure - you will need IV (salt) and authentication tag.

We all know that mbedtls library is a very lightweight c library

apparently the mbedtls already support multiple modes of operations, it's up to you to choose

0
On

You need to complete your crypting with calling of mbedtls_cipher_finish.

The reason to finish comes from need to add padding, what is not done by update. The PKCS7 padding scheme (being used by default) always adds something even if the source data has N * BlockSize length.

https://tls.mbed.org/api/cipher_8h.html#a6678691c02cb3f1322b2179987bfffb2

0
On

You could either encrypt your full buffer using mbedtls_cipher_crypt() , or cipher your buffer in several calls to mbedtls_cipher_update().
To add padding, you should call mbedtls_cipher_set_padding_mode. However, as you can see from the code the default padding scheme is PKCS7 , if MBEDTLS_CIPHER_PADDING_PKCS7 is defined.
According to your code, it seems that you are using AES ECB( you haven't set any IV ). AES ECB does NOT support padding, and for security reasons, it accepts only AES BLOCK size of input (16 bytes). As mentioned below, you should consider using AES CBC for your operation ,as AES ECB is not secure for inputs more than 16 bytes, and your functions should be as generic as possible to support large strings as well.