186 lines
4.2 KiB
C
186 lines
4.2 KiB
C
/*
|
|
* Copyright (c) 2016 Nordic Semiconductor ASA
|
|
* Copyright (c) 2016 Vinayak Kariappa Chettimada
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#include <string.h>
|
|
#include <soc.h>
|
|
|
|
#include "mem.h"
|
|
#include "ecb.h"
|
|
|
|
#include "debug.h"
|
|
|
|
void ecb_encrypt(uint8_t const *const key_le,
|
|
uint8_t const *const clear_text_le,
|
|
uint8_t * const cipher_text_le,
|
|
uint8_t * const cipher_text_be)
|
|
{
|
|
struct {
|
|
uint8_t key[16];
|
|
uint8_t clear_text[16];
|
|
uint8_t cipher_text[16];
|
|
} __packed 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 {
|
|
NRF_ECB->TASKS_STOPECB = 1;
|
|
NRF_ECB->ECBDATAPTR = (uint32_t) &ecb;
|
|
NRF_ECB->EVENTS_ENDECB = 0;
|
|
NRF_ECB->EVENTS_ERRORECB = 0;
|
|
NRF_ECB->TASKS_STARTECB = 1;
|
|
while ((NRF_ECB->EVENTS_ENDECB == 0) &&
|
|
(NRF_ECB->EVENTS_ERRORECB == 0) &&
|
|
(NRF_ECB->ECBDATAPTR != 0)) {
|
|
/*__WFE();*/
|
|
}
|
|
NRF_ECB->TASKS_STOPECB = 1;
|
|
} while ((NRF_ECB->EVENTS_ERRORECB != 0) || (NRF_ECB->ECBDATAPTR == 0));
|
|
|
|
NRF_ECB->ECBDATAPTR = 0;
|
|
|
|
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));
|
|
}
|
|
}
|
|
|
|
uint32_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 = (uint32_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 */
|
|
_NvicIrqUnpend(ECB_IRQn);
|
|
irq_enable(ECB_IRQn);
|
|
|
|
/* start the encryption h/w */
|
|
NRF_ECB->TASKS_STARTECB = 1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void ecb_cleanup(void)
|
|
{
|
|
/* stop h/w */
|
|
NRF_ECB->TASKS_STOPECB = 1;
|
|
|
|
/* cleanup interrupt */
|
|
irq_disable(ECB_IRQn);
|
|
}
|
|
|
|
void ecb_isr(void)
|
|
{
|
|
if (NRF_ECB->EVENTS_ERRORECB) {
|
|
struct ecb *ecb = (struct ecb *)NRF_ECB->ECBDATAPTR;
|
|
|
|
ecb_cleanup();
|
|
|
|
ecb->fp_ecb(1, 0, 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 {
|
|
uint32_t volatile done;
|
|
uint32_t status;
|
|
uint8_t cipher_text[16];
|
|
};
|
|
|
|
static void ecb_cb(uint32_t status, uint8_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));
|
|
}
|
|
}
|
|
|
|
uint32_t ecb_ut(void)
|
|
{
|
|
uint8_t key[16] = {
|
|
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0x00,
|
|
0x11, 0x22, 0x33, 0x44, 0x55 };
|
|
uint8_t clear_text[16] = {
|
|
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0x00,
|
|
0x11, 0x22, 0x33, 0x44, 0x55 };
|
|
uint8_t cipher_text[16];
|
|
uint32_t status = 0;
|
|
struct ecb ecb;
|
|
struct ecb_ut_context context;
|
|
|
|
ecb_encrypt(key, clear_text, cipher_text, 0);
|
|
|
|
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;
|
|
}
|