2

I'm using this library: https://tls.mbed.org/download with an Espressif ESP32. The goal is to encrypt some data using AES-CTR then decrypt the cypher-text back to the original plain-text. I am getting incorrect result after I've decrypted.

Since we're using CTR mode, we don't need to have a separate "decrypt" function; We can just call the encrypt function once to encrypt then call the same function one more time and it should decrypt. At least, that's what most sources say and that was the case with this other implementation: https://github.com/kokke/tiny-AES-c

I tried using the same nonce, same stream-block, different nonces, different stream-blocks, set the key before each of the function calls, etc.

    mbedtls_aes_context aes;
    unsigned char key[16];
    size_t plainText_len = 64;
    unsigned int nc_off = 0;
    unsigned char nonce_counter[16] = {0};
    unsigned char stream_block[16] = {0};
    unsigned char plainText[64] = {0x48, 0x45, 0x4c, 0x4c, 0x4f};
    unsigned char encryptText[64];
    unsigned char decryptText[64];
    memcpy(key, key_128, 16); //key_128 comes from a different file

    //Print Key
    printf("aes Key: \n");
    for(int i = 0; i < 16; i++){
        printf("%x",key[i]);
    }
    printf("\n");

    //Print plain-text
    printf("aes plainText: \n");
    for(int i = 0; i < 5; i++){
        printf("%x",plainText[i]);
    }
    printf("\n");

    esp_aes_init(&aes); //context is initialized
    esp_aes_setkey(&aes, key, 128); //key is associated to context
    esp_aes_crypt_ctr(&aes, plainText_len, &nc_off, nonce_counter, stream_block, plainText, encryptText); //encrypt

    //Print encrypt-text
    printf("aes encryptText: \n");
    for(int i = 0; i < 5; i++){
        printf("%x",encryptText[i]);
    }
    printf("\n");

    esp_aes_crypt_ctr(&aes, plainText_len, &nc_off, nonce_counter, stream_block, encryptText, decryptText); //decrypt

    //Print decrypt-text
    printf("aes decrypt: \n");
    for(int i = 0; i < 5; i++){
        printf("%x",decryptText[i]);
    }
    printf("\n");

After the encrypt function is called a second time the resulting decryptText should be the same as the original plain-text, however, at the moment plainText =/= decryptText.

This is what my monitor is printing:

aes key: 7d3043fb95355e6ccd850ad8debc279
aes plainText: 48454c4c4f
aes encryptText: 852b97da59
aes decryptText: 814268329f

As you can see, I'm missing something that'll properly decrypt the encryptText!

  • 3
    Well, you at least have to reinitialize the cipher context prior to decryption. Behind the scenes there's an IV that increments each block after initialization and it needs to be reset to the value it had at the start of the encryption process. I see lots of security issues here as well, it looks like you're all set up to shoot yourself in the foot. – President James K. Polk Aug 13 '19 at 19:46
  • 1
    I switched to cfb128 and it works; @JamesKPolk what kind of security issues? – phantomBlurrr Aug 13 '19 at 20:45
  • 1
    I'll let someone else answer that if they care to, I don't. – President James K. Polk Aug 13 '19 at 20:50

1 Answers1

0

Since we're using CTR mode, we don't need to have a separate "decrypt" function; We can just call the encrypt function...

I think you are conflating topics. CTR mode does operate the cipher in the forward direction for both encryption and decryption. However, the same sort of symmetry may not exist in the higher level mbedTLS objects.


esp_aes_init(&aes); //context is initialized
esp_aes_setkey(&aes, key, 128); //key is associated to context

esp_aes_crypt_ctr(&aes, plainText_len, &nc_off, nonce_counter, stream_block, plainText, encryptText); //encrypt

// ...

esp_aes_crypt_ctr(&aes, plainText_len, &nc_off, nonce_counter, stream_block, encryptText, decryptText); //decrypt

// ...

esp_aes_crypt_ctr is a define for mbedtls_aes_crypt_ctr. mbedtls_aes_crypt_ctr docs say the function updates both nonce_counter and stream_block. I believe you need to restart both when you want to perform decryption.

Here is one of the mentions of stream_block in the docs. You are not contiuing encryption. You need to restart the parameter.

stream_block - The saved stream block for resuming. This is overwritten by the function. It must be a readable-writeable buffer of 16 Bytes.

But in the bigger picture as was commented by @James... You should probably use mbedTLS the way it was designed to be used rather than trying to take shortcuts.

jww
  • 83,594
  • 69
  • 338
  • 732
  • 1
    thanks for your reply! I tried doing as you mentioned: reset nonce & stream block, but it wasn't working for some reason. I am having trouble understanding you final observation: how am I taking shortcuts? I am following guide from mbed for encrypting. Again, thanks for reply! – phantomBlurrr Aug 14 '19 at 14:02