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