1 /*
2 * Copyright 2017-2022 NXP
3 * All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
8 #include "fsl_hashcrypt.h"
9
10 /* Component ID definition, used by tools. */
11 #ifndef FSL_COMPONENT_ID
12 #define FSL_COMPONENT_ID "platform.drivers.hashcrypt"
13 #endif
14
15 /*******************************************************************************
16 * Definitions
17 *******************************************************************************/
18
19 /*!< SHA-1 and SHA-256 block size */
20 #define SHA_BLOCK_SIZE 64U
21 /*!< max number of blocks that can be proccessed in one run (master mode) */
22 #define SHA_MASTER_MAX_BLOCKS 2048U
23 /*!< max number of blocks the SHA engine can copy, starting at MEMADDR */
24 #define SHA_MAX_BLOCK_COUNT 2047U
25
26 /*!< Use standard C library memcpy */
27 #define hashcrypt_memcpy memcpy
28
29 /*! Internal states of the HASH creation process */
30 typedef enum _hashcrypt_sha_algo_state
31 {
32 kHASHCRYPT_HashInit = 1u, /*!< Init state, the NEW bit in SHA Control register has not been written yet. */
33 kHASHCRYPT_HashUpdate, /*!< Update state, DIGEST registers contain running hash, NEW bit in SHA control register has
34 been written. */
35 } hashcrypt_sha_algo_state_t;
36
37 /*! 64-byte block represented as byte array of 16 32-bit words */
38 typedef union _sha_hash_block
39 {
40 uint32_t w[SHA_BLOCK_SIZE / 4]; /*!< array of 32-bit words */
41 uint8_t b[SHA_BLOCK_SIZE]; /*!< byte array */
42 } hashcrypt_sha_block_t;
43
44 /*! internal sha context structure */
45 typedef struct _hashcrypt_sha_ctx_internal
46 {
47 hashcrypt_sha_block_t blk; /*!< memory buffer. only full 64-byte blocks are written to SHA during hash updates */
48 size_t blksz; /*!< number of valid bytes in memory buffer */
49 hashcrypt_algo_t algo; /*!< selected algorithm from the set of supported algorithms */
50 hashcrypt_sha_algo_state_t state; /*!< finite machine state of the hash software process */
51 size_t fullMessageSize; /*!< track message size during SHA_Update(). The value is used for padding. */
52 uint32_t remainingBlcks; /*!< number of remaining blocks to process in AHB master mode */
53 hashcrypt_callback_t hashCallback; /*!< pointer to HASH callback function */
54 void
55 *userData; /*!< user data to be passed as an argument to callback function, once callback is invoked from isr */
56 #if defined(FSL_FEATURE_HASHCRYPT_HAS_RELOAD_FEATURE) && (FSL_FEATURE_HASHCRYPT_HAS_RELOAD_FEATURE > 0)
57 uint32_t runningHash[8]; /*!< running hash. up to SHA-256, that is 32 bytes. */
58 #endif
59 } hashcrypt_sha_ctx_internal_t;
60
61 #if defined(FSL_FEATURE_HASHCRYPT_HAS_RELOAD_FEATURE) && (FSL_FEATURE_HASHCRYPT_HAS_RELOAD_FEATURE > 0)
62 #define SHA1_LEN 5u
63 #define SHA256_LEN 8u
64 #endif
65
66 /*!< SHA-1 and SHA-256 digest length in bytes */
67 enum _hashcrypt_sha_digest_len
68 {
69 kHASHCRYPT_OutLenSha1 = 20u,
70 kHASHCRYPT_OutLenSha256 = 32u,
71 };
72
73 /*!< pointer to hash context structure used by isr */
74 static hashcrypt_hash_ctx_t *s_ctx;
75
76 /*!< macro for checking build time condition. It is used to assure the hashcrypt_sha_ctx_internal_t can fit into
77 * hashcrypt_hash_ctx_t */
78 #define BUILD_ASSERT(condition, msg) extern int msg[1 - 2 * (!(condition))] __attribute__((unused))
79
80 /*******************************************************************************
81 * Code
82 ******************************************************************************/
83
84 /*!
85 * @brief Swap bytes withing 32-bit word.
86 *
87 * This function changes endianess of a 32-bit word.
88 *
89 * @param in 32-bit unsigned integer
90 * @return 32-bit unsigned integer with different endianess (big endian to little endian and vice versa).
91 */
92
93 #define swap_bytes(in) __REV(in)
94
95 /*!
96 * @brief Increment a 16 byte integer.
97 *
98 * This function increments by one a 16 byte integer.
99 *
100 * @param input Pointer to a 16 byte integer to be incremented by one.
101 */
ctrIncrement(uint8_t * input)102 static void ctrIncrement(uint8_t *input)
103 {
104 int i = 15;
105 while (input[i] == (uint8_t)0xFFu)
106 {
107 input[i] = (uint8_t)0x00u;
108 i--;
109 if (i < 0)
110 {
111 return;
112 }
113 }
114
115 if (i >= 0)
116 {
117 input[i] += (uint8_t)1u;
118 }
119 }
120
121 /*!
122 * @brief Reads an unaligned word.
123 *
124 * This function creates a 32-bit word from an input array of four bytes.
125 *
126 * @param src Input array of four bytes. The array can start at any address in memory.
127 * @return 32-bit unsigned int created from the input byte array.
128 */
129
130 /* Force lower optimization for Keil, otherwise it replaces inline LDR with LDM */
131 #if defined(__CC_ARM)
132 #pragma push
133 #pragma O0
134 #endif
135
hashcrypt_get_word_from_unaligned(const uint8_t * srcAddr)136 static inline uint32_t hashcrypt_get_word_from_unaligned(const uint8_t *srcAddr)
137 {
138 #if (!(defined(__CORTEX_M)) || (defined(__CORTEX_M) && (__CORTEX_M == 0)))
139 register const uint8_t *src = srcAddr;
140 /* Cortex M0 does not support misaligned loads */
141 if (0U != ((uint32_t)src & 0x3u))
142 {
143 union _align_bytes_t
144 {
145 uint32_t word;
146 uint8_t byte[sizeof(uint32_t)];
147 } my_bytes;
148
149 my_bytes.byte[0] = *src;
150 my_bytes.byte[1] = src[1];
151 my_bytes.byte[2] = src[2];
152 my_bytes.byte[3] = src[3];
153 return my_bytes.word;
154 }
155 else
156 {
157 /* addr aligned to 0-modulo-4 so it is safe to type cast */
158 return *((const uint32_t *)(uint32_t)src);
159 }
160 #elif defined(__CC_ARM)
161 /* -O3 optimization in Keil 5.15 and 5.16a uses LDM instruction here (LDM r4!, {r0})
162 * which is wrong, because srcAddr might be unaligned.
163 * LDM on unaligned address causes hard-fault. in contrary,
164 * LDR supports unaligned address on Cortex M4 */
165
166 register uint32_t retVal;
167 __asm
168 {
169 LDR retVal, [srcAddr]
170 }
171 return retVal;
172 #else
173 return *((const uint32_t *)(uintptr_t)srcAddr);
174 #endif
175 }
176
177 /* End lower optimization */
178 #if defined(__CC_ARM)
179 #pragma pop
180 #endif
181
hashcrypt_get_key_from_unaligned_src(uint8_t * dest,const uint8_t * src,size_t size)182 static status_t hashcrypt_get_key_from_unaligned_src(uint8_t *dest, const uint8_t *src, size_t size)
183 {
184 status_t retVal = kStatus_InvalidArgument;
185 uint32_t i;
186
187 /* destination is SDK driver internal workspace and it must be aligned */
188 assert(0x0u == ((uint32_t)dest & 0x1u));
189 if (0U != ((uint32_t)dest & 0x1u))
190 {
191 return retVal;
192 }
193
194 for (i = 0; i < ((uint32_t)size / 4u); i++)
195 {
196 ((uint32_t *)(uintptr_t)dest)[i] = hashcrypt_get_word_from_unaligned(&src[i * sizeof(uint32_t)]);
197 }
198
199 return kStatus_Success;
200 }
201
202 /*!
203 * @brief LDM to SHA engine INDATA and ALIAS registers.
204 *
205 * This function writes 16 words starting from the src address (must be word aligned)
206 * to the dst address. Dst address does not increment (destination is peripheral module register INDATA).
207 * Src address increments to load 16 consecutive words.
208 *
209 * @param dst peripheral register address (word aligned)
210 * @param src address of the input 512-bit block (16 words) (word aligned)
211 *
212 */
hashcrypt_sha_ldm_stm_16_words(HASHCRYPT_Type * base,const uint32_t * src)213 __STATIC_FORCEINLINE void hashcrypt_sha_ldm_stm_16_words(HASHCRYPT_Type *base, const uint32_t *src)
214 {
215 /* Data Synchronization Barrier */
216 __DSB();
217 /*
218 typedef struct _one_block
219 {
220 uint32_t a[8];
221 } one_block_t;
222
223 volatile one_block_t *ldst = (void *)(uintptr_t)(&base->INDATA);
224 one_block_t *lsrc = (void *)(uintptr_t)src;
225 *ldst = lsrc[0];
226 *ldst = lsrc[1];
227 */
228
229 /* Data Synchronization Barrier prevent compiler from reordering memory write when -O2 or higher is used. */
230 /* The address is passed to the crypto engine for hashing below, therefore out */
231 /* of order memory write due to compiler optimization must be prevented. */
232 __DSB();
233
234 base->MEMADDR = HASHCRYPT_MEMADDR_BASE(src);
235 base->MEMCTRL = HASHCRYPT_MEMCTRL_MASTER(1) | HASHCRYPT_MEMCTRL_COUNT(1);
236
237 __DSB();
238 }
239
240 /*!
241 * @brief Loads data to Hashcrypt engine INDATA register.
242 *
243 * This function writes desired number of bytes starting from the src address
244 * to the dst address. Dst address does not increment (destination is peripheral module register INDATA).
245 * Src address increments to load consecutive words.
246 *
247 * @param src address of the input block
248 * @param size number of bytes to write
249 *
250 */
hashcrypt_load_data(HASHCRYPT_Type * base,uint32_t * src,size_t size)251 __STATIC_INLINE void hashcrypt_load_data(HASHCRYPT_Type *base, uint32_t *src, size_t size)
252 {
253 /* 16 bytes aligned input block */
254 uint32_t __attribute__((aligned(4))) inAlign[HASHCRYPT_AES_BLOCK_SIZE / sizeof(uint32_t)];
255 uint32_t *in;
256 uint8_t i;
257
258 in = src;
259 /* Check if address of src data is aligned */
260 if ((0U != ((uint32_t)in & 3U)))
261 {
262 for (i = 0; i < ((uint32_t)size / 4U); i++)
263 {
264 inAlign[i] = hashcrypt_get_word_from_unaligned((uint8_t *)&src[i]);
265 }
266 in = &inAlign[0];
267 }
268
269 if (size >= sizeof(uint32_t))
270 {
271 base->INDATA = in[0];
272 size -= sizeof(uint32_t);
273 }
274
275 for (uint32_t j = 0; j < size / 4U; j++)
276 {
277 base->ALIAS[j] = in[j + 1U];
278 }
279 }
280
281 /*!
282 * @brief Checks availability of HW AES key.
283 *
284 * This function checks if the AES key is present at dedicated hardware bus
285 * and can be used at actual security level.
286 *
287 * @param base HASHCRYPT peripheral base address
288 * @param handle Handle used for this request.
289 * @return kStatus_Success if available, kStatus_Fail otherwise.
290 *
291 */
hashcrypt_check_need_key(HASHCRYPT_Type * base,hashcrypt_handle_t * handle)292 static status_t hashcrypt_check_need_key(HASHCRYPT_Type *base, hashcrypt_handle_t *handle)
293 {
294 if (handle->keyType == kHASHCRYPT_SecretKey)
295 {
296 volatile uint32_t wait = 50u;
297 /* wait until STATUS register is non-zero */
298 while ((wait > 0U) && (base->STATUS == 0U))
299 {
300 wait--;
301 }
302 /* if NEEDKEY bit is not set, HW key is available */
303 if (0U == (base->STATUS & HASHCRYPT_STATUS_NEEDKEY_MASK))
304 {
305 return kStatus_Success;
306 }
307 /* NEEDKEY is set, HW key is not available */
308 return kStatus_Fail;
309 }
310 else
311 {
312 /* in case user key is used, return success */
313 return kStatus_Success;
314 }
315 }
316
317 /*!
318 * @brief Read OUTDATA registers.
319 *
320 * This function copies OUTDATA to output buffer.
321 *
322 * @param base Hachcrypt peripheral base address.
323 * @param[out] output Output buffer.
324 * @param Number of bytes to copy.
325 * @return kStatus_Success if no hashing error, kStatus_Fail otherwise.
326 */
hashcrypt_get_data(HASHCRYPT_Type * base,uint32_t * output,size_t outputSize)327 static status_t hashcrypt_get_data(HASHCRYPT_Type *base, uint32_t *output, size_t outputSize)
328 {
329 status_t status = kStatus_Fail;
330 uint32_t digest[8];
331
332 while ((0U == (base->STATUS & HASHCRYPT_STATUS_DIGEST_MASK)) &&
333 (0U == (base->STATUS & HASHCRYPT_STATUS_ERROR_MASK)))
334 {
335 }
336
337 if (0U == (base->STATUS & HASHCRYPT_STATUS_ERROR_MASK))
338 {
339 status = kStatus_Success;
340 }
341
342 /* Data Synchronization Barrier */
343 __DSB();
344
345 for (int i = 0; i < 8; i++)
346 {
347 digest[i] = swap_bytes(base->DIGEST0[i]);
348 }
349
350 if (outputSize > sizeof(digest))
351 {
352 outputSize = sizeof(digest);
353 }
354 (void)hashcrypt_memcpy(output, digest, outputSize);
355
356 return status;
357 }
358
359 /*!
360 * @brief Initialize the Hashcrypt engine for new operation.
361 *
362 * This function sets NEW and MODE fields in Hashcrypt Control register to start new operation.
363 *
364 * @param base Hashcrypt peripheral base address.
365 * @param hashcrypt_algo_t Internal context.
366 */
hashcrypt_engine_init(HASHCRYPT_Type * base,hashcrypt_algo_t algo)367 static void hashcrypt_engine_init(HASHCRYPT_Type *base, hashcrypt_algo_t algo)
368 {
369 /* NEW bit must be set before we switch from previous mode otherwise new mode will not work correctly */
370 base->CTRL = HASHCRYPT_CTRL_NEW_HASH(1);
371 base->CTRL = HASHCRYPT_CTRL_MODE(algo) | HASHCRYPT_CTRL_NEW_HASH(1);
372 }
373
374 /*!
375 * @brief Deinitialization of the Hashcrypt engine.
376 *
377 * This function sets MODE field in Hashcrypt Control register to zero - disabled.
378 * This reduces power consumption of HASHCRYPT.
379 *
380 * @param base Hashcrypt peripheral base address.
381 */
hashcrypt_engine_deinit(HASHCRYPT_Type * base)382 static inline void hashcrypt_engine_deinit(HASHCRYPT_Type *base)
383 {
384 base->CTRL &= ~(HASHCRYPT_CTRL_MODE_MASK);
385 }
386
387 /*!
388 * @brief Loads user key to INDATA register.
389 *
390 * This function writes user key stored in handle into HashCrypt INDATA register.
391 *
392 * @param base Hashcrypt peripheral base address.
393 * @param handle Handle used for this request.
394 */
hashcrypt_aes_load_userKey(HASHCRYPT_Type * base,hashcrypt_handle_t * handle)395 static void hashcrypt_aes_load_userKey(HASHCRYPT_Type *base, hashcrypt_handle_t *handle)
396 {
397 size_t keySize = 0;
398
399 switch (handle->keySize)
400 {
401 case kHASHCRYPT_Aes128:
402 keySize = 16;
403 break;
404 case kHASHCRYPT_Aes192:
405 keySize = 24;
406 break;
407 case kHASHCRYPT_Aes256:
408 keySize = 32;
409 break;
410 default:
411 /* All the cases have been listed above, the default clause should not be reached. */
412 break;
413 }
414 if (keySize == 0U)
415 {
416 return;
417 }
418 hashcrypt_load_data(base, &handle->keyWord[0], keySize);
419 }
420
421 /*!
422 * @brief Performs AES encryption/decryption of one data block.
423 *
424 * This function encrypts/decrypts one block of data with specified size.
425 *
426 * @param base Hashcrypt peripheral base address.
427 * @param input input data
428 * @param output output data
429 * @param size size of data block to process in bytes (must be 16bytes multiple).
430 */
hashcrypt_aes_one_block_aligned(HASHCRYPT_Type * base,const uint8_t * input,uint8_t * output,size_t size)431 static status_t hashcrypt_aes_one_block_aligned(HASHCRYPT_Type *base,
432 const uint8_t *input,
433 uint8_t *output,
434 size_t size)
435 {
436 status_t status = kStatus_Fail;
437 uint32_t idx = 0;
438
439 base->MEMADDR = HASHCRYPT_MEMADDR_BASE(input);
440 base->MEMCTRL = HASHCRYPT_MEMCTRL_MASTER(1) | HASHCRYPT_MEMCTRL_COUNT(size / 16U);
441 while (size >= HASHCRYPT_AES_BLOCK_SIZE)
442 {
443 /* Get result */
444 while ((0U == (base->STATUS & HASHCRYPT_STATUS_DIGEST_MASK)) &&
445 (0U == (base->STATUS & HASHCRYPT_STATUS_ERROR_MASK)))
446 {
447 }
448
449 for (int i = 0; i < 4; i++)
450 {
451 ((uint32_t *)(uintptr_t)output + idx)[i] = swap_bytes(base->DIGEST0[i]);
452 }
453
454 idx += HASHCRYPT_AES_BLOCK_SIZE / 4U;
455 size -= HASHCRYPT_AES_BLOCK_SIZE;
456 }
457
458 if (0U == (base->STATUS & HASHCRYPT_STATUS_ERROR_MASK))
459 {
460 status = kStatus_Success;
461 }
462
463 return status;
464 }
465
466 /*!
467 * @brief Performs AES encryption/decryption of one data block.
468 *
469 * This function encrypts/decrypts one block of data with specified size.
470 *
471 * @param base Hashcrypt peripheral base address.
472 * @param input input data
473 * @param output output data
474 * @param size size of data block to process in bytes (must be 16bytes multiple).
475 */
hashcrypt_aes_one_block_unaligned(HASHCRYPT_Type * base,const uint8_t * input,uint8_t * output,size_t size)476 static status_t hashcrypt_aes_one_block_unaligned(HASHCRYPT_Type *base,
477 const uint8_t *input,
478 uint8_t *output,
479 size_t size)
480 {
481 status_t status = kStatus_Fail;
482
483 /* we use AHB master mode as much as possible */
484 /* however, it can work only with aligned input data */
485 /* so, if unaligned, we do memcpy to temp buffer on stack, which is aligned, and use AHB mode to read data in */
486 /* then we read data back to it and do memcpy to the output buffer */
487 uint32_t temp[256 / sizeof(uint32_t)];
488 int cnt = 0;
489 while (size != 0U)
490 {
491 size_t actSz = size >= 256u ? 256u : size;
492 size_t actSzOrig = actSz;
493 (void)memcpy(temp, (const uint32_t *)(uintptr_t)(input + 256 * cnt), actSz);
494 size -= actSz;
495 base->MEMADDR = HASHCRYPT_MEMADDR_BASE(temp);
496 base->MEMCTRL = HASHCRYPT_MEMCTRL_MASTER(1) | HASHCRYPT_MEMCTRL_COUNT(actSz / 16U);
497 uint32_t outidx = 0;
498 while (actSz != 0U)
499 {
500 while ((0U == (base->STATUS & HASHCRYPT_STATUS_DIGEST_MASK)) &&
501 (0U == (base->STATUS & HASHCRYPT_STATUS_ERROR_MASK)))
502 {
503 }
504 for (int i = 0; i < 4; i++)
505 {
506 (temp + outidx)[i] = swap_bytes(base->DIGEST0[i]);
507 }
508 outidx += HASHCRYPT_AES_BLOCK_SIZE / 4U;
509 actSz -= HASHCRYPT_AES_BLOCK_SIZE;
510 }
511 (void)memcpy(output + 256 * cnt, (const uint8_t *)(uintptr_t)temp, actSzOrig);
512 cnt++;
513 }
514
515 if (0U == (base->STATUS & HASHCRYPT_STATUS_ERROR_MASK))
516 {
517 status = kStatus_Success;
518 }
519
520 return status;
521 }
522
523 /*!
524 * @brief Performs AES encryption/decryption of one data block.
525 *
526 * This function encrypts/decrypts one block of data with specified size.
527 *
528 * @param base Hashcrypt peripheral base address.
529 * @param input input data
530 * @param output output data
531 * @param size size of data block to process in bytes (must be 16bytes multiple).
532 */
hashcrypt_aes_one_block(HASHCRYPT_Type * base,const uint8_t * input,uint8_t * output,size_t size)533 static status_t hashcrypt_aes_one_block(HASHCRYPT_Type *base, const uint8_t *input, uint8_t *output, size_t size)
534 {
535 status_t status = kStatus_Fail;
536
537 /*MEMCTRL bitfield for COUNT is 11 bits, and this limits the number of blocks to process in one Master run to 2047
538 (2^11 -1) blocks . Each block is 16bytes long, so biggest data size which can we do in one Master run is (2047
539 blocks *16 bytes) = 32752 So, when size is overflowing HASHCRYPT_MEMCTRL_COUNT field of MEMCTRL register, we split
540 our data into more smaller chunks */
541
542 if (size > 32752U)
543
544 {
545 size_t numBlock = size / 32752U; /* number of blocks, each block is processed in one run*/
546 size_t remainingSize = size - (numBlock * 32752U); /* size of last block */
547
548 if ((0U != ((uint32_t)input & 0x3u)) || (0U != ((uint32_t)output & 0x3u))) /* If data is unaligned*/
549 {
550 for (uint32_t i = 0; i < numBlock; i++)
551 {
552 status = hashcrypt_aes_one_block_unaligned(base, input, output, 32752U);
553 input += 32752U;
554 output += 32752U;
555 }
556 status = hashcrypt_aes_one_block_unaligned(base, input, output, remainingSize);
557 }
558 else /* If data is aligned*/
559 {
560 for (uint32_t i = 0; i < numBlock; i++)
561 {
562 status = hashcrypt_aes_one_block_aligned(base, input, output, 32752U);
563 input += 32752U;
564 output += 32752U;
565 }
566 status = hashcrypt_aes_one_block_aligned(base, input, output, remainingSize);
567 }
568 }
569
570 else /* size is less than COUNT field of MEMCTRL register so we can process all data at once */
571 {
572 /* we use AHB master mode as much as possible */
573 /* however, it can work only with aligned input data */
574 /* so, if unaligned, we do memcpy to temp buffer on stack, which is aligned, and use AHB mode to read data in */
575 /* then we read data back to it and do memcpy to the output buffer */
576 if ((0U != ((uint32_t)input & 0x3u)) || (0U != ((uint32_t)output & 0x3u)))
577 {
578 status = hashcrypt_aes_one_block_unaligned(base, input, output, size);
579 }
580 else
581 {
582 status = hashcrypt_aes_one_block_aligned(base, input, output, size);
583 }
584 }
585 return status;
586 }
587
588 /*!
589 * @brief Check validity of algoritm.
590 *
591 * This function checks the validity of input argument.
592 *
593 * @param algo Tested algorithm value.
594 * @return kStatus_Success if valid, kStatus_InvalidArgument otherwise.
595 */
hashcrypt_sha_check_input_alg(HASHCRYPT_Type * base,hashcrypt_algo_t algo)596 static status_t hashcrypt_sha_check_input_alg(HASHCRYPT_Type *base, hashcrypt_algo_t algo)
597 {
598 if ((algo == kHASHCRYPT_Sha1) || (algo == kHASHCRYPT_Sha256))
599 {
600 return kStatus_Success;
601 }
602
603 return kStatus_InvalidArgument;
604 }
605
606 /*!
607 * @brief Check validity of input arguments.
608 *
609 * This function checks the validity of input arguments.
610 *
611 * @param base SHA peripheral base address.
612 * @param ctx Memory buffer given by user application where the SHA_Init/SHA_Update/SHA_Finish store context.
613 * @param algo Tested algorithm value.
614 * @return kStatus_Success if valid, kStatus_InvalidArgument otherwise.
615 */
hashcrypt_sha_check_input_args(HASHCRYPT_Type * base,hashcrypt_hash_ctx_t * ctx,hashcrypt_algo_t algo)616 static status_t hashcrypt_sha_check_input_args(HASHCRYPT_Type *base, hashcrypt_hash_ctx_t *ctx, hashcrypt_algo_t algo)
617 {
618 /* Check validity of input algorithm */
619 if (kStatus_Success != hashcrypt_sha_check_input_alg(base, algo))
620 {
621 return kStatus_InvalidArgument;
622 }
623
624 if ((NULL == ctx) || (NULL == base))
625 {
626 return kStatus_InvalidArgument;
627 }
628
629 return kStatus_Success;
630 }
631
632 /*!
633 * @brief Check validity of internal software context.
634 *
635 * This function checks if the internal context structure looks correct.
636 *
637 * @param ctxInternal Internal context.
638 * @return kStatus_Success if valid, kStatus_InvalidArgument otherwise.
639 */
hashcrypt_sha_check_context(HASHCRYPT_Type * base,hashcrypt_sha_ctx_internal_t * ctxInternal)640 static status_t hashcrypt_sha_check_context(HASHCRYPT_Type *base, hashcrypt_sha_ctx_internal_t *ctxInternal)
641 {
642 if ((NULL == ctxInternal) || (kStatus_Success != hashcrypt_sha_check_input_alg(base, ctxInternal->algo)))
643 {
644 return kStatus_InvalidArgument;
645 }
646 return kStatus_Success;
647 }
648
649 /*!
650 * @brief Load 512-bit block (16 words) into SHA engine.
651 *
652 * This function aligns the input block and moves it into SHA engine INDATA.
653 * CPU polls the WAITING bit and then moves data by using LDM and STM instructions.
654 *
655 * @param base SHA peripheral base address.
656 * @param blk 512-bit block
657 */
hashcrypt_sha_one_block(HASHCRYPT_Type * base,const uint8_t * blk)658 static void hashcrypt_sha_one_block(HASHCRYPT_Type *base, const uint8_t *blk)
659 {
660 uint32_t temp[SHA_BLOCK_SIZE / sizeof(uint32_t)];
661 const uint32_t *actBlk;
662
663 /* make sure the 512-bit block is word aligned */
664 if (0U != ((uintptr_t)blk & 0x3u))
665 {
666 (void)hashcrypt_memcpy(temp, (const uint32_t *)(uintptr_t)blk, SHA_BLOCK_SIZE);
667 actBlk = (const uint32_t *)(uintptr_t)temp;
668 }
669 else
670 {
671 actBlk = (const uint32_t *)(uintptr_t)blk;
672 }
673
674 /* poll waiting. */
675 while (0U == (base->STATUS & HASHCRYPT_STATUS_WAITING_MASK))
676 {
677 }
678 /* feed INDATA (and ALIASes). use STM instruction. */
679 hashcrypt_sha_ldm_stm_16_words(base, actBlk);
680 }
681
682 /*!
683 * @brief Adds message to current hash.
684 *
685 * This function merges the message to fill the internal buffer, empties the internal buffer if
686 * it becomes full, then process all remaining message data.
687 *
688 *
689 * @param base SHA peripheral base address.
690 * @param ctxInternal Internal context.
691 * @param message Input message.
692 * @param messageSize Size of input message in bytes.
693 * @return kStatus_Success if message hashed, kStatus_Fail otherwise.
694 */
hashcrypt_sha_process_message_data(HASHCRYPT_Type * base,hashcrypt_sha_ctx_internal_t * ctxInternal,const uint8_t * message,size_t messageSize)695 static status_t hashcrypt_sha_process_message_data(HASHCRYPT_Type *base,
696 hashcrypt_sha_ctx_internal_t *ctxInternal,
697 const uint8_t *message,
698 size_t messageSize)
699 {
700 status_t status = kStatus_Fail;
701
702 /* first fill the internal buffer to full block */
703 if (ctxInternal->blksz != 0U)
704 {
705 size_t toCopy = SHA_BLOCK_SIZE - ctxInternal->blksz;
706 (void)hashcrypt_memcpy(&ctxInternal->blk.b[ctxInternal->blksz], message, toCopy);
707 message += toCopy;
708 messageSize -= toCopy;
709
710 /* process full internal block */
711 hashcrypt_sha_one_block(base, &ctxInternal->blk.b[0]);
712 }
713
714 /* process all full blocks in message[] */
715 if (messageSize >= SHA_BLOCK_SIZE)
716 {
717 if (0U != ((uintptr_t)message & 0x3u))
718 {
719 while (messageSize >= SHA_BLOCK_SIZE)
720 {
721 hashcrypt_sha_one_block(base, message);
722 message += SHA_BLOCK_SIZE;
723 messageSize -= SHA_BLOCK_SIZE;
724 }
725 }
726 else
727 {
728 /* number of blocks and number of rounds needed to compute hash */
729 uint32_t blkNum = (messageSize >> 6); /* div by 64 bytes */
730 uint32_t blkFullRounds = blkNum / SHA_MAX_BLOCK_COUNT;
731
732 /* feed the SHA engine with the maximum possible number of blocks */
733 while (blkFullRounds >= 1U)
734 {
735 /* poll waiting. */
736 while (0U == (base->STATUS & HASHCRYPT_STATUS_WAITING_MASK))
737 {
738 }
739 uint32_t blkBytes = SHA_MAX_BLOCK_COUNT * 64u; /* number of bytes in maximum block count */
740
741 __DSB();
742 base->MEMADDR = HASHCRYPT_MEMADDR_BASE(message);
743 base->MEMCTRL = HASHCRYPT_MEMCTRL_MASTER(1) | HASHCRYPT_MEMCTRL_COUNT(SHA_MAX_BLOCK_COUNT);
744 __DSB();
745
746 while ((0U == (base->STATUS & HASHCRYPT_STATUS_DIGEST_MASK)) &&
747 (0U == (base->STATUS & HASHCRYPT_STATUS_ERROR_MASK)))
748 {
749 }
750 message += blkBytes;
751 messageSize -= blkBytes;
752 blkFullRounds -= 1U;
753 blkNum -= SHA_MAX_BLOCK_COUNT;
754 }
755
756 if (blkNum != 0U)
757 {
758 /* same as above, but only for the remaining number of blocks < SHA_MAX_BLOCK_COUNT */
759 while (0U == (base->STATUS & HASHCRYPT_STATUS_WAITING_MASK))
760 {
761 }
762 uint32_t blkBytes = blkNum * 64u; /* number of bytes in 64 bytes blocks */
763
764 __DSB();
765 base->MEMADDR = HASHCRYPT_MEMADDR_BASE(message);
766 base->MEMCTRL = HASHCRYPT_MEMCTRL_MASTER(1) | HASHCRYPT_MEMCTRL_COUNT(blkNum);
767 __DSB();
768
769 while ((0U == (base->STATUS & HASHCRYPT_STATUS_DIGEST_MASK)) &&
770 (0U == (base->STATUS & HASHCRYPT_STATUS_ERROR_MASK)))
771 {
772 }
773 message += blkBytes;
774 messageSize -= blkBytes;
775 }
776 }
777 }
778
779 if (0U == (base->STATUS & HASHCRYPT_STATUS_ERROR_MASK))
780 {
781 status = kStatus_Success;
782 }
783
784 /* copy last incomplete message bytes into internal block */
785 (void)hashcrypt_memcpy(&ctxInternal->blk.b[0], message, messageSize);
786 ctxInternal->blksz = messageSize;
787 return status;
788 }
789
790 /*!
791 * @brief Finalize the running hash to make digest.
792 *
793 * This function empties the internal buffer, adds padding bits, and generates final digest.
794 *
795 * @param base SHA peripheral base address.
796 * @param ctxInternal Internal context.
797 * @return kStatus_Success if finalized, kStatus_Fail otherwise.
798 */
hashcrypt_sha_finalize(HASHCRYPT_Type * base,hashcrypt_sha_ctx_internal_t * ctxInternal)799 static status_t hashcrypt_sha_finalize(HASHCRYPT_Type *base, hashcrypt_sha_ctx_internal_t *ctxInternal)
800 {
801 status_t status = kStatus_Fail;
802 hashcrypt_sha_block_t lastBlock;
803
804 (void)memset(&lastBlock, 0, sizeof(hashcrypt_sha_block_t));
805
806 /* this is last call, so need to flush buffered message bytes along with padding */
807 if (ctxInternal->blksz <= 55u)
808 {
809 /* last data is 440 bits or less. */
810 (void)hashcrypt_memcpy(&lastBlock.b[0], &ctxInternal->blk.b[0], ctxInternal->blksz);
811 lastBlock.b[ctxInternal->blksz] = (uint8_t)0x80U;
812 lastBlock.w[SHA_BLOCK_SIZE / 4U - 1U] = swap_bytes(8u * ctxInternal->fullMessageSize);
813 hashcrypt_sha_one_block(base, &lastBlock.b[0]);
814 }
815 else
816 {
817 if (ctxInternal->blksz < SHA_BLOCK_SIZE)
818 {
819 ctxInternal->blk.b[ctxInternal->blksz] = (uint8_t)0x80U;
820 for (uint32_t i = ctxInternal->blksz + 1u; i < SHA_BLOCK_SIZE; i++)
821 {
822 ctxInternal->blk.b[i] = 0;
823 }
824 }
825 else
826 {
827 lastBlock.b[0] = (uint8_t)0x80U;
828 }
829
830 hashcrypt_sha_one_block(base, &ctxInternal->blk.b[0]);
831 lastBlock.w[SHA_BLOCK_SIZE / 4U - 1U] = swap_bytes(8u * ctxInternal->fullMessageSize);
832 hashcrypt_sha_one_block(base, &lastBlock.b[0]);
833 }
834 /* poll wait for final digest */
835 while ((0U == (base->STATUS & HASHCRYPT_STATUS_DIGEST_MASK)) &&
836 (0U == (base->STATUS & HASHCRYPT_STATUS_ERROR_MASK)))
837 {
838 }
839
840 if (0U == (base->STATUS & HASHCRYPT_STATUS_ERROR_MASK))
841 {
842 status = kStatus_Success;
843 }
844
845 return status;
846 }
847
hashcrypt_save_running_hash(HASHCRYPT_Type * base,hashcrypt_sha_ctx_internal_t * ctxInternal)848 static status_t hashcrypt_save_running_hash(HASHCRYPT_Type *base, hashcrypt_sha_ctx_internal_t *ctxInternal)
849 {
850 #if defined(FSL_FEATURE_HASHCRYPT_HAS_RELOAD_FEATURE) && (FSL_FEATURE_HASHCRYPT_HAS_RELOAD_FEATURE > 0)
851 status_t status = kStatus_Fail;
852 size_t len = (ctxInternal->algo == kHASHCRYPT_Sha1) ? SHA1_LEN : SHA256_LEN;
853
854 /* Wait until digest is ready */
855 while ((0U == (base->STATUS & HASHCRYPT_STATUS_DIGEST_MASK)) &&
856 (0U == (base->STATUS & HASHCRYPT_STATUS_ERROR_MASK)))
857 {
858 }
859
860 /* Store partial digest to context */
861 for (uint32_t i = 0; i < len; i++)
862 {
863 ctxInternal->runningHash[i] = base->DIGEST0[i];
864 }
865
866 if (0U == (base->STATUS & HASHCRYPT_STATUS_ERROR_MASK))
867 {
868 status = kStatus_Success;
869 }
870
871 return status;
872 #else
873 return kStatus_Success;
874 #endif
875 }
876
hashcrypt_restore_running_hash(HASHCRYPT_Type * base,hashcrypt_sha_ctx_internal_t * ctxInternal)877 static void hashcrypt_restore_running_hash(HASHCRYPT_Type *base, hashcrypt_sha_ctx_internal_t *ctxInternal)
878 {
879 #if defined(FSL_FEATURE_HASHCRYPT_HAS_RELOAD_FEATURE) && (FSL_FEATURE_HASHCRYPT_HAS_RELOAD_FEATURE > 0)
880 size_t len = (ctxInternal->algo == kHASHCRYPT_Sha1) ? SHA1_LEN : SHA256_LEN;
881
882 /* When switching from different mode, need to set NEW bit to work properly */
883 if ((base->CTRL & HASHCRYPT_CTRL_MODE_MASK) != HASHCRYPT_CTRL_MODE(ctxInternal->algo))
884 {
885 base->CTRL = HASHCRYPT_CTRL_NEW_HASH(1);
886 base->CTRL = HASHCRYPT_CTRL_MODE(ctxInternal->algo) | HASHCRYPT_CTRL_NEW_HASH(1);
887 }
888 /* Set RELOAD bit to allow registers to be used */
889 base->CTRL |= HASHCRYPT_CTRL_RELOAD_MASK;
890
891 /* Reload partial hash digest */
892 for (uint32_t i = 0; i < len; i++)
893 {
894 base->RELOAD[i] = ctxInternal->runningHash[i];
895 }
896 /* Clear RELOAD register before continuing */
897 base->CTRL &= ~HASHCRYPT_CTRL_RELOAD_MASK;
898 #endif
899 }
900
HASHCRYPT_SHA(HASHCRYPT_Type * base,hashcrypt_algo_t algo,const uint8_t * input,size_t inputSize,uint8_t * output,size_t * outputSize)901 status_t HASHCRYPT_SHA(HASHCRYPT_Type *base,
902 hashcrypt_algo_t algo,
903 const uint8_t *input,
904 size_t inputSize,
905 uint8_t *output,
906 size_t *outputSize)
907 {
908 hashcrypt_hash_ctx_t hashCtx;
909 status_t status;
910
911 status = HASHCRYPT_SHA_Init(base, &hashCtx, algo);
912 if (status != kStatus_Success)
913 {
914 return status;
915 }
916
917 status = HASHCRYPT_SHA_Update(base, &hashCtx, input, inputSize);
918 if (status != kStatus_Success)
919 {
920 return status;
921 }
922
923 status = HASHCRYPT_SHA_Finish(base, &hashCtx, output, outputSize);
924
925 return status;
926 }
927
HASHCRYPT_SHA_Init(HASHCRYPT_Type * base,hashcrypt_hash_ctx_t * ctx,hashcrypt_algo_t algo)928 status_t HASHCRYPT_SHA_Init(HASHCRYPT_Type *base, hashcrypt_hash_ctx_t *ctx, hashcrypt_algo_t algo)
929 {
930 status_t status;
931
932 hashcrypt_sha_ctx_internal_t *ctxInternal;
933 /* compile time check for the correct structure size */
934 BUILD_ASSERT(sizeof(hashcrypt_hash_ctx_t) >= sizeof(hashcrypt_sha_ctx_internal_t), hashcrypt_hash_ctx_t_size);
935
936 status = hashcrypt_sha_check_input_args(base, ctx, algo);
937 if (status != kStatus_Success)
938 {
939 return status;
940 }
941
942 /* set algorithm in context struct for later use */
943 ctxInternal = (hashcrypt_sha_ctx_internal_t *)(uint32_t)ctx;
944 ctxInternal->algo = algo;
945 ctxInternal->blksz = 0u;
946 #ifdef HASHCRYPT_SHA_DO_WIPE_CONTEXT
947 for (int i = 0; i < sizeof(ctxInternal->blk.w) / sizeof(ctxInternal->blk.w[0]); i++)
948 {
949 ctxInternal->blk.w[i] = 0u;
950 }
951 #endif /* HASHCRYPT_SHA_DO_WIPE_CONTEXT */
952 ctxInternal->state = kHASHCRYPT_HashInit;
953 ctxInternal->fullMessageSize = 0;
954 return kStatus_Success;
955 }
956
HASHCRYPT_SHA_Update(HASHCRYPT_Type * base,hashcrypt_hash_ctx_t * ctx,const uint8_t * input,size_t inputSize)957 status_t HASHCRYPT_SHA_Update(HASHCRYPT_Type *base, hashcrypt_hash_ctx_t *ctx, const uint8_t *input, size_t inputSize)
958 {
959 bool isUpdateState;
960 status_t status;
961 hashcrypt_sha_ctx_internal_t *ctxInternal;
962 size_t blockSize;
963
964 if (inputSize == 0U)
965 {
966 return kStatus_Success;
967 }
968
969 ctxInternal = (hashcrypt_sha_ctx_internal_t *)(uint32_t)ctx;
970 #ifdef HASHCRYPT_SHA_DO_CHECK_CONTEXT
971 status = hashcrypt_sha_check_context(base, ctxInternal);
972 if (kStatus_Success != status)
973 {
974 return status;
975 }
976 #endif /* HASHCRYPT_SHA_DO_CHECK_CONTEXT */
977
978 ctxInternal->fullMessageSize += inputSize;
979 blockSize = SHA_BLOCK_SIZE;
980 /* if we are still less than 64 bytes, keep only in context */
981 if ((ctxInternal->blksz + inputSize) <= blockSize)
982 {
983 (void)hashcrypt_memcpy((&ctxInternal->blk.b[0]) + ctxInternal->blksz, input, inputSize);
984 ctxInternal->blksz += inputSize;
985 return kStatus_Success;
986 }
987 else
988 {
989 isUpdateState = ctxInternal->state == kHASHCRYPT_HashUpdate;
990 if (!isUpdateState)
991 {
992 /* start NEW hash */
993 hashcrypt_engine_init(base, ctxInternal->algo);
994 ctxInternal->state = kHASHCRYPT_HashUpdate;
995 }
996 else
997 {
998 hashcrypt_restore_running_hash(base, ctxInternal);
999 }
1000 }
1001
1002 /* process message data */
1003 /* Data Synchronization Barrier */
1004 __DSB();
1005 status = hashcrypt_sha_process_message_data(base, ctxInternal, input, inputSize);
1006 if (kStatus_Success != status)
1007 {
1008 return status;
1009 }
1010
1011 __DSB();
1012 status = hashcrypt_save_running_hash(base, ctxInternal);
1013 return status;
1014 }
1015
HASHCRYPT_SHA_Finish(HASHCRYPT_Type * base,hashcrypt_hash_ctx_t * ctx,uint8_t * output,size_t * outputSize)1016 status_t HASHCRYPT_SHA_Finish(HASHCRYPT_Type *base, hashcrypt_hash_ctx_t *ctx, uint8_t *output, size_t *outputSize)
1017 {
1018 size_t algOutSize = 0;
1019 status_t status;
1020 hashcrypt_sha_ctx_internal_t *ctxInternal;
1021 #ifdef HASHCRYPT_SHA_DO_CHECK_CONTEXT
1022 uint32_t *ctxW;
1023 uint32_t i;
1024 #endif /* HASHCRYPT_SHA_DO_CHECK_CONTEXT */
1025
1026 if (output == NULL)
1027 {
1028 return kStatus_InvalidArgument;
1029 }
1030
1031 ctxInternal = (hashcrypt_sha_ctx_internal_t *)(uint32_t)ctx;
1032 #ifdef HASHCRYPT_SHA_DO_CHECK_CONTEXT
1033 status = hashcrypt_sha_check_context(base, ctxInternal);
1034 if (kStatus_Success != status)
1035 {
1036 return status;
1037 }
1038 #endif /* HASHCRYPT_SHA_DO_CHECK_CONTEXT */
1039
1040 if (ctxInternal->state == kHASHCRYPT_HashInit)
1041 {
1042 hashcrypt_engine_init(base, ctxInternal->algo);
1043 }
1044 else
1045 {
1046 hashcrypt_restore_running_hash(base, ctxInternal);
1047 }
1048
1049 size_t outSize = 0u;
1050
1051 /* compute algorithm output length */
1052 switch (ctxInternal->algo)
1053 {
1054 case kHASHCRYPT_Sha1:
1055 outSize = (size_t)kHASHCRYPT_OutLenSha1;
1056 break;
1057 case kHASHCRYPT_Sha256:
1058 outSize = (size_t)kHASHCRYPT_OutLenSha256;
1059 break;
1060 default:
1061 /* All the cases have been listed above, the default clause should not be reached. */
1062 break;
1063 }
1064 algOutSize = outSize;
1065
1066 /* flush message last incomplete block, if there is any, and add padding bits */
1067 status = hashcrypt_sha_finalize(base, ctxInternal);
1068 if (kStatus_Success != status)
1069 {
1070 return status;
1071 }
1072
1073 if (outputSize != NULL)
1074 {
1075 if (algOutSize < *outputSize)
1076 {
1077 *outputSize = algOutSize;
1078 }
1079 else
1080 {
1081 algOutSize = *outputSize;
1082 }
1083 }
1084
1085 status = hashcrypt_get_data(base, (uint32_t *)(uintptr_t)output, algOutSize);
1086 if (kStatus_Success != status)
1087 {
1088 return status;
1089 }
1090
1091 #ifdef HASHCRYPT_SHA_DO_WIPE_CONTEXT
1092 ctxW = (uint32_t *)ctx;
1093 for (i = 0; i < HASHCRYPT_HASH_CTX_SIZE; i++)
1094 {
1095 ctxW[i] = 0u;
1096 }
1097 #endif /* HASHCRYPT_SHA_DO_WIPE_CONTEXT */
1098 return status;
1099 }
1100
HASHCRYPT_SHA_SetCallback(HASHCRYPT_Type * base,hashcrypt_hash_ctx_t * ctx,hashcrypt_callback_t callback,void * userData)1101 void HASHCRYPT_SHA_SetCallback(HASHCRYPT_Type *base,
1102 hashcrypt_hash_ctx_t *ctx,
1103 hashcrypt_callback_t callback,
1104 void *userData)
1105 {
1106 hashcrypt_sha_ctx_internal_t *ctxInternal;
1107
1108 s_ctx = ctx;
1109 ctxInternal = (hashcrypt_sha_ctx_internal_t *)(uint32_t)ctx;
1110 ctxInternal->hashCallback = callback;
1111 ctxInternal->userData = userData;
1112
1113 (void)EnableIRQ(HASHCRYPT_IRQn);
1114 }
1115
HASHCRYPT_SHA_UpdateNonBlocking(HASHCRYPT_Type * base,hashcrypt_hash_ctx_t * ctx,const uint8_t * input,size_t inputSize)1116 status_t HASHCRYPT_SHA_UpdateNonBlocking(HASHCRYPT_Type *base,
1117 hashcrypt_hash_ctx_t *ctx,
1118 const uint8_t *input,
1119 size_t inputSize)
1120 {
1121 hashcrypt_sha_ctx_internal_t *ctxInternal;
1122 uint32_t numBlocks;
1123 status_t status;
1124
1125 if (inputSize == 0U)
1126 {
1127 return kStatus_Success;
1128 }
1129
1130 if (0U != ((uintptr_t)input & 0x3U))
1131 {
1132 return kStatus_Fail;
1133 }
1134
1135 ctxInternal = (hashcrypt_sha_ctx_internal_t *)(uint32_t)ctx;
1136 status = hashcrypt_sha_check_context(base, ctxInternal);
1137 if (kStatus_Success != status)
1138 {
1139 return status;
1140 }
1141
1142 ctxInternal->fullMessageSize = inputSize;
1143 ctxInternal->remainingBlcks = inputSize / SHA_BLOCK_SIZE;
1144 ctxInternal->blksz = inputSize % SHA_BLOCK_SIZE;
1145
1146 /* copy last incomplete block to context */
1147 if ((ctxInternal->blksz > 0U) && (ctxInternal->blksz <= SHA_BLOCK_SIZE))
1148 {
1149 (void)hashcrypt_memcpy((&ctxInternal->blk.b[0]), input + SHA_BLOCK_SIZE * ctxInternal->remainingBlcks,
1150 ctxInternal->blksz);
1151 }
1152
1153 if (ctxInternal->remainingBlcks >= SHA_MASTER_MAX_BLOCKS)
1154 {
1155 numBlocks = SHA_MASTER_MAX_BLOCKS - 1U;
1156 }
1157 else
1158 {
1159 numBlocks = ctxInternal->remainingBlcks;
1160 }
1161 /* update remainingBlks so that ISR can run another hash if necessary */
1162 ctxInternal->remainingBlcks -= numBlocks;
1163
1164 /* compute hash using AHB Master mode for full blocks */
1165 if (numBlocks > 0U)
1166 {
1167 ctxInternal->state = kHASHCRYPT_HashUpdate;
1168 hashcrypt_engine_init(base, ctxInternal->algo);
1169
1170 /* Enable digest and error interrupts and start hash */
1171 base->INTENSET = HASHCRYPT_INTENCLR_DIGEST_MASK | HASHCRYPT_INTENCLR_ERROR_MASK;
1172 base->MEMADDR = HASHCRYPT_MEMADDR_BASE(input);
1173 base->MEMCTRL = HASHCRYPT_MEMCTRL_MASTER(1) | HASHCRYPT_MEMCTRL_COUNT(numBlocks);
1174 }
1175 /* no full blocks, invoke callback directly */
1176 else
1177 {
1178 ctxInternal->hashCallback(HASHCRYPT, ctx, status, ctxInternal->userData);
1179 }
1180
1181 return status;
1182 }
1183
HASHCRYPT_AES_SetKey(HASHCRYPT_Type * base,hashcrypt_handle_t * handle,const uint8_t * key,size_t keySize)1184 status_t HASHCRYPT_AES_SetKey(HASHCRYPT_Type *base, hashcrypt_handle_t *handle, const uint8_t *key, size_t keySize)
1185 {
1186 status_t retVal = kStatus_InvalidArgument;
1187
1188 switch (keySize)
1189 {
1190 case 16:
1191 handle->keySize = kHASHCRYPT_Aes128;
1192 break;
1193 case 24:
1194 handle->keySize = kHASHCRYPT_Aes192;
1195 break;
1196 case 32:
1197 handle->keySize = kHASHCRYPT_Aes256;
1198 break;
1199 default:
1200 handle->keySize = kHASHCRYPT_InvalidKey;
1201 break;
1202 }
1203
1204 if (handle->keySize == kHASHCRYPT_InvalidKey)
1205 {
1206 return retVal;
1207 }
1208
1209 if (handle->keyType == kHASHCRYPT_SecretKey)
1210 {
1211 /* for kHASHCRYPT_SecretKey just return Success */
1212 retVal = kStatus_Success;
1213 }
1214 else if (handle->keyType == kHASHCRYPT_UserKey)
1215 {
1216 retVal = hashcrypt_get_key_from_unaligned_src((uint8_t *)&handle->keyWord[0], key, keySize);
1217 }
1218 else
1219 {
1220 retVal = kStatus_InvalidArgument;
1221 }
1222
1223 return retVal;
1224 }
1225
HASHCRYPT_AES_EncryptEcb(HASHCRYPT_Type * base,hashcrypt_handle_t * handle,const uint8_t * plaintext,uint8_t * ciphertext,size_t size)1226 status_t HASHCRYPT_AES_EncryptEcb(
1227 HASHCRYPT_Type *base, hashcrypt_handle_t *handle, const uint8_t *plaintext, uint8_t *ciphertext, size_t size)
1228 {
1229 status_t status = kStatus_Fail;
1230
1231 if ((0U != (size % 16u)) || (handle->keySize == kHASHCRYPT_InvalidKey))
1232 {
1233 return kStatus_InvalidArgument;
1234 }
1235
1236 uint32_t keyType = (handle->keyType == kHASHCRYPT_UserKey) ? 0U : 1u;
1237 base->CRYPTCFG = HASHCRYPT_CRYPTCFG_AESMODE(kHASHCRYPT_AesEcb) | HASHCRYPT_CRYPTCFG_AESDECRYPT(AES_ENCRYPT) |
1238 HASHCRYPT_CRYPTCFG_AESSECRET(keyType) | HASHCRYPT_CRYPTCFG_AESKEYSZ(handle->keySize) |
1239 HASHCRYPT_CRYPTCFG_MSW1ST_OUT(1) | HASHCRYPT_CRYPTCFG_SWAPKEY(1) | HASHCRYPT_CRYPTCFG_SWAPDAT(1) |
1240 HASHCRYPT_CRYPTCFG_MSW1ST(1);
1241
1242 hashcrypt_engine_init(base, kHASHCRYPT_Aes);
1243
1244 /* in case of HW AES key, check if it is available */
1245 if (hashcrypt_check_need_key(base, handle) != kStatus_Success)
1246 {
1247 hashcrypt_engine_deinit(base);
1248 return kStatus_Fail;
1249 }
1250
1251 /* load key if kHASHCRYPT_UserKey is selected */
1252 if (handle->keyType == kHASHCRYPT_UserKey)
1253 {
1254 hashcrypt_aes_load_userKey(base, handle);
1255 }
1256
1257 /* load message and get result */
1258 status = hashcrypt_aes_one_block(base, plaintext, ciphertext, size);
1259 /* After processing all data, hashcrypt engine is set to disabled to lower power consumption */
1260 hashcrypt_engine_deinit(base);
1261
1262 return status;
1263 }
1264
HASHCRYPT_AES_DecryptEcb(HASHCRYPT_Type * base,hashcrypt_handle_t * handle,const uint8_t * ciphertext,uint8_t * plaintext,size_t size)1265 status_t HASHCRYPT_AES_DecryptEcb(
1266 HASHCRYPT_Type *base, hashcrypt_handle_t *handle, const uint8_t *ciphertext, uint8_t *plaintext, size_t size)
1267 {
1268 status_t status = kStatus_Fail;
1269
1270 if ((0U != (size % 16u)) || (handle->keySize == kHASHCRYPT_InvalidKey))
1271 {
1272 return kStatus_InvalidArgument;
1273 }
1274
1275 uint32_t keyType = (handle->keyType == kHASHCRYPT_UserKey) ? 0U : 1u;
1276 base->CRYPTCFG = HASHCRYPT_CRYPTCFG_AESMODE(kHASHCRYPT_AesEcb) | HASHCRYPT_CRYPTCFG_AESDECRYPT(AES_DECRYPT) |
1277 HASHCRYPT_CRYPTCFG_AESSECRET(keyType) | HASHCRYPT_CRYPTCFG_AESKEYSZ(handle->keySize) |
1278 HASHCRYPT_CRYPTCFG_MSW1ST_OUT(1) | HASHCRYPT_CRYPTCFG_SWAPKEY(1) | HASHCRYPT_CRYPTCFG_SWAPDAT(1) |
1279 HASHCRYPT_CRYPTCFG_MSW1ST(1);
1280
1281 hashcrypt_engine_init(base, kHASHCRYPT_Aes);
1282
1283 /* in case of HW AES key, check if it is available */
1284 if (hashcrypt_check_need_key(base, handle) != kStatus_Success)
1285 {
1286 hashcrypt_engine_deinit(base);
1287 return kStatus_Fail;
1288 }
1289
1290 /* load key if kHASHCRYPT_UserKey is selected */
1291 if (handle->keyType == kHASHCRYPT_UserKey)
1292 {
1293 hashcrypt_aes_load_userKey(base, handle);
1294 }
1295
1296 /* load message and get result */
1297 status = hashcrypt_aes_one_block(base, ciphertext, plaintext, size);
1298
1299 /* After processing all data, hashcrypt engine is set to disabled to lower power consumption */
1300 hashcrypt_engine_deinit(base);
1301 return status;
1302 }
1303
HASHCRYPT_AES_EncryptCbc(HASHCRYPT_Type * base,hashcrypt_handle_t * handle,const uint8_t * plaintext,uint8_t * ciphertext,size_t size,const uint8_t iv[16])1304 status_t HASHCRYPT_AES_EncryptCbc(HASHCRYPT_Type *base,
1305 hashcrypt_handle_t *handle,
1306 const uint8_t *plaintext,
1307 uint8_t *ciphertext,
1308 size_t size,
1309 const uint8_t iv[16])
1310 {
1311 status_t status = kStatus_Fail;
1312
1313 if (0U != ((size % 16u)) || (handle->keySize == kHASHCRYPT_InvalidKey))
1314 {
1315 return kStatus_InvalidArgument;
1316 }
1317
1318 uint32_t keyType = (handle->keyType == kHASHCRYPT_UserKey) ? 0U : 1u;
1319 base->CRYPTCFG = HASHCRYPT_CRYPTCFG_AESMODE(kHASHCRYPT_AesCbc) | HASHCRYPT_CRYPTCFG_AESDECRYPT(AES_ENCRYPT) |
1320 HASHCRYPT_CRYPTCFG_AESSECRET(keyType) | HASHCRYPT_CRYPTCFG_AESKEYSZ(handle->keySize) |
1321 HASHCRYPT_CRYPTCFG_MSW1ST_OUT(1) | HASHCRYPT_CRYPTCFG_SWAPKEY(1) | HASHCRYPT_CRYPTCFG_SWAPDAT(1) |
1322 HASHCRYPT_CRYPTCFG_MSW1ST(1);
1323
1324 hashcrypt_engine_init(base, kHASHCRYPT_Aes);
1325
1326 /* in case of HW AES key, check if it is available */
1327 if (hashcrypt_check_need_key(base, handle) != kStatus_Success)
1328 {
1329 hashcrypt_engine_deinit(base);
1330 return kStatus_Fail;
1331 }
1332
1333 /* load key if kHASHCRYPT_UserKey is selected */
1334 if (handle->keyType == kHASHCRYPT_UserKey)
1335 {
1336 hashcrypt_aes_load_userKey(base, handle);
1337 }
1338
1339 /* load 16b iv */
1340 hashcrypt_load_data(base, (uint32_t *)(uintptr_t)iv, 16);
1341
1342 /* load message and get result */
1343 status = hashcrypt_aes_one_block(base, plaintext, ciphertext, size);
1344
1345 /* After processing all data, hashcrypt engine is set to disabled to lower power consumption */
1346 hashcrypt_engine_deinit(base);
1347 return status;
1348 }
1349
HASHCRYPT_AES_DecryptCbc(HASHCRYPT_Type * base,hashcrypt_handle_t * handle,const uint8_t * ciphertext,uint8_t * plaintext,size_t size,const uint8_t iv[16])1350 status_t HASHCRYPT_AES_DecryptCbc(HASHCRYPT_Type *base,
1351 hashcrypt_handle_t *handle,
1352 const uint8_t *ciphertext,
1353 uint8_t *plaintext,
1354 size_t size,
1355 const uint8_t iv[16])
1356 {
1357 status_t status = kStatus_Fail;
1358
1359 if ((0U != (size % 16u)) || (handle->keySize == kHASHCRYPT_InvalidKey))
1360 {
1361 return kStatus_InvalidArgument;
1362 }
1363
1364 uint32_t keyType = (handle->keyType == kHASHCRYPT_UserKey) ? 0U : 1u;
1365 base->CRYPTCFG = HASHCRYPT_CRYPTCFG_AESMODE(kHASHCRYPT_AesCbc) | HASHCRYPT_CRYPTCFG_AESDECRYPT(AES_DECRYPT) |
1366 HASHCRYPT_CRYPTCFG_AESSECRET(keyType) | HASHCRYPT_CRYPTCFG_AESKEYSZ(handle->keySize) |
1367 HASHCRYPT_CRYPTCFG_MSW1ST_OUT(1) | HASHCRYPT_CRYPTCFG_SWAPKEY(1) | HASHCRYPT_CRYPTCFG_SWAPDAT(1) |
1368 HASHCRYPT_CRYPTCFG_MSW1ST(1);
1369
1370 hashcrypt_engine_init(base, kHASHCRYPT_Aes);
1371
1372 /* in case of HW AES key, check if it is available */
1373 if (hashcrypt_check_need_key(base, handle) != kStatus_Success)
1374 {
1375 hashcrypt_engine_deinit(base);
1376 return kStatus_Fail;
1377 }
1378
1379 /* load key if kHASHCRYPT_UserKey is selected */
1380 if (handle->keyType == kHASHCRYPT_UserKey)
1381 {
1382 hashcrypt_aes_load_userKey(base, handle);
1383 }
1384
1385 /* load iv */
1386 hashcrypt_load_data(base, (uint32_t *)(uintptr_t)iv, 16);
1387
1388 /* load message and get result */
1389 status = hashcrypt_aes_one_block(base, ciphertext, plaintext, size);
1390
1391 /* After processing all data, hashcrypt engine is set to disabled to lower power consumption */
1392 hashcrypt_engine_deinit(base);
1393 return status;
1394 }
1395
HASHCRYPT_AES_CryptCtr(HASHCRYPT_Type * base,hashcrypt_handle_t * handle,const uint8_t * input,uint8_t * output,size_t size,uint8_t counter[HASHCRYPT_AES_BLOCK_SIZE],uint8_t counterlast[HASHCRYPT_AES_BLOCK_SIZE],size_t * szLeft)1396 status_t HASHCRYPT_AES_CryptCtr(HASHCRYPT_Type *base,
1397 hashcrypt_handle_t *handle,
1398 const uint8_t *input,
1399 uint8_t *output,
1400 size_t size,
1401 uint8_t counter[HASHCRYPT_AES_BLOCK_SIZE],
1402 uint8_t counterlast[HASHCRYPT_AES_BLOCK_SIZE],
1403 size_t *szLeft)
1404 {
1405 uint32_t lastSize;
1406 uint8_t lastBlock[HASHCRYPT_AES_BLOCK_SIZE] = {0};
1407 uint8_t *lastEncryptedCounter;
1408 status_t status = kStatus_Fail;
1409
1410 if (handle->keySize == kHASHCRYPT_InvalidKey)
1411 {
1412 return kStatus_InvalidArgument;
1413 }
1414
1415 uint32_t keyType = (handle->keyType == kHASHCRYPT_UserKey) ? 0U : 1u;
1416 base->CRYPTCFG = HASHCRYPT_CRYPTCFG_AESMODE(kHASHCRYPT_AesCtr) | HASHCRYPT_CRYPTCFG_AESDECRYPT(AES_ENCRYPT) |
1417 HASHCRYPT_CRYPTCFG_AESSECRET(keyType) | HASHCRYPT_CRYPTCFG_AESKEYSZ(handle->keySize) |
1418 HASHCRYPT_CRYPTCFG_MSW1ST_OUT(1) | HASHCRYPT_CRYPTCFG_SWAPKEY(1) | HASHCRYPT_CRYPTCFG_SWAPDAT(1) |
1419 HASHCRYPT_CRYPTCFG_MSW1ST(1);
1420
1421 hashcrypt_engine_init(base, kHASHCRYPT_Aes);
1422
1423 /* in case of HW AES key, check if it is available */
1424 if (hashcrypt_check_need_key(base, handle) != kStatus_Success)
1425 {
1426 hashcrypt_engine_deinit(base);
1427 return kStatus_Fail;
1428 }
1429
1430 /* load key if kHASHCRYPT_UserKey is selected */
1431 if (handle->keyType == kHASHCRYPT_UserKey)
1432 {
1433 hashcrypt_aes_load_userKey(base, handle);
1434 }
1435
1436 /* load nonce */
1437 hashcrypt_load_data(base, (uint32_t *)(uintptr_t)counter, 16);
1438
1439 lastSize = size % HASHCRYPT_AES_BLOCK_SIZE;
1440 size -= lastSize;
1441
1442 /* encrypt full 16byte blocks */
1443 status = hashcrypt_aes_one_block(base, input, output, size);
1444 if (status != kStatus_Success)
1445 {
1446 hashcrypt_engine_deinit(base);
1447 return status;
1448 }
1449
1450 while (size != 0U)
1451 {
1452 ctrIncrement(counter);
1453 size -= 16u;
1454 input += 16;
1455 output += 16;
1456 }
1457
1458 if (lastSize != 0U)
1459 {
1460 if (counterlast != NULL)
1461 {
1462 lastEncryptedCounter = counterlast;
1463 }
1464 else
1465 {
1466 lastEncryptedCounter = lastBlock;
1467 }
1468
1469 /* Perform encryption with all zeros to get last counter. XOR with zeros doesn't change. */
1470 status = hashcrypt_aes_one_block(base, lastBlock, lastEncryptedCounter, HASHCRYPT_AES_BLOCK_SIZE);
1471 if (status != kStatus_Success)
1472 {
1473 hashcrypt_engine_deinit(base);
1474 return status;
1475 }
1476 /* remain output = input XOR counterlast */
1477 for (uint32_t i = 0; i < lastSize; i++)
1478 {
1479 output[i] = input[i] ^ lastEncryptedCounter[i];
1480 }
1481 /* Increment counter parameter */
1482 ctrIncrement(counter);
1483 }
1484 else
1485 {
1486 lastSize = HASHCRYPT_AES_BLOCK_SIZE;
1487 /* no remaining bytes in couterlast so clearing it */
1488 if (counterlast != NULL)
1489 {
1490 (void)memset(counterlast, 0, HASHCRYPT_AES_BLOCK_SIZE);
1491 }
1492 }
1493
1494 if (szLeft != NULL)
1495 {
1496 *szLeft = HASHCRYPT_AES_BLOCK_SIZE - lastSize;
1497 }
1498
1499 /* After processing all data, hashcrypt engine is set to disabled to lower power consumption */
1500 hashcrypt_engine_deinit(base);
1501 return kStatus_Success;
1502 }
1503
HASHCRYPT_AES_CryptOfb(HASHCRYPT_Type * base,hashcrypt_handle_t * handle,const uint8_t * input,uint8_t * output,size_t size,const uint8_t iv[HASHCRYPT_AES_BLOCK_SIZE])1504 status_t HASHCRYPT_AES_CryptOfb(HASHCRYPT_Type *base,
1505 hashcrypt_handle_t *handle,
1506 const uint8_t *input,
1507 uint8_t *output,
1508 size_t size,
1509 const uint8_t iv[HASHCRYPT_AES_BLOCK_SIZE])
1510 {
1511 status_t status = kStatus_Fail;
1512 uint8_t zeroes[HASHCRYPT_AES_BLOCK_SIZE] = {0};
1513 uint8_t blockOutput[HASHCRYPT_AES_BLOCK_SIZE] = {0};
1514
1515 if (handle->keySize == kHASHCRYPT_InvalidKey)
1516 {
1517 return kStatus_InvalidArgument;
1518 }
1519
1520 uint32_t keyType = (handle->keyType == kHASHCRYPT_UserKey) ? 0U : 1u;
1521
1522 base->CRYPTCFG = HASHCRYPT_CRYPTCFG_AESMODE(kHASHCRYPT_AesCbc) | HASHCRYPT_CRYPTCFG_AESDECRYPT(AES_ENCRYPT) |
1523 HASHCRYPT_CRYPTCFG_AESSECRET(keyType) | HASHCRYPT_CRYPTCFG_AESKEYSZ(handle->keySize) |
1524 HASHCRYPT_CRYPTCFG_MSW1ST_OUT(1) | HASHCRYPT_CRYPTCFG_SWAPKEY(1) | HASHCRYPT_CRYPTCFG_SWAPDAT(1) |
1525 HASHCRYPT_CRYPTCFG_MSW1ST(1);
1526
1527 hashcrypt_engine_init(base, kHASHCRYPT_Aes);
1528
1529 /* in case of HW AES key, check if it is available */
1530 if (hashcrypt_check_need_key(base, handle) != kStatus_Success)
1531 {
1532 hashcrypt_engine_deinit(base);
1533 return kStatus_Fail;
1534 }
1535
1536 /* load key if kHASHCRYPT_UserKey is selected */
1537 if (handle->keyType == kHASHCRYPT_UserKey)
1538 {
1539 hashcrypt_aes_load_userKey(base, handle);
1540 }
1541
1542 /* load iv */
1543 hashcrypt_load_data(base, (uint32_t *)(uintptr_t)iv, HASHCRYPT_AES_BLOCK_SIZE);
1544
1545 /*Use AES CBC mode and feed input with zeroes as input*/
1546 /*Output block is then XORed with input*/
1547
1548 while (size >= 16u)
1549 {
1550 status = hashcrypt_aes_one_block(base, zeroes, blockOutput, HASHCRYPT_AES_BLOCK_SIZE);
1551 if (status != kStatus_Success)
1552 {
1553 hashcrypt_engine_deinit(base);
1554 return status;
1555 }
1556 /* XOR input with output block to get output*/
1557 for (uint32_t i = 0; i < HASHCRYPT_AES_BLOCK_SIZE; i++)
1558 {
1559 output[i] = input[i] ^ blockOutput[i];
1560 }
1561 size -= 16u;
1562 output += 16;
1563 input += 16;
1564 }
1565
1566 /* OFB can have non-block multiple size.*/
1567 if (size != 0U)
1568 {
1569 status = hashcrypt_aes_one_block(base, zeroes, blockOutput, HASHCRYPT_AES_BLOCK_SIZE);
1570 if (status != kStatus_Success)
1571 {
1572 hashcrypt_engine_deinit(base);
1573 return status;
1574 }
1575
1576 /* XOR input with output block to get output*/
1577 for (uint32_t i = 0; i < size; i++)
1578 {
1579 output[i] = input[i] ^ blockOutput[i];
1580 }
1581 }
1582
1583 /* After processing all data, hashcrypt engine is set to disabled to lower power consumption */
1584 hashcrypt_engine_deinit(base);
1585 return status;
1586 }
1587
HASHCRYPT_AES_EncryptCfb(HASHCRYPT_Type * base,hashcrypt_handle_t * handle,const uint8_t * plaintext,uint8_t * ciphertext,size_t size,const uint8_t iv[HASHCRYPT_AES_BLOCK_SIZE])1588 status_t HASHCRYPT_AES_EncryptCfb(HASHCRYPT_Type *base,
1589 hashcrypt_handle_t *handle,
1590 const uint8_t *plaintext,
1591 uint8_t *ciphertext,
1592 size_t size,
1593 const uint8_t iv[HASHCRYPT_AES_BLOCK_SIZE])
1594 {
1595 status_t status = kStatus_Fail;
1596 uint8_t zeroes[HASHCRYPT_AES_BLOCK_SIZE] = {0};
1597 uint8_t blockOutput[HASHCRYPT_AES_BLOCK_SIZE] = {0};
1598
1599 /* For CFB mode size must be 16-byte multiple */
1600 if ((0U != (size % 16u)) || (handle->keySize == kHASHCRYPT_InvalidKey))
1601 {
1602 return kStatus_InvalidArgument;
1603 }
1604
1605 uint32_t keyType = (handle->keyType == kHASHCRYPT_UserKey) ? 0U : 1u;
1606
1607 base->CRYPTCFG = HASHCRYPT_CRYPTCFG_AESMODE(kHASHCRYPT_AesCbc) | HASHCRYPT_CRYPTCFG_AESDECRYPT(AES_ENCRYPT) |
1608 HASHCRYPT_CRYPTCFG_AESSECRET(keyType) | HASHCRYPT_CRYPTCFG_AESKEYSZ(handle->keySize) |
1609 HASHCRYPT_CRYPTCFG_MSW1ST_OUT(1) | HASHCRYPT_CRYPTCFG_SWAPKEY(1) | HASHCRYPT_CRYPTCFG_SWAPDAT(1) |
1610 HASHCRYPT_CRYPTCFG_MSW1ST(1);
1611
1612 hashcrypt_engine_init(base, kHASHCRYPT_Aes);
1613
1614 /* in case of HW AES key, check if it is available */
1615 if (hashcrypt_check_need_key(base, handle) != kStatus_Success)
1616 {
1617 hashcrypt_engine_deinit(base);
1618 return kStatus_Fail;
1619 }
1620
1621 /* load key if kHASHCRYPT_UserKey is selected */
1622 if (handle->keyType == kHASHCRYPT_UserKey)
1623 {
1624 hashcrypt_aes_load_userKey(base, handle);
1625 }
1626
1627 /* load iv */
1628 hashcrypt_load_data(base, (uint32_t *)(uintptr_t)iv, HASHCRYPT_AES_BLOCK_SIZE);
1629
1630 /*Use AES CBC mode and feed input with zeroes for first block */
1631 /*Output block is then XORed with plaintext to get ciphertext*/
1632
1633 status = hashcrypt_aes_one_block(base, zeroes, blockOutput, HASHCRYPT_AES_BLOCK_SIZE);
1634 if (status != kStatus_Success)
1635 {
1636 hashcrypt_engine_deinit(base);
1637 return status;
1638 }
1639 /* XOR plaintext with output block to get ciphertext*/
1640 for (uint32_t i = 0; i < HASHCRYPT_AES_BLOCK_SIZE; i++)
1641 {
1642 ciphertext[i] = plaintext[i] ^ blockOutput[i];
1643 }
1644 size -= 16u;
1645
1646 /*Remaining blocks use previous plaintext as input for aes block function */
1647 while (size >= 16u)
1648 {
1649 status = hashcrypt_aes_one_block(base, plaintext, blockOutput, HASHCRYPT_AES_BLOCK_SIZE);
1650 ciphertext += 16;
1651 plaintext += 16;
1652
1653 if (status != kStatus_Success)
1654 {
1655 hashcrypt_engine_deinit(base);
1656 return status;
1657 }
1658 /* XOR plaintext with output block to get ciphertext*/
1659 for (uint32_t i = 0; i < HASHCRYPT_AES_BLOCK_SIZE; i++)
1660 {
1661 ciphertext[i] = plaintext[i] ^ blockOutput[i];
1662 }
1663 size -= 16u;
1664 }
1665
1666 /* After processing all data, hashcrypt engine is set to disabled to lower power consumption */
1667 hashcrypt_engine_deinit(base);
1668 return status;
1669 }
1670
HASHCRYPT_AES_DecryptCfb(HASHCRYPT_Type * base,hashcrypt_handle_t * handle,const uint8_t * ciphertext,uint8_t * plaintext,size_t size,const uint8_t iv[HASHCRYPT_AES_BLOCK_SIZE])1671 status_t HASHCRYPT_AES_DecryptCfb(HASHCRYPT_Type *base,
1672 hashcrypt_handle_t *handle,
1673 const uint8_t *ciphertext,
1674 uint8_t *plaintext,
1675 size_t size,
1676 const uint8_t iv[HASHCRYPT_AES_BLOCK_SIZE])
1677 {
1678 status_t status = kStatus_Fail;
1679 uint8_t zeroes[HASHCRYPT_AES_BLOCK_SIZE] = {0};
1680 uint8_t blockOutput[HASHCRYPT_AES_BLOCK_SIZE] = {0};
1681
1682 /* For CFB mode size must be 16-byte multiple */
1683 if ((0U != (size % 16u)) || (handle->keySize == kHASHCRYPT_InvalidKey))
1684 {
1685 return kStatus_InvalidArgument;
1686 }
1687
1688 uint32_t keyType = (handle->keyType == kHASHCRYPT_UserKey) ? 0U : 1u;
1689
1690 base->CRYPTCFG = HASHCRYPT_CRYPTCFG_AESMODE(kHASHCRYPT_AesCbc) | HASHCRYPT_CRYPTCFG_AESDECRYPT(AES_ENCRYPT) |
1691 HASHCRYPT_CRYPTCFG_AESSECRET(keyType) | HASHCRYPT_CRYPTCFG_AESKEYSZ(handle->keySize) |
1692 HASHCRYPT_CRYPTCFG_MSW1ST_OUT(1) | HASHCRYPT_CRYPTCFG_SWAPKEY(1) | HASHCRYPT_CRYPTCFG_SWAPDAT(1) |
1693 HASHCRYPT_CRYPTCFG_MSW1ST(1);
1694
1695 hashcrypt_engine_init(base, kHASHCRYPT_Aes);
1696
1697 /* in case of HW AES key, check if it is available */
1698 if (hashcrypt_check_need_key(base, handle) != kStatus_Success)
1699 {
1700 hashcrypt_engine_deinit(base);
1701 return kStatus_Fail;
1702 }
1703
1704 /* load key if kHASHCRYPT_UserKey is selected */
1705 if (handle->keyType == kHASHCRYPT_UserKey)
1706 {
1707 hashcrypt_aes_load_userKey(base, handle);
1708 }
1709
1710 /* load iv */
1711 hashcrypt_load_data(base, (uint32_t *)(uintptr_t)iv, HASHCRYPT_AES_BLOCK_SIZE);
1712
1713 /*Use AES CBC mode and feed input with zeroes for first block */
1714 /*Output block is then XORed with ciphertext to get plaintext*/
1715
1716 status = hashcrypt_aes_one_block(base, zeroes, blockOutput, HASHCRYPT_AES_BLOCK_SIZE);
1717 if (status != kStatus_Success)
1718 {
1719 hashcrypt_engine_deinit(base);
1720 return status;
1721 }
1722 /* XOR ciphertext with output block to get plaintext*/
1723 for (uint32_t i = 0; i < HASHCRYPT_AES_BLOCK_SIZE; i++)
1724 {
1725 plaintext[i] = ciphertext[i] ^ blockOutput[i];
1726 }
1727 size -= 16u;
1728
1729 /*Remaining blocks use previous plaintext as input for aes block function */
1730 while (size >= 16u)
1731 {
1732 status = hashcrypt_aes_one_block(base, plaintext, blockOutput, HASHCRYPT_AES_BLOCK_SIZE);
1733 ciphertext += 16;
1734 plaintext += 16;
1735
1736 if (status != kStatus_Success)
1737 {
1738 hashcrypt_engine_deinit(base);
1739 return status;
1740 }
1741 /* XOR plaintext with ciphertext block to get plaintext*/
1742 for (uint32_t i = 0; i < HASHCRYPT_AES_BLOCK_SIZE; i++)
1743 {
1744 plaintext[i] = ciphertext[i] ^ blockOutput[i];
1745 }
1746 size -= 16u;
1747 }
1748
1749 /* After processing all data, hashcrypt engine is set to disabled to lower power consumption */
1750 hashcrypt_engine_deinit(base);
1751 return status;
1752 }
1753
1754 void HASHCRYPT_DriverIRQHandler(void);
HASHCRYPT_DriverIRQHandler(void)1755 void HASHCRYPT_DriverIRQHandler(void)
1756 {
1757 hashcrypt_sha_ctx_internal_t *ctxInternal;
1758 HASHCRYPT_Type *base = HASHCRYPT;
1759 uint32_t numBlocks;
1760 status_t status;
1761
1762 ctxInternal = (hashcrypt_sha_ctx_internal_t *)(uint32_t)s_ctx;
1763
1764 if (0U == (base->STATUS & HASHCRYPT_STATUS_ERROR_MASK))
1765 {
1766 if (ctxInternal->remainingBlcks > 0U)
1767 {
1768 if (ctxInternal->remainingBlcks >= SHA_MASTER_MAX_BLOCKS)
1769 {
1770 numBlocks = SHA_MASTER_MAX_BLOCKS - 1U;
1771 }
1772 else
1773 {
1774 numBlocks = ctxInternal->remainingBlcks;
1775 }
1776 /* some blocks still remaining, update remainingBlcks for next ISR and start another hash */
1777 ctxInternal->remainingBlcks -= numBlocks;
1778 base->MEMCTRL = HASHCRYPT_MEMCTRL_MASTER(1) | HASHCRYPT_MEMCTRL_COUNT(numBlocks);
1779 return;
1780 }
1781 /* no full blocks left, disable interrupts and AHB master mode */
1782 base->INTENCLR = HASHCRYPT_INTENCLR_DIGEST_MASK | HASHCRYPT_INTENCLR_ERROR_MASK;
1783 base->MEMCTRL = HASHCRYPT_MEMCTRL_MASTER(0);
1784 status = hashcrypt_save_running_hash(base, ctxInternal);
1785 }
1786 else
1787 {
1788 status = kStatus_Fail;
1789 }
1790
1791 /* Invoke callback if there is one */
1792 if (NULL != ctxInternal->hashCallback)
1793 {
1794 ctxInternal->hashCallback(HASHCRYPT, s_ctx, status, ctxInternal->userData);
1795 }
1796 }
1797
HASHCRYPT_Init(HASHCRYPT_Type * base)1798 void HASHCRYPT_Init(HASHCRYPT_Type *base)
1799 {
1800 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
1801 CLOCK_EnableClock(kCLOCK_HashCrypt);
1802 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
1803 RESET_PeripheralReset(kHASHCRYPT_RST_SHIFT_RSTn);
1804 }
1805
HASHCRYPT_Deinit(HASHCRYPT_Type * base)1806 void HASHCRYPT_Deinit(HASHCRYPT_Type *base)
1807 {
1808 RESET_SetPeripheralReset(kHASHCRYPT_RST_SHIFT_RSTn);
1809 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
1810 CLOCK_DisableClock(kCLOCK_HashCrypt);
1811 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
1812 }
1813