Defines | Enumerations | Functions

AES encryption (hal_aes)
[nRF24LU1+ HAL]


The nRF24LE1 contains a co-processor for computing an 8 by 8 Galois Field Multiplication with an 8 bits output. This is the polynomial used by AES (Advanced Encryption Standard).

The nRF24LU1 contains a full hardware implementation of the AES algorithm, supporting both encryption and decryption for the modes ECB, CTR, OFB, CFB and CBC.

The AES HAL contains a common interface using the dedicated hardware implementation for the nRF24LU1 and a firmware implementation utilizing the Galois Multiplication co-processor for the nRF24LE1.

Note that for the nRF24LE1 implementation only ECB mode encryption is supported.

Defines

#define _AES_ENABLE_GET_DEC_KEY_

Enumerations

enum  aes_modes_t {
  CBC, CFB, OFB, CTR,
  ECB, CBC, CFB, OFB,
  CTR, ECB
}

Functions

void hal_aes_setup (_Bool decrypt_enable, aes_modes_t mode, uint8_t *keyin, uint8_t *ivin)
void hal_aes_crypt (uint8_t *dest_buf, uint8_t *src_buf)
void hal_aes_get_dec_key (uint8_t *dest_dec_key, uint8_t *src_enc_key)

Define Documentation

#define _AES_ENABLE_GET_DEC_KEY_

Must be defined in order to enable the function aes_get_dec_key()

Definition at line 43 of file hal_aes.h.


Enumeration Type Documentation

Enumerator:
CBC 
CFB 
OFB 
CTR 
ECB 
CBC 
CFB 
OFB 
CTR 
ECB 

Definition at line 46 of file hal_aes.h.


Function Documentation

void hal_aes_setup ( _Bool  decrypt_enable,
aes_modes_t  mode,
uint8_t *  keyin,
uint8_t *  ivin 
)
Remarks:
This interface is common to nRF24LU1+ and nRF24LE1. For nRF24LE1 only ECB mode and encryption has been implemented. Other modes (described below) only apply to the nRF24LU1+ implementation. This is because nRF24LU1 comes with built-in HW support for AES encryption in various modes. nRF24LE1 has only limited support for AES where most of the implemenation is done in SW.

Configures the AES module prior to encrypting/decrypting with aes_crypt(). The parameters reside in memory, thus the function does not need to be run every time aes_crypt() is used.

Parameters:
decrypt_enableselects encrypt or decrypt operation. Possible arguments are:

  • true selects decrypt operation
  • false selects encrypt operation
modeselects AES mode of operation. Possible arguments are:

  • ECB
  • CTR
  • OFB
  • CFB
  • CBC
keyinis a pointer to a 16 byte array containing the key to be used for the cryptographic operation. Passing a zero pointer will leave the previous written key unaltered.
ivinis a pointer to a 16 byte array containing the initialization vector needed for CTR, OFB, CFB and CBC mode of operation. Passing a zero pointer will leave the previous written initialization vector unaltered.
Remarks:

Which key is to be used for the cryptographic operation depends on the selected mode(ECB/CTR/OFB/CFB/CBC) and the direction of operation (encrypt/decrypt). For modes ECB and CBC the decrypt operation is different from the encrypt operation, while for the remaining modes the operation is identical for the two directions. As a result, when using ECB or CBC mode the key needed for decrypting a block of data is different from the key that was used for encrypting the block, while for CTR, OFB and CFB the selected direction of operation does not care and the same key is used for both encryption and decryption.

The function aes_get_dec_key() can be used to aquire the decryption key from the encryption key when using ECB and CFB mode.

The initializtion vector is only loaded internally to the AES engine after one of the following occurences:

  1. A new initializtion vector is passed
  2. Mode of operation is changed
  3. In CBC mode when direction of operation is changed

Definition at line 94 of file hal_aes.c.

{
   if(keyin != NULL)
   {
      aes_keyin_write_buf(keyin, 0, AES_BUF_SIZE);
   }

   if(ivin)
   {
      aes_initvect_write_buf(ivin, 0, AES_BUF_SIZE);
      aes_set_mode(ECB);            // Dummy change of mode in order to load init-vector
      aes_set_mode(CBC);
   }

   if(decrypt)
   {
     AESCS=(AESCS & ~AESCS_E_D_MASK) | DECRYPT<<AESCS_E_D_BIT_POS;
   }
   else
   {
     AESCS=(AESCS & ~AESCS_E_D_MASK) | ENCRYPT<<AESCS_E_D_BIT_POS;
   }

   aes_set_mode(mode);
}
void hal_aes_crypt ( uint8_t *  dest_buf,
uint8_t *  src_buf 
)

Encrypts or decrypts a 128 bit (16 byte) block. The cryptographic operation is configured by using aes_setup().

Parameters:
dest_bufis a pointer to the 16 byte destination array.
src_bufis a pointer to the 16 byte source array.
Remarks:
See also:
hal_aes_setup();

Definition at line 120 of file hal_aes.c.

{
   aes_data_write_buf(src_buf, 0, AES_BUF_SIZE);
   aes_go();
   while(aes_busy());
   aes_data_read_buf(dest_buf, 0, AES_BUF_SIZE);
}
void hal_aes_get_dec_key ( uint8_t *  dest_dec_key,
uint8_t *  src_enc_key 
)

Calculates decryption key from encryption key. For ECB and CBC mode of operation, different keys are used for encryption and decryption. This function calculates the required decryption key for these modes, based on the encryption key.

Parameters:
dest_dec_keyis a pointer to the 16 byte destination array where the calculated encryption key is to be placed.
src_enc_keyis a pointer to the 16 byte source array containing the encryption key from which the decryption key is to be calculated.
Remarks:
Before using this function _AES_ENABLE_GET_DEC_KEY_ must be defined.
See also:
hal_aes_setup(), _AES_ENABLE_GET_DEC_KEY_

Definition at line 128 of file hal_aes.c.

{
   uint8_t index, loop, rcon_int; //lint -esym(644, rcon_int) "variable may not have been initialized"
   for(index=0; index<16; index++)
   {
      output_dec_key[index]=input_enc_key[index];
   }
   for(loop=0; loop<10; loop++)
   {
      if(loop==0)
      {
         rcon_int=1;
      }
      else
      {
         rcon_int=((rcon_int & 0x80) ? (rcon_int<<1) ^ 0x1b : rcon_int<<1); // xtime operation
      }

      output_dec_key[0]^=S[output_dec_key[13]];
      output_dec_key[1]^=S[output_dec_key[14]];
      output_dec_key[2]^=S[output_dec_key[15]];
      output_dec_key[3]^=S[output_dec_key[12]];
      output_dec_key[0] ^= rcon_int;

      for(index=0; index < 12; index++)
      {
         output_dec_key[index+4]^=output_dec_key[index];
      }
   }
}