1 /*
2  * Copyright (c) 2016-2024 Nordic Semiconductor ASA
3  * Copyright (c) 2016 Vinayak Kariappa Chettimada
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #include <stdint.h>
9 #include <string.h>
10 
11 #include <zephyr/sys/byteorder.h>
12 
13 #include <hal/nrf_ecb.h>
14 
15 #include "util/mem.h"
16 
17 #include "hal/cpu.h"
18 #include "hal/ecb.h"
19 
20 #include "hal/debug.h"
21 
22 #if defined(NRF54L_SERIES)
23 #define NRF_ECB                   NRF_ECB00
24 #define ECB_IRQn                  ECB00_IRQn
25 #define ECB_INTENSET_ERRORECB_Msk ECB_INTENSET_ERROR_Msk
26 #define ECB_INTENSET_ENDECB_Msk   ECB_INTENSET_END_Msk
27 #define TASKS_STARTECB            TASKS_START
28 #define TASKS_STOPECB             TASKS_STOP
29 #define EVENTS_ENDECB             EVENTS_END
30 #define EVENTS_ERRORECB           EVENTS_ERROR
31 #define NRF_ECB_TASK_STARTECB     NRF_ECB_TASK_START
32 #define NRF_ECB_TASK_STOPECB      NRF_ECB_TASK_STOP
33 #define ECBDATAPTR                IN.PTR
34 
35 struct ecb_job_ptr {
36 	void *ptr;
37 	struct {
38 		uint32_t length:24;
39 		uint32_t attribute:8;
40 	} __packed;
41 } __packed;
42 
43 /* Product Specification recommends a value of 11, but prior work had used 7 */
44 #define ECB_JOB_PTR_ATTRIBUTE 7U
45 #endif /* NRF54L_SERIES */
46 
47 struct ecb_param {
48 	uint8_t key[16];
49 	uint8_t clear_text[16];
50 	uint8_t cipher_text[16];
51 
52 #if defined(NRF54L_SERIES)
53 	struct ecb_job_ptr in[2];
54 	struct ecb_job_ptr out[2];
55 #endif /* NRF54L_SERIES */
56 } __packed;
57 
do_ecb(struct ecb_param * ep)58 static void do_ecb(struct ecb_param *ep)
59 {
60 	do {
61 		nrf_ecb_task_trigger(NRF_ECB, NRF_ECB_TASK_STOPECB);
62 
63 #if defined(NRF54L_SERIES)
64 		NRF_ECB->KEY.VALUE[3] = sys_get_be32(&ep->key[0]);
65 		NRF_ECB->KEY.VALUE[2] = sys_get_be32(&ep->key[4]);
66 		NRF_ECB->KEY.VALUE[1] = sys_get_be32(&ep->key[8]);
67 		NRF_ECB->KEY.VALUE[0] = sys_get_be32(&ep->key[12]);
68 
69 		ep->in[0].ptr = ep->clear_text;
70 		ep->in[0].length = sizeof(ep->clear_text);
71 		ep->in[0].attribute = ECB_JOB_PTR_ATTRIBUTE;
72 		ep->in[1].ptr = NULL;
73 		ep->in[1].length = 0U;
74 		ep->in[1].attribute = 0U;
75 
76 		ep->out[0].ptr = ep->cipher_text;
77 		ep->out[0].length = sizeof(ep->cipher_text);
78 		ep->out[0].attribute = ECB_JOB_PTR_ATTRIBUTE;
79 		ep->out[1].ptr = NULL;
80 		ep->out[1].length = 0U;
81 		ep->out[1].attribute = 0U;
82 
83 		NRF_ECB->IN.PTR = (uint32_t)ep->in;
84 		NRF_ECB->OUT.PTR = (uint32_t)ep->out;
85 #else /* !NRF54L_SERIES */
86 		NRF_ECB->ECBDATAPTR = (uint32_t)ep;
87 #endif /* !NRF54L_SERIES */
88 
89 		NRF_ECB->EVENTS_ENDECB = 0;
90 		NRF_ECB->EVENTS_ERRORECB = 0;
91 		nrf_ecb_task_trigger(NRF_ECB, NRF_ECB_TASK_STARTECB);
92 		while ((NRF_ECB->EVENTS_ENDECB == 0) &&
93 		       (NRF_ECB->EVENTS_ERRORECB == 0) &&
94 		       (NRF_ECB->ECBDATAPTR != 0)) {
95 #if defined(CONFIG_SOC_SERIES_BSIM_NRFXX)
96 			k_busy_wait(10);
97 #else
98 			/* FIXME: use cpu_sleep(), but that will need interrupt
99 			 *        wake up source and hence necessary appropriate
100 			 *        code.
101 			 */
102 #endif
103 		}
104 		nrf_ecb_task_trigger(NRF_ECB, NRF_ECB_TASK_STOPECB);
105 	} while ((NRF_ECB->EVENTS_ERRORECB != 0) || (NRF_ECB->ECBDATAPTR == 0));
106 
107 	NRF_ECB->ECBDATAPTR = 0;
108 }
109 
ecb_encrypt_be(uint8_t const * const key_be,uint8_t const * const clear_text_be,uint8_t * const cipher_text_be)110 void ecb_encrypt_be(uint8_t const *const key_be, uint8_t const *const clear_text_be,
111 		    uint8_t * const cipher_text_be)
112 {
113 	struct ecb_param ecb;
114 
115 	memcpy(&ecb.key[0], key_be, sizeof(ecb.key));
116 	memcpy(&ecb.clear_text[0], clear_text_be, sizeof(ecb.clear_text));
117 
118 	do_ecb(&ecb);
119 
120 	memcpy(cipher_text_be, &ecb.cipher_text[0], sizeof(ecb.cipher_text));
121 }
122 
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)123 void ecb_encrypt(uint8_t const *const key_le, uint8_t const *const clear_text_le,
124 		 uint8_t * const cipher_text_le, uint8_t * const cipher_text_be)
125 {
126 	struct ecb_param ecb;
127 
128 	mem_rcopy(&ecb.key[0], key_le, sizeof(ecb.key));
129 	mem_rcopy(&ecb.clear_text[0], clear_text_le, sizeof(ecb.clear_text));
130 
131 	do_ecb(&ecb);
132 
133 	if (cipher_text_le) {
134 		mem_rcopy(cipher_text_le, &ecb.cipher_text[0],
135 			  sizeof(ecb.cipher_text));
136 	}
137 
138 	if (cipher_text_be) {
139 		memcpy(cipher_text_be, &ecb.cipher_text[0],
140 			 sizeof(ecb.cipher_text));
141 	}
142 }
143 
ecb_encrypt_nonblocking(struct ecb * e)144 void ecb_encrypt_nonblocking(struct ecb *e)
145 {
146 	/* prepare to be used in a BE AES h/w */
147 	if (e->in_key_le) {
148 		mem_rcopy(&e->in_key_be[0], e->in_key_le, sizeof(e->in_key_be));
149 	}
150 	if (e->in_clear_text_le) {
151 		mem_rcopy(&e->in_clear_text_be[0], e->in_clear_text_le,
152 			  sizeof(e->in_clear_text_be));
153 	}
154 
155 	/* setup the encryption h/w */
156 #if defined(NRF54L_SERIES)
157 	NRF_ECB->KEY.VALUE[3] = sys_get_be32(&e->in_key_be[0]);
158 	NRF_ECB->KEY.VALUE[2] = sys_get_be32(&e->in_key_be[4]);
159 	NRF_ECB->KEY.VALUE[1] = sys_get_be32(&e->in_key_be[8]);
160 	NRF_ECB->KEY.VALUE[0] = sys_get_be32(&e->in_key_be[12]);
161 
162 	struct ecb_job_ptr *in = (void *)((uint8_t *)e + sizeof(*e));
163 	struct ecb_job_ptr *out = (void *)((uint8_t *)in + 16U);
164 
165 	in[0].ptr = e->in_clear_text_be;
166 	in[0].length = sizeof(e->in_clear_text_be);
167 	in[0].attribute = ECB_JOB_PTR_ATTRIBUTE;
168 	in[1].ptr = NULL;
169 	in[1].length = 0U;
170 	in[1].attribute = 0U;
171 
172 	out[0].ptr = e->out_cipher_text_be;
173 	out[0].length = sizeof(e->out_cipher_text_be);
174 	out[0].attribute = ECB_JOB_PTR_ATTRIBUTE;
175 	out[1].ptr = NULL;
176 	out[1].length = 0U;
177 	out[1].attribute = 0U;
178 
179 	NRF_ECB->IN.PTR = (uint32_t)in;
180 	NRF_ECB->OUT.PTR = (uint32_t)out;
181 #else /* !NRF54L_SERIES */
182 	NRF_ECB->ECBDATAPTR = (uint32_t)e;
183 #endif /* !NRF54L_SERIES */
184 	NRF_ECB->EVENTS_ENDECB = 0;
185 	NRF_ECB->EVENTS_ERRORECB = 0;
186 	nrf_ecb_int_enable(NRF_ECB, ECB_INTENSET_ERRORECB_Msk
187 				    | ECB_INTENSET_ENDECB_Msk);
188 
189 	/* enable interrupt */
190 	NVIC_ClearPendingIRQ(ECB_IRQn);
191 	irq_enable(ECB_IRQn);
192 
193 	/* start the encryption h/w */
194 	nrf_ecb_task_trigger(NRF_ECB, NRF_ECB_TASK_STARTECB);
195 }
196 
isr_ecb(const void * arg)197 static void isr_ecb(const void *arg)
198 {
199 #if defined(NRF54L_SERIES)
200 	struct ecb *e = (void *)((uint8_t *)NRF_ECB->ECBDATAPTR -
201 				 sizeof(struct ecb));
202 #else /* !NRF54L_SERIES */
203 	struct ecb *e = (void *)NRF_ECB->ECBDATAPTR;
204 #endif /* !NRF54L_SERIES */
205 
206 	ARG_UNUSED(arg);
207 
208 	/* Stop ECB h/w */
209 	nrf_ecb_task_trigger(NRF_ECB, NRF_ECB_TASK_STOPECB);
210 
211 	/* We are done or encountered error, disable interrupt */
212 	irq_disable(ECB_IRQn);
213 
214 	if (NRF_ECB->EVENTS_ERRORECB) {
215 		NRF_ECB->EVENTS_ERRORECB = 0U;
216 
217 		e->fp_ecb(1U, NULL, e->context);
218 	}
219 
220 	else if (NRF_ECB->EVENTS_ENDECB) {
221 		NRF_ECB->EVENTS_ENDECB = 0U;
222 
223 		e->fp_ecb(0U, &e->out_cipher_text_be[0],
224 			      e->context);
225 	}
226 
227 	else {
228 		LL_ASSERT(false);
229 	}
230 }
231 
232 struct ecb_ut_context {
233 	uint32_t volatile done;
234 	uint32_t status;
235 	uint8_t  cipher_text[16];
236 };
237 
ecb_cb(uint32_t status,uint8_t * cipher_be,void * context)238 static void ecb_cb(uint32_t status, uint8_t *cipher_be, void *context)
239 {
240 	struct ecb_ut_context *ecb_ut_context =
241 		(struct ecb_ut_context *)context;
242 
243 	ecb_ut_context->done = 1U;
244 	ecb_ut_context->status = status;
245 	if (!status) {
246 		mem_rcopy(ecb_ut_context->cipher_text, cipher_be,
247 			  sizeof(ecb_ut_context->cipher_text));
248 	}
249 }
250 
ecb_ut(void)251 int ecb_ut(void)
252 {
253 	uint8_t key[] = {
254 		0xbf, 0x01, 0xfb, 0x9d, 0x4e, 0xf3, 0xbc, 0x36,
255 		0xd8, 0x74, 0xf5, 0x39, 0x41, 0x38, 0x68, 0x4c
256 	};
257 	uint8_t clear_text[] = {
258 		0x13, 0x02, 0xf1, 0xe0, 0xdf, 0xce, 0xbd, 0xac,
259 		0x79, 0x68, 0x57, 0x46, 0x35, 0x24, 0x13, 0x02
260 	};
261 	uint8_t cipher_text_expected[] = {
262 		0x66, 0xc6, 0xc2, 0x27, 0x8e, 0x3b, 0x8e, 0x05,
263 		0x3e, 0x7e, 0xa3, 0x26, 0x52, 0x1b, 0xad, 0x99
264 	};
265 	uint8_t cipher_text_actual[16];
266 	int status;
267 
268 	(void)memset(cipher_text_actual, 0, sizeof(cipher_text_actual));
269 	ecb_encrypt(key, clear_text, cipher_text_actual, NULL);
270 
271 	status = memcmp(cipher_text_actual, cipher_text_expected,
272 			sizeof(cipher_text_actual));
273 	if (status) {
274 		return status;
275 	}
276 
277 #if defined(CONFIG_BT_CTLR_DYNAMIC_INTERRUPTS)
278 	irq_connect_dynamic(ECB_IRQn, CONFIG_BT_CTLR_ULL_LOW_PRIO, isr_ecb, NULL, 0);
279 #else /* !CONFIG_BT_CTLR_DYNAMIC_INTERRUPTS */
280 	IRQ_CONNECT(ECB_IRQn, CONFIG_BT_CTLR_ULL_LOW_PRIO, isr_ecb, NULL, 0);
281 #endif /* !CONFIG_BT_CTLR_DYNAMIC_INTERRUPTS */
282 
283 	uint8_t ecb_mem[sizeof(struct ecb) + 32U];
284 	struct ecb *e = (void *)ecb_mem;
285 	struct ecb_ut_context context;
286 
287 	(void)memset(&context, 0, sizeof(context));
288 	e->in_key_le = key;
289 	e->in_clear_text_le = clear_text;
290 	e->fp_ecb = ecb_cb;
291 	e->context = &context;
292 	ecb_encrypt_nonblocking(e);
293 	do {
294 #if defined(CONFIG_SOC_SERIES_BSIM_NRFXX)
295 		k_busy_wait(10);
296 #else
297 		cpu_sleep();
298 #endif
299 	} while (!context.done);
300 
301 	if (context.status != 0U) {
302 		return context.status;
303 	}
304 
305 	status = memcmp(cipher_text_expected, context.cipher_text,
306 			sizeof(cipher_text_expected));
307 	if (status) {
308 		return status;
309 	}
310 
311 	return status;
312 }
313