blob: 400260ef5252121b1f5a95b479f2bd165227c3a4 [file] [log] [blame]
/*
* Copyright (c) 2019-2020, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
*/
#include "crypto_hw.h"
#include "cc_lib.h"
#include "cc_pal_buff_attr.h"
#include "cc_rnd_common.h"
#include "mbedtls/platform.h"
#include "mbedtls/ctr_drbg.h"
#include "mbedtls/entropy.h"
#include "mbedtls_cc_mng_int.h"
#include "arm_cmse.h"
#include "mbedtls_cc_util_key_derivation.h"
#include "tfm_attest_hal.h"
#include "prod_hw_defs.h"
#include "cc_otp_defs.h"
#include "region_defs.h"
#define CC312_NULL_CONTEXT "NO SALT!"
CCRndContext_t* CC312_pRndCtx = NULL;
CCRndWorkBuff_t* CC312_pRndWorkBuff = NULL;
mbedtls_ctr_drbg_context* CC312_pRndState = NULL;
mbedtls_entropy_context* CC312_pMbedtlsEntropy = NULL;
CCError_t CC_PalDataBufferAttrGet(const unsigned char *pDataBuffer,
size_t buffSize, uint8_t buffType,
uint8_t *pBuffNs)
{
CC_UNUSED_PARAM(buffType);
*pBuffNs = DATA_BUFFER_IS_SECURE;
#if defined(__ARM_ARCH_8M_MAIN__) || defined(__ARM_ARCH_8M_BASE__)
if (cmse_check_address_range((void*)pDataBuffer, buffSize, CMSE_NONSECURE)) {
*pBuffNs = DATA_BUFFER_IS_NONSECURE;
}
#else
if (pDataBuffer >= (uint8_t *)NS_DATA_START &&
(pDataBuffer + buffSize) <= (uint8_t *)NS_DATA_LIMIT) {
*pBuffNs = DATA_BUFFER_IS_NONSECURE;
}
#endif
return CC_OK;
}
/*
* \brief Initialize the CC312 crypto accelerator
*/
int crypto_hw_accelerator_init(void)
{
int ret = 0;
/* Allocate memory on heap */
CC312_pRndCtx = mbedtls_calloc(1, sizeof(CCRndContext_t));
CC312_pRndWorkBuff = mbedtls_calloc(1, sizeof(CCRndWorkBuff_t));
CC312_pRndState = mbedtls_calloc(1, sizeof(mbedtls_ctr_drbg_context));
CC312_pMbedtlsEntropy = mbedtls_calloc(1, sizeof(mbedtls_entropy_context));
/* Check if memory allocation was successful */
if ( !CC312_pRndCtx || !CC312_pRndWorkBuff
|| !CC312_pRndState || !CC312_pMbedtlsEntropy) {
mbedtls_free(CC312_pRndCtx);
mbedtls_free(CC312_pRndWorkBuff);
mbedtls_free(CC312_pRndState);
mbedtls_free(CC312_pMbedtlsEntropy);
return -1;
}
/* Init Rnd context's inner members */
CC312_pRndCtx->rndState = CC312_pRndState;
CC312_pRndCtx->entropyCtx = CC312_pMbedtlsEntropy;
/* Initialise CryptoCell library */
ret = CC_LibInit(CC312_pRndCtx, CC312_pRndWorkBuff);
if (ret != CC_LIB_RET_OK) {
mbedtls_free(CC312_pRndCtx);
mbedtls_free(CC312_pRndWorkBuff);
mbedtls_free(CC312_pRndState);
mbedtls_free(CC312_pMbedtlsEntropy);
return ret;
}
return 0;
}
/*
* \brief Deallocate the CC312 crypto accelerator
*/
int crypto_hw_accelerator_finish(void)
{
int ret = 0;
ret = CC_LibFini(CC312_pRndCtx);
if(ret != CC_LIB_RET_OK) {
return ret;
}
mbedtls_free(CC312_pRndCtx);
mbedtls_free(CC312_pRndWorkBuff);
mbedtls_free(CC312_pRndState);
mbedtls_free(CC312_pMbedtlsEntropy);
return 0;
}
int crypto_hw_accelerator_get_lcs(uint32_t *lcs)
{
return mbedtls_mng_lcsGet(lcs);
}
int crypto_hw_accelerator_huk_derive_key(const uint8_t *label,
size_t label_size,
const uint8_t *context,
size_t context_size,
uint8_t *key,
size_t key_size)
{
if (context == NULL || context_size == 0) {
/* The CC312 requires the context to not be null, so a default
* is given.
*/
context = (const uint8_t *)CC312_NULL_CONTEXT;
context_size = sizeof(CC312_NULL_CONTEXT);
}
return mbedtls_util_key_derivation_cmac(CC_UTIL_ROOT_KEY, NULL,
label, label_size,
context, context_size,
key, key_size);
}
/*
* Count number of zero bits in 32-bit word.
* Copied from:
* lib/ext/cryptocell-312-runtime/host/src/ \
* cc3x_productionlib/common/prod_util.c: CC_PROD_GetZeroCount(..)
*/
static int get_zero_bits_count(uint32_t *buf,
uint32_t buf_word_size,
uint32_t *zero_count)
{
uint32_t val;
uint32_t index = 0;
*zero_count = 0;
for (index = 0; index < buf_word_size; index++) {
val = buf[index];
val = val - ((val >> 1) & 0x55555555);
val = (val & 0x33333333) + ((val >> 2) & 0x33333333);
val = ((((val + (val >> 4)) & 0xF0F0F0F) * 0x1010101) >> 24);
*zero_count += (32 - val);
}
/* All 0's and all 1's is forbidden */
if ((*zero_count == 0)
|| (*zero_count == buf_word_size*CC_BITS_IN_32BIT_WORD)) {
*zero_count = 0;
return -1;
}
return 0;
}
/*
* Get attestation private key from CC312 OTP
*/
int crypto_hw_accelerator_get_attestation_private_key(uint8_t *buf,
uint32_t *size)
{
uint32_t *key = (uint32_t *)buf;
uint32_t otp_val;
uint32_t otp_zero_count;
uint32_t zero_count;
int i;
int rc;
if (key == NULL ||
*size < CC_OTP_ATTESTATION_KEY_SIZE_IN_WORDS * sizeof(uint32_t)) {
return -1;
}
*size = CC_OTP_ATTESTATION_KEY_SIZE_IN_WORDS * sizeof(uint32_t);
/* Get provisioned key from OTP, 8 words */
for (i = 0; i < CC_OTP_ATTESTATION_KEY_SIZE_IN_WORDS; i++) {
CC_PROD_OTP_READ(otp_val, CC_OTP_ATTESTATION_KEY_OFFSET + i);
*key = otp_val;
key++;
}
/* Verify the zero number of private key */
rc = get_zero_bits_count((uint32_t *)buf,
CC_OTP_ATTESTATION_KEY_SIZE_IN_WORDS,
&zero_count);
if (rc) {
return -1;
}
CC_PROD_OTP_READ(otp_zero_count, CC_OTP_ATTESTATION_KEY_ZERO_COUNT_OFFSET);
if (otp_zero_count != zero_count) {
return -1;
}
return 0;
}
#ifdef BL2
int crypto_hw_accelerator_get_rotpk_hash(uint8_t image_id,
uint8_t *rotpk_hash,
uint32_t *rotpk_hash_size)
{
int32_t ret;
mbedtls_mng_pubKeyType_t key_index;
uint32_t rotpk_hash_size_in_words;
if (image_id == 0) {
#if (MCUBOOT_IMAGE_NUMBER == 1)
key_index = CC_MNG_HASH_BOOT_KEY_256B;
rotpk_hash_size_in_words = 8;
#elif (MCUBOOT_IMAGE_NUMBER == 2)
key_index = CC_MNG_HASH_BOOT_KEY_0_128B;
rotpk_hash_size_in_words = 4;
} else if (image_id == 1) {
key_index = CC_MNG_HASH_BOOT_KEY_1_128B;
rotpk_hash_size_in_words = 4;
#endif /* MCUBOOT_IMAGE_NUMBER == 1 */
} else {
return -1;
}
if (*rotpk_hash_size < rotpk_hash_size_in_words * sizeof(uint32_t)) {
return -1;
}
*rotpk_hash_size = rotpk_hash_size_in_words * sizeof(uint32_t);
ret = mbedtls_mng_pubKeyHashGet(key_index, (uint32_t *)rotpk_hash,
rotpk_hash_size_in_words);
if (ret) {
return ret;
}
return 0;
}
#endif /* BL2 */