Topic: [SOLVED] IV being changed by AesSetKey

Hi all, this is my first post.

I've got a little project I want to use wolfcrypt for, and before getting started on the production system I just threw together a bit of proof-of-concept code. Then I got unexpected results so I added a bunch of print lines for debug purposes, and here's the code as it stands:

#include <stdio.h>
#include <wolfssl/wolfcrypt/aes.h>

size_t padLength(size_t plainLength){
    size_t numBlocks = plainLength / AES_BLOCK_SIZE;
    return (numBlocks+1) * AES_BLOCK_SIZE;
}

void printBytes(byte *array, size_t length){
    for (size_t i=0; i<length; ++i){
        printf("%02X ", array[i]);
    }
}

size_t unpadLength(byte *array, size_t length){
    return length-(array[length-1]);
}

int main() {
    int error;
    byte key[] = "1234567890abcdef01234567";
    byte iv[] = "1234567890abcdef";
    Aes aesEncrypt;
    Aes aesDecrypt;
    printf("\nIV before SetKey(Encrypt): ");
    printBytes(iv, AES_BLOCK_SIZE);
    error = wc_AesSetKey(&aesEncrypt, key, (word32)strlen((char *)key), iv, AES_ENCRYPTION);
    if (error){
        printf("\nEncrypt set key failed with error: %d\n", error);
    }
    printf("\nIV  after SetKey(Encrypt): ");
    printBytes(iv, AES_BLOCK_SIZE);
    printf("\n aesEncrypt.reg  contents: ");
    printBytes((byte *) aesEncrypt.reg, AES_BLOCK_SIZE);
    error = wc_AesSetKey(&aesDecrypt, key, (word32)strlen((char *)key), iv, AES_DECRYPTION);
    if (error){
        printf("\nDecrypt set key failed with error: %d\n", error);
    }
    printf("\nIV  after SetKey(Decrypt): ");
    printBytes(iv, AES_BLOCK_SIZE);
    printf("\n aesDecrypt.reg  contents: ");
    printBytes((byte *) aesDecrypt.reg, AES_BLOCK_SIZE);
    byte plain[] = "AAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB";
    size_t plainLength = sizeof(plain);
    size_t paddedLength = padLength(plainLength);
    byte padded[paddedLength];
    byte padding = (byte)(paddedLength-plainLength);
    memcpy(padded, plain, plainLength);
    for (size_t i=plainLength; i<paddedLength; ++i){
        padded[i]=padding;
    }
    byte cipher[paddedLength];
    error = wc_AesCbcEncrypt(&aesEncrypt, cipher, padded, (word32)paddedLength);
    if (error){
        printf("\nEncryption failed with error: %d\n", error);
    }
    byte plain2[paddedLength];
    error = wc_AesCbcDecrypt(&aesDecrypt, plain2, cipher, (word32)paddedLength);
    if (error){
        printf("\nDecryption failed with error: %d\n", error);
    }
    printf("\nPlain1: ");
    printBytes(plain,sizeof(plain));
    printf("\n%s\nPadded: ",plain);
    printBytes(padded,paddedLength);
    printf("\nCipher: ");
    printBytes(cipher, paddedLength);
    printf("\nPlain2: ");
    printBytes(plain2, unpadLength(plain2, paddedLength));
    printf("\n%s\n",plain2);
    return 0;
}

When I run that code, I get the following output:

IV before SetKey(Encrypt): 31 32 33 34 35 36 37 38 39 30 61 62 63 64 65 66 
IV  after SetKey(Encrypt): 31 32 33 34 00 00 00 00 39 30 61 62 63 64 65 66 
 aesEncrypt.reg  contents: 31 32 33 34 00 00 00 00 39 30 61 62 63 64 65 66 
IV  after SetKey(Decrypt): 31 32 33 34 00 00 00 00 39 30 61 62 63 64 65 66 
 aesDecrypt.reg  contents: 31 32 33 34 00 00 00 00 39 30 61 62 63 64 65 66 
Plain1: 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 00 
AAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
Padded: 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 00 05 05 05 05 05 
Cipher: 8A D4 F6 7D 53 E1 FA 88 36 9C 83 00 D8 A5 1A 60 43 AB 87 03 FE E6 1B C0 44 DF CD 71 18 D8 D7 93 C9 E5 66 48 C9 16 12 AF 07 A7 43 AF 98 95 2D 62 AA 44 FA 04 96 CE E1 73 F1 04 30 B7 CC A9 59 75 
Plain2: 41 41 41 41 74 77 76 79 41 41 41 41 41 41 41 41 41 41 41 41 74 77 76 79 42 42 42 42 42 42 42 42 42 42 42 42 77 74 75 7A 42 42 42 42 42 42 42 42 42 42 42 42 77 74 75 7A 42 42 00 
AAAAtwvyAAAAAAAAAAAAtwvyBBBBBBBBBBBBwtuzBBBBBBBBBBBBwtuzBB

When I moved things around so the decrypt struct gets configured before the encrypt chunk and ran it again I got:

IV before SetKey(Decrypt): 31 32 33 34 35 36 37 38 39 30 61 62 63 64 65 66 
IV  after SetKey(Decrypt): 31 32 33 34 35 36 37 38 39 30 61 62 63 64 65 66 
 aesDecrypt.reg  contents: 31 32 33 34 35 36 37 38 39 30 61 62 63 64 65 66 
