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