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