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