CC26xx Driver Library
[aes.h] Advanced Encryption Standard

Functions

void AESStartDMAOperation (const uint8_t *channel0Addr, uint32_t channel0Length, uint8_t *channel1Addr, uint32_t channel1Length)
 Start a crypto DMA operation. More...
 
void AESSetInitializationVector (const uint32_t *initializationVector)
 Write the initialization vector (IV) to the crypto module. More...
 
void AESWriteCCMInitializationVector (const uint8_t *nonce, uint32_t nonceLength)
 Generate and load the initialization vector for a CCM operation. More...
 
uint32_t AESReadTag (uint8_t *tag, uint32_t tagLength)
 Read the tag out from the crypto module. More...
 
uint32_t AESVerifyTag (const uint8_t *tag, uint32_t tagLength)
 Verifies the provided tag against calculated one. More...
 
uint32_t AESWriteToKeyStore (const uint8_t *aesKey, uint32_t aesKeyLength, uint32_t keyStoreArea)
 Transfer a key from main memory to a key area within the key store. More...
 
uint32_t AESReadFromKeyStore (uint32_t keyStoreArea)
 Transfer a key from key store area to the internal buffers within the hardware module. More...
 
uint32_t AESWaitForIRQFlags (uint32_t irqFlags)
 Poll the interrupt status register and clear when done. More...
 
void AESConfigureCCMCtrl (uint32_t nonceLength, uint32_t macLength, bool encrypt)
 Configure AES engine for CCM operation. More...
 
static void AESInvalidateKey (uint32_t keyStoreArea)
 Invalidate a key in the key store. More...
 
static void AESSelectAlgorithm (uint32_t algorithm)
 Select type of operation. More...
 
static void AESSetCtrl (uint32_t ctrlMask)
 Set up the next crypto module operation. More...
 
static void AESSetDataLength (uint32_t length)
 Specify length of the crypto operation. More...
 
static void AESSetAuthLength (uint32_t length)
 Specify the length of the additional authentication data (AAD). More...
 
static void AESReset (void)
 Reset the accelerator and cancel ongoing operations. More...
 
static void AESIntEnable (uint32_t intFlags)
 Enable individual crypto interrupt sources. More...
 
static void AESIntDisable (uint32_t intFlags)
 Disable individual crypto interrupt sources. More...
 
static uint32_t AESIntStatusMasked (void)
 Get the current masked interrupt status. More...
 
static uint32_t AESIntStatusRaw (void)
 Get the current raw interrupt status. More...
 
static void AESIntClear (uint32_t intFlags)
 Clear crypto interrupt sources. More...
 
static void AESIntRegister (void(*handlerFxn)(void))
 Register an interrupt handler for a crypto interrupt. More...
 
static void AESIntUnregister (void)
 Unregister an interrupt handler for a crypto interrupt. More...
 

Detailed Description

Introduction

The AES (advanced encryption standard) API provides access to the AES and key store functionality of the crypto core. The SHA2 accelerator is also contained within the crypto core. Hence, only one of SHA2 and AES may be used at the same time. This module offers hardware acceleration for several protocols using the AES block cypher. The protocols below are supported by the hardware. The driverlib documentation only explicitly references the most commonly used ones.

The key store is a section of crypto memory that is only accessible to the crypto module and may be written to by the application via the crypto DMA. It is not possible to read from the key store to main memory. Thereby, it is not possible to compromise the key should the application be hacked if the original key in main memory was overwritten already.

The crypto core does not have retention and all configuration settings and keys in the keystore are lost when going into standby or shutdown. The typical security advantages a key store offers are not available in these low power modes as the key must be saved in regular memory to reload it after going into standby or shutdown. Consequently, the keystore primarily serves as an interface to the AES accelerator.

Function Documentation

void AESConfigureCCMCtrl ( uint32_t  nonceLength,
uint32_t  macLength,
bool  encrypt 
)

Configure AES engine for CCM operation.

Parameters
[in]nonceLengthLength of the nonce. Must be <= 14.
[in]macLengthLength of the MAC. Must be <= 16.
[in]encryptWhether to set up an encrypt or decrypt operation.
  • true: encrypt
  • false: decrypt
Returns
None
339 {
340  uint32_t ctrlVal = 0;
341 
342  ctrlVal = ((15 - nonceLength - 1) << CRYPTO_AESCTL_CCM_L_S);
343  if ( macLength >= 2 ) {
344  ctrlVal |= ((( macLength - 2 ) >> 1 ) << CRYPTO_AESCTL_CCM_M_S );
345  }
346  ctrlVal |= CRYPTO_AESCTL_CCM |
350  ctrlVal |= encrypt ? CRYPTO_AESCTL_DIR : 0;
351 
352  AESSetCtrl(ctrlVal);
353 }
static void AESSetCtrl(uint32_t ctrlMask)
Set up the next crypto module operation.
Definition: aes.h:527

Here is the call graph for this function:

static void AESIntClear ( uint32_t  intFlags)
inlinestatic

Clear crypto interrupt sources.

The specified crypto interrupt sources are cleared, so that they no longer assert. This function must be called in the interrupt handler to keep the interrupt from being recognized again immediately upon exit.

Note
Due to write buffers and synchronizers in the system it may take several clock cycles from a register write clearing an event in the module until the event is actually cleared in the NVIC of the system CPU. It is recommended to clear the event source early in the interrupt service routine (ISR) to allow the event clear to propagate to the NVIC before returning from the ISR.
Parameters
[in]intFlagsis a bit mask of the interrupt sources to be cleared.
Returns
None
716 {
717  // Check the arguments.
718  ASSERT((intFlags & AES_DMA_IN_DONE) ||
719  (intFlags & AES_RESULT_RDY));
720 
721  // Clear the requested interrupt sources,
722  HWREG(CRYPTO_BASE + CRYPTO_O_IRQCLR) = intFlags;
723 }
#define ASSERT(expr)
Definition: debug.h:73
#define AES_RESULT_RDY
Definition: aes.h:108
#define AES_DMA_IN_DONE
Definition: aes.h:107
static void AESIntDisable ( uint32_t  intFlags)
inlinestatic

Disable individual crypto interrupt sources.

This function disables the indicated crypto interrupt sources. Only the sources that are enabled can be reflected to the processor interrupt. Disabled sources have no effect on the processor.

Parameters
[in]intFlagsis the bitwise OR of the interrupt sources to be enabled.
Returns
None
643 {
644  // Check the arguments.
645  ASSERT((intFlags & AES_DMA_IN_DONE) ||
646  (intFlags & AES_RESULT_RDY));
647 
648  // Disable the specified interrupts.
649  HWREG(CRYPTO_BASE + CRYPTO_O_IRQEN) &= ~intFlags;
650 }
#define ASSERT(expr)
Definition: debug.h:73
#define AES_RESULT_RDY
Definition: aes.h:108
#define AES_DMA_IN_DONE
Definition: aes.h:107
static void AESIntEnable ( uint32_t  intFlags)
inlinestatic

Enable individual crypto interrupt sources.

This function enables the indicated crypto interrupt sources. Only the sources that are enabled can be reflected to the processor interrupt. Disabled sources have no effect on the processor.

Parameters
[in]intFlagsis the bitwise OR of the interrupt sources to be enabled.
Returns
None
615 {
616  // Check the arguments.
617  ASSERT((intFlags & AES_DMA_IN_DONE) ||
618  (intFlags & AES_RESULT_RDY));
619 
620  // Using level interrupt.
622 
623  // Enable the specified interrupts.
624  HWREG(CRYPTO_BASE + CRYPTO_O_IRQEN) |= intFlags;
625 }
#define ASSERT(expr)
Definition: debug.h:73
#define AES_RESULT_RDY
Definition: aes.h:108
#define AES_DMA_IN_DONE
Definition: aes.h:107
static void AESIntRegister ( void(*)(void)  handlerFxn)
inlinestatic

Register an interrupt handler for a crypto interrupt.

This function does the actual registering of the interrupt handler. This function enables the global interrupt in the interrupt controller; specific crypto interrupts must be enabled via AESIntEnable(). It is the interrupt handler's responsibility to clear the interrupt source.

Parameters
handlerFxnis a pointer to the function to be called when the crypto interrupt occurs.
Returns
None
See also
IntRegister() for important information about registering interrupt handlers.
744 {
745  // Register the interrupt handler.
746  IntRegister(INT_CRYPTO_RESULT_AVAIL_IRQ, handlerFxn);
747 
748  // Enable the crypto interrupt.
749  IntEnable(INT_CRYPTO_RESULT_AVAIL_IRQ);
750 }
void IntRegister(uint32_t ui32Interrupt, void(*pfnHandler)(void))
Registers a function as an interrupt handler in the dynamic vector table.
Definition: interrupt.c:153
void IntEnable(uint32_t ui32Interrupt)
Enables an interrupt or system exception.
Definition: interrupt.c:283

Here is the call graph for this function:

static uint32_t AESIntStatusMasked ( void  )
inlinestatic

Get the current masked interrupt status.

This function returns the masked interrupt status of the crypto module.

Returns
Returns the status of the masked lines when enabled:
664 {
665  uint32_t mask;
666 
667  // Return the masked interrupt status
668  mask = HWREG(CRYPTO_BASE + CRYPTO_O_IRQEN);
669  return(mask & HWREG(CRYPTO_BASE + CRYPTO_O_IRQSTAT));
670 }
static uint32_t AESIntStatusRaw ( void  )
inlinestatic

Get the current raw interrupt status.

