Skip to content

Instantly share code, notes, and snippets.

@sjlongland
Last active September 24, 2019 23:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sjlongland/e4cba74423116ebc77313602bd5d30fa to your computer and use it in GitHub Desktop.
Save sjlongland/e4cba74423116ebc77313602bd5d30fa to your computer and use it in GitHub Desktop.
AES/SHA mbedtls implementation
/* vim: set tw=78 sw=4 ts=4 et:
* Copyright (c) 2017, VRT Systems
* 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.
*/
#include "rom.h"
#include "aes.h"
#include "sysctrl.h"
#include <assert.h>
/*!
* Number of AES users
*/
static uint32_t cc2538AesUsers;
#ifdef AES_TRACE
#include <stdio.h>
#include <string.h>
#endif
#define AES_CTRL_ALG_SEL_TAG (1 << 31) /* DMA includes TAG */
#define AES_CTRL_ALG_SEL_HASH (1 << 2) /* Hash mode */
#define AES_CTRL_ALG_SEL_AES (1 << 1) /* AES encrypt/decrypt mode */
#define AES_CTRL_ALG_SEL_KEYSTORE (1 << 0) /* Key store mode */
#define AES_HASH_MODE_IN_SHA256 (1 << 3) /* Hash mode is SHA256 */
#define AES_HASH_MODE_IN_NEW (1 << 0) /* Generate new hash */
#define AES_CTRL_INT_RESULT_AV (1 << 0) /* Result available */
#define AES_CTRL_INT_DMA_IN_DONE (1 << 1) /* DMA Input complete */
#define AES_CTRL_INT_DMA_BUS_ERR (1 << 31) /* DMA Bus Error */
#define AES_CTRL_INT_DMA_KEY_ST_WR_ERR (1 << 30) /* DMA Key Store Write Error */
#define AES_CTRL_INT_DMA_KEY_ST_RD_ERR (1 << 29) /* DMA Key Store Read Error */
#define AES_HASH_IO_BUF_CTRL_PAD_DMA_MSG (1 << 7) /* Pad DMAed message data */
#define AES_DMAC_CHx_CTRL_EN (1 << 0) /* Enable DMA channel */
#define AES_DMAC_CHx_CTRL_PRIO (1 << 1) /* Enable DMA priority */
#define AES_CTRL_INT_CFG_LEVEL (1 << 0)
#define AES_AES_CTRL_CTX_READY (1 << 31) /* AES Context ready */
#define AES_AES_CTRL_SAVED_CTX_READY (1 << 30) /* AES Saved Context ready */
#define AES_AES_CTRL_SAVE_CTX (1 << 29) /* AES Save Context */
#define AES_AES_CTRL_CCM_M(m) ((m) << 22) /* AES-CCM M field */
#define AES_AES_CTRL_CCM_L(l) ((l) << 19) /* AES-CCM L field */
#define AES_AES_CTRL_CCM (1 << 18) /* AES CCM mode */
#define AES_AES_CTRL_GCM(m) ((m) << 16) /* AES-GCM mode */
#define AES_AES_CTRL_CBC_MAC (1 << 15) /* AES-CBC MAC */
#define AES_AES_CTRL_CTR_WIDTH(w) ((w) << 7) /* AES-CTR counter width */
#define AES_AES_CTRL_CTR (1 << 6) /* AES-CTR mode */
#define AES_AES_CTRL_CBC (1 << 5) /* AES-CBC mode */
#define AES_AES_CTRL_DIRECTION (1 << 2) /* Direction (1=encrypt) */
#define AES_AES_CTRL_INPUT_READY (1 << 1) /* Input is ready */
#define AES_AES_CTRL_OUTPUT_READY (1 << 0) /* Output is ready */
#define AES_KEY_STORE_READ_AREA_BUSY (1 << 31) /* Key store busy */
/**
* Enable the AES crypto engine
*/
void cc2538AesEnable()
{
assert(cc2538AesUsers < UINT32_MAX);
if (!cc2538AesUsers) {
/* First customer */
uint8_t delay = 16;
/* Turn on AES module */
HWREG(SYS_CTRL_RCGCSEC) |= (1 << SYS_CTRL_xCGCSEC_AES);
HWREG(SYS_CTRL_SCGCSEC) |= (1 << SYS_CTRL_xCGCSEC_AES);
HWREG(SYS_CTRL_DCGCSEC) |= (1 << SYS_CTRL_xCGCSEC_AES);
/* Reset the module */
HWREG(SYS_CTRL_SRSEC) |= (1 << SYS_CTRL_xCGCSEC_AES);
while(delay--);
HWREG(SYS_CTRL_SRSEC) &= ~(1 << SYS_CTRL_xCGCSEC_AES);
#ifdef AES_TRACE
iprintf("%s:%d: AES enabled\r\n", __FILE__, __LINE__);
#endif
}
cc2538AesUsers++;
}
/**
* Disable the AES crypto engine
*/
void cc2538AesDisable()
{
assert(cc2538AesUsers > 0);
cc2538AesUsers--;
if (!cc2538AesUsers) {
/* Turn off AES module */
HWREG(SYS_CTRL_RCGCSEC) &= ~(1 << SYS_CTRL_xCGCSEC_AES);
HWREG(SYS_CTRL_SCGCSEC) &= ~(1 << SYS_CTRL_xCGCSEC_AES);
HWREG(SYS_CTRL_DCGCSEC) &= ~(1 << SYS_CTRL_xCGCSEC_AES);
#ifdef AES_TRACE
iprintf("%s:%d: AES disabled\r\n", __FILE__, __LINE__);
#endif
}
}
/**
* Determine the result of the hash operation.
*
* @retval 0 Operation competed successfully
* @retval -EINPROGRESS Device is still busy performing an operation
* @retval -EIO Memory transfer failed
*/
int32_t cc2538AesHashStatus()
{
uint32_t status = HWREG(AES_CTRL_INT_STAT);
#ifdef AES_TRACE
iprintf("%s:%d: AES status = 0x%08lx\r\n", __FILE__, __LINE__, status);
#endif
if (!(status & AES_CTRL_INT_RESULT_AV)) {
#ifdef AES_TRACE
iprintf("%s:%d: hash in progress\r\n", __FILE__, __LINE__);
#endif
return -EINPROGRESS;
}
if (status & AES_CTRL_INT_DMA_BUS_ERR) {
#ifdef AES_TRACE
iprintf("%s:%d: DMA bus error\r\n", __FILE__, __LINE__);
#endif
return -EIO;
}
/* All good */
return 0;
}
/**
* Clear the state of the hashing registers. This acknowledges the related
* interrupt flags and resets the state ready for use.
*/
void cc2538AesHashFinish()
{
HWREG(AES_CTRL_INT_EN) = 0;
HWREG(AES_CTRL_INT_CLR) = AES_CTRL_INT_RESULT_AV
| AES_CTRL_INT_DMA_IN_DONE
| AES_CTRL_INT_DMA_BUS_ERR
| AES_CTRL_INT_DMA_KEY_ST_RD_ERR
| AES_CTRL_INT_DMA_KEY_ST_WR_ERR;
HWREG(AES_DMAC_CH0_CTRL) = 0;
HWREG(AES_DMAC_CH1_CTRL) = 0;
#ifdef AES_TRACE
iprintf("%s:%d: AES hash finished\r\n", __FILE__, __LINE__);
#endif
}
/**
* Begin hashing a given block of data, returning the hash value to the given
* block of memory. The SHA-256 hash of the data block will be computed in
* hardware and returned to the given block of memory.
*
* Blocks must reside in RAM and can be a maximum of 64kB in size. To hash
* more than 64kB, allocate a buffer of <= 64kB, then:
* - read in the first buffer and call this function initially with
* `dataLen=buffer size`, `hashIn=NULL` and `pad=False`.
* - read in the next buffer and call again with `dataLen=buffer size`,
* `hashIn=previous result` and `pad=False`.
* - read in the final buffer and call with `dataLen=remainder`,
* `hashIn=previous result` and `pad=True`.
* After calling the last function, the result buffer should contain the
* correct hash value.
*
* The `totalLen` must be set to the length of the entire block of data. When
* hashing a single block less than 64kB in size, `totalLen = dataLen`.
*
* The following assumptions are made:
* - the block will not be re-located or modified during the operation
* - the block start address is correctly aligned (32-bit word alignment)
* - Both input and output hash buffers are 32-bit word aligned.
*
* @param[in] dataIn Data input to be hashed
* @param[in] dataLen Length of data to be hashed
* @param[in] totalLen Total length of data to be hashed (if hashing a
* large block in smaller chunks)
* @param[in] hashIn Initial hash value input, NULL if creating a new hash.
* @param[out] hashOut Hash value output.
* @param[in] hashLen Hash value length.
* @param[in] pad Whether or not to pad the data
*
* @retval 0 Operation begun
* @retval -EBUSY Device is busy with another operation
*/
int32_t cc2538AesHashStart(const void *dataIn, uint16_t dataLen,
uint32_t totalLen, void *hashIn, void *hashOut, uint32_t hashLen,
_Bool pad)
{
uint32_t temp;
#ifdef AES_TRACE
iprintf("%s:%d: AES hash start("
"in %p(%u of %lu) "
"hash %p→%p(%lu) "
"pad=%c)\r\n",
__FILE__, __LINE__,
(void*)dataIn, dataLen, totalLen,
(void*)hashIn, (void*)hashOut, hashLen,
(pad) ? 'Y' : 'N'
);
#endif
/* Check we're not busy or have an unacknowledged state */
if (HWREG(AES_DMAC_STATUS) || HWREG(AES_CTRL_INT_STAT)) {
#ifdef AES_TRACE
iprintf("%s:%d: AES busy\r\n", __FILE__, __LINE__);
#endif
return -EBUSY;
}
/*
* Sanity check alignment of values. For 32-bit boundary alignment,
* the lower two bits should both be zero.
*/
if (((uintptr_t)dataIn) & 0x3) {
#ifdef AES_TRACE
iprintf("%s:%d: dataIn misaligned\r\n", __FILE__, __LINE__);
#endif
return -EFAULT;
}
if (((uintptr_t)hashIn) & 0x3) {
#ifdef AES_TRACE
iprintf("%s:%d: hashIn misaligned\r\n", __FILE__, __LINE__);
#endif
return -EFAULT;
}
if (((uintptr_t)hashOut) & 0x3) {
#ifdef AES_TRACE
iprintf("%s:%d: hashOut misaligned\r\n", __FILE__, __LINE__);
#endif
return -EFAULT;
}
/*
* Enable interrupts. They won't *actually* interrupt the CPU unless
* also enabled in NVIC, *BUT* we won't see anything in the interrupt
* status unless these are set.
*/
HWREG(AES_CTRL_INT_CFG) = AES_CTRL_INT_CFG_LEVEL;
HWREG(AES_CTRL_INT_EN) = AES_CTRL_INT_DMA_IN_DONE
| AES_CTRL_INT_RESULT_AV;
/* Select SHA256 as our algorithm */
HWREG(AES_CTRL_ALG_SEL) = AES_CTRL_ALG_SEL_HASH
| AES_CTRL_ALG_SEL_TAG;
if (hashIn)
{
#ifdef AES_TRACE
iprintf("%s:%d: copy hash in\r\n", __FILE__, __LINE__);
#endif
/* Existing hash given, copy it in first */
CC2538_ROM_FUNC.memcpy((void*)(AES_HASH_DIGEST_A), hashIn, hashLen);
/* Select SHA256 mode with existing hash result */
HWREG(AES_HASH_MODE_IN) = AES_HASH_MODE_IN_SHA256;
}
else
{
#ifdef AES_TRACE
iprintf("%s:%d: new hash\r\n", __FILE__, __LINE__);
#endif
/* No existing hash, so assume new hash */
HWREG(AES_HASH_MODE_IN) = AES_HASH_MODE_IN_SHA256 | AES_HASH_MODE_IN_NEW;
}
/*
* Copy across size. The message length is given in bits so we need to
* multiply by 8. This pushes the *upper* three bits into the upper
* 32-bit long word: the same result is achieved by left shifting 32-3=29
* places.
*/
HWREG(AES_HASH_LENGTH_IN_L) = totalLen << 3;
HWREG(AES_HASH_LENGTH_IN_H) = totalLen >> 29;
/* Enable padding of the message if selected */
if (pad)
HWREG(AES_HASH_IO_BUF_CTRL) = AES_HASH_IO_BUF_CTRL_PAD_DMA_MSG;
else
HWREG(AES_HASH_IO_BUF_CTRL) = 0;
/* If the length is less than 4 bytes, store in a temporary buffer */
if (dataLen < sizeof(temp)) {
#ifdef AES_TRACE
iprintf("%s:%d: copy %p (%u) to temporary stack buffer\r\n",
__FILE__, __LINE__, (void*)dataIn, dataLen
);
#endif
temp = 0;
CC2538_ROM_FUNC.memcpy(&temp, dataIn, dataLen);
dataIn = (void*)(&temp);
}
/* Set up DMA channel 0 to read the incoming data */
#ifdef AES_TRACE
iprintf("%s:%d: read from %p (%u)\r\n",
__FILE__, __LINE__, (void*)dataIn, dataLen
);
#endif
HWREG(AES_DMAC_CH0_CTRL) = AES_DMAC_CHx_CTRL_EN;
HWREG(AES_DMAC_CH0_EXTADDR) = (uint32_t)dataIn;
HWREG(AES_DMAC_CH0_DMALENGTH) = dataLen;
/* Set up DMA channel 1 to write the outgoing hash */
#ifdef AES_TRACE
iprintf("%s:%d: write to %p (%lu)\r\n",
__FILE__, __LINE__, (void*)hashOut, hashLen
);
#endif
HWREG(AES_DMAC_CH1_CTRL) = AES_DMAC_CHx_CTRL_EN;
HWREG(AES_DMAC_CH1_EXTADDR) = (uint32_t)hashOut;
HWREG(AES_DMAC_CH1_DMALENGTH) = hashLen;
#ifdef AES_TRACE
iprintf("%s:%d: hashing started\r\n", __FILE__, __LINE__);
#endif
return 0;
}
/*
* Return which slots are occupied by a key. Returns a bitmap of keys.
*/
uint8_t cc2538AesKeyStoreStatus() {
uint8_t res = HWREG(AES_KEY_STORE_WRITTEN_AREA) & 0x000000fful;
#ifdef AES_TRACE
iprintf("%s:%d: key status = 0x%02x\r\n", __FILE__, __LINE__, res);
#endif
return res;
}
/*
* Get the currently defined key length.
*/
uint8_t cc2538AesKeyStoreGetLength() {
return HWREG(AES_KEY_STORE_SIZE);
}
/*
* Set the key length for all keys in the key store.
* *Warning*: This will erase all existing keys in the key store!
*
* @param[in] len Length of keys to use in the key store
* (see @ref hal_aes_ks_len)
* @retval -EINVAL Invalid key length.
*/
int32_t cc2538AesKeyStoreSetLength(uint8_t len) {
#ifdef AES_TRACE
iprintf("%s:%d: AES key store set length (%u)\r\n",
__FILE__, __LINE__, len);
#endif
/* Check we're not busy or have an unacknowledged state */
if (HWREG(AES_DMAC_STATUS) || HWREG(AES_CTRL_INT_STAT)) {
#ifdef AES_TRACE
iprintf("%s:%d: AES busy\r\n", __FILE__, __LINE__);
#endif
return -EBUSY;
}
/* We only support 3 possible key sizes */
switch (len) {
case AES_KS_LEN_128:
case AES_KS_LEN_192:
case AES_KS_LEN_256:
break;
default:
#ifdef AES_TRACE
iprintf("%s:%d: invalid len\r\n", __FILE__, __LINE__);
#endif
return -EINVAL;
}
/* Select the key size */
HWREG(AES_KEY_STORE_SIZE) = len;
return 0;
}
/*
* Write a key to the key store at the given slot.
*
* @param[in] slot Key store slot position (0…AES_KS_NUM_KEYS-1)
* @param[in] key Key data
*
* @retval 0 Success
* @retval -EINVAL Invalid arguments (e.g. misaligned position or input)
*/
int32_t cc2538AesKeyStoreWrite(uint8_t slot, const uint8_t* key) {
const uint8_t len = cc2538AesKeyStoreGetLength();
#ifdef AES_TRACE
iprintf("%s:%d: AES key store write (slot %u key %p len %u)\r\n",
__FILE__, __LINE__, slot, (void*)key, len);
#endif
/*
* Key buffer storage. For 192-bit keys, the AES core expects the key to
* be padded to 256-bits. Copying the buffer here also solves the issue that
* the key pointer may be imporperly aligned.
*/
uint32_t key_buffer[8];
int32_t res = 0;
uint8_t byte_len;
/* Check we're not busy or have an unacknowledged state */
if (HWREG(AES_DMAC_STATUS) || HWREG(AES_CTRL_INT_STAT)) {
#ifdef AES_TRACE
iprintf("%s:%d: AES busy\r\n", __FILE__, __LINE__);
#endif
return -EBUSY;
}
/* There are 8 slots */
if (slot >= AES_KS_NUM_KEYS) {
#ifdef AES_TRACE
iprintf("%s:%d: invalid slot\r\n", __FILE__, __LINE__);
#endif
return -EBADF;
}
/* We only support 3 possible key sizes */
switch (len) {
case AES_KS_LEN_128:
byte_len = 128/8;
if ((uintptr_t)key & 0x03) {
/* Misaligned key */
CC2538_ROM_FUNC.memset(key_buffer, 0, sizeof(key_buffer));
CC2538_ROM_FUNC.memcpy(key_buffer, key, byte_len);
/* Use this buffer instead of the given one, copy entire buffer */
key = (uint8_t*)key_buffer;
}
break;
case AES_KS_LEN_192:
/* Copy the key to our buffer and pad with zeros */
CC2538_ROM_FUNC.memset(key_buffer, 0, sizeof(key_buffer));
CC2538_ROM_FUNC.memcpy(key_buffer, key, 192/8);
/* Use this buffer instead of the given one, copy entire buffer */
key = (uint8_t*)key_buffer;
byte_len = 256/8;
break;
case AES_KS_LEN_256:
byte_len = 256/8;
if ((uintptr_t)key & 0x03) {
/* Copy the key to our buffer */
CC2538_ROM_FUNC.memcpy(key_buffer, key, 192/8);
key = (uint8_t*)key_buffer;
}
break;
default:
#ifdef AES_TRACE
iprintf("%s:%d: invalid len\r\n", __FILE__, __LINE__);
#endif
return -EINVAL;
}
/*
* Enable interrupts. They won't *actually* interrupt the CPU unless
* also enabled in NVIC, *BUT* we won't see anything in the interrupt
* status unless these are set.
*/
HWREG(AES_CTRL_INT_CFG) = AES_CTRL_INT_CFG_LEVEL;
HWREG(AES_CTRL_INT_EN) = AES_CTRL_INT_DMA_IN_DONE
| AES_CTRL_INT_RESULT_AV;
/* Select key store as our "algorithm" */
HWREG(AES_CTRL_ALG_SEL) = AES_CTRL_ALG_SEL_KEYSTORE;
/* Select the key size */
HWREG(AES_KEY_STORE_SIZE) = len;
/* Select the destination slot to write to. */
HWREG(AES_KEY_STORE_WRITE_AREA) = (1 << slot);
/* Set up DMA channel 0 to read the new key */
HWREG(AES_DMAC_CH0_CTRL) = AES_DMAC_CHx_CTRL_EN;
HWREG(AES_DMAC_CH0_EXTADDR) = (uint32_t)key;
HWREG(AES_DMAC_CH0_DMALENGTH) = byte_len;
/* Busy-wait for it to finish (shouldn't be long) */
while (!HWREG(AES_CTRL_INT_STAT));
#ifdef AES_TRACE
iprintf("%s:%d: status = 0x%08lx\r\n", __FILE__, __LINE__,
HWREG(AES_CTRL_INT_STAT));
#endif
/* Check for errors */
if (HWREG(AES_CTRL_INT_STAT) & (AES_CTRL_INT_DMA_BUS_ERR
| AES_CTRL_INT_DMA_KEY_ST_WR_ERR)) {
/* DMA error */
res = -EIO;
}
/* We should be good */
HWREG(AES_CTRL_INT_EN) = 0;
HWREG(AES_CTRL_INT_CLR) = AES_CTRL_INT_RESULT_AV
| AES_CTRL_INT_DMA_IN_DONE
| AES_CTRL_INT_DMA_BUS_ERR
| AES_CTRL_INT_DMA_KEY_ST_RD_ERR
| AES_CTRL_INT_DMA_KEY_ST_WR_ERR;
HWREG(AES_DMAC_CH0_CTRL) = 0;
/* De-select the algorithm */
HWREG(AES_CTRL_ALG_SEL) = 0;
/* See if there's already an error */
if (res) {
#ifdef AES_TRACE
iprintf("%s:%d: failed %s\r\n", __FILE__, __LINE__, strerror(-res));
#endif
return res;
}
/* See if it got written in the end */
if (cc2538AesKeyStoreStatus() & (1 << slot)) {
/* Success */
#ifdef AES_TRACE
iprintf("%s:%d: success\r\n", __FILE__, __LINE__);
#endif
return 0;
} else {
/* Didn't get written after all */
#ifdef AES_TRACE
iprintf("%s:%d: failed (unknown)\r\n", __FILE__, __LINE__);
#endif
return -EPROTO;
}
}
/*
* Encrypt or decrypt one or more blocks using AES-ECB.
*
* @param[in] slot The key store slot containing the desired key
* @param[in] direction Direction: 0 = decrypt, 1 = encrypt
* @param[in] input Clear-text (direction=0) or Cipher-text
* (direction=1) buffer.
* @param[in] input_sz Length of input buffer
* @param[out] output Clear-text (direction=1) or Cipher-text
* (direction=0) buffer.
* @param[in] output_sz Length of output buffer
* @param[out] ciphertext Encrypted data
* @param[in] ciphertext_sz Length of the encrypted data buffer
*/
int32_t cc2538AesEcb(
uint8_t slot,
uint8_t direction,
const uint8_t* input,
size_t input_sz,
uint8_t* output,
size_t output_sz
) {
#ifdef AES_TRACE
iprintf("%s:%d: AES crypt (slot %u dir %u in %p(%u) out %p(%u))\r\n",
__FILE__, __LINE__, slot, direction,
(void*)input, input_sz,
(void*)output, output_sz
);
#endif
int32_t res = 0;
/* Check we're not busy or have an unacknowledged state */
if (HWREG(AES_DMAC_STATUS) || HWREG(AES_CTRL_INT_STAT)) {
#ifdef AES_TRACE
iprintf("%s:%d: AES busy\r\n", __FILE__, __LINE__);
#endif
return -EBUSY;
}
/* Ensure the key is defined */
if (!(cc2538AesKeyStoreStatus() & (1 << slot))) {
#ifdef AES_TRACE
iprintf("%s:%d: no key in slot\r\n", __FILE__, __LINE__);
#endif
return -ENOENT;
}
/*
* Sanity check alignment of values. For 32-bit boundary alignment,
* the lower two bits should both be zero.
*/
if (((uintptr_t)input) & 0x3) {
#ifdef AES_TRACE
iprintf("%s:%d: input misaligned\r\n", __FILE__, __LINE__);
#endif
return -EFAULT;
}
if (((uintptr_t)output) & 0x3) {
#ifdef AES_TRACE
iprintf("%s:%d: output misaligned\r\n", __FILE__, __LINE__);
#endif
return -EFAULT;
}
/*
* Enable interrupts. They won't *actually* interrupt the CPU unless
* also enabled in NVIC, *BUT* we won't see anything in the interrupt
* status unless these are set.
*/
HWREG(AES_CTRL_INT_CFG) = AES_CTRL_INT_CFG_LEVEL;
HWREG(AES_CTRL_INT_EN) = AES_CTRL_INT_DMA_IN_DONE
| AES_CTRL_INT_RESULT_AV;
/* Select the AES algorithm */
HWREG(AES_CTRL_ALG_SEL) = AES_CTRL_ALG_SEL_AES;
/* Select the desired key and wait for it to be loaded */
HWREG(AES_KEY_STORE_READ_AREA) = slot;
while(HWREG(AES_KEY_STORE_READ_AREA) & AES_KEY_STORE_READ_AREA_BUSY);
/* Define the message length and sub-algorithm options */
HWREG(AES_AES_CTRL) = (direction) ? AES_AES_CTRL_DIRECTION : 0;
const size_t msg_len = (direction) ? input_sz : output_sz;
HWREG(AES_AES_C_LENGTH_0) = msg_len;
HWREG(AES_AES_C_LENGTH_1) = 0;
/* Set up DMA channel 0 to read the input into the AES module */
HWREG(AES_DMAC_CH0_CTRL) = AES_DMAC_CHx_CTRL_EN;
HWREG(AES_DMAC_CH0_EXTADDR) = (uint32_t)input;
HWREG(AES_DMAC_CH0_DMALENGTH) = input_sz;
/* Set up DMA channel 1 to read the output out of the AES module */
HWREG(AES_DMAC_CH1_CTRL) = AES_DMAC_CHx_CTRL_EN;
HWREG(AES_DMAC_CH1_EXTADDR) = (uint32_t)output;
HWREG(AES_DMAC_CH1_DMALENGTH) = output_sz;
/* Busy-wait for it to finish or for error (shouldn't be long) */
while (!(HWREG(AES_CTRL_INT_STAT) & (AES_CTRL_INT_RESULT_AV
| AES_CTRL_INT_DMA_KEY_ST_RD_ERR
| AES_CTRL_INT_DMA_KEY_ST_WR_ERR
| AES_CTRL_INT_DMA_BUS_ERR)));
#ifdef AES_TRACE
iprintf("%s:%d: status = 0x%08lx\r\n", __FILE__, __LINE__,
HWREG(AES_CTRL_INT_STAT));
#endif
/* Check for errors */
if (HWREG(AES_CTRL_INT_STAT) & AES_CTRL_INT_DMA_BUS_ERR) {
/* DMA error */
res = -EIO;
} else if (HWREG(AES_CTRL_INT_STAT) & (AES_CTRL_INT_DMA_KEY_ST_RD_ERR
| AES_CTRL_INT_DMA_KEY_ST_WR_ERR)) {
/* Key store error */
res = -ENOENT;
}
/* We should be good */
HWREG(AES_CTRL_INT_EN) = 0;
HWREG(AES_CTRL_INT_CLR) = AES_CTRL_INT_RESULT_AV
| AES_CTRL_INT_DMA_IN_DONE
| AES_CTRL_INT_DMA_BUS_ERR
| AES_CTRL_INT_DMA_KEY_ST_RD_ERR
| AES_CTRL_INT_DMA_KEY_ST_WR_ERR;
HWREG(AES_DMAC_CH0_CTRL) = 0;
/* De-select the algorithm */
HWREG(AES_CTRL_ALG_SEL) = 0;
#ifdef AES_TRACE
iprintf("%s:%d: res = %s\r\n", __FILE__, __LINE__, strerror(-res));
#endif
return res;
}
/* vim: set tw=78 sw=4 ts=4 et:
* Copyright (c) 2017, VRT Systems
* 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.
*/
#ifndef AES_H_
#define AES_H_
#include <stdint.h>
#include <stdbool.h>
#include <errno.h>
#ifdef __cplusplus
extern "C" {
#endif
/*!
* @addtogroup hal_cc2538
* @{
*
* @defgroup hal_cc2538_aes AES/SHA-256 Cryptograhy Module support
*
* The AES module is a hardware module built into the TI CC2538
* microcontroller which implements hardware AES-128 encryption/decryption and
* SHA-256 hash generation.
*
* Prior to performing any operations, the module must be enabled using the
* @ref cc2538AesEnable function. In low power applications, it may be desirable
* to switch this function back off again when not in use, the
* @ref cc2538AesDisable function can accomplish this.
*
* Actual hashes are generated by calling @ref cc2538AesHashStart. The hardware
* module will begin computing a hash with the given data and the CC2538's
* CPU is free to go about its business whilst this value is computed.
*
* @ref cc2538AesHashStatus can be periodically polled to find out if hashing is
* complete or if there was an error. After hashing, @ref cc2538AesHashFinish
* should be called to reset the state of the AES module.
*
* @{
*/
/*!
* @defgroup hal_aes_hwreg AES hardware registers
* @{
*/
#include "cc2538-reg.h"
/*! AES Module base address */
#define AES_BASE (0x4008b000)
/*! AES DMA Ch0 Control */
#define AES_DMAC_CH0_CTRL (AES_BASE | 0x000)
/*! AES DMA Ch0 Address */
#define AES_DMAC_CH0_EXTADDR (AES_BASE | 0x004)
/*! AES DMA Ch0 Length */
#define AES_DMAC_CH0_DMALENGTH (AES_BASE | 0x00c)
/*! AES DMA Status */
#define AES_DMAC_STATUS (AES_BASE | 0x018)
/*! AES DMA Software Reset */
#define AES_DMAC_SWRES (AES_BASE | 0x01c)
/*! AES DMA Ch1 Control */
#define AES_DMAC_CH1_CTRL (AES_BASE | 0x020)
/*! AES DMA Ch1 Address */
#define AES_DMAC_CH1_EXTADDR (AES_BASE | 0x024)
/*! AES DMA Ch1 Length */
#define AES_DMAC_CH1_DMALENGTH (AES_BASE | 0x02c)
/*! AES DMA Master Run-Time Parameters */
#define AES_DMAC_MST_RUNPARAMS (AES_BASE | 0x078)
/*! AES DMA Port Error Raw Status */
#define AES_DMAC_PERSR (AES_BASE | 0x07c)
/*! AES DMA Options */
#define AES_DMAC_OPTIONS (AES_BASE | 0x0f8)
/*! AES DMA Version */
#define AES_DMAC_VERSION (AES_BASE | 0x0fc)
/*! AES Key Store Write area */
#define AES_KEY_STORE_WRITE_AREA (AES_BASE | 0x400)
/*! AES Key Store Writtten area */
#define AES_KEY_STORE_WRITTEN_AREA (AES_BASE | 0x404)
/*! AES Key Store Size */
#define AES_KEY_STORE_SIZE (AES_BASE | 0x408)
/*! AES Key Store Read area */
#define AES_KEY_STORE_READ_AREA (AES_BASE | 0x40c)
/*! AES Control */
#define AES_AES_CTRL (AES_BASE | 0x550)
/*! AES Crypto length MSW */
#define AES_AES_C_LENGTH_0 (AES_BASE | 0x554)
/*! AES Crypto length LSW */
#define AES_AES_C_LENGTH_1 (AES_BASE | 0x558)
/*! AES Hash I/O Buffer Control */
#define AES_HASH_IO_BUF_CTRL (AES_BASE | 0x640)
/*! AES Hash Mode */
#define AES_HASH_MODE_IN (AES_BASE | 0x644)
/*! AES Hash Length: Lower 32-bits */
#define AES_HASH_LENGTH_IN_L (AES_BASE | 0x648)
/*! AES Hash Length: Upper 32-bits */
#define AES_HASH_LENGTH_IN_H (AES_BASE | 0x64c)
/*! AES Hash Output: Part A */
#define AES_HASH_DIGEST_A (AES_BASE | 0x650)
/*! AES Hash Output: Part B */
#define AES_HASH_DIGEST_B (AES_BASE | 0x654)
/*! AES Hash Output: Part C */
#define AES_HASH_DIGEST_C (AES_BASE | 0x658)
/*! AES Hash Output: Part D */
#define AES_HASH_DIGEST_D (AES_BASE | 0x65c)
/*! AES Hash Output: Part E */
#define AES_HASH_DIGEST_E (AES_BASE | 0x660)
/*! AES Hash Output: Part F */
#define AES_HASH_DIGEST_F (AES_BASE | 0x664)
/*! AES Hash Output: Part G */
#define AES_HASH_DIGEST_G (AES_BASE | 0x668)
/*! AES Hash Output: Part H */
#define AES_HASH_DIGEST_H (AES_BASE | 0x66c)
/*! AES Control Algorithm Select */
#define AES_CTRL_ALG_SEL (AES_BASE | 0x700)
/*! AES Master PROT privileged access enable */
#define AES_CTRL_PROT_EN (AES_BASE | 0x704)
/*! AES Control Software Reset */
#define AES_CTRL_SW_RESET (AES_BASE | 0x740)
/*! AES Control Interrupt Configuration */
#define AES_CTRL_INT_CFG (AES_BASE | 0x780)
/*! AES Control Interrupt Enable */
#define AES_CTRL_INT_EN (AES_BASE | 0x784)
/*! AES Control Interrupt Clear */
#define AES_CTRL_INT_CLR (AES_BASE | 0x788)
/*! AES Control Interrupt Set */
#define AES_CTRL_INT_SET (AES_BASE | 0x78c)
/*! AES Control Interrupt Status */
#define AES_CTRL_INT_STAT (AES_BASE | 0x790)
/*! AES Control Options */
#define AES_CTRL_OPTIONS (AES_BASE | 0x7f8)
/*! @} */
/**
* Enable the AES crypto engine
*/
void cc2538AesEnable();
/**
* Disable the AES crypto engine
*/
void cc2538AesDisable();
/*!
* @defgroup hal_aes_sha256 SHA-256
* @{
*/
/**
* Determine the result of the hash operation.
*
* @retval 0 Operation competed successfully
* @retval -EINPROGRESS Device is still busy performing an operation
* @retval -EIO Memory transfer failed
*/
int32_t cc2538AesHashStatus();
/**
* Clear the state of the hashing registers. This acknowledges the related
* interrupt flags and resets the state ready for use.
*/
void cc2538AesHashFinish();
/**
* Begin hashing a given block of data, returning the hash value to the given
* block of memory. The SHA-256 hash of the data block will be computed in
* hardware and returned to the given block of memory.
*
* Blocks must reside in RAM and can be a maximum of 64kB in size. To hash
* more than 64kB, allocate a buffer of <= 64kB, then:
* - read in the first buffer and call this function initially with
* `dataLen=buffer size`, `hashIn=NULL` and `pad=False`.
* - read in the next buffer and call again with `dataLen=buffer size`,
* `hashIn=previous result` and `pad=False`.
* - read in the final buffer and call with `dataLen=remainder`,
* `hashIn=previous result` and `pad=True`.
* After calling the last function, the result buffer should contain the
* correct hash value.
*
* The `totalLen` must be set to the length of the entire block of data. When
* hashing a single block less than 64kB in size, `totalLen = dataLen`.
*
* The following assumptions are made:
* - the block will not be re-located or modified during the operation
* - the block start address is correctly aligned (32-bit word alignment)
* - Both input and output hash buffers are 32-bit word aligned.
*
* @param[in] dataIn Data input to be hashed
* @param[in] dataLen Length of data to be hashed
* @param[in] totalLen Total length of data to be hashed (if hashing a
* large block in smaller chunks)
* @param[in] hashIn Initial hash value input, NULL if creating a new hash.
* @param[out] hashOut Hash value output.
* @param[in] hashLen Hash value length.
* @param[in] pad Whether or not to pad the data
*
* @retval 0 Operation begun
* @retval -EBUSY Device is busy with another operation
*/
int32_t cc2538AesHashStart(const void *dataIn, uint16_t dataLen,
uint32_t totalLen, void *hashIn, void *hashOut, uint32_t hashLen,
_Bool pad);
/*!
* @}
*/
/*!
* @defgroup hal_aes_ks Key store
* @{
*
* The CC2538 AES module has a 8-slot key store for storing AES keys. Each
* slot is 128-bits in size, so two slots must be used when storing a 192 or
* 256-bit key (and the key must not straddle a 256-bit boundary).
*
* The keys (from the CC2538's perspective) are write-only.
*/
/*!
* @defgroup hal_aes_ks_len Key lengths
* @{
*
* These constants define the length of a key. In cases where a key is
* greater than 128-bits in length; two adjacent key slots are consumed and
* only "even"-numbered slots (i.e. 0, 2, 4 or 6) may be used.
*/
#define AES_KS_LEN_128 (1) /*!< Key length is 128-bits */
#define AES_KS_LEN_192 (2) /*!< Key length is 192-bits */
#define AES_KS_LEN_256 (3) /*!< Key length is 256-bits */
/*!
* @}
*/
/*!
* Number of key store slots.
*/
#define AES_KS_NUM_KEYS (8)
/*!
* Return which slots are occupied by a key. Returns a bitmap of keys.
*/
uint8_t cc2538AesKeyStoreStatus();
/*!
* Get the currently defined key length.
*/
uint8_t cc2538AesKeyStoreGetLength();
/*!
* Set the key length for all keys in the key store.
* *Warning*: This will erase all existing keys in the key store!
*
* @param[in] len Length of keys to use in the key store
* (see @ref hal_aes_ks_len)
* @retval -EINVAL Invalid key length.
*/
int32_t cc2538AesKeyStoreSetLength(uint8_t len);
/*!
* Write a key to the key store at the given slot. Note: if a key length of
* 192 or 256 bits was selected, only slots 0, 2, 4 or 6 may be used.
*
* @param[in] slot Key store slot position (0…AES_KS_NUM_KEYS-1)
* @param[in] key Key data
*
* @retval 0 Success
* @retval -EINVAL Invalid arguments (e.g. misaligned input)
*/
int32_t cc2538AesKeyStoreWrite(uint8_t slot, const uint8_t* key);
/*!
* @}
*/
/*!
* @defgroup hal_aes_ecb AES-ECB functions
* @{
*/
/*!
* Encrypt or decrypt one or more blocks using AES-ECB.
*
* @param[in] slot The key store slot containing the desired key
* @param[in] direction Direction: 0 = decrypt, 1 = encrypt
* @param[in] input Clear-text (direction=0) or Cipher-text
* (direction=1) buffer.
* @param[in] input_sz Length of input buffer
* @param[out] output Clear-text (direction=1) or Cipher-text
* (direction=0) buffer.
* @param[in] output_sz Length of output buffer
* @param[out] ciphertext Encrypted data
* @param[in] ciphertext_sz Length of the encrypted data buffer
*/
int32_t cc2538AesEcb(
uint8_t slot,
uint8_t direction,
const uint8_t* input,
size_t input_sz,
uint8_t* output,
size_t output_sz
);
/*!
* @}
*/
/*!
* @}
*/
#ifdef __cplusplus
} // end extern "C"
#endif
/*!
* @}
* @}
*/
#endif // AES_H_
/* vim: set tw=78 sw=4 ts=4 et:
* Copyright (c) 2017, VRT Systems
* 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.
*/
#ifndef AES_H_
#define AES_H_
#include <stdint.h>
#include <stdbool.h>
#include <errno.h>
#ifdef __cplusplus
extern "C" {
#endif
/*!
* @addtogroup hal_cc2538
* @{
*
* @defgroup hal_cc2538_aes AES/SHA-256 Cryptograhy Module support
*
* The AES module is a hardware module built into the TI CC2538
* microcontroller which implements hardware AES-128 encryption/decryption and
* SHA-256 hash generation.
*
* Prior to performing any operations, the module must be enabled using the
* @ref cc2538AesEnable function. In low power applications, it may be desirable
* to switch this function back off again when not in use, the
* @ref cc2538AesDisable function can accomplish this.
*
* Actual hashes are generated by calling @ref cc2538AesHashStart. The hardware
* module will begin computing a hash with the given data and the CC2538's
* CPU is free to go about its business whilst this value is computed.
*
* @ref cc2538AesHashStatus can be periodically polled to find out if hashing is
* complete or if there was an error. After hashing, @ref cc2538AesHashFinish
* should be called to reset the state of the AES module.
*
* @{
*/
/*!
* @defgroup hal_aes_hwreg AES hardware registers
* @{
*/
#include "cc2538-reg.h"
/*! AES Module base address */
#define AES_BASE (0x4008b000)
/*! AES DMA Ch0 Control */
#define AES_DMAC_CH0_CTRL (AES_BASE | 0x000)
/*! AES DMA Ch0 Address */
#define AES_DMAC_CH0_EXTADDR (AES_BASE | 0x004)
/*! AES DMA Ch0 Length */
#define AES_DMAC_CH0_DMALENGTH (AES_BASE | 0x00c)
/*! AES DMA Status */
#define AES_DMAC_STATUS (AES_BASE | 0x018)
/*! AES DMA Software Reset */
#define AES_DMAC_SWRES (AES_BASE | 0x01c)
/*! AES DMA Ch1 Control */
#define AES_DMAC_CH1_CTRL (AES_BASE | 0x020)
/*! AES DMA Ch1 Address */
#define AES_DMAC_CH1_EXTADDR (AES_BASE | 0x024)
/*! AES DMA Ch1 Length */
#define AES_DMAC_CH1_DMALENGTH (AES_BASE | 0x02c)
/*! AES DMA Master Run-Time Parameters */
#define AES_DMAC_MST_RUNPARAMS (AES_BASE | 0x078)
/*! AES DMA Port Error Raw Status */
#define AES_DMAC_PERSR (AES_BASE | 0x07c)
/*! AES DMA Options */
#define AES_DMAC_OPTIONS (AES_BASE | 0x0f8)
/*! AES DMA Version */
#define AES_DMAC_VERSION (AES_BASE | 0x0fc)
/*! AES Key Store Write area */
#define AES_KEY_STORE_WRITE_AREA (AES_BASE | 0x400)
/*! AES Key Store Writtten area */
#define AES_KEY_STORE_WRITTEN_AREA (AES_BASE | 0x404)
/*! AES Key Store Size */
#define AES_KEY_STORE_SIZE (AES_BASE | 0x408)
/*! AES Key Store Read area */
#define AES_KEY_STORE_READ_AREA (AES_BASE | 0x40c)
/*! AES Control */
#define AES_AES_CTRL (AES_BASE | 0x550)
/*! AES Crypto length MSW */
#define AES_AES_C_LENGTH_0 (AES_BASE | 0x554)
/*! AES Crypto length LSW */
#define AES_AES_C_LENGTH_1 (AES_BASE | 0x558)
/*! AES Hash I/O Buffer Control */
#define AES_HASH_IO_BUF_CTRL (AES_BASE | 0x640)
/*! AES Hash Mode */
#define AES_HASH_MODE_IN (AES_BASE | 0x644)
/*! AES Hash Length: Lower 32-bits */
#define AES_HASH_LENGTH_IN_L (AES_BASE | 0x648)
/*! AES Hash Length: Upper 32-bits */
#define AES_HASH_LENGTH_IN_H (AES_BASE | 0x64c)
/*! AES Hash Output: Part A */
#define AES_HASH_DIGEST_A (AES_BASE | 0x650)
/*! AES Hash Output: Part B */
#define AES_HASH_DIGEST_B (AES_BASE | 0x654)
/*! AES Hash Output: Part C */
#define AES_HASH_DIGEST_C (AES_BASE | 0x658)
/*! AES Hash Output: Part D */
#define AES_HASH_DIGEST_D (AES_BASE | 0x65c)
/*! AES Hash Output: Part E */
#define AES_HASH_DIGEST_E (AES_BASE | 0x660)
/*! AES Hash Output: Part F */
#define AES_HASH_DIGEST_F (AES_BASE | 0x664)
/*! AES Hash Output: Part G */
#define AES_HASH_DIGEST_G (AES_BASE | 0x668)
/*! AES Hash Output: Part H */
#define AES_HASH_DIGEST_H (AES_BASE | 0x66c)
/*! AES Control Algorithm Select */
#define AES_CTRL_ALG_SEL (AES_BASE | 0x700)
/*! AES Master PROT privileged access enable */
#define AES_CTRL_PROT_EN (AES_BASE | 0x704)
/*! AES Control Software Reset */
#define AES_CTRL_SW_RESET (AES_BASE | 0x740)
/*! AES Control Interrupt Configuration */
#define AES_CTRL_INT_CFG (AES_BASE | 0x780)
/*! AES Control Interrupt Enable */
#define AES_CTRL_INT_EN (AES_BASE | 0x784)
/*! AES Control Interrupt Clear */
#define AES_CTRL_INT_CLR (AES_BASE | 0x788)
/*! AES Control Interrupt Set */
#define AES_CTRL_INT_SET (AES_BASE | 0x78c)
/*! AES Control Interrupt Status */
#define AES_CTRL_INT_STAT (AES_BASE | 0x790)
/*! AES Control Options */
#define AES_CTRL_OPTIONS (AES_BASE | 0x7f8)
/*! @} */
/**
* Enable the AES crypto engine
*/
void cc2538AesEnable();
/**
* Disable the AES crypto engine
*/
void cc2538AesDisable();
/*!
* @defgroup hal_aes_sha256 SHA-256
* @{
*/
/**
* Determine the result of the hash operation.
*
* @retval 0 Operation competed successfully
* @retval -EINPROGRESS Device is still busy performing an operation
* @retval -EIO Memory transfer failed
*/
int32_t cc2538AesHashStatus();
/**
* Clear the state of the hashing registers. This acknowledges the related
* interrupt flags and resets the state ready for use.
*/
void cc2538AesHashFinish();
/**
* Begin hashing a given block of data, returning the hash value to the given
* block of memory. The SHA-256 hash of the data block will be computed in
* hardware and returned to the given block of memory.
*
* Blocks must reside in RAM and can be a maximum of 64kB in size. To hash
* more than 64kB, allocate a buffer of <= 64kB, then:
* - read in the first buffer and call this function initially with
* `dataLen=buffer size`, `hashIn=NULL` and `pad=False`.
* - read in the next buffer and call again with `dataLen=buffer size`,
* `hashIn=previous result` and `pad=False`.
* - read in the final buffer and call with `dataLen=remainder`,
* `hashIn=previous result` and `pad=True`.
* After calling the last function, the result buffer should contain the
* correct hash value.
*
* The `totalLen` must be set to the length of the entire block of data. When
* hashing a single block less than 64kB in size, `totalLen = dataLen`.
*
* The following assumptions are made:
* - the block will not be re-located or modified during the operation
* - the block start address is correctly aligned (32-bit word alignment)
* - Both input and output hash buffers are 32-bit word aligned.
*
* @param[in] dataIn Data input to be hashed
* @param[in] dataLen Length of data to be hashed
* @param[in] totalLen Total length of data to be hashed (if hashing a
* large block in smaller chunks)
* @param[in] hashIn Initial hash value input, NULL if creating a new hash.
* @param[out] hashOut Hash value output.
* @param[in] hashLen Hash value length.
* @param[in] pad Whether or not to pad the data
*
* @retval 0 Operation begun
* @retval -EBUSY Device is busy with another operation
*/
int32_t cc2538AesHashStart(const void *dataIn, uint16_t dataLen,
uint32_t totalLen, void *hashIn, void *hashOut, uint32_t hashLen,
_Bool pad);
/*!
* @}
*/
/*!
* @defgroup hal_aes_ks Key store
* @{
*
* The CC2538 AES module has a 8-slot key store for storing AES keys. Each
* slot is 128-bits in size, so two slots must be used when storing a 192 or
* 256-bit key (and the key must not straddle a 256-bit boundary).
*
* The keys (from the CC2538's perspective) are write-only.
*/
/*!
* @defgroup hal_aes_ks_len Key lengths
* @{
*
* These constants define the length of a key. In cases where a key is
* greater than 128-bits in length; two adjacent key slots are consumed and
* only "even"-numbered slots (i.e. 0, 2, 4 or 6) may be used.
*/
#define AES_KS_LEN_128 (1) /*!< Key length is 128-bits */
#define AES_KS_LEN_192 (2) /*!< Key length is 192-bits */
#define AES_KS_LEN_256 (3) /*!< Key length is 256-bits */
/*!
* @}
*/
/*!
* Number of key store slots.
*/
#define AES_KS_NUM_KEYS (8)
/*!
* Return which slots are occupied by a key. Returns a bitmap of keys.
*/
uint8_t cc2538AesKeyStoreStatus();
/*!
* Get the currently defined key length.
*/
uint8_t cc2538AesKeyStoreGetLength();
/*!
* Set the key length for all keys in the key store.
* *Warning*: This will erase all existing keys in the key store!
*
* @param[in] len Length of keys to use in the key store
* (see @ref hal_aes_ks_len)
* @retval -EINVAL Invalid key length.
*/
int32_t cc2538AesKeyStoreSetLength(uint8_t len);
/*!
* Write a key to the key store at the given slot. Note: if a key length of
* 192 or 256 bits was selected, only slots 0, 2, 4 or 6 may be used.
*
* @param[in] slot Key store slot position (0…AES_KS_NUM_KEYS-1)
* @param[in] key Key data
*
* @retval 0 Success
* @retval -EINVAL Invalid arguments (e.g. misaligned input)
*/
int32_t cc2538AesKeyStoreWrite(uint8_t slot, const uint8_t* key);
/*!
* @}
*/
/*!
* @defgroup hal_aes_ecb AES-ECB functions
* @{
*/
/*!
* Encrypt or decrypt one or more blocks using AES-ECB.
*
* @param[in] slot The key store slot containing the desired key
* @param[in] direction Direction: 0 = decrypt, 1 = encrypt
* @param[in] input Clear-text (direction=0) or Cipher-text
* (direction=1) buffer.
* @param[in] input_sz Length of input buffer
* @param[out] output Clear-text (direction=1) or Cipher-text
* (direction=0) buffer.
* @param[in] output_sz Length of output buffer
* @param[out] ciphertext Encrypted data
* @param[in] ciphertext_sz Length of the encrypted data buffer
*/
int32_t cc2538AesEcb(
uint8_t slot,
uint8_t direction,
const uint8_t* input,
size_t input_sz,
uint8_t* output,
size_t output_sz
);
/*!
* @}
*/
/*!
* @}
*/
#ifdef __cplusplus
} // end extern "C"
#endif
/*!
* @}
* @}
*/
#endif // AES_H_
/* vim: set tw=78 sw=4 ts=4 et:
* Copyright (c) 2019, Widesky.cloud
* 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.
*/
#ifndef AES_ALT_H_
#define AES_ALT_H_
#ifndef BOOTLOADER
#include "mbedtls-config.h"
#endif
#ifdef MBEDTLS_AES_ALT
#include <stdint.h>
#include <stdbool.h>
#include <errno.h>
#ifdef __cplusplus
extern "C" {
#endif
/*!
* @addtogroup hal_cc2538_aes
* @{
*
* @defgroup hal_cc2538_mbedtls_aes mbedtls Hardware AES implementation
*
* This module defines glue logic for integrating hardware AES in `mbedtls`.
*
* @{
*/
/**
* \brief The AES context-type definition.
*/
typedef struct
{
/*! Key storage */
uint32_t key[8];
/*! Temporary result buffer */
uint32_t buf[4];
/*! Key slot */
uint8_t key_slot;
/*! Key length */
uint8_t key_len;
}
mbedtls_aes_context;
/*!
* @}
* @}
*/
#ifdef __cplusplus
}
#endif
#endif
#endif /* aes.h */
/*
* Copyright (c) 2016, The OpenThread Authors.
* 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.
*/
/**
* @file
* This file includes CC2538 register definitions.
*
*/
#ifndef CC2538_REG_H_
#define CC2538_REG_H_
#include <stdint.h>
// clang-format off
#define HWREG(x) (*((volatile uint32_t *)(x)))
/*!
* Return the address of a hardware register array element index.
*
* @param reg Register address
* @param idx Register array index
*/
#define HWREG_ARR_ADDR(reg, idx) ((reg) + ((idx) << 2))
/*!
* For registers that are arrays of 32-bit integers.
*
* @param reg Register address
* @param idx Register array index
*/
#define HWREG_ARR(reg, idx) HWREG(HWREG_ARR_ADDR(reg, idx))
#define NVIC_ST_CTRL 0xE000E010 // SysTick Control and Status
#define NVIC_ST_RELOAD 0xE000E014 // SysTick Reload Value Register
#define NVIC_EN0 0xE000E100 // Interrupt 0-31 Set Enable
#define NVIC_ST_CTRL_COUNT 0x00010000 // Count Flag
#define NVIC_ST_CTRL_CLK_SRC 0x00000004 // Clock Source
#define NVIC_ST_CTRL_INTEN 0x00000002 // Interrupt Enable
#define NVIC_ST_CTRL_ENABLE 0x00000001 // Enable
#define RFCORE_XREG_SRCMATCH_EN 0x00000001 // SRCMATCH.SRC_MATCH_EN(1)
#define RFCORE_XREG_SRCMATCH_AUTOPEND 0x00000002 // SRCMATCH.AUTOPEND(1)
#define RFCORE_XREG_SRCMATCH_PEND_DATAREQ_ONLY 0x00000004 // SRCMATCH.PEND_DATAREQ_ONLY(1)
#define RFCORE_XREG_SRCMATCH_ENABLE_STATUS_SIZE 3 // Num of register for source match enable status
#define RFCORE_XREG_SRCMATCH_SHORT_ENTRIES 24 // 24 short address entries in maximum
#define RFCORE_XREG_SRCMATCH_EXT_ENTRIES 12 // 12 extended address entries in maximum
#define RFCORE_XREG_SRCMATCH_SHORT_ENTRY_OFFSET 4 // address offset for one short address entry
#define RFCORE_XREG_SRCMATCH_EXT_ENTRY_OFFSET 8 // address offset for one extended address entry
#define INT_UART0 21 // UART0 Rx and Tx
#define IEEE_EUI64 0x00280028 // Address of IEEE EUI-64 address
#define RFCORE_FFSM_SRCADDRESS_TABLE 0x40088400 // Source Address Table
#define RFCORE_FFSM_SRCEXTPENDEN0 0x40088590 // Enable/Disable automatic pending per extended address
#define RFCORE_FFSM_SRCSHORTPENDEN0 0x4008859C // Enable/Disable automatic pending per short address
#define RFCORE_FFSM_EXT_ADDR0 0x400885A8 // Local address information
#define RFCORE_FFSM_PAN_ID0 0x400885C8 // Local address information
#define RFCORE_FFSM_PAN_ID1 0x400885CC // Local address information
#define RFCORE_FFSM_SHORT_ADDR0 0x400885D0 // Local address information
#define RFCORE_FFSM_SHORT_ADDR1 0x400885D4 // Local address information
#define RFCORE_XREG_FRMFILT0 0x40088600 // The frame filtering function
#define RFCORE_XREG_SRCMATCH 0x40088608 // Source address matching and pending bits
#define RFCORE_XREG_SRCSHORTEN0 0x4008860C // Short address matching
#define RFCORE_XREG_SRCEXTEN0 0x40088618 // Extended address matching
#define RFCORE_XREG_FRMCTRL0 0x40088624 // Frame handling
#define RFCORE_XREG_FRMCTRL1 0x40088628 // Frame handling
#define RFCORE_XREG_RXENABLE 0x4008862C // RX enabling
#define RFCORE_XREG_FREQCTRL 0x4008863C // Controls the RF frequency
#define RFCORE_XREG_TXPOWER 0x40088640 // Controls the output power
#define RFCORE_XREG_FSMSTAT0 0x40088648 // Radio finite state machine status
#define RFCORE_XREG_FSMSTAT1 0x4008864C // Radio status register
#define RFCORE_XREG_FIFOPCTRL 0x40088650 // FIFOP threshold
#define RFCORE_XREG_CCACTRL0 0x40088658 // CCA threshold
#define RFCORE_XREG_RSSISTAT 0x40088664 // RSSI valid status register
#define RFCORE_XREG_AGCCTRL1 0x400886C8 // AGC reference level
#define RFCORE_XREG_RFC_OBS_CTRL 0x400887AC // RF Core observable output
#define RFCORE_XREG_TXFILTCFG 0x400887E8 // TX filter configuration
#define RFCORE_XREG_RFRND 0x4008869C // Random data
#define RFCORE_SFR_RFDATA 0x40088828 // The TX FIFO and RX FIFO
#define RFCORE_SFR_RFERRF 0x4008882C // RF error interrupt flags
#define RFCORE_SFR_RFIRQF0 0x40088834 // RF interrupt flags
#define RFCORE_SFR_RFST 0x40088838 // RF CSMA-CA/strobe processor
#define CCTEST_OBSSEL 0x44010014 // CCTEST observable output route
#define RFCORE_XREG_FRMFILT0_FRAME_FILTER_EN 0x00000001 // Enables frame filtering
#define RFCORE_XREG_FRMCTRL0_AUTOACK 0x00000020
#define RFCORE_XREG_FRMCTRL0_AUTOCRC 0x00000040
#define RFCORE_XREG_FRMCTRL0_INFINITY_RX 0x00000008
#define RFCORE_XREG_FRMCTRL1_PENDING_OR 0x00000004
#define RFCORE_XREG_RFRND_IRND 0x00000001
#define RFCORE_XREG_FSMSTAT0_STATE_MASK 0x0000003F
#define RFCORE_XREG_FSMSTAT0_CAL_DONE 0x00000080
#define RFCORE_XREG_FSMSTAT0_CAL_RUN 0x00000040
#define RFCORE_XREG_FSMSTAT0_STATE_IDLE 0x00000000
#define RFCORE_XREG_FSMSTAT0_STATE_RX_CAL 0x00000002
#define RFCORE_XREG_FSMSTAT0_STATE_SFD_WAIT0 0x00000003
#define RFCORE_XREG_FSMSTAT0_STATE_SFD_WAIT1 0x00000004
#define RFCORE_XREG_FSMSTAT0_STATE_SFD_WAIT2 0x00000005
#define RFCORE_XREG_FSMSTAT0_STATE_SFD_WAIT3 0x00000006
#define RFCORE_XREG_FSMSTAT0_STATE_RX0 0x00000007
#define RFCORE_XREG_FSMSTAT0_STATE_RX1 0x00000008
#define RFCORE_XREG_FSMSTAT0_STATE_RX2 0x00000009
#define RFCORE_XREG_FSMSTAT0_STATE_RX3 0x0000000A
#define RFCORE_XREG_FSMSTAT0_STATE_RX4 0x0000000B
#define RFCORE_XREG_FSMSTAT0_STATE_RX5 0x0000000C
#define RFCORE_XREG_FSMSTAT0_STATE_RX6 0x0000000D
#define RFCORE_XREG_FSMSTAT0_STATE_RX_WAIT 0x0000000E
#define RFCORE_XREG_FSMSTAT0_STATE_RX_FRST 0x00000010
#define RFCORE_XREG_FSMSTAT0_STATE_RX_OVER 0x00000011
#define RFCORE_XREG_FSMSTAT0_STATE_TX_CAL 0x00000020
#define RFCORE_XREG_FSMSTAT0_STATE_TX0 0x00000022
#define RFCORE_XREG_FSMSTAT0_STATE_TX1 0x00000023
#define RFCORE_XREG_FSMSTAT0_STATE_TX2 0x00000024
#define RFCORE_XREG_FSMSTAT0_STATE_TX3 0x00000025
#define RFCORE_XREG_FSMSTAT0_STATE_TX4 0x00000026
#define RFCORE_XREG_FSMSTAT0_STATE_TX_FINAL 0x00000027
#define RFCORE_XREG_FSMSTAT0_STATE_RXTX_TRANS 0x00000028
#define RFCORE_XREG_FSMSTAT0_STATE_ACK_CAL 0x00000030
#define RFCORE_XREG_FSMSTAT0_STATE_ACK0 0x00000031
#define RFCORE_XREG_FSMSTAT0_STATE_ACK1 0x00000032
#define RFCORE_XREG_FSMSTAT0_STATE_ACK2 0x00000033
#define RFCORE_XREG_FSMSTAT0_STATE_ACK3 0x00000034
#define RFCORE_XREG_FSMSTAT0_STATE_ACK4 0x00000035
#define RFCORE_XREG_FSMSTAT0_STATE_ACK5 0x00000036
#define RFCORE_XREG_FSMSTAT0_STATE_ACK_DELAY 0x00000037
#define RFCORE_XREG_FSMSTAT0_STATE_TX_UNDER 0x00000038
#define RFCORE_XREG_FSMSTAT0_STATE_TX_DOWN0 0x0000001A
#define RFCORE_XREG_FSMSTAT0_STATE_TX_DOWN1 0x0000003A
#define RFCORE_XREG_FSMSTAT1_RX_ACTIVE 0x00000001
#define RFCORE_XREG_FSMSTAT1_TX_ACTIVE 0x00000002
#define RFCORE_XREG_FSMSTAT1_LOCK_STATUS 0x00000004
#define RFCORE_XREG_FSMSTAT1_SAMPLED_CCA 0x00000008
#define RFCORE_XREG_FSMSTAT1_CCA 0x00000010 // Clear channel assessment
#define RFCORE_XREG_FSMSTAT1_SFD 0x00000020
#define RFCORE_XREG_FSMSTAT1_FIFOP 0x00000040
#define RFCORE_XREG_FSMSTAT1_FIFO 0x00000080
#define RFCORE_XREG_RSSISTAT_RSSI_VALID 0x00000001 // RSSI value is valid.
#define RFCORE_XREG_RFC_OBS_POL_INV 0x00000040 // Invert polarity of OBS signal
#define RFCORE_XREG_RFC_OBS_MUX_ZERO 0x00000000 // Observable = constant zero
#define RFCORE_XREG_RFC_OBS_MUX_ONE 0x00000001 // Observable = constant one
#define RFCORE_XREG_RFC_OBS_MUX_SNIFF_DATA 0x00000008 // RFC sniff data
#define RFCORE_XREG_RFC_OBS_MUX_SNIFF_CLK 0x00000009 // RFC sniff clock
#define RFCORE_XREG_RFC_OBS_MUX_RSSI_VALID 0x0000000c // RSSI valid
#define RFCORE_XREG_RFC_OBS_MUX_DEMOD_CCA 0x0000000d // Clear channel assessment
#define RFCORE_XREG_RFC_OBS_MUX_SAMPLED_CCA 0x0000000e // Sampled CCA signal
#define RFCORE_XREG_RFC_OBS_MUX_SFD_SYNC 0x0000000f // SFD received or transmitted
#define RFCORE_XREG_RFC_OBS_MUX_TX_ACTIVE 0x00000010 // Transmitter is active
#define RFCORE_XREG_RFC_OBS_MUX_RX_ACTIVE 0x00000011 // Receiver is active
#define RFCORE_XREG_RFC_OBS_MUX_FFCTRL_FIFO 0x00000012 // One or more bytes in FIFO
#define RFCORE_XREG_RFC_OBS_MUX_FFCTRL_FIFOP 0x00000013 // One or more frames in FIFO
#define RFCORE_XREG_RFC_OBS_MUX_PACKET_DONE 0x00000014 // Packet received
#define RFCORE_XREG_RFC_OBS_MUX_RFC_XOR_RAND_IQ 0x00000016 // RAND I ^ RAND Q
#define RFCORE_XREG_RFC_OBS_MUX_RFC_RAND_Q 0x00000017 // Random data from Q channel
#define RFCORE_XREG_RFC_OBS_MUX_RFC_RAND_I 0x00000018 // Random data from I channel
#define RFCORE_XREG_RFC_OBS_MUX_LOCK_STATUS 0x00000019 // PLL is in lock
#define RFCORE_XREG_RFC_OBS_MUX_PA_PD 0x00000028 // Power amp power down
#define RFCORE_XREG_RFC_OBS_MUX_LNA_PD 0x0000002a // LNA power down
#define RFCORE_SFR_RFERRF_NLOCK 0x00000001 // Failed to achieve PLL lock.
#define RFCORE_SFR_RFERRF_RXABO 0x00000002 // RX Aborted.
#define RFCORE_SFR_RFERRF_RXOVERF 0x00000004 // RX FIFO overflowed.
#define RFCORE_SFR_RFERRF_RXUNDERF 0x00000008 // RX FIFO underflowed.
#define RFCORE_SFR_RFERRF_TXOVERF 0x00000010 // TX FIFO overflowed.
#define RFCORE_SFR_RFERRF_TXUNDERF 0x00000020 // TX FIFO underflowed.
#define RFCORE_SFR_RFERRF_STROBEERR 0x00000040 // Command Strobe Error.
#define RFCORE_SFR_RFST_INSTR_RXON 0xE3 // Instruction set RX on
#define RFCORE_SFR_RFST_INSTR_TXON 0xE9 // Instruction set TX on
#define RFCORE_SFR_RFST_INSTR_RFOFF 0xEF // Instruction set RF off
#define RFCORE_SFR_RFST_INSTR_FLUSHRX 0xED // Instruction set flush rx buffer
#define RFCORE_SFR_RFST_INSTR_FLUSHTX 0xEE // Instruction set flush tx buffer
#define CCTEST_OBSSEL_EN 0x00000080 // Enable the OBS output on this pin
#define CCTEST_OBSSEL_SEL_OBS0 0x00000000 // Route OBS0 to pin
#define CCTEST_OBSSEL_SEL_OBS1 0x00000001 // Route OBS1 to pin
#define CCTEST_OBSSEL_SEL_OBS2 0x00000002 // Route OBS2 to pin
#define ANA_REGS_BASE 0x400D6000 // ANA_REGS
#define ANA_REGS_O_IVCTRL 0x00000004 // Analog control register
#define SYS_CTRL_BASE 0x400d2000
#define SYS_CTRL_CLOCK_CTRL (SYS_CTRL_BASE + 0x000)
#define SYS_CTRL_CLOCK_STA (SYS_CTRL_BASE + 0x004)
#define SYS_CTRL_RCGCGPT (SYS_CTRL_BASE + 0x008)
#define SYS_CTRL_SCGCGPT (SYS_CTRL_BASE + 0x00c)
#define SYS_CTRL_DCGCGPT (SYS_CTRL_BASE + 0x010)
#define SYS_CTRL_SRGPT (SYS_CTRL_BASE + 0x014)
#define SYS_CTRL_RCGCSSI (SYS_CTRL_BASE + 0x018)
#define SYS_CTRL_SCGCSSI (SYS_CTRL_BASE + 0x01c)
#define SYS_CTRL_DCGCSSI (SYS_CTRL_BASE + 0x020)
#define SYS_CTRL_SRSSI (SYS_CTRL_BASE + 0x024)
#define SYS_CTRL_RCGCUART (SYS_CTRL_BASE + 0x028)
#define SYS_CTRL_SCGCUART (SYS_CTRL_BASE + 0x02c)
#define SYS_CTRL_DCGCUART (SYS_CTRL_BASE + 0x030)
#define SYS_CTRL_SRUART (SYS_CTRL_BASE + 0x034)
#define SYS_CTRL_RCGCI2C (SYS_CTRL_BASE + 0x038)
#define SYS_CTRL_SCGCI2C (SYS_CTRL_BASE + 0x03c)
#define SYS_CTRL_DCGCI2C (SYS_CTRL_BASE + 0x040)
#define SYS_CTRL_SRI2C (SYS_CTRL_BASE + 0x044)
#define SYS_CTRL_RCGCSEC (SYS_CTRL_BASE + 0x048)
#define SYS_CTRL_SCGCSEC (SYS_CTRL_BASE + 0x04c)
#define SYS_CTRL_DCGCSEC (SYS_CTRL_BASE + 0x050)
#define SYS_CTRL_SRSEC (SYS_CTRL_BASE + 0x054)
#define SYS_CTRL_PMCTL (SYS_CTRL_BASE + 0x058)
#define SYS_CTRL_SRCRC (SYS_CTRL_BASE + 0x05c)
#define SYS_CTRL_PWRDBG (SYS_CTRL_BASE + 0x074)
#define SYS_CTRL_CLD (SYS_CTRL_BASE + 0x080)
#define SYS_CTRL_IWE (SYS_CTRL_BASE + 0x094)
#define SYS_CTRL_I_MAP (SYS_CTRL_BASE + 0x098)
#define SYS_CTRL_RCGCRFC (SYS_CTRL_BASE + 0x0a8)
#define SYS_CTRL_SCGCRFC (SYS_CTRL_BASE + 0x0ac)
#define SYS_CTRL_DCGCRFC (SYS_CTRL_BASE + 0x0b0)
#define SYS_CTRL_EMUOVR (SYS_CTRL_BASE + 0x0b4)
#define SYS_CTRL_RCGCRFC_RFC0 0x00000001
#define SYS_CTRL_SCGCRFC_RFC0 0x00000001
#define SYS_CTRL_DCGCRFC_RFC0 0x00000001
#define SYS_CTRL_RCGCUART_UART0 0x00000001
#define SYS_CTRL_SCGCUART_UART0 0x00000001
#define SYS_CTRL_DCGCUART_UART0 0x00000001
#define SYS_CTRL_RCGCUART_UART1 0x00000002
#define SYS_CTRL_SCGCUART_UART1 0x00000002
#define SYS_CTRL_DCGCUART_UART1 0x00000002
#define IOC_PA0_SEL 0x400D4000 // Peripheral select control
#define IOC_PA1_SEL 0x400D4004 // Peripheral select control
#define IOC_PA2_SEL 0x400D4008
#define IOC_PA3_SEL 0x400D400C
#define IOC_UARTRXD_UART0 0x400D4100
#define IOC_UARTRXD_UART1 0x400D4108
#define IOC_PA0_OVER 0x400D4080
#define IOC_PA1_OVER 0x400D4084
#define IOC_PA2_OVER 0x400D4088
#define IOC_PA3_OVER 0x400D408C
#define IOC_MUX_OUT_SEL_UART0_TXD 0x00000000
#define IOC_MUX_OUT_SEL_UART1_TXD 0x00000002
#define IOC_OVERRIDE_OE 0x00000008 // PAD Config Override Output Enable
#define IOC_OVERRIDE_PUE 0x00000004 // PAD Config Override Pull-Up Enable
#define IOC_OVERRIDE_DIS 0x00000000 // PAD Config Override Disabled
#define UART0_BASE 0x4000C000
#define UART1_BASE 0x4000D000
#define GPIO_A_BASE 0x400D9000 // GPIO A
#define GPIO_B_BASE 0x400DA000 // GPIO B
#define GPIO_C_BASE 0x400DB000 // GPIO C
#define GPIO_D_BASE 0x400DC000 // GPIO D
#define GPIO_O_DIR 0x00000400
#define GPIO_O_AFSEL 0x00000420
#define GPIO_PIN(x) (1UL << x) // Arbitrary GPIO pin
#define GPIO_PIN_0 0x00000001 // GPIO pin 0
#define GPIO_PIN_1 0x00000002 // GPIO pin 1
#define GPIO_PIN_2 0x00000004 // GPIO pin 2
#define GPIO_PIN_3 0x00000008 // GPIO pin 3
#define GPIO_PIN_4 0x00000010 // GPIO pin 4
#define GPIO_PIN_5 0x00000020 // GPIO pin 5
#define GPIO_PIN_6 0x00000040 // GPIO pin 6
#define GPIO_PIN_7 0x00000080 // GPIO pin 7
#define UART_O_DR 0x00000000 // UART data
#define UART_O_FR 0x00000018 // UART flag
#define UART_O_IBRD 0x00000024
#define UART_O_FBRD 0x00000028
#define UART_O_LCRH 0x0000002C
#define UART_O_CTL 0x00000030 // UART control
#define UART_O_IM 0x00000038 // UART interrupt mask
#define UART_O_MIS 0x00000040 // UART masked interrupt status
#define UART_O_ICR 0x00000044 // UART interrupt clear
#define UART_O_CC 0x00000FC8 // UART clock configuration
#define UART_FR_RXFE 0x00000010 // UART receive FIFO empty
#define UART_FR_TXFF 0x00000020 // UART transmit FIFO full
#define UART_FR_RXFF 0x00000040 // UART receive FIFO full
#define UART_CONFIG_WLEN_8 0x00000060 // 8 bit data
#define UART_CONFIG_STOP_ONE 0x00000000 // One stop bit
#define UART_CONFIG_PAR_NONE 0x00000000 // No parity
#define UART_CTL_UARTEN 0x00000001 // UART enable
#define UART_CTL_TXE 0x00000100 // UART transmit enable
#define UART_CTL_RXE 0x00000200 // UART receive enable
#define UART_IM_RXIM 0x00000010 // UART receive interrupt mask
#define UART_IM_RTIM 0x00000040 // UART receive time-out interrupt
#define SOC_ADC_ADCCON1 0x400D7000 // ADC Control
#define SOC_ADC_RNDL 0x400D7014 // RNG low data
#define SOC_ADC_RNDH 0x400D7018 // RNG high data
#define SOC_ADC_ADCCON1_RCTRL0 0x00000004 // ADCCON1 RCTRL bit 0
#define SOC_ADC_ADCCON1_RCTRL1 0x00000008 // ADCCON1 RCTRL bit 1
#define FLASH_CTRL_FCTL 0x400D3008 // Flash control
#define FLASH_CTRL_DIECFG0 0x400D3014 // Flash information
// clang-format on
#endif
/* vim: set tw=78 ts=8 noet si: */
/*
* TI CC2538 ROM Functions
* (C) 2018 VRT Systems
*/
/*!
* @addtogroup hal_cc2538
* @{
*
* @defgroup hal_cc2538_rom Built-in ROM function routines
* @{
*/
#ifndef _ROM_H
#define _ROM_H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/*!
* ROM Function table in the CC2538. This table, and the functions it
* points to, live in the mask ROM present in the CC2538.
*/
struct cc2538_rom_t {
/*!
* Compute a CRC32 checksum of the given data and return it.
*
* @param[in] src Data to checksum
* @param[in] length Number of bytes to checksum
* @returns CRC32 checksum of the data
*/
uint32_t (*volatile crc32)(
const uint8_t* src,
uint32_t length);
/*!
* Return the size of the CC2538's internal flash.
*/
uint32_t (*volatile get_flash_size)(void);
/*!
* Return the CC2538 chip ID
*/
uint32_t (*volatile get_chip_id)(void);
/*!
* Perform a page erase of the internal flash.
*
* @param[in] addr Address of the page to erase
* @param[in] size Number of bytes to erase
* (must be a multiple of the sector size)
* @retval 0 Success
* @retval -1 Failure
* @retval -2 Invalid parameters
*/
int32_t (*volatile page_erase)(uint32_t addr, uint32_t size);
/*!
* Program a page of internal flash.
*
* @param[in] src Source data to program
* @param[in] addr Address in flash to store the data
* @param[in] size Number of bytes to program
*
* @retval 0 Success
* @retval -1 Failure
* @retval -2 Invalid parameters
*/
int32_t (*volatile program)(
const uint32_t* src,
uint32_t addr,
uint32_t size);
/*!
* Reset the CC2538
*/
void (*volatile reset)(void);
/*!
* Set a region of memory to a given value.
*
* @param[out] dest Destination buffer to write
* @param[in] data Data to fill the buffer with
* @param[in] size Number of bytes to write
*/
void* (*volatile memset)(
void* dest,
int32_t data,
uint32_t size);
/*!
* Copy a region of memory to another location.
*
* @param[out] dest Destination buffer to write
* @param[in] src Source buffer to read
* @param[in] size Number of bytes to copy
*/
void* (*volatile memcpy)(
void* dest,
const void* src,
uint32_t size);
/*!
* Compare two regions of memory for equivalence.
*
* @param[in] src1 First region to compare
* @param[in] src2 Second region to compare
* @param[in] size Number of bytes to compare
*/
void* (*volatile memcmp)(
void* dest,
const void* src,
uint32_t size);
/*!
* Move a region of memory to another location.
*
* @param[out] dest Destination buffer to write
* @param[in] src Source buffer to read
* @param[in] size Number of bytes to copy
*/
void* (*volatile memmove)(
void* dest,
const void* src,
uint32_t size);
};
/* Linker script defines this symbol */
#define CC2538_ROM_FUNC (*((struct cc2538_rom_t*)0x00000048))
#ifdef __cplusplus
}
#endif
#endif
/*!
* @}
* @}
*/
/* vim: set tw=78 sw=4 ts=4 et:
* Copyright (c) 2019, Widesky.cloud
* 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.
*/
#ifndef BOOTLOADER
#include <hal/sha256_alt.h>
#endif
#ifdef MBEDTLS_SHA256_ALT
#include <assert.h>
#ifdef MBED_SHA256_TRACE
#include <stdio.h>
#include <string.h>
#endif
#include <mbedtls/sha256.h>
#include "rom.h"
#include "aes.h"
void mbedtls_sha256_init(mbedtls_sha256_context *ctx) {
#ifdef MBED_SHA256_TRACE
iprintf("%s:%d: init %p\r\n", __FILE__, __LINE__, (void*)ctx);
#endif
CC2538_ROM_FUNC.memset(ctx, 0, sizeof( mbedtls_sha256_context ));
}
void mbedtls_sha256_free(mbedtls_sha256_context* ctx) {
#ifdef MBED_SHA256_TRACE
iprintf("%s:%d: free %p\r\n", __FILE__, __LINE__, (void*)ctx);
#endif
if (ctx == NULL)
return;
mbedtls_sha256_init(ctx);
}
void mbedtls_sha256_clone(mbedtls_sha256_context *dst,
const mbedtls_sha256_context *src) {
#ifdef MBED_SHA256_TRACE
iprintf("%s:%d: clone %p → %p\r\n", __FILE__, __LINE__,
(void*)src, (void*)dst);
#endif
CC2538_ROM_FUNC.memcpy(dst, src, sizeof(mbedtls_sha256_context));
}
/*!
* \brief This function starts a SHA-224 or SHA-256 checksum
* calculation.
*
* \param ctx The context to initialize.
* \param is224 Determines which function to use:
* 0: Use SHA-256, or 1: Use SHA-224.
*
* \return \c 0 on success.
*/
int mbedtls_sha256_starts_ret(mbedtls_sha256_context *ctx, int is224) {
mbedtls_sha256_init(ctx);
#ifdef MBED_SHA256_TRACE
iprintf("%s:%d: initialise context %p (224=%d)\r\n",
__FILE__, __LINE__,
(void*)ctx, is224);
#endif
if (is224) {
/* Initialise the hash state for SHA-224 */
ctx->state[0] = 0xd89e05c1;
ctx->state[1] = 0x07d57c36;
ctx->state[2] = 0x17dd7030;
ctx->state[3] = 0x39590ef7;
ctx->state[4] = 0x310bc0ff;
ctx->state[5] = 0x11155868;
ctx->state[6] = 0xa78ff964;
ctx->state[7] = 0xa44ffabe;
}
ctx->is224 = (uint8_t)is224;
/* Start up the AES cryptoprocessor */
cc2538AesEnable();
return 0;
}
static int32_t mbedtls_sha256_hw_hash_block(mbedtls_sha256_context* ctx,
const uint8_t* buffer, uint8_t buffer_sz) {
uint32_t hash[8];
/* Increment the total */
size_t total = ctx->total + buffer_sz;
#ifdef MBED_SHA256_TRACE
{
iprintf("%s:%d: hash %u bytes {",
__FILE__, __LINE__,
buffer_sz);
uint8_t dumprem = buffer_sz;
const uint8_t* ptr = buffer;
while (dumprem) {
iprintf(" %02x", *ptr);
ptr++;
dumprem--;
}
iprintf(" }, so far: %lu\r\n", ctx->total);
}
#endif
int32_t res = cc2538AesHashStart(
/* Input data chunk and size */
buffer,
buffer_sz,
/* Total length (only used during padding) */
0,
/*
* Incoming hash, set to NULL if first block
* on SHA-256.
*/
(ctx->is224 || ctx->total)
? ctx->state /* SHA-224 or not first block */
: NULL, /* SHA-256 first block */
hash,
sizeof(hash),
false
);
#ifdef MBED_SHA256_TRACE
iprintf("%s:%d: hash result: %s\r\n",
__FILE__, __LINE__,
strerror(-res));
#endif
if (!res) {
/* Wait for hashing to finish */
res = cc2538AesHashStatus();
while (res == -EINPROGRESS) {
res = cc2538AesHashStatus();
}
}
cc2538AesHashFinish();
if (!res) {
/* Buffer hashed, clear it and copy the state back. */
ctx->total = total;
CC2538_ROM_FUNC.memcpy(ctx->state, hash, sizeof(hash));
#ifdef MBED_SHA256_TRACE
{
uint8_t idx;
iprintf("%s:%d: hash state: {", __FILE__, __LINE__);
for (idx = 0; idx < 8; idx++) {
iprintf(" 0x%08lx", ctx->state[idx]);
}
iprintf(" }\r\n");
}
#endif
}
return res;
}
/*!
* Process an arbitrary 64-byte block
*/
int mbedtls_internal_sha256_process( mbedtls_sha256_context *ctx,
const unsigned char data[64] ) {
uint32_t hash[8];
#ifdef MBED_SHA256_TRACE
{
iprintf("%s:%d: internal hash 64 bytes {",
__FILE__, __LINE__);
uint8_t dumprem = 64;
const uint8_t* ptr = data;
while (dumprem) {
iprintf(" %02x", *ptr);
ptr++;
dumprem--;
}
iprintf(" }\r\n");
}
#endif
int32_t res = cc2538AesHashStart(
/* Input data chunk and size */
data, 64,
/* Total length (only used during padding) */
0,
/* Incoming hash. */
ctx->state,
hash,
sizeof(hash),
false
);
#ifdef MBED_SHA256_TRACE
iprintf("%s:%d: internal hash 64 bytes from %p: %s\r\n",
__FILE__, __LINE__,
(void*)data, strerror(-res));
#endif
if (!res) {
/* Wait for hashing to finish */
res = cc2538AesHashStatus();
while (res == -EINPROGRESS) {
res = cc2538AesHashStatus();
}
}
cc2538AesHashFinish();
if (!res) {
/* Success, copy result out */
CC2538_ROM_FUNC.memcpy(ctx->state, hash, sizeof(hash));
#ifdef MBED_SHA256_TRACE
{
uint8_t idx;
iprintf("%s:%d: hash state: {", __FILE__, __LINE__);
for (idx = 0; idx < 8; idx++) {
iprintf(" 0x%08lx", ctx->state[idx]);
}
iprintf(" }\r\n");
}
#endif
return 0;
} else {
return MBEDTLS_ERR_SHA256_HW_ACCEL_FAILED;
}
}
/*!
* \brief This function feeds an input buffer into an ongoing
* SHA-256 checksum calculation.
*
* \param ctx The SHA-256 context.
* \param input The buffer holding the data.
* \param ilen The length of the input data.
*
* \return \c 0 on success.
*/
int mbedtls_sha256_update_ret( mbedtls_sha256_context *ctx,
const unsigned char *input,
size_t ilen ) {
while (ilen) {
/* The DMAC does not like blocks bigger than 64kiB */
size_t blen = ilen;
if (blen > 65536)
blen = 65536;
int32_t res = mbedtls_sha256_hw_hash_block(ctx, input, blen);
if (res < 0)
return MBEDTLS_ERR_SHA256_HW_ACCEL_FAILED;
/* Move on */
ilen -= blen;
input += blen;
}
return 0;
}
/*!
* \brief This function finishes the SHA-256 operation, and writes
* the result to the output buffer.
*
* \param ctx The SHA-256 context.
* \param output The SHA-224 or SHA-256 checksum result.
*
* \return \c 0 on success.
*/
int mbedtls_sha256_finish_ret( mbedtls_sha256_context *ctx,
unsigned char output[32] ) {
/*
* FIPS 180-4 states that we must first append a '1' bit,
* followed by k zeros, followed by the message length (l) in bits as
* a 64-bit big-endian integer.
*
* k is the smallest non-negative value of k that satisfies the equation
* l + 1 + k ≡ 448 mod 512.
*
* The idea that we add enough bits to fill the final block up with 448
* bits… that leaves 64-bits over for the length of the message.
*
* Our messages are *always* a multiple of 8-bits in length, so k will be
* some multiple of 8; plus 7. We can re-express that equation in bytes:
*
* L + 1 + K ≡ 56 mod 64
*
* We append the byte 0x80 (0b10000000), followed by K bytes; where K is
* the smallest non-negative value of K that satisfies that above
* equation.
*/
/*
* Start off by computing the length of the message in bits. We'll count
* in bytes, but we need the total bits for the final 8 bytes of the
* padding.
*/
uint64_t msglen = ctx->total * 8;
/*
* Compute the length of the padding including message length.
* We ignore the "whole blocks" and just focus on the partial final block.
*
* If the message is a multiple of 64 bytes; padding will be a whole block,
* otherwise it's whatever's left.
*
* Allocate that number of bytes on the stack and zero it out.
*/
uint8_t padding_len = 64 - (ctx->total % 64);
#ifdef MBED_SHA256_TRACE
iprintf("%s:%d: message length %lu bytes, padding %u bytes\r\n",
__FILE__, __LINE__, ctx->total, padding_len);
#endif
uint8_t padding[padding_len];
CC2538_ROM_FUNC.memset(padding, 0, padding_len);
/* Start with a "one", followed by 7 zeros */
padding[0] = 0x80;
/*
* Copy in the length, in big-endian format. We stop
* when there are no more bits to set (we zeroed everything
* earlier).
*/
uint8_t* ptr = &padding[padding_len - sizeof(msglen)];
while (msglen) {
/* Take 8 MSBs */
*ptr = (msglen >> 56) & 0xff;
#ifdef MBED_SHA256_TRACE
iprintf("%s:%d: append message length byte 0x%02x\r\n",
__FILE__, __LINE__, *ptr);
#endif
/* Shift them off the end and move on */
msglen <<= 8;
ptr++;
}
/* Finish off the last block */
#ifdef MBED_SHA256_TRACE
iprintf("%s:%d: hash the final block\r\n",
__FILE__, __LINE__);
#endif
int32_t res = mbedtls_sha256_hw_hash_block(ctx, padding, padding_len);
/* The total length after padding must be a multiple of 64 bytes */
assert(!(ctx->total % 64));
cc2538AesDisable();
#ifdef MBED_SHA256_TRACE
iprintf("%s:%d: final result: %s\r\n",
__FILE__, __LINE__, strerror(-res));
#endif
if (res < 0)
return MBEDTLS_ERR_SHA256_HW_ACCEL_FAILED;
/* Copy out the result */
#ifdef MBED_SHA256_TRACE
{
uint8_t idx;
iprintf("%s:%d: hash state: {", __FILE__, __LINE__);
for (idx = 0; idx < 8; idx++) {
iprintf(" 0x%08lx", ctx->state[idx]);
}
iprintf(" }\r\n");
}
#endif
CC2538_ROM_FUNC.memcpy(output, ctx->state, sizeof(ctx->state));
return 0;
}
#else
extern char _null;
#endif
/* vim: set tw=78 sw=4 ts=4 et:
* Copyright (c) 2019, Widesky.cloud
* 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.
*/
#ifndef SHA256_ALT_H_
#define SHA256_ALT_H_
#ifndef BOOTLOADER
#include "mbedtls-config.h"
#endif
#ifdef MBEDTLS_SHA256_ALT
#include <stdint.h>
#include <stdbool.h>
#include <errno.h>
#ifdef __cplusplus
extern "C" {
#endif
/*!
* @addtogroup hal_cc2538_aes
* @{
*
* @defgroup hal_cc2538_mbedtls_sha256 mbedtls Hardware SHA-256 implementation
*
* This module defines glue logic for integrating hardware SHA-256 in `mbedtls`.
*
* @{
*/
/**
* @brief The SHA-256 context structure.
*
* The structure is used both for SHA-256 and for SHA-224
* checksum calculations. The choice between these two is
* made in the call to mbedtls_sha256_starts_ret().
*
* This is a direct copy-paste from mbedtls.
*/
typedef struct
{
/*! The number of Bytes processed. */
uint32_t total;
/*! The intermediate digest state. */
uint32_t state[8];
/*! The data block being processed. */
unsigned char buffer[64];
/*! Number of bytes in the buffer */
uint8_t buffer_sz;
/*!
* Determines which function to use:
* 0: Use SHA-256, or 1: Use SHA-224.
*/
uint8_t is224;
}
mbedtls_sha256_context;
#ifdef __cplusplus
} // end extern "C"
#endif
/*!
* @}
* @}
*/
#endif
#endif
/* vim: set tw=78 ts=8 noet si: */
/*
* CC2538 System Control driver
* (C) 2017 VRT Systems
*/
/*!
* @addtogroup hal_cc2538
* @{
*
* @defgroup hal_cc2538_sysctrl System Control
* @{
*/
#ifndef _SYSCTRL_H
#define _SYSCTRL_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include "cc2538-reg.h"
/*! Resonant frequency of the external crystal in Hz */
#define F_CRYSTAL (32000000ul)
/*! Resonant frequency of the internal RC oscillator in Hz */
#define F_RCOSC (16000000ul)
#ifndef F_REF
/*! Frequency of the reference oscillator; should be F_CRYSTAL or F_RCOSC */
#define F_REF F_CRYSTAL
#endif
#ifndef F_CPU
/*! Desired CPU frequency in Hz (fraction of F_CRYSTAL) */
#define F_CPU (F_REF)
#endif
#ifndef F_IO
/*! Desired I/O frequency in Hz (fraction of F_CRYSTAL) */
#define F_IO (F_REF)
#endif
#define SYS_CTRL_CPU_DIV (((F_REF) / (F_CPU)) - 1)
#define SYS_CTRL_IO_DIV (((F_REF) / (F_IO)) - 1)
#define SYS_CTRL_CLOCK_CTRL_OSC32K_CALDIS (25)
#define SYS_CTRL_CLOCK_CTRL_OSC32K (24)
#define SYS_CTRL_CLOCK_CTRL_AMP_DET (21)
#define SYS_CTRL_CLOCK_CTRL_OSC_PD (17)
#define SYS_CTRL_CLOCK_CTRL_OSC (16)
#define SYS_CTRL_CLOCK_CTRL_IO_DIV (8)
#define SYS_CTRL_CLOCK_CTRL_IO_DIV_m (0x07ul)
#define SYS_CTRL_CLOCK_CTRL_SYS_DIV (0)
#define SYS_CTRL_CLOCK_CTRL_SYS_DIV_m (0x07ul)
#define SYS_CTRL_CLOCK_STA_SYNC_OSC32K (26)
#define SYS_CTRL_CLOCK_STA_OSC32K_CALDIS (25)
#define SYS_CTRL_CLOCK_STA_OSC32K (24)
#define SYS_CTRL_CLOCK_STA_RST (22)
#define SYS_CTRL_CLOCK_STA_RST_m (3ul << SYS_CTRL_CLOCK_STA_RST)
#define SYS_CTRL_CLOCK_STA_SOURCE_CHANGE (20)
#define SYS_CTRL_CLOCK_STA_XOSC_STB (19)
#define SYS_CTRL_CLOCK_STA_HSOSC_STB (18)
#define SYS_CTRL_CLOCK_STA_OSC_PD (17)
#define SYS_CTRL_CLOCK_STA_OSC (16)
#define SYS_CTRL_CLOCK_STA_IO_DIV (8)
#define SYS_CTRL_CLOCK_STA_IO_DIV_m (0x07ul)
#define SYS_CTRL_CLOCK_STA_SYS_DIV (0)
#define SYS_CTRL_CLOCK_STA_SYS_DIV_m (0x07ul)
/* Reset causes */
#define SYS_CTRL_CLOCK_STA_RST_POR \
(0ul << SYS_CTRL_CLOCK_STA_RST)
#define SYS_CTRL_CLOCK_STA_RST_EXT \
(1ul << SYS_CTRL_CLOCK_STA_RST)
#define SYS_CTRL_CLOCK_STA_RST_WDT \
(2ul << SYS_CTRL_CLOCK_STA_RST)
#define SYS_CTRL_CLOCK_STA_RST_SW \
(3ul << SYS_CTRL_CLOCK_STA_RST)
/*! Return the speed of the IO clock in Hz */
static inline uint32_t sysctrl_io_clock_rate() {
#ifndef SYS_VAR_FREQ
return F_IO;
#else
uint8_t rate = (HWREG(SYS_CTRL_CLOCK_STA) >> SYS_CTRL_CLOCK_STA_IO_DIV)
& SYS_CTRL_CLOCK_STA_IO_DIV_m;
return F_REF / (rate + 1);
#endif
}
/*! Return the speed of the SYS clock in Hz */
static inline uint32_t sysctrl_sys_clock_rate() {
#ifndef SYS_VAR_FREQ
return F_CPU;
#else
uint8_t rate = (HWREG(SYS_CTRL_CLOCK_STA) >> SYS_CTRL_CLOCK_STA_SYS_DIV)
& SYS_CTRL_CLOCK_STA_SYS_DIV_m;
return F_REF / (rate + 1);
#endif
}
#define SYS_CTRL_xCGCGPT_GPT3 (3)
#define SYS_CTRL_xCGCGPT_GPT2 (2)
#define SYS_CTRL_xCGCGPT_GPT1 (1)
#define SYS_CTRL_xCGCGPT_GPT0 (0)
#define SYS_CTRL_xCGCSSI_SSI1 (1)
#define SYS_CTRL_xCGCSSI_SSI0 (0)
#define SYS_CTRL_xCGCUART_UART1 (1)
#define SYS_CTRL_xCGCUART_UART0 (0)
#define SYS_CTRL_xCGCI2C_I2C0 (0)
#define SYS_CTRL_xCGCSEC_AES (1)
#define SYS_CTRL_xCGCSEC_PKA (0)
#define SYS_CTRL_PMCTL_PM (0)
#define SYS_CTRL_SRCRC_CRC_REN_USB (8)
#define SYS_CTRL_SRCRC_CRC_REN_RF (0)
#define SYS_CTRL_PWRDBG_FORCE_WARM_RESET (3)
#define SYS_CTRL_CLD_VALID (8)
#define SYS_CTRL_CLD_EN (0)
#define SYS_CTRL_IWE_SM_TIMER_IWE (5)
#define SYS_CTRL_IWE_USB_IWE (4)
#define SYS_CTRL_IWE_PORT_D_IWE (3)
#define SYS_CTRL_IWE_PORT_C_IWE (2)
#define SYS_CTRL_IWE_PORT_B_IWE (1)
#define SYS_CTRL_IWE_PORT_A_IWE (0)
#define SYS_CTRL_I_MAP_ALTMAP (0)
#define SYS_CTRL_xCGCRFC_RFC0 (0)
#define SYS_CTRL_EMUOVR_ICEPICK_FORCE_CLOCK_CG (7)
#define SYS_CTRL_EMUOVR_ICEPICK_FORCE_POWER_CG (6)
#define SYS_CTRL_EMUOVR_ICEPICK_INHIBIT_SLEEP_CG (5)
#define SYS_CTRL_EMUOVR_ICEMELTER_WKUP_CG (4)
#define SYS_CTRL_EMUOVR_ICEPICK_FORCE_CLOCK_PM (3)
#define SYS_CTRL_EMUOVR_ICEPICK_FORCE_POWER_PM (2)
#define SYS_CTRL_EMUOVR_ICEPICK_INHIBIT_SLEEP_PM (1)
#define SYS_CTRL_EMUOVR_ICEMELTER_WKUP_PM (0)
#ifdef __cplusplus
}
#endif
#endif
/*!
* @}
* @}
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment