AES/SHA mbedtls implementation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* 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; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* 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_ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* 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_ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* 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 */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* 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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* 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 | |
/*! | |
* @} | |
* @} | |
*/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* 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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* 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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* 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