1 /******************************************************************************
2 *
3 * Copyright (C) 2022-2023 Maxim Integrated Products, Inc. (now owned by
4 * Analog Devices, Inc.),
5 * Copyright (C) 2023-2024 Analog Devices, Inc.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 ******************************************************************************/
20
21 #include <stdlib.h>
22 #include <string.h>
23
24 #include "mxc_sys.h"
25 #include "mxc_device.h"
26 #include "mxc_errors.h"
27 #include "mxc_assert.h"
28 #include "mxc_lock.h"
29
30 #include "ctb.h"
31 #include "ctb_reva.h"
32 #include "ctb_common.h"
33
34 #if (TARGET_NUM != 32572)
35 #include "icc_reva.h"
36 #endif
37
38 enum { DMA_ID, HSH_ID, CPH_ID, MAA_ID, RNG_ID, NUM_IDS };
39
40 typedef enum {
41 DMA_CALLBACK_DISABLED = 0,
42 DMA_CALLBACK_ECC_Compute = 1,
43 DMA_CALLBACK_ECC_Error = 2,
44 DMA_CALLBACK_CRC = 3
45 } mxc_ctb_reva_dma_callback_t;
46
47 /***** Global Variables *****/
48
49 static void *saved_requests[NUM_IDS];
50 static mxc_ctb_reva_complete_cb_t MXC_CTB_Callbacks[NUM_IDS];
51
52 static mxc_ctb_reva_dma_callback_t dma_cb_func;
53
54 static int async_dataLength, async_numBlocks, async_i, async_blockSize, async_lastBlockSize;
55 static uint32_t TRNG_count, TRNG_maxLength;
56 static uint8_t *TRNG_data;
57
58 static uint32_t enabled_features = 0;
59
60 static uint32_t crc_seed = 0xFFFFFFFF;
61 static uint32_t crc_xor = 0;
62
63 /***** Function Prototypes *****/
64
65 static int MXC_CTB_ECC_Compare(mxc_ctb_ecc_req_t *req);
66 static void MXC_CTB_Hash_SendBlock(mxc_ctb_hash_req_t *req);
67 static int MXC_CTB_Cipher_EncDecAsc(mxc_ctb_cipher_req_t *req);
68
69 /* ************************************************************************* */
70 /* Global Control/Configuration functions */
71 /* ************************************************************************* */
72
MXC_CTB_RevA_Init(mxc_ctb_reva_regs_t * ctb_regs,uint32_t features)73 int MXC_CTB_RevA_Init(mxc_ctb_reva_regs_t *ctb_regs, uint32_t features)
74 {
75 ctb_regs->ctrl = MXC_F_CTB_REVA_CTRL_RST;
76 while (ctb_regs->ctrl & MXC_F_CTB_REVA_CTRL_RST) {}
77
78 ctb_regs->ctrl |= MXC_F_CTB_REVA_CTRL_FLAG_MODE;
79
80 enabled_features |= features;
81
82 if (features & MXC_CTB_REVA_FEATURE_DMA) {
83 MXC_FreeLock((void *)&MXC_CTB_Callbacks[DMA_ID]);
84 dma_cb_func = DMA_CALLBACK_DISABLED;
85 }
86
87 if (features & MXC_CTB_REVA_FEATURE_CRC) {
88 ctb_regs->crc_ctrl |= MXC_F_CTB_REVA_CRC_CTRL_CRC;
89 }
90
91 if (features & MXC_CTB_REVA_FEATURE_HASH) {
92 MXC_FreeLock((void *)&MXC_CTB_Callbacks[HSH_ID]);
93 } else if (!(enabled_features & MXC_CTB_REVA_FEATURE_HASH)) {
94 // Hash has not been initialized previously and is
95 // not initialized in this call to MXC_CTB_Init,
96 // clear hash_ctrl reg.
97 ctb_regs->hash_ctrl = 0;
98 }
99
100 if (features & MXC_CTB_REVA_FEATURE_CIPHER) {
101 MXC_FreeLock((void *)&MXC_CTB_Callbacks[CPH_ID]);
102 }
103
104 if (features & MXC_CTB_REVA_FEATURE_TRNG) {
105 MXC_FreeLock((void *)&MXC_CTB_Callbacks[RNG_ID]);
106 }
107
108 // Clear done flags
109 MXC_CTB_DoneClear(features);
110
111 return E_NO_ERROR;
112 }
113
MXC_CTB_CheckInterrupts(void)114 static int MXC_CTB_CheckInterrupts(void)
115 {
116 return ((mxc_ctb_reva_regs_t *)MXC_CTB)->ctrl & MXC_F_CTB_REVA_CTRL_INTR;
117 }
118
MXC_CTB_RevA_EnableInt(mxc_ctb_reva_regs_t * ctb_regs)119 void MXC_CTB_RevA_EnableInt(mxc_ctb_reva_regs_t *ctb_regs)
120 {
121 // Clear pending interrupts
122 MXC_CTB_DoneClear(MXC_CTB_REVA_FEATURE_DMA | MXC_CTB_REVA_FEATURE_ECC |
123 MXC_CTB_REVA_FEATURE_HASH | MXC_CTB_REVA_FEATURE_CRC |
124 MXC_CTB_REVA_FEATURE_CIPHER);
125
126 // Enable device interrupts
127 ctb_regs->ctrl |= MXC_F_CTB_REVA_CTRL_INTR;
128
129 // Enable IRQ
130 #ifndef __riscv
131 NVIC_EnableIRQ(CRYPTO_IRQn);
132 #endif
133 }
134
MXC_CTB_RevA_DisableInt(mxc_ctb_reva_regs_t * ctb_regs)135 void MXC_CTB_RevA_DisableInt(mxc_ctb_reva_regs_t *ctb_regs)
136 {
137 // Disable IRQ
138 #ifndef __riscv
139 NVIC_DisableIRQ(CRYPTO_IRQn);
140 #endif
141
142 // Disable device interrupts
143 ctb_regs->ctrl &= ~MXC_F_CTB_REVA_CTRL_INTR;
144 }
145
MXC_CTB_RevA_Ready(mxc_ctb_reva_regs_t * ctb_regs)146 int MXC_CTB_RevA_Ready(mxc_ctb_reva_regs_t *ctb_regs)
147 {
148 return !!(ctb_regs->ctrl & MXC_F_CTB_REVA_CTRL_RDY);
149 }
150
MXC_CTB_RevA_DoneClear(mxc_ctb_reva_regs_t * ctb_regs,uint32_t features)151 void MXC_CTB_RevA_DoneClear(mxc_ctb_reva_regs_t *ctb_regs, uint32_t features)
152 {
153 uint32_t mask = 0;
154 uint32_t w1c = (MXC_F_CTB_REVA_CTRL_HSH_DONE | MXC_F_CTB_REVA_CTRL_CPH_DONE |
155 MXC_F_CTB_REVA_CTRL_GLS_DONE);
156
157 if (features & MXC_CTB_REVA_FEATURE_DMA) {
158 mask |= MXC_F_CTB_REVA_CTRL_DMA_DONE;
159 mask |= MXC_F_CTB_REVA_CTRL_GLS_DONE;
160 }
161
162 if (features & MXC_CTB_REVA_FEATURE_HASH) {
163 mask |= MXC_F_CTB_REVA_CTRL_HSH_DONE;
164 }
165
166 if (features & MXC_CTB_REVA_FEATURE_CIPHER) {
167 mask |= MXC_F_CTB_REVA_CTRL_CPH_DONE;
168 }
169
170 ctb_regs->ctrl = (ctb_regs->ctrl & ~w1c) | mask;
171 }
172
MXC_CTB_RevA_Done(mxc_ctb_reva_regs_t * ctb_regs)173 uint32_t MXC_CTB_RevA_Done(mxc_ctb_reva_regs_t *ctb_regs)
174 {
175 uint32_t features = 0;
176
177 if (ctb_regs->ctrl & MXC_F_CTB_REVA_CTRL_DMA_DONE) {
178 features |= MXC_CTB_REVA_FEATURE_DMA;
179 }
180
181 if (ctb_regs->ctrl & MXC_F_CTB_REVA_CTRL_HSH_DONE) {
182 if (ctb_regs->hash_ctrl) { // set flag if only configured
183 features |= MXC_CTB_REVA_FEATURE_HASH;
184 }
185 }
186
187 if (ctb_regs->ctrl & MXC_F_CTB_REVA_CTRL_CPH_DONE) {
188 if (ctb_regs->cipher_ctrl) { // set flag if only configured
189 features |= MXC_CTB_REVA_FEATURE_CIPHER;
190 }
191 }
192
193 return features;
194 }
195
MXC_CTB_RevA_Reset(uint32_t features)196 void MXC_CTB_RevA_Reset(uint32_t features)
197 {
198 MXC_CTB_Shutdown(features);
199 MXC_CTB_Init(features);
200 }
201
202 #if (TARGET_NUM != 32572)
MXC_CTB_RevA_CacheInvalidate(void)203 void MXC_CTB_RevA_CacheInvalidate(void)
204 {
205 // Write non-zero value to invalidate
206 ((mxc_icc_reva_regs_t *)MXC_ICC)->invalidate = 1;
207
208 // Wait for completion of invalidation
209 while ((((mxc_icc_reva_regs_t *)MXC_ICC)->ctrl & MXC_F_ICC_REVA_CTRL_RDY) == 0) {}
210 }
211 #endif
212
MXC_CTB_RevA_Shutdown(uint32_t features)213 int MXC_CTB_RevA_Shutdown(uint32_t features)
214 {
215 enabled_features &= ~features;
216
217 if (features & MXC_CTB_REVA_FEATURE_CIPHER) {
218 MXC_CTB_RevA_Cipher_SetCipher((mxc_ctb_reva_regs_t *)MXC_CTB, MXC_CTB_REVA_CIPHER_DIS);
219 }
220
221 if (features & MXC_CTB_REVA_FEATURE_HASH) {
222 MXC_CTB_RevA_Hash_SetFunction((mxc_ctb_reva_regs_t *)MXC_CTB, MXC_CTB_REVA_HASH_DIS);
223 }
224
225 if (features & MXC_CTB_REVA_FEATURE_DMA) {
226 dma_cb_func = DMA_CALLBACK_DISABLED;
227 }
228
229 return E_NO_ERROR;
230 }
231
MXC_CTB_RevA_GetEnabledFeatures(void)232 uint32_t MXC_CTB_RevA_GetEnabledFeatures(void)
233 {
234 return enabled_features;
235 }
236
MXC_CTB_RevA_Handler(mxc_trng_reva_regs_t * trng)237 void MXC_CTB_RevA_Handler(mxc_trng_reva_regs_t *trng)
238 {
239 void *req;
240 uint32_t temp;
241 mxc_ctb_reva_complete_cb_t cb;
242
243 uint32_t features = MXC_CTB_Done();
244
245 if (features & MXC_CTB_REVA_FEATURE_HASH) {
246 req = saved_requests[HSH_ID];
247 MXC_CTB_DoneClear(MXC_CTB_REVA_FEATURE_HASH | MXC_CTB_REVA_FEATURE_DMA |
248 MXC_CTB_REVA_FEATURE_CIPHER);
249 features &= ~(MXC_CTB_REVA_FEATURE_HASH | MXC_CTB_REVA_FEATURE_CIPHER);
250
251 async_i++;
252
253 if (async_i != async_numBlocks) {
254 MXC_CTB_Hash_SendBlock((mxc_ctb_hash_req_t *)req);
255 } else {
256 MXC_CTB_Hash_GetResult(((mxc_ctb_hash_req_t *)req)->hash, (int *)&temp);
257 cb = MXC_CTB_Callbacks[HSH_ID];
258 MXC_FreeLock((void *)&MXC_CTB_Callbacks[HSH_ID]);
259 cb(req, 0);
260 }
261 }
262
263 if (features & MXC_CTB_REVA_FEATURE_CIPHER) {
264 req = saved_requests[CPH_ID];
265 MXC_CTB_DoneClear(MXC_CTB_REVA_FEATURE_CIPHER | MXC_CTB_REVA_FEATURE_DMA);
266 features &= ~MXC_CTB_REVA_FEATURE_CIPHER;
267
268 if (MXC_CTB_Cipher_EncDecAsc(req)) {
269 cb = MXC_CTB_Callbacks[CPH_ID];
270 MXC_FreeLock((void *)&MXC_CTB_Callbacks[CPH_ID]);
271 cb(req, 0);
272 }
273 }
274
275 if (features & MXC_CTB_REVA_FEATURE_DMA) {
276 req = saved_requests[DMA_ID];
277 MXC_CTB_DoneClear(MXC_CTB_REVA_FEATURE_DMA);
278
279 switch (dma_cb_func) {
280 case DMA_CALLBACK_ECC_Compute:
281 ((mxc_ctb_reva_ecc_req_t *)req)->checksum = MXC_CTB_ECC_GetResult();
282 cb = MXC_CTB_Callbacks[DMA_ID];
283 MXC_FreeLock((void *)&MXC_CTB_Callbacks[DMA_ID]);
284 cb(req, 0);
285 break;
286
287 case DMA_CALLBACK_ECC_Error:
288 temp = MXC_CTB_ECC_Compare((mxc_ctb_ecc_req_t *)req);
289 cb = MXC_CTB_Callbacks[DMA_ID];
290 MXC_FreeLock((void *)&MXC_CTB_Callbacks[DMA_ID]);
291 cb(req, temp);
292 break;
293
294 case DMA_CALLBACK_CRC:
295 ((mxc_ctb_reva_crc_req_t *)req)->resultCRC = MXC_CTB_CRC_GetResult();
296 cb = MXC_CTB_Callbacks[DMA_ID];
297 MXC_FreeLock((void *)&MXC_CTB_Callbacks[DMA_ID]);
298 cb(req, 0);
299 break;
300
301 case DMA_CALLBACK_DISABLED:
302 // Another function is in progress, do nothing
303 break;
304 }
305 }
306
307 if ((features == 0) && MXC_CTB_Callbacks[RNG_ID]) { /* interrupt caused by TRNG */
308 // if this is last block, disable interrupt before reading MXC_TRNG->data
309 if (TRNG_maxLength <= TRNG_count + 4) {
310 trng->ctrl &= ~MXC_F_TRNG_REVA_CTRL_RND_IE;
311 }
312
313 temp = trng->data;
314
315 if ((TRNG_count + 3) < TRNG_maxLength) {
316 memcpy(&(TRNG_data[TRNG_count]), (uint8_t *)(&temp), 4);
317 TRNG_count += 4;
318 } else {
319 memcpy(&(TRNG_data[TRNG_count]), (uint8_t *)(&temp), TRNG_maxLength & 0x03);
320 TRNG_count += (TRNG_maxLength & 0x03);
321 }
322
323 if (TRNG_maxLength == TRNG_count) {
324 cb = MXC_CTB_Callbacks[RNG_ID];
325 MXC_FreeLock((void *)&MXC_CTB_Callbacks[RNG_ID]);
326 cb(0, 0);
327 }
328 }
329 }
330
331 /************************************/
332 /* CTB DMA - Used for all features */
333 /************************************/
334
MXC_CTB_RevA_DMA_SetReadSource(mxc_ctb_reva_regs_t * ctb_regs,mxc_ctb_reva_dma_read_source_t source)335 void MXC_CTB_RevA_DMA_SetReadSource(mxc_ctb_reva_regs_t *ctb_regs,
336 mxc_ctb_reva_dma_read_source_t source)
337 {
338 MXC_SETFIELD(ctb_regs->ctrl, MXC_F_CTB_REVA_CTRL_RDSRC,
339 source << MXC_F_CTB_REVA_CTRL_RDSRC_POS);
340 }
341
MXC_CTB_RevA_DMA_GetReadSource(mxc_ctb_reva_regs_t * ctb_regs)342 mxc_ctb_reva_dma_read_source_t MXC_CTB_RevA_DMA_GetReadSource(mxc_ctb_reva_regs_t *ctb_regs)
343 {
344 return (mxc_ctb_reva_dma_read_source_t)((ctb_regs->ctrl & MXC_F_CTB_REVA_CTRL_RDSRC) >>
345 MXC_F_CTB_REVA_CTRL_RDSRC_POS);
346 }
347
MXC_CTB_RevA_DMA_SetWriteSource(mxc_ctb_reva_regs_t * ctb_regs,mxc_ctb_reva_dma_write_source_t source)348 void MXC_CTB_RevA_DMA_SetWriteSource(mxc_ctb_reva_regs_t *ctb_regs,
349 mxc_ctb_reva_dma_write_source_t source)
350 {
351 MXC_SETFIELD(ctb_regs->ctrl, MXC_F_CTB_REVA_CTRL_WRSRC,
352 source << MXC_F_CTB_REVA_CTRL_WRSRC_POS);
353 }
354
MXC_CTB_RevA_DMA_GetWriteSource(mxc_ctb_reva_regs_t * ctb_regs)355 mxc_ctb_reva_dma_write_source_t MXC_CTB_RevA_DMA_GetWriteSource(mxc_ctb_reva_regs_t *ctb_regs)
356 {
357 return (mxc_ctb_reva_dma_write_source_t)((ctb_regs->ctrl & MXC_F_CTB_REVA_CTRL_WRSRC) >>
358 MXC_F_CTB_REVA_CTRL_WRSRC_POS);
359 }
360
MXC_CTB_RevA_DMA_SetSource(mxc_ctb_reva_regs_t * ctb_regs,uint8_t * source)361 void MXC_CTB_RevA_DMA_SetSource(mxc_ctb_reva_regs_t *ctb_regs, uint8_t *source)
362 {
363 ctb_regs->dma_src = (uint32_t)source;
364 }
365
MXC_CTB_RevA_DMA_SetDestination(mxc_ctb_reva_regs_t * ctb_regs,uint8_t * dest)366 void MXC_CTB_RevA_DMA_SetDestination(mxc_ctb_reva_regs_t *ctb_regs, uint8_t *dest)
367 {
368 ctb_regs->dma_dest = (uint32_t)dest;
369 }
370
MXC_CTB_RevA_DMA_StartTransfer(mxc_ctb_reva_regs_t * ctb_regs,uint32_t length)371 void MXC_CTB_RevA_DMA_StartTransfer(mxc_ctb_reva_regs_t *ctb_regs, uint32_t length)
372 {
373 ctb_regs->dma_cnt = length;
374 }
375
MXC_CTB_RevA_DMA_SetupOperation(mxc_ctb_reva_dma_req_t * req)376 int MXC_CTB_RevA_DMA_SetupOperation(mxc_ctb_reva_dma_req_t *req)
377 {
378 if (req == NULL) {
379 return E_NULL_PTR;
380 }
381
382 MXC_CTB_DMA_SetReadSource((mxc_ctb_dma_read_source_t)MXC_CTB_REVA_DMA_READ_FIFO_DMA);
383
384 if (req->destBuffer == NULL) {
385 MXC_CTB_DMA_SetWriteSource((mxc_ctb_dma_write_source_t)MXC_CTB_REVA_DMA_WRITE_FIFO_NONE);
386 } else {
387 MXC_CTB_DMA_SetWriteSource((mxc_ctb_dma_write_source_t)MXC_CTB_REVA_DMA_WRITE_FIFO_CIPHER);
388 }
389
390 MXC_CTB_DMA_SetSource(req->sourceBuffer);
391 MXC_CTB_DMA_SetDestination(req->destBuffer);
392
393 return E_NO_ERROR;
394 }
395
MXC_CTB_RevA_DMA_DoOperation(mxc_ctb_reva_dma_req_t * req)396 int MXC_CTB_RevA_DMA_DoOperation(mxc_ctb_reva_dma_req_t *req)
397 {
398 if (req == NULL) {
399 return E_NULL_PTR;
400 }
401
402 MXC_CTB_DMA_SetupOperation((mxc_ctb_dma_req_t *)req);
403
404 MXC_CTB_DMA_StartTransfer(req->length);
405
406 while (!(MXC_CTB_Done() & MXC_CTB_REVA_FEATURE_DMA)) {}
407
408 MXC_CTB_DoneClear(MXC_CTB_REVA_FEATURE_DMA);
409
410 return E_NO_ERROR;
411 }
412
413 /* ************************************************************************* */
414 /* True Random Number Generator(TRNG) functions */
415 /* ************************************************************************* */
416
MXC_CTB_RevA_TRNG_RandomInt(mxc_trng_reva_regs_t * trng)417 int MXC_CTB_RevA_TRNG_RandomInt(mxc_trng_reva_regs_t *trng)
418 {
419 while (!(trng->status & MXC_F_TRNG_REVA_STATUS_RDY)) {}
420
421 return (int)trng->data;
422 }
423
MXC_CTB_RevA_TRNG_Random(uint8_t * data,uint32_t len)424 int MXC_CTB_RevA_TRNG_Random(uint8_t *data, uint32_t len)
425 {
426 unsigned int i, temp;
427
428 if (data == NULL) {
429 return E_NULL_PTR;
430 }
431
432 for (i = 0; i + 3 < len; i += 4) {
433 temp = MXC_CTB_TRNG_RandomInt();
434 memcpy(&(data[i]), (uint8_t *)(&temp), 4);
435 }
436
437 if (len & 0x03) {
438 temp = MXC_CTB_TRNG_RandomInt();
439 memcpy(&(data[i]), (uint8_t *)(&temp), len & 0x03);
440 }
441
442 return E_NO_ERROR;
443 }
444
MXC_CTB_RevA_TRNG_RandomAsync(mxc_trng_reva_regs_t * trng,uint8_t * data,uint32_t len,mxc_ctb_reva_complete_cb_t callback)445 void MXC_CTB_RevA_TRNG_RandomAsync(mxc_trng_reva_regs_t *trng, uint8_t *data, uint32_t len,
446 mxc_ctb_reva_complete_cb_t callback)
447 {
448 MXC_ASSERT(data && callback);
449
450 if (len == 0) {
451 return;
452 }
453
454 while (MXC_GetLock((void *)&MXC_CTB_Callbacks[RNG_ID], 1) != E_NO_ERROR) {}
455
456 #ifndef __riscv
457 NVIC_DisableIRQ(TRNG_IRQn);
458 #endif
459
460 TRNG_data = data;
461 TRNG_count = 0;
462 TRNG_maxLength = len;
463 MXC_CTB_Callbacks[RNG_ID] = callback;
464
465 // Enable interrupts
466 trng->ctrl |= MXC_F_TRNG_REVA_CTRL_RND_IE;
467
468 #ifndef __riscv
469 NVIC_EnableIRQ(TRNG_IRQn);
470 #endif
471 }
472
473 /* ************************************************************************* */
474 /* Error Correction Code(ECC) functions */
475 /* ************************************************************************* */
476
477 /*******************************/
478 /* Low Level Functions */
479 /*******************************/
480
MXC_CTB_RevA_ECC_Enable(mxc_ctb_reva_regs_t * ctb_regs)481 void MXC_CTB_RevA_ECC_Enable(mxc_ctb_reva_regs_t *ctb_regs)
482 {
483 ctb_regs->crc_ctrl |= MXC_F_CTB_REVA_CRC_CTRL_HRST;
484
485 while (ctb_regs->crc_ctrl & MXC_F_CTB_REVA_CRC_CTRL_HRST) {}
486
487 ctb_regs->crc_ctrl |= MXC_F_CTB_REVA_CRC_CTRL_HAM;
488 }
489
MXC_CTB_RevA_ECC_Disable(mxc_ctb_reva_regs_t * ctb_regs)490 void MXC_CTB_RevA_ECC_Disable(mxc_ctb_reva_regs_t *ctb_regs)
491 {
492 ctb_regs->crc_ctrl &= ~MXC_F_CTB_REVA_CRC_CTRL_HAM;
493 }
494
MXC_CTB_RevA_ECC_GetResult(mxc_ctb_reva_regs_t * ctb_regs)495 uint32_t MXC_CTB_RevA_ECC_GetResult(mxc_ctb_reva_regs_t *ctb_regs)
496 {
497 // Include bit 16 to aid error correction
498 return ctb_regs->ham_ecc;
499 }
500
501 /*******************************/
502 /* High Level Functions */
503 /*******************************/
504
MXC_CTB_ECC_Compare(mxc_ctb_ecc_req_t * req)505 static int MXC_CTB_ECC_Compare(mxc_ctb_ecc_req_t *req)
506 {
507 if (req == NULL) {
508 return E_NULL_PTR;
509 }
510
511 uint32_t new_ecc = MXC_CTB_ECC_GetResult();
512
513 uint32_t error = req->checksum ^ new_ecc;
514
515 if (error & (1 << 16)) {
516 // Correct single bit error
517 // Location of failing bit is NOT of XOR
518 uint16_t failing_bit_location = ~error;
519
520 int byte = failing_bit_location >> 3;
521 int bit = failing_bit_location & 0x7;
522
523 req->dataBuffer[byte] ^= (1 << bit);
524
525 return 1;
526
527 } else if (error) {
528 // Double bit error is not correctable with ECC
529 return 2;
530 }
531
532 return E_NO_ERROR;
533 }
534
MXC_CTB_ECC_Setup(mxc_ctb_ecc_req_t * req)535 static int MXC_CTB_ECC_Setup(mxc_ctb_ecc_req_t *req)
536 {
537 mxc_ctb_reva_dma_req_t dma_req;
538 int enabled;
539
540 if (req == NULL) {
541 return E_NULL_PTR;
542 }
543
544 if (req->dataBuffer == NULL) {
545 return E_NULL_PTR;
546 }
547
548 if (req->dataLen == 0) {
549 return E_BAD_PARAM;
550 }
551
552 enabled = MXC_CTB_CheckInterrupts();
553 MXC_CTB_DisableInt();
554
555 MXC_CTB_ECC_Enable();
556
557 dma_req.sourceBuffer = req->dataBuffer;
558 dma_req.length = req->dataLen;
559
560 MXC_CTB_DMA_DoOperation((mxc_ctb_dma_req_t *)&dma_req);
561
562 if (enabled) {
563 MXC_CTB_EnableInt();
564 }
565
566 return E_NO_ERROR;
567 }
568
MXC_CTB_RevA_ECC_Compute(mxc_ctb_reva_ecc_req_t * req)569 int MXC_CTB_RevA_ECC_Compute(mxc_ctb_reva_ecc_req_t *req)
570 {
571 uint32_t error = MXC_CTB_ECC_Setup((mxc_ctb_ecc_req_t *)req);
572
573 if (error != E_NO_ERROR) {
574 return error;
575 }
576
577 req->checksum = MXC_CTB_ECC_GetResult();
578 return E_NO_ERROR;
579 }
580
MXC_CTB_RevA_ECC_ErrorCheck(mxc_ctb_reva_ecc_req_t * req)581 int MXC_CTB_RevA_ECC_ErrorCheck(mxc_ctb_reva_ecc_req_t *req)
582 {
583 uint32_t error = MXC_CTB_ECC_Setup((mxc_ctb_ecc_req_t *)req);
584
585 if (error != E_NO_ERROR) {
586 return error;
587 }
588
589 return MXC_CTB_ECC_Compare((mxc_ctb_ecc_req_t *)req);
590 }
591
MXC_CTB_ECC_SetupAsync(mxc_ctb_ecc_req_t * req)592 static void MXC_CTB_ECC_SetupAsync(mxc_ctb_ecc_req_t *req)
593 {
594 mxc_ctb_reva_dma_req_t dma_req;
595
596 MXC_ASSERT(req);
597 MXC_ASSERT(req->callback && req->dataBuffer);
598
599 while (MXC_GetLock((void *)&MXC_CTB_Callbacks[DMA_ID], 1) != E_NO_ERROR) {}
600
601 MXC_CTB_DisableInt();
602
603 MXC_CTB_Callbacks[DMA_ID] = req->callback;
604 saved_requests[DMA_ID] = req;
605
606 dma_req.sourceBuffer = req->dataBuffer;
607
608 MXC_CTB_DMA_SetupOperation((mxc_ctb_dma_req_t *)&dma_req);
609
610 MXC_CTB_ECC_Enable();
611 MXC_CTB_EnableInt();
612 }
613
MXC_CTB_RevA_ECC_ComputeAsync(mxc_ctb_reva_ecc_req_t * req)614 void MXC_CTB_RevA_ECC_ComputeAsync(mxc_ctb_reva_ecc_req_t *req)
615 {
616 MXC_CTB_ECC_SetupAsync((mxc_ctb_ecc_req_t *)req);
617
618 dma_cb_func = DMA_CALLBACK_ECC_Compute;
619 MXC_CTB_DMA_StartTransfer(req->dataLen);
620 }
621
MXC_CTB_RevA_ECC_ErrorCheckAsync(mxc_ctb_reva_ecc_req_t * req)622 void MXC_CTB_RevA_ECC_ErrorCheckAsync(mxc_ctb_reva_ecc_req_t *req)
623 {
624 MXC_CTB_ECC_SetupAsync((mxc_ctb_ecc_req_t *)req);
625
626 dma_cb_func = DMA_CALLBACK_ECC_Error;
627 MXC_CTB_DMA_StartTransfer(req->dataLen);
628 }
629
630 /* ************************************************************************* */
631 /* Cyclic Redundancy Check(CRC) functions */
632 /* ************************************************************************* */
633
634 /*******************************/
635 /* Low Level Functions */
636 /*******************************/
637
MXC_CTB_RevA_CRC_SetDirection(mxc_ctb_reva_regs_t * ctb_regs,mxc_ctb_reva_crc_bitorder_t bitOrder)638 void MXC_CTB_RevA_CRC_SetDirection(mxc_ctb_reva_regs_t *ctb_regs,
639 mxc_ctb_reva_crc_bitorder_t bitOrder)
640 {
641 MXC_SETFIELD(ctb_regs->crc_ctrl, MXC_F_CTB_REVA_CRC_CTRL_MSB,
642 bitOrder << MXC_F_CTB_REVA_CRC_CTRL_MSB_POS);
643 }
644
MXC_CTB_RevA_CRC_GetDirection(mxc_ctb_reva_regs_t * ctb_regs)645 mxc_ctb_reva_crc_bitorder_t MXC_CTB_RevA_CRC_GetDirection(mxc_ctb_reva_regs_t *ctb_regs)
646 {
647 return (mxc_ctb_reva_crc_bitorder_t)((ctb_regs->crc_ctrl & MXC_F_CTB_REVA_CRC_CTRL_MSB) >>
648 MXC_F_CTB_REVA_CRC_CTRL_MSB_POS);
649 }
650
MXC_CTB_RevA_CRC_SetPoly(mxc_ctb_reva_regs_t * ctb_regs,uint32_t poly)651 void MXC_CTB_RevA_CRC_SetPoly(mxc_ctb_reva_regs_t *ctb_regs, uint32_t poly)
652 {
653 ctb_regs->crc_poly = poly;
654 }
655
MXC_CTB_RevA_CRC_GetPoly(mxc_ctb_reva_regs_t * ctb_regs)656 uint32_t MXC_CTB_RevA_CRC_GetPoly(mxc_ctb_reva_regs_t *ctb_regs)
657 {
658 return ctb_regs->crc_poly;
659 }
660
MXC_CTB_RevA_CRC_GetResult(mxc_ctb_reva_regs_t * ctb_regs)661 uint32_t MXC_CTB_RevA_CRC_GetResult(mxc_ctb_reva_regs_t *ctb_regs)
662 {
663 return ctb_regs->crc_val ^ crc_xor;
664 }
665
MXC_CTB_RevA_CRC_SetInitialValue(uint32_t seed)666 void MXC_CTB_RevA_CRC_SetInitialValue(uint32_t seed)
667 {
668 crc_seed = seed;
669 }
670
MXC_CTB_RevA_CRC_SetFinalXORValue(uint32_t xor)671 void MXC_CTB_RevA_CRC_SetFinalXORValue(uint32_t xor)
672 {
673 crc_xor = xor;
674 }
675
676 /*******************************/
677 /* High Level Functions */
678 /*******************************/
679
MXC_CTB_RevA_CRC_Compute(mxc_ctb_reva_regs_t * ctb_regs,mxc_ctb_reva_crc_req_t * req)680 int MXC_CTB_RevA_CRC_Compute(mxc_ctb_reva_regs_t *ctb_regs, mxc_ctb_reva_crc_req_t *req)
681 {
682 mxc_ctb_reva_dma_req_t dma_req;
683 int enabled;
684
685 if (req == NULL) {
686 return E_NULL_PTR;
687 }
688
689 enabled = MXC_CTB_CheckInterrupts();
690 MXC_CTB_DisableInt();
691
692 ctb_regs->crc_val = crc_seed; // Preset CRC value to all 1's
693
694 dma_req.sourceBuffer = req->dataBuffer;
695 dma_req.destBuffer = NULL;
696 dma_req.length = req->dataLen;
697
698 MXC_CTB_DMA_DoOperation((mxc_ctb_dma_req_t *)&dma_req);
699
700 // Store the crc value
701 req->resultCRC = MXC_CTB_CRC_GetResult();
702
703 if (enabled) {
704 MXC_CTB_EnableInt();
705 }
706
707 return E_SUCCESS;
708 }
709
MXC_CTB_RevA_CRC_ComputeAsync(mxc_ctb_reva_regs_t * ctb_regs,mxc_ctb_reva_crc_req_t * req)710 void MXC_CTB_RevA_CRC_ComputeAsync(mxc_ctb_reva_regs_t *ctb_regs, mxc_ctb_reva_crc_req_t *req)
711 {
712 mxc_ctb_reva_dma_req_t dma_req;
713
714 MXC_ASSERT(req);
715 MXC_ASSERT(req->callback);
716
717 while (MXC_GetLock((void *)&MXC_CTB_Callbacks[DMA_ID], 1) != E_NO_ERROR) {}
718
719 MXC_CTB_DisableInt();
720
721 MXC_CTB_Callbacks[DMA_ID] = req->callback;
722 saved_requests[DMA_ID] = req;
723 dma_cb_func = DMA_CALLBACK_CRC;
724
725 ctb_regs->crc_val = crc_seed; // Preset CRC value to all 1's
726
727 dma_req.sourceBuffer = req->dataBuffer;
728 dma_req.destBuffer = NULL;
729
730 MXC_CTB_DMA_SetupOperation((mxc_ctb_dma_req_t *)&dma_req);
731
732 MXC_CTB_EnableInt();
733
734 MXC_CTB_DMA_StartTransfer(req->dataLen);
735 }
736
737 /* ************************************************************************* */
738 /* Hash functions */
739 /* ************************************************************************* */
740
741 /***********************/
742 /* Low Level Functions */
743 /***********************/
744
MXC_CTB_RevA_Hash_SetFunction(mxc_ctb_reva_regs_t * ctb_regs,mxc_ctb_reva_hash_func_t function)745 void MXC_CTB_RevA_Hash_SetFunction(mxc_ctb_reva_regs_t *ctb_regs, mxc_ctb_reva_hash_func_t function)
746 {
747 MXC_SETFIELD(ctb_regs->hash_ctrl, MXC_F_CTB_REVA_HASH_CTRL_HASH,
748 function << MXC_F_CTB_REVA_HASH_CTRL_HASH_POS);
749 }
750
MXC_CTB_RevA_Hash_GetFunction(mxc_ctb_reva_regs_t * ctb_regs)751 mxc_ctb_reva_hash_func_t MXC_CTB_RevA_Hash_GetFunction(mxc_ctb_reva_regs_t *ctb_regs)
752 {
753 return (mxc_ctb_reva_hash_func_t)((ctb_regs->hash_ctrl & MXC_F_CTB_REVA_HASH_CTRL_HASH) >>
754 MXC_F_CTB_REVA_HASH_CTRL_HASH_POS);
755 }
756
MXC_CTB_RevA_Hash_SetAutoPad(mxc_ctb_reva_regs_t * ctb_regs,int pad)757 void MXC_CTB_RevA_Hash_SetAutoPad(mxc_ctb_reva_regs_t *ctb_regs, int pad)
758 {
759 MXC_SETFIELD(ctb_regs->hash_ctrl, MXC_F_CTB_REVA_HASH_CTRL_LAST,
760 (!!pad) << MXC_F_CTB_REVA_HASH_CTRL_LAST_POS);
761 }
762
MXC_CTB_RevA_Hash_GetAutoPad(mxc_ctb_reva_regs_t * ctb_regs)763 int MXC_CTB_RevA_Hash_GetAutoPad(mxc_ctb_reva_regs_t *ctb_regs)
764 {
765 return !!(ctb_regs->hash_ctrl & MXC_F_CTB_REVA_HASH_CTRL_LAST);
766 }
767
MXC_CTB_RevA_Hash_GetResult(mxc_ctb_reva_regs_t * ctb_regs,uint8_t * digest,int * len)768 void MXC_CTB_RevA_Hash_GetResult(mxc_ctb_reva_regs_t *ctb_regs, uint8_t *digest, int *len)
769 {
770 *len = MXC_CTB_Hash_GetDigestSize(MXC_CTB_Hash_GetFunction());
771 memcpy(digest, (uint8_t *)&ctb_regs->hash_digest[0], *len);
772 }
773
MXC_CTB_RevA_Hash_SetMessageSize(mxc_ctb_reva_regs_t * ctb_regs,uint32_t size)774 void MXC_CTB_RevA_Hash_SetMessageSize(mxc_ctb_reva_regs_t *ctb_regs, uint32_t size)
775 {
776 ctb_regs->hash_msg_sz[0] = size;
777 }
778
MXC_CTB_RevA_Hash_SetSource(mxc_ctb_reva_regs_t * ctb_regs,mxc_ctb_reva_hash_source_t source)779 void MXC_CTB_RevA_Hash_SetSource(mxc_ctb_reva_regs_t *ctb_regs, mxc_ctb_reva_hash_source_t source)
780 {
781 MXC_SETFIELD(ctb_regs->ctrl, MXC_F_CTB_REVA_CTRL_SRC,
782 (!!source) << MXC_F_CTB_REVA_CTRL_SRC_POS);
783 }
784
MXC_CTB_RevA_Hash_GetSource(mxc_ctb_reva_regs_t * ctb_regs)785 mxc_ctb_reva_hash_source_t MXC_CTB_RevA_Hash_GetSource(mxc_ctb_reva_regs_t *ctb_regs)
786 {
787 return (mxc_ctb_reva_hash_source_t)((ctb_regs->ctrl & MXC_F_CTB_REVA_CTRL_SRC) >>
788 MXC_F_CTB_REVA_CTRL_SRC_POS);
789 }
790
MXC_CTB_RevA_Hash_InitializeHash(mxc_ctb_reva_regs_t * ctb_regs)791 void MXC_CTB_RevA_Hash_InitializeHash(mxc_ctb_reva_regs_t *ctb_regs)
792 {
793 ctb_regs->hash_ctrl |= MXC_F_CTB_REVA_HASH_CTRL_INIT;
794
795 while (ctb_regs->hash_ctrl & MXC_F_CTB_REVA_HASH_CTRL_INIT) {}
796 }
797
798 /************************/
799 /* High Level Functions */
800 /************************/
801
MXC_CTB_RevA_Hash_Compute(mxc_ctb_reva_hash_req_t * req)802 int MXC_CTB_RevA_Hash_Compute(mxc_ctb_reva_hash_req_t *req)
803 {
804 int i, block, numBlocks, blockSize, lastBlockSize;
805 mxc_ctb_reva_dma_req_t dma_req;
806
807 if (req == NULL) {
808 return E_NULL_PTR;
809 }
810
811 if (!(req->msg && req->hash)) {
812 return E_NULL_PTR;
813 }
814
815 if (req->len <= 0) {
816 return E_INVALID;
817 }
818
819 int enabled = MXC_CTB_CheckInterrupts();
820 MXC_CTB_DisableInt();
821
822 MXC_CTB_Hash_SetMessageSize(req->len);
823 MXC_CTB_Hash_SetSource((mxc_ctb_hash_source_t)MXC_CTB_REVA_HASH_SOURCE_INFIFO);
824 MXC_CTB_Hash_InitializeHash();
825
826 blockSize = MXC_CTB_Hash_GetBlockSize(MXC_CTB_Hash_GetFunction());
827 numBlocks = ((int)req->len - 1) / blockSize + 1;
828 lastBlockSize = req->len % blockSize;
829
830 if (lastBlockSize == 0) {
831 lastBlockSize = blockSize;
832 }
833
834 dma_req.sourceBuffer = req->msg;
835
836 MXC_CTB_DMA_SetupOperation((mxc_ctb_dma_req_t *)&dma_req);
837
838 for (block = 0; block < numBlocks; block++) {
839 if (block != numBlocks - 1) {
840 // Send data to the crypto data register 32-bits at a time
841 MXC_CTB_DMA_StartTransfer(blockSize);
842
843 } else {
844 // Set the last req->msg bit for auto padding the msg
845 MXC_CTB_Hash_SetAutoPad(1);
846
847 MXC_CTB_DMA_StartTransfer(lastBlockSize);
848 }
849
850 // Wait until operation is complete
851 while (!(MXC_CTB_Done() & MXC_CTB_REVA_FEATURE_HASH)) {}
852 }
853
854 // Get the msg digest
855 // Note: i is throwaway
856 MXC_CTB_Hash_GetResult(req->hash, &i);
857
858 if (enabled) {
859 MXC_CTB_EnableInt();
860 }
861
862 return E_NO_ERROR;
863 }
864
MXC_CTB_Hash_SendBlock(mxc_ctb_hash_req_t * req)865 static void MXC_CTB_Hash_SendBlock(mxc_ctb_hash_req_t *req)
866 {
867 if (async_i != async_numBlocks - 1) {
868 MXC_CTB_DMA_StartTransfer(async_blockSize);
869 } else {
870 // Set the last bit for auto padding the msg
871 MXC_CTB_Hash_SetAutoPad(1);
872
873 MXC_CTB_DMA_StartTransfer(async_lastBlockSize);
874 }
875 }
876
MXC_CTB_RevA_Hash_ComputeAsync(mxc_ctb_reva_hash_req_t * req)877 void MXC_CTB_RevA_Hash_ComputeAsync(mxc_ctb_reva_hash_req_t *req)
878 {
879 mxc_ctb_reva_dma_req_t dma_req;
880
881 MXC_ASSERT(req);
882 MXC_ASSERT(req->msg && req->hash && req->callback);
883
884 if (req->len <= 0) {
885 return;
886 }
887
888 while (MXC_GetLock((void *)&MXC_CTB_Callbacks[HSH_ID], 1) != E_NO_ERROR) {}
889
890 MXC_CTB_DisableInt();
891
892 MXC_CTB_Callbacks[HSH_ID] = req->callback;
893 saved_requests[HSH_ID] = req;
894
895 MXC_CTB_Hash_SetMessageSize(req->len);
896 MXC_CTB_Hash_SetSource((mxc_ctb_hash_source_t)MXC_CTB_REVA_HASH_SOURCE_INFIFO);
897 MXC_CTB_Hash_InitializeHash();
898
899 async_blockSize = MXC_CTB_Hash_GetBlockSize(MXC_CTB_Hash_GetFunction());
900 async_numBlocks = ((int)req->len - 1) / async_blockSize + 1;
901 async_lastBlockSize = req->len % async_blockSize;
902 async_i = 0;
903
904 if (async_lastBlockSize == 0) {
905 async_lastBlockSize = async_blockSize;
906 }
907
908 dma_req.sourceBuffer = req->msg;
909 MXC_CTB_DMA_SetupOperation((mxc_ctb_dma_req_t *)&dma_req);
910
911 MXC_CTB_EnableInt();
912
913 MXC_CTB_Hash_SendBlock((mxc_ctb_hash_req_t *)req);
914 }
915
916 /* ************************************************************************* */
917 /* Cipher functions */
918 /* ************************************************************************* */
919
920 /************************/
921 /* Low Level Functions */
922 /************************/
923
MXC_CTB_RevA_Cipher_SetMode(mxc_ctb_reva_regs_t * ctb_regs,mxc_ctb_reva_cipher_mode_t mode)924 void MXC_CTB_RevA_Cipher_SetMode(mxc_ctb_reva_regs_t *ctb_regs, mxc_ctb_reva_cipher_mode_t mode)
925 {
926 MXC_SETFIELD(ctb_regs->cipher_ctrl, MXC_F_CTB_REVA_CIPHER_CTRL_MODE,
927 mode << MXC_F_CTB_REVA_CIPHER_CTRL_MODE_POS);
928 }
929
MXC_CTB_RevA_Cipher_GetMode(mxc_ctb_reva_regs_t * ctb_regs)930 mxc_ctb_reva_cipher_mode_t MXC_CTB_RevA_Cipher_GetMode(mxc_ctb_reva_regs_t *ctb_regs)
931 {
932 return (mxc_ctb_reva_cipher_mode_t)((ctb_regs->cipher_ctrl & MXC_F_CTB_REVA_CIPHER_CTRL_MODE) >>
933 MXC_F_CTB_REVA_CIPHER_CTRL_MODE_POS);
934 }
935
MXC_CTB_RevA_Cipher_SetCipher(mxc_ctb_reva_regs_t * ctb_regs,mxc_ctb_reva_cipher_t cipher)936 void MXC_CTB_RevA_Cipher_SetCipher(mxc_ctb_reva_regs_t *ctb_regs, mxc_ctb_reva_cipher_t cipher)
937 {
938 MXC_SETFIELD(ctb_regs->cipher_ctrl, MXC_F_CTB_REVA_CIPHER_CTRL_CIPHER,
939 cipher << MXC_F_CTB_REVA_CIPHER_CTRL_CIPHER_POS);
940 }
941
MXC_CTB_RevA_Cipher_GetCipher(mxc_ctb_reva_regs_t * ctb_regs)942 mxc_ctb_reva_cipher_t MXC_CTB_RevA_Cipher_GetCipher(mxc_ctb_reva_regs_t *ctb_regs)
943 {
944 return (mxc_ctb_reva_cipher_t)((ctb_regs->cipher_ctrl & MXC_F_CTB_REVA_CIPHER_CTRL_CIPHER) >>
945 MXC_F_CTB_REVA_CIPHER_CTRL_CIPHER_POS);
946 }
947
MXC_CTB_RevA_Cipher_SetKeySource(mxc_ctb_reva_regs_t * ctb_regs,mxc_ctb_reva_cipher_key_t source)948 void MXC_CTB_RevA_Cipher_SetKeySource(mxc_ctb_reva_regs_t *ctb_regs,
949 mxc_ctb_reva_cipher_key_t source)
950 {
951 MXC_SETFIELD(ctb_regs->cipher_ctrl, MXC_F_CTB_REVA_CIPHER_CTRL_SRC,
952 source << MXC_F_CTB_REVA_CIPHER_CTRL_SRC_POS);
953 }
954
MXC_CTB_RevA_Cipher_GetKeySource(mxc_ctb_reva_regs_t * ctb_regs)955 mxc_ctb_reva_cipher_key_t MXC_CTB_RevA_Cipher_GetKeySource(mxc_ctb_reva_regs_t *ctb_regs)
956 {
957 return (mxc_ctb_reva_cipher_key_t)((ctb_regs->cipher_ctrl & MXC_F_CTB_REVA_CIPHER_CTRL_SRC) >>
958 MXC_F_CTB_REVA_CIPHER_CTRL_SRC_POS);
959 }
960
MXC_CTB_RevA_Cipher_LoadKey(mxc_ctb_reva_regs_t * ctb_regs)961 void MXC_CTB_RevA_Cipher_LoadKey(mxc_ctb_reva_regs_t *ctb_regs)
962 {
963 if ((mxc_ctb_reva_cipher_key_t)MXC_CTB_Cipher_GetKeySource() ==
964 MXC_CTB_REVA_CIPHER_KEY_SOFTWARE) {
965 return;
966 }
967
968 ctb_regs->cipher_ctrl |= MXC_F_CTB_REVA_CIPHER_CTRL_KEY;
969 }
970
MXC_CTB_RevA_Cipher_SetOperation(mxc_ctb_reva_regs_t * ctb_regs,mxc_ctb_reva_cipher_operation_t operation)971 void MXC_CTB_RevA_Cipher_SetOperation(mxc_ctb_reva_regs_t *ctb_regs,
972 mxc_ctb_reva_cipher_operation_t operation)
973 {
974 MXC_SETFIELD(ctb_regs->cipher_ctrl, MXC_F_CTB_REVA_CIPHER_CTRL_ENC,
975 operation << MXC_F_CTB_REVA_CIPHER_CTRL_ENC_POS);
976 }
977
MXC_CTB_RevA_Cipher_SetKey(mxc_ctb_reva_regs_t * ctb_regs,uint8_t * key,uint32_t len)978 void MXC_CTB_RevA_Cipher_SetKey(mxc_ctb_reva_regs_t *ctb_regs, uint8_t *key, uint32_t len)
979 {
980 if ((mxc_ctb_reva_cipher_key_t)MXC_CTB_Cipher_GetKeySource() !=
981 MXC_CTB_REVA_CIPHER_KEY_SOFTWARE) {
982 return;
983 }
984
985 memcpy((uint8_t *)&ctb_regs->cipher_key[0], key, len);
986 }
987
MXC_CTB_RevA_Cipher_SetIV(mxc_ctb_reva_regs_t * ctb_regs,uint8_t * iv,uint32_t len)988 void MXC_CTB_RevA_Cipher_SetIV(mxc_ctb_reva_regs_t *ctb_regs, uint8_t *iv, uint32_t len)
989 {
990 memcpy((uint8_t *)&ctb_regs->cipher_init[0], iv, len);
991 }
992
MXC_CTB_RevA_Cipher_GetIV(mxc_ctb_reva_regs_t * ctb_regs,uint8_t * ivOut,uint32_t len)993 void MXC_CTB_RevA_Cipher_GetIV(mxc_ctb_reva_regs_t *ctb_regs, uint8_t *ivOut, uint32_t len)
994 {
995 memcpy(ivOut, (uint8_t *)&ctb_regs->cipher_init[0], len);
996 }
997
998 /************************/
999 /* High Level Functions */
1000 /************************/
1001
MXC_CTB_Cipher_Generic(mxc_ctb_cipher_req_t * req,int op)1002 static int MXC_CTB_Cipher_Generic(mxc_ctb_cipher_req_t *req, int op)
1003 {
1004 int i, enabled;
1005 mxc_ctb_reva_dma_req_t dma_req;
1006
1007 if (req == NULL) {
1008 return E_NULL_PTR;
1009 }
1010
1011 if (!(req->plaintext && req->ciphertext)) {
1012 return E_NULL_PTR;
1013 }
1014
1015 if (req->ptLen == 0) {
1016 return E_INVALID;
1017 }
1018
1019 enabled = MXC_CTB_CheckInterrupts();
1020 MXC_CTB_DisableInt();
1021
1022 int dataLength = MXC_CTB_Cipher_GetBlockSize(MXC_CTB_Cipher_GetCipher());
1023 int numBlocks = ((int)req->ptLen - 1) / dataLength + 1;
1024
1025 // Load Initial Vector if necessary
1026 if ((mxc_ctb_reva_cipher_mode_t)MXC_CTB_Cipher_GetMode() != MXC_CTB_REVA_MODE_ECB) {
1027 if (req->iv == NULL) {
1028 return E_NULL_PTR;
1029 }
1030
1031 MXC_CTB_Cipher_SetIV(req->iv, dataLength);
1032 }
1033
1034 // Configure for encryption/decryption
1035 MXC_CTB_Cipher_SetOperation((mxc_ctb_cipher_operation_t)op);
1036
1037 dma_req.sourceBuffer = req->plaintext;
1038 dma_req.destBuffer = req->ciphertext;
1039 dma_req.length = dataLength;
1040
1041 MXC_CTB_DMA_SetWriteSource((mxc_ctb_dma_write_source_t)MXC_CTB_REVA_DMA_WRITE_FIFO_CIPHER);
1042 MXC_CTB_DMA_SetupOperation((mxc_ctb_dma_req_t *)&dma_req);
1043
1044 for (i = 0; i < numBlocks; i++) {
1045 // Wait until ready for data
1046 while (!MXC_CTB_Ready()) {}
1047
1048 MXC_CTB_DMA_StartTransfer(dataLength);
1049
1050 // Wait until operation is complete
1051 while (!(MXC_CTB_Done() & MXC_CTB_REVA_FEATURE_CIPHER)) {}
1052 }
1053
1054 if (enabled) {
1055 MXC_CTB_EnableInt();
1056 }
1057
1058 return E_NO_ERROR;
1059 }
1060
MXC_CTB_RevA_Cipher_Encrypt(mxc_ctb_reva_cipher_req_t * req)1061 int MXC_CTB_RevA_Cipher_Encrypt(mxc_ctb_reva_cipher_req_t *req)
1062 {
1063 return MXC_CTB_Cipher_Generic((mxc_ctb_cipher_req_t *)req, 0);
1064 }
1065
MXC_CTB_RevA_Cipher_Decrypt(mxc_ctb_reva_cipher_req_t * req)1066 int MXC_CTB_RevA_Cipher_Decrypt(mxc_ctb_reva_cipher_req_t *req)
1067 {
1068 return MXC_CTB_Cipher_Generic((mxc_ctb_cipher_req_t *)req, 1);
1069 }
1070
MXC_CTB_Cipher_EncDecAsc(mxc_ctb_cipher_req_t * req)1071 static int MXC_CTB_Cipher_EncDecAsc(mxc_ctb_cipher_req_t *req)
1072 {
1073 async_i++;
1074
1075 if (async_i == async_numBlocks) {
1076 return 1;
1077 }
1078
1079 MXC_CTB_DMA_StartTransfer(async_dataLength);
1080 return 0;
1081 }
1082
MXC_CTB_Cipher_GenericAsync(mxc_ctb_cipher_req_t * req,int op)1083 static void MXC_CTB_Cipher_GenericAsync(mxc_ctb_cipher_req_t *req, int op)
1084 {
1085 mxc_ctb_reva_dma_req_t dma_req;
1086
1087 MXC_ASSERT(req);
1088 MXC_ASSERT(req->plaintext && req->ciphertext && req->callback);
1089
1090 while (MXC_GetLock((void *)&MXC_CTB_Callbacks[CPH_ID], 1) != E_NO_ERROR) {}
1091
1092 MXC_CTB_DisableInt();
1093
1094 MXC_CTB_Callbacks[CPH_ID] = req->callback;
1095 saved_requests[CPH_ID] = req;
1096
1097 async_dataLength = MXC_CTB_Cipher_GetBlockSize(MXC_CTB_Cipher_GetCipher());
1098 async_numBlocks = ((int)req->ptLen - 1) / async_dataLength + 1;
1099 async_i = 0;
1100
1101 // Load Initial Vector if necessary
1102 if ((mxc_ctb_reva_cipher_mode_t)MXC_CTB_Cipher_GetMode() != MXC_CTB_REVA_MODE_ECB) {
1103 MXC_ASSERT(req->iv);
1104
1105 MXC_CTB_Cipher_SetIV(req->iv, async_dataLength);
1106 }
1107
1108 // Configure for encryption
1109 MXC_CTB_Cipher_SetOperation((mxc_ctb_cipher_operation_t)op);
1110
1111 dma_req.sourceBuffer = req->plaintext;
1112 dma_req.destBuffer = req->ciphertext;
1113
1114 MXC_CTB_DMA_SetWriteSource((mxc_ctb_dma_write_source_t)MXC_CTB_REVA_DMA_WRITE_FIFO_CIPHER);
1115 MXC_CTB_DMA_SetupOperation((mxc_ctb_dma_req_t *)&dma_req);
1116
1117 MXC_CTB_EnableInt();
1118
1119 // Wait until ready for data
1120 while (!MXC_CTB_Ready()) {}
1121
1122 MXC_CTB_DMA_StartTransfer(async_dataLength);
1123 }
1124
MXC_CTB_RevA_Cipher_EncryptAsync(mxc_ctb_reva_cipher_req_t * req)1125 void MXC_CTB_RevA_Cipher_EncryptAsync(mxc_ctb_reva_cipher_req_t *req)
1126 {
1127 MXC_CTB_Cipher_GenericAsync((mxc_ctb_cipher_req_t *)req, 0);
1128 }
1129
MXC_CTB_RevA_Cipher_DecryptAsync(mxc_ctb_reva_cipher_req_t * req)1130 void MXC_CTB_RevA_Cipher_DecryptAsync(mxc_ctb_reva_cipher_req_t *req)
1131 {
1132 MXC_CTB_Cipher_GenericAsync((mxc_ctb_cipher_req_t *)req, 1);
1133 }
1134