[da15000] AES Hardware support (#2091)

This commit is contained in:
JakubBrachTieto
2017-08-16 09:57:39 -07:00
committed by Jonathan Hui
parent a8105f7fcc
commit ff270a1233
14 changed files with 4476 additions and 10 deletions
+15
View File
@@ -47,6 +47,7 @@ configure_OPTIONS = \
--with-ncp-bus=uart \
--with-examples=da15000 \
--enable-linker-map \
MBEDTLS_CPPFLAGS="$(DA15000_MBEDTLS_CPPFLAGS)" \
$(NULL)
include $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/common-switches.mk
@@ -54,6 +55,20 @@ include $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/common-switches.mk
TopSourceDir := $(dir $(shell readlink $(firstword $(MAKEFILE_LIST))))..
AbsTopSourceDir := $(dir $(realpath $(firstword $(MAKEFILE_LIST))))..
DA15000_MBEDTLS_CPPFLAGS = -DMBEDTLS_CONFIG_FILE='\"da15000-mbedtls-config.h\"'
DA15000_MBEDTLS_CPPFLAGS += -I$(PWD)/examples/platforms/da15000/crypto
DA15000_MBEDTLS_CPPFLAGS += -I$(PWD)/third_party/dialog/DialogSDK/bsp/include
DA15000_MBEDTLS_CPPFLAGS += -I$(PWD)/third_party/dialog/DialogSDK/bsp/peripherals/include
DA15000_MBEDTLS_CPPFLAGS += -I$(PWD)/third_party/dialog/DialogSDK/bsp/adapters/include
DA15000_MBEDTLS_CPPFLAGS += -I$(PWD)/third_party/dialog/DialogSDK/bsp/memory/include
DA15000_MBEDTLS_CPPFLAGS += -I$(PWD)/third_party/dialog/DialogSDK/interfaces/ftdf/include
DA15000_MBEDTLS_CPPFLAGS += -I$(PWD)/third_party/dialog/DialogSDK/bsp/config
DA15000_MBEDTLS_CPPFLAGS += -I$(PWD)/third_party/dialog/DialogSDK
DA15000_MBEDTLS_CPPFLAGS += -I$(PWD)/third_party/dialog/DialogSDK/interfaces/ftdf/src
DA15000_MBEDTLS_CPPFLAGS += -I$(PWD)/third_party/mbedtls/repo.patched/include
DA15000_MBEDTLS_CPPFLAGS += -I$(PWD)/third_party/mbedtls
DA15000_MBEDTLS_CPPFLAGS += -include$(PWD)/examples/platforms/da15000/custom_config_qspi.h
CONFIG_FILE = OPENTHREAD_PROJECT_CORE_CONFIG_FILE='\"openthread-core-da15000-config.h\"'
CONFIG_FILE_PATH = $(AbsTopSourceDir)/examples/platforms/da15000/
+7
View File
@@ -33,6 +33,8 @@ lib_LIBRARIES
libopenthread_da15000_a_CPPFLAGS = \
-I$(top_srcdir)/include \
-I$(top_srcdir)/examples/platforms \
-I$(top_srcdir)/examples/platforms/da15000 \
-I$(top_srcdir)/examples/platforms/da15000/crypto \
-I$(top_srcdir)/src/core \
-I$(top_srcdir)/third_party/dialog/DialogSDK/bsp/include \
-I$(top_srcdir)/third_party/dialog/DialogSDK/bsp/peripherals/include \
@@ -42,6 +44,7 @@ libopenthread_da15000_a_CPPFLAGS
-I$(top_srcdir)/third_party/dialog/DialogSDK/bsp/config \
-I$(top_srcdir)/third_party/dialog/DialogSDK \
-I$(top_srcdir)/third_party/dialog/DialogSDK/interfaces/ftdf/src \
-I$(top_srcdir)/third_party/mbedtls/repo.patched/include \
-include$(top_srcdir)/examples/platforms/da15000/custom_config_qspi.h \
-Wno-unknown-pragmas \
-Wno-sign-compare \
@@ -52,6 +55,7 @@ libopenthread_da15000_a_CPPFLAGS
-Wno-unused-variable \
-Wno-missing-field-initializers \
-fno-strict-aliasing \
$(MBEDTLS_CPPFLAGS) \
$(NULL)
PLATFORM_SOURCES = \
@@ -68,6 +72,7 @@ PLATFORM_SOURCES
startup-gcc.c \
clock.c \
misc.c \
crypto/aes_alt.c \
$(NULL)
DIALOG_SOURCES = \
@@ -82,6 +87,8 @@ DIALOG_SOURCES
@top_builddir@/third_party/dialog/DialogSDK/bsp/peripherals/src/hw_watchdog.c \
@top_builddir@/third_party/dialog/DialogSDK/bsp/peripherals/src/sys_tcs.c \
@top_builddir@/third_party/dialog/DialogSDK/bsp/peripherals/src/hw_uart.c \
@top_builddir@/third_party/dialog/DialogSDK/bsp/peripherals/src/hw_aes_hash.c \
@top_builddir@/third_party/dialog/DialogSDK/bsp/peripherals/src/hw_crypto.c \
@top_builddir@/third_party/dialog/DialogSDK/bsp/peripherals/src/hw_otpc.c \
@top_builddir@/third_party/dialog/DialogSDK/bsp/peripherals/src/hw_fem_sky66112-11.c \
@top_builddir@/third_party/dialog/DialogSDK/bsp/peripherals/src/hw_dma.c \
+22
View File
@@ -34,6 +34,8 @@
*/
#include <stdint.h>
#include "sdk_defs.h"
//#include <tool.h>
#define __NAKED __attribute__((naked))
#define __USED __attribute__((used))
@@ -111,4 +113,24 @@ void __USED __NAKED __NO_RETURN __gcc_program_start(void)
while (1);
}
uint32_t DA15000_phy_addr(uint32_t addr)
{
static const uint32_t remap[] =
{
MEMORY_ROM_BASE,
MEMORY_OTP_BASE,
MEMORY_QSPIF_BASE,
MEMORY_SYSRAM_BASE,
MEMORY_QSPIF_BASE,
MEMORY_OTP_BASE,
MEMORY_CACHERAM_BASE,
0
};
if (addr >= MEMORY_REMAPPED_END)
{
return addr;
}
return addr + remap[REG_GETF(CRG_TOP, SYS_CTRL_REG, REMAP_ADR0)];
}
+204
View File
@@ -0,0 +1,204 @@
/*
* 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 <stdint.h>
#include <common/code_utils.hpp>
#include "hw_aes_hash.h"
static void mbedtls_zeroize(void *v, size_t n)
{
volatile unsigned char *p = (unsigned char *)v;
while (n--) { *p++ = 0; }
}
void mbedtls_aes_init(mbedtls_aes_context *ctx)
{
memset(ctx, 0, sizeof(mbedtls_aes_context));
}
void mbedtls_aes_free(mbedtls_aes_context *ctx)
{
if (ctx == NULL)
{
return;
}
hw_aes_hash_disable_clock();
mbedtls_zeroize(ctx, sizeof(mbedtls_aes_context));
}
int mbedtls_aes_setkey_enc(mbedtls_aes_context *ctx, const unsigned char *key, unsigned int keybits)
{
int retval = 0;
switch (keybits)
{
case 128:
ctx->hwKeyLen = HW_AES_128;
memcpy(ctx->aes_enc_key, key, 16);
break;
case 192:
ctx->hwKeyLen = HW_AES_192;
memcpy(ctx->aes_enc_key, key, 24);
break;
case 256:
ctx->hwKeyLen = HW_AES_256;
memcpy(ctx->aes_enc_key, key, 32);
break;
default:
retval = MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
break;
}
return retval;
}
int mbedtls_aes_setkey_dec(mbedtls_aes_context *ctx, const unsigned char *key, unsigned int keybits)
{
int retval = 0;
switch (keybits)
{
case 128:
ctx->hwKeyLen = HW_AES_128;
memcpy(ctx->aes_dec_key, key, 16);
break;
case 192:
ctx->hwKeyLen = HW_AES_192;
memcpy(ctx->aes_enc_key, key, 24);
break;
case 256:
ctx->hwKeyLen = HW_AES_256;
memcpy(ctx->aes_enc_key, key, 32);
break;
default:
retval = MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
break;
}
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 = 0;
hw_aes_hash_enable_clock();
hw_aes_hash_mark_input_block_as_last();
hw_aes_hash_cfg_aes_ecb(ctx->hwKeyLen);
hw_aes_hash_store_keys(ctx->hwKeyLen, ctx->aes_enc_key, HW_AES_PERFORM_KEY_EXPANSION);
hw_aes_hash_cfg_dma((uint8_t *)input, (uint8_t *)output, 16);
switch (mode)
{
case MBEDTLS_AES_ENCRYPT:
hw_aes_hash_encrypt();
retval = 0;
break;
case MBEDTLS_AES_DECRYPT:
hw_aes_hash_decrypt();
retval = 0;
break;
default:
retval = -1;
break;
}
while (hw_aes_hash_is_active())
{
;
}
return retval;
}
int mbedtls_aes_self_test(int verbose)
{
(void)verbose;
/* 128-bit Key 2b7e151628aed2a6abf7158809cf4f3c */
const uint8_t key_128b[16] = { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88,
0x09, 0xcf, 0x4f, 0x3c
};
int retval = 0;
mbedtls_aes_context aes;
uint8_t input[16] = {0};
uint8_t output[16] = {0};
uint8_t decrypt[16] = {0};
strcpy((char *)input, (const char *)"hw_cryptaes_test");
mbedtls_aes_init(&aes);
retval = mbedtls_aes_setkey_enc(&aes, (const unsigned char *)key_128b, 128);
VerifyOrExit(retval != 0, retval = -1);
retval = mbedtls_aes_setkey_dec(&aes, (const unsigned char *)key_128b, 128);
VerifyOrExit(retval != 0, retval = -1);
retval = mbedtls_aes_crypt_ecb(&aes, MBEDTLS_AES_ENCRYPT, input, output);
VerifyOrExit(retval != 0, retval = -1);
retval = mbedtls_aes_crypt_ecb(&aes, MBEDTLS_AES_DECRYPT, output, decrypt);
VerifyOrExit(retval != 0, retval = -1);
mbedtls_aes_free(&aes);
exit:
return retval;
}
#endif /* MBEDTLS_AES_ALT */
+169
View File
@@ -0,0 +1,169 @@
/*
* 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.
*/
#ifndef MBEDTLS_AES_ALT_H
#define MBEDTLS_AES_ALT_H
#if !defined(MBEDTLS_CONFIG_FILE)
#include "da15000-mbedtls-config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#ifdef MBEDTLS_AES_ALT
#ifdef __cplusplus
extern "C" {
#endif
#include "common/code_utils.hpp"
typedef struct
{
uint8_t hwKeyLen;
unsigned char aes_enc_key[32]; /* Encryption key */
unsigned char aes_dec_key[32]; /* Decryption key */
} mbedtls_aes_context;
/**
* @brief Initialize AES context
*
* @param [in,out] ctx AES context to be initialized
*/
void mbedtls_aes_init(mbedtls_aes_context *ctx);
/**
* @brief Clear AES context
*
* \param ctx AES context to be cleared
*/
void mbedtls_aes_free(mbedtls_aes_context *ctx);
/**
* \brief AES key schedule (encryption)
*
* \param ctx AES context to be initialized
* \param key encryption key
* \param keybits must be 128, 192 or 256
*
* \return 0 if successful, or MBEDTLS_ERR_AES_INVALID_KEY_LENGTH
*/
int mbedtls_aes_setkey_enc(mbedtls_aes_context *ctx, const unsigned char *key,
unsigned int keybits);
/**
* \brief AES key schedule (decryption)
*
* \param ctx AES context to be initialized
* \param key decryption key
* \param keybits must be 128, 192 or 256
*
* \return 0 if successful, or MBEDTLS_ERR_AES_INVALID_KEY_LENGTH
*/
int mbedtls_aes_setkey_dec(mbedtls_aes_context *ctx, const unsigned char *key,
unsigned int keybits);
/**
* \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]);
/**
* \brief AES-CBC buffer encryption/decryption
* Length should be a multiple of the block
* size (16 bytes)
*
* \note Upon exit, the content of the IV is updated so that you can
* call the function same function again on the following
* block(s) of data and get the same result as if it was
* encrypted in one call. This allows a "streaming" usage.
* If on the other hand you need to retain the contents of the
* IV, you should either save it manually or use the cipher
* module instead.
*
* \param ctx AES context
* \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT
* \param length length of the input data
* \param iv initialization vector (updated after use)
* \param input buffer holding the input data
* \param output buffer holding the output data
*
* \return 0 if successful, or MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH
*/
int mbedtls_aes_crypt_cbc( mbedtls_aes_context *ctx,
int mode,
size_t length,
unsigned char iv[16],
const unsigned char *input,
unsigned char *output );
/**
* \brief AES-CTR buffer encryption/decryption
*
* Warning: You have to keep the maximum use of your counter in mind!
*
* Note: Due to the nature of CTR you should use the same key schedule for
* both encryption and decryption. So a context initialized with
* mbedtls_aes_setkey_enc() for both MBEDTLS_AES_ENCRYPT and MBEDTLS_AES_DECRYPT.
*
* \param ctx AES context
* \param length The length of the data
* \param nc_off The offset in the current stream_block (for resuming
* within current cipher stream). The offset pointer to
* should be 0 at the start of a stream.
* \param nonce_counter The 128-bit nonce and counter.
* \param stream_block The saved stream-block for resuming. Is overwritten
* by the function.
* \param input The input data stream
* \param output The output data stream
*
* \return 0 if successful
*/
int mbedtls_aes_crypt_ctr( mbedtls_aes_context *ctx,
size_t length,
size_t *nc_off,
unsigned char nonce_counter[16],
unsigned char stream_block[16],
const unsigned char *input,
unsigned char *output );
#ifdef __cplusplus
}
#endif
#endif /* MBEDTLS_AES_ALT */
#endif /* MBEDTLS_AES_ALT_H */
File diff suppressed because it is too large Load Diff
@@ -91,7 +91,7 @@
#define dg_configUSE_HW_TIMER0 (1)
#define dg_configUSE_HW_AES_HASH (1)
/*************************************************************************************************\
* OS specific config
*/
+1 -1
View File
@@ -81,7 +81,7 @@ extern void SystemCoreClockUpdate (void);
* \return physical address (for DMA, AES/HASH etc.) -- can be same or different as addr
*
*/
extern uint32_t black_orca_phy_addr(uint32_t addr);
extern uint32_t DA15000_phy_addr(uint32_t addr);
#ifdef __cplusplus
@@ -0,0 +1,768 @@
/**
* \addtogroup BSP
* \{
* \addtogroup DEVICES
* \{
* \addtogroup AES_HASH
* \{
* \brief AES/Hash Engine
*/
/**
****************************************************************************************
*
* @file hw_cpm.c
*
* @brief Clock and Power Manager Driver
*
* Copyright (c) 2016, Dialog Semiconductor
* 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 HW_AES_HASH_H_
#define HW_AES_HASH_H_
#if dg_configUSE_HW_AES_HASH
#include <stdbool.h>
#include <stdint.h>
#include <sdk_defs.h>
/**
* \brief AES/Hash callback
*
* This function is called by the AES/Hash driver when the interrupt is fired.
*
*/
typedef void (*hw_aes_hash_cb)(void);
/**
* \brief AES key sizes. Possible values: HW_AES_128, HW_AES_192, HW_AES_256.
*/
typedef enum {
HW_AES_128 = 0,
HW_AES_192 = 1,
HW_AES_256 = 2
} hw_aes_key_size;
/**
* \brief AES direction. Possible values: HW_AES_DECRYPT, HW_AES_ENCRYPT.
*/
typedef enum {
HW_AES_DECRYPT = 0,
HW_AES_ENCRYPT = 1
} hw_aes_direction;
/**
* \brief AES/Hash modes. Possible values: HW_AES_ECB, HW_AES_CBC, HW_AES_CTR, HW_HASH_MD5,
* HW_AES_SHA_1, HW_AES_SHA_256_224, HW_AES_SHA_256, HW_AES_SHA_384, HW_AES_SHA_512,
* HW_AES_SHA_512_224, HW_AES_SHA_512_256.
*/
typedef enum {
HW_AES_ECB,
HW_AES_CBC,
HW_AES_CTR,
HW_HASH_MD5,
HW_HASH_SHA_1,
HW_HASH_SHA_256_224,
HW_HASH_SHA_256,
HW_HASH_SHA_384,
HW_HASH_SHA_512,
HW_HASH_SHA_512_224,
HW_HASH_SHA_512_256
} hw_aes_hash_mode;
/**
* \brief Key expansion modes.
* Possible values HW_AES_PERFORM_KEY_EXPANSION, HW_AES_DO_NOT_PERFORM_KEY_EXPANSION
*/
typedef enum {
HW_AES_PERFORM_KEY_EXPANSION = 0, /**< Key expansion is performed by the engine */
HW_AES_DO_NOT_PERFORM_KEY_EXPANSION /**< Key expansion is performed by the software */
} hw_aes_hash_key_exp_t;
/**
\brief AES/Hash setup structure.
*/
typedef struct {
hw_aes_hash_mode mode; /**< AES/Hash mode. */
hw_aes_direction aesDirection; /**< AES direction. Only used when the mode is an AES mode.*/
hw_aes_key_size aesKeySize; /**< AES key size. Only used when the mode is an AES mode. */
bool aesKeyExpand; /**< When true the key expansion process is execute. When false the key
expansion process is not executed. The user should write the AES keys in CRYPTO_RAM.
Only used when the mode is an AES mode. */
uint32 aesKeys; /**< The start address of the buffer containing the AES key. */
uint32 aesIvCtrblk_0_31; /**< In CBC mode IV[31:0] and in CTR mode the initial value of the
32 bits counter. Only used when the mode is an AES CBC/CTR mode. */
uint32 aesIvCtrblk_32_63; /**< In CBC mode IV[63:32] and in CTR[63:32].
Only used when the mode is an AES CBC/CTR mode. */
uint32 aesIvCtrblk_64_95; /**< In CBC mode IV[95:64] and in CTR[95:64].
Only used when the mode is an AES CBC/CTR mode. */
uint32 aesIvCtrblk_96_127; /**< In CBC mode IV[127:96] and in CTR[127:96].
Only used when the mode is an AES CBC/CTR mode. */
bool aesWriteBackAll; /**< When true all the AES resulting data is written to memory.
When false only the final block of the AES resulting data is written to memory.
Only used when the mode is an AES mode. */
uint8 hashOutLength; /**< The number of bytes of the hash result to be saved to memory.
Only used when mode is a Hash mode. */
bool moreDataToCome; /**< When false this is the last data block. When true more data is to
come. */
uint32 sourceAddress; /**< The physical address of the input data that needs to be processed. */
uint32 destinationAddress; /**< The physical address (RAM only) where the resulting data needs
to be written. If NULL the register is not written.*/
uint32 dataSize; /**< The number of bytes that need to be processed. If this number is not
a multiple of a block size, the data is automatically extended with zeros. */
bool enableInterrupt; /**< When true the callback function is called after the operation
has ended. */
hw_aes_hash_cb callback; /**< The callback function that is called when enable interrupt
is true. */
} hw_aes_hash_setup;
/**
* \brief Enable AES/HASH engine clock
*
* This function enables the AES/HASH engine clock.
*/
__STATIC_INLINE void hw_aes_hash_enable_clock(void)
{
GLOBAL_INT_DISABLE();
REG_SET_BIT(CRG_TOP, CLK_AMBA_REG, AES_CLK_ENABLE);
GLOBAL_INT_RESTORE();
}
/**
* \brief Disable AES/HASH engine clock
*
* This function disables the AES/HASH engine clock.
*/
__STATIC_INLINE void hw_aes_hash_disable_clock(void)
{
GLOBAL_INT_DISABLE();
REG_CLR_BIT(CRG_TOP, CLK_AMBA_REG, AES_CLK_ENABLE);
GLOBAL_INT_RESTORE();
}
/**
* \brief Check if AES/HASH engine clock is enabled
*
* \return Non-zero value if enabled, 0 otherwise
*/
__STATIC_INLINE int hw_aes_hash_clock_is_enabled(void)
{
return (CRG_TOP->CLK_AMBA_REG) & (CRG_TOP_CLK_AMBA_REG_AES_CLK_ENABLE_Msk);
}
/**
* \brief AES/Hash enable.
*
* This function sets up and starts a AES/HASH engine operation. All the
* configuration details are included in the setup input structure.
*
* \param [in] setup The setup structure with setup values.
*
* \deprecated You can use hw_aes_hash_init with hw_aes_hash_start instead.
*
* \sa hw_aes_hash_init
* \sa hw_aes_hash_start
*
*/
void hw_aes_hash_enable(const hw_aes_hash_setup setup) DEPRECATED;
/**
* \brief AES/Hash initialize.
*
* This function sets up a AES/HASH engine operation. All the configuration details
* are included in the setup input structure. The operation can then start by calling
* hw_aes_hash_start
*
* \param [in] setup The setup structure with setup values.
*
* \note There are some restrictions in the value of dataSize of the setup structure depending on
* the mode. This function will do appropriate checking using assertions. The following
* table shows what the value of dataSize should be:
*
* mode | moreDataToCome = true | moreDataToCome = false
* ------------------- | --------------------- | ----------------------
* HW_AES_ECB | multiple of 16 | multiple of 16
* HW_AES_CBC | multiple of 16 | no restrictions
* HW_AES_CTR | multiple of 16 | no restrictions
* HW_HASH_MD5 | multiple of 8 | no restrictions
* HW_HASH_SHA_1 | multiple of 8 | no restrictions
* HW_HASH_SHA_256_224 | multiple of 8 | no restrictions
* HW_HASH_SHA_256 | multiple of 8 | no restrictions
* HW_HASH_SHA_384 | multiple of 8 | no restrictions
* HW_HASH_SHA_512 | multiple of 8 | no restrictions
* HW_HASH_SHA_512_224 | multiple of 8 | no restrictions
* HW_HASH_SHA_512_256 | multiple of 8 | no restrictions
*
* \sa hw_aes_hash_start
*
*/
void hw_aes_hash_init(hw_aes_hash_setup *setup);
/**
* \brief AES/Hash restart.
*
* This function restarts the AES/Hash engine. This function can be used when the engine waits for
* more input data.
*
* \param [in] sourceAddress The start address of the data that needs to be processed.
* \param [in] dataSize The number of bytes that need to be processed. If this number is not
* a multiple of a block size, the data is automatically extended with zeros.
* \param [in] moreDataToCome When false this is the last data block. When true more data is to
* come.
*
*/
void hw_aes_hash_restart(const uint32 sourceAddress, const uint32 dataSize,
const bool moreDataToCome);
/**
* \brief AES/Hash is active.
*
* This function tells if the AES/Hash engine is active or not.
*
* \return True if the AES/Hash engine is active and false when it is inactive.
*
*/
bool hw_aes_hash_is_active();
/**
* \brief AES/Hash is waiting for more data.
*
* This function tells if the AES/Hash engine is waiting for more data or not.
*
* \return True if the AES/Hash engine is waiting more data and false when it is not.
*
*/
bool hw_aes_hash_wait_for_in();
/**
* \brief AES/Hash disable.
*
* This function disables the AES/HASH engine and its interrupt request signal.
*
* \param [in] waitTillInactive When true the AES/HASH engine is disabled after any pending operation
* finishes. When false the AES/Hash is disabled immediately.
*
*/
void hw_aes_hash_disable(const bool waitTillInactive);
/**
* \brief Mark next input block as being last
*
* This function is used to configure the engine so as to consider the next input block
* as the last of the operation. When the operation finishes, the engine's status
* becomes "inactive".
*/
__STATIC_INLINE void hw_aes_hash_mark_input_block_as_last(void)
{
REG_CLR_BIT(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_MORE_IN);
}
/**
* \brief Mark next input block as not being last
*
* This function is used to configure the engine so as to expect more input blocks
* after the operation. When the operation finishes, the engine's status
* becomes "waiting for input".
*/
__STATIC_INLINE void hw_aes_hash_mark_input_block_as_not_last(void)
{
REG_SET_BIT(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_MORE_IN);
}
/**
* \brief Configure engine for AES ECB encryption/decryption
*
* This function configures the engine for AES ECB encryption/decryption
*
* \param[in] key_size The size of the key used in the encryption/decryption
*
* \warning AES ECB is not recommended for use in cryptographic protocols.
*/
__STATIC_INLINE void hw_aes_hash_cfg_aes_ecb(hw_aes_key_size key_size)
{
uint32 crypto_ctrl_reg = AES_HASH->CRYPTO_CTRL_REG;
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_HASH_SEL, crypto_ctrl_reg, 0);
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_ALG_MD, crypto_ctrl_reg, 0);
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_ALG, crypto_ctrl_reg, 0);
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_AES_KEY_SZ, crypto_ctrl_reg, key_size);
AES_HASH->CRYPTO_CTRL_REG = crypto_ctrl_reg;
}
/**
* \brief Configure engine for AES CTR encryption/decryption
*
* This function configures the engine for AES CTR encryption/decryption
*
* \param[in] key_size The size of the key used in the encryption/decryption
*/
__STATIC_INLINE void hw_aes_hash_cfg_aes_ctr(hw_aes_key_size key_size)
{
uint32 crypto_ctrl_reg = AES_HASH->CRYPTO_CTRL_REG;
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_HASH_SEL, crypto_ctrl_reg, 0);
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_ALG_MD, crypto_ctrl_reg, 2);
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_ALG, crypto_ctrl_reg, 0);
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_AES_KEY_SZ, crypto_ctrl_reg, key_size);
AES_HASH->CRYPTO_CTRL_REG = crypto_ctrl_reg;
}
/**
* \brief Configure engine for AES CBC encryption/decryption
*
* This function configures the engine for AES CBC encryption/decryption
*
* \param[in] key_size The size of the key used in the encryption/decryption
*/
__STATIC_INLINE void hw_aes_hash_cfg_aes_cbc(hw_aes_key_size key_size)
{
uint32 crypto_ctrl_reg = AES_HASH->CRYPTO_CTRL_REG;
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_HASH_SEL, crypto_ctrl_reg, 0);
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_ALG_MD, crypto_ctrl_reg, 3);
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_ALG, crypto_ctrl_reg, 0);
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_AES_KEY_SZ, crypto_ctrl_reg, key_size);
AES_HASH->CRYPTO_CTRL_REG = crypto_ctrl_reg;
}
/**
* \brief Configure engine for MD5 hash
*
* This function configures the engine to perform MD5 hashing
*
* \param[in] result_size The size in bytes of the result that the engine will write
* to the output memory. Accepted values are 1 to 16. Out of
* range values are adjusted to the closest limit.
*/
__STATIC_INLINE void hw_aes_hash_cfg_md5(unsigned int result_size)
{
uint32_t crypto_ctrl_reg = AES_HASH->CRYPTO_CTRL_REG;
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_HASH_OUT_LEN, crypto_ctrl_reg,
(result_size > 16)? 15: (result_size == 0)? 0 : (result_size - 1));
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_HASH_SEL, crypto_ctrl_reg, 1);
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_ALG_MD, crypto_ctrl_reg, 0);
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_ALG, crypto_ctrl_reg, 0);
AES_HASH->CRYPTO_CTRL_REG = crypto_ctrl_reg;
}
/**
* \brief Configure engine for SHA1 hash
*
* This function configures the engine to perform SHA1 hashing
*
* \param[in] result_size The size in bytes of the result that the engine will write
* to the output memory. Accepted values are 1 to 20. Out of
* range values are adjusted to the closest limit.
*/
__STATIC_INLINE void hw_aes_hash_cfg_sha1(unsigned int result_size)
{
uint32_t crypto_ctrl_reg = AES_HASH->CRYPTO_CTRL_REG;
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_HASH_OUT_LEN, crypto_ctrl_reg,
(result_size > 20)? 19: (result_size == 0)? 0 : (result_size - 1));
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_HASH_SEL, crypto_ctrl_reg, 1);
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_ALG_MD, crypto_ctrl_reg, 0);
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_ALG, crypto_ctrl_reg, 1);
AES_HASH->CRYPTO_CTRL_REG = crypto_ctrl_reg;
}
/**
* \brief Configure engine for SHA-224 hash
*
* This function configures the engine to perform SHA-224 hashing
*
* \param[in] result_size The size in bytes of the result that the engine will write
* to the output memory. Accepted values are 1 to 28. Out of
* range values are adjusted to the closest limit.
*/
__STATIC_INLINE void hw_aes_hash_cfg_sha_224(unsigned int result_size)
{
uint32_t crypto_ctrl_reg = AES_HASH->CRYPTO_CTRL_REG;
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_HASH_OUT_LEN, crypto_ctrl_reg,
(result_size > 28)? 27: (result_size == 0)? 0 : (result_size - 1));
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_HASH_SEL, crypto_ctrl_reg, 1);
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_ALG_MD, crypto_ctrl_reg, 0);
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_ALG, crypto_ctrl_reg, 2);
AES_HASH->CRYPTO_CTRL_REG = crypto_ctrl_reg;
}
/**
* \brief Configure engine for SHA-256 hash
*
* This function configures the engine to perform SHA-256 hashing
*
* \param[in] result_size The size in bytes of the result that the engine will write
* to the output memory. Accepted values are 1 to 32. Out of
* range values are adjusted to the closest limit.
*/
__STATIC_INLINE void hw_aes_hash_cfg_sha_256(unsigned int result_size)
{
uint32_t crypto_ctrl_reg = AES_HASH->CRYPTO_CTRL_REG;
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_HASH_OUT_LEN, crypto_ctrl_reg,
(result_size > 32)? 31: (result_size == 0)? 0 : (result_size - 1));
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_HASH_SEL, crypto_ctrl_reg, 1);
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_ALG_MD, crypto_ctrl_reg, 0);
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_ALG, crypto_ctrl_reg, 3);
AES_HASH->CRYPTO_CTRL_REG = crypto_ctrl_reg;
}
/**
* \brief Configure engine for SHA-384 hash
*
* This function configures the engine to perform SHA-384 hashing
*
* \param[in] result_size The size in bytes of the result that the engine will write
* to the output memory. Accepted values are 1 to 48. Out of
* range values are adjusted to the closest limit.
*/
__STATIC_INLINE void hw_aes_hash_cfg_sha_384(unsigned int result_size)
{
uint32_t crypto_ctrl_reg = AES_HASH->CRYPTO_CTRL_REG;
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_HASH_OUT_LEN, crypto_ctrl_reg,
(result_size > 48)? 47: (result_size == 0)? 0 : (result_size - 1));
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_HASH_SEL, crypto_ctrl_reg, 1);
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_ALG_MD, crypto_ctrl_reg, 1);
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_ALG, crypto_ctrl_reg, 0);
AES_HASH->CRYPTO_CTRL_REG = crypto_ctrl_reg;
}
/**
* \brief Configure engine for SHA-512 hash
*
* This function configures the engine to perform SHA-512 hashing
*
* \param[in] result_size The size in bytes of the result that the engine will write
* to the output memory. Accepted values are 1 to 64. Out of
* range values are adjusted to the closest limit.
*/
__STATIC_INLINE void hw_aes_hash_cfg_sha_512(unsigned int result_size)
{
uint32_t crypto_ctrl_reg = AES_HASH->CRYPTO_CTRL_REG;
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_HASH_OUT_LEN, crypto_ctrl_reg,
(result_size > 64)? 63: (result_size == 0)? 0 : (result_size - 1));
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_HASH_SEL, crypto_ctrl_reg, 1);
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_ALG_MD, crypto_ctrl_reg, 1);
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_ALG, crypto_ctrl_reg, 1);
AES_HASH->CRYPTO_CTRL_REG = crypto_ctrl_reg;
}
/**
* \brief Configure engine for SHA-512/224 hash
*
* This function configures the engine to perform SHA-512/224 hashing
*
* \param[in] result_size The size in bytes of the result that the engine will write
* to the output memory. Accepted values are 1 to 28. Out of
* range values are adjusted to the closest limit.
*/
__STATIC_INLINE void hw_aes_hash_cfg_sha_512_224(unsigned int result_size)
{
uint32_t crypto_ctrl_reg = AES_HASH->CRYPTO_CTRL_REG;
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_HASH_OUT_LEN, crypto_ctrl_reg,
(result_size > 28)? 27: (result_size == 0)? 0 : (result_size - 1));
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_HASH_SEL, crypto_ctrl_reg, 1);
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_ALG_MD, crypto_ctrl_reg, 1);
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_ALG, crypto_ctrl_reg, 2);
AES_HASH->CRYPTO_CTRL_REG = crypto_ctrl_reg;
}
/**
* \brief Configure engine for SHA-512/256 hash
*
* This function configures the engine to perform SHA-512/256 hashing
*
* \param[in] result_size The size in bytes of the result that the engine will write
* to the output memory. Accepted values are 1 to 32. Out of
* range values are adjusted to the closest limit.
*/
__STATIC_INLINE void hw_aes_hash_cfg_sha_512_256(unsigned int result_size)
{
uint32_t crypto_ctrl_reg = AES_HASH->CRYPTO_CTRL_REG;
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_HASH_OUT_LEN, crypto_ctrl_reg,
(result_size > 32)? 31: (result_size == 0)? 0 : (result_size - 1));
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_HASH_SEL, crypto_ctrl_reg, 1);
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_ALG_MD, crypto_ctrl_reg, 1);
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_ALG, crypto_ctrl_reg, 3);
AES_HASH->CRYPTO_CTRL_REG = crypto_ctrl_reg;
}
/**
* \brief Store initialization vector in AES/HASH engine memory
*
* This function stores the initialization vector (IV) that is necessary for AES CBC
* mode.
*
*
* \sa hw_aes_store_ic
*
* \param[in] iv The address of the buffer containing the initialization vector
*/
void hw_aes_hash_store_iv(const uint8 *iv);
/**
* \brief Store counter initialization in AES/HASH engine memory
*
* This function stores the counter initialization that is necessary for AES CTR
* mode.
*
*
* \sa hw_aes_store_iv
*
* \param[in] ic The address of the buffer containing the counter initialization
*/
void hw_aes_hash_store_ic(const uint8 *ic);
/**
* \brief Store AES keys in AES/HASH engine memory
*
* This function stores the keys used for AES encryption/decryption in AES/HASH engine memory.
* If key expansion is performed by the engine, then aes_keys should contain only the base
* key. Otherwise it should contain all the expanded keys.
*
* \note
* After an AES operation with a certain key, further operations using the same key do not
* need storing it to the AES/HASH memory again.
*
* \param[in] key_size The size of the key used in the encryption/decryption
* \param[in] aes_keys The address of the buffer containing the keys
* \param[in] key_exp Define if key expansion will be performed by hw or sw
*/
void hw_aes_hash_store_keys(hw_aes_key_size key_size, const uint8 *aes_keys, hw_aes_hash_key_exp_t key_exp);
/**
* \brief Configure DMA for data manipulation
*
* This function configures the DMA machine with the source and destination buffers.
*
* \param[in] src The physical address of the buffer containing the input data for the operation
* \param[in] dst The physical address (RAM or Cache RAM only) of the buffer where the output of the
* operation will be stored. The dst address must be NULL when configuring the DMA
* while the engine is waiting for more input data.
* \param[in] len The length of the input data
*/
void hw_aes_hash_cfg_dma(const uint8 *src, uint8 *dst, unsigned int len);
/**
* \brief Start AES/HASH engine operation
*
* This function starts a AES/HASH operation. The operation depends on the configuration that
* has been applied before calling this function
*
* \sa hw_aes_hash_init
*
*/
__STATIC_INLINE void hw_aes_hash_start(void)
{
AES_HASH->CRYPTO_START_REG = 1;
}
/**
* \brief Start AES encryption
*
* This function starts an AES encryption. AES mode, key and input/output data should be configured
* before calling this function.
*
* \sa hw_aes_hash_init
* \sa hw_aes_hash_cfg_aes_ecb
* \sa hw_aes_hash_cfg_aes_ctr
* \sa hw_aes_hash_cfg_aes_cbc
* \sa hw_aes_hash_store_keys
* \sa hw_aes_hash_cfg_dma
*/
__STATIC_INLINE void hw_aes_hash_encrypt(void)
{
REG_SET_BIT(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_ENCDEC);
AES_HASH->CRYPTO_START_REG = 1;
}
/**
* \brief Start AES decryption
*
* This function starts an AES decryption. AES mode, key and input/output data should be configured
* before calling this function.
*
* \sa hw_aes_hash_init
* \sa hw_aes_hash_cfg_aes_ecb
* \sa hw_aes_hash_cfg_aes_ctr
* \sa hw_aes_hash_cfg_aes_cbc
* \sa hw_aes_hash_store_keys
* \sa hw_aes_hash_cfg_dma
*/
__STATIC_INLINE void hw_aes_hash_decrypt(void)
{
REG_CLR_BIT(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_ENCDEC);
AES_HASH->CRYPTO_START_REG = 1;
}
/**
* \brief Enable AES/HASH engine interrupt
*
* This function enables the AES/HASH engine interrupt and sets a callback function
* to be called when the interrupt occurs.
*
* \param[in] cb The callback function for the interrupt
*
* \deprecated Consider using hw_crypto API along with hw_aes_hash_enable_interrupt_source()
*/
DEPRECATED_MSG("consider using hw_crypto API along with hw_aes_hash_enable_interrupt_source")
void hw_aes_hash_enable_interrupt(hw_aes_hash_cb cb);
/**
* \brief Disable AES/HASH engine interrupt
*
* This function disables the AES/HASH engine interrupt.
*
* \deprecated Consider using hw_crypto API along with hw_aes_hash_disable_interrupt_source()
*/
DEPRECATED_MSG("consider using hw_crypto API along with hw_aes_hash_disable_interrupt_source")
void hw_aes_hash_disable_interrupt(void);
/**
* \brief Enable AES/HASH engine interrupt source
*
* This function enables AES/HASH engine interrupt source.
*
* \note AES/HASH engine and ECC engine are common sources of CRYPTO system interrupt. This
* function does not enable the CRYPTO interrupt itself. Use hw_crypto_enable_aes_hash_interrupt()
* in addition, in order to enable the CRYPTO interrupt.
*/
static inline void hw_aes_hash_enable_interrupt_source(void)
{
REG_SET_BIT(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_IRQ_EN);
}
/**
* \brief Disable AES/HASH engine interrupt source
*
* This function disables AES/HASH engine interrupt source.
*
* \note AES/HASH engine and ECC engine are common sources of CRYPTO system interrupt. This
* function does not disable the CRYPTO interrupt itself. Use hw_crypto_disable_aes_hash_interrupt()
* in order to disable the CRYPTO interrupt.
*/
static inline void hw_aes_hash_disable_interrupt_source(void)
{
REG_CLR_BIT(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_IRQ_EN);
}
/**
* \brief Clear AES/HASH engine pending interrupt
*
* This function clears AES/HASH engine pending interrupt request.
*
* \note AES/HASH engine and ECC engine are common sources of CRYPTO system interrupt. This
* function does not clear pending CRYPTO interrupt. Use hw_crypto_clear_pending_interrupt()
* in order to clear pending CRYPTO interrupt.
*/
static inline void hw_aes_hash_clear_interrupt_req(void)
{
AES_HASH->CRYPTO_CLRIRQ_REG = 0x1;
}
/**
* \brief Set output mode to write all
*
* This function configures the AES/HASH engine to write back to memory all the
* resulting data.
*
* \note
* Only applicable to AES operations.
*/
__STATIC_INLINE void hw_aes_hash_output_mode_write_all(void)
{
REG_CLR_BIT(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_OUT_MD);
}
/**
* \brief Set output mode to write final
*
* This function configures the AES/HASH engine to write back to memory only the
* the last block of the resulting data.
*
* \note
* Only applicable to AES operations.
*/
__STATIC_INLINE void hw_aes_hash_output_mode_write_final(void)
{
REG_SET_BIT(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_OUT_MD);
}
/**
* \brief Check input data size restriction
*
* This function checks the restrictions of input data length. It returns 0 if the restrictions are not
* violated, -1 otherwise. It checks the configured values at the time it is called so it should be
* used just before starting an operation. The function can be useful for debugging. The following
* table summarizes the restrictions for the input data length.
*
* ALGORITHM | NOT LAST DATA BLOCK | LAST DATA BLOCK
* ------------------- | --------------------- | ----------------
* HW_AES_ECB | multiple of 16 | multiple of 16
* HW_AES_CBC | multiple of 16 | no restrictions
* HW_AES_CTR | multiple of 16 | no restrictions
* HW_HASH_MD5 | multiple of 8 | no restrictions
* HW_HASH_SHA_1 | multiple of 8 | no restrictions
* HW_HASH_SHA_256_224 | multiple of 8 | no restrictions
* HW_HASH_SHA_256 | multiple of 8 | no restrictions
* HW_HASH_SHA_384 | multiple of 8 | no restrictions
* HW_HASH_SHA_512 | multiple of 8 | no restrictions
* HW_HASH_SHA_512_224 | multiple of 8 | no restrictions
* HW_HASH_SHA_512_256 | multiple of 8 | no restrictions
*
*/
int hw_aes_hash_check_restrictions(void);
#endif /* dg_configUSE_HW_AES_HASH */
#endif /* HW_AES_HASH_H_ */
/**
* \}
* \}
* \}
*/
@@ -0,0 +1,108 @@
/**
* \addtogroup BSP
* \{
* \addtogroup DEVICES
* \{
* \addtogroup CRYPTO
* \{
* \brief Interrupt handling for the crypto engines (AES/HASH, ECC)
*/
/**
****************************************************************************************
*
* @file hw_cpm.c
*
* @brief Clock and Power Manager Driver
*
* Copyright (c) 2016, Dialog Semiconductor
* 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.
*
*
****************************************************************************************
*/
#if (dg_configUSE_HW_AES_HASH || dg_configUSE_HW_ECC)
#include <sdk_defs.h>
/**
* \brief Crypto engines callback
*
* This function type is used for callbacks called when the crypto engines (AES/HASH, ECC)
* generate an interrupt.
*
* \param [in] status The status register (either AES/HASH or ECC) at the time of the interrupt.
*
*/
typedef void (*hw_crypto_cb)(unsigned int status);
/**
* \brief Enable interrupt for AES/HASH crypto engine.
*
* \param [in] cb A callback to be called when interrupt occurs. It must always be provided.
*
* \note AES/HASH engine and ECC engine are common sources of CRYPTO system interrupt. This
* function only enables CRYPTO interrupt itself and registers a callback for AES/HASH
* related CRYPTO interrupts. In order to fully enable AES/HASH interrupts
* hw_aes_hash_enable_interrupt_source() must also be called
*/
void hw_crypto_enable_aes_hash_interrupt(hw_crypto_cb cb);
/**
* \brief Enable interrupt for ECC crypto engine.
*
* \param [in] cb A callback to be called when interrupt occurs. It must always be provided.
*/
void hw_crypto_enable_ecc_interrupt(hw_crypto_cb cb);
/**
* \brief Disable interrupt for AES/HASH crypto engine.
*/
void hw_crypto_disable_aes_hash_interrupt(void);
/**
* \brief Disable interrupt for ECC crypto engine.
*/
void hw_crypto_disable_ecc_interrupt(void);
/**
* \brief Clear pending interrupt from AES/HASH and ECC crypto engines.
*
* \note This function clears the pending CRYPTO interrupt only on the NVI Controller.
* Use hw_aes_hash_clear_interrupt_req() and hw_ecc_clear_interrupt_source() to clear the
* source of CRYPTO interrupt on the AES/HASH and ECC engines respectively.
*/
static inline void hw_crypto_clear_pending_interrupt(void)
{
NVIC_ClearPendingIRQ(CRYPTO_IRQn);
}
#endif /* (dg_configUSE_HW_AES_HASH || dg_configUSE_HW_ECC) */
/**
* \}
* \}
* \}
*/
@@ -0,0 +1,414 @@
/**
* \addtogroup BSP
* \{
* \addtogroup DEVICES
* \{
* \addtogroup AES_HASH
* \{
*/
/**
****************************************************************************************
*
* @file hw_cpm.c
*
* @brief Clock and Power Manager Driver
*
* Copyright (c) 2016, Dialog Semiconductor
* 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.
*
*
****************************************************************************************
*/
#if dg_configUSE_HW_AES_HASH
#include "hw_aes_hash.h"
#include "hw_crypto.h"
#define MODE_IS_AES(m) (m <= HW_AES_CTR)
static void hw_aes_hash_wait_on_inactive(void)
{
while (!REG_GETF(AES_HASH, CRYPTO_STATUS_REG, CRYPTO_INACTIVE)) {
;
};
}
static void hw_aes_hash_set_mode(const hw_aes_hash_setup* setup)
{
uint32_t crypt0_ctrl_reg = AES_HASH->CRYPTO_CTRL_REG;
switch (setup->mode) {
case HW_AES_ECB:
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_HASH_SEL, crypt0_ctrl_reg, 0);
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_ALG_MD, crypt0_ctrl_reg, 0);
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_ALG, crypt0_ctrl_reg, 0);
break;
case HW_AES_CBC:
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_HASH_SEL, crypt0_ctrl_reg, 0);
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_ALG_MD, crypt0_ctrl_reg, 3);
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_ALG, crypt0_ctrl_reg, 0);
AES_HASH->CRYPTO_MREG0_REG = setup->aesIvCtrblk_0_31;
AES_HASH->CRYPTO_MREG1_REG = setup->aesIvCtrblk_32_63;
AES_HASH->CRYPTO_MREG2_REG = setup->aesIvCtrblk_64_95;
AES_HASH->CRYPTO_MREG3_REG = setup->aesIvCtrblk_96_127;
break;
case HW_AES_CTR:
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_HASH_SEL, crypt0_ctrl_reg, 0);
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_ALG_MD, crypt0_ctrl_reg, 2);
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_ALG, crypt0_ctrl_reg, 0);
AES_HASH->CRYPTO_MREG0_REG = setup->aesIvCtrblk_0_31;
AES_HASH->CRYPTO_MREG1_REG = setup->aesIvCtrblk_32_63;
AES_HASH->CRYPTO_MREG2_REG = setup->aesIvCtrblk_64_95;
AES_HASH->CRYPTO_MREG3_REG = setup->aesIvCtrblk_96_127;
break;
case HW_HASH_MD5:
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_HASH_SEL, crypt0_ctrl_reg, 1);
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_ALG_MD, crypt0_ctrl_reg, 0);
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_ALG, crypt0_ctrl_reg, 0);
break;
case HW_HASH_SHA_1:
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_HASH_SEL, crypt0_ctrl_reg, 1);
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_ALG_MD, crypt0_ctrl_reg, 0);
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_ALG, crypt0_ctrl_reg, 1);
break;
case HW_HASH_SHA_256_224:
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_HASH_SEL, crypt0_ctrl_reg, 1);
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_ALG_MD, crypt0_ctrl_reg, 0);
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_ALG, crypt0_ctrl_reg, 2);
break;
case HW_HASH_SHA_256:
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_HASH_SEL, crypt0_ctrl_reg, 1);
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_ALG_MD, crypt0_ctrl_reg, 0);
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_ALG, crypt0_ctrl_reg, 3);
break;
case HW_HASH_SHA_384:
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_HASH_SEL, crypt0_ctrl_reg, 1);
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_ALG_MD, crypt0_ctrl_reg, 1);
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_ALG, crypt0_ctrl_reg, 0);
break;
case HW_HASH_SHA_512:
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_HASH_SEL, crypt0_ctrl_reg, 1);
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_ALG_MD, crypt0_ctrl_reg, 1);
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_ALG, crypt0_ctrl_reg, 1);
break;
case HW_HASH_SHA_512_224:
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_HASH_SEL, crypt0_ctrl_reg, 1);
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_ALG_MD, crypt0_ctrl_reg, 1);
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_ALG, crypt0_ctrl_reg, 2);
break;
case HW_HASH_SHA_512_256:
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_HASH_SEL, crypt0_ctrl_reg, 1);
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_ALG_MD, crypt0_ctrl_reg, 1);
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_ALG, crypt0_ctrl_reg, 3);
break;
}
AES_HASH->CRYPTO_CTRL_REG = crypt0_ctrl_reg;
}
static void hw_aes_hash_check_data_size(const hw_aes_hash_setup* setup)
{
switch (setup->mode) {
case HW_AES_ECB:
// In ECB mode the dataSize needs to be a multiple of 16.
ASSERT_ERROR(setup->dataSize % 0x10 == 0);
break;
case HW_AES_CBC:
case HW_AES_CTR:
// If more data is to come in CBC or CTR mode the dataSize needs to be a multiple of 16.
if (setup->moreDataToCome) {
ASSERT_ERROR(setup->dataSize % 0x10 == 0);
}
break;
case HW_HASH_MD5:
case HW_HASH_SHA_1:
case HW_HASH_SHA_256_224:
case HW_HASH_SHA_256:
case HW_HASH_SHA_384:
case HW_HASH_SHA_512:
case HW_HASH_SHA_512_224:
case HW_HASH_SHA_512_256:
// If more data is to come in hash mode the dataSize needs to be a multiple of 8.
if (setup->moreDataToCome) {
ASSERT_ERROR(setup->dataSize % 0x8 == 0);
}
break;
}
}
hw_aes_hash_cb hw_aes_hash_old_style_cb = NULL;
static void hw_aes_hash_old_cb_style_support(unsigned int status)
{
if (hw_aes_hash_old_style_cb) {
hw_aes_hash_old_style_cb();
}
}
void hw_aes_hash_enable_interrupt(hw_aes_hash_cb cb)
{
hw_aes_hash_old_style_cb = cb;
hw_crypto_enable_aes_hash_interrupt(hw_aes_hash_old_cb_style_support);
REG_SET_BIT(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_IRQ_EN);
}
void hw_aes_hash_disable_interrupt(void)
{
REG_CLR_BIT(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_IRQ_EN);
hw_crypto_disable_aes_hash_interrupt();
}
static inline uint32 hw_aes_hash_construct_word(const uint8 *data)
{
if ((uint32)data & 0x3) {
uint32 internal_buf;
uint8 *p = (uint8 *)&internal_buf + 3;
unsigned int i;
for (i = 0; i < 4; i++) {
*(p--) = *(data++);
}
return internal_buf;
}
else {
return SWAP32(*(uint32 *)data);
}
}
void hw_aes_hash_store_keys(hw_aes_key_size key_size, const uint8 *aes_keys, hw_aes_hash_key_exp_t key_exp)
{
volatile uint32 *kmem_ptr = &AES_HASH->CRYPTO_KEYS_START;
unsigned int key_wrds;
if (key_exp == HW_AES_DO_NOT_PERFORM_KEY_EXPANSION) {
/* Key expansion is provided by the software */
REG_CLR_BIT(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_AES_KEXP);
key_wrds = (key_size == HW_AES_256) ? 60 : (key_size == HW_AES_192) ? 52 : 44;
}
else {
/* Key expansion needs to be performed by the engine */
REG_SET_BIT(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_AES_KEXP);
key_wrds = (key_size == HW_AES_256) ? 8 : (key_size == HW_AES_192) ? 6 : 4;
}
do {
*(kmem_ptr++) = hw_aes_hash_construct_word(aes_keys);
aes_keys += 4;
key_wrds--;
} while (key_wrds > 0);
}
void hw_aes_hash_enable(const hw_aes_hash_setup setup)
{
hw_aes_hash_check_data_size(&setup);
hw_aes_hash_enable_clock();
hw_aes_hash_set_mode(&setup);
uint32_t crypto_ctrl_reg = AES_HASH->CRYPTO_CTRL_REG;
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_MORE_IN, crypto_ctrl_reg,
setup.moreDataToCome);
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_HASH_OUT_LEN, crypto_ctrl_reg,
(setup.hashOutLength - 1));
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_ENCDEC, crypto_ctrl_reg,
setup.aesDirection);
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_AES_KEXP, crypto_ctrl_reg,
setup.aesKeyExpand);
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_AES_KEY_SZ, crypto_ctrl_reg,
setup.aesKeySize);
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_OUT_MD, crypto_ctrl_reg,
!setup.aesWriteBackAll);
AES_HASH->CRYPTO_CTRL_REG = crypto_ctrl_reg;
if (MODE_IS_AES(setup.mode)) {
hw_aes_hash_store_keys(setup.aesKeySize, (uint8 *)setup.aesKeys, !setup.aesKeyExpand);
}
hw_aes_hash_cfg_dma((const uint8 *)setup.sourceAddress, (uint8 *)setup.destinationAddress,
(unsigned int)setup.dataSize);
if (setup.enableInterrupt) {
hw_aes_hash_old_style_cb = setup.callback;
hw_aes_hash_enable_interrupt_source();
hw_crypto_enable_aes_hash_interrupt(hw_aes_hash_old_cb_style_support);
}
else {
hw_aes_hash_disable_interrupt_source();
hw_crypto_disable_aes_hash_interrupt();
}
hw_aes_hash_start();
}
void hw_aes_hash_init(hw_aes_hash_setup *setup)
{
hw_aes_hash_check_data_size(setup);
hw_aes_hash_enable_clock();
hw_aes_hash_set_mode(setup);
uint32_t crypto_ctrl_reg = AES_HASH->CRYPTO_CTRL_REG;
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_MORE_IN, crypto_ctrl_reg,
setup->moreDataToCome);
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_HASH_OUT_LEN, crypto_ctrl_reg,
(setup->hashOutLength - 1));
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_ENCDEC, crypto_ctrl_reg,
setup->aesDirection);
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_AES_KEXP, crypto_ctrl_reg,
setup->aesKeyExpand);
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_AES_KEY_SZ, crypto_ctrl_reg,
setup->aesKeySize);
REG_SET_FIELD(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_OUT_MD, crypto_ctrl_reg,
!setup->aesWriteBackAll);
AES_HASH->CRYPTO_CTRL_REG = crypto_ctrl_reg;
if (MODE_IS_AES(setup->mode)) {
hw_aes_hash_store_keys(setup->aesKeySize, (uint8 *)setup->aesKeys, !setup->aesKeyExpand);
}
hw_aes_hash_cfg_dma((const uint8 *)setup->sourceAddress, (uint8 *)setup->destinationAddress,
(unsigned int)setup->dataSize);
if (setup->enableInterrupt) {
hw_aes_hash_old_style_cb = setup->callback;
hw_aes_hash_enable_interrupt_source();
hw_crypto_enable_aes_hash_interrupt(hw_aes_hash_old_cb_style_support);
}
else {
hw_aes_hash_disable_interrupt_source();
hw_crypto_disable_aes_hash_interrupt();
}
}
void hw_aes_hash_restart(const uint32 sourceAddress, const uint32 dataSize,
const bool moreDataToCome)
{
hw_aes_hash_cfg_dma((const uint8 *)sourceAddress, NULL, (unsigned int)dataSize);
REG_SETF(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_MORE_IN, moreDataToCome);
hw_aes_hash_start();
}
bool hw_aes_hash_is_active()
{
return REG_GETF(AES_HASH, CRYPTO_STATUS_REG, CRYPTO_INACTIVE) == 0;
}
bool hw_aes_hash_wait_for_in()
{
return REG_GETF(AES_HASH, CRYPTO_STATUS_REG, CRYPTO_WAIT_FOR_IN) == 1;
}
void hw_aes_hash_disable(const bool waitOnFinish)
{
if (waitOnFinish)
hw_aes_hash_wait_on_inactive();
hw_aes_hash_disable_interrupt_source();
AES_HASH->CRYPTO_CLRIRQ_REG = 1;
GLOBAL_INT_DISABLE();
REG_CLR_BIT(CRG_TOP, CLK_AMBA_REG, AES_CLK_ENABLE);
GLOBAL_INT_RESTORE();
REG_CLR_BIT(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_MORE_IN);
}
void hw_aes_hash_cfg_dma(const uint8 *src, uint8 *dst, unsigned int len)
{
/* Source address setting */
AES_HASH->CRYPTO_FETCH_ADDR_REG = DA15000_phy_addr((uint32)src);
/* Destination address setting */
if (dst) {
unsigned int remap_type = REG_GETF(CRG_TOP, SYS_CTRL_REG, REMAP_ADR0);
if (IS_SYSRAM_ADDRESS(dst) ||
(IS_REMAPPED_ADDRESS(dst) && (remap_type == 0x3))) {
AES_HASH->CRYPTO_DEST_ADDR_REG = DA15000_phy_addr((uint32)dst);
#if dg_configEXEC_MODE != MODE_IS_CACHED
} else if (IS_CACHERAM_ADDRESS(dst)) {
AES_HASH->CRYPTO_DEST_ADDR_REG = DA15000_phy_addr((uint32)dst);
#endif
} else {
/*
* Destination address can only reside in RAM or Cache RAM, but in case of remapped
* address, REMAP_ADR0 cannot be 0x6 (Cache Data RAM)
*/
ASSERT_ERROR(0);
}
}
/* Data length setting */
AES_HASH->CRYPTO_LEN_REG = (uint32)len;
}
static void hw_aes_hash_store_in_mode_dependent_regs(const uint8 *buf)
{
AES_HASH->CRYPTO_MREG0_REG = hw_aes_hash_construct_word(buf + 12);
AES_HASH->CRYPTO_MREG1_REG = hw_aes_hash_construct_word(buf + 8);
AES_HASH->CRYPTO_MREG2_REG = hw_aes_hash_construct_word(buf + 4);
AES_HASH->CRYPTO_MREG3_REG = hw_aes_hash_construct_word(buf + 0);
}
void hw_aes_hash_store_iv(const uint8 *iv)
{
hw_aes_hash_store_in_mode_dependent_regs(iv);
}
void hw_aes_hash_store_ic(const uint8 *ic)
{
hw_aes_hash_store_in_mode_dependent_regs(ic);
}
int hw_aes_hash_check_restrictions(void)
{
unsigned int is_hash = AES_HASH->CRYPTO_CTRL_REG & AES_HASH_CRYPTO_CTRL_REG_CRYPTO_HASH_SEL_Msk;
unsigned int more_in = AES_HASH->CRYPTO_CTRL_REG & AES_HASH_CRYPTO_CTRL_REG_CRYPTO_MORE_IN_Msk;
if (is_hash) {
if (more_in && (AES_HASH->CRYPTO_LEN_REG & 0x7)) {
return -1;
}
}
else {
unsigned int is_ecb = (((AES_HASH->CRYPTO_CTRL_REG & AES_HASH_CRYPTO_CTRL_REG_CRYPTO_ALG_MD_Msk) == 0) |
((AES_HASH->CRYPTO_CTRL_REG & AES_HASH_CRYPTO_CTRL_REG_CRYPTO_ALG_MD_Msk) == 0x0100));
if ((is_ecb || more_in) && (AES_HASH->CRYPTO_LEN_REG & 0x15)) {
return -1;
}
}
return 0;
}
#endif /* dg_configUSE_HW_AES_HASH */
/**
* \}
* \}
* \}
*/
@@ -0,0 +1,126 @@
/**
* \addtogroup BSP
* \{
* \addtogroup DEVICES
* \{
* \addtogroup CRYPTO
* \{
*/
/**
****************************************************************************************
*
* @file hw_cpm.c
*
* @brief Clock and Power Manager Driver
*
* Copyright (c) 2016, Dialog Semiconductor
* 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.
*
*
****************************************************************************************
*/
#if (dg_configUSE_HW_AES_HASH || dg_configUSE_HW_ECC)
#include "hw_crypto.h"
#if (dg_configSYSTEMVIEW)
# include "SEGGER_SYSVIEW_FreeRTOS.h"
#else
# define SEGGER_SYSTEMVIEW_ISR_ENTER()
# define SEGGER_SYSTEMVIEW_ISR_EXIT()
#endif
__RETAINED static hw_crypto_cb hw_crypto_aes_hash_cb;
__RETAINED static hw_crypto_cb hw_crypto_ecc_cb;
void hw_crypto_enable_aes_hash_interrupt(hw_crypto_cb cb)
{
/* A callback for the interrupt must be provided */
ASSERT_ERROR(cb);
hw_crypto_aes_hash_cb = cb;
NVIC_EnableIRQ(CRYPTO_IRQn);
}
void hw_crypto_enable_ecc_interrupt(hw_crypto_cb cb)
{
/* A callback for the interrupt must be provided */
ASSERT_ERROR(cb);
hw_crypto_ecc_cb = cb;
NVIC_EnableIRQ(CRYPTO_IRQn);
}
void hw_crypto_disable_aes_hash_interrupt(void)
{
hw_crypto_aes_hash_cb = NULL;
if (!hw_crypto_ecc_cb) {
NVIC_DisableIRQ(CRYPTO_IRQn);
}
}
void hw_crypto_disable_ecc_interrupt(void)
{
hw_crypto_ecc_cb = NULL;
if (!hw_crypto_aes_hash_cb) {
NVIC_DisableIRQ(CRYPTO_IRQn);
}
}
void CRYPTO_Handler(void)
{
SEGGER_SYSTEMVIEW_ISR_ENTER();
uint32_t status = AES_HASH->CRYPTO_STATUS_REG;
/* In case both AES/HASH and ECC have triggered an interrupt, first the AES/HASH
will be served, and then the ISR will be called again since the ECC interrupt
source is only cleared by reading its status register */
if (status & AES_HASH_CRYPTO_STATUS_REG_CRYPTO_IRQ_ST_Msk) {
/* Clear AES/HASH interrupt source */
AES_HASH->CRYPTO_CLRIRQ_REG = 0x1;
if (hw_crypto_aes_hash_cb != NULL) {
hw_crypto_aes_hash_cb(status);
}
} else {
/* Clear ECC interrupt source */
status = ECC->ECC_STATUS_REG;
if (hw_crypto_ecc_cb != NULL) {
hw_crypto_ecc_cb(status);
}
}
SEGGER_SYSTEMVIEW_ISR_EXIT();
}
#endif /* (dg_configUSE_HW_AES_HASH || dg_configUSE_HW_ECC) */
/**
* \}
* \}
* \}
*/
+4 -4
View File
@@ -216,8 +216,8 @@ void hw_dma_channel_initialization(DMA_setup *channel_setup)
}
#endif
src_address = black_orca_phy_addr(channel_setup->src_address);
dest_address = black_orca_phy_addr(channel_setup->dest_address);
src_address = DA15000_phy_addr(channel_setup->src_address);
dest_address = DA15000_phy_addr(channel_setup->dest_address);
// Set source address registers
*dma_x_a_start_low_reg = (src_address & 0xffff);
@@ -257,7 +257,7 @@ void hw_dma_channel_initialization(DMA_setup *channel_setup)
void hw_dma_channel_update_source(HW_DMA_CHANNEL channel, void *addr, uint16_t length,
hw_dma_transfer_cb cb)
{
uint32_t phy_addr = black_orca_phy_addr((uint32_t) addr);
uint32_t phy_addr = DA15000_phy_addr((uint32_t) addr);
dma_callbacks_user_data[channel].callback = cb;
@@ -286,7 +286,7 @@ void hw_dma_channel_update_source(HW_DMA_CHANNEL channel, void *addr, uint16_t l
void hw_dma_channel_update_destination(HW_DMA_CHANNEL channel, void *addr, uint16_t length,
hw_dma_transfer_cb cb)
{
uint32_t phy_addr = black_orca_phy_addr((uint32_t) addr);
uint32_t phy_addr = DA15000_phy_addr((uint32_t) addr);
dma_callbacks_user_data[channel].callback = cb;
+4 -4
View File
@@ -757,12 +757,12 @@ bool hw_otpc_dma_prog(const uint32_t *p_data, uint32_t cell_offset, HW_OTPC_WORD
if (IS_SYSRAM_ADDRESS(p_data) ||
(IS_REMAPPED_ADDRESS(p_data) && (remap_type == 0x3)))
{
OTPC->OTPC_AHBADR_REG = black_orca_phy_addr((uint32_t)p_data);
OTPC->OTPC_AHBADR_REG = DA15000_phy_addr((uint32_t)p_data);
#if dg_configEXEC_MODE != MODE_IS_CACHED
}
else if (IS_CACHERAM_ADDRESS(p_data))
{
OTPC->OTPC_AHBADR_REG = black_orca_phy_addr((uint32_t)p_data);
OTPC->OTPC_AHBADR_REG = DA15000_phy_addr((uint32_t)p_data);
#endif
}
else
@@ -831,12 +831,12 @@ void hw_otpc_dma_read(uint32_t *p_data, uint32_t cell_offset, HW_OTPC_WORD cell_
if (IS_SYSRAM_ADDRESS(p_data) ||
(IS_REMAPPED_ADDRESS(p_data) && (remap_type == 0x3)))
{
OTPC->OTPC_AHBADR_REG = black_orca_phy_addr((uint32_t)p_data);
OTPC->OTPC_AHBADR_REG = DA15000_phy_addr((uint32_t)p_data);
#if dg_configEXEC_MODE != MODE_IS_CACHED
}
else if (IS_CACHERAM_ADDRESS(p_data))
{
OTPC->OTPC_AHBADR_REG = black_orca_phy_addr((uint32_t)p_data);
OTPC->OTPC_AHBADR_REG = DA15000_phy_addr((uint32_t)p_data);
#endif
}
else