IV  after SetKey(Encrypt): 31 32 33 34 00 00 00 00 39 30 61 62 63 64 65 66 
 aesEncrypt.reg  contents: 31 32 33 34 00 00 00 00 39 30 61 62 63 64 65 66 
Plain1: 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 00 
AAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
Padded: 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 00 05 05 05 05 05 
Cipher: D2 08 09 0A AB 5B 27 D4 B4 17 4D 55 BD EE 45 44 40 4C F7 92 D1 D2 7D B4 FD 9D 84 DF 67 F4 9E E6 89 60 8E 63 84 8F 72 F3 1E 46 48 8D C0 D1 DF A5 1D BC CC AA 99 EA 5F B3 DA A8 93 8C 43 05 32 9B 
Plain2: 41 41 41 41 74 77 76 79 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 00 
AAAAtwvyAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB

So... AesSetKey is zeroing the second word of the IV if the last argument is AES_ENCRYPTION. Any ideas why this is happening or what I should do differently?

Share

Re: [SOLVED] IV being changed by AesSetKey

I added another local variable as a spacer, like this:

    byte iv[] = "1234567890abcdef";
    byte spacer[32] = {};
    Aes aesEncrypt;

... and now the iv is not being overwritten.

The locations of these variables are found by counting backwards from the highest available address in the memory space, (I checked addresses using gdb), so it would appear that wc_AesSetKey(&aesEncrypt) is writing four bytes of zeroes starting four bytes past the end of the aesEncrypt struct.

This behaviour was seen in the package from the Debian Squeezy (9.0) official repositories and in Archlinux using an AUR build that was current a couple of days ago.

Share

Re: [SOLVED] IV being changed by AesSetKey

Hi Teaspoon,

Thank you for contacting wolfSSL, I'll be looking into your report today to see what may be happening. I will be in touch if I have any questions on your report.


Best Regards,

Kaleb

Re: [SOLVED] IV being changed by AesSetKey

Hi Teaspoon,

Could you tell me more about your project and end goals? What platform are you working on, what architecture?
Have you run the wolfcrypt test application to confirm the underlying crypto is working on your platform?

( <wolf-root>/wolfcrypt/test/test.c )

I ask because I literally just copy/pasted your code, compiled it and my result was:

kalebs-MBP:support-forums-IV-being-changed-3-apr-2016 khimes$ ./run 

IV before SetKey(Encrypt): 31 32 33 34 35 36 37 38 39 30 61 62 63 64 65 66 
IV  after SetKey(Encrypt): 31 32 33 34 35 36 37 38 39 30 61 62 63 64 65 66 
 aesEncrypt.reg  contents: 31 32 33 34 35 36 37 38 39 30 61 62 63 64 65 66 
IV  after SetKey(Decrypt): 31 32 33 34 35 36 37 38 39 30 61 62 63 64 65 66 
 aesDecrypt.reg  contents: 31 32 33 34 35 36 37 38 39 30 61 62 63 64 65 66 
Plain1: 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 00 
AAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
Padded: 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 00 05 05 05 05 05 
Cipher: 8A D4 F6 7D 53 E1 FA 88 36 9C 83 00 D8 A5 1A 60 FB 26 CC A5 22 46 AA F2 2E 9A 5A 40 9E AD EE 7B ED 35 48 36 9E D5 4D E3 7B CD 5A 1D 3D 85 A7 70 DE 86 3C 27 61 0E 00 14 B2 69 34 03 3A 2C 25 0E 
Plain2: 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 00 
AAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB

I also noticed you did not include <wolfssl/options.h> or <wolfssl/wolfcrypt/settings.h> in your project. You should include the same settings file that you used to configure wolfSSL library so your application and the library are not in conflict. If the library and the application linking against the library are in conflict you may experience undefined behavior.

Let me know some more details so we can narrow down why you are seeing this result on your platform/device.


Warm Regards,

Kaleb

5 (edited by Teaspoon 2017-04-05 03:12:14)

Re: [SOLVED] IV being changed by AesSetKey

Thanks for getting back to me, Kaleb.

I'm working on Linux on x86_64 here; a laptopt with a Core i7-3720QM running ArchLinux and a VMWare guest with a Xeon E5-2630 rimmomg Debian 9 (Stretch/Testing).

I made a variant that included wc_encrypt.h and called wc_AesCbcEncryptWithKey (and its Decrypt sibling, of course) and everything worked as expected there.

I hadn't realised that the extra includes were relevant... I believe I included them to start with, but I was working in the CLion IDE and may have let it run its "remove unused imports" code cleanup step. Including woflssl/options.h in before aes.h has got the above sample code working as expected.

Thanks!

P.S. In case you're curious, the longer-term project is to develop a StorageArea plugin for Orthanc that will have its image and other data files encrypted as they're written to disk and decrypted as they're retrieved.

Share

Re: [SOLVED] IV being changed by AesSetKey

Hi Teaspoon,

We are pleased to hear you got it resolved by including options.h header file. Yes unfortunately that is very important, the library can be configured differently than the application which can result in undefined behavior as you experienced.

Thanks for the details on your project! Of course we are curios and always love to hear about the exciting ways or embedded TLS/SSL library is being used! I've looked up the Orthanc website, it looks like this is an open-source storage solution for MRI and other medical data, very exciting!! Let us know how the project comes along and of course if you have any other questions please reach out any time. We are always happy to help in any way we can!


Best Regards,

Kaleb