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 /* **** Includes **** */
22 #include <stdint.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include "mxc_device.h"
27 #include "mxc_errors.h"
28 #include "mxc_sys.h"
29 #include "tpu.h"
30 #include "tpu_reva.h"
31 
32 /* **** Global Data **** */
33 
34 /* **** Functions **** */
35 
36 static int MXC_TPU_RevA_TRNG_Read_Status(mxc_trng_revc_regs_t *trng);
37 /* ************************************************************************ */
38 /* Prevent GCC from optimimzing this function to memset */
39 static void __attribute__((optimize("no-tree-loop-distribute-patterns")))
memset32(uint32_t * dst,uint32_t value,unsigned int len)40 memset32(uint32_t *dst, uint32_t value, unsigned int len)
41 {
42     while (len) {
43         *dst = value;
44         dst++;
45         len -= 4;
46     }
47 }
48 
49 /* ************************************************************************ */
50 /* Prevent GCC from optimimzing this function to memcpy */
51 static void __attribute__((optimize("no-tree-loop-distribute-patterns")))
memcpy32(uint32_t * dst,uint32_t * src,unsigned int len)52 memcpy32(uint32_t *dst, uint32_t *src, unsigned int len)
53 {
54     while (len) {
55         *dst = *src;
56         dst++;
57         src++;
58         len -= 4;
59     }
60 }
61 
62 /* ************************************************************************* */
63 /* Global Control/Configuration functions                                    */
64 /* ************************************************************************* */
65 
66 // *********************************** Function to Clear all Done Flags ***************************************
MXC_TPU_RevA_Clear_Done_Flags(mxc_tpu_reva_regs_t * tpu)67 void MXC_TPU_RevA_Clear_Done_Flags(mxc_tpu_reva_regs_t *tpu)
68 {
69     // Clear all done flags
70     tpu->ctrl |= MXC_F_TPU_REVA_CTRL_DMA_DONE | MXC_F_TPU_REVA_CTRL_GLS_DONE |
71                  MXC_F_TPU_REVA_CTRL_HSH_DONE | MXC_F_TPU_REVA_CTRL_CPH_DONE |
72                  MXC_F_TPU_REVA_CTRL_MAA_DONE;
73 }
74 
75 // ************************************** Function to Clear Crypto Register ************************************
MXC_TPU_RevA_Reset(mxc_tpu_reva_regs_t * tpu)76 void MXC_TPU_RevA_Reset(mxc_tpu_reva_regs_t *tpu)
77 {
78     MXC_TPU_Init(MXC_SYS_PERIPH_CLOCK_TPU);
79 
80     // Reset Crypto Accelerator
81     tpu->ctrl = MXC_F_TPU_REVA_CTRL_RST;
82 
83     memset32((uint32_t *)tpu, 0, sizeof(mxc_tpu_reva_regs_t));
84 
85     // Set the legacy bit so done bits are W1C.
86     tpu->ctrl |= MXC_F_TPU_REVA_CTRL_FLAG_MODE;
87 
88     MXC_TPU_RevA_Clear_Done_Flags(tpu);
89 }
90 
91 /* ************************************************************************* */
92 /* Cyclic Redundancy Check (CRC) functions                                   */
93 /* ************************************************************************* */
94 
95 // ************************************ Function to Configure CRC Algorithm ****************************************
MXC_TPU_RevA_CRC_Config(mxc_tpu_reva_regs_t * tpu)96 int MXC_TPU_RevA_CRC_Config(mxc_tpu_reva_regs_t *tpu)
97 {
98     // Reset Crypto Block
99     MXC_TPU_Reset();
100 
101     // Set input and output FIFO modes
102     tpu->ctrl |= MXC_S_TPU_REVA_CTRL_RDSRC_DMAORAPB;
103 
104     // Enable CRC
105     tpu->crc_ctrl = MXC_F_TPU_REVA_CRC_CTRL_CRC_EN;
106 
107     return E_SUCCESS;
108 }
109 
110 // ************************************* Function to Generate CRC value *******************************************
MXC_TPU_RevA_CRC(mxc_tpu_reva_regs_t * tpu,const uint8_t * src,uint32_t len,uint32_t poly,uint32_t * crc)111 int MXC_TPU_RevA_CRC(mxc_tpu_reva_regs_t *tpu, const uint8_t *src, uint32_t len, uint32_t poly,
112                      uint32_t *crc)
113 {
114     int err;
115 
116     // Check if src is pointing to null
117     if (src == NULL || crc == NULL) {
118         return E_NULL_PTR;
119     }
120 
121     // Check if data size is null;
122     if (len == 0) {
123         return E_INVALID;
124     }
125 
126     err = MXC_TPU_CRC_Config();
127     if (err != E_SUCCESS) {
128         return err;
129     }
130 
131     // Load CRC polynomial into crc polynomial register
132     tpu->crc_poly = poly;
133 
134     // Setup DMA transfer
135     tpu->dma_src = (uint32_t)src;
136     tpu->dma_cnt = len;
137 
138     // Wait for dma done flag
139     while (!(tpu->ctrl & MXC_F_TPU_REVA_CTRL_DMA_DONE)) {}
140 
141     // Wait until operation is complete
142     while (!(tpu->ctrl & MXC_F_TPU_REVA_CTRL_GLS_DONE)) {}
143 
144     // Clear gls done flag
145     tpu->ctrl |= MXC_F_TPU_REVA_CTRL_GLS_DONE;
146 
147     // Store the crc value
148     *crc = tpu->crc_val;
149 
150     return E_SUCCESS;
151 }
152 
153 // ************************************ Function to Configure HAM Algorithm ****************************************
MXC_TPU_RevA_Ham_Config(mxc_tpu_reva_regs_t * tpu)154 int MXC_TPU_RevA_Ham_Config(mxc_tpu_reva_regs_t *tpu)
155 {
156     // Reset Crypto Block
157     MXC_TPU_Reset();
158 
159     tpu->ctrl |= MXC_F_TPU_REVA_CTRL_DMADNE_MSK;
160 
161     // Set input and output FIFO modes
162     tpu->ctrl |= MXC_S_TPU_REVA_CTRL_RDSRC_DMAORAPB;
163 
164     // Reset hamming code
165     tpu->crc_ctrl = MXC_F_TPU_REVA_CRC_CTRL_HRST;
166     while (tpu->crc_ctrl & MXC_F_TPU_REVA_CRC_CTRL_HRST) {}
167 
168     // Enable Hamming code
169     tpu->crc_ctrl |= MXC_F_TPU_REVA_CRC_CTRL_HAM;
170 
171     // Clear all done flags
172     MXC_TPU_RevA_Clear_Done_Flags(tpu);
173 
174     return E_SUCCESS;
175 }
176 
177 // ************************************* Function to Generate ECC value *******************************************
MXC_TPU_RevA_Ham(mxc_tpu_reva_regs_t * tpu,const uint8_t * src,uint32_t len,uint32_t * ecc)178 int MXC_TPU_RevA_Ham(mxc_tpu_reva_regs_t *tpu, const uint8_t *src, uint32_t len, uint32_t *ecc)
179 {
180     int err;
181 
182     // Check if data is pointing to null
183     if (src == NULL || ecc == NULL) {
184         return E_NULL_PTR;
185     }
186 
187     // Check if data size is null;
188     if (len == 0) {
189         return E_INVALID;
190     }
191 
192     err = MXC_TPU_RevA_Ham_Config(tpu);
193     if (err != E_SUCCESS) {
194         return err;
195     }
196 
197     // Setup DMA transfer
198     tpu->dma_src = (uint32_t)src;
199     tpu->dma_cnt = len;
200 
201     // Wait until operation is complete
202     while (!(tpu->ctrl & MXC_F_TPU_REVA_CTRL_GLS_DONE)) {}
203 
204     // Wait for dma done flag
205     while (!(tpu->ctrl & MXC_F_TPU_REVA_CTRL_DMA_DONE)) {}
206 
207     // Clear gls done flag
208     tpu->ctrl |= MXC_F_TPU_REVA_CTRL_GLS_DONE;
209 
210     // Store the ecc value
211     *ecc = tpu->ham_ecc;
212 
213     return E_SUCCESS;
214 }
215 
216 /* ************************************************************************* */
217 /* Cipher functions                                                          */
218 /* ************************************************************************* */
219 
220 // ************************************* Function to Get Number of Blocks **************************************
MXC_TPU_RevA_Cipher_GetLength(mxc_tpu_ciphersel_t cipher,unsigned int data_size)221 unsigned int MXC_TPU_RevA_Cipher_GetLength(mxc_tpu_ciphersel_t cipher, unsigned int data_size)
222 {
223     unsigned int numBlocks, block_size;
224     block_size = MXC_TPU_Cipher_Get_Block_Size(cipher);
225     numBlocks = data_size / block_size;
226     if ((data_size % block_size) > 0) {
227         numBlocks++;
228     }
229 
230     return numBlocks;
231 }
232 
233 // ************************ Function to Enable Encrypt/Decrypt Cipher Operation *******************************
MXC_TPU_RevA_Cipher_EncDecSelect(mxc_tpu_reva_regs_t * tpu,int enc)234 void MXC_TPU_RevA_Cipher_EncDecSelect(mxc_tpu_reva_regs_t *tpu, int enc)
235 {
236     // Enable Encryption/Decryption Operation
237     if (enc) {
238         tpu->cipher_ctrl &= ~MXC_F_TPU_REVA_CIPHER_CTRL_ENC;
239     } else {
240         tpu->cipher_ctrl |= MXC_F_TPU_REVA_CIPHER_CTRL_ENC;
241     }
242 }
243 
244 // ******************************* Function to Configure Cipher Operation *************************************
MXC_TPU_RevA_Cipher_Config(mxc_tpu_reva_regs_t * tpu,mxc_tpu_reva_modesel_t mode,mxc_tpu_reva_ciphersel_t cipher)245 int MXC_TPU_RevA_Cipher_Config(mxc_tpu_reva_regs_t *tpu, mxc_tpu_reva_modesel_t mode,
246                                mxc_tpu_reva_ciphersel_t cipher)
247 {
248     // Reset crypto block
249     MXC_TPU_Reset();
250 
251     // Select cipher mode ECB/CBC/CFB/CTR
252     // Select cipher operation AES_128/192/256/DES/TDES
253     // Select user cipher key
254     tpu->cipher_ctrl = (mode << MXC_F_TPU_REVA_CIPHER_CTRL_MODE_POS) |
255                        (cipher << MXC_F_TPU_REVA_CIPHER_CTRL_CIPHER_POS) |
256                        MXC_S_TPU_REVA_CIPHER_CTRL_SRC_CIPHERKEY;
257 
258     return E_SUCCESS;
259 }
260 
261 // ******************************* Function to Select the Source of the Cipher Key *************************************
MXC_TPU_RevA_Cipher_KeySelect(mxc_tpu_reva_regs_t * tpu,mxc_tpu_reva_keysrc_t key_src)262 int MXC_TPU_RevA_Cipher_KeySelect(mxc_tpu_reva_regs_t *tpu, mxc_tpu_reva_keysrc_t key_src)
263 {
264     MXC_SETFIELD(tpu->cipher_ctrl, MXC_F_TPU_REVA_CIPHER_CTRL_SRC, key_src);
265 
266     return E_SUCCESS;
267 }
268 
269 // ************************************ Function to Test Cipher Algorithm ***********************************
MXC_TPU_RevA_Cipher_DoOperation(mxc_tpu_reva_regs_t * tpu,const char * src,const char * iv,const char * key,mxc_tpu_ciphersel_t cipher,mxc_tpu_modesel_t mode,unsigned int data_size,char * outptr)270 int MXC_TPU_RevA_Cipher_DoOperation(mxc_tpu_reva_regs_t *tpu, const char *src, const char *iv,
271                                     const char *key, mxc_tpu_ciphersel_t cipher,
272                                     mxc_tpu_modesel_t mode, unsigned int data_size, char *outptr)
273 {
274     unsigned int keyLength, dataLength, numBlocks, i;
275     uint32_t key_src = tpu->cipher_ctrl & MXC_F_TPU_REVA_CIPHER_CTRL_SRC;
276 
277     if (data_size == 0) {
278         return E_INVALID;
279     }
280 
281     // Check if src, key, iv is a null pointer
282     if (src == NULL || (iv == NULL && mode != (mxc_tpu_modesel_t)MXC_TPU_REVA_MODE_ECB)) {
283         return E_NULL_PTR;
284     } else if (key == NULL &&
285                key_src ==
286                    MXC_TPU_REVA_KEYSRC_KEY0) { // Key source 0 requires valid key to copy into CIPHER_KEY[0:7]
287         return E_NULL_PTR;
288     }
289 
290     numBlocks = MXC_TPU_Cipher_GetLength(cipher, data_size);
291 
292     keyLength = MXC_TPU_Cipher_Get_Key_Size(cipher);
293     dataLength = MXC_TPU_Cipher_Get_Block_Size(cipher);
294 
295     // If using key source 0, copy key into CIPHER_KEY[0:7]
296     if (key_src == MXC_TPU_REVA_KEYSRC_KEY0) {
297         memcpy32((void *)&tpu->cipher_key[0], (void *)key, keyLength);
298     }
299 
300     // Load Initial Vector if necessary
301     if (mode != MXC_TPU_MODE_ECB) {
302         memcpy32((void *)&tpu->cipher_init[0], (void *)iv, dataLength);
303     }
304 
305     for (i = 0; i < numBlocks; i++) {
306         // Wait until ready for data
307         while (!(tpu->ctrl & MXC_F_TPU_REVA_CTRL_RDY)) {}
308 
309         // Load plaintext into data in register to start the operation
310         memcpy32((void *)&tpu->data_in[0], (void *)src, dataLength);
311 
312         // Wait until operation is complete
313         while (!(tpu->ctrl & MXC_F_TPU_REVA_CTRL_CPH_DONE)) {}
314 
315         // Copy data out
316         memcpy32((void *)outptr, (void *)&tpu->data_out[0], dataLength);
317 
318         src += dataLength;
319         outptr += dataLength;
320 
321         // Clear done flag so reading of the next block will be gated properly.
322         tpu->ctrl |= MXC_F_TPU_REVA_CTRL_CPH_DONE;
323     }
324 
325     return E_SUCCESS;
326 }
327 
MXC_TPU_RevA_Cipher_DES_Encrypt(const char * plaintext,const char * iv,const char * key,mxc_tpu_modesel_t mode,unsigned int data_size,char * outptr)328 int MXC_TPU_RevA_Cipher_DES_Encrypt(const char *plaintext, const char *iv, const char *key,
329                                     mxc_tpu_modesel_t mode, unsigned int data_size, char *outptr)
330 {
331     // Enable cipher encrypt/decrypt process
332     MXC_TPU_Cipher_EncDecSelect(1);
333 
334     // Start the cipher operation
335     return MXC_TPU_Cipher_DoOperation(
336         plaintext, iv, key, (mxc_tpu_ciphersel_t)MXC_TPU_REVA_CIPHER_DES, mode, data_size, outptr);
337 }
338 
MXC_TPU_RevA_Cipher_DES_Decrypt(const char * ciphertext,const char * iv,const char * key,mxc_tpu_modesel_t mode,unsigned int data_size,char * outptr)339 int MXC_TPU_RevA_Cipher_DES_Decrypt(const char *ciphertext, const char *iv, const char *key,
340                                     mxc_tpu_modesel_t mode, unsigned int data_size, char *outptr)
341 {
342     // Enable cipher encrypt/decrypt process
343     MXC_TPU_Cipher_EncDecSelect(0);
344 
345     // Start the cipher operation
346     return MXC_TPU_Cipher_DoOperation(
347         ciphertext, iv, key, (mxc_tpu_ciphersel_t)MXC_TPU_REVA_CIPHER_DES, mode, data_size, outptr);
348 }
349 
MXC_TPU_RevA_Cipher_TDES_Encrypt(const char * plaintext,const char * iv,const char * key,mxc_tpu_modesel_t mode,unsigned int data_size,char * outptr)350 int MXC_TPU_RevA_Cipher_TDES_Encrypt(const char *plaintext, const char *iv, const char *key,
351                                      mxc_tpu_modesel_t mode, unsigned int data_size, char *outptr)
352 {
353     // Enable cipher encrypt/decrypt process
354     MXC_TPU_Cipher_EncDecSelect(1);
355 
356     // Start the cipher operation
357     return MXC_TPU_Cipher_DoOperation(
358         plaintext, iv, key, (mxc_tpu_ciphersel_t)MXC_TPU_REVA_CIPHER_TDES, mode, data_size, outptr);
359 }
360 
MXC_TPU_RevA_Cipher_TDES_Decrypt(const char * ciphertext,const char * iv,const char * key,mxc_tpu_modesel_t mode,unsigned int data_size,char * outptr)361 int MXC_TPU_RevA_Cipher_TDES_Decrypt(const char *ciphertext, const char *iv, const char *key,
362                                      mxc_tpu_modesel_t mode, unsigned int data_size, char *outptr)
363 {
364     // Enable cipher encrypt/decrypt process
365     MXC_TPU_Cipher_EncDecSelect(0);
366 
367     // Start the cipher operation
368     return MXC_TPU_Cipher_DoOperation(ciphertext, iv, key,
369                                       (mxc_tpu_ciphersel_t)MXC_TPU_REVA_CIPHER_TDES, mode,
370                                       data_size, outptr);
371 }
372 
MXC_TPU_RevA_Cipher_AES_Encrypt(const char * plaintext,const char * iv,const char * key,mxc_tpu_ciphersel_t cipher,mxc_tpu_modesel_t mode,unsigned int data_size,char * outptr)373 int MXC_TPU_RevA_Cipher_AES_Encrypt(const char *plaintext, const char *iv, const char *key,
374                                     mxc_tpu_ciphersel_t cipher, mxc_tpu_modesel_t mode,
375                                     unsigned int data_size, char *outptr)
376 {
377     if ((cipher != MXC_TPU_CIPHER_AES128) && (cipher != MXC_TPU_CIPHER_AES192) &&
378         (cipher != MXC_TPU_CIPHER_AES256)) {
379         return E_BAD_PARAM;
380     }
381 
382     // Enable cipher encrypt/decrypt process
383     MXC_TPU_Cipher_EncDecSelect(1);
384 
385     // Start the cipher operation
386     return MXC_TPU_Cipher_DoOperation(plaintext, iv, key, cipher, mode, data_size, outptr);
387 }
388 
MXC_TPU_RevA_Cipher_AES_Decrypt(const char * ciphertext,const char * iv,const char * key,mxc_tpu_ciphersel_t cipher,mxc_tpu_modesel_t mode,unsigned int data_size,char * outptr)389 int MXC_TPU_RevA_Cipher_AES_Decrypt(const char *ciphertext, const char *iv, const char *key,
390                                     mxc_tpu_ciphersel_t cipher, mxc_tpu_modesel_t mode,
391                                     unsigned int data_size, char *outptr)
392 {
393     if ((cipher != MXC_TPU_CIPHER_AES128) && (cipher != MXC_TPU_CIPHER_AES192) &&
394         (cipher != MXC_TPU_CIPHER_AES256)) {
395         return E_BAD_PARAM;
396     }
397 
398     // Enable cipher encrypt/decrypt process
399     MXC_TPU_Cipher_EncDecSelect(0);
400 
401     // Start the cipher operation
402     return MXC_TPU_Cipher_DoOperation(ciphertext, iv, key, cipher, mode, data_size, outptr);
403 }
404 
405 /* ************************************************************************* */
406 /* Hash functions                                                            */
407 /* ************************************************************************* */
408 
MXC_TPU_RevA_Hash_SHA_Size(unsigned int * blocks,unsigned int * length,unsigned int * lbyte,mxc_tpu_hashfunsel_t fun)409 void MXC_TPU_RevA_Hash_SHA_Size(unsigned int *blocks, unsigned int *length, unsigned int *lbyte,
410                                 mxc_tpu_hashfunsel_t fun)
411 {
412     unsigned block_size_sha = MXC_TPU_Hash_Get_Block_Size_SHA(fun);
413 
414     if (*blocks == 0) {
415         // Special case for 0 length message
416         *blocks = 1;
417         *lbyte = 1;
418     } else {
419         // Get size of last block of data
420         *lbyte = ((*length) - (((*blocks) - 1) * block_size_sha));
421     }
422 }
423 
424 // ********************************** Function to Configure SHA Algorithm *************************************
MXC_TPU_RevA_Hash_Config(mxc_tpu_reva_regs_t * tpu,mxc_tpu_hashfunsel_t func)425 int MXC_TPU_RevA_Hash_Config(mxc_tpu_reva_regs_t *tpu, mxc_tpu_hashfunsel_t func)
426 {
427     int funcInt = (int)func;
428     if ((funcInt < (int)MXC_V_TPU_REVA_HASH_CTRL_HASH_DIS) ||
429         (funcInt > (int)MXC_V_TPU_REVA_HASH_CTRL_HASH_SHA512)) {
430         return E_BAD_PARAM;
431     }
432 
433     // Reset Crypto Block
434     MXC_TPU_Reset();
435 
436     // Select the Hash Function
437     tpu->hash_ctrl = func << MXC_F_TPU_REVA_HASH_CTRL_HASH_POS;
438 
439     // Initialize the hash values
440     tpu->hash_ctrl |= MXC_F_TPU_REVA_HASH_CTRL_INIT;
441 
442     // Wait until operation is complete
443     while (tpu->hash_ctrl & MXC_F_TPU_REVA_HASH_CTRL_INIT) {}
444 
445     return E_SUCCESS;
446 }
447 
448 // ************************************ Function to test SHA Algorithm ****************************************
MXC_TPU_RevA_Hash_SHA(mxc_tpu_reva_regs_t * tpu,const char * msg,mxc_tpu_hashfunsel_t fun,unsigned int byteLen,char * digest)449 int MXC_TPU_RevA_Hash_SHA(mxc_tpu_reva_regs_t *tpu, const char *msg, mxc_tpu_hashfunsel_t fun,
450                           unsigned int byteLen, char *digest)
451 {
452     unsigned int last_byte = 0;
453     unsigned int block, word, numBlocks, block_size_sha, dgst_size;
454     int i;
455     int err;
456 
457     // Check if msg, digest msg is a null pointer
458     if (msg == NULL || digest == NULL) {
459         return E_NULL_PTR;
460     }
461 
462     if (byteLen == 0) {
463         return E_INVALID;
464     }
465 
466     err = MXC_TPU_Hash_Config(fun);
467     if (err != E_SUCCESS) {
468         return err;
469     }
470     block_size_sha = MXC_TPU_Hash_Get_Block_Size_SHA(fun);
471     dgst_size = MXC_TPU_Hash_Get_Dgst_Size(fun);
472     // Write message size
473     tpu->hash_msg_sz[0] = byteLen;
474 
475     // Determine the size of message data without padding
476     numBlocks = (byteLen + (block_size_sha - 1)) / block_size_sha;
477     MXC_TPU_Hash_SHA_Size(&numBlocks, &byteLen, &last_byte, fun);
478 
479     for (block = 0; block < numBlocks; block++) {
480         // Clear done flags
481         MXC_TPU_RevA_Clear_Done_Flags(tpu);
482 
483         // Send data to the crypto data register 32-bits at a time
484         if (block != numBlocks - 1) {
485             for (i = block * block_size_sha, word = 0; word < block_size_sha; word += 4) {
486                 // Wait until ready for data
487                 while (!(tpu->ctrl & MXC_F_TPU_REVA_CTRL_RDY)) {}
488 
489                 tpu->data_in[0] = (uint32_t)(msg[word + i]) | ((uint32_t)(msg[word + 1 + i]) << 8) |
490                                   ((uint32_t)(msg[word + 2 + i]) << 16) |
491                                   ((uint32_t)(msg[word + 3 + i]) << 24);
492             }
493         } else {
494             // Determine the current block
495             i = block * block_size_sha;
496 
497             // Set the last msg bit for auto padding the msg
498             tpu->hash_ctrl |= MXC_F_TPU_REVA_HASH_CTRL_LAST;
499 
500             // Process the last block
501             for (word = 0; word < last_byte; word += 4) {
502                 // Wait until ready for data
503                 while (!(tpu->ctrl & MXC_F_TPU_REVA_CTRL_RDY)) {}
504 
505                 // Send data to the crypto data register
506                 if (last_byte >= (word + 4)) {
507                     tpu->data_in[0] = (uint32_t)(msg[word + i]) +
508                                       ((uint32_t)(msg[word + 1 + i]) << 8) +
509                                       ((uint32_t)(msg[word + 2 + i]) << 16) +
510                                       ((uint32_t)(msg[word + 3 + i]) << 24);
511                 } else if ((last_byte & 3) == 1) {
512                     tpu->data_in[0] = msg[word + i];
513                 } else if ((last_byte & 3) == 2) {
514                     tpu->data_in[0] =
515                         (uint32_t)msg[word + i] + ((uint32_t)(msg[word + 1 + i]) << 8);
516                 } else if ((last_byte & 3) == 3) {
517                     tpu->data_in[0] = (uint32_t)msg[word + i] +
518                                       ((uint32_t)(msg[word + 1 + i]) << 8) +
519                                       ((uint32_t)(msg[word + 2 + i]) << 16);
520                 }
521             }
522         }
523 
524         // Wait until operation is complete
525         while (!(tpu->ctrl & MXC_F_TPU_REVA_CTRL_HSH_DONE)) {}
526     }
527 
528     // Clear the done flags
529     MXC_TPU_RevA_Clear_Done_Flags(tpu);
530 
531     // Get the msg digest
532     memcpy((uint32_t *)digest, (uint32_t *)&tpu->hash_digest[0], dgst_size);
533 
534     return E_SUCCESS;
535 }
536 
537 /* ************************************************************************* */
538 /* True Random Number Generator (TRNG) functions                             */
539 /* ************************************************************************* */
540 
MXC_TPU_RevA_TRNG_Read_Status(mxc_trng_revc_regs_t * trng)541 static int MXC_TPU_RevA_TRNG_Read_Status(mxc_trng_revc_regs_t *trng)
542 {
543     //  Check if a random number is ready to be read
544     if (trng->st & MXC_F_TRNG_REVC_ST_RND_RDY) {
545         return E_NO_ERROR;
546     } else {
547         //  Return bad state if TRNG is disabled
548         return E_BAD_STATE;
549     }
550 }
551 
MXC_TPU_RevA_TRNG_Read8BIT(mxc_trng_revc_regs_t * trng)552 uint8_t MXC_TPU_RevA_TRNG_Read8BIT(mxc_trng_revc_regs_t *trng)
553 {
554     //  Wait for TRNG to be ready
555     while (MXC_TPU_RevA_TRNG_Read_Status(trng) != E_NO_ERROR) {}
556 
557     return ((uint8_t)(trng->data & 0xFF));
558     {
559     }
560 }
561 
MXC_TPU_RevA_TRNG_Read16BIT(mxc_trng_revc_regs_t * trng)562 uint16_t MXC_TPU_RevA_TRNG_Read16BIT(mxc_trng_revc_regs_t *trng)
563 {
564     //  Wait for TRNG to be ready
565     while (MXC_TPU_RevA_TRNG_Read_Status(trng) != E_NO_ERROR) {}
566 
567     return ((uint16_t)(trng->data & 0xFFFF));
568 }
569 
MXC_TPU_RevA_TRNG_Read32BIT(mxc_trng_revc_regs_t * trng)570 uint32_t MXC_TPU_RevA_TRNG_Read32BIT(mxc_trng_revc_regs_t *trng)
571 {
572     //   Wait for TRNG to be ready
573     while (MXC_TPU_RevA_TRNG_Read_Status(trng) != E_NO_ERROR) {}
574 
575     return ((uint32_t)trng->data);
576 }
577 
MXC_TPU_RevA_TRNG_Read(mxc_trng_revc_regs_t * trng,uint8_t * data,int len)578 void MXC_TPU_RevA_TRNG_Read(mxc_trng_revc_regs_t *trng, uint8_t *data, int len)
579 {
580     int i = 0;
581     uint32_t temp;
582 
583     while (len >= 4) {
584         temp = MXC_TPU_TRNG_Read32BIT((mxc_trng_regs_t *)trng);
585         memcpy(&data[i], &temp, 4);
586         i += 4;
587         len -= 4;
588     }
589     while (len) {
590         data[i++] = MXC_TPU_TRNG_Read8BIT((mxc_trng_regs_t *)trng);
591         len--;
592     }
593 }
594 
MXC_TPU_RevA_TRNG_Generate_AES(mxc_trng_revc_regs_t * trng)595 void MXC_TPU_RevA_TRNG_Generate_AES(mxc_trng_revc_regs_t *trng)
596 {
597     // Start key generation
598     trng->cn |= MXC_F_TRNG_REVC_CN_AESKG_MEU;
599     // Field will be auto-set to 0 while key generation is in progress.  Wait for it to complete.
600     while ((trng->st & MXC_F_TRNG_REVC_ST_AESKGD_MEU_S) == 0) {}
601 }
602 
603 /* ************************************************************************* */
604 /* Modular Arithmetic Accelerator (MAA) functions                             */
605 /* ************************************************************************* */
606 
607 /* **** Definitions **** */
608 int exponent = 0;
609 
610 // MAA crypto memory block address
611 #define MAA_A (MXC_BASE_TPU + 0x100) // MAA_A memory offset
612 #define MAA_B (MXC_BASE_TPU + 0x200) // MAA_B memory offset
613 #define MAA_R (MXC_BASE_TPU + 0x300) // MAA_R memory offset
614 #define MAA_T (MXC_BASE_TPU + 0x400) // MAA_T memory offset
615 #define MAA_E (MXC_BASE_TPU + 0x500) // MAA_E memory offset
616 #define MAA_M (MXC_BASE_TPU + 0x600) // MAA_M memory offset
617 
618 // Define a pointer pointing to different MAA memory location
619 volatile unsigned int *maa_a = (volatile unsigned int *)MAA_A;
620 volatile unsigned int *maa_b = (volatile unsigned int *)MAA_B;
621 volatile unsigned int *maa_r = (volatile unsigned int *)MAA_R;
622 volatile unsigned int *maa_t = (volatile unsigned int *)MAA_T;
623 volatile unsigned int *maa_e = (volatile unsigned int *)MAA_E;
624 volatile unsigned int *maa_m = (volatile unsigned int *)MAA_M;
625 
626 /* **** Functions **** */
MXC_TPU_RevA_MAA_Mem_Clear(void)627 void MXC_TPU_RevA_MAA_Mem_Clear(void)
628 {
629     // Initialize MAA memory
630     memset((uint32_t *)MAA_A, 0, MAA_MAX_SIZE);
631     memset((uint32_t *)MAA_B, 0, MAA_MAX_SIZE);
632     memset((uint32_t *)MAA_R, 0, MAA_MAX_SIZE);
633     memset((uint32_t *)MAA_T, 0, MAA_MAX_SIZE);
634     memset((uint32_t *)MAA_E, 0, MAA_MAX_SIZE);
635     memset((uint32_t *)MAA_M, 0, MAA_MAX_SIZE);
636 }
637 
MXC_TPU_RevA_MAA_Reset(mxc_tpu_reva_regs_t * tpu)638 void MXC_TPU_RevA_MAA_Reset(mxc_tpu_reva_regs_t *tpu)
639 {
640     // Reset Crypto Accelerator
641     tpu->ctrl = MXC_F_TPU_REVA_CTRL_RST;
642     memset((uint32_t *)tpu, 0, sizeof(mxc_tpu_reva_regs_t));
643     MXC_TPU_MAA_Mem_Clear();
644 }
645 
MXC_TPU_RevA_MAA_Init(mxc_tpu_reva_regs_t * tpu,unsigned int size)646 int MXC_TPU_RevA_MAA_Init(mxc_tpu_reva_regs_t *tpu, unsigned int size)
647 {
648     int err;
649 
650     // Check if size is within the valid range
651     if (size > MAA_MAX_WORD_SIZE) {
652         return E_BAD_PARAM;
653     }
654 
655     err = MXC_TPU_Init(MXC_SYS_PERIPH_CLOCK_TPU);
656     if (err != E_NO_ERROR) {
657         return err;
658     }
659 
660     // Reset crypto block
661     MXC_TPU_MAA_Reset();
662 
663     // Set the legacy bit
664     tpu->ctrl = MXC_F_TPU_REVA_CTRL_FLAG_MODE;
665 
666     // Clear interrupt flags
667     tpu->ctrl &= ~MXC_F_TPU_REVA_CTRL_INT;
668 
669     // Set MAA word size
670     tpu->maa_maws = (size << MXC_F_TPU_REVA_MAA_MAWS_MSGSZ_POS) & MXC_F_TPU_REVA_MAA_MAWS_MSGSZ;
671 
672     // Define memory locations for MAA
673     tpu->maa_ctrl |=
674         (0x6 << MXC_F_TPU_REVA_MAA_CTRL_TMA_POS) | (0x4 << MXC_F_TPU_REVA_MAA_CTRL_RMA_POS) |
675         (0x2 << MXC_F_TPU_REVA_MAA_CTRL_BMA_POS) | (0X0 << MXC_F_TPU_REVA_MAA_CTRL_AMA_POS);
676 
677     MXC_TPU_RevA_Clear_Done_Flags(tpu);
678 
679     return E_SUCCESS;
680 }
681 
MXC_TPU_RevA_MAA_Compute(mxc_tpu_reva_regs_t * tpu,mxc_tpu_maa_clcsel_t clc,char * multiplier,char * multiplicand,char * exp,char * mod,int * result,unsigned int len)682 int MXC_TPU_RevA_MAA_Compute(mxc_tpu_reva_regs_t *tpu, mxc_tpu_maa_clcsel_t clc, char *multiplier,
683                              char *multiplicand, char *exp, char *mod, int *result,
684                              unsigned int len)
685 {
686     unsigned i;
687 
688     // Check that we're performing a valid operation
689     if (clc >= 0x6) {
690         return E_INVALID;
691     }
692 
693     // Check if exp pointing to NULL for exponent calculation
694     if ((clc == MXC_TPU_MAA_EXP) && (exp == NULL)) {
695         return E_NULL_PTR;
696     }
697 
698     // Check if multiplier, multipilicand & mod operands pointing to null
699     if (multiplier == NULL || multiplicand == NULL || mod == NULL || result == NULL) {
700         return E_NULL_PTR;
701     }
702 
703     if (len == 0) {
704         return E_INVALID;
705     }
706 
707     // Initialize MAA memory
708     MXC_TPU_MAA_Mem_Clear();
709 
710     // Copy operands into the memory
711     if (clc == MXC_TPU_MAA_EXP) {
712         memcpy((void *)MAA_E, (uint32_t *)exp, len);
713     }
714     memcpy((void *)MAA_A, (uint32_t *)multiplier, len);
715     memcpy((void *)MAA_B, (uint32_t *)multiplicand, len);
716     memcpy((void *)MAA_M, (uint32_t *)mod, len);
717 
718     // Start MAA
719     MXC_SETFIELD(tpu->maa_ctrl, MXC_F_TPU_REVA_MAA_CTRL_CLC, clc);
720     tpu->maa_ctrl |= MXC_F_TPU_REVA_MAA_CTRL_STC;
721 
722     // Check if MAA Error occurs
723     if (tpu->maa_ctrl & MXC_F_TPU_REVA_MAA_CTRL_MAAER) {
724         return E_BAD_STATE;
725     }
726 
727     // Wait until operation is complete
728     while (!(tpu->ctrl & MXC_F_TPU_REVA_CTRL_MAA_DONE)) {}
729 
730     // load the output buffer
731     for (i = 0; i < (len / 4); i++) {
732         // Copy 4 bytes data
733         *(result + i) = (unsigned int)(*(maa_r + i));
734     }
735 
736     MXC_TPU_RevA_Clear_Done_Flags(tpu);
737 
738     return E_SUCCESS;
739 }
740