blob: d9994ca4d523e231ed2c8057d5f330f9442a67ae [file] [log] [blame]
/*
* Copyright (c) 2017, 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.
*/
#include "mbedtls/aes.h"
#include "aes_alt.h"
#ifdef MBEDTLS_AES_ALT
#include <string.h>
#include <driverlib/crypto.h>
#include <driverlib/prcm.h>
#include <utils/code_utils.h>
#define CC2650_AES_KEY_UNUSED (-1)
#define CC2650_AES_CTX_MAGIC (0x7E)
/**
* bitmap of which key stores are currently used
*/
static uint8_t sUsedKeys = 0;
/**
* number of active contexts, used for power on/off of the crypto core
*/
static unsigned int sRefNum = 0;
void mbedtls_aes_init(mbedtls_aes_context *ctx)
{
if (sRefNum++ == 0)
{
/* enable the crypto core */
/* The TRNG should already be running before we ever ask the AES core
* to do anything, if there is any scenario that the TRNG powers off
* the peripheral power domain use this code to repower it
PRCMPowerDomainOn(PRCM_DOMAIN_PERIPH);
while (PRCMPowerDomainStatus(PRCM_DOMAIN_PERIPH) != PRCM_DOMAIN_POWER_ON);
*/
PRCMPeripheralRunEnable(PRCM_PERIPH_CRYPTO);
PRCMPeripheralSleepEnable(PRCM_PERIPH_CRYPTO);
PRCMPeripheralDeepSleepEnable(PRCM_PERIPH_CRYPTO);
PRCMLoadSet();
while (!PRCMLoadGet());
}
ctx->magic = CC2650_AES_CTX_MAGIC;
ctx->key_idx = CC2650_AES_KEY_UNUSED;
}
void mbedtls_aes_free(mbedtls_aes_context *ctx)
{
otEXPECT(ctx->magic == CC2650_AES_CTX_MAGIC);
if (ctx->key_idx != CC2650_AES_KEY_UNUSED)
{
sUsedKeys &= ~(1 << ctx->key_idx);
}
if (--sRefNum == 0)
{
/* disable the crypto core */
/* The TRNG core needs the peripheral power domain powered on to
* function. if there is a situation where the power domain must be
* powered off, use this code to do so.
PRCMPowerDomainOff(PRCM_DOMAIN_PERIPH);
while (PRCMPowerDomainStatus(PRCM_DOMAIN_PERIPH) != PRCM_DOMAIN_POWER_OFF);
*/
PRCMPeripheralRunDisable(PRCM_PERIPH_CRYPTO);
PRCMPeripheralSleepDisable(PRCM_PERIPH_CRYPTO);
PRCMPeripheralDeepSleepDisable(PRCM_PERIPH_CRYPTO);
PRCMLoadSet();
while (!PRCMLoadGet());
}
memset((void *)ctx, 0x00, sizeof(ctx));
exit:
return;
}
int mbedtls_aes_setkey_enc(mbedtls_aes_context *ctx, const unsigned char *key, unsigned int keybits)
{
unsigned char key_idx;
int retval = 0;
otEXPECT_ACTION(ctx->magic == CC2650_AES_CTX_MAGIC, retval = -1);
if (ctx->key_idx != CC2650_AES_KEY_UNUSED)
{
sUsedKeys &= ~(1 << ctx->key_idx);
}
/* our hardware only supports 128 bit keys */
otEXPECT_ACTION(keybits == 128u, retval = MBEDTLS_ERR_AES_INVALID_KEY_LENGTH);
for (key_idx = 0; ((sUsedKeys >> key_idx) & 0x01) != 0 && key_idx < 8; key_idx++);
/* we have no more room for this key */
otEXPECT_ACTION(key_idx < 8, retval = -2);
otEXPECT_ACTION(CRYPTOAesLoadKey((uint32_t *)key, key_idx) == AES_SUCCESS,
retval = MBEDTLS_ERR_AES_INVALID_KEY_LENGTH);
sUsedKeys |= (1 << key_idx);
ctx->key_idx = key_idx;
exit:
return retval;
}
int mbedtls_aes_setkey_dec(mbedtls_aes_context *ctx, const unsigned char *key, unsigned int keybits)
{
unsigned char key_idx;
int retval = 0;
otEXPECT_ACTION(ctx->magic == CC2650_AES_CTX_MAGIC, retval = -1);
if (ctx->key_idx != CC2650_AES_KEY_UNUSED)
{
sUsedKeys &= ~(1 << ctx->key_idx);
}
/* our hardware only supports 128 bit keys */
otEXPECT_ACTION(keybits == 128u, retval = MBEDTLS_ERR_AES_INVALID_KEY_LENGTH);
for (key_idx = 0; ((sUsedKeys >> key_idx) & 0x01) != 0 && key_idx < 8; key_idx++);
/* we have no more room for this key */
otEXPECT_ACTION(key_idx < 8, retval = -2);
otEXPECT_ACTION(CRYPTOAesLoadKey((uint32_t *)key, key_idx) == AES_SUCCESS,
retval = MBEDTLS_ERR_AES_INVALID_KEY_LENGTH);
sUsedKeys |= (1 << key_idx);
ctx->key_idx = key_idx;
exit:
return retval;
}
/**
* \brief AES-ECB block encryption/decryption
*
* \param ctx AES context
* \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT
* \param input 16-byte input block
* \param output 16-byte output block
*
* \return 0 if successful
*/
int mbedtls_aes_crypt_ecb(mbedtls_aes_context *ctx, int mode, const unsigned char input[16], unsigned char output[16])
{
int retval = -1;
retval = CRYPTOAesEcb((uint32_t *)input, (uint32_t *)output, ctx->key_idx, mode == MBEDTLS_AES_ENCRYPT, false);
otEXPECT(retval == AES_SUCCESS);
while ((retval = CRYPTOAesEcbStatus()) == AES_DMA_BSY);
CRYPTOAesEcbFinish();
exit:
return retval;
}
#endif /* MBEDTLS_AES_ALT */