This function returns the raw interrupt status of the crypto module. It returns both the status of the lines routed to the NVIC as well as the error flags.

Returns
Returns the raw interrupt status:
689 {
690  // Return either the raw interrupt status
691  return(HWREG(CRYPTO_BASE + CRYPTO_O_IRQSTAT));
692 }
static void AESIntUnregister ( void  )
inlinestatic

Unregister an interrupt handler for a crypto interrupt.

This function does the actual unregistering of the interrupt handler. It clears the handler called when a crypto interrupt occurs. This function also masks off the interrupt in the interrupt controller so that the interrupt handler no longer is called.

Returns
None
See also
IntRegister() for important information about registering interrupt handlers.
768 {
769  //
770  // Disable the interrupt.
771  //
772  IntDisable(INT_CRYPTO_RESULT_AVAIL_IRQ);
773 
774  //
775  // Unregister the interrupt handler.
776  //
777  IntUnregister(INT_CRYPTO_RESULT_AVAIL_IRQ);
778 }
void IntUnregister(uint32_t ui32Interrupt)
Unregisters an interrupt handler in the dynamic vector table.
Definition: interrupt.c:189
void IntDisable(uint32_t ui32Interrupt)
Disables an interrupt or system exception.
Definition: interrupt.c:327

Here is the call graph for this function:

static void AESInvalidateKey ( uint32_t  keyStoreArea)
inlinestatic

Invalidate a key in the key store.

Parameters
[in]keyStoreAreais the entry in the key store to invalidate. This permanently deletes the key from the key store.
Returns
None

Referenced by AESWriteToKeyStore().

477 {
478  ASSERT((keyStoreArea == AES_KEY_AREA_0) ||
479  (keyStoreArea == AES_KEY_AREA_1) ||
480  (keyStoreArea == AES_KEY_AREA_2) ||
481  (keyStoreArea == AES_KEY_AREA_3) ||
482  (keyStoreArea == AES_KEY_AREA_4) ||
483  (keyStoreArea == AES_KEY_AREA_5) ||
484  (keyStoreArea == AES_KEY_AREA_6) ||
485  (keyStoreArea == AES_KEY_AREA_7));
486 
487  // Clear any previously written key at the key location
488  HWREG(CRYPTO_BASE + CRYPTO_O_KEYWRITTENAREA) = (0x00000001 << keyStoreArea);
489 }
#define AES_KEY_AREA_7
Definition: aes.h:163
#define AES_KEY_AREA_5
Definition: aes.h:161
#define AES_KEY_AREA_6
Definition: aes.h:162
#define AES_KEY_AREA_4
Definition: aes.h:160
#define AES_KEY_AREA_0
Definition: aes.h:156
#define ASSERT(expr)
Definition: debug.h:73
#define AES_KEY_AREA_1
Definition: aes.h:157
#define AES_KEY_AREA_3
Definition: aes.h:159
#define AES_KEY_AREA_2
Definition: aes.h:158
uint32_t AESReadFromKeyStore ( uint32_t  keyStoreArea)

Transfer a key from key store area to the internal buffers within the hardware module.

The function polls until the transfer is complete.

Parameters
[in]keyStoreAreaThe key store area to transfer the key from. When using 256-bit keys, either of the occupied key areas may be specified to load the key. There is no need to specify the length of the key here as the key store keeps track of how long a key associated with any valid key area is and where is starts.
Returns
Returns a status code depending on the result of the transfer. When specifying a keyStoreArea value without a valid key in it an error is returned. If there was an error in the read process itself, an error is returned. Otherwise, a success code is returned.
See also
AESWriteToKeyStore
236 {
237  // Check the arguments.
238  ASSERT((keyStoreArea == AES_KEY_AREA_0) ||
239  (keyStoreArea == AES_KEY_AREA_1) ||
240  (keyStoreArea == AES_KEY_AREA_2) ||
241  (keyStoreArea == AES_KEY_AREA_3) ||
242  (keyStoreArea == AES_KEY_AREA_4) ||
243  (keyStoreArea == AES_KEY_AREA_5) ||
244  (keyStoreArea == AES_KEY_AREA_6) ||
245  (keyStoreArea == AES_KEY_AREA_7));
246 
247  // Check if there is a valid key in the specified keyStoreArea
248  if (!(HWREG(CRYPTO_BASE + CRYPTO_O_KEYWRITTENAREA) & (1 << keyStoreArea))) {
250  }
251 
252  // Enable keys to read (e.g. Key 0).
253  HWREG(CRYPTO_BASE + CRYPTO_O_KEYREADAREA) = keyStoreArea;
254 
255  // Wait until key is loaded to the AES module.
256  // We cannot simply poll the IRQ status as only an error is communicated through
257  // the IRQ status and not the completion of the transfer.
258  do {
259  CPUdelay(1);
260  }
262 
263  // Check for keyStore read error.
265  return AES_KEYSTORE_ERROR;
266  }
267  else {
268  return AES_SUCCESS;
269  }
270 }
#define AES_KEY_AREA_7
Definition: aes.h:163
#define AES_SUCCESS
Definition: aes.h:121
#define AES_KEYSTORE_AREA_INVALID
Definition: aes.h:123
#define AES_KEY_AREA_5
Definition: aes.h:161
#define AES_KEYSTORE_ERROR
Definition: aes.h:122
#define AES_KEY_AREA_6
Definition: aes.h:162
#define AES_KEY_AREA_4
Definition: aes.h:160
#define AES_KEY_AREA_0
Definition: aes.h:156
#define ASSERT(expr)
Definition: debug.h:73
#define AES_KEY_AREA_1
Definition: aes.h:157
#define AES_KEY_AREA_3
Definition: aes.h:159
void CPUdelay(uint32_t ui32Count)
Provide a small non-zero delay using a simple loop counter.
Definition: cpu.c:343
#define AES_KEY_AREA_2
Definition: aes.h:158

