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