diff --git a/cpu/cc2538/Makefile.cc2538 b/cpu/cc2538/Makefile.cc2538 index d4eafc93a..29795111c 100644 --- a/cpu/cc2538/Makefile.cc2538 +++ b/cpu/cc2538/Makefile.cc2538 @@ -49,6 +49,7 @@ 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 += cc2538-rf.c udma.c lpm.c CONTIKI_CPU_SOURCEFILES += dbg.c ieee-addr.c CONTIKI_CPU_SOURCEFILES += slip-arch.c slip.c diff --git a/cpu/cc2538/dev/aes.c b/cpu/cc2538/dev/aes.c new file mode 100644 index 000000000..d5920fee0 --- /dev/null +++ b/cpu/cc2538/dev/aes.c @@ -0,0 +1,118 @@ +/* + * Original file: + * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ + * All rights reserved. + * + * Port to Contiki: + * Copyright (c) 2013, ADVANSEE - http://www.advansee.com/ + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/** + * \addtogroup cc2538-aes + * @{ + * + * \file + * Implementation of the cc2538 AES driver + */ +#include "contiki.h" +#include "dev/rom-util.h" +#include "dev/aes.h" +#include "reg.h" + +#include +/*---------------------------------------------------------------------------*/ +uint8_t +aes_load_key(const void *key, uint8_t key_area) +{ + uint32_t aligned_key[4]; + + /* The key address needs to be 4-byte aligned */ + rom_util_memcpy(aligned_key, key, sizeof(aligned_key)); + + /* 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; + + /* Configure master control module */ + REG(AES_CTRL_ALG_SEL) = AES_CTRL_ALG_SEL_KEYSTORE; + + /* Clear any outstanding events */ + REG(AES_CTRL_INT_CLR) = AES_CTRL_INT_CLR_DMA_IN_DONE | + AES_CTRL_INT_CLR_RESULT_AV; + + /* Configure key store module (area, size): 128-bit key size */ + REG(AES_KEY_STORE_SIZE) = (REG(AES_KEY_STORE_SIZE) & + ~AES_KEY_STORE_SIZE_KEY_SIZE_M) | + AES_KEY_STORE_SIZE_KEY_SIZE_128; + + /* Enable keys to write (e.g. Key 0) */ + REG(AES_KEY_STORE_WRITE_AREA) = 0x00000001 << key_area; + + /* Configure DMAC + * Enable DMA channel 0 */ + REG(AES_DMAC_CH0_CTRL) = AES_DMAC_CH_CTRL_EN; + + /* Base address of the key in ext. memory */ + REG(AES_DMAC_CH0_EXTADDR) = (uint32_t)aligned_key; + + /* Total key length in bytes (e.g. 16 for 1 x 128-bit key) */ + REG(AES_DMAC_CH0_DMALENGTH) = (REG(AES_DMAC_CH0_DMALENGTH) & + ~AES_DMAC_CH_DMALENGTH_DMALEN_M) | + (0x10 << AES_DMAC_CH_DMALENGTH_DMALEN_S); + + /* Wait for operation to complete */ + while(!(REG(AES_CTRL_INT_STAT) & AES_CTRL_INT_STAT_RESULT_AV)); + + /* Check for absence of errors in DMA and key store */ + if(REG(AES_CTRL_INT_STAT) & AES_CTRL_INT_STAT_DMA_BUS_ERR) { + REG(AES_CTRL_INT_CLR) = AES_CTRL_INT_CLR_DMA_BUS_ERR; + return CRYPTO_DMA_BUS_ERROR; + } + if(REG(AES_CTRL_INT_STAT) & AES_CTRL_INT_STAT_KEY_ST_WR_ERR) { + REG(AES_CTRL_INT_CLR) = AES_CTRL_INT_CLR_KEY_ST_WR_ERR; + return AES_KEYSTORE_WRITE_ERROR; + } + + /* Acknowledge the interrupt */ + REG(AES_CTRL_INT_CLR) = AES_CTRL_INT_CLR_DMA_IN_DONE | + AES_CTRL_INT_CLR_RESULT_AV; + + /* Disable master control / DMA clock */ + REG(AES_CTRL_ALG_SEL) = 0x00000000; + + /* Check status, if error return error code */ + if(!(REG(AES_KEY_STORE_WRITTEN_AREA) & (0x00000001 << key_area))) { + return AES_KEYSTORE_WRITE_ERROR; + } + + return CRYPTO_SUCCESS; +} + +/** @} */ diff --git a/cpu/cc2538/dev/aes.h b/cpu/cc2538/dev/aes.h new file mode 100644 index 000000000..5b9e4c343 --- /dev/null +++ b/cpu/cc2538/dev/aes.h @@ -0,0 +1,487 @@ +/* + * Original file: + * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ + * All rights reserved. + * + * Port to Contiki: + * Copyright (c) 2013, ADVANSEE - http://www.advansee.com/ + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/** + * \addtogroup cc2538-crypto + * @{ + * + * \defgroup cc2538-aes cc2538 AES + * + * Driver for the cc2538 AES modes of the security core + * @{ + * + * \file + * Header file for the cc2538 AES driver + */ +#ifndef AES_H_ +#define AES_H_ + +#include "contiki.h" +#include "dev/crypto.h" + +#include +/*---------------------------------------------------------------------------*/ +/** \name AES register offsets + * @{ + */ +#define AES_DMAC_CH0_CTRL 0x4008B000 /**< Channel 0 control */ +#define AES_DMAC_CH0_EXTADDR 0x4008B004 /**< Channel 0 external address */ +#define AES_DMAC_CH0_DMALENGTH 0x4008B00C /**< Channel 0 DMA length */ +#define AES_DMAC_STATUS 0x4008B018 /**< DMAC status */ +#define AES_DMAC_SWRES 0x4008B01C /**< DMAC software reset */ +#define AES_DMAC_CH1_CTRL 0x4008B020 /**< Channel 1 control */ +#define AES_DMAC_CH1_EXTADDR 0x4008B024 /**< Channel 1 external address */ +#define AES_DMAC_CH1_DMALENGTH 0x4008B02C /**< Channel 1 DMA length */ +#define AES_DMAC_MST_RUNPARAMS 0x4008B078 /**< DMAC master run-time parameters */ +#define AES_DMAC_PERSR 0x4008B07C /**< DMAC port error raw status */ +#define AES_DMAC_OPTIONS 0x4008B0F8 /**< DMAC options */ +#define AES_DMAC_VERSION 0x4008B0FC /**< DMAC version */ +#define AES_KEY_STORE_WRITE_AREA \ + 0x4008B400 /**< Key store write area */ +#define AES_KEY_STORE_WRITTEN_AREA \ + 0x4008B404 /**< Key store written area */ +#define AES_KEY_STORE_SIZE 0x4008B408 /**< Key store size */ +#define AES_KEY_STORE_READ_AREA 0x4008B40C /**< Key store read area */ +#define AES_AES_KEY2_0 0x4008B500 /**< AES_KEY2_0 / AES_GHASH_H_IN_0 */ +#define AES_AES_KEY2_1 0x4008B504 /**< AES_KEY2_1 / AES_GHASH_H_IN_1 */ +#define AES_AES_KEY2_2 0x4008B508 /**< AES_KEY2_2 / AES_GHASH_H_IN_2 */ +#define AES_AES_KEY2_3 0x4008B50C /**< AES_KEY2_3 / AES_GHASH_H_IN_3 */ +#define AES_AES_KEY3_0 0x4008B510 /**< AES_KEY3_0 / AES_KEY2_4 */ +#define AES_AES_KEY3_1 0x4008B514 /**< AES_KEY3_1 / AES_KEY2_5 */ +#define AES_AES_KEY3_2 0x4008B518 /**< AES_KEY3_2 / AES_KEY2_6 */ +#define AES_AES_KEY3_3 0x4008B51C /**< AES_KEY3_3 / AES_KEY2_7 */ +#define AES_AES_IV_0 0x4008B540 /**< AES initialization vector */ +#define AES_AES_IV_1 0x4008B544 /**< AES initialization vector */ +#define AES_AES_IV_2 0x4008B548 /**< AES initialization vector */ +#define AES_AES_IV_3 0x4008B54C /**< AES initialization vector */ +#define AES_AES_CTRL 0x4008B550 /**< AES input/output buffer control and mode */ +#define AES_AES_C_LENGTH_0 0x4008B554 /**< AES crypto length (LSW) */ +#define AES_AES_C_LENGTH_1 0x4008B558 /**< AES crypto length (MSW) */ +#define AES_AES_AUTH_LENGTH 0x4008B55C /**< Authentication length */ +#define AES_AES_DATA_IN_OUT_0 0x4008B560 /**< Data input/output */ +#define AES_AES_DATA_IN_OUT_1 0x4008B564 /**< Data Input/Output */ +#define AES_AES_DATA_IN_OUT_2 0x4008B568 /**< Data Input/Output */ +#define AES_AES_DATA_IN_OUT_3 0x4008B56C /**< Data Input/Output */ +#define AES_AES_TAG_OUT_0 0x4008B570 /**< TAG */ +#define AES_AES_TAG_OUT_1 0x4008B574 /**< TAG */ +#define AES_AES_TAG_OUT_2 0x4008B578 /**< TAG */ +#define AES_AES_TAG_OUT_3 0x4008B57C /**< TAG */ +#define AES_HASH_DATA_IN_0 0x4008B600 /**< HASH data input */ +#define AES_HASH_DATA_IN_1 0x4008B604 /**< HASH data input */ +#define AES_HASH_DATA_IN_2 0x4008B608 /**< HASH data input */ +#define AES_HASH_DATA_IN_3 0x4008B60C /**< HASH data input */ +#define AES_HASH_DATA_IN_4 0x4008B610 /**< HASH data input */ +#define AES_HASH_DATA_IN_5 0x4008B614 /**< HASH data input */ +#define AES_HASH_DATA_IN_6 0x4008B618 /**< HASH data input */ +#define AES_HASH_DATA_IN_7 0x4008B61C /**< HASH data input */ +#define AES_HASH_DATA_IN_8 0x4008B620 /**< HASH data input */ +#define AES_HASH_DATA_IN_9 0x4008B624 /**< HASH data input */ +#define AES_HASH_DATA_IN_10 0x4008B628 /**< HASH data input */ +#define AES_HASH_DATA_IN_11 0x4008B62C /**< HASH data input */ +#define AES_HASH_DATA_IN_12 0x4008B630 /**< HASH data input */ +#define AES_HASH_DATA_IN_13 0x4008B634 /**< HASH data input */ +#define AES_HASH_DATA_IN_14 0x4008B638 /**< HASH data input */ +#define AES_HASH_DATA_IN_15 0x4008B63C /**< HASH data input */ +#define AES_HASH_IO_BUF_CTRL 0x4008B640 /**< Input/output buffer control and status */ +#define AES_HASH_MODE_IN 0x4008B644 /**< Hash mode */ +#define AES_HASH_LENGTH_IN_L 0x4008B648 /**< Hash length */ +#define AES_HASH_LENGTH_IN_H 0x4008B64C /**< Hash length */ +#define AES_HASH_DIGEST_A 0x4008B650 /**< Hash digest */ +#define AES_HASH_DIGEST_B 0x4008B654 /**< Hash digest */ +#define AES_HASH_DIGEST_C 0x4008B658 /**< Hash digest */ +#define AES_HASH_DIGEST_D 0x4008B65C /**< Hash digest */ +#define AES_HASH_DIGEST_E 0x4008B660 /**< Hash digest */ +#define AES_HASH_DIGEST_F 0x4008B664 /**< Hash digest */ +#define AES_HASH_DIGEST_G 0x4008B668 /**< Hash digest */ +#define AES_HASH_DIGEST_H 0x4008B66C /**< Hash digest */ +#define AES_CTRL_ALG_SEL 0x4008B700 /**< Algorithm select */ +#define AES_CTRL_PROT_EN 0x4008B704 /**< Master PROT privileged access enable */ +#define AES_CTRL_SW_RESET 0x4008B740 /**< Software reset */ +#define AES_CTRL_INT_CFG 0x4008B780 /**< Interrupt configuration */ +#define AES_CTRL_INT_EN 0x4008B784 /**< Interrupt enable */ +#define AES_CTRL_INT_CLR 0x4008B788 /**< Interrupt clear */ +#define AES_CTRL_INT_SET 0x4008B78C /**< Interrupt set */ +#define AES_CTRL_INT_STAT 0x4008B790 /**< Interrupt status */ +#define AES_CTRL_OPTIONS 0x4008B7F8 /**< Options */ +#define AES_CTRL_VERSION 0x4008B7FC /**< Version */ +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name AES_DMAC_CHx_CTRL registers bit fields + * @{ + */ +#define AES_DMAC_CH_CTRL_PRIO 0x00000002 /**< Channel priority 0: Low 1: High */ +#define AES_DMAC_CH_CTRL_EN 0x00000001 /**< Channel enable */ +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name AES_DMAC_CHx_DMALENGTH registers bit fields + * @{ + */ +#define AES_DMAC_CH_DMALENGTH_DMALEN_M \ + 0x0000FFFF /**< Channel DMA length in bytes mask */ +#define AES_DMAC_CH_DMALENGTH_DMALEN_S 0 /**< Channel DMA length in bytes shift */ +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name AES_DMAC_STATUS register bit fields + * @{ + */ +#define AES_DMAC_STATUS_PORT_ERR \ + 0x00020000 /**< AHB port transfer errors */ +#define AES_DMAC_STATUS_CH1_ACT 0x00000002 /**< Channel 1 active (DMA transfer on-going) */ +#define AES_DMAC_STATUS_CH0_ACT 0x00000001 /**< Channel 0 active (DMA transfer on-going) */ +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name AES_DMAC_SWRES register bit fields + * @{ + */ +#define AES_DMAC_SWRES_SWRES 0x00000001 /**< Software reset enable */ +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name AES_DMAC_MST_RUNPARAMS register bit fields + * @{ + */ +#define AES_DMAC_MST_RUNPARAMS_AHB_MST1_BURST_SIZE_4 \ + (2 << 12) /**< Maximum burst size: 4 bytes */ +#define AES_DMAC_MST_RUNPARAMS_AHB_MST1_BURST_SIZE_8 \ + (3 << 12) /**< Maximum burst size: 8 bytes */ +#define AES_DMAC_MST_RUNPARAMS_AHB_MST1_BURST_SIZE_16 \ + (4 << 12) /**< Maximum burst size: 16 bytes */ +#define AES_DMAC_MST_RUNPARAMS_AHB_MST1_BURST_SIZE_32 \ + (5 << 12) /**< Maximum burst size: 32 bytes */ +#define AES_DMAC_MST_RUNPARAMS_AHB_MST1_BURST_SIZE_64 \ + (6 << 12) /**< Maximum burst size: 64 bytes */ +#define AES_DMAC_MST_RUNPARAMS_AHB_MST1_BURST_SIZE_M \ + 0x0000F000 /**< Maximum burst size mask */ +#define AES_DMAC_MST_RUNPARAMS_AHB_MST1_BURST_SIZE_S \ + 12 /**< Maximum burst size shift */ +#define AES_DMAC_MST_RUNPARAMS_AHB_MST1_IDLE_EN \ + 0x00000800 /**< Idle insertion between bursts */ +#define AES_DMAC_MST_RUNPARAMS_AHB_MST1_INCR_EN \ + 0x00000400 /**< Fixed-length burst or single transfers */ +#define AES_DMAC_MST_RUNPARAMS_AHB_MST1_LOCK_EN \ + 0x00000200 /**< Locked transfers */ +#define AES_DMAC_MST_RUNPARAMS_AHB_MST1_BIGEND \ + 0x00000100 /**< Big endian AHB master */ +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name AES_DMAC_PERSR register bit fields + * @{ + */ +#define AES_DMAC_PERSR_PORT1_AHB_ERROR \ + 0x00001000 /**< AHB bus error */ +#define AES_DMAC_PERSR_PORT1_CHANNEL \ + 0x00000200 /**< Last serviced channel (0 or 1) */ +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name AES_DMAC_OPTIONS register bit fields + * @{ + */ +#define AES_DMAC_OPTIONS_NR_OF_CHANNELS_M \ + 0x00000F00 /**< Number of channels implemented mask */ +#define AES_DMAC_OPTIONS_NR_OF_CHANNELS_S \ + 8 /**< Number of channels implemented shift */ +#define AES_DMAC_OPTIONS_NR_OF_PORTS_M \ + 0x00000007 /**< Number of ports implemented mask */ +#define AES_DMAC_OPTIONS_NR_OF_PORTS_S 0 /**< Number of ports implemented shift */ +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name AES_DMAC_VERSION register bit fields + * @{ + */ +#define AES_DMAC_VERSION_HW_MAJOR_VERSION_M \ + 0x0F000000 /**< Major version number mask */ +#define AES_DMAC_VERSION_HW_MAJOR_VERSION_S \ + 24 /**< Major version number shift */ +#define AES_DMAC_VERSION_HW_MINOR_VERSION_M \ + 0x00F00000 /**< Minor version number mask */ +#define AES_DMAC_VERSION_HW_MINOR_VERSION_S \ + 20 /**< Minor version number shift */ +#define AES_DMAC_VERSION_HW_PATCH_LEVEL_M \ + 0x000F0000 /**< Patch level mask */ +#define AES_DMAC_VERSION_HW_PATCH_LEVEL_S \ + 16 /**< Patch level shift */ +#define AES_DMAC_VERSION_EIP_NUMBER_COMPL_M \ + 0x0000FF00 /**< EIP_NUMBER 1's complement mask */ +#define AES_DMAC_VERSION_EIP_NUMBER_COMPL_S \ + 8 /**< EIP_NUMBER 1's complement shift */ +#define AES_DMAC_VERSION_EIP_NUMBER_M \ + 0x000000FF /**< DMAC EIP-number mask */ +#define AES_DMAC_VERSION_EIP_NUMBER_S 0 /**< DMAC EIP-number shift */ +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name AES_KEY_STORE_SIZE register bit fields + * @{ + */ +#define AES_KEY_STORE_SIZE_KEY_SIZE_128 1 /**< Key size: 128 bits */ +#define AES_KEY_STORE_SIZE_KEY_SIZE_192 2 /**< Key size: 192 bits */ +#define AES_KEY_STORE_SIZE_KEY_SIZE_256 3 /**< Key size: 256 bits */ +#define AES_KEY_STORE_SIZE_KEY_SIZE_M \ + 0x00000003 /**< Key size mask */ +#define AES_KEY_STORE_SIZE_KEY_SIZE_S 0 /**< Key size shift */ +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name AES_KEY_STORE_READ_AREA register bit fields + * @{ + */ +#define AES_KEY_STORE_READ_AREA_BUSY \ + 0x80000000 /**< Key store operation busy */ +#define AES_KEY_STORE_READ_AREA_RAM_AREA_M \ + 0x0000000F /**< Key store RAM area select mask */ +#define AES_KEY_STORE_READ_AREA_RAM_AREA_S \ + 0 /**< Key store RAM area select shift */ +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name AES_AES_CTRL register bit fields + * @{ + */ +#define AES_AES_CTRL_CONTEXT_READY \ + 0x80000000 /**< Context data registers can be overwritten */ +#define AES_AES_CTRL_SAVED_CONTEXT_READY \ + 0x40000000 /**< AES auth. TAG and/or IV block(s) available */ +#define AES_AES_CTRL_SAVE_CONTEXT \ + 0x20000000 /**< Auth. TAG or result IV needs to be stored */ +#define AES_AES_CTRL_CCM_M_M 0x01C00000 /**< CCM auth. field length mask */ +#define AES_AES_CTRL_CCM_M_S 22 /**< CCM auth. field length shift */ +#define AES_AES_CTRL_CCM_L_M 0x00380000 /**< CCM length field width mask */ +#define AES_AES_CTRL_CCM_L_S 19 /**< CCM length field width shift */ +#define AES_AES_CTRL_CCM 0x00040000 /**< AES-CCM mode */ +#define AES_AES_CTRL_GCM 0x00030000 /**< AES-GCM mode */ +#define AES_AES_CTRL_CBC_MAC 0x00008000 /**< AES-CBC MAC mode */ +#define AES_AES_CTRL_CTR_WIDTH_32 (0 << 7) /**< CTR counter width: 32 bits */ +#define AES_AES_CTRL_CTR_WIDTH_64 (1 << 7) /**< CTR counter width: 64 bits */ +#define AES_AES_CTRL_CTR_WIDTH_96 (2 << 7) /**< CTR counter width: 96 bits */ +#define AES_AES_CTRL_CTR_WIDTH_128 \ + (3 << 7) /**< CTR counter width: 128 bits */ +#define AES_AES_CTRL_CTR_WIDTH_M \ + 0x00000180 /**< CTR counter width mask */ +#define AES_AES_CTRL_CTR_WIDTH_S 7 /**< CTR counter width shift */ +#define AES_AES_CTRL_CTR 0x00000040 /**< AES-CTR mode */ +#define AES_AES_CTRL_CBC 0x00000020 /**< AES-CBC mode */ +#define AES_AES_CTRL_KEY_SIZE_128 (1 << 3) /**< Key size: 128 bits */ +#define AES_AES_CTRL_KEY_SIZE_192 (2 << 3) /**< Key size: 192 bits */ +#define AES_AES_CTRL_KEY_SIZE_256 (3 << 3) /**< Key size: 256 bits */ +#define AES_AES_CTRL_KEY_SIZE_M 0x00000018 /**< Key size mask */ +#define AES_AES_CTRL_KEY_SIZE_S 3 /**< Key size shift */ +#define AES_AES_CTRL_DIRECTION_ENCRYPT \ + 0x00000004 /**< Encrypt */ +#define AES_AES_CTRL_INPUT_READY \ + 0x00000002 /**< AES input buffer empty */ +#define AES_AES_CTRL_OUTPUT_READY \ + 0x00000001 /**< AES output block available */ +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name AES_AES_C_LENGTH_1 register bit fields + * @{ + */ +#define AES_AES_C_LENGTH_1_C_LENGTH_M \ + 0x1FFFFFFF /**< Crypto length bits [60:32] mask */ +#define AES_AES_C_LENGTH_1_C_LENGTH_S 0 /**< Crypto length bits [60:32] shift */ +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name AES_HASH_IO_BUF_CTRL register bit fields + * @{ + */ +#define AES_HASH_IO_BUF_CTRL_PAD_DMA_MESSAGE \ + 0x00000080 /**< Hash engine message padding required */ +#define AES_HASH_IO_BUF_CTRL_GET_DIGEST \ + 0x00000040 /**< Hash engine digest requested */ +#define AES_HASH_IO_BUF_CTRL_PAD_MESSAGE \ + 0x00000020 /**< Last message data in HASH_DATA_IN, apply hash padding */ +#define AES_HASH_IO_BUF_CTRL_RFD_IN \ + 0x00000004 /**< Hash engine input buffer can accept new data */ +#define AES_HASH_IO_BUF_CTRL_DATA_IN_AV \ + 0x00000002 /**< Start processing HASH_DATA_IN data */ +#define AES_HASH_IO_BUF_CTRL_OUTPUT_FULL \ + 0x00000001 /**< Output buffer registers available */ +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name AES_HASH_MODE_IN register bit fields + * @{ + */ +#define AES_HASH_MODE_IN_SHA256_MODE \ + 0x00000008 /**< Hash mode */ +#define AES_HASH_MODE_IN_NEW_HASH \ + 0x00000001 /**< New hash session */ +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name AES_CTRL_ALG_SEL register bit fields + * @{ + */ +#define AES_CTRL_ALG_SEL_TAG 0x80000000 /**< DMA operation includes TAG */ +#define AES_CTRL_ALG_SEL_HASH 0x00000004 /**< Select hash engine as DMA destination */ +#define AES_CTRL_ALG_SEL_AES 0x00000002 /**< Select AES engine as DMA source/destination */ +#define AES_CTRL_ALG_SEL_KEYSTORE \ + 0x00000001 /**< Select Key Store as DMA destination */ +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name AES_CTRL_PROT_EN register bit fields + * @{ + */ +#define AES_CTRL_PROT_EN_PROT_EN \ + 0x00000001 /**< m_h_prot[1] asserted for DMA reads towards key store */ +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name AES_CTRL_SW_RESET register bit fields + * @{ + */ +#define AES_CTRL_SW_RESET_SW_RESET \ + 0x00000001 /**< Reset master control and key store */ +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name AES_CTRL_INT_CFG register bit fields + * @{ + */ +#define AES_CTRL_INT_CFG_LEVEL 0x00000001 /**< Level interrupt type */ +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name AES_CTRL_INT_EN register bit fields + * @{ + */ +#define AES_CTRL_INT_EN_DMA_IN_DONE \ + 0x00000002 /**< DMA input done interrupt enabled */ +#define AES_CTRL_INT_EN_RESULT_AV \ + 0x00000001 /**< Result available interrupt enabled */ +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name AES_CTRL_INT_CLR register bit fields + * @{ + */ +#define AES_CTRL_INT_CLR_DMA_BUS_ERR \ + 0x80000000 /**< Clear DMA bus error status */ +#define AES_CTRL_INT_CLR_KEY_ST_WR_ERR \ + 0x40000000 /**< Clear key store write error status */ +#define AES_CTRL_INT_CLR_KEY_ST_RD_ERR \ + 0x20000000 /**< Clear key store read error status */ +#define AES_CTRL_INT_CLR_DMA_IN_DONE \ + 0x00000002 /**< Clear DMA in done interrupt */ +#define AES_CTRL_INT_CLR_RESULT_AV \ + 0x00000001 /**< Clear result available interrupt */ +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name AES_CTRL_INT_SET register bit fields + * @{ + */ +#define AES_CTRL_INT_SET_DMA_IN_DONE \ + 0x00000002 /**< Set DMA data in done interrupt */ +#define AES_CTRL_INT_SET_RESULT_AV \ + 0x00000001 /**< Set result available interrupt */ +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name AES_CTRL_INT_STAT register bit fields + * @{ + */ +#define AES_CTRL_INT_STAT_DMA_BUS_ERR \ + 0x80000000 /**< DMA bus error detected */ +#define AES_CTRL_INT_STAT_KEY_ST_WR_ERR \ + 0x40000000 /**< Write error detected */ +#define AES_CTRL_INT_STAT_KEY_ST_RD_ERR \ + 0x20000000 /**< Read error detected */ +#define AES_CTRL_INT_STAT_DMA_IN_DONE \ + 0x00000002 /**< DMA data in done interrupt status */ +#define AES_CTRL_INT_STAT_RESULT_AV \ + 0x00000001 /**< Result available interrupt status */ +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name AES_CTRL_OPTIONS register bit fields + * @{ + */ +#define AES_CTRL_OPTIONS_TYPE_M 0xFF000000 /**< Device type mask */ +#define AES_CTRL_OPTIONS_TYPE_S 24 /**< Device type shift */ +#define AES_CTRL_OPTIONS_AHBINTERFACE \ + 0x00010000 /**< AHB interface available */ +#define AES_CTRL_OPTIONS_SHA_256 \ + 0x00000100 /**< The HASH core supports SHA-256 */ +#define AES_CTRL_OPTIONS_AES_CCM \ + 0x00000080 /**< AES-CCM available as single operation */ +#define AES_CTRL_OPTIONS_AES_GCM \ + 0x00000040 /**< AES-GCM available as single operation */ +#define AES_CTRL_OPTIONS_AES_256 \ + 0x00000020 /**< AES core supports 256-bit keys */ +#define AES_CTRL_OPTIONS_AES_128 \ + 0x00000010 /**< AES core supports 128-bit keys */ +#define AES_CTRL_OPTIONS_HASH 0x00000004 /**< HASH Core available */ +#define AES_CTRL_OPTIONS_AES 0x00000002 /**< AES core available */ +#define AES_CTRL_OPTIONS_KEYSTORE \ + 0x00000001 /**< KEY STORE available */ +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name AES_CTRL_VERSION register bit fields + * @{ + */ +#define AES_CTRL_VERSION_MAJOR_VERSION_M \ + 0x0F000000 /**< Major version number mask */ +#define AES_CTRL_VERSION_MAJOR_VERSION_S \ + 24 /**< Major version number shift */ +#define AES_CTRL_VERSION_MINOR_VERSION_M \ + 0x00F00000 /**< Minor version number mask */ +#define AES_CTRL_VERSION_MINOR_VERSION_S \ + 20 /**< Minor version number shift */ +#define AES_CTRL_VERSION_PATCH_LEVEL_M \ + 0x000F0000 /**< Patch level mask */ +#define AES_CTRL_VERSION_PATCH_LEVEL_S 16 /**< Patch level shift */ +#define AES_CTRL_VERSION_EIP_NUMBER_COMPL_M \ + 0x0000FF00 /**< EIP_NUMBER 1's complement mask */ +#define AES_CTRL_VERSION_EIP_NUMBER_COMPL_S \ + 8 /**< EIP_NUMBER 1's complement shift */ +#define AES_CTRL_VERSION_EIP_NUMBER_M \ + 0x000000FF /**< EIP-120t EIP-number mask */ +#define AES_CTRL_VERSION_EIP_NUMBER_S 0 /**< EIP-120t EIP-number shift */ +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name AES drivers return codes + * @{ + */ +#define AES_KEYSTORE_READ_ERROR 4 +#define AES_KEYSTORE_WRITE_ERROR 5 +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name AES functions + * @{ + */ + +/** \brief Writes the key into the Key RAM + * \param key Pointer to AES Key + * \param key_area Area in Key RAM where to store the key (0 to 7) + * \return \c CRYPTO_SUCCESS if successful, or CRYPTO/AES error code + */ +uint8_t aes_load_key(const void *key, uint8_t key_area); + +/** @} */ + +#endif /* AES_H_ */ + +/** + * @} + * @} + */ diff --git a/cpu/cc2538/dev/ccm.c b/cpu/cc2538/dev/ccm.c new file mode 100644 index 000000000..b18992802 --- /dev/null +++ b/cpu/cc2538/dev/ccm.c @@ -0,0 +1,376 @@ +/* + * Original file: + * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ + * All rights reserved. + * + * Port to Contiki: + * Copyright (c) 2013, ADVANSEE - http://www.advansee.com/ + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/** + * \addtogroup cc2538-ccm + * @{ + * + * \file + * Implementation of the cc2538 AES-CCM driver + */ +#include "contiki.h" +#include "sys/cc.h" +#include "dev/rom-util.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) +{ + uint32_t iv[4]; + + /* 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; + return AES_KEYSTORE_READ_ERROR; + } + + /* Prepare the encryption 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-128 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_KEY_SIZE_128 | /* Key = 128 */ + AES_AES_CTRL_DIRECTION_ENCRYPT; /* Encryption */ + + /* 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; + 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; + + /* 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 tag[4]; + + if(REG(AES_CTRL_INT_STAT) & AES_CTRL_INT_STAT_DMA_BUS_ERR) { + /* Clear the DMA error bit */ + REG(AES_CTRL_INT_CLR) = AES_CTRL_INT_CLR_DMA_BUS_ERR; + return CRYPTO_DMA_BUS_ERROR; + } + if(REG(AES_CTRL_INT_STAT) & AES_CTRL_INT_STAT_KEY_ST_WR_ERR) { + /* Clear the Key Store Write error bit */ + REG(AES_CTRL_INT_CLR) = AES_CTRL_INT_CLR_KEY_ST_WR_ERR; + return AES_KEYSTORE_WRITE_ERROR; + } + if(REG(AES_CTRL_INT_STAT) & AES_CTRL_INT_STAT_KEY_ST_RD_ERR) { + /* Clear the Key Store Read error bit */ + REG(AES_CTRL_INT_CLR) = AES_CTRL_INT_CLR_KEY_ST_RD_ERR; + return AES_KEYSTORE_READ_ERROR; + } + + /* Disable the master control / DMA clock */ + REG(AES_CTRL_ALG_SEL) = 0x00000000; + + /* 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); + + return CRYPTO_SUCCESS; +} +/*---------------------------------------------------------------------------*/ +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) +{ + uint16_t pdata_len = cdata_len - mic_len; + uint32_t iv[4]; + + /* 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; + 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-128 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 */ + AES_AES_CTRL_KEY_SIZE_128; /* Key = 128 */ + + /* 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; + 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; + + /* 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(); +} +/*---------------------------------------------------------------------------*/ +uint8_t +ccm_auth_decrypt_get_result(const void *cdata, uint16_t cdata_len, + void *mic, uint8_t mic_len) +{ + uint16_t pdata_len = cdata_len - mic_len; + uint32_t tag[4]; + + 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; + return CRYPTO_DMA_BUS_ERROR; + } + if(REG(AES_CTRL_INT_STAT) & AES_CTRL_INT_STAT_KEY_ST_WR_ERR) { + /* Clear the Key Store Write error bit */ + REG(AES_CTRL_INT_CLR) = AES_CTRL_INT_CLR_KEY_ST_WR_ERR; + return AES_KEYSTORE_WRITE_ERROR; + } + if(REG(AES_CTRL_INT_STAT) & AES_CTRL_INT_STAT_KEY_ST_RD_ERR) { + /* Clear the Key Store Read error bit */ + REG(AES_CTRL_INT_CLR) = AES_CTRL_INT_CLR_KEY_ST_RD_ERR; + return AES_KEYSTORE_READ_ERROR; + } + + /* Disable the master control / DMA clock */ + REG(AES_CTRL_ALG_SEL) = 0x00000000; + + /* 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; +} + +/** @} */ diff --git a/cpu/cc2538/dev/ccm.h b/cpu/cc2538/dev/ccm.h new file mode 100644 index 000000000..65c4e36b3 --- /dev/null +++ b/cpu/cc2538/dev/ccm.h @@ -0,0 +1,137 @@ +/* + * Original file: + * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ + * All rights reserved. + * + * Port to Contiki: + * Copyright (c) 2013, ADVANSEE - http://www.advansee.com/ + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/** + * \addtogroup cc2538-aes + * @{ + * + * \defgroup cc2538-ccm cc2538 AES-CCM + * + * Driver for the cc2538 AES-CCM mode of the security core + * @{ + * + * \file + * Header file for the cc2538 AES-CCM driver + */ +#ifndef CCM_H_ +#define CCM_H_ + +#include "contiki.h" +#include "dev/aes.h" + +#include +#include +/*---------------------------------------------------------------------------*/ +/** \name AES-CCM driver return codes + * @{ + */ +#define CCM_AUTHENTICATION_FAILED 6 +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name AES-CCM functions + * @{ + */ + +/** \brief Starts the CCM authentication and encryption operation + * \param len_len Number of octets in length field (2, 4 or 8) + * \param key_area Area in Key RAM where the key is stored (0 to 7) + * \param nonce Pointer to nonce (15 - \p len_len octets) + * \param adata Pointer to additional authenticated data, or \c NULL + * \param adata_len Length of additional authenticated data in octets, or \c 0 + * \param pdata Pointer to message to authenticate and encrypt, or \c NULL + * \param pdata_len Length of message to authenticate and encrypt in octets, or \c 0 + * \param mic_len Number of octets in authentication field (even value between 0 and 16) + * \return \c CRYPTO_SUCCESS if successful, or CRYPTO/AES/CCM error code + */ +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); + +/** \brief Checks the status of the CCM authentication and encryption operation + * \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); + +/** \brief Gets the result of the CCM authentication and encryption operation + * \param mic Pointer to authentication field, or \c NULL + * \param mic_len Number of octets in authentication field (even value between 0 and 16) + * \return \c CRYPTO_SUCCESS if successful, or CRYPTO/AES/CCM error code + * \note This function must be called only after \c ccm_auth_encrypt_start(). + */ +uint8_t ccm_auth_encrypt_get_result(void *mic, uint8_t mic_len); + +/** \brief Starts the CCM authentication checking and decryption operation + * \param len_len Number of octets in length field (2, 4 or 8) + * \param key_area Area in Key RAM where the key is stored (0 to 7) + * \param nonce Pointer to nonce (15 - \p len_len octets) + * \param adata Pointer to additional authenticated data, or \c NULL + * \param adata_len Length of additional authenticated data in octets, or \c 0 + * \param cdata Pointer to encrypted and authenticated message + * \param cdata_len Length of encrypted and authenticated message in octets + * \param mic_len Number of octets in authentication field (even value between 0 and 16) + * \return \c CRYPTO_SUCCESS if successful, or CRYPTO/AES/CCM error code + */ +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); + +/** \brief Checks the status of the CCM authentication checking and decryption operation + * \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); + +/** \brief Gets the result of the CCM authentication checking and decryption operation + * \param cdata Pointer to encrypted and authenticated message + * \param cdata_len Length of encrypted and authenticated message in octets + * \param mic Pointer to authentication field, or \c NULL + * \param mic_len Number of octets in authentication field (even value between 0 and 16) + * \return \c CRYPTO_SUCCESS if successful, or CRYPTO/AES/CCM error code + * \note This function must be called only after \c ccm_auth_decrypt_start(). + */ +uint8_t ccm_auth_decrypt_get_result(const void *cdata, uint16_t cdata_len, + void *mic, uint8_t mic_len); + +/** @} */ + +#endif /* CCM_H_ */ + +/** + * @} + * @} + */ diff --git a/cpu/cc2538/dev/crypto.c b/cpu/cc2538/dev/crypto.c new file mode 100644 index 000000000..faf3845b0 --- /dev/null +++ b/cpu/cc2538/dev/crypto.c @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2013, ADVANSEE - http://www.advansee.com/ + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/** + * \addtogroup cc2538-crypto + * @{ + * + * \file + * Implementation of the cc2538 AES/SHA cryptoprocessor driver + */ +#include "contiki.h" +#include "dev/sys-ctrl.h" +#include "dev/crypto.h" +#include "reg.h" +/*---------------------------------------------------------------------------*/ +void +crypto_init(void) +{ + volatile int i; + + crypto_enable(); + + /* Reset the AES/SHA cryptoprocessor */ + REG(SYS_CTRL_SRSEC) |= SYS_CTRL_SRSEC_AES; + for(i = 0; i < 16; i++); + REG(SYS_CTRL_SRSEC) &= ~SYS_CTRL_SRSEC_AES; +} +/*---------------------------------------------------------------------------*/ +void +crypto_enable(void) +{ + /* Enable the clock for the AES/SHA cryptoprocessor */ + REG(SYS_CTRL_RCGCSEC) |= SYS_CTRL_RCGCSEC_AES; + REG(SYS_CTRL_SCGCSEC) |= SYS_CTRL_SCGCSEC_AES; + REG(SYS_CTRL_DCGCSEC) |= SYS_CTRL_DCGCSEC_AES; +} +/*---------------------------------------------------------------------------*/ +void +crypto_disable(void) +{ + /* Gate the clock for the AES/SHA cryptoprocessor */ + REG(SYS_CTRL_RCGCSEC) &= ~SYS_CTRL_RCGCSEC_AES; + REG(SYS_CTRL_SCGCSEC) &= ~SYS_CTRL_SCGCSEC_AES; + REG(SYS_CTRL_DCGCSEC) &= ~SYS_CTRL_DCGCSEC_AES; +} + +/** @} */ diff --git a/cpu/cc2538/dev/crypto.h b/cpu/cc2538/dev/crypto.h new file mode 100644 index 000000000..e51111602 --- /dev/null +++ b/cpu/cc2538/dev/crypto.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2013, ADVANSEE - http://www.advansee.com/ + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/** + * \addtogroup cc2538 + * @{ + * + * \defgroup cc2538-crypto cc2538 AES/SHA cryptoprocessor + * + * Driver for the cc2538 AES/SHA cryptoprocessor + * @{ + * + * \file + * Header file for the cc2538 AES/SHA cryptoprocessor driver + */ +#ifndef CRYPTO_H_ +#define CRYPTO_H_ + +#include "contiki.h" +/*---------------------------------------------------------------------------*/ +/** \name Crypto drivers return codes + * @{ + */ +#define CRYPTO_SUCCESS 0 +#define CRYPTO_INVALID_PARAM 1 +#define CRYPTO_NULL_ERROR 2 +#define CRYPTO_DMA_BUS_ERROR 3 +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name Crypto functions + * @{ + */ + +/** \brief Enables and resets the AES/SHA cryptoprocessor + */ +void crypto_init(void); + +/** \brief Enables the AES/SHA cryptoprocessor + */ +void crypto_enable(void); + +/** \brief Disables the AES/SHA cryptoprocessor + * \note Call this function to save power when the cryptoprocessor is unused. + */ +void crypto_disable(void); + +/** @} */ + +#endif /* CRYPTO_H_ */ + +/** + * @} + * @} + */ diff --git a/cpu/cc2538/dev/sha256.c b/cpu/cc2538/dev/sha256.c new file mode 100644 index 000000000..16067c2ce --- /dev/null +++ b/cpu/cc2538/dev/sha256.c @@ -0,0 +1,344 @@ +/* + * Original file: + * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ + * All rights reserved. + * + * Port to Contiki: + * Copyright (c) 2013, ADVANSEE - http://www.advansee.com/ + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/** + * \addtogroup cc2538-sha256 + * @{ + * + * \file + * Implementation of the cc2538 SHA-256 driver + */ +#include "contiki.h" +#include "sys/cc.h" +#include "dev/rom-util.h" +#include "dev/aes.h" +#include "dev/sha256.h" +#include "reg.h" + +#include +#include +/*---------------------------------------------------------------------------*/ +#define BLOCK_SIZE 64 +#define OUTPUT_LEN 32 +/*---------------------------------------------------------------------------*/ +/** \brief Starts a new hash session in hardware + * \param state Hash state + * \param data Pointer to input message + * \param hash Destination of the hash (32 bytes) + * \return \c CRYPTO_SUCCESS if successful, or CRYPTO/SHA256 error code + */ +static uint8_t +new_hash(sha256_state_t *state, const void *data, void *hash) +{ + /* 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; + + /* Configure master control module and enable DMA path to the SHA-256 engine + * + Digest readout */ + REG(AES_CTRL_ALG_SEL) = AES_CTRL_ALG_SEL_TAG | AES_CTRL_ALG_SEL_HASH; + + /* Clear any outstanding events */ + REG(AES_CTRL_INT_CLR) = AES_CTRL_INT_CLR_RESULT_AV; + + /* Configure hash engine + * Indicate start of a new hash session and SHA-256 */ + REG(AES_HASH_MODE_IN) = AES_HASH_MODE_IN_SHA256_MODE | + AES_HASH_MODE_IN_NEW_HASH; + + /* If the final digest is required (pad the input DMA data), write the + * following register */ + if(state->final_digest) { + /* Write length of the message (lo) */ + REG(AES_HASH_LENGTH_IN_L) = (uint32_t)state->length; + /* Write length of the message (hi) */ + REG(AES_HASH_LENGTH_IN_H) = (uint32_t)(state->length >> 32); + /* Pad the DMA-ed data */ + REG(AES_HASH_IO_BUF_CTRL) = AES_HASH_IO_BUF_CTRL_PAD_DMA_MESSAGE; + } + + /* Enable DMA channel 0 for message data */ + REG(AES_DMAC_CH0_CTRL) = AES_DMAC_CH_CTRL_EN; + /* Base address of the data in ext. memory */ + REG(AES_DMAC_CH0_EXTADDR) = (uint32_t)data; + if(state->final_digest) { + /* Input data length in bytes, equal to the message */ + REG(AES_DMAC_CH0_DMALENGTH) = state->curlen; + } else { + REG(AES_DMAC_CH0_DMALENGTH) = BLOCK_SIZE; + } + + /* Enable DMA channel 1 for result digest */ + REG(AES_DMAC_CH1_CTRL) = AES_DMAC_CH_CTRL_EN; + /* Base address of the digest buffer */ + REG(AES_DMAC_CH1_EXTADDR) = (uint32_t)hash; + /* Length of the result digest */ + REG(AES_DMAC_CH1_DMALENGTH) = OUTPUT_LEN; + + /* Wait for completion of the operation */ + while(!(REG(AES_CTRL_INT_STAT) & AES_CTRL_INT_STAT_RESULT_AV)); + + 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; + return CRYPTO_DMA_BUS_ERROR; + } + + /* Clear the interrupt */ + REG(AES_CTRL_INT_CLR) = AES_CTRL_INT_CLR_DMA_IN_DONE | + AES_CTRL_INT_CLR_RESULT_AV; + /* Disable master control / DMA clock */ + REG(AES_CTRL_ALG_SEL) = 0x00000000; + /* Clear mode */ + REG(AES_AES_CTRL) = 0x00000000; + + return CRYPTO_SUCCESS; +} +/*---------------------------------------------------------------------------*/ +/** \brief Resumes an already started hash session in hardware + * \param state Hash state + * \param data Pointer to the input message + * \param hash Pointer to the destination of the hash (32 bytes) + * \return \c CRYPTO_SUCCESS if successful, or CRYPTO/SHA256 error code + */ +static uint8_t +resume_hash(sha256_state_t *state, const void *data, void *hash) +{ + /* 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; + + /* Configure master control module and enable the DMA path to the SHA-256 + * engine */ + REG(AES_CTRL_ALG_SEL) = AES_CTRL_ALG_SEL_HASH; + + /* Clear any outstanding events */ + REG(AES_CTRL_INT_CLR) = AES_CTRL_INT_CLR_RESULT_AV; + + /* Configure hash engine + * Indicate the start of a resumed hash session and SHA-256 */ + REG(AES_HASH_MODE_IN) = AES_HASH_MODE_IN_SHA256_MODE; + + /* If the final digest is required (pad the input DMA data) */ + if(state->final_digest) { + /* Write length of the message (lo) */ + REG(AES_HASH_LENGTH_IN_L) = (uint32_t)state->length; + /* Write length of the message (hi) */ + REG(AES_HASH_LENGTH_IN_H) = (uint32_t)(state->length >> 32); + } + + /* Write the initial digest */ + REG(AES_HASH_DIGEST_A) = (uint32_t)state->state[0]; + REG(AES_HASH_DIGEST_B) = (uint32_t)state->state[1]; + REG(AES_HASH_DIGEST_C) = (uint32_t)state->state[2]; + REG(AES_HASH_DIGEST_D) = (uint32_t)state->state[3]; + REG(AES_HASH_DIGEST_E) = (uint32_t)state->state[4]; + REG(AES_HASH_DIGEST_F) = (uint32_t)state->state[5]; + REG(AES_HASH_DIGEST_G) = (uint32_t)state->state[6]; + REG(AES_HASH_DIGEST_H) = (uint32_t)state->state[7]; + + /* If final digest, pad the DMA-ed data */ + if(state->final_digest) { + REG(AES_HASH_IO_BUF_CTRL) = AES_HASH_IO_BUF_CTRL_PAD_DMA_MESSAGE; + } + + /* Enable DMA channel 0 for message data */ + REG(AES_DMAC_CH0_CTRL) = AES_DMAC_CH_CTRL_EN; + /* Base address of the data in ext. memory */ + REG(AES_DMAC_CH0_EXTADDR) = (uint32_t)data; + /* Input data length in bytes, equal to the message */ + if(state->final_digest) { + REG(AES_DMAC_CH0_DMALENGTH) = state->curlen; + } else { + REG(AES_DMAC_CH0_DMALENGTH) = BLOCK_SIZE; + } + + /* Wait for completion of the operation */ + while(!(REG(AES_CTRL_INT_STAT) & AES_CTRL_INT_STAT_RESULT_AV)); + + /* Check for any DMA Bus errors */ + 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; + return CRYPTO_DMA_BUS_ERROR; + } + + /* Read digest */ + ((uint32_t *)hash)[0] = REG(AES_HASH_DIGEST_A); + ((uint32_t *)hash)[1] = REG(AES_HASH_DIGEST_B); + ((uint32_t *)hash)[2] = REG(AES_HASH_DIGEST_C); + ((uint32_t *)hash)[3] = REG(AES_HASH_DIGEST_D); + ((uint32_t *)hash)[4] = REG(AES_HASH_DIGEST_E); + ((uint32_t *)hash)[5] = REG(AES_HASH_DIGEST_F); + ((uint32_t *)hash)[6] = REG(AES_HASH_DIGEST_G); + ((uint32_t *)hash)[7] = REG(AES_HASH_DIGEST_H); + + /* Acknowledge reading of the digest */ + REG(AES_HASH_IO_BUF_CTRL) = AES_HASH_IO_BUF_CTRL_OUTPUT_FULL; + + /* Clear the interrupt */ + REG(AES_CTRL_INT_CLR) = AES_CTRL_INT_CLR_DMA_IN_DONE | + AES_CTRL_INT_CLR_RESULT_AV; + /* Disable master control / DMA clock */ + REG(AES_CTRL_ALG_SEL) = 0x00000000; + /* Clear mode */ + REG(AES_AES_CTRL) = 0x00000000; + + return CRYPTO_SUCCESS; +} +/*---------------------------------------------------------------------------*/ +uint8_t +sha256_init(sha256_state_t *state) +{ + if(state == NULL) { + return CRYPTO_NULL_ERROR; + } + + state->curlen = 0; + state->length = 0; + state->new_digest = true; + state->final_digest = false; + return CRYPTO_SUCCESS; +} +/*---------------------------------------------------------------------------*/ +uint8_t +sha256_process(sha256_state_t *state, const void *data, uint32_t len) +{ + uint32_t n; + uint8_t ret; + + if(state == NULL || data == NULL) { + return CRYPTO_NULL_ERROR; + } + + if(state->curlen > sizeof(state->buf)) { + return CRYPTO_INVALID_PARAM; + } + + if(len > 0 && state->new_digest) { + if(state->curlen == 0 && len > BLOCK_SIZE) { + rom_util_memcpy(state->buf, data, BLOCK_SIZE); + ret = new_hash(state, state->buf, state->state); + if(ret != CRYPTO_SUCCESS) { + return ret; + } + state->new_digest = false; + state->length += BLOCK_SIZE << 3; + data += BLOCK_SIZE; + len -= BLOCK_SIZE; + } else { + n = MIN(len, BLOCK_SIZE - state->curlen); + rom_util_memcpy(&state->buf[state->curlen], data, n); + state->curlen += n; + data += n; + len -= n; + if(state->curlen == BLOCK_SIZE && len > 0) { + ret = new_hash(state, state->buf, state->state); + if(ret != CRYPTO_SUCCESS) { + return ret; + } + state->new_digest = false; + state->length += BLOCK_SIZE << 3; + state->curlen = 0; + } + } + } + + while(len > 0 && !state->new_digest) { + if(state->curlen == 0 && len > BLOCK_SIZE) { + rom_util_memcpy(state->buf, data, BLOCK_SIZE); + ret = resume_hash(state, state->buf, state->state); + if(ret != CRYPTO_SUCCESS) { + return ret; + } + state->length += BLOCK_SIZE << 3; + data += BLOCK_SIZE; + len -= BLOCK_SIZE; + } else { + n = MIN(len, BLOCK_SIZE - state->curlen); + rom_util_memcpy(&state->buf[state->curlen], data, n); + state->curlen += n; + data += n; + len -= n; + if(state->curlen == BLOCK_SIZE && len > 0) { + ret = resume_hash(state, state->buf, state->state); + if(ret != CRYPTO_SUCCESS) { + return ret; + } + state->length += BLOCK_SIZE << 3; + state->curlen = 0; + } + } + } + + return CRYPTO_SUCCESS; +} +/*---------------------------------------------------------------------------*/ +uint8_t +sha256_done(sha256_state_t *state, void *hash) +{ + uint8_t ret; + + if(state == NULL || hash == NULL) { + return CRYPTO_NULL_ERROR; + } + + if(state->curlen > sizeof(state->buf)) { + return CRYPTO_INVALID_PARAM; + } + + /* Increase the length of the message */ + state->length += state->curlen << 3; + state->final_digest = true; + if(state->new_digest) { + ret = new_hash(state, state->buf, hash); + if(ret != CRYPTO_SUCCESS) { + return ret; + } + } else { + ret = resume_hash(state, state->buf, hash); + if(ret != CRYPTO_SUCCESS) { + return ret; + } + } + state->new_digest = false; + state->final_digest = false; + + return CRYPTO_SUCCESS; +} + +/** @} */ diff --git a/cpu/cc2538/dev/sha256.h b/cpu/cc2538/dev/sha256.h new file mode 100644 index 000000000..b2e799bd8 --- /dev/null +++ b/cpu/cc2538/dev/sha256.h @@ -0,0 +1,103 @@ +/* + * Original file: + * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ + * All rights reserved. + * + * Port to Contiki: + * Copyright (c) 2013, ADVANSEE - http://www.advansee.com/ + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/** + * \addtogroup cc2538-crypto + * @{ + * + * \defgroup cc2538-sha526 cc2538 SHA-256 + * + * Driver for the cc2538 SHA-256 mode of the security core + * @{ + * + * \file + * Header file for the cc2538 SHA-256 driver + */ +#ifndef SHA256_H_ +#define SHA256_H_ + +#include "contiki.h" +#include "dev/crypto.h" + +#include +/*---------------------------------------------------------------------------*/ +/** \name SHA-256 structures + * @{ + */ +typedef struct { + uint64_t length; + uint32_t state[8]; + uint32_t curlen; + uint8_t buf[64]; + uint8_t new_digest; + uint8_t final_digest; +} sha256_state_t; +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name SHA-256 functions + * @{ + */ + +/** \brief Initializes the hash state + * \param state Pointer to hash state to initialize + * \return \c CRYPTO_SUCCESS if successful, or CRYPTO/SHA256 error code + */ +uint8_t sha256_init(sha256_state_t *state); + +/** \brief Processes a block of memory through the hash + * \param state Pointer to hash state + * \param data Pointer to the data to hash + * \param len Length of the data to hash in bytes (octets) + * \return \c CRYPTO_SUCCESS if successful, or CRYPTO/SHA256 error code + * \note This function must be called only after \c sha256_init(). + */ +uint8_t sha256_process(sha256_state_t *state, const void *data, uint32_t len); + +/** \brief Terminates hash session to get the digest + * \param state Pointer to hash state + * \param hash Pointer to hash + * \return \c CRYPTO_SUCCESS if successful, or CRYPTO/SHA256 error code + * \note This function must be called only after \c sha256_process(). + */ +uint8_t sha256_done(sha256_state_t *state, void *hash); + +/** @} */ + +#endif /* SHA256_H_ */ + +/** + * @} + * @} + */ diff --git a/cpu/cc2538/dev/sys-ctrl.h b/cpu/cc2538/dev/sys-ctrl.h index a8b61932e..3fda071fe 100644 --- a/cpu/cc2538/dev/sys-ctrl.h +++ b/cpu/cc2538/dev/sys-ctrl.h @@ -161,6 +161,34 @@ #define SYS_CTRL_SRGPT_GPT0 0x00000001 /**< GPT0 is reset */ /** @} */ /*---------------------------------------------------------------------------*/ +/** \name SYS_CTRL_RCGCSEC register bit masks + * @{ + */ +#define SYS_CTRL_RCGCSEC_AES 0x00000002 /**< AES clock enable, CPU running */ +#define SYS_CTRL_RCGCSEC_PKA 0x00000001 /**< PKA clock enable, CPU running */ +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name SYS_CTRL_SCGCSEC register bit masks + * @{ + */ +#define SYS_CTRL_SCGCSEC_AES 0x00000002 /**< AES clock enable, CPU IDLE */ +#define SYS_CTRL_SCGCSEC_PKA 0x00000001 /**< PKA clock enable, CPU IDLE */ +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name SYS_CTRL_DCGCSEC register bit masks + * @{ + */ +#define SYS_CTRL_DCGCSEC_AES 0x00000002 /**< AES clock enable, PM0 */ +#define SYS_CTRL_DCGCSEC_PKA 0x00000001 /**< PKA clock enable, PM0 */ +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name SYS_CTRL_SRSEC register bits + * @{ + */ +#define SYS_CTRL_SRSEC_AES 0x00000002 /**< AES is reset */ +#define SYS_CTRL_SRSEC_PKA 0x00000001 /**< PKA is reset */ +/** @} */ +/*---------------------------------------------------------------------------*/ /** \name SYS_CTRL_PWRDBG register bits * @{ */ diff --git a/examples/cc2538dk/crypto/Makefile b/examples/cc2538dk/crypto/Makefile new file mode 100644 index 000000000..513e37676 --- /dev/null +++ b/examples/cc2538dk/crypto/Makefile @@ -0,0 +1,6 @@ +CONTIKI_PROJECT = ccm-test sha256-test + +all: $(CONTIKI_PROJECT) + +CONTIKI = ../../.. +include $(CONTIKI)/Makefile.include diff --git a/examples/cc2538dk/crypto/Makefile.target b/examples/cc2538dk/crypto/Makefile.target new file mode 100644 index 000000000..777593c88 --- /dev/null +++ b/examples/cc2538dk/crypto/Makefile.target @@ -0,0 +1 @@ +TARGET = cc2538dk diff --git a/examples/cc2538dk/crypto/ccm-test.c b/examples/cc2538dk/crypto/ccm-test.c new file mode 100644 index 000000000..e303c77ef --- /dev/null +++ b/examples/cc2538dk/crypto/ccm-test.c @@ -0,0 +1,345 @@ +/* + * Original file: + * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/ + * All rights reserved. + * + * Port to Contiki: + * Copyright (c) 2013, ADVANSEE - http://www.advansee.com/ + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/** + * \addtogroup cc2538-examples + * @{ + * + * \defgroup cc2538-ccm-test cc2538dk AES-CCM Test Project + * + * AES-CCM access example for CC2538 on SmartRF06EB. + * + * This example shows how AES-CCM should be used. The example also verifies + * the AES-CCM functionality. + * + * @{ + * + * \file + * Example demonstrating AES-CCM on the cc2538dk platform + */ +#include "contiki.h" +#include "sys/rtimer.h" +#include "dev/rom-util.h" +#include "dev/ccm.h" + +#include +#include +#include +/*---------------------------------------------------------------------------*/ +PROCESS(ccm_test_process, "ccm test process"); +AUTOSTART_PROCESSES(&ccm_test_process); +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(ccm_test_process, ev, data) +{ + static const char *const str_res[] = { + "success", + "invalid param", + "NULL error", + "DMA bus error", + "keystore read error", + "keystore write error", + "authentication failed" + }; + static struct { + bool encrypt; + uint8_t len_len; + uint8_t key[16]; + uint8_t key_area; + uint8_t nonce[13]; + uint8_t adata[26]; + uint16_t adata_len; + uint8_t mdata[24]; + uint16_t mdata_len; + uint8_t mic[8]; + uint8_t mic_len; + uint8_t expected[24]; + } vectors[] = { + { + true, /* encrypt */ + 2, /* len_len */ + { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* key */ + 0, /* key_area */ + { 0x00, 0x00, 0xf0, 0xe0, 0xd0, 0xc0, 0xb0, 0xa0, + 0x00, 0x00, 0x00, 0x00, 0x05 }, /* nonce */ + {}, /* adata */ + 0, /* adata_len */ + { 0x14, 0xaa, 0xbb, 0x00, 0x00, 0x01, 0x02, 0x03, + 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f }, /* mdata */ + 20, /* mdata_len */ + {}, /* mic */ + 0, /* mic_len */ + { 0x92, 0xe8, 0xad, 0xca, 0x53, 0x81, 0xbf, 0xd0, + 0x5b, 0xdd, 0xf3, 0x61, 0x09, 0x09, 0x82, 0xe6, + 0x2c, 0x61, 0x01, 0x4e } /* expected */ + }, { + true, /* encrypt */ + 2, /* len_len */ + { 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf }, /* key */ + 0, /* key_area */ + { 0xac, 0xde, 0x48, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x05, 0x02 }, /* nonce */ + { 0x08, 0xd0, 0x84, 0x21, 0x43, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x48, 0xde, 0xac, 0x02, 0x05, 0x00, + 0x00, 0x00, 0x55, 0xcf, 0x00, 0x00, 0x51, 0x52, + 0x53, 0x54 }, /* adata */ + 26, /* adata_len */ + {}, /* mdata */ + 0, /* mdata_len */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* mic */ + 8, /* mic_len */ + { 0x22, 0x3b, 0xc1, 0xec, 0x84, 0x1a, 0xb5, 0x53 } /* expected */ + }, { + true, /* encrypt */ + 2, /* len_len */ + { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* key */ + 0, /* key_area */ + { 0x00, 0x00, 0xf0, 0xe0, 0xd0, 0xc0, 0xb0, 0xa0, + 0x00, 0x00, 0x00, 0x00, 0x05 }, /* nonce */ + { 0x69, 0x98, 0x03, 0x33, 0x63, 0xbb, 0xaa, 0x01, + 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x03 }, /* adata */ + 15, /* adata_len */ + { 0x14, 0xaa, 0xbb, 0x00, 0x00, 0x01, 0x02, 0x03, + 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f }, /* mdata */ + 20, /* mdata_len */ + { 0x00, 0x00, 0x00, 0x00 }, /* mic */ + 4, /* mic_len */ + { 0x92, 0xe8, 0xad, 0xca, 0x53, 0x81, 0xbf, 0xd0, + 0x5b, 0xdd, 0xf3, 0x61, 0x09, 0x09, 0x82, 0xe6, + 0x2c, 0x61, 0x01, 0x4e, 0x7b, 0x34, 0x4f, 0x09 } /* expected */ + }, { + false, /* decrypt */ + 2, /* len_len */ + { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* key */ + 0, /* key_area */ + { 0x00, 0x00, 0xf0, 0xe0, 0xd0, 0xc0, 0xb0, 0xa0, + 0x00, 0x00, 0x00, 0x00, 0x05 }, /* nonce */ + {}, /* adata */ + 0, /* adata_len */ + { 0x92, 0xe8, 0xad, 0xca, 0x53, 0x81, 0xbf, 0xd0, + 0x5b, 0xdd, 0xf3, 0x61, 0x09, 0x09, 0x82, 0xe6, + 0x2c, 0x61, 0x01, 0x4e }, /* mdata */ + 20, /* mdata_len */ + {}, /* mic */ + 0, /* mic_len */ + { 0x14, 0xaa, 0xbb, 0x00, 0x00, 0x01, 0x02, 0x03, + 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f } /* expected */ + }, { + false, /* decrypt */ + 2, /* len_len */ + { 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf }, /* key */ + 0, /* key_area */ + { 0xac, 0xde, 0x48, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x05, 0x02 }, /* nonce */ + { 0x08, 0xd0, 0x84, 0x21, 0x43, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x48, 0xde, 0xac, 0x02, 0x05, 0x00, + 0x00, 0x00, 0x55, 0xcf, 0x00, 0x00, 0x51, 0x52, + 0x53, 0x54 }, /* adata */ + 26, /* adata_len */ + { 0x22, 0x3b, 0xc1, 0xec, 0x84, 0x1a, 0xb5, 0x53 }, /* mdata */ + 8, /* mdata_len */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* mic */ + 8, /* mic_len */ + {} /* expected */ + }, { + false, /* decrypt */ + 2, /* len_len */ + { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* key */ + 0, /* key_area */ + { 0x00, 0x00, 0xf0, 0xe0, 0xd0, 0xc0, 0xb0, 0xa0, + 0x00, 0x00, 0x00, 0x00, 0x05 }, /* nonce */ + { 0x69, 0x98, 0x03, 0x33, 0x63, 0xbb, 0xaa, 0x01, + 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x03 }, /* adata */ + 15, /* adata_len */ + { 0x92, 0xe8, 0xad, 0xca, 0x53, 0x81, 0xbf, 0xd0, + 0x5b, 0xdd, 0xf3, 0x61, 0x09, 0x09, 0x82, 0xe6, + 0x2c, 0x61, 0x01, 0x4e, 0x7b, 0x34, 0x4f, 0x09 }, /* mdata */ + 24, /* mdata_len */ + { 0x00, 0x00, 0x00, 0x00 }, /* mic */ + 4, /* mic_len */ + { 0x14, 0xaa, 0xbb, 0x00, 0x00, 0x01, 0x02, 0x03, + 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f } /* expected */ + } + }; + static int i; + static uint8_t ret; + static rtimer_clock_t time, time2, total_time; + + PROCESS_BEGIN(); + + puts("-----------------------------------------\n" + "Initializing cryptoprocessor..."); + crypto_init(); + + for(i = 0; i < sizeof(vectors) / sizeof(vectors[0]); i++) { + printf("-----------------------------------------\n" + "Test vector #%d: %s\n" + "len_len=%d key_area=%d\n" + "adata_len=%d mdata_len=%d mic_len=%d\n", + i, vectors[i].encrypt ? "encrypt" : "decrypt", + vectors[i].len_len, vectors[i].key_area, + vectors[i].adata_len, vectors[i].mdata_len, vectors[i].mic_len); + + time = RTIMER_NOW(); + ret = aes_load_key(vectors[i].key, vectors[i].key_area); + time = RTIMER_NOW() - time; + total_time = time; + printf("aes_load_key(): %s, %lu us\n", str_res[ret], + (uint32_t)((uint64_t)time * 1000000 / RTIMER_SECOND)); + PROCESS_PAUSE(); + if(ret != CRYPTO_SUCCESS) { + continue; + } + + time = RTIMER_NOW(); + if(vectors[i].encrypt) { + ret = ccm_auth_encrypt_start(vectors[i].len_len, vectors[i].key_area, + vectors[i].nonce, vectors[i].adata, + vectors[i].adata_len, vectors[i].mdata, + vectors[i].mdata_len, vectors[i].mic_len); + time2 = RTIMER_NOW(); + time = time2 - time; + total_time += time; + if(ret == CRYPTO_SUCCESS) { + do { + PROCESS_PAUSE(); + } while(!ccm_auth_encrypt_check_status()); + time2 = RTIMER_NOW() - time2; + total_time += time2; + } + printf("ccm_auth_encrypt_start(): %s, %lu us\n", str_res[ret], + (uint32_t)((uint64_t)time * 1000000 / RTIMER_SECOND)); + if(ret != CRYPTO_SUCCESS) { + PROCESS_PAUSE(); + continue; + } + printf("ccm_auth_encrypt_check_status() wait: %lu us\n", + (uint32_t)((uint64_t)time2 * 1000000 / RTIMER_SECOND)); + + time = RTIMER_NOW(); + ret = ccm_auth_encrypt_get_result(vectors[i].mic, vectors[i].mic_len); + time = RTIMER_NOW() - time; + total_time += time; + printf("ccm_auth_encrypt_get_result(): %s, %lu us\n", str_res[ret], + (uint32_t)((uint64_t)time * 1000000 / RTIMER_SECOND)); + PROCESS_PAUSE(); + if(ret != CRYPTO_SUCCESS) { + continue; + } + + if(rom_util_memcmp(vectors[i].mdata, vectors[i].expected, + vectors[i].mdata_len)) { + puts("Encrypted message does not match expected one"); + } else { + puts("Encrypted message OK"); + } + + if(rom_util_memcmp(vectors[i].mic, + vectors[i].expected + vectors[i].mdata_len, + vectors[i].mic_len)) { + puts("MIC does not match expected one"); + } else { + puts("MIC OK"); + } + } else { + ret = ccm_auth_decrypt_start(vectors[i].len_len, vectors[i].key_area, + vectors[i].nonce, vectors[i].adata, + vectors[i].adata_len, vectors[i].mdata, + vectors[i].mdata_len, vectors[i].mic_len); + time2 = RTIMER_NOW(); + time = time2 - time; + total_time += time; + if(ret == CRYPTO_SUCCESS) { + do { + PROCESS_PAUSE(); + } while(!ccm_auth_decrypt_check_status()); + time2 = RTIMER_NOW() - time2; + total_time += time2; + } + printf("ccm_auth_decrypt_start(): %s, %lu us\n", str_res[ret], + (uint32_t)((uint64_t)time * 1000000 / RTIMER_SECOND)); + if(ret != CRYPTO_SUCCESS) { + PROCESS_PAUSE(); + continue; + } + printf("ccm_auth_decrypt_check_status() wait: %lu us\n", + (uint32_t)((uint64_t)time2 * 1000000 / RTIMER_SECOND)); + + time = RTIMER_NOW(); + ret = ccm_auth_decrypt_get_result(vectors[i].mdata, vectors[i].mdata_len, + vectors[i].mic, vectors[i].mic_len); + time = RTIMER_NOW() - time; + total_time += time; + printf("ccm_auth_decrypt_get_result(): %s, %lu us\n", str_res[ret], + (uint32_t)((uint64_t)time * 1000000 / RTIMER_SECOND)); + PROCESS_PAUSE(); + if(ret != CRYPTO_SUCCESS) { + continue; + } + + if(rom_util_memcmp(vectors[i].mdata, vectors[i].expected, + vectors[i].mdata_len - vectors[i].mic_len)) { + puts("Decrypted message does not match expected one"); + } else { + puts("Decrypted message OK"); + } + } + + printf("Total duration: %lu us\n", + (uint32_t)((uint64_t)total_time * 1000000 / RTIMER_SECOND)); + } + + puts("-----------------------------------------\n" + "Disabling cryptoprocessor..."); + crypto_disable(); + + puts("Done!"); + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/examples/cc2538dk/crypto/sha256-test.c b/examples/cc2538dk/crypto/sha256-test.c new file mode 100644 index 000000000..dcdfd83de --- /dev/null +++ b/examples/cc2538dk/crypto/sha256-test.c @@ -0,0 +1,260 @@ +/* + * Original file: + * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/ + * All rights reserved. + * + * Port to Contiki: + * Copyright (c) 2013, ADVANSEE - http://www.advansee.com/ + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/** + * \addtogroup cc2538-examples + * @{ + * + * \defgroup cc2538-sha256-test cc2538dk SHA-256 Test Project + * + * SHA-256 access example for CC2538 on SmartRF06EB. + * + * This example shows how SHA-256 should be used. The example also verifies + * the SHA-256 functionality. + * + * @{ + * + * \file + * Example demonstrating SHA-256 on the cc2538dk platform + */ +#include "contiki.h" +#include "sys/rtimer.h" +#include "dev/rom-util.h" +#include "dev/sha256.h" + +#include +#include +#include +#include +/*---------------------------------------------------------------------------*/ +PROCESS(sha256_test_process, "sha256 test process"); +AUTOSTART_PROCESSES(&sha256_test_process); +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(sha256_test_process, ev, data) +{ + static const char *const str_res[] = { + "success", + "invalid param", + "NULL error", + "DMA bus error" + }; + static const struct { + const char *data[3]; + uint8_t sha256[32]; + } vectors[] = { + { /* Simple */ + { + "abc", + NULL, + NULL + }, { + 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea, + 0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23, + 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c, + 0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad + } + }, { /* Simple */ + { + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + NULL, + NULL, + }, { + 0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8, + 0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39, + 0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67, + 0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1 + } + }, { /* Message of length 130 */ + { + "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklabcd" + "efghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmn", + NULL, + NULL + }, { + 0x15, 0xd2, 0x3e, 0xea, 0x57, 0xb3, 0xd4, 0x61, + 0xbf, 0x38, 0x91, 0x12, 0xab, 0x4c, 0x43, 0xce, + 0x85, 0xe1, 0x68, 0x23, 0x8a, 0xaa, 0x54, 0x8e, + 0xc8, 0x6f, 0x0c, 0x9d, 0x65, 0xf9, 0xb9, 0x23 + } + }, { /* Message of length 128 */ + { + "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklabcd" + "efghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkl", + NULL, + NULL + }, { + 0xf8, 0xa3, 0xf2, 0x26, 0xfc, 0x42, 0x10, 0xe9, + 0x0d, 0x13, 0x0c, 0x7f, 0x41, 0xf2, 0xbe, 0x66, + 0x45, 0x53, 0x85, 0xd2, 0x92, 0x0a, 0xda, 0x78, + 0x15, 0xf8, 0xf7, 0x95, 0xd9, 0x44, 0x90, 0x5f + } + }, { /* Message of length 64 */ + { + "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkl", + NULL, + NULL + }, { + 0x2f, 0xcd, 0x5a, 0x0d, 0x60, 0xe4, 0xc9, 0x41, + 0x38, 0x1f, 0xcc, 0x4e, 0x00, 0xa4, 0xbf, 0x8b, + 0xe4, 0x22, 0xc3, 0xdd, 0xfa, 0xfb, 0x93, 0xc8, + 0x09, 0xe8, 0xd1, 0xe2, 0xbf, 0xff, 0xae, 0x8e + } + }, { /* Message of length 66 */ + { + "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmn", + NULL, + NULL + }, { + 0x92, 0x90, 0x1c, 0x85, 0x82, 0xe3, 0x1c, 0x05, + 0x69, 0xb5, 0x36, 0x26, 0x9c, 0xe2, 0x2c, 0xc8, + 0x30, 0x8b, 0xa4, 0x17, 0xab, 0x36, 0xc1, 0xbb, + 0xaf, 0x08, 0x4f, 0xf5, 0x8b, 0x18, 0xdc, 0x6a + } + }, { + { + "abcdbcdecdefde", + "fgefghfghighijhijkijkljklmklmnlmnomnopnopq", + NULL + }, { + 0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8, + 0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39, + 0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67, + 0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1 + } + }, { + { + "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkl", + "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkl", + NULL + }, { + 0xf8, 0xa3, 0xf2, 0x26, 0xfc, 0x42, 0x10, 0xe9, + 0x0d, 0x13, 0x0c, 0x7f, 0x41, 0xf2, 0xbe, 0x66, + 0x45, 0x53, 0x85, 0xd2, 0x92, 0x0a, 0xda, 0x78, + 0x15, 0xf8, 0xf7, 0x95, 0xd9, 0x44, 0x90, 0x5f + } + }, { + { + "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefgh", + "ijkl", + "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkl" + }, { + 0xf8, 0xa3, 0xf2, 0x26, 0xfc, 0x42, 0x10, 0xe9, + 0x0d, 0x13, 0x0c, 0x7f, 0x41, 0xf2, 0xbe, 0x66, + 0x45, 0x53, 0x85, 0xd2, 0x92, 0x0a, 0xda, 0x78, + 0x15, 0xf8, 0xf7, 0x95, 0xd9, 0x44, 0x90, 0x5f + } + } + }; + static sha256_state_t state; + static uint8_t sha256[32]; + static int i, j; + static uint8_t ret; + static rtimer_clock_t total_time; + rtimer_clock_t time; + size_t len; + + PROCESS_BEGIN(); + + puts("-----------------------------------------\n" + "Initializing cryptoprocessor..."); + crypto_init(); + + for(i = 0; i < sizeof(vectors) / sizeof(vectors[0]); i++) { + printf("-----------------------------------------\n" + "Test vector #%d:\n", i); + + time = RTIMER_NOW(); + ret = sha256_init(&state); + time = RTIMER_NOW() - time; + total_time = time; + printf("sha256_init(): %s, %lu us\n", str_res[ret], + (uint32_t)((uint64_t)time * 1000000 / RTIMER_SECOND)); + PROCESS_PAUSE(); + if(ret != CRYPTO_SUCCESS) { + continue; + } + + for(j = 0; j < sizeof(vectors[i].data) / sizeof(vectors[i].data[0]) && + vectors[i].data[j] != NULL; j++) { + len = strlen(vectors[i].data[j]); + printf("Buffer #%d (length: %u):\n", j, len); + time = RTIMER_NOW(); + ret = sha256_process(&state, vectors[i].data[j], len); + time = RTIMER_NOW() - time; + total_time += time; + printf("sha256_process(): %s, %lu us\n", str_res[ret], + (uint32_t)((uint64_t)time * 1000000 / RTIMER_SECOND)); + PROCESS_PAUSE(); + if(ret != CRYPTO_SUCCESS) { + break; + } + } + if(ret != CRYPTO_SUCCESS) { + continue; + } + + time = RTIMER_NOW(); + ret = sha256_done(&state, sha256); + time = RTIMER_NOW() - time; + total_time += time; + printf("sha256_done(): %s, %lu us\n", str_res[ret], + (uint32_t)((uint64_t)time * 1000000 / RTIMER_SECOND)); + PROCESS_PAUSE(); + if(ret != CRYPTO_SUCCESS) { + continue; + } + + if(rom_util_memcmp(sha256, vectors[i].sha256, sizeof(sha256))) { + puts("Computed SHA-256 hash does not match expected hash"); + } else { + puts("Computed SHA-256 hash OK"); + } + printf("Total duration: %lu us\n", + (uint32_t)((uint64_t)total_time * 1000000 / RTIMER_SECOND)); + } + + puts("-----------------------------------------\n" + "Disabling cryptoprocessor..."); + crypto_disable(); + + puts("Done!"); + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/platform/cc2538dk/README.md b/platform/cc2538dk/README.md index e69b977b1..f6dc640f8 100644 --- a/platform/cc2538dk/README.md +++ b/platform/cc2538dk/README.md @@ -29,6 +29,7 @@ In terms of hardware support, the following drivers have been implemented: * Low Power Modes * General-Purpose Timers. NB: GPT0 is in use by the platform code, the remaining GPTs are available for application development. * ADC + * Cryptoprocessor (AES-CCM-128, SHA-256) * SmartRF06 EB and BB peripherals * LEDs * Buttons diff --git a/platform/remote/README.md b/platform/remote/README.md index f4ce1d302..f7a556af6 100644 --- a/platform/remote/README.md +++ b/platform/remote/README.md @@ -44,6 +44,7 @@ In terms of hardware support, the following drivers have been implemented: * Low Power Modes * General-Purpose Timers. NB: GPT0 is in use by the platform code, the remaining GPTs are available for application development. * ADC + * Cryptoprocessor (AES-CCM-128, SHA-256) * LEDs * Buttons * Internal/external 2.4GHz antenna switch controllable by SW.