Here is the call graph for this function:

uint32_t AESReadTag ( uint8_t *  tag,
uint32_t  tagLength 
)

Read the tag out from the crypto module.

This function copies the tagLength bytes from the tag calculated by the crypto module in CCM, GCM, or CBC-MAC mode to tag.

Parameters
[out]tagPointer to an array of tagLength bytes.
[in]tagLengthNumber of bytes to copy to tag.
Returns
Returns a status code depending on the result of the transfer.

Referenced by AESVerifyTag().

278 {
279  // The intermediate array is used instead of a caller-provided one
280  // to enable a simple API with no unintuitive alignment or size requirements.
281  // This is a trade-off of stack-depth vs ease-of-use that came out on the
282  // ease-of-use side.
283  uint32_t computedTag[AES_BLOCK_SIZE / sizeof(uint32_t)];
284 
285  // Wait until the computed tag is ready.
287 
288  // Read computed tag out from the HW registers
289  // Need to read out all 128 bits in four reads to correctly clear CRYPTO_AESCTL_SAVED_CONTEXT_RDY flag
290  computedTag[0] = HWREG(CRYPTO_BASE + CRYPTO_O_AESTAGOUT0);
291  computedTag[1] = HWREG(CRYPTO_BASE + CRYPTO_O_AESTAGOUT1);
292  computedTag[2] = HWREG(CRYPTO_BASE + CRYPTO_O_AESTAGOUT2);
293  computedTag[3] = HWREG(CRYPTO_BASE + CRYPTO_O_AESTAGOUT3);
294 
295  memcpy(tag, computedTag, tagLength);
296 
297  return AES_SUCCESS;
298 }
#define AES_SUCCESS
Definition: aes.h:121
#define AES_BLOCK_SIZE
Definition: aes.h:136
static void AESReset ( void  )
inlinestatic

Reset the accelerator and cancel ongoing operations.

Returns
None
595 {
596  HWREG(CRYPTO_BASE + CRYPTO_O_SWRESET) = 0x00000001;
597 }
static void AESSelectAlgorithm ( uint32_t  algorithm)
inlinestatic

Select type of operation.

Parameters
[in]algorithmFlags that specify which type of operation the crypto module shall perform. The flags are mutually exclusive.
Returns
None
506 {
507  ASSERT((algorithm == AES_ALGSEL_AES) ||
508  (algorithm == AES_ALGSEL_AES | AES_ALGSEL_TAG) ||
509  (algorithm == AES_ALGSEL_KEY_STORE));
510 
511  HWREG(CRYPTO_BASE + CRYPTO_O_ALGSEL) = algorithm;
512 }
#define AES_ALGSEL_AES
Definition: aes.h:144
#define AES_ALGSEL_KEY_STORE
Definition: aes.h:145
#define ASSERT(expr)
Definition: debug.h:73
#define AES_ALGSEL_TAG
Definition: aes.h:146
static void AESSetAuthLength ( uint32_t  length)
inlinestatic

Specify the length of the additional authentication data (AAD).

Despite specifying it here, the crypto DMA must still be set up with the correct AAD length.

Parameters
[in]lengthSpecifies how long the AAD is in a CCM operation. In CCM mode, set this to 0 if no AAD is required. If set to 0, AESWriteDataLength() must be set to >0. Range depends on the mode:
  • ECB: Do not call.
  • CBC: [0]
  • CBC-MAC: [0]
  • CCM: [0, sizeof(RAM)]
Returns
None
See also
AESWriteDataLength
582 {
583  HWREG(CRYPTO_BASE + CRYPTO_O_AESAUTHLEN) = length;
584 }
static void AESSetCtrl ( uint32_t  ctrlMask)
inlinestatic

Set up the next crypto module operation.

