cc2538: Add crypto drivers and examples for AES-CCM and SHA-256

Signed-off-by: Benoît Thébaudeau <benoit.thebaudeau.dev@gmail.com>
This commit is contained in:
Benoît Thébaudeau 2015-05-15 19:52:08 +02:00
parent c03536f04e
commit 117dc4e5e3
16 changed files with 2363 additions and 0 deletions

View file

@ -49,6 +49,7 @@ CONTIKI_CPU_DIRS += ../cc253x/usb/common ../cc253x/usb/common/cdc-acm
### CPU-dependent source files ### CPU-dependent source files
CONTIKI_CPU_SOURCEFILES += clock.c rtimer-arch.c uart.c watchdog.c 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 += 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 += cc2538-rf.c udma.c lpm.c
CONTIKI_CPU_SOURCEFILES += dbg.c ieee-addr.c CONTIKI_CPU_SOURCEFILES += dbg.c ieee-addr.c
CONTIKI_CPU_SOURCEFILES += slip-arch.c slip.c CONTIKI_CPU_SOURCEFILES += slip-arch.c slip.c

118
cpu/cc2538/dev/aes.c Normal file
View file

@ -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 <stdint.h>
/*---------------------------------------------------------------------------*/
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;
}
/** @} */

487
cpu/cc2538/dev/aes.h Normal file
View file

@ -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 <stdint.h>
/*---------------------------------------------------------------------------*/
/** \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_ */
/**
* @}
* @}
*/

376
cpu/cc2538/dev/ccm.c Normal file
View file

@ -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 <stdbool.h>
#include <stdint.h>
/*---------------------------------------------------------------------------*/
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;
}
/** @} */

137
cpu/cc2538/dev/ccm.h Normal file
View file

@ -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 <stdbool.h>
#include <stdint.h>
/*---------------------------------------------------------------------------*/
/** \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_ */
/**
* @}
* @}
*/

74
cpu/cc2538/dev/crypto.c Normal file
View file

@ -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;
}
/** @} */

81
cpu/cc2538/dev/crypto.h Normal file
View file

@ -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_ */
/**
* @}
* @}
*/

344
cpu/cc2538/dev/sha256.c Normal file
View file

@ -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 <stdbool.h>
#include <stdint.h>
/*---------------------------------------------------------------------------*/
#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;
}
/** @} */

103
cpu/cc2538/dev/sha256.h Normal file
View file

@ -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 <stdint.h>
/*---------------------------------------------------------------------------*/
/** \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_ */
/**
* @}
* @}
*/

View file

@ -161,6 +161,34 @@
#define SYS_CTRL_SRGPT_GPT0 0x00000001 /**< GPT0 is reset */ #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 /** \name SYS_CTRL_PWRDBG register bits
* @{ * @{
*/ */

View file

@ -0,0 +1,6 @@
CONTIKI_PROJECT = ccm-test sha256-test
all: $(CONTIKI_PROJECT)
CONTIKI = ../../..
include $(CONTIKI)/Makefile.include

View file

@ -0,0 +1 @@
TARGET = cc2538dk

View file

@ -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 <stdbool.h>
#include <stdio.h>
#include <stdint.h>
/*---------------------------------------------------------------------------*/
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();
}
/*---------------------------------------------------------------------------*/
/**
* @}
* @}
*/

View file

@ -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 <stddef.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
/*---------------------------------------------------------------------------*/
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();
}
/*---------------------------------------------------------------------------*/
/**
* @}
* @}
*/

View file

@ -29,6 +29,7 @@ In terms of hardware support, the following drivers have been implemented:
* Low Power Modes * Low Power Modes
* General-Purpose Timers. NB: GPT0 is in use by the platform code, the remaining GPTs are available for application development. * General-Purpose Timers. NB: GPT0 is in use by the platform code, the remaining GPTs are available for application development.
* ADC * ADC
* Cryptoprocessor (AES-CCM-128, SHA-256)
* SmartRF06 EB and BB peripherals * SmartRF06 EB and BB peripherals
* LEDs * LEDs
* Buttons * Buttons

View file

@ -44,6 +44,7 @@ In terms of hardware support, the following drivers have been implemented:
* Low Power Modes * Low Power Modes
* General-Purpose Timers. NB: GPT0 is in use by the platform code, the remaining GPTs are available for application development. * General-Purpose Timers. NB: GPT0 is in use by the platform code, the remaining GPTs are available for application development.
* ADC * ADC
* Cryptoprocessor (AES-CCM-128, SHA-256)
* LEDs * LEDs
* Buttons * Buttons
* Internal/external 2.4GHz antenna switch controllable by SW. * Internal/external 2.4GHz antenna switch controllable by SW.