This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

NRF51822 AES HW module clarification

hi,

I was reading documentation and forum but failed to get a clear picture how AES module work. So far my understanding is:

There are two ways to access AES either in Softdevice using sd_ecb_block_encrypt or using directly from code nrf_ecb_crypt

However, no decryption is provided at all, which meant that if I want to have application layer security I have to implement software AES? This, however, raises a question, there has to be decryption functionality since BLE LL is encrypted... Why is it not provided by drivers?

The other, not clear, specifications: the sd_ecb_block_encrypt may be delayed if BLE is transmitting. Is this the case for nrf_ecb_crypt too? What does "delayed" mean? Will the function return later or it will return false and a user has to retry him self?

cheers!

  • AES is a symmetric algorithm where the same key is used for both encryption and decryption, but it has a forward transform (encryption) and an inverse transform (decryption). The nrf51 ECB block only provides support for the forward transform.

    However, you can still use the ECB hardware for stream decryption as long as you use a chaining mode that only relies on the forward transform.

    See csrc.nist.gov/.../sp800-38a.pdf starting on page 10.

    CBC (cipher block chaining) requires both the forward and inverse transforms, but CFB (cipher feedback mode), OFB (output feedback mode) and CTR (counter mode) only use the forward transform.

    I use the AES hardware to generate a OFB keystream for decryption in my bootloader DFU.

    sd_ecb_block_encrypt() blocks until the hardware is available, so you just call it. You are sharing the AES hardware with the stack (if you are using encryption) so your encryption operation may be delayed until the AES block is available.

    To setup the keys you initialize the nrf_ecb_hal_data_t with a key and an initialization vector (placed in the cleartext field) and set keyStreamIdx to 0.

    nrf_ecb_hal_data_t ecb __aligned(4);
    uin8_t keyStreamIdx;
    uint8_t aesKey[SOC_ECB_KEY_LENGTH];
    uint8_t aesIV[SOC_ECB_KEY_LENGTH];   
    
    /* The first round of the OFB encrypts the IV with the AES key */
    keyStreamIdx = 0;
    memset(ecb.ciphertext, 0xCD, sizeof(ecb.ciphertext)); // not needed
    memcpy(ecb.key,       aesKey, sizeof(ecb.key));
    memcpy(ecb.cleartext, aesIV,  sizeof(ecb.cleartext));
    

    In OFB, the AES block is effectively used as a pseudo random number generator. This function provides a stream of 32 bit numbers:

    /* keyStream: Return next word in output feedback sequence */
    static uint32_t keyStream(void)
    {
        uint32_t key;
         
        /* do we need more key data? */
        if (keyStreamIdx == 0)
        {
            /* generate more key data */
            sd_ecb_block_encrypt(&ecb);
            
            /* cleartext for next round is ciphertext from this round */
            memcpy(ecb.cleartext, ecb.ciphertext, sizeof(ecb.cleartext));
        }
        
        key = ((uint32_t*)ecb.ciphertext)[keyStreamIdx++];
        if (keyStreamIdx == sizeof(ecb.ciphertext) / 4)   
            keyStreamIdx = 0; // will need more data next round 
        
        return key;
    }
    

    The actual decryption is just a xor:

       uint32_t data[...];
       int length = sizeof(data);
    
        /* decryption is just an xor using a key stream generated 
         * by AES encyption hardware. 
         */
        for (int w = 0; w < length / sizeof(uint32_t); w++)
            data[w] ^= keyStream();
    

    In my bootloader the data being encrypted is always a multiple of 4 bytes and the source pointer is always 32 bit aligned. If you can't guarantee the alignment/size you could also do this a byte at a time.

    To generate OFB encrypted data I use openssl:

    openssl enc -aes-128-ofb -nopad -nosalt -e -K {key} -iv {iv} < input > output
    

    Keep in mind that it is very easy to misuse encryption. The underlying algorithms may be sound but it is often trivial to miss-use them.

    In the case of OFB or CTR, an attacker can modify any data that is known prior to encryption by XORing in the known data and then XORing in different data. As a result encryption alone is not sufficient, you also want to verify that the correct data was decrypted. I am signing the decrypted data with a SHA1. The SHA1, AES key and AES IV are encrypted using RSA-512 and decrypted on the device using a public key that is written at manufacturing time. The bootloader will refuse to activate a new firmware image if the SHA1 is not correct and encrypting the SHA1 requires access to the private key (which obviously is not stored on the device).

    If you google for info on OFB you will see that CTR is recommended over OFB because of an issue known as 'short cycle'. In my case I'm decrypting at most 2MB per key/iv pair, the chance of hitting a short cycle with a random key/iv pair in under 2MB is in the noise.

    It would be more secure to use CFB over OFB/CTR, but I didn't want to deal with the extra round of buffering (the data comes in 20 bytes at a time, but CFB operates on 16 bytes at a time).

    I'm using SHA1 over SHA256 because it the code was >256bytes smaller and SHA1 is plenty of coverage for a BLE device. I'm using RSA-512 because it was the smallest key size that could encrypt my 56 byte payload (16 byte AES key, 16 byte IV, 20 byte SHA1).

  • Hi,

    Thanks for walking through!

    It is still unclear for me what is the difference between nrf_ecb_crypt and sd_ecb_block_encrypt. I dont see either your initializing aes.

    Moreover, if the hardware AES is shared, does nrf51 set moves the keys back and forth or I have to set key every time I want to use encryption?

  • The sd_ecb_block_enrycpt will do the same as nrf_ecb_crypt, it just does it through the softdevice (sd).

  • THANKS for the detailed answer and example code. Are you doing the PK RSA decryption in software, and which sample code / library did you implement to do this?

  • Since you're using MAC-then-encrypt, I hope you're adequately defending against the padding oracle attack (en.wikipedia.org/.../Padding_oracle_attack). It is generally recommended to use encrypt-then-MAC.

Related