Conditionally compiled changes to the NRF52 HAL so it can run on simulated HW on the native port. (HW models are not included in this commit) All changes are under ifdefs and therefore will not have any effect on normal builds Signed-off-by: Alberto Escolar Piedras <alpi@oticon.com>
217 lines
4.7 KiB
C
217 lines
4.7 KiB
C
/*
|
|
* Copyright (c) 2016 Nordic Semiconductor ASA
|
|
* Copyright (c) 2016 Vinayak Kariappa Chettimada
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#include <string.h>
|
|
#include <soc.h>
|
|
#if !defined(CONFIG_ARCH_POSIX)
|
|
#include <arch/arm/cortex_m/cmsis.h>
|
|
#endif
|
|
|
|
#include "util/mem.h"
|
|
#include "hal/ecb.h"
|
|
|
|
#include "common/log.h"
|
|
#include "hal/debug.h"
|
|
|
|
struct ecb_param {
|
|
u8_t key[16];
|
|
u8_t clear_text[16];
|
|
u8_t cipher_text[16];
|
|
} __packed;
|
|
|
|
static void do_ecb(struct ecb_param *ecb)
|
|
{
|
|
do {
|
|
NRF_ECB->TASKS_STOPECB = 1;
|
|
NRF_ECB->ECBDATAPTR = (u32_t)ecb;
|
|
NRF_ECB->EVENTS_ENDECB = 0;
|
|
NRF_ECB->EVENTS_ERRORECB = 0;
|
|
NRF_ECB->TASKS_STARTECB = 1;
|
|
#if defined(CONFIG_BOARD_NRFXX_NWTSIM)
|
|
NRF_ECB_regw_sideeffects_TASKS_STOPECB();
|
|
NRF_ECB_regw_sideeffects_TASKS_STARTECB();
|
|
#endif
|
|
while ((NRF_ECB->EVENTS_ENDECB == 0) &&
|
|
(NRF_ECB->EVENTS_ERRORECB == 0) &&
|
|
(NRF_ECB->ECBDATAPTR != 0)) {
|
|
#if defined(CONFIG_BOARD_NRFXX_NWTSIM)
|
|
__WFE();
|
|
#else
|
|
/*__WFE();*/
|
|
#endif
|
|
}
|
|
NRF_ECB->TASKS_STOPECB = 1;
|
|
#if defined(CONFIG_BOARD_NRFXX_NWTSIM)
|
|
NRF_ECB_regw_sideeffects_TASKS_STOPECB();
|
|
#endif
|
|
} while ((NRF_ECB->EVENTS_ERRORECB != 0) || (NRF_ECB->ECBDATAPTR == 0));
|
|
|
|
NRF_ECB->ECBDATAPTR = 0;
|
|
}
|
|
|
|
void ecb_encrypt_be(u8_t const *const key_be, u8_t const *const clear_text_be,
|
|
u8_t * const cipher_text_be)
|
|
{
|
|
struct ecb_param ecb;
|
|
|
|
memcpy(&ecb.key[0], key_be, sizeof(ecb.key));
|
|
memcpy(&ecb.clear_text[0], clear_text_be, sizeof(ecb.clear_text));
|
|
|
|
do_ecb(&ecb);
|
|
|
|
memcpy(cipher_text_be, &ecb.cipher_text[0], sizeof(ecb.cipher_text));
|
|
}
|
|
|
|
void ecb_encrypt(u8_t const *const key_le, u8_t const *const clear_text_le,
|
|
u8_t * const cipher_text_le, u8_t * const cipher_text_be)
|
|
{
|
|
struct ecb_param ecb;
|
|
|
|
mem_rcopy(&ecb.key[0], key_le, sizeof(ecb.key));
|
|
mem_rcopy(&ecb.clear_text[0], clear_text_le, sizeof(ecb.clear_text));
|
|
|
|
do_ecb(&ecb);
|
|
|
|
if (cipher_text_le) {
|
|
mem_rcopy(cipher_text_le, &ecb.cipher_text[0],
|
|
sizeof(ecb.cipher_text));
|
|
}
|
|
|
|
if (cipher_text_be) {
|
|
memcpy(cipher_text_be, &ecb.cipher_text[0],
|
|
sizeof(ecb.cipher_text));
|
|
}
|
|
}
|
|
|
|
u32_t ecb_encrypt_nonblocking(struct ecb *ecb)
|
|
{
|
|
/* prepare to be used in a BE AES h/w */
|
|
if (ecb->in_key_le) {
|
|
mem_rcopy(&ecb->in_key_be[0], ecb->in_key_le,
|
|
sizeof(ecb->in_key_be));
|
|
}
|
|
if (ecb->in_clear_text_le) {
|
|
mem_rcopy(&ecb->in_clear_text_be[0],
|
|
ecb->in_clear_text_le,
|
|
sizeof(ecb->in_clear_text_be));
|
|
}
|
|
|
|
/* setup the encryption h/w */
|
|
NRF_ECB->ECBDATAPTR = (u32_t)ecb;
|
|
NRF_ECB->EVENTS_ENDECB = 0;
|
|
NRF_ECB->EVENTS_ERRORECB = 0;
|
|
NRF_ECB->INTENSET = ECB_INTENSET_ERRORECB_Msk | ECB_INTENSET_ENDECB_Msk;
|
|
|
|
/* enable interrupt */
|
|
NVIC_ClearPendingIRQ(ECB_IRQn);
|
|
irq_enable(ECB_IRQn);
|
|
|
|
/* start the encryption h/w */
|
|
NRF_ECB->TASKS_STARTECB = 1;
|
|
#if defined(CONFIG_BOARD_NRFXX_NWTSIM)
|
|
NRF_ECB_regw_sideeffects_INTENSET();
|
|
NRF_ECB_regw_sideeffects_TASKS_STARTECB();
|
|
#endif
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void ecb_cleanup(void)
|
|
{
|
|
/* stop h/w */
|
|
NRF_ECB->TASKS_STOPECB = 1;
|
|
#if defined(CONFIG_BOARD_NRFXX_NWTSIM)
|
|
NRF_ECB_regw_sideeffects_TASKS_STOPECB();
|
|
#endif
|
|
|
|
/* cleanup interrupt */
|
|
irq_disable(ECB_IRQn);
|
|
}
|
|
|
|
void isr_ecb(void *param)
|
|
{
|
|
ARG_UNUSED(param);
|
|
|
|
if (NRF_ECB->EVENTS_ERRORECB) {
|
|
struct ecb *ecb = (struct ecb *)NRF_ECB->ECBDATAPTR;
|
|
|
|
ecb_cleanup();
|
|
|
|
ecb->fp_ecb(1, NULL, ecb->context);
|
|
}
|
|
|
|
else if (NRF_ECB->EVENTS_ENDECB) {
|
|
struct ecb *ecb = (struct ecb *)NRF_ECB->ECBDATAPTR;
|
|
|
|
ecb_cleanup();
|
|
|
|
ecb->fp_ecb(0, &ecb->out_cipher_text_be[0],
|
|
ecb->context);
|
|
}
|
|
|
|
else {
|
|
LL_ASSERT(0);
|
|
}
|
|
}
|
|
|
|
struct ecb_ut_context {
|
|
u32_t volatile done;
|
|
u32_t status;
|
|
u8_t cipher_text[16];
|
|
};
|
|
|
|
static void ecb_cb(u32_t status, u8_t *cipher_be, void *context)
|
|
{
|
|
struct ecb_ut_context *ecb_ut_context =
|
|
(struct ecb_ut_context *)context;
|
|
|
|
ecb_ut_context->done = 1;
|
|
ecb_ut_context->status = status;
|
|
if (!status) {
|
|
mem_rcopy(ecb_ut_context->cipher_text, cipher_be,
|
|
sizeof(ecb_ut_context->cipher_text));
|
|
}
|
|
}
|
|
|
|
u32_t ecb_ut(void)
|
|
{
|
|
u8_t key[16] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88,
|
|
0x99, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 };
|
|
u8_t clear_text[16] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
|
|
0x88, 0x99, 0x00, 0x11, 0x22, 0x33, 0x44,
|
|
0x55 };
|
|
u8_t cipher_text[16];
|
|
u32_t status = 0;
|
|
struct ecb ecb;
|
|
struct ecb_ut_context context;
|
|
|
|
ecb_encrypt(key, clear_text, cipher_text, NULL);
|
|
|
|
context.done = 0;
|
|
ecb.in_key_le = key;
|
|
ecb.in_clear_text_le = clear_text;
|
|
ecb.fp_ecb = ecb_cb;
|
|
ecb.context = &context;
|
|
status = ecb_encrypt_nonblocking(&ecb);
|
|
do {
|
|
__WFE();
|
|
__SEV();
|
|
__WFE();
|
|
} while (!context.done);
|
|
|
|
if (context.status != 0) {
|
|
return context.status;
|
|
}
|
|
|
|
status = memcmp(cipher_text, context.cipher_text, sizeof(cipher_text));
|
|
if (status) {
|
|
return status;
|
|
}
|
|
|
|
return status;
|
|
}
|