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