1 /*
2 * Copyright (c) 2016 Nordic Semiconductor ASA
3 * Copyright (c) 2016 Vinayak Kariappa Chettimada
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
8 #include <string.h>
9
10 #include <hal/nrf_ecb.h>
11
12 #include "util/mem.h"
13
14 #include "hal/cpu.h"
15 #include "hal/ecb.h"
16
17 #include "hal/debug.h"
18
19 struct ecb_param {
20 uint8_t key[16];
21 uint8_t clear_text[16];
22 uint8_t cipher_text[16];
23 } __packed;
24
do_ecb(struct ecb_param * ecb)25 static void do_ecb(struct ecb_param *ecb)
26 {
27 do {
28 nrf_ecb_task_trigger(NRF_ECB, NRF_ECB_TASK_STOPECB);
29 NRF_ECB->ECBDATAPTR = (uint32_t)ecb;
30 NRF_ECB->EVENTS_ENDECB = 0;
31 NRF_ECB->EVENTS_ERRORECB = 0;
32 nrf_ecb_task_trigger(NRF_ECB, NRF_ECB_TASK_STARTECB);
33 while ((NRF_ECB->EVENTS_ENDECB == 0) &&
34 (NRF_ECB->EVENTS_ERRORECB == 0) &&
35 (NRF_ECB->ECBDATAPTR != 0)) {
36 #if defined(CONFIG_SOC_SERIES_BSIM_NRFXX)
37 k_busy_wait(10);
38 #else
39 /* FIXME: use cpu_sleep(), but that will need interrupt
40 * wake up source and hence necessary appropriate
41 * code.
42 */
43 #endif
44 }
45 nrf_ecb_task_trigger(NRF_ECB, NRF_ECB_TASK_STOPECB);
46 } while ((NRF_ECB->EVENTS_ERRORECB != 0) || (NRF_ECB->ECBDATAPTR == 0));
47
48 NRF_ECB->ECBDATAPTR = 0;
49 }
50
ecb_encrypt_be(uint8_t const * const key_be,uint8_t const * const clear_text_be,uint8_t * const cipher_text_be)51 void ecb_encrypt_be(uint8_t const *const key_be, uint8_t const *const clear_text_be,
52 uint8_t * const cipher_text_be)
53 {
54 struct ecb_param ecb;
55
56 memcpy(&ecb.key[0], key_be, sizeof(ecb.key));
57 memcpy(&ecb.clear_text[0], clear_text_be, sizeof(ecb.clear_text));
58
59 do_ecb(&ecb);
60
61 memcpy(cipher_text_be, &ecb.cipher_text[0], sizeof(ecb.cipher_text));
62 }
63
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)64 void ecb_encrypt(uint8_t const *const key_le, uint8_t const *const clear_text_le,
65 uint8_t * const cipher_text_le, uint8_t * const cipher_text_be)
66 {
67 struct ecb_param ecb;
68
69 mem_rcopy(&ecb.key[0], key_le, sizeof(ecb.key));
70 mem_rcopy(&ecb.clear_text[0], clear_text_le, sizeof(ecb.clear_text));
71
72 do_ecb(&ecb);
73
74 if (cipher_text_le) {
75 mem_rcopy(cipher_text_le, &ecb.cipher_text[0],
76 sizeof(ecb.cipher_text));
77 }
78
79 if (cipher_text_be) {
80 memcpy(cipher_text_be, &ecb.cipher_text[0],
81 sizeof(ecb.cipher_text));
82 }
83 }
84
ecb_encrypt_nonblocking(struct ecb * ecb)85 uint32_t ecb_encrypt_nonblocking(struct ecb *ecb)
86 {
87 /* prepare to be used in a BE AES h/w */
88 if (ecb->in_key_le) {
89 mem_rcopy(&ecb->in_key_be[0], ecb->in_key_le,
90 sizeof(ecb->in_key_be));
91 }
92 if (ecb->in_clear_text_le) {
93 mem_rcopy(&ecb->in_clear_text_be[0],
94 ecb->in_clear_text_le,
95 sizeof(ecb->in_clear_text_be));
96 }
97
98 /* setup the encryption h/w */
99 NRF_ECB->ECBDATAPTR = (uint32_t)ecb;
100 NRF_ECB->EVENTS_ENDECB = 0;
101 NRF_ECB->EVENTS_ERRORECB = 0;
102 nrf_ecb_int_enable(NRF_ECB, ECB_INTENSET_ERRORECB_Msk
103 | ECB_INTENSET_ENDECB_Msk);
104
105 /* enable interrupt */
106 NVIC_ClearPendingIRQ(ECB_IRQn);
107 irq_enable(ECB_IRQn);
108
109 /* start the encryption h/w */
110 nrf_ecb_task_trigger(NRF_ECB, NRF_ECB_TASK_STARTECB);
111
112 return 0;
113 }
114
ecb_cleanup(void)115 static void ecb_cleanup(void)
116 {
117 /* stop h/w */
118 NRF_ECB->TASKS_STOPECB = 1;
119 nrf_ecb_task_trigger(NRF_ECB, NRF_ECB_TASK_STOPECB);
120
121 /* cleanup interrupt */
122 irq_disable(ECB_IRQn);
123 }
124
isr_ecb(void * param)125 void isr_ecb(void *param)
126 {
127 ARG_UNUSED(param);
128
129 if (NRF_ECB->EVENTS_ERRORECB) {
130 struct ecb *ecb = (struct ecb *)NRF_ECB->ECBDATAPTR;
131
132 ecb_cleanup();
133
134 ecb->fp_ecb(1, NULL, ecb->context);
135 }
136
137 else if (NRF_ECB->EVENTS_ENDECB) {
138 struct ecb *ecb = (struct ecb *)NRF_ECB->ECBDATAPTR;
139
140 ecb_cleanup();
141
142 ecb->fp_ecb(0, &ecb->out_cipher_text_be[0],
143 ecb->context);
144 }
145
146 else {
147 LL_ASSERT(0);
148 }
149 }
150
151 struct ecb_ut_context {
152 uint32_t volatile done;
153 uint32_t status;
154 uint8_t cipher_text[16];
155 };
156
ecb_cb(uint32_t status,uint8_t * cipher_be,void * context)157 static void ecb_cb(uint32_t status, uint8_t *cipher_be, void *context)
158 {
159 struct ecb_ut_context *ecb_ut_context =
160 (struct ecb_ut_context *)context;
161
162 ecb_ut_context->done = 1U;
163 ecb_ut_context->status = status;
164 if (!status) {
165 mem_rcopy(ecb_ut_context->cipher_text, cipher_be,
166 sizeof(ecb_ut_context->cipher_text));
167 }
168 }
169
ecb_ut(void)170 uint32_t ecb_ut(void)
171 {
172 uint8_t key[16] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88,
173 0x99, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 };
174 uint8_t clear_text[16] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
175 0x88, 0x99, 0x00, 0x11, 0x22, 0x33, 0x44,
176 0x55 };
177 uint8_t cipher_text[16];
178 uint32_t status = 0U;
179 struct ecb ecb;
180 struct ecb_ut_context context;
181
182 ecb_encrypt(key, clear_text, cipher_text, NULL);
183
184 context.done = 0U;
185 ecb.in_key_le = key;
186 ecb.in_clear_text_le = clear_text;
187 ecb.fp_ecb = ecb_cb;
188 ecb.context = &context;
189 status = ecb_encrypt_nonblocking(&ecb);
190 do {
191 cpu_sleep();
192 } while (!context.done);
193
194 if (context.status != 0U) {
195 return context.status;
196 }
197
198 status = memcmp(cipher_text, context.cipher_text, sizeof(cipher_text));
199 if (status) {
200 return status;
201 }
202
203 return status;
204 }
205