The function uses a bitwise OR of the fields within the CRYPTO_O_AESCTL register. The relevant field names have the format:

  • CRYPTO_AESCTL_[field name]
Parameters
[in]ctrlMaskSpecifies which register fields shall be set.
Returns
None

Referenced by AESConfigureCCMCtrl().

528 {
529  HWREG(CRYPTO_BASE + CRYPTO_O_AESCTL) = ctrlMask;
530 }
static void AESSetDataLength ( uint32_t  length)
inlinestatic

Specify length of the crypto operation.

Despite specifying it here, the crypto DMA must still be set up with the correct data length.

Parameters
[in]lengthData length in bytes. If this value is set to 0, only authentication of the AAD is performed in CCM-mode and AESWriteAuthLength() must be set to >0. Range depends on the mode:
  • ECB: [16]
  • CBC: [1, sizeof(RAM)]
  • CBC-MAC: [1, sizeof(RAM)]
  • CCM: [0, sizeof(RAM)]
Returns
None
See also
AESWriteAuthLength
555 {
556  HWREG(CRYPTO_BASE + CRYPTO_O_AESDATALEN0) = length;
557  HWREG(CRYPTO_BASE + CRYPTO_O_AESDATALEN1) = 0;
558 }
void AESSetInitializationVector ( const uint32_t *  initializationVector)

Write the initialization vector (IV) to the crypto module.

Depending on the mode of operation, the tag must be constructed differently:

  • CBC: No special care must be taken. Any 128-bit IV (initialization vector) will suffice.
  • CBC-MAC: IV's must be all 0's.
  • CCM: Only 12 and 13 byte IV's are permitted. See code below for formatting.
    1 uint8_t initVectorLength = 12; // Could also be 13
    2 
    3 union {
    4  uint32_t word[4];
    5  uint8_t byte[16];
    6 } initVector;
    7 
    8 uint8_t initVectorUnformatted[initVectorLength];
    9 
    10 // This is the same field length value that is written to the ctrl register
    11 initVector.byte[0] = L - 1;
    12 
    13 memcpy(&initVector.byte[1], initVectorUnformatted, initVectorLength);
    14 
    15 // Fill the remaining bytes with zeros
    16 for (initVectorLength++; initVectorLength < sizeof(initVector.byte); initVectorLength++) {
    17  initVector.byte[initVectorLength] = 0;
    18 }
Parameters
[in]initializationVectorPointer to an array with four 32-bit elements to be used as initialization vector. Elements of array must be word aligned in memory.
Returns
None

Referenced by AESWriteCCMInitializationVector().

77 {
78  // Write initialization vector to the aes registers
79  HWREG(CRYPTO_BASE + CRYPTO_O_AESIV0) = initializationVector[0];
80  HWREG(CRYPTO_BASE + CRYPTO_O_AESIV1) = initializationVector[1];
81  HWREG(CRYPTO_BASE + CRYPTO_O_AESIV2) = initializationVector[2];
82  HWREG(CRYPTO_BASE + CRYPTO_O_AESIV3) = initializationVector[3];
83 }
void AESStartDMAOperation ( const uint8_t *  channel0Addr,
uint32_t  channel0Length,
uint8_t *  channel1Addr,
uint32_t  channel1Length 
)

Start a crypto DMA operation.

Enable the crypto DMA channels, configure the channel addresses, and set the length of the data transfer. Setting the length of the data transfer automatically starts the transfer. It is also used by the hardware module as a signal to begin the encryption, decryption, or MAC operation.

Parameters
[in]channel0AddrA pointer to the address channel 0 shall use.
[in]channel0LengthLength of the data in bytes to be read from or written to at channel0Addr. Set to 0 to not set up this channel. Permitted ranges are mode dependent and displayed below.
  • ECB: [16]
  • CBC: [1, sizeof(RAM)]
  • CBC-MAC: [1, sizeof(RAM)]
  • CCM: [1, sizeof(RAM)]
[out]channel1AddrA pointer to the address channel 1 shall use.
[in]channel1LengthLength of the data in bytes to be read from or written to at channel1Addr. Set to 0 to not set up this channel.Permitted ranges are mode dependent and displayed below.
  • ECB: [16]
  • CBC: [1, sizeof(RAM)]
  • CBC-MAC: [1, sizeof(RAM)]
  • CCM: [1, sizeof(RAM)]
Returns
None

Referenced by AESWriteToKeyStore().

