diff --git a/cpu/cc2538/dev/aes.c b/cpu/cc2538/dev/aes.c index 1bd70690c..429def67b 100644 --- a/cpu/cc2538/dev/aes.c +++ b/cpu/cc2538/dev/aes.c @@ -42,9 +42,11 @@ */ #include "contiki.h" #include "dev/rom-util.h" +#include "dev/nvic.h" #include "dev/aes.h" #include "reg.h" +#include #include /*---------------------------------------------------------------------------*/ uint8_t @@ -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) { @@ -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; } } @@ -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; +} /** @} */ diff --git a/cpu/cc2538/dev/aes.h b/cpu/cc2538/dev/aes.h index 39c794b51..19366e680 100644 --- a/cpu/cc2538/dev/aes.h +++ b/cpu/cc2538/dev/aes.h @@ -51,6 +51,7 @@ #include "contiki.h" #include "dev/crypto.h" +#include #include /*---------------------------------------------------------------------------*/ /** \name AES register offsets @@ -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 @@ -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 @@ -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_ */ diff --git a/cpu/cc2538/dev/ccm.c b/cpu/cc2538/dev/ccm.c index b25ef29b3..70e3fac34 100644 --- a/cpu/cc2538/dev/ccm.c +++ b/cpu/cc2538/dev/ccm.c @@ -43,49 +43,30 @@ #include "contiki.h" #include "sys/cc.h" #include "dev/rom-util.h" -#include "dev/nvic.h" #include "dev/ccm.h" -#include "reg.h" #include #include /*---------------------------------------------------------------------------*/ -uint8_t -ccm_auth_encrypt_start(uint8_t len_len, uint8_t key_area, const void *nonce, - const void *adata, uint16_t adata_len, void *pdata, - uint16_t pdata_len, uint8_t mic_len, - struct process *process) +static uint8_t +ccm_auth_crypt_start(uint8_t encrypt, uint8_t len_len, uint8_t key_area, + const void *nonce, const void *adata, uint16_t adata_len, + void *data, uint16_t data_len, uint8_t mic_len, + struct process *process) { + uint32_t ctrl; uint32_t iv[4]; - if(REG(AES_CTRL_ALG_SEL) != 0x00000000) { - return CRYPTO_RESOURCE_IN_USE; - } + /* Program AES-CCM authentication/crypto operation */ + ctrl = AES_AES_CTRL_SAVE_CONTEXT | /* Save context */ + (((MAX(mic_len, 2) - 2) >> 1) << AES_AES_CTRL_CCM_M_S) | /* M */ + ((len_len - 1) << AES_AES_CTRL_CCM_L_S) | /* L */ + AES_AES_CTRL_CCM | /* CCM */ + AES_AES_CTRL_CTR_WIDTH_128 | /* CTR width 128 */ + AES_AES_CTRL_CTR | /* CTR */ + (encrypt ? AES_AES_CTRL_DIRECTION_ENCRYPT : 0); /* En/decryption */ - /* 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; - } - - /* Prepare the encryption initialization vector + /* Prepare the crypto initialization vector * Flags: L' = L - 1 */ ((uint8_t *)iv)[0] = len_len - 1; /* Nonce */ @@ -93,134 +74,31 @@ ccm_auth_encrypt_start(uint8_t len_len, uint8_t key_area, const void *nonce, /* Initialize counter to 0 */ rom_util_memset(&((uint8_t *)iv)[16 - len_len], 0, len_len); - /* Write initialization vector */ - REG(AES_AES_IV_0) = iv[0]; - REG(AES_AES_IV_1) = iv[1]; - REG(AES_AES_IV_2) = iv[2]; - REG(AES_AES_IV_3) = iv[3]; + return aes_auth_crypt_start(ctrl, key_area, iv, adata, adata_len, + data, data, data_len, process); +} +/*---------------------------------------------------------------------------*/ +static uint8_t +ccm_auth_crypt_get_result(const void *cdata, uint16_t cdata_len, + void *mic, uint8_t mic_len) +{ + uint32_t tag[4]; + uint16_t data_len; + uint8_t ret; - /* Program AES-CCM encryption */ - REG(AES_AES_CTRL) = AES_AES_CTRL_SAVE_CONTEXT | /* Save context */ - (((MAX(mic_len, 2) - 2) >> 1) << AES_AES_CTRL_CCM_M_S) | /* M */ - ((len_len - 1) << AES_AES_CTRL_CCM_L_S) | /* L */ - AES_AES_CTRL_CCM | /* CCM */ - AES_AES_CTRL_CTR_WIDTH_128 | /* CTR width 128 */ - AES_AES_CTRL_CTR | /* CTR */ - AES_AES_CTRL_DIRECTION_ENCRYPT; /* Encryption */ + ret = aes_auth_crypt_get_result(NULL, tag); + if(ret != CRYPTO_SUCCESS) { + return ret; + } - /* Write the length of the crypto block (lo) */ - REG(AES_AES_C_LENGTH_0) = pdata_len; - /* Write the length of the crypto block (hi) */ - REG(AES_AES_C_LENGTH_1) = 0; - - /* 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 input data in ext. memory */ - 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; + if(cdata != NULL) { + /* Check MIC */ + data_len = cdata_len - mic_len; + if(rom_util_memcmp(tag, &((const uint8_t *)cdata)[data_len], mic_len)) { + return AES_AUTHENTICATION_FAILED; } } - /* 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(pdata_len != 0) { - /* Configure DMAC - * Enable DMA channel 0 */ - REG(AES_DMAC_CH0_CTRL) = AES_DMAC_CH_CTRL_EN; - /* Base address of the payload data in ext. memory */ - REG(AES_DMAC_CH0_EXTADDR) = (uint32_t)pdata; - /* Payload data length in bytes */ - REG(AES_DMAC_CH0_DMALENGTH) = pdata_len; - - /* Enable DMA channel 1 */ - REG(AES_DMAC_CH1_CTRL) = AES_DMAC_CH_CTRL_EN; - /* Base address of the output data buffer */ - REG(AES_DMAC_CH1_EXTADDR) = (uint32_t)pdata; - /* Output data length in bytes */ - REG(AES_DMAC_CH1_DMALENGTH) = pdata_len; - } - - return CRYPTO_SUCCESS; -} -/*---------------------------------------------------------------------------*/ -uint8_t -ccm_auth_encrypt_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 -ccm_auth_encrypt_get_result(void *mic, uint8_t mic_len) -{ - uint32_t aes_ctrl_int_stat; - uint32_t tag[4]; - - 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; - } - - /* Read tag - * Wait for the context ready bit */ - while(!(REG(AES_AES_CTRL) & AES_AES_CTRL_SAVED_CONTEXT_READY)); - - /* Read the tag registers */ - tag[0] = REG(AES_AES_TAG_OUT_0); - tag[1] = REG(AES_AES_TAG_OUT_1); - tag[2] = REG(AES_AES_TAG_OUT_2); - 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; - /* Copy tag to MIC */ rom_util_memcpy(mic, tag, mic_len); @@ -228,186 +106,36 @@ ccm_auth_encrypt_get_result(void *mic, uint8_t mic_len) } /*---------------------------------------------------------------------------*/ uint8_t +ccm_auth_encrypt_start(uint8_t len_len, uint8_t key_area, const void *nonce, + const void *adata, uint16_t adata_len, void *pdata, + uint16_t pdata_len, uint8_t mic_len, + struct process *process) +{ + return ccm_auth_crypt_start(true, len_len, key_area, nonce, adata, adata_len, + pdata, pdata_len, mic_len, process); +} +/*---------------------------------------------------------------------------*/ +uint8_t +ccm_auth_encrypt_get_result(void *mic, uint8_t mic_len) +{ + return ccm_auth_crypt_get_result(NULL, 0, mic, mic_len); +} +/*---------------------------------------------------------------------------*/ +uint8_t ccm_auth_decrypt_start(uint8_t len_len, uint8_t key_area, const void *nonce, const void *adata, uint16_t adata_len, void *cdata, uint16_t cdata_len, uint8_t mic_len, struct process *process) { - uint16_t pdata_len = cdata_len - mic_len; - uint32_t iv[4]; + uint16_t data_len = cdata_len - mic_len; - 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; - } - - /* Prepare the decryption initialization vector - * Flags: L' = L - 1 */ - ((uint8_t *)iv)[0] = len_len - 1; - /* Nonce */ - rom_util_memcpy(&((uint8_t *)iv)[1], nonce, 15 - len_len); - /* Initialize counter to 0 */ - rom_util_memset(&((uint8_t *)iv)[16 - len_len], 0, len_len); - - /* Write initialization vector */ - REG(AES_AES_IV_0) = iv[0]; - REG(AES_AES_IV_1) = iv[1]; - REG(AES_AES_IV_2) = iv[2]; - REG(AES_AES_IV_3) = iv[3]; - - /* Program AES-CCM decryption */ - REG(AES_AES_CTRL) = AES_AES_CTRL_SAVE_CONTEXT | /* Save context */ - (((MAX(mic_len, 2) - 2) >> 1) << AES_AES_CTRL_CCM_M_S) | /* M */ - ((len_len - 1) << AES_AES_CTRL_CCM_L_S) | /* L */ - AES_AES_CTRL_CCM | /* CCM */ - AES_AES_CTRL_CTR_WIDTH_128 | /* CTR width 128 */ - AES_AES_CTRL_CTR; /* CTR */ - - /* Write the length of the crypto block (lo) */ - REG(AES_AES_C_LENGTH_0) = pdata_len; - /* Write the length of the crypto block (hi) */ - REG(AES_AES_C_LENGTH_1) = 0; - - /* 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 input data in ext. memory */ - 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(pdata_len != 0) { - /* Configure DMAC - * Enable DMA channel 0 */ - REG(AES_DMAC_CH0_CTRL) = AES_DMAC_CH_CTRL_EN; - /* Base address of the payload data in ext. memory */ - REG(AES_DMAC_CH0_EXTADDR) = (uint32_t)cdata; - /* Payload data length in bytes */ - REG(AES_DMAC_CH0_DMALENGTH) = pdata_len; - - /* Enable DMA channel 1 */ - REG(AES_DMAC_CH1_CTRL) = AES_DMAC_CH_CTRL_EN; - /* Base address of the output data buffer */ - REG(AES_DMAC_CH1_EXTADDR) = (uint32_t)cdata; - /* Output data length in bytes */ - REG(AES_DMAC_CH1_DMALENGTH) = pdata_len; - } - - return CRYPTO_SUCCESS; -} -/*---------------------------------------------------------------------------*/ -uint8_t -ccm_auth_decrypt_check_status(void) -{ - /* Check if result is available or some error has occured */ - return ccm_auth_encrypt_check_status(); + return ccm_auth_crypt_start(false, len_len, key_area, nonce, adata, adata_len, + cdata, data_len, mic_len, process); } /*---------------------------------------------------------------------------*/ uint8_t ccm_auth_decrypt_get_result(const void *cdata, uint16_t cdata_len, void *mic, uint8_t mic_len) -{ - uint32_t aes_ctrl_int_stat; - uint16_t pdata_len = cdata_len - mic_len; - uint32_t tag[4]; - - 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; - } - - /* Read tag - * Wait for the context ready bit */ - while(!(REG(AES_AES_CTRL) & AES_AES_CTRL_SAVED_CONTEXT_READY)); - - /* Read the tag registers */ - tag[0] = REG(AES_AES_TAG_OUT_0); - tag[1] = REG(AES_AES_TAG_OUT_1); - tag[2] = REG(AES_AES_TAG_OUT_2); - 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; - - /* Check MIC */ - if(rom_util_memcmp(tag, &((const uint8_t *)cdata)[pdata_len], mic_len)) { - return CCM_AUTHENTICATION_FAILED; - } - - /* Copy tag to MIC */ - rom_util_memcpy(mic, tag, mic_len); - - return CRYPTO_SUCCESS; -} +__attribute__ ((alias("ccm_auth_crypt_get_result"))); /** @} */ diff --git a/cpu/cc2538/dev/ccm.h b/cpu/cc2538/dev/ccm.h index 1cab578af..0a83c217f 100644 --- a/cpu/cc2538/dev/ccm.h +++ b/cpu/cc2538/dev/ccm.h @@ -54,12 +54,6 @@ #include #include /*---------------------------------------------------------------------------*/ -/** \name AES-CCM driver return codes - * @{ - */ -#define CCM_AUTHENTICATION_FAILED 7 -/** @} */ -/*---------------------------------------------------------------------------*/ /** \name AES-CCM functions * @{ */ @@ -86,7 +80,7 @@ uint8_t ccm_auth_encrypt_start(uint8_t len_len, uint8_t key_area, * \retval false Result not yet available, and no error occurred * \retval true Result available, or error occurred */ -uint8_t ccm_auth_encrypt_check_status(void); +#define ccm_auth_encrypt_check_status aes_auth_crypt_check_status /** \brief Gets the result of the CCM authentication and encryption operation * \param mic Pointer to authentication field, or \c NULL @@ -118,7 +112,7 @@ uint8_t ccm_auth_decrypt_start(uint8_t len_len, uint8_t key_area, * \retval false Result not yet available, and no error occurred * \retval true Result available, or error occurred */ -uint8_t ccm_auth_decrypt_check_status(void); +#define ccm_auth_decrypt_check_status aes_auth_crypt_check_status /** \brief Gets the result of the CCM authentication checking and decryption operation * \param cdata Pointer to encrypted and authenticated message