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..1bd70690c --- /dev/null +++ b/cpu/cc2538/dev/aes.c @@ -0,0 +1,152 @@ +/* + * 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_keys(const void *keys, uint8_t key_size, uint8_t count, + uint8_t start_area) +{ + uint32_t aes_key_store_size; + uint32_t areas; + uint64_t aligned_keys[16]; + int i; + + if(REG(AES_CTRL_ALG_SEL) != 0x00000000) { + return CRYPTO_RESOURCE_IN_USE; + } + + /* 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); + aligned_keys[(i << 2) + 3] = 0; + } + } + + /* Change count to the number of 128-bit key areas */ + if(key_size != AES_KEY_STORE_SIZE_KEY_SIZE_128) { + count <<= 1; + } + + /* The keys base address needs to be 4-byte aligned */ + if(key_size != AES_KEY_STORE_SIZE_KEY_SIZE_192) { + rom_util_memcpy(aligned_keys, keys, count << 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; + + /* 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 (areas, size) + * Note that writing AES_KEY_STORE_SIZE deletes all stored keys */ + aes_key_store_size = REG(AES_KEY_STORE_SIZE); + if((aes_key_store_size & AES_KEY_STORE_SIZE_KEY_SIZE_M) != key_size) { + REG(AES_KEY_STORE_SIZE) = (aes_key_store_size & + ~AES_KEY_STORE_SIZE_KEY_SIZE_M) | key_size; + } + + /* Free possibly already occupied key areas */ + areas = ((0x00000001 << count) - 1) << start_area; + REG(AES_KEY_STORE_WRITTEN_AREA) = areas; + + /* Enable key areas to write */ + REG(AES_KEY_STORE_WRITE_AREA) = areas; + + /* Configure DMAC + * Enable DMA channel 0 */ + REG(AES_DMAC_CH0_CTRL) = AES_DMAC_CH_CTRL_EN; + + /* Base address of the keys in ext. memory */ + REG(AES_DMAC_CH0_EXTADDR) = (uint32_t)aligned_keys; + + /* Total keys 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) | + (count << (4 + 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; + /* Disable master control / DMA clock */ + REG(AES_CTRL_ALG_SEL) = 0x00000000; + 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; + /* Disable master control / DMA clock */ + REG(AES_CTRL_ALG_SEL) = 0x00000000; + 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) & areas) != areas) { + 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..39c794b51 --- /dev/null +++ b/cpu/cc2538/dev/aes.h @@ -0,0 +1,495 @@ +/* + * 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 5 +#define AES_KEYSTORE_WRITE_ERROR 6 +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name AES functions + * @{ + */ + +/** \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) + * \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 + * stored keys. + */ +uint8_t aes_load_keys(const void *keys, uint8_t key_size, uint8_t count, + uint8_t start_area); + +/** @} */ + +#endif /* AES_H_ */ + +/** + * @} + * @} + */ diff --git a/cpu/cc2538/dev/ccm.c b/cpu/cc2538/dev/ccm.c new file mode 100644 index 000000000..b25ef29b3 --- /dev/null +++ b/cpu/cc2538/dev/ccm.c @@ -0,0 +1,413 @@ +/* + * 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/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) +{ + uint32_t iv[4]; + + 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 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 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 */ + + /* 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)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); + + 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, + struct process *process) +{ + uint16_t pdata_len = cdata_len - mic_len; + uint32_t iv[4]; + + 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(); +} +/*---------------------------------------------------------------------------*/ +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; +} + +/** @} */ diff --git a/cpu/cc2538/dev/ccm.h b/cpu/cc2538/dev/ccm.h new file mode 100644 index 000000000..1cab578af --- /dev/null +++ b/cpu/cc2538/dev/ccm.h @@ -0,0 +1,141 @@ +/* + * 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 7 +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \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) + * \param process Process to be polled upon completion of the operation, or \c NULL + * \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, + struct process *process); + +/** \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) + * \param process Process to be polled upon completion of the operation, or \c NULL + * \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, + struct process *process); + +/** \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..7dc5d3342 --- /dev/null +++ b/cpu/cc2538/dev/crypto.c @@ -0,0 +1,120 @@ +/* + * 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 "sys/energest.h" +#include "dev/sys-ctrl.h" +#include "dev/nvic.h" +#include "dev/crypto.h" +#include "dev/aes.h" +#include "reg.h" +#include "lpm.h" + +#include +/*---------------------------------------------------------------------------*/ +static volatile struct process *notification_process = NULL; +/*---------------------------------------------------------------------------*/ +/** \brief The AES/SHA cryptoprocessor ISR + * + * This is the interrupt service routine for the AES/SHA + * cryptoprocessor. + * + * This ISR is called at worst from PM0, so lpm_exit() does not need + * to be called. + */ +void +crypto_isr(void) +{ + ENERGEST_ON(ENERGEST_TYPE_IRQ); + + nvic_interrupt_unpend(NVIC_INT_AES); + nvic_interrupt_disable(NVIC_INT_AES); + + if(notification_process != NULL) { + process_poll((struct process *)notification_process); + notification_process = NULL; + } + + ENERGEST_OFF(ENERGEST_TYPE_IRQ); +} +/*---------------------------------------------------------------------------*/ +static bool +permit_pm1(void) +{ + return REG(AES_CTRL_ALG_SEL) == 0; +} +/*---------------------------------------------------------------------------*/ +void +crypto_init(void) +{ + volatile int i; + + lpm_register_peripheral(permit_pm1); + + 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; +} +/*---------------------------------------------------------------------------*/ +void +crypto_register_process_notification(struct process *p) +{ + notification_process = p; +} + +/** @} */ diff --git a/cpu/cc2538/dev/crypto.h b/cpu/cc2538/dev/crypto.h new file mode 100644 index 000000000..ad06ef343 --- /dev/null +++ b/cpu/cc2538/dev/crypto.h @@ -0,0 +1,89 @@ +/* + * 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_RESOURCE_IN_USE 3 +#define CRYPTO_DMA_BUS_ERROR 4 +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \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); + +/** \brief Registers a process to be notified of the completion of a crypto + * operation + * \param p Process to be polled upon IRQ + * \note This function is only supposed to be called by the crypto drivers. + */ +void crypto_register_process_notification(struct process *p); + +/** @} */ + +#endif /* CRYPTO_H_ */ + +/** + * @} + * @} + */ diff --git a/cpu/cc2538/dev/sha256.c b/cpu/cc2538/dev/sha256.c new file mode 100644 index 000000000..347c54081 --- /dev/null +++ b/cpu/cc2538/dev/sha256.c @@ -0,0 +1,356 @@ +/* + * 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; + /* Disable master control / DMA clock */ + REG(AES_CTRL_ALG_SEL) = 0x00000000; + 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; + /* Disable master control / DMA clock */ + REG(AES_CTRL_ALG_SEL) = 0x00000000; + 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(REG(AES_CTRL_ALG_SEL) != 0x00000000) { + return CRYPTO_RESOURCE_IN_USE; + } + + 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; + } + + if(REG(AES_CTRL_ALG_SEL) != 0x00000000) { + return CRYPTO_RESOURCE_IN_USE; + } + + /* 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/cpu/cc2538/lpm.c b/cpu/cc2538/lpm.c index abe75c02e..91d67acc9 100644 --- a/cpu/cc2538/lpm.c +++ b/cpu/cc2538/lpm.c @@ -101,7 +101,7 @@ static uint8_t max_pm; #ifdef LPM_CONF_PERIPH_PERMIT_PM1_FUNCS_MAX #define LPM_PERIPH_PERMIT_PM1_FUNCS_MAX LPM_CONF_PERIPH_PERMIT_PM1_FUNCS_MAX #else -#define LPM_PERIPH_PERMIT_PM1_FUNCS_MAX 2 +#define LPM_PERIPH_PERMIT_PM1_FUNCS_MAX 3 #endif static lpm_periph_permit_pm1_func_t diff --git a/cpu/cc2538/startup-gcc.c b/cpu/cc2538/startup-gcc.c index b4155fa29..2aa82894e 100644 --- a/cpu/cc2538/startup-gcc.c +++ b/cpu/cc2538/startup-gcc.c @@ -67,6 +67,7 @@ void udma_err_isr(void); void usb_isr(void) WEAK_ALIAS(default_handler); void uart0_isr(void) WEAK_ALIAS(default_handler); void uart1_isr(void) WEAK_ALIAS(default_handler); +void crypto_isr(void); /* Boot Loader Backdoor selection */ #if FLASH_CCA_CONF_BOOTLDR_BACKDOOR @@ -269,7 +270,7 @@ void(*const vectors[])(void) = usb_isr, /* 156 USB */ cc2538_rf_rx_tx_isr, /* 157 RFCORE RX/TX */ cc2538_rf_err_isr, /* 158 RFCORE Error */ - default_handler, /* 159 AES */ + crypto_isr, /* 159 AES */ default_handler, /* 160 PKA */ rtimer_isr, /* 161 SM Timer */ default_handler, /* 162 MACTimer */ 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..64c4fcf18 --- /dev/null +++ b/examples/cc2538dk/crypto/ccm-test.c @@ -0,0 +1,733 @@ +/* + * 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", + "resource in use", + "DMA bus error", + "keystore read error", + "keystore write error", + "authentication failed" + }; + static const uint8_t keys128[][16] = { + { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf } + }; + static const uint8_t keys192[][24] = { + { 0x26, 0x51, 0x1f, 0xb5, 0x1f, 0xcf, 0xa7, 0x5c, + 0xb4, 0xb4, 0x4d, 0xa7, 0x5a, 0x6e, 0x5a, 0x0e, + 0xb8, 0xd9, 0xc8, 0xf3, 0xb9, 0x06, 0xf8, 0x86 }, + { 0x08, 0x6e, 0x29, 0x67, 0xcd, 0xe9, 0x9e, 0x90, + 0xfa, 0xae, 0xa8, 0xa9, 0x4e, 0x16, 0x8b, 0xf0, + 0xe0, 0x66, 0xc5, 0x03, 0xa8, 0x49, 0xa9, 0xf3 }, + { 0xce, 0xb0, 0x09, 0xae, 0xa4, 0x45, 0x44, 0x51, + 0xfe, 0xad, 0xf0, 0xe6, 0xb3, 0x6f, 0x45, 0x55, + 0x5d, 0xd0, 0x47, 0x23, 0xba, 0xa4, 0x48, 0xe8 }, + { 0x11, 0xfd, 0x45, 0x74, 0x3d, 0x94, 0x6e, 0x6d, + 0x37, 0x34, 0x1f, 0xec, 0x49, 0x94, 0x7e, 0x8c, + 0x70, 0x48, 0x24, 0x94, 0xa8, 0xf0, 0x7f, 0xcc } + }; + static const uint8_t keys256[][32] = { + { 0x26, 0x51, 0x1f, 0xb5, 0x1f, 0xcf, 0xa7, 0x5c, + 0xb4, 0xb4, 0x4d, 0xa7, 0x5a, 0x6e, 0x5a, 0x0e, + 0xb8, 0xd9, 0xc8, 0xf3, 0xb9, 0x06, 0xf8, 0x86, + 0xdf, 0x3b, 0xa3, 0xe6, 0xda, 0x3a, 0x13, 0x89 }, + { 0xc6, 0xc1, 0x4c, 0x65, 0x5e, 0x52, 0xc8, 0xa4, + 0xc7, 0xe8, 0xd5, 0x4e, 0x97, 0x4d, 0x69, 0x8e, + 0x1f, 0x21, 0xee, 0x3b, 0xa7, 0x17, 0xa0, 0xad, + 0xfa, 0x61, 0x36, 0xd0, 0x26, 0x68, 0xc4, 0x76 }, + { 0x55, 0x35, 0x21, 0xa7, 0x65, 0xab, 0x0c, 0x3f, + 0xd2, 0x03, 0x65, 0x4e, 0x99, 0x16, 0x33, 0x0e, + 0x18, 0x9b, 0xdf, 0x95, 0x1f, 0xee, 0xe9, 0xb4, + 0x4b, 0x10, 0xda, 0x20, 0x8f, 0xee, 0x7a, 0xcf }, + { 0x90, 0x74, 0xb1, 0xae, 0x4c, 0xa3, 0x34, 0x2f, + 0xe5, 0xbf, 0x6f, 0x14, 0xbc, 0xf2, 0xf2, 0x79, + 0x04, 0xf0, 0xb1, 0x51, 0x79, 0xd9, 0x5a, 0x65, + 0x4f, 0x61, 0xe6, 0x99, 0x69, 0x2e, 0x6f, 0x71 } + }; + static const struct { + const void *keys; + uint8_t key_size; + uint8_t count; + } keys[] = { + { keys128, AES_KEY_STORE_SIZE_KEY_SIZE_128, + sizeof(keys128) / sizeof(keys128[0]) }, + { keys192, AES_KEY_STORE_SIZE_KEY_SIZE_192, + sizeof(keys192) / sizeof(keys192[0]) }, + { keys256, AES_KEY_STORE_SIZE_KEY_SIZE_256, + sizeof(keys256) / sizeof(keys256[0]) } + }; + static struct { + bool encrypt; + uint8_t len_len; + uint8_t key_size_index; + uint8_t key_area; + uint8_t nonce[13]; + uint8_t adata[32]; + uint16_t adata_len; + uint8_t mdata[40]; + uint16_t mdata_len; + uint8_t mic[16]; + uint8_t mic_len; + uint8_t expected[40]; + } vectors[] = { + { + true, /* encrypt */ + 2, /* len_len */ + 0, /* key_size_index */ + 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 */ + 0, /* key_size_index */ + 1, /* 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 */ + 0, /* key_size_index */ + 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 */ + 0, /* key_size_index */ + 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 */ + 0, /* key_size_index */ + 1, /* 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 */ + 0, /* key_size_index */ + 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 */ + }, { + true, /* encrypt */ + 2, /* len_len */ + 1, /* key_size_index */ + 0, /* key_area */ + { 0x15, 0xb3, 0x69, 0x88, 0x96, 0x99, 0xb6, 0xde, + 0x1f, 0xa3, 0xee, 0x73, 0xe5 }, /* nonce */ + {}, /* adata */ + 0, /* adata_len */ + { 0x39, 0xf0, 0x8a, 0x2a, 0xf1, 0xd8, 0xda, 0x62, + 0x12, 0x55, 0x06, 0x39, 0xb9, 0x1f, 0xb2, 0x57, + 0x3e, 0x39, 0xa8, 0xeb, 0x5d, 0x80, 0x1d, 0xe8 }, /* mdata */ + 24, /* mdata_len */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* mic */ + 16, /* mic_len */ + { 0x63, 0x42, 0xb8, 0x70, 0x0e, 0xde, 0xc9, 0x7a, + 0x96, 0x0e, 0xb1, 0x6e, 0x7c, 0xb1, 0xeb, 0x44, + 0x12, 0xfb, 0x4e, 0x26, 0x3d, 0xdd, 0x22, 0x06, + 0xb0, 0x90, 0x15, 0x5d, 0x34, 0xa7, 0x6c, 0x83, + 0x24, 0xe5, 0x55, 0x0c, 0x3e, 0xf4, 0x26, 0xed } /* expected */ + }, { + true, /* encrypt */ + 2, /* len_len */ + 1, /* key_size_index */ + 2, /* key_area */ + { 0x92, 0x95, 0x42, 0xcd, 0x69, 0x0f, 0x1b, 0xab, + 0xcf, 0x16, 0x96, 0xcb, 0x03 }, /* nonce */ + { 0x58, 0xf7, 0x0b, 0xab, 0x24, 0xe0, 0xa6, 0x13, + 0x7e, 0x5c, 0xd3, 0xeb, 0x18, 0x65, 0x6f, 0x2b, + 0x5c, 0xcd, 0xdc, 0x3f, 0x53, 0x8a, 0x00, 0x00, + 0xc6, 0x51, 0x90, 0xe4, 0xa3, 0x66, 0x8e, 0x71 }, /* adata */ + 32, /* adata_len */ + {}, /* mdata */ + 0, /* mdata_len */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* mic */ + 16, /* mic_len */ + { 0x3b, 0xf9, 0xd9, 0x3a, 0xf6, 0xff, 0xac, 0x9a, + 0xc8, 0x4c, 0xd3, 0x20, 0x2d, 0x4e, 0x0c, 0xc8 } /* expected */ + }, { + true, /* encrypt */ + 8, /* len_len */ + 1, /* key_size_index */ + 4, /* key_area */ + { 0x76, 0x40, 0x43, 0xc4, 0x94, 0x60, 0xb7 }, /* nonce */ + { 0x6e, 0x80, 0xdd, 0x7f, 0x1b, 0xad, 0xf3, 0xa1, + 0xc9, 0xab, 0x25, 0xc7, 0x5f, 0x10, 0xbd, 0xe7, + 0x8c, 0x23, 0xfa, 0x0e, 0xb8, 0xf9, 0xaa, 0xa5, + 0x3a, 0xde, 0xfb, 0xf4, 0xcb, 0xf7, 0x8f, 0xe4 }, /* adata */ + 32, /* adata_len */ + { 0xc8, 0xd2, 0x75, 0xf9, 0x19, 0xe1, 0x7d, 0x7f, + 0xe6, 0x9c, 0x2a, 0x1f, 0x58, 0x93, 0x9d, 0xfe, + 0x4d, 0x40, 0x37, 0x91, 0xb5, 0xdf, 0x13, 0x10 }, /* mdata */ + 24, /* mdata_len */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* mic */ + 16, /* mic_len */ + { 0x8a, 0x0f, 0x3d, 0x82, 0x29, 0xe4, 0x8e, 0x74, + 0x87, 0xfd, 0x95, 0xa2, 0x8a, 0xd3, 0x92, 0xc8, + 0x0b, 0x36, 0x81, 0xd4, 0xfb, 0xc7, 0xbb, 0xfd, + 0x2d, 0xd6, 0xef, 0x1c, 0x45, 0xd4, 0xcc, 0xb7, + 0x23, 0xdc, 0x07, 0x44, 0x14, 0xdb, 0x50, 0x6d } /* expected */ + }, { + true, /* encrypt */ + 2, /* len_len */ + 1, /* key_size_index */ + 6, /* key_area */ + { 0xc6, 0xae, 0xeb, 0xcb, 0x14, 0x6c, 0xfa, 0xfa, + 0xae, 0x66, 0xf7, 0x8a, 0xab }, /* nonce */ + { 0x7d, 0xc8, 0xc5, 0x21, 0x44, 0xa7, 0xcb, 0x65, + 0xb3, 0xe5, 0xa8, 0x46, 0xe8, 0xfd, 0x7e, 0xae, + 0x37, 0xbf, 0x69, 0x96, 0xc2, 0x99, 0xb5, 0x6e, + 0x49, 0x14, 0x4e, 0xbf, 0x43, 0xa1, 0x77, 0x0f }, /* adata */ + 32, /* adata_len */ + { 0xee, 0x7e, 0x60, 0x75, 0xba, 0x52, 0x84, 0x6d, + 0xe5, 0xd6, 0x25, 0x49, 0x59, 0xa1, 0x8a, 0xff, + 0xc4, 0xfa, 0xf5, 0x9c, 0x8e, 0xf6, 0x34, 0x89 }, /* mdata */ + 24, /* mdata_len */ + { 0x00, 0x00, 0x00, 0x00 }, /* mic */ + 4, /* mic_len */ + { 0x13, 0x7d, 0x9d, 0xa5, 0x9b, 0xaf, 0x5c, 0xbf, + 0xd4, 0x66, 0x20, 0xc5, 0xf2, 0x98, 0xfc, 0x76, + 0x6d, 0xe1, 0x0a, 0xc6, 0x8e, 0x77, 0x4e, 0xdf, + 0x1f, 0x2c, 0x5b, 0xad } /* expected */ + }, { + false, /* decrypt */ + 2, /* len_len */ + 1, /* key_size_index */ + 0, /* key_area */ + { 0x15, 0xb3, 0x69, 0x88, 0x96, 0x99, 0xb6, 0xde, + 0x1f, 0xa3, 0xee, 0x73, 0xe5 }, /* nonce */ + {}, /* adata */ + 0, /* adata_len */ + { 0x63, 0x42, 0xb8, 0x70, 0x0e, 0xde, 0xc9, 0x7a, + 0x96, 0x0e, 0xb1, 0x6e, 0x7c, 0xb1, 0xeb, 0x44, + 0x12, 0xfb, 0x4e, 0x26, 0x3d, 0xdd, 0x22, 0x06, + 0xb0, 0x90, 0x15, 0x5d, 0x34, 0xa7, 0x6c, 0x83, + 0x24, 0xe5, 0x55, 0x0c, 0x3e, 0xf4, 0x26, 0xed }, /* mdata */ + 40, /* mdata_len */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* mic */ + 16, /* mic_len */ + { 0x39, 0xf0, 0x8a, 0x2a, 0xf1, 0xd8, 0xda, 0x62, + 0x12, 0x55, 0x06, 0x39, 0xb9, 0x1f, 0xb2, 0x57, + 0x3e, 0x39, 0xa8, 0xeb, 0x5d, 0x80, 0x1d, 0xe8 } /* expected */ + }, { + false, /* decrypt */ + 2, /* len_len */ + 1, /* key_size_index */ + 2, /* key_area */ + { 0x92, 0x95, 0x42, 0xcd, 0x69, 0x0f, 0x1b, 0xab, + 0xcf, 0x16, 0x96, 0xcb, 0x03 }, /* nonce */ + { 0x58, 0xf7, 0x0b, 0xab, 0x24, 0xe0, 0xa6, 0x13, + 0x7e, 0x5c, 0xd3, 0xeb, 0x18, 0x65, 0x6f, 0x2b, + 0x5c, 0xcd, 0xdc, 0x3f, 0x53, 0x8a, 0x00, 0x00, + 0xc6, 0x51, 0x90, 0xe4, 0xa3, 0x66, 0x8e, 0x71 }, /* adata */ + 32, /* adata_len */ + { 0x3b, 0xf9, 0xd9, 0x3a, 0xf6, 0xff, 0xac, 0x9a, + 0xc8, 0x4c, 0xd3, 0x20, 0x2d, 0x4e, 0x0c, 0xc8 }, /* mdata */ + 16, /* mdata_len */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* mic */ + 16, /* mic_len */ + {} /* expected */ + }, { + false, /* decrypt */ + 8, /* len_len */ + 1, /* key_size_index */ + 4, /* key_area */ + { 0x76, 0x40, 0x43, 0xc4, 0x94, 0x60, 0xb7 }, /* nonce */ + { 0x6e, 0x80, 0xdd, 0x7f, 0x1b, 0xad, 0xf3, 0xa1, + 0xc9, 0xab, 0x25, 0xc7, 0x5f, 0x10, 0xbd, 0xe7, + 0x8c, 0x23, 0xfa, 0x0e, 0xb8, 0xf9, 0xaa, 0xa5, + 0x3a, 0xde, 0xfb, 0xf4, 0xcb, 0xf7, 0x8f, 0xe4 }, /* adata */ + 32, /* adata_len */ + { 0x8a, 0x0f, 0x3d, 0x82, 0x29, 0xe4, 0x8e, 0x74, + 0x87, 0xfd, 0x95, 0xa2, 0x8a, 0xd3, 0x92, 0xc8, + 0x0b, 0x36, 0x81, 0xd4, 0xfb, 0xc7, 0xbb, 0xfd, + 0x2d, 0xd6, 0xef, 0x1c, 0x45, 0xd4, 0xcc, 0xb7, + 0x23, 0xdc, 0x07, 0x44, 0x14, 0xdb, 0x50, 0x6d }, /* mdata */ + 40, /* mdata_len */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* mic */ + 16, /* mic_len */ + { 0xc8, 0xd2, 0x75, 0xf9, 0x19, 0xe1, 0x7d, 0x7f, + 0xe6, 0x9c, 0x2a, 0x1f, 0x58, 0x93, 0x9d, 0xfe, + 0x4d, 0x40, 0x37, 0x91, 0xb5, 0xdf, 0x13, 0x10 } /* expected */ + }, { + false, /* decrypt */ + 2, /* len_len */ + 1, /* key_size_index */ + 6, /* key_area */ + { 0xc6, 0xae, 0xeb, 0xcb, 0x14, 0x6c, 0xfa, 0xfa, + 0xae, 0x66, 0xf7, 0x8a, 0xab }, /* nonce */ + { 0x7d, 0xc8, 0xc5, 0x21, 0x44, 0xa7, 0xcb, 0x65, + 0xb3, 0xe5, 0xa8, 0x46, 0xe8, 0xfd, 0x7e, 0xae, + 0x37, 0xbf, 0x69, 0x96, 0xc2, 0x99, 0xb5, 0x6e, + 0x49, 0x14, 0x4e, 0xbf, 0x43, 0xa1, 0x77, 0x0f }, /* adata */ + 32, /* adata_len */ + { 0x13, 0x7d, 0x9d, 0xa5, 0x9b, 0xaf, 0x5c, 0xbf, + 0xd4, 0x66, 0x20, 0xc5, 0xf2, 0x98, 0xfc, 0x76, + 0x6d, 0xe1, 0x0a, 0xc6, 0x8e, 0x77, 0x4e, 0xdf, + 0x1f, 0x2c, 0x5b, 0xad }, /* mdata */ + 28, /* mdata_len */ + { 0x00, 0x00, 0x00, 0x00 }, /* mic */ + 4, /* mic_len */ + { 0xee, 0x7e, 0x60, 0x75, 0xba, 0x52, 0x84, 0x6d, + 0xe5, 0xd6, 0x25, 0x49, 0x59, 0xa1, 0x8a, 0xff, + 0xc4, 0xfa, 0xf5, 0x9c, 0x8e, 0xf6, 0x34, 0x89 } /* expected */ + }, { + true, /* encrypt */ + 2, /* len_len */ + 2, /* key_size_index */ + 0, /* key_area */ + { 0x72, 0xa6, 0x0f, 0x34, 0x5a, 0x19, 0x78, 0xfb, + 0x40, 0xf2, 0x8a, 0x2f, 0xa4 }, /* nonce */ + {}, /* adata */ + 0, /* adata_len */ + { 0x30, 0xd5, 0x6f, 0xf2, 0xa2, 0x5b, 0x83, 0xfe, + 0xe7, 0x91, 0x11, 0x0f, 0xca, 0xea, 0x48, 0xe4, + 0x1d, 0xb7, 0xc7, 0xf0, 0x98, 0xa8, 0x10, 0x00 }, /* mdata */ + 24, /* mdata_len */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* mic */ + 16, /* mic_len */ + { 0x55, 0xf0, 0x68, 0xc0, 0xbb, 0xba, 0x8b, 0x59, + 0x80, 0x13, 0xdd, 0x18, 0x41, 0xfd, 0x74, 0x0f, + 0xda, 0x29, 0x02, 0x32, 0x21, 0x48, 0xab, 0x5e, + 0x93, 0x57, 0x53, 0xe6, 0x01, 0xb7, 0x9d, 0xb4, + 0xae, 0x73, 0x0b, 0x6a, 0xe3, 0x50, 0x07, 0x31 } /* expected */ + }, { + true, /* encrypt */ + 2, /* len_len */ + 2, /* key_size_index */ + 2, /* key_area */ + { 0x29, 0x1e, 0x91, 0xb1, 0x9d, 0xe5, 0x18, 0xcd, + 0x78, 0x06, 0xde, 0x44, 0xf6 }, /* nonce */ + { 0xb4, 0xf8, 0x32, 0x69, 0x44, 0xa4, 0x5d, 0x95, + 0xf9, 0x18, 0x87, 0xc2, 0xa6, 0xac, 0x36, 0xb6, + 0x0e, 0xea, 0x5e, 0xde, 0xf8, 0x4c, 0x1c, 0x35, + 0x81, 0x46, 0xa6, 0x66, 0xb6, 0x87, 0x83, 0x35 }, /* adata */ + 32, /* adata_len */ + {}, /* mdata */ + 0, /* mdata_len */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* mic */ + 16, /* mic_len */ + { 0xca, 0x48, 0x2c, 0x67, 0x4b, 0x59, 0x90, 0x46, + 0xcc, 0x7d, 0x7e, 0xe0, 0xd0, 0x0e, 0xec, 0x1e } /* expected */ + }, { + true, /* encrypt */ + 8, /* len_len */ + 2, /* key_size_index */ + 4, /* key_area */ + { 0xaa, 0xa2, 0x3f, 0x10, 0x16, 0x47, 0xd8 }, /* nonce */ + { 0xa3, 0x55, 0xd4, 0xc6, 0x11, 0x81, 0x2e, 0x5f, + 0x92, 0x58, 0xd7, 0x18, 0x8b, 0x3d, 0xf8, 0x85, + 0x14, 0x77, 0x09, 0x4f, 0xfc, 0x2a, 0xf2, 0xcf, + 0x0c, 0x86, 0x70, 0xdb, 0x90, 0x3f, 0xbb, 0xe0 }, /* adata */ + 32, /* adata_len */ + { 0x64, 0x4e, 0xb3, 0x4b, 0x9a, 0x12, 0x6e, 0x43, + 0x7b, 0x5e, 0x01, 0x5e, 0xea, 0x14, 0x1c, 0xa1, + 0xa8, 0x80, 0x20, 0xf2, 0xd5, 0xd6, 0xcc, 0x2c }, /* mdata */ + 24, /* mdata_len */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* mic */ + 16, /* mic_len */ + { 0x27, 0xed, 0x90, 0x66, 0x81, 0x74, 0xeb, 0xf8, + 0x24, 0x1a, 0x3c, 0x74, 0xb3, 0x5e, 0x12, 0x46, + 0xb6, 0x61, 0x7e, 0x41, 0x23, 0x57, 0x8f, 0x15, + 0x3b, 0xdb, 0x67, 0x06, 0x2a, 0x13, 0xef, 0x4e, + 0x98, 0x6f, 0x5b, 0xb3, 0xd0, 0xbb, 0x43, 0x07 } /* expected */ + }, { + true, /* encrypt */ + 2, /* len_len */ + 2, /* key_size_index */ + 6, /* key_area */ + { 0x2e, 0x1e, 0x01, 0x32, 0x46, 0x85, 0x00, 0xd4, + 0xbd, 0x47, 0x86, 0x25, 0x63 }, /* nonce */ + { 0x3c, 0x5f, 0x54, 0x04, 0x37, 0x0a, 0xbd, 0xcb, + 0x1e, 0xdd, 0xe9, 0x9d, 0xe6, 0x0d, 0x06, 0x82, + 0xc6, 0x00, 0xb0, 0x34, 0xe0, 0x63, 0xb7, 0xd3, + 0x23, 0x77, 0x23, 0xda, 0x70, 0xab, 0x75, 0x52 }, /* adata */ + 32, /* adata_len */ + { 0x23, 0x90, 0x29, 0xf1, 0x50, 0xbc, 0xcb, 0xd6, + 0x7e, 0xdb, 0xb6, 0x7f, 0x8a, 0xe4, 0x56, 0xb4, + 0xea, 0x06, 0x6a, 0x4b, 0xee, 0xe0, 0x65, 0xf9 }, /* mdata */ + 24, /* mdata_len */ + { 0x00, 0x00, 0x00, 0x00 }, /* mic */ + 4, /* mic_len */ + { 0x9c, 0x8d, 0x5d, 0xd2, 0x27, 0xfd, 0x9f, 0x81, + 0x23, 0x76, 0x01, 0x83, 0x0a, 0xfe, 0xe4, 0xf0, + 0x11, 0x56, 0x36, 0xc8, 0xe5, 0xd5, 0xfd, 0x74, + 0x3c, 0xb9, 0xaf, 0xed } /* expected */ + }, { + false, /* decrypt */ + 2, /* len_len */ + 2, /* key_size_index */ + 0, /* key_area */ + { 0x72, 0xa6, 0x0f, 0x34, 0x5a, 0x19, 0x78, 0xfb, + 0x40, 0xf2, 0x8a, 0x2f, 0xa4 }, /* nonce */ + {}, /* adata */ + 0, /* adata_len */ + { 0x55, 0xf0, 0x68, 0xc0, 0xbb, 0xba, 0x8b, 0x59, + 0x80, 0x13, 0xdd, 0x18, 0x41, 0xfd, 0x74, 0x0f, + 0xda, 0x29, 0x02, 0x32, 0x21, 0x48, 0xab, 0x5e, + 0x93, 0x57, 0x53, 0xe6, 0x01, 0xb7, 0x9d, 0xb4, + 0xae, 0x73, 0x0b, 0x6a, 0xe3, 0x50, 0x07, 0x31 }, /* mdata */ + 40, /* mdata_len */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* mic */ + 16, /* mic_len */ + { 0x30, 0xd5, 0x6f, 0xf2, 0xa2, 0x5b, 0x83, 0xfe, + 0xe7, 0x91, 0x11, 0x0f, 0xca, 0xea, 0x48, 0xe4, + 0x1d, 0xb7, 0xc7, 0xf0, 0x98, 0xa8, 0x10, 0x00 } /* expected */ + }, { + false, /* decrypt */ + 2, /* len_len */ + 2, /* key_size_index */ + 2, /* key_area */ + { 0x29, 0x1e, 0x91, 0xb1, 0x9d, 0xe5, 0x18, 0xcd, + 0x78, 0x06, 0xde, 0x44, 0xf6 }, /* nonce */ + { 0xb4, 0xf8, 0x32, 0x69, 0x44, 0xa4, 0x5d, 0x95, + 0xf9, 0x18, 0x87, 0xc2, 0xa6, 0xac, 0x36, 0xb6, + 0x0e, 0xea, 0x5e, 0xde, 0xf8, 0x4c, 0x1c, 0x35, + 0x81, 0x46, 0xa6, 0x66, 0xb6, 0x87, 0x83, 0x35 }, /* adata */ + 32, /* adata_len */ + { 0xca, 0x48, 0x2c, 0x67, 0x4b, 0x59, 0x90, 0x46, + 0xcc, 0x7d, 0x7e, 0xe0, 0xd0, 0x0e, 0xec, 0x1e }, /* mdata */ + 16, /* mdata_len */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* mic */ + 16, /* mic_len */ + {} /* expected */ + }, { + false, /* decrypt */ + 8, /* len_len */ + 2, /* key_size_index */ + 4, /* key_area */ + { 0xaa, 0xa2, 0x3f, 0x10, 0x16, 0x47, 0xd8 }, /* nonce */ + { 0xa3, 0x55, 0xd4, 0xc6, 0x11, 0x81, 0x2e, 0x5f, + 0x92, 0x58, 0xd7, 0x18, 0x8b, 0x3d, 0xf8, 0x85, + 0x14, 0x77, 0x09, 0x4f, 0xfc, 0x2a, 0xf2, 0xcf, + 0x0c, 0x86, 0x70, 0xdb, 0x90, 0x3f, 0xbb, 0xe0 }, /* adata */ + 32, /* adata_len */ + { 0x27, 0xed, 0x90, 0x66, 0x81, 0x74, 0xeb, 0xf8, + 0x24, 0x1a, 0x3c, 0x74, 0xb3, 0x5e, 0x12, 0x46, + 0xb6, 0x61, 0x7e, 0x41, 0x23, 0x57, 0x8f, 0x15, + 0x3b, 0xdb, 0x67, 0x06, 0x2a, 0x13, 0xef, 0x4e, + 0x98, 0x6f, 0x5b, 0xb3, 0xd0, 0xbb, 0x43, 0x07 }, /* mdata */ + 40, /* mdata_len */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* mic */ + 16, /* mic_len */ + { 0x64, 0x4e, 0xb3, 0x4b, 0x9a, 0x12, 0x6e, 0x43, + 0x7b, 0x5e, 0x01, 0x5e, 0xea, 0x14, 0x1c, 0xa1, + 0xa8, 0x80, 0x20, 0xf2, 0xd5, 0xd6, 0xcc, 0x2c } /* expected */ + }, { + false, /* decrypt */ + 2, /* len_len */ + 2, /* key_size_index */ + 6, /* key_area */ + { 0x2e, 0x1e, 0x01, 0x32, 0x46, 0x85, 0x00, 0xd4, + 0xbd, 0x47, 0x86, 0x25, 0x63 }, /* nonce */ + { 0x3c, 0x5f, 0x54, 0x04, 0x37, 0x0a, 0xbd, 0xcb, + 0x1e, 0xdd, 0xe9, 0x9d, 0xe6, 0x0d, 0x06, 0x82, + 0xc6, 0x00, 0xb0, 0x34, 0xe0, 0x63, 0xb7, 0xd3, + 0x23, 0x77, 0x23, 0xda, 0x70, 0xab, 0x75, 0x52 }, /* adata */ + 32, /* adata_len */ + { 0x9c, 0x8d, 0x5d, 0xd2, 0x27, 0xfd, 0x9f, 0x81, + 0x23, 0x76, 0x01, 0x83, 0x0a, 0xfe, 0xe4, 0xf0, + 0x11, 0x56, 0x36, 0xc8, 0xe5, 0xd5, 0xfd, 0x74, + 0x3c, 0xb9, 0xaf, 0xed }, /* mdata */ + 28, /* mdata_len */ + { 0x00, 0x00, 0x00, 0x00 }, /* mic */ + 4, /* mic_len */ + { 0x23, 0x90, 0x29, 0xf1, 0x50, 0xbc, 0xcb, 0xd6, + 0x7e, 0xdb, 0xb6, 0x7f, 0x8a, 0xe4, 0x56, 0xb4, + 0xea, 0x06, 0x6a, 0x4b, 0xee, 0xe0, 0x65, 0xf9 } /* expected */ + } + }; + static int i; + static uint8_t key_size_index = -1, 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++) { + if(key_size_index != vectors[i].key_size_index) { + key_size_index = vectors[i].key_size_index; + printf("-----------------------------------------\n" + "Filling %d-bit key store...\n", 128 + (key_size_index << 6)); + time = RTIMER_NOW(); + ret = aes_load_keys(keys[key_size_index].keys, + keys[key_size_index].key_size, keys[key_size_index].count, 0); + time = RTIMER_NOW() - time; + printf("aes_load_keys(): %s, %lu us\n", str_res[ret], + (uint32_t)((uint64_t)time * 1000000 / RTIMER_SECOND)); + PROCESS_PAUSE(); + if(ret != CRYPTO_SUCCESS) { + break; + } + } + + 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(); + 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, + &ccm_test_process); + time2 = RTIMER_NOW(); + time = time2 - time; + total_time = time; + if(ret == CRYPTO_SUCCESS) { + PROCESS_WAIT_EVENT_UNTIL(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, + &ccm_test_process); + time2 = RTIMER_NOW(); + time = time2 - time; + total_time = time; + if(ret == CRYPTO_SUCCESS) { + PROCESS_WAIT_EVENT_UNTIL(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..f690ed27d --- /dev/null +++ b/examples/cc2538dk/crypto/sha256-test.c @@ -0,0 +1,261 @@ +/* + * 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", + "resource in use", + "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..dde73842e 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-256, SHA-256) * SmartRF06 EB and BB peripherals * LEDs * Buttons diff --git a/platform/remote/README.md b/platform/remote/README.md index f4ce1d302..7172ebd02 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-256, SHA-256) * LEDs * Buttons * Internal/external 2.4GHz antenna switch controllable by SW.