91 {
92  if (channel0Length && channel0Addr) {
93  // We actually want to perform an operation. Clear any outstanding events.
94  HWREG(CRYPTO_BASE + CRYPTO_O_IRQCLR) = CRYPTO_IRQCLR_RESULT_AVAIL_M | CRYPTO_IRQEN_DMA_IN_DONE_M; // This might need AES_IRQEN_DMA_IN_DONE as well
95 
97 
98  // Configure the DMA controller - enable both DMA channels.
100 
101  // Base address of the payload data in ext. memory.
102  HWREG(CRYPTO_BASE + CRYPTO_O_DMACH0EXTADDR) = (uint32_t)channel0Addr;
103 
104  // Payload data length in bytes, equal to the cipher text length.
105  HWREG(CRYPTO_BASE + CRYPTO_O_DMACH0LEN) = channel0Length;
106  }
107 
108  if (channel1Length && channel1Addr) {
109  // Enable DMA channel 1.
111 
112  // Base address of the output data buffer.
113  HWREG(CRYPTO_BASE + CRYPTO_O_DMACH1EXTADDR) = (uint32_t)channel1Addr;
114 
115  // Output data length in bytes, equal to the cipher text length.
116  HWREG(CRYPTO_BASE + CRYPTO_O_DMACH1LEN) = channel1Length;
117  }
118 }
uint32_t AESVerifyTag ( const uint8_t *  tag,
uint32_t  tagLength 
)

Verifies the provided tag against calculated one.

This function compares the provided tag against the tag calculated by the crypto module during the last CCM, GCM, or CBC-MAC

This function copies the tagLength bytes from the tag calculated by the crypto module in CCM, GCM, or CBC-MAC mode to tag.

Parameters
[in]tagPointer to an array of tagLength bytes.
[in]tagLengthNumber of bytes to compare.
Returns
Returns a status code depending on the result of the transfer.
307 {
308  uint32_t resultStatus;
309  // The intermediate array is allocated on the stack to ensure users do not
310  // point the tag they provide and the one computed at the same location.
311  // That would cause memcmp to compare an array against itself. We could add
312  // a check that verifies that the arrays are not the same. If we did that and
313  // modified AESReadTag to just copy all 128 bits into a provided array,
314  // we could save 16 bytes of stack space while making the API much more
315  // complicated.
316  uint8_t computedTag[AES_BLOCK_SIZE];
317 
318  resultStatus = AESReadTag(computedTag, tagLength);
319 
320  if (resultStatus != AES_SUCCESS) {
321  return resultStatus;
322  }
323 
324  resultStatus = memcmp(computedTag, tag, tagLength);
325 
326  if (resultStatus != 0) {
328  }
329 
330  return AES_SUCCESS;
331 }
#define AES_SUCCESS
Definition: aes.h:121
#define AES_TAG_VERIFICATION_FAILED
Definition: aes.h:127
uint32_t AESReadTag(uint8_t *tag, uint32_t tagLength)
Read the tag out from the crypto module.
Definition: aes.c:277
#define AES_BLOCK_SIZE
Definition: aes.h:136

Here is the call graph for this function:

uint32_t AESWaitForIRQFlags ( uint32_t  irqFlags)

Poll the interrupt status register and clear when done.

This function polls until one of the bits in the irqFlags is asserted. Only AES_DMA_IN_DONE and AES_RESULT_RDY can actually trigger the interrupt line. That means that one of those should always be included in irqFlags and will always be returned together with any error codes.

Parameters
[in]irqFlagsIRQ flags to poll and mask that the status register will be masked with. May consist of any bitwise OR of the flags below that includes at least one of AES_DMA_IN_DONE or AES_RESULT_RDY :
Returns
Returns the IRQ status register masked with irqFlags. May be any bitwise OR of the following masks:

Referenced by AESWriteToKeyStore().

