Skip to content

Commit

Permalink
Merge pull request contiki-os#1435 from bthebaudeau/cc2538-hw-llsec
Browse files Browse the repository at this point in the history
cc2538: Add support for hardware-accelerated llsec
  • Loading branch information
bthebaudeau committed Jan 4, 2016
2 parents ca919ab + 69eacbd commit 626d676
Show file tree
Hide file tree
Showing 26 changed files with 1,622 additions and 444 deletions.
11 changes: 0 additions & 11 deletions core/lib/aes-128.c
Original file line number Diff line number Diff line change
Expand Up @@ -167,17 +167,6 @@ encrypt(uint8_t *state)
}
/*---------------------------------------------------------------------------*/
void
aes_128_padded_encrypt(uint8_t *plaintext_and_result, uint8_t plaintext_len)
{
uint8_t block[AES_128_BLOCK_SIZE];

memset(block, 0, AES_128_BLOCK_SIZE);
memcpy(block, plaintext_and_result, plaintext_len);
AES_128.encrypt(block);
memcpy(plaintext_and_result, block, plaintext_len);
}
/*---------------------------------------------------------------------------*/
void
aes_128_set_padded_key(uint8_t *key, uint8_t key_len)
{
uint8_t block[AES_128_BLOCK_SIZE];
Expand Down
11 changes: 3 additions & 8 deletions core/lib/aes-128.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@
* Konrad Krentz <[email protected]>
*/

#ifndef AES_H_
#define AES_H_
#ifndef AES_128_H_
#define AES_128_H_

#include "contiki.h"

Expand Down Expand Up @@ -67,16 +67,11 @@ struct aes_128_driver {
void (* encrypt)(uint8_t *plaintext_and_result);
};

/**
* \brief Pads the plaintext with zeroes before calling AES_128.encrypt
*/
void aes_128_padded_encrypt(uint8_t *plaintext_and_result, uint8_t plaintext_len);

/**
* \brief Pads the key with zeroes before calling AES_128.set_key
*/
void aes_128_set_padded_key(uint8_t *key, uint8_t key_len);

extern const struct aes_128_driver AES_128;

#endif /* AES_H_ */
#endif /* AES_128_H_ */
1 change: 1 addition & 0 deletions core/net/netstack.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ netstack_init(void)
{
NETSTACK_RADIO.init();
NETSTACK_RDC.init();
NETSTACK_LLSEC.init();
NETSTACK_MAC.init();
NETSTACK_NETWORK.init();
}
Expand Down
3 changes: 2 additions & 1 deletion cpu/cc2538/Makefile.cc2538
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ CONTIKI_CPU_DIRS += ../cc253x/usb/common ../cc253x/usb/common/cdc-acm
### CPU-dependent source files
CONTIKI_CPU_SOURCEFILES += clock.c rtimer-arch.c uart.c watchdog.c
CONTIKI_CPU_SOURCEFILES += nvic.c cpu.c sys-ctrl.c gpio.c ioc.c spi.c adc.c
CONTIKI_CPU_SOURCEFILES += crypto.c aes.c ccm.c sha256.c
CONTIKI_CPU_SOURCEFILES += crypto.c aes.c ecb.c ccm.c sha256.c
CONTIKI_CPU_SOURCEFILES += cc2538-aes-128.c cc2538-ccm-star.c
CONTIKI_CPU_SOURCEFILES += cc2538-rf.c udma.c lpm.c
CONTIKI_CPU_SOURCEFILES += pka.c bignum-driver.c ecc-driver.c ecc-algorithm.c
CONTIKI_CPU_SOURCEFILES += ecc-curve.c
Expand Down
183 changes: 181 additions & 2 deletions cpu/cc2538/dev/aes.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,11 @@
*/
#include "contiki.h"
#include "dev/rom-util.h"
#include "dev/nvic.h"
#include "dev/aes.h"
#include "reg.h"

#include <stdbool.h>
#include <stdint.h>
/*---------------------------------------------------------------------------*/
uint8_t
Expand All @@ -53,7 +55,7 @@ aes_load_keys(const void *keys, uint8_t key_size, uint8_t count,
{
uint32_t aes_key_store_size;
uint32_t areas;
uint64_t aligned_keys[16];
uint64_t aligned_keys[AES_KEY_AREAS * 128 / 8 / sizeof(uint64_t)];
int i;

if(REG(AES_CTRL_ALG_SEL) != 0x00000000) {
Expand All @@ -63,7 +65,8 @@ aes_load_keys(const void *keys, uint8_t key_size, uint8_t count,
/* 192-bit keys must be padded to 256 bits */
if(key_size == AES_KEY_STORE_SIZE_KEY_SIZE_192) {
for(i = 0; i < count; i++) {
rom_util_memcpy(&aligned_keys[i << 2], &((uint64_t *)keys)[i * 3], 24);
rom_util_memcpy(&aligned_keys[i << 2], &((const uint64_t *)keys)[i * 3],
192 / 8);
aligned_keys[(i << 2) + 3] = 0;
}
}
Expand Down Expand Up @@ -148,5 +151,181 @@ aes_load_keys(const void *keys, uint8_t key_size, uint8_t count,

return CRYPTO_SUCCESS;
}
/*---------------------------------------------------------------------------*/
uint8_t
aes_auth_crypt_start(uint32_t ctrl, uint8_t key_area, const void *iv,
const void *adata, uint16_t adata_len,
const void *data_in, void *data_out, uint16_t data_len,
struct process *process)
{
if(REG(AES_CTRL_ALG_SEL) != 0x00000000) {
return CRYPTO_RESOURCE_IN_USE;
}

/* Workaround for AES registers not retained after PM2 */
REG(AES_CTRL_INT_CFG) = AES_CTRL_INT_CFG_LEVEL;
REG(AES_CTRL_INT_EN) = AES_CTRL_INT_EN_DMA_IN_DONE |
AES_CTRL_INT_EN_RESULT_AV;

REG(AES_CTRL_ALG_SEL) = AES_CTRL_ALG_SEL_AES;
REG(AES_CTRL_INT_CLR) = AES_CTRL_INT_CLR_DMA_IN_DONE |
AES_CTRL_INT_CLR_RESULT_AV;

REG(AES_KEY_STORE_READ_AREA) = key_area;

/* Wait until key is loaded to the AES module */
while(REG(AES_KEY_STORE_READ_AREA) & AES_KEY_STORE_READ_AREA_BUSY);

/* Check for Key Store read error */
if(REG(AES_CTRL_INT_STAT) & AES_CTRL_INT_STAT_KEY_ST_RD_ERR) {
/* Clear the Keystore Read error bit */
REG(AES_CTRL_INT_CLR) = AES_CTRL_INT_CLR_KEY_ST_RD_ERR;
/* Disable the master control / DMA clock */
REG(AES_CTRL_ALG_SEL) = 0x00000000;
return AES_KEYSTORE_READ_ERROR;
}

if(iv != NULL) {
/* Write initialization vector */
REG(AES_AES_IV_0) = ((const uint32_t *)iv)[0];
REG(AES_AES_IV_1) = ((const uint32_t *)iv)[1];
REG(AES_AES_IV_2) = ((const uint32_t *)iv)[2];
REG(AES_AES_IV_3) = ((const uint32_t *)iv)[3];
}

/* Program AES authentication/crypto operation */
REG(AES_AES_CTRL) = ctrl;

/* Write the length of the payload block (lo) */
REG(AES_AES_C_LENGTH_0) = data_len;
/* Write the length of the payload block (hi) */
REG(AES_AES_C_LENGTH_1) = 0;

/* For combined modes only (CCM or GCM) */
if(ctrl & (AES_AES_CTRL_CCM | AES_AES_CTRL_GCM)) {
/* Write the length of the AAD data block (may be non-block size-aligned) */
REG(AES_AES_AUTH_LENGTH) = adata_len;

if(adata_len != 0) {
/* Configure DMAC to fetch the AAD data
* Enable DMA channel 0 */
REG(AES_DMAC_CH0_CTRL) = AES_DMAC_CH_CTRL_EN;
/* Base address of the AAD data buffer */
REG(AES_DMAC_CH0_EXTADDR) = (uint32_t)adata;
/* AAD data length in bytes */
REG(AES_DMAC_CH0_DMALENGTH) = adata_len;

/* Wait for completion of the AAD data transfer, DMA_IN_DONE */
while(!(REG(AES_CTRL_INT_STAT) & AES_CTRL_INT_STAT_DMA_IN_DONE));

/* Check for the absence of error */
if(REG(AES_CTRL_INT_STAT) & AES_CTRL_INT_STAT_DMA_BUS_ERR) {
/* Clear the DMA error */
REG(AES_CTRL_INT_CLR) = AES_CTRL_INT_CLR_DMA_BUS_ERR;
/* Disable the master control / DMA clock */
REG(AES_CTRL_ALG_SEL) = 0x00000000;
return CRYPTO_DMA_BUS_ERROR;
}
}
}

/* Clear interrupt status */
REG(AES_CTRL_INT_CLR) = AES_CTRL_INT_CLR_DMA_IN_DONE |
AES_CTRL_INT_CLR_RESULT_AV;

if(process != NULL) {
crypto_register_process_notification(process);
nvic_interrupt_unpend(NVIC_INT_AES);
nvic_interrupt_enable(NVIC_INT_AES);
}

/* Enable result available bit in interrupt enable */
REG(AES_CTRL_INT_EN) = AES_CTRL_INT_EN_RESULT_AV;

if(data_len != 0) {
/* Configure DMAC
* Enable DMA channel 0 */
REG(AES_DMAC_CH0_CTRL) = AES_DMAC_CH_CTRL_EN;
/* Base address of the input payload data buffer */
REG(AES_DMAC_CH0_EXTADDR) = (uint32_t)data_in;
/* Input payload data length in bytes */
REG(AES_DMAC_CH0_DMALENGTH) = data_len;

if(data_out != NULL) {
/* Enable DMA channel 1 */
REG(AES_DMAC_CH1_CTRL) = AES_DMAC_CH_CTRL_EN;
/* Base address of the output payload data buffer */
REG(AES_DMAC_CH1_EXTADDR) = (uint32_t)data_out;
/* Output payload data length in bytes */
REG(AES_DMAC_CH1_DMALENGTH) = data_len;
}
}

return CRYPTO_SUCCESS;
}
/*---------------------------------------------------------------------------*/
uint8_t
aes_auth_crypt_check_status(void)
{
return !!(REG(AES_CTRL_INT_STAT) &
(AES_CTRL_INT_STAT_DMA_BUS_ERR | AES_CTRL_INT_STAT_KEY_ST_WR_ERR |
AES_CTRL_INT_STAT_KEY_ST_RD_ERR | AES_CTRL_INT_STAT_RESULT_AV));
}
/*---------------------------------------------------------------------------*/
uint8_t
aes_auth_crypt_get_result(void *iv, void *tag)
{
uint32_t aes_ctrl_int_stat;

aes_ctrl_int_stat = REG(AES_CTRL_INT_STAT);
/* Clear the error bits */
REG(AES_CTRL_INT_CLR) = AES_CTRL_INT_CLR_DMA_BUS_ERR |
AES_CTRL_INT_CLR_KEY_ST_WR_ERR |
AES_CTRL_INT_CLR_KEY_ST_RD_ERR;

nvic_interrupt_disable(NVIC_INT_AES);
crypto_register_process_notification(NULL);

/* Disable the master control / DMA clock */
REG(AES_CTRL_ALG_SEL) = 0x00000000;

if(aes_ctrl_int_stat & AES_CTRL_INT_STAT_DMA_BUS_ERR) {
return CRYPTO_DMA_BUS_ERROR;
}
if(aes_ctrl_int_stat & AES_CTRL_INT_STAT_KEY_ST_WR_ERR) {
return AES_KEYSTORE_WRITE_ERROR;
}
if(aes_ctrl_int_stat & AES_CTRL_INT_STAT_KEY_ST_RD_ERR) {
return AES_KEYSTORE_READ_ERROR;
}

if(iv != NULL || tag != NULL) {
/* Read result
* Wait for the context ready bit */
while(!(REG(AES_AES_CTRL) & AES_AES_CTRL_SAVED_CONTEXT_READY));

if(iv != NULL) {
/* Read the initialization vector registers */
((uint32_t *)iv)[0] = REG(AES_AES_IV_0);
((uint32_t *)iv)[1] = REG(AES_AES_IV_1);
((uint32_t *)iv)[2] = REG(AES_AES_IV_2);
((uint32_t *)iv)[3] = REG(AES_AES_IV_3);
}

if(tag != NULL) {
/* Read the tag registers */
((uint32_t *)tag)[0] = REG(AES_AES_TAG_OUT_0);
((uint32_t *)tag)[1] = REG(AES_AES_TAG_OUT_1);
((uint32_t *)tag)[2] = REG(AES_AES_TAG_OUT_2);
((uint32_t *)tag)[3] = REG(AES_AES_TAG_OUT_3);
}
}

/* Clear the interrupt status */
REG(AES_CTRL_INT_CLR) = AES_CTRL_INT_CLR_DMA_IN_DONE |
AES_CTRL_INT_CLR_RESULT_AV;

return CRYPTO_SUCCESS;
}

/** @} */
57 changes: 53 additions & 4 deletions cpu/cc2538/dev/aes.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
#include "contiki.h"
#include "dev/crypto.h"

#include <stdbool.h>
#include <stdint.h>
/*---------------------------------------------------------------------------*/
/** \name AES register offsets
Expand Down Expand Up @@ -464,6 +465,16 @@
*/
#define AES_KEYSTORE_READ_ERROR 5
#define AES_KEYSTORE_WRITE_ERROR 6
#define AES_AUTHENTICATION_FAILED 7
/** @} */
/*---------------------------------------------------------------------------*/
/** \name AES constants
* @{
*/
#define AES_KEY_AREAS 8
#define AES_BLOCK_LEN (128 / 8)
#define AES_IV_LEN AES_BLOCK_LEN
#define AES_TAG_LEN AES_BLOCK_LEN
/** @} */
/*---------------------------------------------------------------------------*/
/** \name AES functions
Expand All @@ -473,10 +484,11 @@
/** \brief Writes keys into the Key RAM
* \param keys Pointer to AES Keys
* \param key_size Key size: \c AES_KEY_STORE_SIZE_KEY_SIZE_x
* \param count Number of keys (1 to 8 - \p start_area for 128-bit keys, 1 to
* (8 - \p start_area) / 2 for 192- and 256-bit keys)
* \param start_area Start area in Key RAM where to store the key (0 to 7, must
* be even for 192- and 256-bit keys)
* \param count Number of keys (1 to \c AES_KEY_AREAS - \p start_area for
* 128-bit keys, 1 to (\c AES_KEY_AREAS - \p start_area) / 2 for 192- and
* 256-bit keys)
* \param start_area Start area in Key RAM where to store the keys (0 to
* \c AES_KEY_AREAS - 1, must be even for 192- and 256-bit keys)
* \return \c CRYPTO_SUCCESS if successful, or CRYPTO/AES error code
* \note Calling this function with a value of \p key_size different from the
* one passed for the previous calls causes the deletion of all previously
Expand All @@ -485,6 +497,43 @@
uint8_t aes_load_keys(const void *keys, uint8_t key_size, uint8_t count,
uint8_t start_area);

/** \brief Starts an AES authentication/crypto operation
* \param ctrl Contents of the \c AES_AES_CTRL register
* \param key_area Area in Key RAM where the key is stored (0 to
* \c AES_KEY_AREAS - 1)
* \param iv Pointer to 128-bit initialization vector, or \c NULL
* \param adata Pointer to additional authenticated data in SRAM, or \c NULL
* \param adata_len Length of additional authenticated data in octets, or \c 0
* \param data_in Pointer to input payload data in SRAM, or \c NULL
* \param data_out Pointer to output payload data in SRAM (may be \p data_in),
* or \c NULL
* \param data_len Length of payload data in octets, or \c 0
* \param process Process to be polled upon completion of the operation, or
* \c NULL
* \return \c CRYPTO_SUCCESS if successful, or CRYPTO/AES error code
* \note This function is only supposed to be called by the AES drivers.
*/
uint8_t aes_auth_crypt_start(uint32_t ctrl, uint8_t key_area, const void *iv,
const void *adata, uint16_t adata_len,
const void *data_in, void *data_out,
uint16_t data_len, struct process *process);

/** \brief Checks the status of the AES authentication/crypto operation
* \retval false Result not yet available, and no error occurred
* \retval true Result available, or error occurred
* \note This function is only supposed to be called by the AES drivers.
*/
uint8_t aes_auth_crypt_check_status(void);

/** \brief Gets the result of the AES authentication/crypto operation
* \param iv Pointer to 128-bit result initialization vector, or \c NULL
* \param tag Pointer to 128-bit result tag, or \c NULL
* \return \c CRYPTO_SUCCESS if successful, or CRYPTO/AES error code
* \note This function must be called only after \c aes_auth_crypt_start().
* \note This function is only supposed to be called by the AES drivers.
*/
uint8_t aes_auth_crypt_get_result(void *iv, void *tag);

/** @} */

#endif /* AES_H_ */
Expand Down
Loading

0 comments on commit 626d676

Please sign in to comment.