126 {
127  uint32_t irqTrigger = 0;
128  // Wait for the DMA operation to complete. Add a delay to make sure we are
129  // not flooding the bus with requests too much.
130  do {
131  CPUdelay(1);
132  }
133  while(!(HWREG(CRYPTO_BASE + CRYPTO_O_IRQSTAT) & irqFlags & (CRYPTO_IRQSTAT_DMA_IN_DONE_M |
137 
138  // Save the IRQ trigger source
139  irqTrigger = HWREG(CRYPTO_BASE + CRYPTO_O_IRQSTAT) & irqFlags;
140 
141  // Clear IRQ flags
142  HWREG(CRYPTO_BASE + CRYPTO_O_IRQCLR) = irqTrigger;
143 
144  return irqTrigger;
145 }
void CPUdelay(uint32_t ui32Count)
Provide a small non-zero delay using a simple loop counter.
Definition: cpu.c:343

Here is the call graph for this function:

void AESWriteCCMInitializationVector ( const uint8_t *  nonce,
uint32_t  nonceLength 
)

Generate and load the initialization vector for a CCM operation.

Parameters
[in]noncePointer to a nonce of length nonceLength.
[in]nonceLengthNumber of bytes to copy from nonce when creating the CCM IV. The L-value is also derived from it.
Returns
None
361 {
362  union {
363  uint32_t word[4];
364  uint8_t byte[16];
365  } initializationVector = {{0}};
366 
367  initializationVector.byte[0] = 15 - nonceLength - 1;
368 
369  memcpy(&(initializationVector.byte[1]), nonce, nonceLength);
370 
371  AESSetInitializationVector(initializationVector.word);
372 }
void AESSetInitializationVector(const uint32_t *initializationVector)
Write the initialization vector (IV) to the crypto module.
Definition: aes.c:76

Here is the call graph for this function:

uint32_t AESWriteToKeyStore ( const uint8_t *  aesKey,
uint32_t  aesKeyLength,
uint32_t  keyStoreArea 
)

Transfer a key from main memory to a key area within the key store.

The crypto DMA transfers the key and function does not return until the operation completes. The keyStore can only contain valid keys of one aesKeyLength at any one point in time. The keyStore cannot contain both 128-bit and 256-bit keys simultaneously. When a key of a different aesKeyLength from the previous aesKeyLength is loaded, all previous keys are invalidated.

Parameters
[in]aesKeyPointer to key. Does not need to be word-aligned.
[in]aesKeyLengthThe key size in bytes. Currently, 128-bit, 192-bit, and 256-bit keys are supported.
[in]keyStoreAreaThe key store area to transfer the key to. When using 128-bit keys, only the specified key store area will be occupied. When using 256-bit or 192-bit keys, two consecutive key areas are used to store the key.
Returns
Returns a status code depending on the result of the transfer. If there was an error in the read process itself, an error is returned. Otherwise, a success code is returned.
See also
AESReadFromKeyStore
153 {
154  // Check the arguments.
155  ASSERT((keyStoreArea == AES_KEY_AREA_0) ||
156  (keyStoreArea == AES_KEY_AREA_1) ||
157  (keyStoreArea == AES_KEY_AREA_2) ||
158  (keyStoreArea == AES_KEY_AREA_3) ||
159  (keyStoreArea == AES_KEY_AREA_4) ||
160  (keyStoreArea == AES_KEY_AREA_5) ||
161  (keyStoreArea == AES_KEY_AREA_6) ||
162  (keyStoreArea == AES_KEY_AREA_7));
163 
164  ASSERT((aesKeyLength == AES_128_KEY_LENGTH_BYTES) ||
165  (aesKeyLength == AES_192_KEY_LENGTH_BYTES) ||
166  (aesKeyLength == AES_256_KEY_LENGTH_BYTES));
167 
168  uint32_t keySize = 0;
169 
170  switch (aesKeyLength) {
172  keySize = CRYPTO_KEYSIZE_SIZE_128_BIT;
173  break;
175  keySize = CRYPTO_KEYSIZE_SIZE_192_BIT;
176  break;
178  keySize = CRYPTO_KEYSIZE_SIZE_256_BIT;
179  break;
180  }
181 
182  // Clear any previously written key at the keyLocation
183  AESInvalidateKey(keyStoreArea);
184 
185  // Disable the external interrupt to stop the interrupt form propagating
186  // from the module to the System CPU.
187  IntDisable(INT_CRYPTO_RESULT_AVAIL_IRQ);
188 
189  // Enable internal interrupts.
192 
193  // Configure master control module.
195 
196  // Clear any outstanding events.
198 
199  // Configure the size of keys contained within the key store
200  // Do not write to the register if the correct key size is already set.
201  // Writing to this register causes all current keys to be invalidated.
202  uint32_t keyStoreKeySize = HWREG(CRYPTO_BASE + CRYPTO_O_KEYSIZE);
203  if (keySize != keyStoreKeySize) {
204  HWREG(CRYPTO_BASE + CRYPTO_O_KEYSIZE) = keySize;
205  }
206 
207  // Enable key to write (e.g. Key 0).
208  HWREG(CRYPTO_BASE + CRYPTO_O_KEYWRITEAREA) = 1 << keyStoreArea;
209 
210  // Total key length in bytes (16 for 1 x 128-bit key and 32 for 1 x 256-bit key).
211  AESStartDMAOperation(aesKey, aesKeyLength, 0, 0);
212 
213  // Wait for the DMA operation to complete.
215 
216  // Re-enable interrupts globally.
217  IntPendClear(INT_CRYPTO_RESULT_AVAIL_IRQ);
218  IntEnable(INT_CRYPTO_RESULT_AVAIL_IRQ);
219 
220  // If we had a bus error or the key is not in the CRYPTO_O_KEYWRITTENAREA, return an error.
221  if ((irqTrigger & (CRYPTO_IRQSTAT_DMA_BUS_ERR_M | CRYPTO_IRQSTAT_KEY_ST_WR_ERR_M)) || !(HWREG(CRYPTO_BASE + CRYPTO_O_KEYWRITTENAREA) & (1 << keyStoreArea))) {
222  // There was an error in writing to the keyStore.
223  return AES_KEYSTORE_ERROR;
224  }
225  else {
226  return AES_SUCCESS;
227  }
228 }
uint32_t AESWaitForIRQFlags(uint32_t irqFlags)
Poll the interrupt status register and clear when done.
Definition: aes.c:125
void IntPendClear(uint32_t ui32Interrupt)
Unpends an interrupt.
Definition: interrupt.c:443
#define AES_KEY_AREA_7
Definition: aes.h:163
#define AES_SUCCESS
Definition: aes.h:121
#define AES_KEY_AREA_5
Definition: aes.h:161
#define AES_KEYSTORE_ERROR
Definition: aes.h:122
#define AES_KEY_AREA_6
Definition: aes.h:162
#define AES_KEY_AREA_4
Definition: aes.h:160
#define AES_KEY_AREA_0
Definition: aes.h:156
#define ASSERT(expr)
Definition: debug.h:73
static void AESInvalidateKey(uint32_t keyStoreArea)
Invalidate a key in the key store.
Definition: aes.h:476
#define AES_KEY_AREA_1
Definition: aes.h:157
#define AES_128_KEY_LENGTH_BYTES
Definition: aes.h:132
#define AES_KEY_AREA_3
Definition: aes.h:159
#define AES_192_KEY_LENGTH_BYTES
Definition: aes.h:133
void AESStartDMAOperation(const uint8_t *channel0Addr, uint32_t channel0Length, uint8_t *channel1Addr, uint32_t channel1Length)
Start a crypto DMA operation.
Definition: aes.c:90
#define AES_256_KEY_LENGTH_BYTES
Definition: aes.h:134
#define AES_KEY_AREA_2
Definition: aes.h:158
void IntDisable(uint32_t ui32Interrupt)
Disables an interrupt or system exception.
Definition: interrupt.c:327
void IntEnable(uint32_t ui32Interrupt)
Enables an interrupt or system exception.
Definition: interrupt.c:283

Here is the call graph for this function:

Macro Definition Documentation

#define AES_128_KEY_LENGTH_BYTES   (128 / 8)

Referenced by AESWriteToKeyStore().

#define AES_192_KEY_LENGTH_BYTES   (192 / 8)

Referenced by AESWriteToKeyStore().

#define AES_256_KEY_LENGTH_BYTES   (256 / 8)

Referenced by AESWriteToKeyStore().

#define AES_ALGSEL_AES   CRYPTO_ALGSEL_AES_M

Referenced by AESSelectAlgorithm().

#define AES_ALGSEL_KEY_STORE   CRYPTO_ALGSEL_KEY_STORE_M

Referenced by AESSelectAlgorithm().

#define AES_ALGSEL_TAG   CRYPTO_ALGSEL_TAG_M

Referenced by AESSelectAlgorithm().

#define AES_BLOCK_SIZE   16

Referenced by AESReadTag(), and AESVerifyTag().

#define AES_CTR_WIDTH_128   0x3
#define AES_CTR_WIDTH_32   0x0
#define AES_CTR_WIDTH_64   0x1
#define AES_CTR_WIDTH_96   0x2
#define AES_DMA_BUS_ERR   CRYPTO_IRQCLR_DMA_BUS_ERR_M
#define AES_DMA_BUSY   3
#define AES_DMA_CHANNEL0_ACTIVE   CRYPTO_DMASTAT_CH0_ACT_M
#define AES_DMA_CHANNEL1_ACTIVE   CRYPTO_DMASTAT_CH1_ACT_M
#define AES_DMA_ERROR   4
#define AES_DMA_IN_DONE   CRYPTO_IRQEN_DMA_IN_DONE_M
#define AES_DMA_PORT_ERROR   CRYPTO_DMASTAT_PORT_ERR_M
#define AES_IV_LENGTH_BYTES   16
#define AES_KEY_AREA_0   0
#define AES_KEY_AREA_1   1
#define AES_KEY_AREA_2   2
#define AES_KEY_AREA_3   3
#define AES_KEY_AREA_4   4
#define AES_KEY_AREA_5   5
#define AES_KEY_AREA_6   6
#define AES_KEY_AREA_7   7
#define AES_KEY_ST_RD_ERR   CRYPTO_IRQCLR_KEY_ST_RD_ERR_M
#define AES_KEY_ST_WR_ERR   CRYPTO_IRQCLR_KEY_ST_WR_ERR_M
#define AES_KEYSTORE_AREA_INVALID   2

Referenced by AESReadFromKeyStore().

#define AES_KEYSTORE_ERROR   1
#define AES_RESULT_RDY   CRYPTO_IRQEN_RESULT_AVAIL_M
#define AES_TAG_LENGTH_BYTES   16
#define AES_TAG_NOT_READY   5
#define AES_TAG_VERIFICATION_FAILED   6

Referenced by AESVerifyTag().