1 /*
2  * Copyright (c) 2015-2016, Freescale Semiconductor, Inc.
3  * Copyright 2016-2020 NXP
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 #include "fsl_ltc.h"
10 
11 /*******************************************************************************
12  * Definitions
13  ******************************************************************************/
14 
15 /* Component ID definition, used by tools. */
16 #ifndef FSL_COMPONENT_ID
17 #define FSL_COMPONENT_ID "platform.drivers.ltc"
18 #endif
19 
20 #define LTC_FIFO_SZ_MAX_DOWN_ALGN (0xff0u)
21 
22 #define LTC_AES_GCM_TYPE_AAD 55
23 #define LTC_AES_GCM_TYPE_IV  0
24 
25 #define LTC_CCM_TAG_IDX 8 /*! For CCM encryption, the encrypted final MAC is written to the context word 8-11 */
26 #define LTC_GCM_TAG_IDX 0 /*! For GCM encryption, the encrypted final MAC is written to the context word 0-3 */
27 
28 enum _ltc_md_dk_bit_shift
29 {
30     kLTC_ModeRegBitShiftDK = 12U,
31 };
32 
33 /*! @brief LTC status flags */
34 enum _ltc_status_flag
35 {
36     kLTC_StatusAesBusy = 1U << LTC_STA_AB_SHIFT,
37 #if defined(FSL_FEATURE_LTC_HAS_DES) && FSL_FEATURE_LTC_HAS_DES
38     kLTC_StatusDesBusy = 1U << LTC_STA_DB_SHIFT,
39 #endif /* FSL_FEATURE_LTC_HAS_DES */
40 #if defined(FSL_FEATURE_LTC_HAS_PKHA) && FSL_FEATURE_LTC_HAS_PKHA
41     kLTC_StatusPkhaBusy = 1U << LTC_STA_PB_SHIFT,
42 #endif /* FSL_FEATURE_LTC_HAS_PKHA */
43 #if defined(FSL_FEATURE_LTC_HAS_SHA) && FSL_FEATURE_LTC_HAS_SHA
44     kLTC_StatusMdhaBusy = 1U << LTC_STA_MB_SHIFT,
45 #endif /* FSL_FEATURE_LTC_HAS_SHA */
46     kLTC_StatusDoneIsr  = 1U << LTC_STA_DI_SHIFT,
47     kLTC_StatusErrorIsr = 1U << LTC_STA_EI_SHIFT,
48 #if defined(FSL_FEATURE_LTC_HAS_PKHA) && FSL_FEATURE_LTC_HAS_PKHA
49     kLTC_StatusPublicKeyPrime  = 1U << LTC_STA_PKP_SHIFT,
50     kLTC_StatusPublicKeyOpOne  = 1U << LTC_STA_PKO_SHIFT,
51     kLTC_StatusPublicKeyOpZero = 1U << LTC_STA_PKZ_SHIFT,
52 #endif /* FSL_FEATURE_LTC_HAS_PKHA */
53     kLTC_StatusAll = LTC_STA_AB_MASK |
54 #if defined(FSL_FEATURE_LTC_HAS_DES) && FSL_FEATURE_LTC_HAS_DES
55                      LTC_STA_DB_MASK |
56 #endif /* FSL_FEATURE_LTC_HAS_DES */
57 #if defined(FSL_FEATURE_LTC_HAS_SHA) && FSL_FEATURE_LTC_HAS_SHA
58                      LTC_STA_MB_MASK |
59 #endif /* FSL_FEATURE_LTC_HAS_SHA */
60                      LTC_STA_DI_MASK | LTC_STA_EI_MASK
61 #if defined(FSL_FEATURE_LTC_HAS_PKHA) && FSL_FEATURE_LTC_HAS_PKHA
62                      | LTC_STA_PB_MASK | LTC_STA_PKP_MASK | LTC_STA_PKO_MASK | LTC_STA_PKZ_MASK
63 #endif /* FSL_FEATURE_LTC_HAS_PKHA */
64 };
65 
66 /*! @brief LTC clear register */
67 typedef enum _ltc_clear_written
68 {
69     kLTC_ClearMode     = 1U << LTC_CW_CM_SHIFT,
70     kLTC_ClearDataSize = 1U << LTC_CW_CDS_SHIFT,
71     kLTC_ClearIcvSize  = 1U << LTC_CW_CICV_SHIFT,
72     kLTC_ClearContext  = 1U << LTC_CW_CCR_SHIFT,
73     kLTC_ClearKey      = 1U << LTC_CW_CKR_SHIFT,
74 #if defined(FSL_FEATURE_LTC_HAS_PKHA) && FSL_FEATURE_LTC_HAS_PKHA
75     kLTC_ClearPkhaSizeA = 1U << LTC_CW_CPKA_SHIFT,
76     kLTC_ClearPkhaSizeB = 1U << LTC_CW_CPKB_SHIFT,
77     kLTC_ClearPkhaSizeN = 1U << LTC_CW_CPKN_SHIFT,
78     kLTC_ClearPkhaSizeE = 1U << LTC_CW_CPKE_SHIFT,
79     kLTC_ClearAllSize   = (int)kLTC_ClearPkhaSizeA | kLTC_ClearPkhaSizeB | kLTC_ClearPkhaSizeN | kLTC_ClearPkhaSizeE,
80 #endif /* FSL_FEATURE_LTC_HAS_PKHA */
81     kLTC_ClearOutputFifo = 1U << LTC_CW_COF_SHIFT,
82     kLTC_ClearInputFifo  = (int)(1U << LTC_CW_CIF_SHIFT),
83     kLTC_ClearAll = (int)(LTC_CW_CM_MASK | LTC_CW_CDS_MASK | LTC_CW_CICV_MASK | LTC_CW_CCR_MASK | LTC_CW_CKR_MASK |
84 #if defined(FSL_FEATURE_LTC_HAS_PKHA) && FSL_FEATURE_LTC_HAS_PKHA
85                           LTC_CW_CPKA_MASK | LTC_CW_CPKB_MASK | LTC_CW_CPKN_MASK | LTC_CW_CPKE_MASK |
86 #endif /* FSL_FEATURE_LTC_HAS_PKHA */
87                           LTC_CW_COF_MASK | LTC_CW_CIF_MASK)
88 } ltc_clear_written_t;
89 
90 enum _ltc_ctrl_swap
91 {
92     kLTC_CtrlSwapAll =
93         LTC_CTL_IFS_MASK | LTC_CTL_OFS_MASK | LTC_CTL_KIS_MASK | LTC_CTL_KOS_MASK | LTC_CTL_CIS_MASK | LTC_CTL_COS_MASK,
94 };
95 
96 /*! @brief Type used in GCM and CCM modes.
97 
98     Content of a block is established via individual bytes and moved to LTC
99    IFIFO by moving 32-bit words.
100 */
101 typedef union _ltc_xcm_block_t
102 {
103     uint32_t w[4]; /*!< LTC context register is 16 bytes written as four 32-bit words */
104     uint8_t b[16]; /*!< 16 octets block for CCM B0 and CTR0 and for GCM */
105 } ltc_xcm_block_t;
106 
107 #if defined(FSL_FEATURE_LTC_HAS_PKHA) && FSL_FEATURE_LTC_HAS_PKHA
108 
109 /*! @brief PKHA functions - arithmetic, copy/clear memory. */
110 typedef enum _ltc_pkha_func_t
111 {
112     kLTC_PKHA_ClearMem           = 1U,
113     kLTC_PKHA_ArithModAdd        = 2U,  /*!< (A + B) mod N */
114     kLTC_PKHA_ArithModSub1       = 3U,  /*!< (A - B) mod N */
115     kLTC_PKHA_ArithModSub2       = 4U,  /*!< (B - A) mod N */
116     kLTC_PKHA_ArithModMul        = 5U,  /*!< (A x B) mod N */
117     kLTC_PKHA_ArithModExp        = 6U,  /*!< (A^E) mod N */
118     kLTC_PKHA_ArithModRed        = 7U,  /*!< (A) mod N */
119     kLTC_PKHA_ArithModInv        = 8U,  /*!< (A^-1) mod N */
120     kLTC_PKHA_ArithEccAdd        = 9U,  /*!< (P1 + P2) */
121     kLTC_PKHA_ArithEccDouble     = 10U, /*!< (P2 + P2) */
122     kLTC_PKHA_ArithEccMul        = 11U, /*!< (E x P1) */
123     kLTC_PKHA_ArithModR2         = 12U, /*!< (R^2 mod N) */
124     kLTC_PKHA_ArithGcd           = 14U, /*!< GCD (A, N) */
125     kLTC_PKHA_ArithPrimalityTest = 15U, /*!< Miller-Rabin */
126     kLTC_PKHA_CopyMemSizeN       = 16U,
127     kLTC_PKHA_CopyMemSizeSrc     = 17U,
128 } ltc_pkha_func_t;
129 
130 /*! @brief Register areas for PKHA clear memory operations. */
131 typedef enum _ltc_pkha_reg_area
132 {
133     kLTC_PKHA_RegA   = 8U,
134     kLTC_PKHA_RegB   = 4U,
135     kLTC_PKHA_RegE   = 2U,
136     kLTC_PKHA_RegN   = 1U,
137     kLTC_PKHA_RegAll = kLTC_PKHA_RegA | kLTC_PKHA_RegB | kLTC_PKHA_RegE | kLTC_PKHA_RegN,
138 } ltc_pkha_reg_area_t;
139 
140 /*! @brief Quadrant areas for 2048-bit registers for PKHA copy memory
141  * operations. */
142 typedef enum _ltc_pkha_quad_area_t
143 {
144     kLTC_PKHA_Quad0 = 0U,
145     kLTC_PKHA_Quad1 = 1U,
146     kLTC_PKHA_Quad2 = 2U,
147     kLTC_PKHA_Quad3 = 3U,
148 } ltc_pkha_quad_area_t;
149 
150 /*! @brief User-supplied (R^2 mod N) input or LTC should calculate. */
151 typedef enum _ltc_pkha_r2_t
152 {
153     kLTC_PKHA_CalcR2  = 0U, /*!< Calculate (R^2 mod N) */
154     kLTC_PKHA_InputR2 = 1U  /*!< (R^2 mod N) supplied as input */
155 } ltc_pkha_r2_t;
156 
157 /*! @brief LTC PKHA parameters */
158 typedef struct _ltc_pkha_mode_params_t
159 {
160     ltc_pkha_func_t func;
161     ltc_pkha_f2m_t arithType;
162     ltc_pkha_montgomery_form_t montFormIn;
163     ltc_pkha_montgomery_form_t montFormOut;
164     ltc_pkha_reg_area_t srcReg;
165     ltc_pkha_quad_area_t srcQuad;
166     ltc_pkha_reg_area_t dstReg;
167     ltc_pkha_quad_area_t dstQuad;
168     ltc_pkha_timing_t equalTime;
169     ltc_pkha_r2_t r2modn;
170 } ltc_pkha_mode_params_t;
171 
172 #endif /* FSL_FEATURE_LTC_HAS_PKHA */
173 
174 /*******************************************************************************
175  * Prototypes
176  ******************************************************************************/
177 #if defined(FSL_FEATURE_LTC_HAS_PKHA) && FSL_FEATURE_LTC_HAS_PKHA
178 static status_t ltc_pkha_clear_regabne(LTC_Type *base, bool A, bool B, bool N, bool E);
179 #endif /* FSL_FEATURE_LTC_HAS_PKHA */
180 
181 /*******************************************************************************
182  * Code
183  ******************************************************************************/
184 
185 /*******************************************************************************
186  * LTC Common code static
187  ******************************************************************************/
188 /*!
189  * @brief Tests the correct key size.
190  *
191  * This function tests the correct key size.
192  * @param keySize Input key length in bytes.
193  * @return True if the key length is supported, false if not.
194  */
ltc_check_key_size(const uint32_t keySize)195 bool ltc_check_key_size(const uint32_t keySize)
196 {
197     return ((keySize == 16u)
198 #if defined(FSL_FEATURE_LTC_HAS_AES192) && FSL_FEATURE_LTC_HAS_AES192
199             || ((keySize == 24u))
200 #endif /* FSL_FEATURE_LTC_HAS_AES192 */
201 #if defined(FSL_FEATURE_LTC_HAS_AES256) && FSL_FEATURE_LTC_HAS_AES256
202             || ((keySize == 32u))
203 #endif /* FSL_FEATURE_LTC_HAS_AES256 */
204     );
205 }
206 
207 /*! @brief LTC driver wait mechanism. */
ltc_wait(LTC_Type * base)208 status_t ltc_wait(LTC_Type *base)
209 {
210     status_t status;
211 
212     bool error = false;
213     bool done  = false;
214 
215     /* Wait for 'done' or 'error' flag. */
216     while ((!error) && (!done))
217     {
218         uint32_t temp32 = base->STA;
219         error           = (0U != (temp32 & LTC_STA_EI_MASK)) ? true : false;
220         done            = (0U != (temp32 & LTC_STA_DI_MASK)) ? true : false;
221     }
222 
223     if (error)
224     {
225         base->COM = LTC_COM_ALL_MASK; /* Reset all engine to clear the error flag */
226         status    = kStatus_Fail;
227     }
228     else /* 'done' */
229     {
230         status = kStatus_Success;
231 
232         base->CW = (uint32_t)kLTC_ClearDataSize;
233         /* Clear 'done' interrupt status.  This also clears the mode register. */
234         base->STA = (uint32_t)kLTC_StatusDoneIsr;
235     }
236 
237     return status;
238 }
239 
240 /*!
241  * @brief Clears the LTC module.
242  * This function can be used to clear all sensitive data from theLTC module, such as private keys. It is called
243  * internally by the LTC driver in case of an error or operation complete.
244  * @param base LTC peripheral base address
245  * @param pkha Include LTC PKHA register clear. If there is no PKHA, the argument is ignored.
246  */
ltc_clear_all(LTC_Type * base,bool addPKHA)247 void ltc_clear_all(LTC_Type *base, bool addPKHA)
248 {
249     base->CW = (uint32_t)kLTC_ClearAll;
250 #if defined(FSL_FEATURE_LTC_HAS_PKHA) && FSL_FEATURE_LTC_HAS_PKHA
251     if (addPKHA)
252     {
253         (void)ltc_pkha_clear_regabne(base, true, true, true, true);
254     }
255 #endif /* FSL_FEATURE_LTC_HAS_PKHA */
256 }
257 
ltc_memcpy(void * dst,const void * src,size_t size)258 void ltc_memcpy(void *dst, const void *src, size_t size)
259 {
260 #if defined(__cplusplus)
261     register uint8_t *to         = (uint8_t *)dst;
262     register const uint8_t *from = (const uint8_t *)src;
263 #else
264     register uint8_t *to         = dst;
265     register const uint8_t *from = src;
266 #endif
267     while (0U != size)
268     {
269         *to = *from;
270         size--;
271         to++;
272         from++;
273     }
274 }
275 
276 /*!
277  * @brief Reads an unaligned word.
278  *
279  * This function creates a 32-bit word from an input array of four bytes.
280  *
281  * @param src Input array of four bytes. The array can start at any address in memory.
282  * @return 32-bit unsigned int created from the input byte array.
283  */
284 
285 /* Force lower optimization for Keil, otherwise it replaces inline LDR with LDM */
286 #if defined(__CC_ARM)
287 #pragma push
288 #pragma O0
289 #endif
290 
ltc_get_word_from_unaligned(const uint8_t * srcAddr)291 static inline uint32_t ltc_get_word_from_unaligned(const uint8_t *srcAddr)
292 {
293 #if (!(defined(__CORTEX_M)) || (defined(__CORTEX_M) && (__CORTEX_M == 0)))
294     register const uint8_t *src = srcAddr;
295     /* Cortex M0 does not support misaligned loads */
296     if (0U != ((uint32_t)src & 0x3u))
297     {
298         union _align_bytes_t
299         {
300             uint32_t word;
301             uint8_t byte[sizeof(uint32_t)];
302         } my_bytes;
303 
304         my_bytes.byte[0] = *src;
305         my_bytes.byte[1] = src[1];
306         my_bytes.byte[2] = src[2];
307         my_bytes.byte[3] = src[3];
308         return my_bytes.word;
309     }
310     else
311     {
312         /* addr aligned to 0-modulo-4 so it is safe to type cast */
313         return *((const uint32_t *)(uint32_t)src);
314     }
315 #elif defined(__CC_ARM)
316     /* -O3 optimization in Keil 5.15 and 5.16a uses LDM instruction here (LDM r4!, {r0})
317      *    which is wrong, because srcAddr might be unaligned.
318      *    LDM on unaligned address causes hard-fault. in contrary,
319      *    LDR supports unaligned address on Cortex M4 */
320 
321     register uint32_t retVal;
322     __asm
323     {
324         LDR retVal, [srcAddr]
325     }
326     return retVal;
327 #else
328     return *((const uint32_t *)(uint32_t)srcAddr);
329 #endif
330 }
331 
332 /* End lower optimization */
333 #if defined(__CC_ARM)
334 #pragma pop
335 #endif
336 
337 /*!
338  * @brief Converts a 32-bit word into a byte array.
339  *
340  * This function creates an output array of four bytes from an input 32-bit word.
341  *
342  * @param srcWord Input 32-bit unsigned integer.
343  * @param dst Output array of four bytes. The array can start at any address in memory.
344  */
ltc_set_unaligned_from_word(uint32_t srcWord,uint8_t * dstAddr)345 static inline void ltc_set_unaligned_from_word(uint32_t srcWord, uint8_t *dstAddr)
346 {
347 #if (!(defined(__CORTEX_M)) || (defined(__CORTEX_M) && (__CORTEX_M == 0)))
348     register uint8_t *dst = dstAddr;
349     /* Cortex M0 does not support misaligned stores */
350     if (0U != ((uint32_t)dst & 0x3u))
351     {
352         *dst++ = (uint8_t)(srcWord & 0x000000FFU);
353         *dst++ = (uint8_t)((srcWord & 0x0000FF00U) >> 8U);
354         *dst++ = (uint8_t)((srcWord & 0x00FF0000U) >> 16U);
355         *dst++ = (uint8_t)((srcWord & 0xFF000000U) >> 24U);
356     }
357     else
358     {
359         *((uint32_t *)(uint32_t)dstAddr) = srcWord; /* addr aligned to 0-modulo-4 so it is safe to type cast */
360     }
361 #elif defined(__CC_ARM)
362     __asm
363     {
364         STR srcWord, [dstAddr]
365     }
366     return;
367 #else
368     *((uint32_t *)(uint32_t)dstAddr) = srcWord;
369 #endif
370 }
371 
372 /*!
373  * @brief Sets the LTC keys.
374  *
375  * This function writes the LTC keys into the key register.  The keys should
376  * be written before the key size.
377  *
378  * @param base LTC peripheral base address
379  * @param key Key
380  * @param keySize Number of bytes for all keys to be loaded (maximum 32, must be a
381  *                multiple of 4).
382  */
ltc_set_key(LTC_Type * base,const uint8_t * key,uint8_t keySize)383 static void ltc_set_key(LTC_Type *base, const uint8_t *key, uint8_t keySize)
384 {
385     uint32_t i;
386 
387     for (i = 0; i < ((uint32_t)keySize / 4u); i++)
388     {
389         base->KEY[i] = ltc_get_word_from_unaligned(&key[i * sizeof(uint32_t)]);
390     }
391 }
392 
393 /*!
394  * @brief Gets the LTC keys.
395  *
396  * This function retrieves the LTC keys from the key register.
397  *
398  * @param base LTC peripheral base address
399  * @param key Array of data to store keys
400  * @param keySize Number of bytes of keys to retrieve
401  */
ltc_get_key(LTC_Type * base,uint8_t * key,uint8_t keySize)402 static void ltc_get_key(LTC_Type *base, uint8_t *key, uint8_t keySize)
403 {
404     uint32_t i;
405 
406     for (i = 0; i < ((uint32_t)keySize / 4U); i++)
407     {
408         ltc_set_unaligned_from_word(base->KEY[i], &key[i * sizeof(uint32_t)]);
409     }
410 }
411 
412 /*!
413  * @brief Writes the LTC context register;
414  *
415  * The LTC context register is a 512 bit (64 byte) register that holds
416  * internal context for the crypto engine.  The meaning varies based on the
417  * algorithm and operating state being used.  This register is written by the
418  * driver/application to load state such as IV, counter, and so on. Then, it is
419  * updated by the internal crypto engine as needed.
420  *
421  * @param base LTC peripheral base address
422  * @param data Data to write
423  * @param dataSize Size of data to write in bytes
424  * @param startIndex Starting word (4-byte) index into the 16-word register.
425  * @return Status of write
426  */
ltc_set_context(LTC_Type * base,const uint8_t * data,uint8_t dataSize,uint8_t startIndex)427 status_t ltc_set_context(LTC_Type *base, const uint8_t *data, uint8_t dataSize, uint8_t startIndex)
428 {
429     uint32_t i;
430     uint8_t j;
431     uint8_t szLeft;
432 
433     /* Context register is 16 words in size (64 bytes).  Ensure we are only
434      * writing a valid amount of data. */
435     if (startIndex + (dataSize / 4u) >= 16u)
436     {
437         return kStatus_InvalidArgument;
438     }
439 
440     j      = 0;
441     szLeft = dataSize % 4u;
442     for (i = (uint32_t)startIndex; i < ((uint32_t)startIndex + (uint32_t)dataSize / 4u); i++)
443     {
444         base->CTX[i] = ltc_get_word_from_unaligned(&data[j]);
445         j += (uint8_t)sizeof(uint32_t);
446     }
447 
448     if (0U != szLeft)
449     {
450         uint32_t context_data = {0};
451         ltc_memcpy(&context_data, &data[j], (uint32_t)szLeft);
452         base->CTX[i] = context_data;
453     }
454     return kStatus_Success;
455 }
456 
457 /*!
458  * @brief Reads the LTC context register.
459  *
460  * The LTC context register is a 512 bit (64 byte) register that holds
461  * internal context for the crypto engine.  The meaning varies based on the
462  * algorithm and operating state being used.  This register is written by the
463  * driver/application to load state such as IV, counter, and so on. Then, it is
464  * updated by the internal crypto engine as needed.
465  *
466  * @param base LTC peripheral base address
467  * @param data Destination of read data
468  * @param dataSize Size of data to read in bytes
469  * @param startIndex Starting word (4-byte) index into the 16-word register.
470  * @return Status of read
471  */
ltc_get_context(LTC_Type * base,uint8_t * dest,uint8_t dataSize,uint8_t startIndex)472 status_t ltc_get_context(LTC_Type *base, uint8_t *dest, uint8_t dataSize, uint8_t startIndex)
473 {
474     uint32_t i;
475     int32_t j;
476     uint8_t szLeft;
477     uint32_t rdCtx;
478 
479     /* Context register is 16 words in size (64 bytes).  Ensure we are only
480      * writing a valid amount of data. */
481     if (startIndex + (dataSize / 4u) >= 16u)
482     {
483         return kStatus_InvalidArgument;
484     }
485 
486     j      = 0;
487     szLeft = dataSize % 4u;
488     for (i = (uint32_t)startIndex; i < ((uint32_t)startIndex + (uint32_t)dataSize / 4u); i++)
489     {
490         ltc_set_unaligned_from_word(base->CTX[i], &dest[j]);
491         j += (int32_t)sizeof(uint32_t);
492     }
493 
494     if (0U != szLeft)
495     {
496         rdCtx = base->CTX[i];
497         ltc_memcpy(&dest[j], &rdCtx, (uint32_t)szLeft);
498     }
499     return kStatus_Success;
500 }
501 
ltc_symmetric_alg_state(LTC_Type * base,const uint8_t * key,uint8_t keySize,ltc_algorithm_t alg,ltc_mode_symmetric_alg_t mode,ltc_mode_encrypt_t enc,ltc_mode_algorithm_state_t as)502 static status_t ltc_symmetric_alg_state(LTC_Type *base,
503                                         const uint8_t *key,
504                                         uint8_t keySize,
505                                         ltc_algorithm_t alg,
506                                         ltc_mode_symmetric_alg_t mode,
507                                         ltc_mode_encrypt_t enc,
508                                         ltc_mode_algorithm_state_t as)
509 {
510     ltc_mode_t modeReg;
511 
512     /* Clear internal register states. */
513     base->CW = (uint32_t)kLTC_ClearAll;
514 
515     /* Set byte swap on for several registers we will be reading and writing
516      * user data to/from. */
517     base->CTL |= (uint32_t)kLTC_CtrlSwapAll;
518 
519     /* Write the key in place. */
520     ltc_set_key(base, key, keySize);
521 
522     /* Write the key size.  This must be done after writing the key, and this
523      * action locks the ability to modify the key registers. */
524     base->KS = keySize;
525 
526     /* Clear the 'done' interrupt. */
527     base->STA = (uint32_t)kLTC_StatusDoneIsr;
528 
529     /* Set the proper block and algorithm mode. */
530     modeReg = (uint32_t)alg | (uint32_t)enc | (uint32_t)as | (uint32_t)mode;
531 
532     /* Write the mode register to the hardware. */
533     base->MD = modeReg;
534 
535     return kStatus_Success;
536 }
537 
538 /*!
539  * @brief Initializes the LTC for symmetric encrypt/decrypt operation. Mode is set to UPDATE.
540  *
541  * @param base LTC peripheral base address
542  * @param key Input key to use for encryption
543  * @param keySize Size of the input key, in bytes. Must be 8, 16, 24, or 32.
544  * @param alg Symmetric algorithm
545  * @param mode Symmetric block mode
546  * @param enc Encrypt/decrypt control
547  * @return Status
548  */
ltc_symmetric_update(LTC_Type * base,const uint8_t * key,uint8_t keySize,ltc_algorithm_t alg,ltc_mode_symmetric_alg_t mode,ltc_mode_encrypt_t enc)549 status_t ltc_symmetric_update(LTC_Type *base,
550                               const uint8_t *key,
551                               uint8_t keySize,
552                               ltc_algorithm_t alg,
553                               ltc_mode_symmetric_alg_t mode,
554                               ltc_mode_encrypt_t enc)
555 {
556     return ltc_symmetric_alg_state(base, key, keySize, alg, mode, enc, kLTC_ModeUpdate);
557 }
558 
559 #if defined(FSL_FEATURE_LTC_HAS_GCM) && FSL_FEATURE_LTC_HAS_GCM
560 /*!
561  * @brief Initializes the LTC for symmetric encrypt/decrypt operation. Mode is set to FINALIZE.
562  *
563  * @param base LTC peripheral base address
564  * @param key Input key to use for encryption
565  * @param keySize Size of the input key, in bytes. Must be 8, 16, 24, or 32.
566  * @param alg Symmetric algorithm
567  * @param mode Symmetric block mode
568  * @param enc Encrypt/decrypt control
569  * @return Status
570  */
ltc_symmetric_final(LTC_Type * base,const uint8_t * key,uint8_t keySize,ltc_algorithm_t alg,ltc_mode_symmetric_alg_t mode,ltc_mode_encrypt_t enc)571 static status_t ltc_symmetric_final(LTC_Type *base,
572                                     const uint8_t *key,
573                                     uint8_t keySize,
574                                     ltc_algorithm_t alg,
575                                     ltc_mode_symmetric_alg_t mode,
576                                     ltc_mode_encrypt_t enc)
577 {
578     return ltc_symmetric_alg_state(base, key, keySize, alg, mode, enc, kLTC_ModeFinalize);
579 }
580 #endif /* FSL_FEATURE_LTC_HAS_GCM */
581 
582 /*!
583  * @brief Initializes the LTC for symmetric encrypt/decrypt operation. Mode is set to INITIALIZE.
584  *
585  * @param base LTC peripheral base address
586  * @param key Input key to use for encryption
587  * @param keySize Size of the input key, in bytes. Must be 8, 16, 24, or 32.
588  * @param alg Symmetric algorithm
589  * @param mode Symmetric block mode
590  * @param enc Encrypt/decrypt control
591  * @return Status
592  */
ltc_symmetric_init(LTC_Type * base,const uint8_t * key,uint8_t keySize,ltc_algorithm_t alg,ltc_mode_symmetric_alg_t mode,ltc_mode_encrypt_t enc)593 static status_t ltc_symmetric_init(LTC_Type *base,
594                                    const uint8_t *key,
595                                    uint8_t keySize,
596                                    ltc_algorithm_t alg,
597                                    ltc_mode_symmetric_alg_t mode,
598                                    ltc_mode_encrypt_t enc)
599 {
600     return ltc_symmetric_alg_state(base, key, keySize, alg, mode, enc, kLTC_ModeInit);
601 }
602 
603 /*!
604  * @brief Initializes the LTC for symmetric encrypt/decrypt operation. Mode is set to INITIALIZE/FINALIZE.
605  *
606  * @param base LTC peripheral base address
607  * @param key Input key to use for encryption
608  * @param keySize Size of the input key, in bytes. Must be 8, 16, 24, or 32.
609  * @param alg Symmetric algorithm
610  * @param mode Symmetric block mode
611  * @param enc Encrypt/decrypt control
612  * @return Status
613  */
ltc_symmetric_init_final(LTC_Type * base,const uint8_t * key,uint8_t keySize,ltc_algorithm_t alg,ltc_mode_symmetric_alg_t mode,ltc_mode_encrypt_t enc)614 static status_t ltc_symmetric_init_final(LTC_Type *base,
615                                          const uint8_t *key,
616                                          uint8_t keySize,
617                                          ltc_algorithm_t alg,
618                                          ltc_mode_symmetric_alg_t mode,
619                                          ltc_mode_encrypt_t enc)
620 {
621     return ltc_symmetric_alg_state(base, key, keySize, alg, mode, enc, kLTC_ModeInitFinal);
622 }
623 
ltc_symmetric_process(LTC_Type * base,uint32_t inSize,const uint8_t ** inData,uint8_t ** outData)624 void ltc_symmetric_process(LTC_Type *base, uint32_t inSize, const uint8_t **inData, uint8_t **outData)
625 {
626     uint32_t outSize;
627     uint32_t fifoData;
628     uint32_t fifoStatus;
629 
630     register const uint8_t *in = *inData;
631     register uint8_t *out      = *outData;
632 
633     outSize = inSize;
634     while ((outSize > 0u) || (inSize > 0u))
635     {
636         fifoStatus = base->FIFOSTA;
637 
638         /* Check output FIFO level to make sure there is at least an entry
639          * ready to be read. */
640         if (0U != (fifoStatus & LTC_FIFOSTA_OFL_MASK))
641         {
642             /* Read data from the output FIFO. */
643             if (outSize > 0u)
644             {
645                 if (outSize >= sizeof(uint32_t))
646                 {
647                     ltc_set_unaligned_from_word(base->OFIFO, out);
648                     out = &out[sizeof(uint32_t)];
649                     outSize -= sizeof(uint32_t);
650                 }
651                 else /* (outSize > 0) && (outSize < 4) */
652                 {
653                     fifoData = base->OFIFO;
654                     ltc_memcpy(out, &fifoData, outSize);
655                     out     = &out[outSize];
656                     outSize = 0;
657                 }
658             }
659         }
660 
661         /* Check input FIFO status to see if it is full.  We can
662          * only write more data when both input and output FIFOs are not at a full state.
663          * At the same time we are sure Output FIFO is not full because we have poped at least one entry
664          * by the while loop above.
665          */
666         if (0U == (fifoStatus & LTC_FIFOSTA_IFF_MASK))
667         {
668             /* Copy data to the input FIFO.
669              * Data can only be copied one word at a time, so pad the data
670              * appropriately if it is less than this size. */
671             if (inSize > 0u)
672             {
673                 if (inSize >= sizeof(uint32_t))
674                 {
675                     base->IFIFO = ltc_get_word_from_unaligned(in);
676                     inSize -= sizeof(uint32_t);
677                     in = &in[sizeof(uint32_t)];
678                 }
679                 else /* (inSize > 0) && (inSize < 4) */
680                 {
681                     fifoData = 0;
682                     ltc_memcpy(&fifoData, in, inSize);
683                     base->IFIFO = fifoData;
684                     in          = &in[inSize];
685                     inSize      = 0;
686                 }
687             }
688         }
689     }
690     *inData  = in;
691     *outData = out;
692 }
693 
694 /*!
695  * @brief Processes symmetric data through LTC AES and DES engines.
696  *
697  * @param base LTC peripheral base address
698  * @param inData Input data
699  * @param inSize Size of input data, in bytes
700  * @param outData Output data
701  * @return Status from encrypt/decrypt operation
702  */
ltc_symmetric_process_data(LTC_Type * base,const uint8_t * inData,uint32_t inSize,uint8_t * outData)703 status_t ltc_symmetric_process_data(LTC_Type *base, const uint8_t *inData, uint32_t inSize, uint8_t *outData)
704 {
705     uint32_t lastSize;
706 
707     if ((NULL == inData) || (NULL == outData))
708     {
709         return kStatus_InvalidArgument;
710     }
711 
712     /* Write the data size. */
713     base->DS = inSize;
714 
715     /* Split the inSize into full 16-byte chunks and last incomplete block due to LTC AES OFIFO errata */
716     if (inSize <= 16u)
717     {
718         lastSize = inSize;
719         inSize   = 0;
720     }
721     else
722     {
723         /* Process all 16-byte data chunks. */
724         lastSize = inSize % 16u;
725         if (lastSize == 0u)
726         {
727             lastSize = 16;
728             inSize -= 16u;
729         }
730         else
731         {
732             inSize -= lastSize; /* inSize will be rounded down to 16 byte boundary. remaining bytes in lastSize */
733         }
734     }
735 
736     ltc_symmetric_process(base, inSize, &inData, &outData);
737     ltc_symmetric_process(base, lastSize, &inData, &outData);
738     return ltc_wait(base);
739 }
740 
741 /*!
742  * @brief Splits the LTC job into sessions. Used for CBC, CTR, CFB, OFB cipher block modes.
743  *
744  * @param base LTC peripheral base address
745  * @param inData Input data to process.
746  * @param inSize Input size of the input buffer.
747  * @param outData Output data buffer.
748  */
ltc_process_message_in_sessions(LTC_Type * base,const uint8_t * inData,uint32_t inSize,uint8_t * outData)749 static status_t ltc_process_message_in_sessions(LTC_Type *base,
750                                                 const uint8_t *inData,
751                                                 uint32_t inSize,
752                                                 uint8_t *outData)
753 {
754     uint32_t sz;
755     status_t retval;
756     ltc_mode_t modeReg; /* read and write LTC mode register */
757 
758     sz = LTC_FIFO_SZ_MAX_DOWN_ALGN;
759 
760     /* modeReg value will be used if message is split into multiple LTC_FIFO_SZ_MAX_DOWN_ALGN chunks */
761     /* in case of AES CBC and AES ECB decryption */
762     /* the conversion of AES forward key to AES reverse key happens with the 1st chunk */
763     /* so all the following chunks already have the reverse key */
764     /* thus we add the MD register bit 12 to the MD value to notify the AES engine
765        that the key is the AES reverse key */
766     /* This really needs to be done only for AES ECB and CBC Decrypt as these are the only */
767     /* cipher block modes that use AES reverse key */
768     modeReg = base->MD;
769     /* AES CBC Decrypt */
770     if (modeReg == 0x00100100u)
771     {
772         /* add MSB of AAI - DK (Decrypt Key) bit */
773         modeReg = 0x00101100u;
774     }
775     /* AES ECB Decrypt */
776     if (modeReg == 0x00100200u)
777     {
778         /* add MSB of AAI - DK (Decrypt Key) bit */
779         modeReg = 0x00101200u;
780     }
781 
782     retval = kStatus_Success;
783 
784     while (0U != inSize)
785     {
786         if (inSize <= sz)
787         {
788             retval = ltc_symmetric_process_data(base, inData, inSize, outData);
789             if (kStatus_Success != retval)
790             {
791                 return retval;
792             }
793             inSize = 0;
794         }
795         else
796         {
797             retval = ltc_symmetric_process_data(base, inData, sz, outData);
798             if (kStatus_Success != retval)
799             {
800                 return retval;
801             }
802             inData = &inData[sz];
803             inSize -= sz;
804             outData  = &outData[sz];
805             base->MD = modeReg;
806         }
807     }
808     return retval;
809 }
810 
ltc_move_block_to_ififo(LTC_Type * base,const ltc_xcm_block_t * blk,uint32_t num_bytes)811 static void ltc_move_block_to_ififo(LTC_Type *base, const ltc_xcm_block_t *blk, uint32_t num_bytes)
812 {
813     uint32_t i = 0;
814     uint32_t words;
815 
816     words = num_bytes / 4u;
817     if (0U != (num_bytes % 4u))
818     {
819         words++;
820     }
821 
822     if (words > 4u)
823     {
824         words = 4;
825     }
826 
827     while (i < words)
828     {
829         if (0U == (base->FIFOSTA & LTC_FIFOSTA_IFF_MASK))
830         {
831             /* Copy data to the input FIFO. */
832             base->IFIFO = blk->w[i++];
833         }
834     }
835 }
836 
ltc_move_to_ififo(LTC_Type * base,const uint8_t * data,uint32_t dataSize)837 static void ltc_move_to_ififo(LTC_Type *base, const uint8_t *data, uint32_t dataSize)
838 {
839     ltc_xcm_block_t blk;
840     ltc_xcm_block_t blkZero = {{0x0u, 0x0u, 0x0u, 0x0u}};
841 
842     while (0U != dataSize)
843     {
844         if (dataSize > 16u)
845         {
846             ltc_memcpy(&blk, data, 16u);
847             dataSize -= 16u;
848             data = &data[16];
849         }
850         else
851         {
852             ltc_memcpy(&blk, &blkZero, sizeof(ltc_xcm_block_t)); /* memset blk to zeroes */
853             ltc_memcpy(&blk, data, dataSize);
854             dataSize = 0;
855         }
856         ltc_move_block_to_ififo(base, (const ltc_xcm_block_t *)(uint32_t)&blk, sizeof(ltc_xcm_block_t));
857     }
858 }
859 
860 /*!
861  * @brief Processes symmetric data through LTC AES in multiple sessions.
862  *
863  * Specific for AES CCM and GCM modes as they need to update mode register.
864  *
865  * @param base LTC peripheral base address
866  * @param inData Input data
867  * @param inSize Size of input data, in bytes
868  * @param outData Output data
869  * @param lastAs The LTC Algorithm state to be set sup for last block during message processing in multiple sessions.
870  *               For CCM it is kLTC_ModeFinalize. For GCM it is kLTC_ModeInitFinal.
871  * @return Status from encrypt/decrypt operation
872  */
ltc_symmetric_process_data_multiple(LTC_Type * base,const uint8_t * inData,uint32_t inSize,uint8_t * outData,ltc_mode_t modeReg,ltc_mode_algorithm_state_t lastAs)873 static status_t ltc_symmetric_process_data_multiple(LTC_Type *base,
874                                                     const uint8_t *inData,
875                                                     uint32_t inSize,
876                                                     uint8_t *outData,
877                                                     ltc_mode_t modeReg,
878                                                     ltc_mode_algorithm_state_t lastAs)
879 {
880     uint32_t fifoConsumed;
881     uint32_t lastSize;
882     uint32_t sz;
883     uint32_t max_ltc_fifo_size;
884     ltc_mode_algorithm_state_t fsm;
885     status_t status;
886 
887     if ((NULL == inData) || (NULL == outData))
888     {
889         return kStatus_InvalidArgument;
890     }
891 
892     if (!(((uint8_t)kLTC_ModeFinalize == (uint8_t)lastAs) || ((uint8_t)kLTC_ModeInitFinal == (uint8_t)lastAs)))
893     {
894         return kStatus_InvalidArgument;
895     }
896 
897     if (0u == inSize)
898     {
899         return kStatus_Success;
900     }
901 
902     if (inSize <= 16u)
903     {
904         fsm      = lastAs;
905         lastSize = inSize;
906     }
907     else
908     {
909         fsm = (ltc_mode_algorithm_state_t)(
910             modeReg &
911             LTC_MD_AS_MASK); /* this will be either kLTC_ModeInit or kLTC_ModeUpdate, based on prior processing */
912 
913         /* Process all 16-byte data chunks. */
914         lastSize = inSize % 16u;
915         if (lastSize == 0u)
916         {
917             lastSize = 16u;
918             inSize -= 16u;
919         }
920         else
921         {
922             inSize -= lastSize; /* inSize will be rounded down to 16 byte boundary. remaining bytes in lastSize */
923         }
924     }
925 
926     max_ltc_fifo_size = LTC_FIFO_SZ_MAX_DOWN_ALGN;
927     fifoConsumed      = base->DS;
928 
929     while (0U != lastSize)
930     {
931         if ((fsm == kLTC_ModeUpdate) || (fsm == kLTC_ModeInit))
932         {
933             while (0U != inSize)
934             {
935                 if (inSize > (max_ltc_fifo_size - fifoConsumed))
936                 {
937                     sz = (max_ltc_fifo_size - fifoConsumed);
938                 }
939                 else
940                 {
941                     sz = inSize;
942                 }
943                 base->DS = sz;
944                 ltc_symmetric_process(base, sz, &inData, &outData);
945                 inSize -= sz;
946                 fifoConsumed = 0;
947 
948                 /* after we completed INITIALIZE job, are there still any data left? */
949                 if (0U != inSize)
950                 {
951                     fsm    = kLTC_ModeUpdate;
952                     status = ltc_wait(base);
953                     if (kStatus_Success != status)
954                     {
955                         return status;
956                     }
957                     modeReg &= ~LTC_MD_AS_MASK;
958                     modeReg |= (uint32_t)fsm;
959                     base->MD = modeReg;
960                 }
961                 else
962                 {
963                     fsm = lastAs;
964                 }
965             }
966         }
967 
968         else if ((fsm == kLTC_ModeFinalize) || (fsm == kLTC_ModeInitFinal))
969         {
970             /* process last block in FINALIZE */
971 
972             status = ltc_wait(base);
973             if (kStatus_Success != status)
974             {
975                 return status;
976             }
977 
978             modeReg &= ~LTC_MD_AS_MASK;
979             modeReg |= (uint32_t)lastAs;
980             base->MD = modeReg;
981 
982             base->DS = lastSize;
983             ltc_symmetric_process(base, lastSize, &inData, &outData);
984             lastSize = 0;
985         }
986         else
987         {
988             /*do nothing*/
989         }
990     }
991 
992     status = ltc_wait(base);
993     return status;
994 }
995 
996 /*!
997  * @brief Receives MAC compare.
998  *
999  * This function is a sub-process of CCM and GCM decryption.
1000  * It compares received MAC with the MAC computed during decryption.
1001  *
1002  * @param base LTC peripheral base address
1003  * @param tag Received MAC.
1004  * @param tagSize Number of bytes in the received MAC.
1005  * @param modeReg LTC Mode Register current value. It is modified and written to LTC Mode Register.
1006  */
ltc_aes_received_mac_compare(LTC_Type * base,const uint8_t * tag,uint32_t tagSize,ltc_mode_t modeReg)1007 static status_t ltc_aes_received_mac_compare(LTC_Type *base, const uint8_t *tag, uint32_t tagSize, ltc_mode_t modeReg)
1008 {
1009     ltc_xcm_block_t blk = {{0x0u, 0x0u, 0x0u, 0x0u}};
1010 
1011     base->CW  = (uint32_t)kLTC_ClearDataSize;
1012     base->STA = (uint32_t)kLTC_StatusDoneIsr;
1013 
1014     modeReg &= ~LTC_MD_AS_MASK;
1015     modeReg |= (uint32_t)kLTC_ModeUpdate | LTC_MD_ICV_TEST_MASK;
1016     base->MD = modeReg;
1017 
1018     base->DS   = 0u;
1019     base->ICVS = tagSize;
1020     ltc_memcpy(&blk.b[0], &tag[0], tagSize);
1021 
1022     ltc_move_block_to_ififo(base, (const ltc_xcm_block_t *)(uint32_t)&blk, tagSize);
1023     return ltc_wait(base);
1024 }
1025 
1026 /*!
1027  * @brief Processes tag during AES GCM and CCM.
1028  *
1029  * This function is a sub-process of CCM and GCM encryption and decryption.
1030  * For encryption, it writes computed MAC to the output tag.
1031  * For decryption, it compares the received MAC with the computed MAC.
1032  *
1033  * @param base LTC peripheral base address
1034  * @param[in,out] tag Output computed MAC during encryption or Input received MAC during decryption.
1035  * @param tagSize Size of MAC buffer in bytes.
1036  * @param modeReg LTC Mode Register current value. It is checked to read Enc/Dec bit.
1037  *                 It is modified and written to LTC Mode Register during decryption.
1038  * @param ctx Index to LTC context registers with computed MAC for encryption process.
1039  */
ltc_aes_process_tag(LTC_Type * base,uint8_t * tag,uint32_t tagSize,ltc_mode_t modeReg,uint32_t ctx)1040 static status_t ltc_aes_process_tag(LTC_Type *base, uint8_t *tag, uint32_t tagSize, ltc_mode_t modeReg, uint32_t ctx)
1041 {
1042     status_t status = kStatus_Success;
1043     if (NULL != tag)
1044     {
1045         /* For decrypt, compare received MAC with the computed MAC. */
1046         if ((uint32_t)kLTC_ModeDecrypt == (modeReg & LTC_MD_ENC_MASK))
1047         {
1048             status = ltc_aes_received_mac_compare(base, tag, tagSize, modeReg);
1049         }
1050         else /* FSL_AES_GCM_TYPE_ENCRYPT */
1051         {
1052             /* For encryption, write the computed and encrypted MAC to user buffer */
1053             status = ltc_get_context(base, &tag[0], (uint8_t)tagSize, (uint8_t)ctx);
1054         }
1055     }
1056     return status;
1057 }
1058 
1059 /*******************************************************************************
1060  * LTC Common code public
1061  ******************************************************************************/
1062 /*!
1063  * brief Initializes the LTC driver.
1064  * This function initializes the LTC driver.
1065  * param base LTC peripheral base address
1066  */
LTC_Init(LTC_Type * base)1067 void LTC_Init(LTC_Type *base)
1068 {
1069 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
1070     /* ungate clock */
1071     CLOCK_EnableClock(kCLOCK_Ltc0);
1072 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
1073 }
1074 
1075 /*!
1076  * brief Deinitializes the LTC driver.
1077  * This function deinitializes the LTC driver.
1078  * param base LTC peripheral base address
1079  */
LTC_Deinit(LTC_Type * base)1080 void LTC_Deinit(LTC_Type *base)
1081 {
1082 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
1083     /* gate clock */
1084     CLOCK_DisableClock(kCLOCK_Ltc0);
1085 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
1086 }
1087 
1088 #if defined(FSL_FEATURE_LTC_HAS_DPAMS) && FSL_FEATURE_LTC_HAS_DPAMS
1089 /*!
1090  * brief Sets the DPA Mask Seed register.
1091  *
1092  * The DPA Mask Seed register reseeds the mask that provides resistance against DPA (differential power analysis)
1093  * attacks on AES or DES keys.
1094  *
1095  * Differential Power Analysis Mask (DPA) resistance uses a randomly changing mask that introduces
1096  * "noise" into the power consumed by the AES or DES. This reduces the signal-to-noise ratio that differential
1097  * power analysis attacks use to "guess" bits of the key. This randomly changing mask should be
1098  * seeded at POR, and continues to provide DPA resistance from that point on. However, to provide even more
1099  * DPA protection it is recommended that the DPA mask be reseeded after every 50,000 blocks have
1100  * been processed. At that time, software can opt to write a new seed (preferably obtained from an RNG)
1101  * into the DPA Mask Seed register (DPAMS), or software can opt to provide the new seed earlier or
1102  * later, or not at all. DPA resistance continues even if the DPA mask is never reseeded.
1103  *
1104  * param base LTC peripheral base address
1105  * param mask The DPA mask seed.
1106  */
LTC_SetDpaMaskSeed(LTC_Type * base,uint32_t mask)1107 void LTC_SetDpaMaskSeed(LTC_Type *base, uint32_t mask)
1108 {
1109     base->DPAMS = mask;
1110     /* second write as workaround for DPA mask re-seed errata */
1111     base->DPAMS = mask;
1112 }
1113 #endif /* FSL_FEATURE_LTC_HAS_DPAMS */
1114 
1115 /*******************************************************************************
1116  * AES Code static
1117  ******************************************************************************/
ltc_aes_decrypt_ecb(LTC_Type * base,const uint8_t * ciphertext,uint8_t * plaintext,uint32_t size,const uint8_t * key,uint32_t keySize,ltc_aes_key_t keyType)1118 static status_t ltc_aes_decrypt_ecb(LTC_Type *base,
1119                                     const uint8_t *ciphertext,
1120                                     uint8_t *plaintext,
1121                                     uint32_t size,
1122                                     const uint8_t *key,
1123                                     uint32_t keySize,
1124                                     ltc_aes_key_t keyType)
1125 {
1126     status_t retval;
1127 
1128     /* Initialize algorithm state. */
1129     retval = ltc_symmetric_update(base, key, (uint8_t)keySize, kLTC_AlgorithmAES, kLTC_ModeECB, kLTC_ModeDecrypt);
1130     if (kStatus_Success != retval)
1131     {
1132         return retval;
1133     }
1134 
1135     /* set DK bit in the LTC Mode Register AAI field for directly loaded decrypt keys */
1136     if (keyType == kLTC_DecryptKey)
1137     {
1138         uint32_t u32mask = 1;
1139         base->MD |= (u32mask << (uint32_t)kLTC_ModeRegBitShiftDK);
1140     }
1141 
1142     /* Process data and return status. */
1143     retval = ltc_process_message_in_sessions(base, &ciphertext[0], size, &plaintext[0]);
1144     return retval;
1145 }
1146 
1147 /*******************************************************************************
1148  * AES Code public
1149  ******************************************************************************/
1150 /*!
1151  * brief Transforms an AES encrypt key (forward AES) into the decrypt key (inverse AES).
1152  *
1153  * Transforms the AES encrypt key (forward AES) into the decrypt key (inverse AES).
1154  * The key derived by this function can be used as a direct load decrypt key
1155  * for AES ECB and CBC decryption operations (keyType argument).
1156  *
1157  * param base LTC peripheral base address
1158  * param encryptKey Input key for decrypt key transformation
1159  * param[out] decryptKey Output key, the decrypt form of the AES key.
1160  * param keySize Size of the input key and output key in bytes. Must be 16, 24, or 32.
1161  * return Status from key generation operation
1162  */
LTC_AES_GenerateDecryptKey(LTC_Type * base,const uint8_t * encryptKey,uint8_t * decryptKey,uint32_t keySize)1163 status_t LTC_AES_GenerateDecryptKey(LTC_Type *base, const uint8_t *encryptKey, uint8_t *decryptKey, uint32_t keySize)
1164 {
1165     uint8_t plaintext[LTC_AES_BLOCK_SIZE];
1166     uint8_t ciphertext[LTC_AES_BLOCK_SIZE];
1167     status_t status;
1168 
1169     if (!ltc_check_key_size(keySize))
1170     {
1171         return kStatus_InvalidArgument;
1172     }
1173 
1174     /* ECB decrypt with encrypt key will convert the key in LTC context into decrypt form of the key */
1175     status = ltc_aes_decrypt_ecb(base, ciphertext, plaintext, LTC_AES_BLOCK_SIZE, encryptKey, keySize, kLTC_EncryptKey);
1176     /* now there is decrypt form of the key in the LTC context, so take it */
1177     ltc_get_key(base, decryptKey, (uint8_t)keySize);
1178 
1179     ltc_clear_all(base, false);
1180 
1181     return status;
1182 }
1183 
1184 /*!
1185  * brief Encrypts AES using the ECB block mode.
1186  *
1187  * Encrypts AES using the ECB block mode.
1188  *
1189  * param base LTC peripheral base address
1190  * param plaintext Input plain text to encrypt
1191  * param[out] ciphertext Output cipher text
1192  * param size Size of input and output data in bytes. Must be multiple of 16 bytes.
1193  * param key Input key to use for encryption
1194  * param keySize Size of the input key, in bytes. Must be 16, 24, or 32.
1195  * return Status from encrypt operation
1196  */
LTC_AES_EncryptEcb(LTC_Type * base,const uint8_t * plaintext,uint8_t * ciphertext,uint32_t size,const uint8_t * key,uint32_t keySize)1197 status_t LTC_AES_EncryptEcb(
1198     LTC_Type *base, const uint8_t *plaintext, uint8_t *ciphertext, uint32_t size, const uint8_t *key, uint32_t keySize)
1199 {
1200     status_t retval;
1201 
1202     if (!ltc_check_key_size(keySize))
1203     {
1204         return kStatus_InvalidArgument;
1205     }
1206     /* ECB mode, size must be 16-byte multiple */
1207     if ((size < 16u) || (0U != (size % 16u)))
1208     {
1209         return kStatus_InvalidArgument;
1210     }
1211 
1212     /* Initialize algorithm state. */
1213     retval = ltc_symmetric_update(base, key, (uint8_t)keySize, kLTC_AlgorithmAES, kLTC_ModeECB, kLTC_ModeEncrypt);
1214     if (kStatus_Success != retval)
1215     {
1216         return retval;
1217     }
1218 
1219     /* Process data and return status. */
1220     retval = ltc_process_message_in_sessions(base, &plaintext[0], size, &ciphertext[0]);
1221     ltc_clear_all(base, false);
1222     return retval;
1223 }
1224 
1225 /*!
1226  * brief Decrypts AES using ECB block mode.
1227  *
1228  * Decrypts AES using ECB block mode.
1229  *
1230  * param base LTC peripheral base address
1231  * param ciphertext Input cipher text to decrypt
1232  * param[out] plaintext Output plain text
1233  * param size Size of input and output data in bytes. Must be multiple of 16 bytes.
1234  * param key Input key.
1235  * param keySize Size of the input key, in bytes. Must be 16, 24, or 32.
1236  * param keyType Input type of the key (allows to directly load decrypt key for AES ECB decrypt operation.)
1237  * return Status from decrypt operation
1238  */
LTC_AES_DecryptEcb(LTC_Type * base,const uint8_t * ciphertext,uint8_t * plaintext,uint32_t size,const uint8_t * key,uint32_t keySize,ltc_aes_key_t keyType)1239 status_t LTC_AES_DecryptEcb(LTC_Type *base,
1240                             const uint8_t *ciphertext,
1241                             uint8_t *plaintext,
1242                             uint32_t size,
1243                             const uint8_t *key,
1244                             uint32_t keySize,
1245                             ltc_aes_key_t keyType)
1246 {
1247     status_t status;
1248 
1249     if (!ltc_check_key_size(keySize))
1250     {
1251         return kStatus_InvalidArgument;
1252     }
1253     /* ECB mode, size must be 16-byte multiple */
1254     if ((size < 16u) || (0U != (size % 16u)))
1255     {
1256         return kStatus_InvalidArgument;
1257     }
1258 
1259     status = ltc_aes_decrypt_ecb(base, ciphertext, plaintext, size, key, keySize, keyType);
1260     ltc_clear_all(base, false);
1261     return status;
1262 }
1263 
1264 /*!
1265  * brief Encrypts AES using CBC block mode.
1266  *
1267  * param base LTC peripheral base address
1268  * param plaintext Input plain text to encrypt
1269  * param[out] ciphertext Output cipher text
1270  * param size Size of input and output data in bytes. Must be multiple of 16 bytes.
1271  * param iv Input initial vector to combine with the first input block.
1272  * param key Input key to use for encryption
1273  * param keySize Size of the input key, in bytes. Must be 16, 24, or 32.
1274  * return Status from encrypt operation
1275  */
LTC_AES_EncryptCbc(LTC_Type * base,const uint8_t * plaintext,uint8_t * ciphertext,uint32_t size,const uint8_t iv[LTC_AES_IV_SIZE],const uint8_t * key,uint32_t keySize)1276 status_t LTC_AES_EncryptCbc(LTC_Type *base,
1277                             const uint8_t *plaintext,
1278                             uint8_t *ciphertext,
1279                             uint32_t size,
1280                             const uint8_t iv[LTC_AES_IV_SIZE],
1281                             const uint8_t *key,
1282                             uint32_t keySize)
1283 {
1284     status_t retval;
1285 
1286     if (!ltc_check_key_size(keySize))
1287     {
1288         return kStatus_InvalidArgument;
1289     }
1290 
1291     /* CBC mode, size must be 16-byte multiple */
1292     if ((size < 16u) || (0U != (size % 16u)))
1293     {
1294         return kStatus_InvalidArgument;
1295     }
1296 
1297     /* Initialize algorithm state. */
1298     retval = ltc_symmetric_update(base, key, (uint8_t)keySize, kLTC_AlgorithmAES, kLTC_ModeCBC, kLTC_ModeEncrypt);
1299     if (kStatus_Success != retval)
1300     {
1301         return retval;
1302     }
1303 
1304     /* Write IV data to the context register. */
1305     retval = ltc_set_context(base, &iv[0], LTC_AES_IV_SIZE, 0);
1306     if (kStatus_Success != retval)
1307     {
1308         return retval;
1309     }
1310 
1311     /* Process data and return status. */
1312     retval = ltc_process_message_in_sessions(base, &plaintext[0], size, &ciphertext[0]);
1313     ltc_clear_all(base, false);
1314     return retval;
1315 }
1316 
1317 /*!
1318  * brief Decrypts AES using CBC block mode.
1319  *
1320  * param base LTC peripheral base address
1321  * param ciphertext Input cipher text to decrypt
1322  * param[out] plaintext Output plain text
1323  * param size Size of input and output data in bytes. Must be multiple of 16 bytes.
1324  * param iv Input initial vector to combine with the first input block.
1325  * param key Input key to use for decryption
1326  * param keySize Size of the input key, in bytes. Must be 16, 24, or 32.
1327  * param keyType Input type of the key (allows to directly load decrypt key for AES CBC decrypt operation.)
1328  * return Status from decrypt operation
1329  */
LTC_AES_DecryptCbc(LTC_Type * base,const uint8_t * ciphertext,uint8_t * plaintext,uint32_t size,const uint8_t iv[LTC_AES_IV_SIZE],const uint8_t * key,uint32_t keySize,ltc_aes_key_t keyType)1330 status_t LTC_AES_DecryptCbc(LTC_Type *base,
1331                             const uint8_t *ciphertext,
1332                             uint8_t *plaintext,
1333                             uint32_t size,
1334                             const uint8_t iv[LTC_AES_IV_SIZE],
1335                             const uint8_t *key,
1336                             uint32_t keySize,
1337                             ltc_aes_key_t keyType)
1338 {
1339     status_t retval;
1340 
1341     if (!ltc_check_key_size(keySize))
1342     {
1343         return kStatus_InvalidArgument;
1344     }
1345     /* CBC mode, size must be 16-byte multiple */
1346     if ((size < 16u) || (0U != (size % 16u)))
1347     {
1348         return kStatus_InvalidArgument;
1349     }
1350 
1351     /* Initialize algorithm state. */
1352     retval = ltc_symmetric_update(base, key, (uint8_t)keySize, kLTC_AlgorithmAES, kLTC_ModeCBC, kLTC_ModeDecrypt);
1353     if (kStatus_Success != retval)
1354     {
1355         return retval;
1356     }
1357 
1358     /* Write IV data to the context register. */
1359     retval = ltc_set_context(base, &iv[0], LTC_AES_IV_SIZE, 0);
1360     if (kStatus_Success != retval)
1361     {
1362         return retval;
1363     }
1364 
1365     /* set DK bit in the LTC Mode Register AAI field for directly loaded decrypt keys */
1366     if (keyType == kLTC_DecryptKey)
1367     {
1368         uint32_t u32mask = 1;
1369         base->MD |= (u32mask << (uint8_t)kLTC_ModeRegBitShiftDK);
1370     }
1371 
1372     /* Process data and return status. */
1373     retval = ltc_process_message_in_sessions(base, &ciphertext[0], size, &plaintext[0]);
1374     ltc_clear_all(base, false);
1375     return retval;
1376 }
1377 
1378 /*!
1379  * brief Encrypts or decrypts AES using CTR block mode.
1380  *
1381  * Encrypts or decrypts AES using CTR block mode.
1382  * AES CTR mode uses only forward AES cipher and same algorithm for encryption and decryption.
1383  * The only difference between encryption and decryption is that, for encryption, the input argument
1384  * is plain text and the output argument is cipher text. For decryption, the input argument is cipher text
1385  * and the output argument is plain text.
1386  *
1387  * param base LTC peripheral base address
1388  * param input Input data for CTR block mode
1389  * param[out] output Output data for CTR block mode
1390  * param size Size of input and output data in bytes
1391  * param[in,out] counter Input counter (updates on return)
1392  * param key Input key to use for forward AES cipher
1393  * param keySize Size of the input key, in bytes. Must be 16, 24, or 32.
1394  * param[out] counterlast Output cipher of last counter, for chained CTR calls. NULL can be passed if chained calls are
1395  * not used.
1396  * param[out] szLeft Output number of bytes in left unused in counterlast block. NULL can be passed if chained calls
1397  * are not used.
1398  * return Status from encrypt operation
1399  */
LTC_AES_CryptCtr(LTC_Type * base,const uint8_t * input,uint8_t * output,uint32_t size,uint8_t counter[LTC_AES_BLOCK_SIZE],const uint8_t * key,uint32_t keySize,uint8_t counterlast[LTC_AES_BLOCK_SIZE],uint32_t * szLeft)1400 status_t LTC_AES_CryptCtr(LTC_Type *base,
1401                           const uint8_t *input,
1402                           uint8_t *output,
1403                           uint32_t size,
1404                           uint8_t counter[LTC_AES_BLOCK_SIZE],
1405                           const uint8_t *key,
1406                           uint32_t keySize,
1407                           uint8_t counterlast[LTC_AES_BLOCK_SIZE],
1408                           uint32_t *szLeft)
1409 {
1410     status_t retval;
1411     uint32_t lastSize;
1412 
1413     if (!ltc_check_key_size(keySize))
1414     {
1415         return kStatus_InvalidArgument;
1416     }
1417 
1418     lastSize = 0U;
1419     if (counterlast != NULL)
1420     {
1421         /* Split the size into full 16-byte chunks and last incomplete block due to LTC AES OFIFO errata */
1422         if (size <= 16U)
1423         {
1424             lastSize = size;
1425             size     = 0U;
1426         }
1427         else
1428         {
1429             /* Process all 16-byte data chunks. */
1430             lastSize = size % 16U;
1431             if (lastSize == 0U)
1432             {
1433                 lastSize = 16U;
1434                 size -= 16U;
1435             }
1436             else
1437             {
1438                 size -= lastSize; /* size will be rounded down to 16 byte boundary. remaining bytes in lastSize */
1439             }
1440         }
1441     }
1442 
1443     /* Initialize algorithm state. */
1444     retval = ltc_symmetric_update(base, key, (uint8_t)keySize, kLTC_AlgorithmAES, kLTC_ModeCTR, kLTC_ModeEncrypt);
1445     if (kStatus_Success != retval)
1446     {
1447         return retval;
1448     }
1449 
1450     /* Write initial counter data to the context register.
1451      * NOTE the counter values start at 4-bytes offset into the context. */
1452     retval = ltc_set_context(base, &counter[0], 16U, 4U);
1453     if (kStatus_Success != retval)
1454     {
1455         return retval;
1456     }
1457 
1458     /* Process data and return status. */
1459     retval = ltc_process_message_in_sessions(base, input, size, output);
1460     if (kStatus_Success != retval)
1461     {
1462         return retval;
1463     }
1464 
1465     input  = &input[size];
1466     output = &output[size];
1467 
1468     if ((counterlast != NULL) && (0U != lastSize))
1469     {
1470         uint8_t zeroes[16] = {0};
1471         ltc_mode_t modeReg;
1472 
1473         modeReg = (uint32_t)kLTC_AlgorithmAES | (uint32_t)kLTC_ModeCTR | (uint32_t)kLTC_ModeEncrypt;
1474         /* Write the mode register to the hardware. */
1475         base->MD = modeReg | (uint32_t)kLTC_ModeFinalize;
1476 
1477         /* context is re-used (CTRi) */
1478 
1479         /* Process data and return status. */
1480         retval = ltc_symmetric_process_data(base, input, lastSize, output);
1481         if (kStatus_Success != retval)
1482         {
1483             return retval;
1484         }
1485         if (NULL != szLeft)
1486         {
1487             *szLeft = 16U - lastSize;
1488         }
1489 
1490         /* Initialize algorithm state. */
1491         base->MD = modeReg | (uint32_t)kLTC_ModeUpdate;
1492 
1493         /* context is re-used (CTRi) */
1494 
1495         /* Process data and return status. */
1496         retval = ltc_symmetric_process_data(base, zeroes, 16U, counterlast);
1497     }
1498     (void)ltc_get_context(base, &counter[0], 16U, 4U);
1499     ltc_clear_all(base, false);
1500     return retval;
1501 }
1502 
1503 #if defined(FSL_FEATURE_LTC_HAS_GCM) && FSL_FEATURE_LTC_HAS_GCM
1504 /*******************************************************************************
1505  * GCM Code static
1506  ******************************************************************************/
ltc_aes_gcm_check_input_args(LTC_Type * base,const uint8_t * src,const uint8_t * iv,const uint8_t * aad,const uint8_t * key,uint8_t * dst,uint32_t inputSize,uint32_t ivSize,uint32_t aadSize,uint32_t keySize,uint32_t tagSize)1507 static status_t ltc_aes_gcm_check_input_args(LTC_Type *base,
1508                                              const uint8_t *src,
1509                                              const uint8_t *iv,
1510                                              const uint8_t *aad,
1511                                              const uint8_t *key,
1512                                              uint8_t *dst,
1513                                              uint32_t inputSize,
1514                                              uint32_t ivSize,
1515                                              uint32_t aadSize,
1516                                              uint32_t keySize,
1517                                              uint32_t tagSize)
1518 {
1519     if (NULL == base)
1520     {
1521         return kStatus_InvalidArgument;
1522     }
1523 
1524     /* tag can be NULL to skip tag processing */
1525     if ((NULL == key) || ((0U != ivSize) && (NULL == iv)) || ((0U != aadSize) && (NULL == aad)) ||
1526         ((0U != inputSize) && ((NULL == src) || (NULL == dst))))
1527     {
1528         return kStatus_InvalidArgument;
1529     }
1530 
1531     /* octet length of tag (tagSize) must be element of 4,8,12,13,14,15,16 */
1532     if (((tagSize > 16u) || (tagSize < 12u)) && (tagSize != 4u) && (tagSize != 8u))
1533     {
1534         return kStatus_InvalidArgument;
1535     }
1536 
1537     /* check if keySize is supported */
1538     if (!ltc_check_key_size(keySize))
1539     {
1540         return kStatus_InvalidArgument;
1541     }
1542 
1543     /* no IV AAD DATA makes no sense */
1544     if (0U == (inputSize + ivSize + aadSize))
1545     {
1546         return kStatus_InvalidArgument;
1547     }
1548 
1549     return kStatus_Success;
1550 }
1551 
1552 /*!
1553  * @brief Process Wrapper for void (*pfunc)(LTC_Type*, uint32_t, bool). Sets IV Size register.
1554  */
ivsize_next(LTC_Type * base,uint32_t ivSize,bool iv_only)1555 static void ivsize_next(LTC_Type *base, uint32_t ivSize, bool iv_only)
1556 {
1557     base->IVSZ = LTC_IVSZ_IL(iv_only) | ((ivSize)&LTC_DS_DS_MASK);
1558 }
1559 
1560 /*!
1561  * @brief Process Wrapper for void (*pfunc)(LTC_Type*, uint32_t, bool). Sets AAD Size register.
1562  */
aadsize_next(LTC_Type * base,uint32_t aadSize,bool aad_only)1563 static void aadsize_next(LTC_Type *base, uint32_t aadSize, bool aad_only)
1564 {
1565     base->AADSZ = LTC_AADSZ_AL(aad_only) | ((aadSize)&LTC_DS_DS_MASK);
1566 }
1567 
1568 /*!
1569  * @brief Process IV or AAD string in multi-session.
1570  *
1571  * @param base LTC peripheral base address
1572  * @param iv IV or AAD data
1573  * @param ivSize Size in bytes of IV or AAD data
1574  * @param modeReg LTC peripheral Mode register value
1575  * @param iv_only IV only or AAD only flag
1576  * @param type selects between IV or AAD
1577  */
ltc_aes_gcm_process_iv_aad(LTC_Type * base,const uint8_t * iv,uint32_t ivSize,ltc_mode_t modeReg,bool iv_only,int type,ltc_mode_t modeLast)1578 static status_t ltc_aes_gcm_process_iv_aad(
1579     LTC_Type *base, const uint8_t *iv, uint32_t ivSize, ltc_mode_t modeReg, bool iv_only, int type, ltc_mode_t modeLast)
1580 {
1581     uint32_t sz;
1582     status_t retval;
1583     void (*next_size_func)(LTC_Type * ltcBase, uint32_t nextSize, bool authOnly);
1584 
1585     if ((NULL == iv) || (ivSize == 0U))
1586     {
1587         return kStatus_InvalidArgument;
1588     }
1589 
1590     sz             = LTC_FIFO_SZ_MAX_DOWN_ALGN;
1591     next_size_func = type == LTC_AES_GCM_TYPE_AAD ? aadsize_next : ivsize_next;
1592 
1593     while (0U != ivSize)
1594     {
1595         if (ivSize < sz)
1596         {
1597             modeReg &= ~LTC_MD_AS_MASK;
1598             modeReg |= modeLast;
1599             base->MD = modeReg;
1600             next_size_func(base, ivSize, iv_only);
1601             ltc_move_to_ififo(base, iv, ivSize);
1602             ivSize = 0;
1603         }
1604         else
1605         {
1606             /* set algorithm state to UPDATE */
1607             modeReg &= ~LTC_MD_AS_MASK;
1608             modeReg |= (uint32_t)kLTC_ModeUpdate;
1609             base->MD = modeReg;
1610 
1611             next_size_func(base, (uint16_t)sz, true);
1612             ltc_move_to_ififo(base, iv, sz);
1613             ivSize -= sz;
1614             iv += sz;
1615         }
1616 
1617         retval = ltc_wait(base);
1618         if (kStatus_Success != retval)
1619         {
1620             return retval;
1621         }
1622     } /* end while */
1623     return kStatus_Success;
1624 }
1625 
ltc_aes_gcm_process(LTC_Type * base,ltc_mode_encrypt_t encryptMode,const uint8_t * src,uint32_t inputSize,const uint8_t * iv,uint32_t ivSize,const uint8_t * aad,uint32_t aadSize,const uint8_t * key,uint32_t keySize,uint8_t * dst,uint8_t * tag,uint32_t tagSize)1626 static status_t ltc_aes_gcm_process(LTC_Type *base,
1627                                     ltc_mode_encrypt_t encryptMode,
1628                                     const uint8_t *src,
1629                                     uint32_t inputSize,
1630                                     const uint8_t *iv,
1631                                     uint32_t ivSize,
1632                                     const uint8_t *aad,
1633                                     uint32_t aadSize,
1634                                     const uint8_t *key,
1635                                     uint32_t keySize,
1636                                     uint8_t *dst,
1637                                     uint8_t *tag,
1638                                     uint32_t tagSize)
1639 {
1640     status_t retval;          /* return value */
1641     uint32_t max_ltc_fifo_sz; /* maximum data size that we can put to LTC FIFO in one session. 12-bit limit. */
1642     ltc_mode_t modeReg;       /* read and write LTC mode register */
1643 
1644     bool single_ses_proc_all; /* iv, aad and src data can be processed in one session */
1645     bool iv_only;
1646     bool aad_only;
1647 
1648     retval = ltc_aes_gcm_check_input_args(base, src, iv, aad, key, dst, inputSize, ivSize, aadSize, keySize, tagSize);
1649 
1650     /* API input validation */
1651     if (kStatus_Success != retval)
1652     {
1653         return retval;
1654     }
1655 
1656     max_ltc_fifo_sz = LTC_DS_DS_MASK; /* 12-bit field limit */
1657 
1658     /*
1659      * Write value to LTC AADSIZE (rounded up to next 16 byte boundary)
1660      * plus the write value to LTC IV (rounded up to next 16 byte boundary)
1661      * plus the inputSize. If the result is less than max_ltc_fifo_sz
1662      * then all can be processed in one session FINALIZE.
1663      * Otherwise, we have to split into multiple session, going through UPDATE(s), INITIALIZE, UPDATE(s) and FINALIZE.
1664      */
1665     single_ses_proc_all =
1666         (((aadSize + 15u) & 0xfffffff0u) + ((ivSize + 15u) & 0xfffffff0u) + inputSize) <= max_ltc_fifo_sz;
1667 
1668     /* setup key, algorithm and set the alg.state */
1669     if (single_ses_proc_all)
1670     {
1671         (void)ltc_symmetric_final(base, key, (uint8_t)keySize, kLTC_AlgorithmAES, kLTC_ModeGCM, encryptMode);
1672         modeReg = base->MD;
1673 
1674         iv_only  = (aadSize == 0U) && (inputSize == 0U);
1675         aad_only = (inputSize == 0U);
1676 
1677         /* DS_MASK here is not a bug. IV size field can be written with more than 4-bits,
1678          * as the IVSZ write value, aligned to next 16 bytes boundary, is written also to the Data Size.
1679          * For example, I can write 22 to IVSZ, 32 will be written to Data Size and IVSZ will have value 6, which is 22
1680          * mod 16.
1681          */
1682         base->IVSZ = LTC_IVSZ_IL(iv_only) | ((ivSize)&LTC_DS_DS_MASK);
1683         ltc_move_to_ififo(base, iv, ivSize);
1684         if (iv_only && ivSize != 0U)
1685         {
1686             retval = ltc_wait(base);
1687             if (kStatus_Success != retval)
1688             {
1689                 return retval;
1690             }
1691         }
1692         base->AADSZ = LTC_AADSZ_AL(aad_only) | ((aadSize)&LTC_DS_DS_MASK);
1693         ltc_move_to_ififo(base, aad, aadSize);
1694         if (aad_only && (0U != aadSize))
1695         {
1696             retval = ltc_wait(base);
1697             if (kStatus_Success != retval)
1698             {
1699                 return retval;
1700             }
1701         }
1702 
1703         if (0U != inputSize)
1704         {
1705             /* Workaround for the LTC Data Size register update errata TKT261180 */
1706             while (16U < base->DS)
1707             {
1708             }
1709 
1710             (void)ltc_symmetric_process_data(base, &src[0], inputSize, &dst[0]);
1711         }
1712     }
1713     else
1714     {
1715         retval = ltc_symmetric_init(base, key, (uint8_t)keySize, kLTC_AlgorithmAES, kLTC_ModeGCM, encryptMode);
1716         if (kStatus_Success != retval)
1717         {
1718             return retval;
1719         }
1720         modeReg = base->MD;
1721 
1722         /* process IV */
1723         if (0U != ivSize)
1724         {
1725             /* last chunk of IV is always INITIALIZE (for GHASH to occur) */
1726             retval = ltc_aes_gcm_process_iv_aad(base, iv, ivSize, modeReg, true, LTC_AES_GCM_TYPE_IV,
1727                                                 (uint32_t)kLTC_ModeInit);
1728             if (kStatus_Success != retval)
1729             {
1730                 return retval;
1731             }
1732         }
1733 
1734         /* process AAD */
1735         if (0U != aadSize)
1736         {
1737             /* AS mode to process last chunk of AAD. it differs if we are in GMAC or GCM */
1738             ltc_mode_t lastModeReg;
1739             if (0U == inputSize)
1740             {
1741                 /* if there is no DATA, set mode to compute final MAC. this is GMAC mode */
1742                 lastModeReg = (uint32_t)kLTC_ModeInitFinal;
1743             }
1744             else
1745             {
1746                 /* there are confidential DATA. so process last chunk of AAD in UPDATE mode */
1747                 lastModeReg = (uint32_t)kLTC_ModeUpdate;
1748             }
1749             retval = ltc_aes_gcm_process_iv_aad(base, aad, aadSize, modeReg, true, LTC_AES_GCM_TYPE_AAD, lastModeReg);
1750             if (kStatus_Success != retval)
1751             {
1752                 return retval;
1753             }
1754         }
1755 
1756         /* there are DATA. */
1757         if (0U != inputSize)
1758         {
1759             /* set algorithm state to UPDATE */
1760             modeReg &= ~LTC_MD_AS_MASK;
1761             modeReg |= (uint32_t)kLTC_ModeUpdate;
1762             base->MD = modeReg;
1763             retval =
1764                 ltc_symmetric_process_data_multiple(base, &src[0], inputSize, &dst[0], modeReg, kLTC_ModeInitFinal);
1765         }
1766     }
1767     if (kStatus_Success != retval)
1768     {
1769         return retval;
1770     }
1771     retval = ltc_aes_process_tag(base, tag, tagSize, modeReg, LTC_GCM_TAG_IDX);
1772     return retval;
1773 }
1774 
1775 /*******************************************************************************
1776  * GCM Code public
1777  ******************************************************************************/
1778 /*!
1779  * brief Encrypts AES and tags using GCM block mode.
1780  *
1781  * Encrypts AES and optionally tags using GCM block mode. If plaintext is NULL, only the GHASH is calculated and output
1782  * in the 'tag' field.
1783  *
1784  * param base LTC peripheral base address
1785  * param plaintext Input plain text to encrypt
1786  * param[out] ciphertext Output cipher text.
1787  * param size Size of input and output data in bytes
1788  * param iv Input initial vector
1789  * param ivSize Size of the IV
1790  * param aad Input additional authentication data
1791  * param aadSize Input size in bytes of AAD
1792  * param key Input key to use for encryption
1793  * param keySize Size of the input key, in bytes. Must be 16, 24, or 32.
1794  * param[out] tag Output hash tag. Set to NULL to skip tag processing.
1795  * param tagSize Input size of the tag to generate, in bytes. Must be 4,8,12,13,14,15 or 16.
1796  * return Status from encrypt operation
1797  */
LTC_AES_EncryptTagGcm(LTC_Type * base,const uint8_t * plaintext,uint8_t * ciphertext,uint32_t size,const uint8_t * iv,uint32_t ivSize,const uint8_t * aad,uint32_t aadSize,const uint8_t * key,uint32_t keySize,uint8_t * tag,uint32_t tagSize)1798 status_t LTC_AES_EncryptTagGcm(LTC_Type *base,
1799                                const uint8_t *plaintext,
1800                                uint8_t *ciphertext,
1801                                uint32_t size,
1802                                const uint8_t *iv,
1803                                uint32_t ivSize,
1804                                const uint8_t *aad,
1805                                uint32_t aadSize,
1806                                const uint8_t *key,
1807                                uint32_t keySize,
1808                                uint8_t *tag,
1809                                uint32_t tagSize)
1810 {
1811     status_t status;
1812 
1813     status = ltc_aes_gcm_process(base, kLTC_ModeEncrypt, plaintext, size, iv, ivSize, aad, aadSize, key, keySize,
1814                                  ciphertext, tag, tagSize);
1815 
1816     ltc_clear_all(base, false);
1817     return status;
1818 }
1819 
1820 /*!
1821  * brief Decrypts AES and authenticates using GCM block mode.
1822  *
1823  * Decrypts AES and optionally authenticates using GCM block mode. If ciphertext is NULL, only the GHASH is calculated
1824  * and compared with the received GHASH in 'tag' field.
1825  *
1826  * param base LTC peripheral base address
1827  * param ciphertext Input cipher text to decrypt
1828  * param[out] plaintext Output plain text.
1829  * param size Size of input and output data in bytes
1830  * param iv Input initial vector
1831  * param ivSize Size of the IV
1832  * param aad Input additional authentication data
1833  * param aadSize Input size in bytes of AAD
1834  * param key Input key to use for encryption
1835  * param keySize Size of the input key, in bytes. Must be 16, 24, or 32.
1836  * param tag Input hash tag to compare. Set to NULL to skip tag processing.
1837  * param tagSize Input size of the tag, in bytes. Must be 4, 8, 12, 13, 14, 15, or 16.
1838  * return Status from decrypt operation
1839  */
LTC_AES_DecryptTagGcm(LTC_Type * base,const uint8_t * ciphertext,uint8_t * plaintext,uint32_t size,const uint8_t * iv,uint32_t ivSize,const uint8_t * aad,uint32_t aadSize,const uint8_t * key,uint32_t keySize,const uint8_t * tag,uint32_t tagSize)1840 status_t LTC_AES_DecryptTagGcm(LTC_Type *base,
1841                                const uint8_t *ciphertext,
1842                                uint8_t *plaintext,
1843                                uint32_t size,
1844                                const uint8_t *iv,
1845                                uint32_t ivSize,
1846                                const uint8_t *aad,
1847                                uint32_t aadSize,
1848                                const uint8_t *key,
1849                                uint32_t keySize,
1850                                const uint8_t *tag,
1851                                uint32_t tagSize)
1852 {
1853     uint8_t temp_tag[16] = {0}; /* max. octet length of Integrity Check Value ICV (tag) is 16 */
1854     uint8_t *tag_ptr;
1855     status_t status;
1856 
1857     tag_ptr = NULL;
1858     if (NULL != tag)
1859     {
1860         ltc_memcpy(temp_tag, tag, tagSize);
1861         tag_ptr = &temp_tag[0];
1862     }
1863     status = ltc_aes_gcm_process(base, kLTC_ModeDecrypt, ciphertext, size, iv, ivSize, aad, aadSize, key, keySize,
1864                                  plaintext, tag_ptr, tagSize);
1865 
1866     ltc_clear_all(base, false);
1867     return status;
1868 }
1869 #endif /* FSL_FEATURE_LTC_HAS_GCM */
1870 
1871 /*******************************************************************************
1872  * CCM Code static
1873  ******************************************************************************/
ltc_aes_ccm_check_input_args(LTC_Type * base,const uint8_t * src,const uint8_t * iv,const uint8_t * key,uint8_t * dst,uint32_t ivSize,uint32_t aadSize,uint32_t keySize,uint32_t tagSize)1874 static status_t ltc_aes_ccm_check_input_args(LTC_Type *base,
1875                                              const uint8_t *src,
1876                                              const uint8_t *iv,
1877                                              const uint8_t *key,
1878                                              uint8_t *dst,
1879                                              uint32_t ivSize,
1880                                              uint32_t aadSize,
1881                                              uint32_t keySize,
1882                                              uint32_t tagSize)
1883 {
1884     if (NULL == base)
1885     {
1886         return kStatus_InvalidArgument;
1887     }
1888 
1889     /* tag can be NULL to skip tag processing */
1890     if ((NULL == src) || (NULL == iv) || (NULL == key) || (NULL == dst))
1891     {
1892         return kStatus_InvalidArgument;
1893     }
1894 
1895     /* size of Nonce (ivSize) must be element of 7,8,9,10,11,12,13 */
1896     if ((ivSize < 7u) || (ivSize > 13u))
1897     {
1898         return kStatus_InvalidArgument;
1899     }
1900     /* octet length of MAC (tagSize) must be element of 4,6,8,10,12,14,16 for tag processing or zero to skip tag
1901      * processing */
1902     if (((tagSize > 0u) && (tagSize < 4u)) || (tagSize > 16u) || (0U != (tagSize & 1u)))
1903     {
1904         return kStatus_InvalidArgument;
1905     }
1906 
1907     /* check if keySize is supported */
1908     if (!ltc_check_key_size(keySize))
1909     {
1910         return kStatus_InvalidArgument;
1911     }
1912 
1913     /* LTC does not support more AAD than this */
1914     if (aadSize >= 65280u)
1915     {
1916         return kStatus_InvalidArgument;
1917     }
1918     return kStatus_Success;
1919 }
1920 
swap_bytes(uint32_t in)1921 static uint32_t swap_bytes(uint32_t in)
1922 {
1923     return (((in & 0x000000ffu) << 24U) | ((in & 0x0000ff00u) << 8U) | ((in & 0x00ff0000u) >> 8U) |
1924             ((in & 0xff000000u) >> 24U));
1925 }
1926 
ltc_aes_ccm_context_init(LTC_Type * base,uint32_t inputSize,const uint8_t * iv,uint32_t ivSize,uint32_t aadSize,uint32_t tagSize)1927 static void ltc_aes_ccm_context_init(
1928     LTC_Type *base, uint32_t inputSize, const uint8_t *iv, uint32_t ivSize, uint32_t aadSize, uint32_t tagSize)
1929 {
1930     ltc_xcm_block_t blk;
1931     ltc_xcm_block_t blkZero = {{0x0u, 0x0u, 0x0u, 0x0u}};
1932 
1933     uint32_t q; /* octet length of binary representation of the octet length of the payload. computed as (15 - n), where
1934               n is length of nonce(=ivSize) */
1935     uint8_t flags; /* flags field in B0 and CTR0 */
1936 
1937     /* compute B0 */
1938     ltc_memcpy(&blk, &blkZero, sizeof(blk));
1939     /* tagSize - size of output MAC */
1940     q     = 15u - ivSize;
1941     flags = (uint8_t)(8u * ((tagSize - 2u) / 2u) + q - 1u); /* 8*M' + L' */
1942     if (0U != aadSize)
1943     {
1944         flags |= 0x40U; /* Adata */
1945     }
1946     blk.b[0] = flags;                  /* flags field */
1947     blk.w[3] = swap_bytes(inputSize);  /* message size, most significant byte first */
1948     ltc_memcpy(&blk.b[1], iv, ivSize); /* nonce field */
1949 
1950     /* Write B0 data to the context register.
1951      */
1952     (void)ltc_set_context(base, &blk.b[0], 16, 0);
1953 
1954     /* Write CTR0 to the context register.
1955      */
1956     ltc_memcpy(&blk, &blkZero, sizeof(blk)); /* ctr(0) field = zero */
1957     blk.b[0] = (uint8_t)(q - 1u);            /* flags field */
1958     ltc_memcpy(&blk.b[1], iv, ivSize);       /* nonce field */
1959     (void)ltc_set_context(base, &blk.b[0], 16, 4);
1960 }
1961 
ltc_aes_ccm_process_aad(LTC_Type * base,uint32_t inputSize,const uint8_t * aad,uint32_t aadSize,ltc_mode_t * modeReg)1962 static status_t ltc_aes_ccm_process_aad(
1963     LTC_Type *base, uint32_t inputSize, const uint8_t *aad, uint32_t aadSize, ltc_mode_t *modeReg)
1964 {
1965     ltc_xcm_block_t blk = {{0x0u, 0x0u, 0x0u, 0x0u}};
1966     uint32_t swapped; /* holds byte swap of uint32_t */
1967     status_t retval;
1968 
1969     if (0U != aadSize)
1970     {
1971         bool aad_only;
1972         bool aad_single_session;
1973 
1974         uint32_t sz = 0;
1975 
1976         aad_only           = inputSize == 0u;
1977         aad_single_session = (((aadSize + 2u) + 15u) & 0xfffffff0u) <= LTC_FIFO_SZ_MAX_DOWN_ALGN;
1978 
1979         /* limit by CCM spec: 2^16 - 2^8 = 65280 */
1980 
1981         /* encoding is two octets, msbyte first */
1982         swapped = swap_bytes(aadSize);
1983         ltc_memcpy(&blk.b[0], ((uint8_t *)&swapped) + sizeof(uint16_t), sizeof(uint16_t));
1984 
1985         sz = aadSize > 14u ? 14u : aadSize; /* limit aad to the end of 16 bytes blk */
1986         ltc_memcpy(&blk.b[2], aad, sz);     /* fill B1 with aad */
1987 
1988         if (aad_single_session)
1989         {
1990             base->AADSZ = LTC_AADSZ_AL((true == aad_only ? 1U : 0U)) | ((aadSize + 2U) & LTC_DS_DS_MASK);
1991             /* move first AAD block (16 bytes block B1) to FIFO */
1992             ltc_move_block_to_ififo(base, (const ltc_xcm_block_t *)(uint32_t)&blk, sizeof(blk));
1993         }
1994         else
1995         {
1996             base->AADSZ = LTC_AADSZ_AL(1U) | (16U);
1997             /* move first AAD block (16 bytes block B1) to FIFO */
1998             ltc_move_block_to_ififo(base, (const ltc_xcm_block_t *)(uint32_t)&blk, sizeof(blk));
1999         }
2000 
2001         /* track consumed AAD. sz bytes have been moved to fifo. */
2002         aadSize -= sz;
2003         aad = &aad[sz];
2004 
2005         if (aad_single_session)
2006         {
2007             /* move remaining AAD to FIFO, then return, to continue with MDATA */
2008             ltc_move_to_ififo(base, aad, aadSize);
2009         }
2010         else if (aadSize == 0u)
2011         {
2012             retval = ltc_wait(base);
2013             if (kStatus_Success != retval)
2014             {
2015                 return retval;
2016             }
2017         }
2018         else
2019         {
2020             while (0U != aadSize)
2021             {
2022                 retval = ltc_wait(base);
2023                 if (kStatus_Success != retval)
2024                 {
2025                     return retval;
2026                 }
2027 
2028                 *modeReg &= ~LTC_MD_AS_MASK;
2029                 *modeReg |= (uint32_t)kLTC_ModeUpdate;
2030                 base->MD = *modeReg;
2031 
2032                 sz = LTC_FIFO_SZ_MAX_DOWN_ALGN;
2033                 if (aadSize < sz)
2034                 {
2035                     base->AADSZ = LTC_AADSZ_AL((true == aad_only ? 1U : 0U)) | (aadSize & LTC_DS_DS_MASK);
2036                     ltc_move_to_ififo(base, aad, aadSize);
2037                     aadSize = 0;
2038                 }
2039                 else
2040                 {
2041                     base->AADSZ = LTC_AADSZ_AL(1U) | (sz & LTC_DS_DS_MASK);
2042                     ltc_move_to_ififo(base, aad, sz);
2043                     aadSize -= sz;
2044                     aad = &aad[sz];
2045                 }
2046             } /* end while */
2047         }     /* end else */
2048     }         /* end if */
2049     return kStatus_Success;
2050 }
2051 
ltc_aes_ccm_process(LTC_Type * base,ltc_mode_encrypt_t encryptMode,const uint8_t * src,uint32_t inputSize,const uint8_t * iv,uint32_t ivSize,const uint8_t * aad,uint32_t aadSize,const uint8_t * key,uint32_t keySize,uint8_t * dst,uint8_t * tag,uint32_t tagSize)2052 static status_t ltc_aes_ccm_process(LTC_Type *base,
2053                                     ltc_mode_encrypt_t encryptMode,
2054                                     const uint8_t *src,
2055                                     uint32_t inputSize,
2056                                     const uint8_t *iv,
2057                                     uint32_t ivSize,
2058                                     const uint8_t *aad,
2059                                     uint32_t aadSize,
2060                                     const uint8_t *key,
2061                                     uint32_t keySize,
2062                                     uint8_t *dst,
2063                                     uint8_t *tag,
2064                                     uint32_t tagSize)
2065 {
2066     status_t retval;          /* return value */
2067     uint32_t max_ltc_fifo_sz; /* maximum data size that we can put to LTC FIFO in one session. 12-bit limit. */
2068     ltc_mode_t modeReg;       /* read and write LTC mode register */
2069 
2070     bool single_ses_proc_all; /* aad and src data can be processed in one session */
2071 
2072     retval = ltc_aes_ccm_check_input_args(base, src, iv, key, dst, ivSize, aadSize, keySize, tagSize);
2073 
2074     /* API input validation */
2075     if (kStatus_Success != retval)
2076     {
2077         return retval;
2078     }
2079 
2080     max_ltc_fifo_sz = LTC_DS_DS_MASK; /* 12-bit field limit */
2081 
2082     /* Write value to LTC AADSIZE will be (aadSize+2) value.
2083      * The value will be rounded up to next 16 byte boundary and added to Data Size register.
2084      * We then add inputSize to Data Size register. If the resulting Data Size is less than max_ltc_fifo_sz
2085      * then all can be processed in one session INITIALIZE/FINALIZE.
2086      * Otherwise, we have to split into multiple session, going through INITIALIZE, UPDATE (if required) and FINALIZE.
2087      */
2088     single_ses_proc_all = ((((aadSize + 2u) + 15u) & 0xfffffff0u) + inputSize) <= max_ltc_fifo_sz;
2089 
2090     /* setup key, algorithm and set the alg.state to INITIALIZE */
2091     if (single_ses_proc_all)
2092     {
2093         retval = ltc_symmetric_init_final(base, key, (uint8_t)keySize, kLTC_AlgorithmAES, kLTC_ModeCCM, encryptMode);
2094         if (kStatus_Success != retval)
2095         {
2096             return retval;
2097         }
2098     }
2099     else
2100     {
2101         retval = ltc_symmetric_init(base, key, (uint8_t)keySize, kLTC_AlgorithmAES, kLTC_ModeCCM, encryptMode);
2102         if (kStatus_Success != retval)
2103         {
2104             return retval;
2105         }
2106     }
2107     modeReg = base->MD;
2108 
2109     /* Initialize LTC context for AES CCM: block B0 and initial counter CTR0 */
2110     ltc_aes_ccm_context_init(base, inputSize, iv, ivSize, aadSize, tagSize);
2111 
2112     /* Process additional authentication data, if there are any.
2113      * Need to split the job into individual sessions of up to 4096 bytes, due to LTC IFIFO data size limit.
2114      */
2115     retval = ltc_aes_ccm_process_aad(base, inputSize, aad, aadSize, &modeReg);
2116     if (kStatus_Success != retval)
2117     {
2118         return retval;
2119     }
2120 
2121     /* Workaround for the LTC Data Size register update errata TKT261180 */
2122     if (0U != inputSize)
2123     {
2124         while (16u < base->DS)
2125         {
2126         }
2127     }
2128 
2129     /* Process message */
2130     if (single_ses_proc_all)
2131     {
2132         retval = ltc_symmetric_process_data(base, &src[0], inputSize, &dst[0]);
2133     }
2134     else
2135     {
2136         retval = ltc_symmetric_process_data_multiple(base, &src[0], inputSize, &dst[0], modeReg, kLTC_ModeFinalize);
2137     }
2138     if (kStatus_Success != retval)
2139     {
2140         return retval;
2141     }
2142     retval = ltc_aes_process_tag(base, tag, tagSize, modeReg, LTC_CCM_TAG_IDX);
2143     return retval;
2144 }
2145 
2146 /*******************************************************************************
2147  * CCM Code public
2148  ******************************************************************************/
2149 /*!
2150  * brief Encrypts AES and tags using CCM block mode.
2151  *
2152  * Encrypts AES and optionally tags using CCM block mode.
2153  *
2154  * param base LTC peripheral base address
2155  * param plaintext Input plain text to encrypt
2156  * param[out] ciphertext Output cipher text.
2157  * param size Size of input and output data in bytes. Zero means authentication only.
2158  * param iv Nonce
2159  * param ivSize Length of the Nonce in bytes. Must be 7, 8, 9, 10, 11, 12, or 13.
2160  * param aad Input additional authentication data. Can be NULL if aadSize is zero.
2161  * param aadSize Input size in bytes of AAD. Zero means data mode only (authentication skipped).
2162  * param key Input key to use for encryption
2163  * param keySize Size of the input key, in bytes. Must be 16, 24, or 32.
2164  * param[out] tag Generated output tag. Set to NULL to skip tag processing.
2165  * param tagSize Input size of the tag to generate, in bytes. Must be 4, 6, 8, 10, 12, 14, or 16.
2166  * return Status from encrypt operation
2167  */
LTC_AES_EncryptTagCcm(LTC_Type * base,const uint8_t * plaintext,uint8_t * ciphertext,uint32_t size,const uint8_t * iv,uint32_t ivSize,const uint8_t * aad,uint32_t aadSize,const uint8_t * key,uint32_t keySize,uint8_t * tag,uint32_t tagSize)2168 status_t LTC_AES_EncryptTagCcm(LTC_Type *base,
2169                                const uint8_t *plaintext,
2170                                uint8_t *ciphertext,
2171                                uint32_t size,
2172                                const uint8_t *iv,
2173                                uint32_t ivSize,
2174                                const uint8_t *aad,
2175                                uint32_t aadSize,
2176                                const uint8_t *key,
2177                                uint32_t keySize,
2178                                uint8_t *tag,
2179                                uint32_t tagSize)
2180 {
2181     status_t status;
2182     status = ltc_aes_ccm_process(base, kLTC_ModeEncrypt, plaintext, size, iv, ivSize, aad, aadSize, key, keySize,
2183                                  ciphertext, tag, tagSize);
2184 
2185     ltc_clear_all(base, false);
2186     return status;
2187 }
2188 
2189 /*!
2190  * brief Decrypts AES and authenticates using CCM block mode.
2191  *
2192  * Decrypts AES and optionally authenticates using CCM block mode.
2193  *
2194  * param base LTC peripheral base address
2195  * param ciphertext Input cipher text to decrypt
2196  * param[out] plaintext Output plain text.
2197  * param size Size of input and output data in bytes. Zero means authentication only.
2198  * param iv Nonce
2199  * param ivSize Length of the Nonce in bytes. Must be 7, 8, 9, 10, 11, 12, or 13.
2200  * param aad Input additional authentication data. Can be NULL if aadSize is zero.
2201  * param aadSize Input size in bytes of AAD. Zero means data mode only (authentication skipped).
2202  * param key Input key to use for decryption
2203  * param keySize Size of the input key, in bytes. Must be 16, 24, or 32.
2204  * param tag Received tag. Set to NULL to skip tag processing.
2205  * param tagSize Input size of the received tag to compare with the computed tag, in bytes. Must be 4, 6, 8, 10, 12,
2206  * 14, or 16.
2207  * return Status from decrypt operation
2208  */
LTC_AES_DecryptTagCcm(LTC_Type * base,const uint8_t * ciphertext,uint8_t * plaintext,uint32_t size,const uint8_t * iv,uint32_t ivSize,const uint8_t * aad,uint32_t aadSize,const uint8_t * key,uint32_t keySize,const uint8_t * tag,uint32_t tagSize)2209 status_t LTC_AES_DecryptTagCcm(LTC_Type *base,
2210                                const uint8_t *ciphertext,
2211                                uint8_t *plaintext,
2212                                uint32_t size,
2213                                const uint8_t *iv,
2214                                uint32_t ivSize,
2215                                const uint8_t *aad,
2216                                uint32_t aadSize,
2217                                const uint8_t *key,
2218                                uint32_t keySize,
2219                                const uint8_t *tag,
2220                                uint32_t tagSize)
2221 {
2222     uint8_t temp_tag[16] = {0}; /* max. octet length of MAC (tag) is 16 */
2223     uint8_t *tag_ptr;
2224     status_t status;
2225 
2226     tag_ptr = NULL;
2227     if (NULL != tag)
2228     {
2229         ltc_memcpy(temp_tag, tag, tagSize);
2230         tag_ptr = &temp_tag[0];
2231     }
2232 
2233     status = ltc_aes_ccm_process(base, kLTC_ModeDecrypt, ciphertext, size, iv, ivSize, aad, aadSize, key, keySize,
2234                                  plaintext, tag_ptr, tagSize);
2235 
2236     ltc_clear_all(base, false);
2237     return status;
2238 }
2239 
2240 #if defined(FSL_FEATURE_LTC_HAS_DES) && FSL_FEATURE_LTC_HAS_DES
2241 /*******************************************************************************
2242  * DES / 3DES Code static
2243  ******************************************************************************/
ltc_des_process(LTC_Type * base,const uint8_t * input,uint8_t * output,uint32_t size,const uint8_t iv[LTC_DES_IV_SIZE],const uint8_t key[LTC_DES_KEY_SIZE],ltc_mode_symmetric_alg_t modeAs,ltc_mode_encrypt_t modeEnc)2244 static status_t ltc_des_process(LTC_Type *base,
2245                                 const uint8_t *input,
2246                                 uint8_t *output,
2247                                 uint32_t size,
2248                                 const uint8_t iv[LTC_DES_IV_SIZE],
2249                                 const uint8_t key[LTC_DES_KEY_SIZE],
2250                                 ltc_mode_symmetric_alg_t modeAs,
2251                                 ltc_mode_encrypt_t modeEnc)
2252 {
2253     status_t retval;
2254 
2255     /* all but OFB, size must be 8-byte multiple */
2256     if ((modeAs != kLTC_ModeOFB) && ((size < 8u) || (0U != (size % 8u))))
2257     {
2258         return kStatus_InvalidArgument;
2259     }
2260 
2261     /* Initialize algorithm state. */
2262     retval = ltc_symmetric_update(base, &key[0], LTC_DES_KEY_SIZE, kLTC_AlgorithmDES, modeAs, modeEnc);
2263     if (kStatus_Success != retval)
2264     {
2265         return retval;
2266     }
2267     if ((modeAs != kLTC_ModeECB))
2268     {
2269         retval = ltc_set_context(base, iv, LTC_DES_IV_SIZE, 0);
2270         if (kStatus_Success != retval)
2271         {
2272             return retval;
2273         }
2274     }
2275 
2276     /* Process data and return status. */
2277     retval = ltc_process_message_in_sessions(base, input, size, output);
2278     ltc_clear_all(base, false);
2279     return retval;
2280 }
2281 
ltc_3des_check_input_args(ltc_mode_symmetric_alg_t modeAs,uint32_t size,const uint8_t * key1,const uint8_t * key2)2282 status_t ltc_3des_check_input_args(ltc_mode_symmetric_alg_t modeAs,
2283                                    uint32_t size,
2284                                    const uint8_t *key1,
2285                                    const uint8_t *key2)
2286 {
2287     /* all but OFB, size must be 8-byte multiple */
2288     if ((modeAs != kLTC_ModeOFB) && ((size < 8u) || (0U != (size % 8u))))
2289     {
2290         return kStatus_InvalidArgument;
2291     }
2292 
2293     if ((key1 == NULL) || (key2 == NULL))
2294     {
2295         return kStatus_InvalidArgument;
2296     }
2297     return kStatus_Success;
2298 }
2299 
ltc_3des_process(LTC_Type * base,const uint8_t * input,uint8_t * output,uint32_t size,const uint8_t iv[LTC_DES_IV_SIZE],const uint8_t key1[LTC_DES_KEY_SIZE],const uint8_t key2[LTC_DES_KEY_SIZE],const uint8_t key3[LTC_DES_KEY_SIZE],ltc_mode_symmetric_alg_t modeAs,ltc_mode_encrypt_t modeEnc)2300 static status_t ltc_3des_process(LTC_Type *base,
2301                                  const uint8_t *input,
2302                                  uint8_t *output,
2303                                  uint32_t size,
2304                                  const uint8_t iv[LTC_DES_IV_SIZE],
2305                                  const uint8_t key1[LTC_DES_KEY_SIZE],
2306                                  const uint8_t key2[LTC_DES_KEY_SIZE],
2307                                  const uint8_t key3[LTC_DES_KEY_SIZE],
2308                                  ltc_mode_symmetric_alg_t modeAs,
2309                                  ltc_mode_encrypt_t modeEnc)
2310 {
2311     status_t retval;
2312     uint8_t key[LTC_DES_KEY_SIZE * 3];
2313     uint8_t keySize = LTC_DES_KEY_SIZE * 2;
2314 
2315     retval = ltc_3des_check_input_args(modeAs, size, key1, key2);
2316     if (kStatus_Success != retval)
2317     {
2318         return retval;
2319     }
2320 
2321     ltc_memcpy(&key[0], &key1[0], LTC_DES_KEY_SIZE);
2322     ltc_memcpy(&key[LTC_DES_KEY_SIZE], &key2[0], LTC_DES_KEY_SIZE);
2323     if (NULL != key3)
2324     {
2325         ltc_memcpy(&key[LTC_DES_KEY_SIZE * 2], &key3[0], LTC_DES_KEY_SIZE);
2326         keySize = (uint8_t)sizeof(key);
2327     }
2328 
2329     /* Initialize algorithm state. */
2330     retval = ltc_symmetric_update(base, &key[0], keySize, kLTC_Algorithm3DES, modeAs, modeEnc);
2331     if (kStatus_Success != retval)
2332     {
2333         return retval;
2334     }
2335 
2336     if ((modeAs != kLTC_ModeECB))
2337     {
2338         retval = ltc_set_context(base, iv, LTC_DES_IV_SIZE, 0);
2339         if (kStatus_Success != retval)
2340         {
2341             return retval;
2342         }
2343     }
2344 
2345     /* Process data and return status. */
2346     retval = ltc_process_message_in_sessions(base, input, size, output);
2347     ltc_clear_all(base, false);
2348     return retval;
2349 }
2350 /*******************************************************************************
2351  * DES / 3DES Code public
2352  ******************************************************************************/
2353 /*!
2354  * brief Encrypts DES using ECB block mode.
2355  *
2356  * Encrypts DES using ECB block mode.
2357  *
2358  * param base LTC peripheral base address
2359  * param plaintext Input plaintext to encrypt
2360  * param[out] ciphertext Output ciphertext
2361  * param size Size of input and output data in bytes. Must be multiple of 8 bytes.
2362  * param key Input key to use for encryption
2363  * return Status from encrypt/decrypt operation
2364  */
LTC_DES_EncryptEcb(LTC_Type * base,const uint8_t * plaintext,uint8_t * ciphertext,uint32_t size,const uint8_t key[LTC_DES_KEY_SIZE])2365 status_t LTC_DES_EncryptEcb(
2366     LTC_Type *base, const uint8_t *plaintext, uint8_t *ciphertext, uint32_t size, const uint8_t key[LTC_DES_KEY_SIZE])
2367 {
2368     return ltc_des_process(base, plaintext, ciphertext, size, NULL, key, kLTC_ModeECB, kLTC_ModeEncrypt);
2369 }
2370 
2371 /*!
2372  * brief Decrypts DES using ECB block mode.
2373  *
2374  * Decrypts DES using ECB block mode.
2375  *
2376  * param base LTC peripheral base address
2377  * param ciphertext Input ciphertext to decrypt
2378  * param[out] plaintext Output plaintext
2379  * param size Size of input and output data in bytes. Must be multiple of 8 bytes.
2380  * param key Input key to use for decryption
2381  * return Status from encrypt/decrypt operation
2382  */
LTC_DES_DecryptEcb(LTC_Type * base,const uint8_t * ciphertext,uint8_t * plaintext,uint32_t size,const uint8_t key[LTC_DES_KEY_SIZE])2383 status_t LTC_DES_DecryptEcb(
2384     LTC_Type *base, const uint8_t *ciphertext, uint8_t *plaintext, uint32_t size, const uint8_t key[LTC_DES_KEY_SIZE])
2385 {
2386     return ltc_des_process(base, ciphertext, plaintext, size, NULL, key, kLTC_ModeECB, kLTC_ModeDecrypt);
2387 }
2388 
2389 /*!
2390  * brief Encrypts DES using CBC block mode.
2391  *
2392  * Encrypts DES using CBC block mode.
2393  *
2394  * param base LTC peripheral base address
2395  * param plaintext Input plaintext to encrypt
2396  * param[out] ciphertext Ouput ciphertext
2397  * param size Size of input and output data in bytes
2398  * param iv Input initial vector to combine with the first plaintext block.
2399  *           The iv does not need to be secret, but it must be unpredictable.
2400  * param key Input key to use for encryption
2401  * return Status from encrypt/decrypt operation
2402  */
LTC_DES_EncryptCbc(LTC_Type * base,const uint8_t * plaintext,uint8_t * ciphertext,uint32_t size,const uint8_t iv[LTC_DES_IV_SIZE],const uint8_t key[LTC_DES_KEY_SIZE])2403 status_t LTC_DES_EncryptCbc(LTC_Type *base,
2404                             const uint8_t *plaintext,
2405                             uint8_t *ciphertext,
2406                             uint32_t size,
2407                             const uint8_t iv[LTC_DES_IV_SIZE],
2408                             const uint8_t key[LTC_DES_KEY_SIZE])
2409 {
2410     return ltc_des_process(base, plaintext, ciphertext, size, iv, key, kLTC_ModeCBC, kLTC_ModeEncrypt);
2411 }
2412 
2413 /*!
2414  * brief Decrypts DES using CBC block mode.
2415  *
2416  * Decrypts DES using CBC block mode.
2417  *
2418  * param base LTC peripheral base address
2419  * param ciphertext Input ciphertext to decrypt
2420  * param[out] plaintext Output plaintext
2421  * param size Size of input data in bytes
2422  * param iv Input initial vector to combine with the first plaintext block.
2423  *           The iv does not need to be secret, but it must be unpredictable.
2424  * param key Input key to use for decryption
2425  * return Status from encrypt/decrypt operation
2426  */
LTC_DES_DecryptCbc(LTC_Type * base,const uint8_t * ciphertext,uint8_t * plaintext,uint32_t size,const uint8_t iv[LTC_DES_IV_SIZE],const uint8_t key[LTC_DES_KEY_SIZE])2427 status_t LTC_DES_DecryptCbc(LTC_Type *base,
2428                             const uint8_t *ciphertext,
2429                             uint8_t *plaintext,
2430                             uint32_t size,
2431                             const uint8_t iv[LTC_DES_IV_SIZE],
2432                             const uint8_t key[LTC_DES_KEY_SIZE])
2433 {
2434     return ltc_des_process(base, ciphertext, plaintext, size, iv, key, kLTC_ModeCBC, kLTC_ModeDecrypt);
2435 }
2436 
2437 /*!
2438  * brief Encrypts DES using CFB block mode.
2439  *
2440  * Encrypts DES using CFB block mode.
2441  *
2442  * param base LTC peripheral base address
2443  * param plaintext Input plaintext to encrypt
2444  * param size Size of input data in bytes
2445  * param iv Input initial block.
2446  * param key Input key to use for encryption
2447  * param[out] ciphertext Output ciphertext
2448  * return Status from encrypt/decrypt operation
2449  */
LTC_DES_EncryptCfb(LTC_Type * base,const uint8_t * plaintext,uint8_t * ciphertext,uint32_t size,const uint8_t iv[LTC_DES_IV_SIZE],const uint8_t key[LTC_DES_KEY_SIZE])2450 status_t LTC_DES_EncryptCfb(LTC_Type *base,
2451                             const uint8_t *plaintext,
2452                             uint8_t *ciphertext,
2453                             uint32_t size,
2454                             const uint8_t iv[LTC_DES_IV_SIZE],
2455                             const uint8_t key[LTC_DES_KEY_SIZE])
2456 {
2457     return ltc_des_process(base, plaintext, ciphertext, size, iv, key, kLTC_ModeCFB, kLTC_ModeEncrypt);
2458 }
2459 
2460 /*!
2461  * brief Decrypts DES using CFB block mode.
2462  *
2463  * Decrypts DES using CFB block mode.
2464  *
2465  * param base LTC peripheral base address
2466  * param ciphertext Input ciphertext to decrypt
2467  * param[out] plaintext Output plaintext
2468  * param size Size of input and output data in bytes
2469  * param iv Input initial block.
2470  * param key Input key to use for decryption
2471  * return Status from encrypt/decrypt operation
2472  */
LTC_DES_DecryptCfb(LTC_Type * base,const uint8_t * ciphertext,uint8_t * plaintext,uint32_t size,const uint8_t iv[LTC_DES_IV_SIZE],const uint8_t key[LTC_DES_KEY_SIZE])2473 status_t LTC_DES_DecryptCfb(LTC_Type *base,
2474                             const uint8_t *ciphertext,
2475                             uint8_t *plaintext,
2476                             uint32_t size,
2477                             const uint8_t iv[LTC_DES_IV_SIZE],
2478                             const uint8_t key[LTC_DES_KEY_SIZE])
2479 {
2480     return ltc_des_process(base, ciphertext, plaintext, size, iv, key, kLTC_ModeCFB, kLTC_ModeDecrypt);
2481 }
2482 
2483 /*!
2484  * brief Encrypts DES using OFB block mode.
2485  *
2486  * Encrypts DES using OFB block mode.
2487  *
2488  * param base LTC peripheral base address
2489  * param plaintext Input plaintext to encrypt
2490  * param[out] ciphertext Output ciphertext
2491  * param size Size of input and output data in bytes
2492  * param iv Input unique input vector. The OFB mode requires that the IV be unique
2493  *           for each execution of the mode under the given key.
2494  * param key Input key to use for encryption
2495  * return Status from encrypt/decrypt operation
2496  */
LTC_DES_EncryptOfb(LTC_Type * base,const uint8_t * plaintext,uint8_t * ciphertext,uint32_t size,const uint8_t iv[LTC_DES_IV_SIZE],const uint8_t key[LTC_DES_KEY_SIZE])2497 status_t LTC_DES_EncryptOfb(LTC_Type *base,
2498                             const uint8_t *plaintext,
2499                             uint8_t *ciphertext,
2500                             uint32_t size,
2501                             const uint8_t iv[LTC_DES_IV_SIZE],
2502                             const uint8_t key[LTC_DES_KEY_SIZE])
2503 {
2504     return ltc_des_process(base, plaintext, ciphertext, size, iv, key, kLTC_ModeOFB, kLTC_ModeEncrypt);
2505 }
2506 
2507 /*!
2508  * brief Decrypts DES using OFB block mode.
2509  *
2510  * Decrypts DES using OFB block mode.
2511  *
2512  * param base LTC peripheral base address
2513  * param ciphertext Input ciphertext to decrypt
2514  * param[out] plaintext Output plaintext
2515  * param size Size of input and output data in bytes. Must be multiple of 8 bytes.
2516  * param iv Input unique input vector. The OFB mode requires that the IV be unique
2517  *           for each execution of the mode under the given key.
2518  * param key Input key to use for decryption
2519  * return Status from encrypt/decrypt operation
2520  */
LTC_DES_DecryptOfb(LTC_Type * base,const uint8_t * ciphertext,uint8_t * plaintext,uint32_t size,const uint8_t iv[LTC_DES_IV_SIZE],const uint8_t key[LTC_DES_KEY_SIZE])2521 status_t LTC_DES_DecryptOfb(LTC_Type *base,
2522                             const uint8_t *ciphertext,
2523                             uint8_t *plaintext,
2524                             uint32_t size,
2525                             const uint8_t iv[LTC_DES_IV_SIZE],
2526                             const uint8_t key[LTC_DES_KEY_SIZE])
2527 {
2528     return ltc_des_process(base, ciphertext, plaintext, size, iv, key, kLTC_ModeOFB, kLTC_ModeDecrypt);
2529 }
2530 
2531 /*!
2532  * brief Encrypts triple DES using ECB block mode with two keys.
2533  *
2534  * Encrypts triple DES using ECB block mode with two keys.
2535  *
2536  * param base LTC peripheral base address
2537  * param plaintext Input plaintext to encrypt
2538  * param[out] ciphertext Output ciphertext
2539  * param size Size of input and output data in bytes. Must be multiple of 8 bytes.
2540  * param key1 First input key for key bundle
2541  * param key2 Second input key for key bundle
2542  * return Status from encrypt/decrypt operation
2543  */
LTC_DES2_EncryptEcb(LTC_Type * base,const uint8_t * plaintext,uint8_t * ciphertext,uint32_t size,const uint8_t key1[LTC_DES_KEY_SIZE],const uint8_t key2[LTC_DES_KEY_SIZE])2544 status_t LTC_DES2_EncryptEcb(LTC_Type *base,
2545                              const uint8_t *plaintext,
2546                              uint8_t *ciphertext,
2547                              uint32_t size,
2548                              const uint8_t key1[LTC_DES_KEY_SIZE],
2549                              const uint8_t key2[LTC_DES_KEY_SIZE])
2550 {
2551     return ltc_3des_process(base, plaintext, ciphertext, size, NULL, key1, key2, NULL, kLTC_ModeECB, kLTC_ModeEncrypt);
2552 }
2553 
2554 /*!
2555  * brief Encrypts triple DES using ECB block mode with three keys.
2556  *
2557  * Encrypts triple DES using ECB block mode with three keys.
2558  *
2559  * param base LTC peripheral base address
2560  * param plaintext Input plaintext to encrypt
2561  * param[out] ciphertext Output ciphertext
2562  * param size Size of input and output data in bytes. Must be multiple of 8 bytes.
2563  * param key1 First input key for key bundle
2564  * param key2 Second input key for key bundle
2565  * param key3 Third input key for key bundle
2566  * return Status from encrypt/decrypt operation
2567  */
LTC_DES3_EncryptEcb(LTC_Type * base,const uint8_t * plaintext,uint8_t * ciphertext,uint32_t size,const uint8_t key1[LTC_DES_KEY_SIZE],const uint8_t key2[LTC_DES_KEY_SIZE],const uint8_t key3[LTC_DES_KEY_SIZE])2568 status_t LTC_DES3_EncryptEcb(LTC_Type *base,
2569                              const uint8_t *plaintext,
2570                              uint8_t *ciphertext,
2571                              uint32_t size,
2572                              const uint8_t key1[LTC_DES_KEY_SIZE],
2573                              const uint8_t key2[LTC_DES_KEY_SIZE],
2574                              const uint8_t key3[LTC_DES_KEY_SIZE])
2575 {
2576     return ltc_3des_process(base, plaintext, ciphertext, size, NULL, key1, key2, key3, kLTC_ModeECB, kLTC_ModeEncrypt);
2577 }
2578 
2579 /*!
2580  * brief Decrypts triple DES using ECB block mode with two keys.
2581  *
2582  * Decrypts triple DES using ECB block mode with two keys.
2583  *
2584  * param base LTC peripheral base address
2585  * param ciphertext Input ciphertext to decrypt
2586  * param[out] plaintext Output plaintext
2587  * param size Size of input and output data in bytes. Must be multiple of 8 bytes.
2588  * param key1 First input key for key bundle
2589  * param key2 Second input key for key bundle
2590  * return Status from encrypt/decrypt operation
2591  */
LTC_DES2_DecryptEcb(LTC_Type * base,const uint8_t * ciphertext,uint8_t * plaintext,uint32_t size,const uint8_t key1[LTC_DES_KEY_SIZE],const uint8_t key2[LTC_DES_KEY_SIZE])2592 status_t LTC_DES2_DecryptEcb(LTC_Type *base,
2593                              const uint8_t *ciphertext,
2594                              uint8_t *plaintext,
2595                              uint32_t size,
2596                              const uint8_t key1[LTC_DES_KEY_SIZE],
2597                              const uint8_t key2[LTC_DES_KEY_SIZE])
2598 {
2599     return ltc_3des_process(base, ciphertext, plaintext, size, NULL, key1, key2, NULL, kLTC_ModeECB, kLTC_ModeDecrypt);
2600 }
2601 
2602 /*!
2603  * brief Decrypts triple DES using ECB block mode with three keys.
2604  *
2605  * Decrypts triple DES using ECB block mode with three keys.
2606  *
2607  * param base LTC peripheral base address
2608  * param ciphertext Input ciphertext to decrypt
2609  * param[out] plaintext Output plaintext
2610  * param size Size of input and output data in bytes. Must be multiple of 8 bytes.
2611  * param key1 First input key for key bundle
2612  * param key2 Second input key for key bundle
2613  * param key3 Third input key for key bundle
2614  * return Status from encrypt/decrypt operation
2615  */
LTC_DES3_DecryptEcb(LTC_Type * base,const uint8_t * ciphertext,uint8_t * plaintext,uint32_t size,const uint8_t key1[LTC_DES_KEY_SIZE],const uint8_t key2[LTC_DES_KEY_SIZE],const uint8_t key3[LTC_DES_KEY_SIZE])2616 status_t LTC_DES3_DecryptEcb(LTC_Type *base,
2617                              const uint8_t *ciphertext,
2618                              uint8_t *plaintext,
2619                              uint32_t size,
2620                              const uint8_t key1[LTC_DES_KEY_SIZE],
2621                              const uint8_t key2[LTC_DES_KEY_SIZE],
2622                              const uint8_t key3[LTC_DES_KEY_SIZE])
2623 {
2624     return ltc_3des_process(base, ciphertext, plaintext, size, NULL, key1, key2, key3, kLTC_ModeECB, kLTC_ModeDecrypt);
2625 }
2626 
2627 /*!
2628  * brief Encrypts triple DES using CBC block mode with two keys.
2629  *
2630  * Encrypts triple DES using CBC block mode with two keys.
2631  *
2632  * param base LTC peripheral base address
2633  * param plaintext Input plaintext to encrypt
2634  * param[out] ciphertext Output ciphertext
2635  * param size Size of input and output data in bytes
2636  * param iv Input initial vector to combine with the first plaintext block.
2637  *           The iv does not need to be secret, but it must be unpredictable.
2638  * param key1 First input key for key bundle
2639  * param key2 Second input key for key bundle
2640  * return Status from encrypt/decrypt operation
2641  */
LTC_DES2_EncryptCbc(LTC_Type * base,const uint8_t * plaintext,uint8_t * ciphertext,uint32_t size,const uint8_t iv[LTC_DES_IV_SIZE],const uint8_t key1[LTC_DES_KEY_SIZE],const uint8_t key2[LTC_DES_KEY_SIZE])2642 status_t LTC_DES2_EncryptCbc(LTC_Type *base,
2643                              const uint8_t *plaintext,
2644                              uint8_t *ciphertext,
2645                              uint32_t size,
2646                              const uint8_t iv[LTC_DES_IV_SIZE],
2647                              const uint8_t key1[LTC_DES_KEY_SIZE],
2648                              const uint8_t key2[LTC_DES_KEY_SIZE])
2649 {
2650     return ltc_3des_process(base, plaintext, ciphertext, size, iv, key1, key2, NULL, kLTC_ModeCBC, kLTC_ModeEncrypt);
2651 }
2652 
2653 /*!
2654  * brief Encrypts triple DES using CBC block mode with three keys.
2655  *
2656  * Encrypts triple DES using CBC block mode with three keys.
2657  *
2658  * param base LTC peripheral base address
2659  * param plaintext Input plaintext to encrypt
2660  * param[out] ciphertext Output ciphertext
2661  * param size Size of input data in bytes
2662  * param iv Input initial vector to combine with the first plaintext block.
2663  *           The iv does not need to be secret, but it must be unpredictable.
2664  * param key1 First input key for key bundle
2665  * param key2 Second input key for key bundle
2666  * param key3 Third input key for key bundle
2667  * return Status from encrypt/decrypt operation
2668  */
LTC_DES3_EncryptCbc(LTC_Type * base,const uint8_t * plaintext,uint8_t * ciphertext,uint32_t size,const uint8_t iv[LTC_DES_IV_SIZE],const uint8_t key1[LTC_DES_KEY_SIZE],const uint8_t key2[LTC_DES_KEY_SIZE],const uint8_t key3[LTC_DES_KEY_SIZE])2669 status_t LTC_DES3_EncryptCbc(LTC_Type *base,
2670                              const uint8_t *plaintext,
2671                              uint8_t *ciphertext,
2672                              uint32_t size,
2673                              const uint8_t iv[LTC_DES_IV_SIZE],
2674                              const uint8_t key1[LTC_DES_KEY_SIZE],
2675                              const uint8_t key2[LTC_DES_KEY_SIZE],
2676                              const uint8_t key3[LTC_DES_KEY_SIZE])
2677 {
2678     return ltc_3des_process(base, plaintext, ciphertext, size, iv, key1, key2, key3, kLTC_ModeCBC, kLTC_ModeEncrypt);
2679 }
2680 
2681 /*!
2682  * brief Decrypts triple DES using CBC block mode with two keys.
2683  *
2684  * Decrypts triple DES using CBC block mode with two keys.
2685  *
2686  * param base LTC peripheral base address
2687  * param ciphertext Input ciphertext to decrypt
2688  * param[out] plaintext Output plaintext
2689  * param size Size of input and output data in bytes
2690  * param iv Input initial vector to combine with the first plaintext block.
2691  *           The iv does not need to be secret, but it must be unpredictable.
2692  * param key1 First input key for key bundle
2693  * param key2 Second input key for key bundle
2694  * return Status from encrypt/decrypt operation
2695  */
LTC_DES2_DecryptCbc(LTC_Type * base,const uint8_t * ciphertext,uint8_t * plaintext,uint32_t size,const uint8_t iv[LTC_DES_IV_SIZE],const uint8_t key1[LTC_DES_KEY_SIZE],const uint8_t key2[LTC_DES_KEY_SIZE])2696 status_t LTC_DES2_DecryptCbc(LTC_Type *base,
2697                              const uint8_t *ciphertext,
2698                              uint8_t *plaintext,
2699                              uint32_t size,
2700                              const uint8_t iv[LTC_DES_IV_SIZE],
2701                              const uint8_t key1[LTC_DES_KEY_SIZE],
2702                              const uint8_t key2[LTC_DES_KEY_SIZE])
2703 {
2704     return ltc_3des_process(base, ciphertext, plaintext, size, iv, key1, key2, NULL, kLTC_ModeCBC, kLTC_ModeDecrypt);
2705 }
2706 
2707 /*!
2708  * brief Decrypts triple DES using CBC block mode with three keys.
2709  *
2710  * Decrypts triple DES using CBC block mode with three keys.
2711  *
2712  * param base LTC peripheral base address
2713  * param ciphertext Input ciphertext to decrypt
2714  * param[out] plaintext Output plaintext
2715  * param size Size of input and output data in bytes
2716  * param iv Input initial vector to combine with the first plaintext block.
2717  *           The iv does not need to be secret, but it must be unpredictable.
2718  * param key1 First input key for key bundle
2719  * param key2 Second input key for key bundle
2720  * param key3 Third input key for key bundle
2721  * return Status from encrypt/decrypt operation
2722  */
LTC_DES3_DecryptCbc(LTC_Type * base,const uint8_t * ciphertext,uint8_t * plaintext,uint32_t size,const uint8_t iv[LTC_DES_IV_SIZE],const uint8_t key1[LTC_DES_KEY_SIZE],const uint8_t key2[LTC_DES_KEY_SIZE],const uint8_t key3[LTC_DES_KEY_SIZE])2723 status_t LTC_DES3_DecryptCbc(LTC_Type *base,
2724                              const uint8_t *ciphertext,
2725                              uint8_t *plaintext,
2726                              uint32_t size,
2727                              const uint8_t iv[LTC_DES_IV_SIZE],
2728                              const uint8_t key1[LTC_DES_KEY_SIZE],
2729                              const uint8_t key2[LTC_DES_KEY_SIZE],
2730                              const uint8_t key3[LTC_DES_KEY_SIZE])
2731 {
2732     return ltc_3des_process(base, ciphertext, plaintext, size, iv, key1, key2, key3, kLTC_ModeCBC, kLTC_ModeDecrypt);
2733 }
2734 
2735 /*!
2736  * brief Encrypts triple DES using CFB block mode with two keys.
2737  *
2738  * Encrypts triple DES using CFB block mode with two keys.
2739  *
2740  * param base LTC peripheral base address
2741  * param plaintext Input plaintext to encrypt
2742  * param[out] ciphertext Output ciphertext
2743  * param size Size of input and output data in bytes
2744  * param iv Input initial block.
2745  * param key1 First input key for key bundle
2746  * param key2 Second input key for key bundle
2747  * return Status from encrypt/decrypt operation
2748  */
LTC_DES2_EncryptCfb(LTC_Type * base,const uint8_t * plaintext,uint8_t * ciphertext,uint32_t size,const uint8_t iv[LTC_DES_IV_SIZE],const uint8_t key1[LTC_DES_KEY_SIZE],const uint8_t key2[LTC_DES_KEY_SIZE])2749 status_t LTC_DES2_EncryptCfb(LTC_Type *base,
2750                              const uint8_t *plaintext,
2751                              uint8_t *ciphertext,
2752                              uint32_t size,
2753                              const uint8_t iv[LTC_DES_IV_SIZE],
2754                              const uint8_t key1[LTC_DES_KEY_SIZE],
2755                              const uint8_t key2[LTC_DES_KEY_SIZE])
2756 {
2757     return ltc_3des_process(base, plaintext, ciphertext, size, iv, key1, key2, NULL, kLTC_ModeCFB, kLTC_ModeEncrypt);
2758 }
2759 
2760 /*!
2761  * brief Encrypts triple DES using CFB block mode with three keys.
2762  *
2763  * Encrypts triple DES using CFB block mode with three keys.
2764  *
2765  * param base LTC peripheral base address
2766  * param plaintext Input plaintext to encrypt
2767  * param[out] ciphertext Output ciphertext
2768  * param size Size of input and ouput data in bytes
2769  * param iv Input initial block.
2770  * param key1 First input key for key bundle
2771  * param key2 Second input key for key bundle
2772  * param key3 Third input key for key bundle
2773  * return Status from encrypt/decrypt operation
2774  */
LTC_DES3_EncryptCfb(LTC_Type * base,const uint8_t * plaintext,uint8_t * ciphertext,uint32_t size,const uint8_t iv[LTC_DES_IV_SIZE],const uint8_t key1[LTC_DES_KEY_SIZE],const uint8_t key2[LTC_DES_KEY_SIZE],const uint8_t key3[LTC_DES_KEY_SIZE])2775 status_t LTC_DES3_EncryptCfb(LTC_Type *base,
2776                              const uint8_t *plaintext,
2777                              uint8_t *ciphertext,
2778                              uint32_t size,
2779                              const uint8_t iv[LTC_DES_IV_SIZE],
2780                              const uint8_t key1[LTC_DES_KEY_SIZE],
2781                              const uint8_t key2[LTC_DES_KEY_SIZE],
2782                              const uint8_t key3[LTC_DES_KEY_SIZE])
2783 {
2784     return ltc_3des_process(base, plaintext, ciphertext, size, iv, key1, key2, key3, kLTC_ModeCFB, kLTC_ModeEncrypt);
2785 }
2786 
2787 /*!
2788  * brief Decrypts triple DES using CFB block mode with two keys.
2789  *
2790  * Decrypts triple DES using CFB block mode with two keys.
2791  *
2792  * param base LTC peripheral base address
2793  * param ciphertext Input ciphertext to decrypt
2794  * param[out] plaintext Output plaintext
2795  * param size Size of input and output data in bytes
2796  * param iv Input initial block.
2797  * param key1 First input key for key bundle
2798  * param key2 Second input key for key bundle
2799  * return Status from encrypt/decrypt operation
2800  */
LTC_DES2_DecryptCfb(LTC_Type * base,const uint8_t * ciphertext,uint8_t * plaintext,uint32_t size,const uint8_t iv[LTC_DES_IV_SIZE],const uint8_t key1[LTC_DES_KEY_SIZE],const uint8_t key2[LTC_DES_KEY_SIZE])2801 status_t LTC_DES2_DecryptCfb(LTC_Type *base,
2802                              const uint8_t *ciphertext,
2803                              uint8_t *plaintext,
2804                              uint32_t size,
2805                              const uint8_t iv[LTC_DES_IV_SIZE],
2806                              const uint8_t key1[LTC_DES_KEY_SIZE],
2807                              const uint8_t key2[LTC_DES_KEY_SIZE])
2808 {
2809     return ltc_3des_process(base, ciphertext, plaintext, size, iv, key1, key2, NULL, kLTC_ModeCFB, kLTC_ModeDecrypt);
2810 }
2811 
2812 /*!
2813  * brief Decrypts triple DES using CFB block mode with three keys.
2814  *
2815  * Decrypts triple DES using CFB block mode with three keys.
2816  *
2817  * param base LTC peripheral base address
2818  * param ciphertext Input ciphertext to decrypt
2819  * param[out] plaintext Output plaintext
2820  * param size Size of input data in bytes
2821  * param iv Input initial block.
2822  * param key1 First input key for key bundle
2823  * param key2 Second input key for key bundle
2824  * param key3 Third input key for key bundle
2825  * return Status from encrypt/decrypt operation
2826  */
LTC_DES3_DecryptCfb(LTC_Type * base,const uint8_t * ciphertext,uint8_t * plaintext,uint32_t size,const uint8_t iv[LTC_DES_IV_SIZE],const uint8_t key1[LTC_DES_KEY_SIZE],const uint8_t key2[LTC_DES_KEY_SIZE],const uint8_t key3[LTC_DES_KEY_SIZE])2827 status_t LTC_DES3_DecryptCfb(LTC_Type *base,
2828                              const uint8_t *ciphertext,
2829                              uint8_t *plaintext,
2830                              uint32_t size,
2831                              const uint8_t iv[LTC_DES_IV_SIZE],
2832                              const uint8_t key1[LTC_DES_KEY_SIZE],
2833                              const uint8_t key2[LTC_DES_KEY_SIZE],
2834                              const uint8_t key3[LTC_DES_KEY_SIZE])
2835 {
2836     return ltc_3des_process(base, ciphertext, plaintext, size, iv, key1, key2, key3, kLTC_ModeCFB, kLTC_ModeDecrypt);
2837 }
2838 
2839 /*!
2840  * brief Encrypts triple DES using OFB block mode with two keys.
2841  *
2842  * Encrypts triple DES using OFB block mode with two keys.
2843  *
2844  * param base LTC peripheral base address
2845  * param plaintext Input plaintext to encrypt
2846  * param[out] ciphertext Output ciphertext
2847  * param size Size of input and output data in bytes
2848  * param iv Input unique input vector. The OFB mode requires that the IV be unique
2849  *           for each execution of the mode under the given key.
2850  * param key1 First input key for key bundle
2851  * param key2 Second input key for key bundle
2852  * return Status from encrypt/decrypt operation
2853  */
LTC_DES2_EncryptOfb(LTC_Type * base,const uint8_t * plaintext,uint8_t * ciphertext,uint32_t size,const uint8_t iv[LTC_DES_IV_SIZE],const uint8_t key1[LTC_DES_KEY_SIZE],const uint8_t key2[LTC_DES_KEY_SIZE])2854 status_t LTC_DES2_EncryptOfb(LTC_Type *base,
2855                              const uint8_t *plaintext,
2856                              uint8_t *ciphertext,
2857                              uint32_t size,
2858                              const uint8_t iv[LTC_DES_IV_SIZE],
2859                              const uint8_t key1[LTC_DES_KEY_SIZE],
2860                              const uint8_t key2[LTC_DES_KEY_SIZE])
2861 {
2862     return ltc_3des_process(base, plaintext, ciphertext, size, iv, key1, key2, NULL, kLTC_ModeOFB, kLTC_ModeEncrypt);
2863 }
2864 
2865 /*!
2866  * brief Encrypts triple DES using OFB block mode with three keys.
2867  *
2868  * Encrypts triple DES using OFB block mode with three keys.
2869  *
2870  * param base LTC peripheral base address
2871  * param plaintext Input plaintext to encrypt
2872  * param[out] ciphertext Output ciphertext
2873  * param size Size of input and output data in bytes
2874  * param iv Input unique input vector. The OFB mode requires that the IV be unique
2875  *           for each execution of the mode under the given key.
2876  * param key1 First input key for key bundle
2877  * param key2 Second input key for key bundle
2878  * param key3 Third input key for key bundle
2879  * return Status from encrypt/decrypt operation
2880  */
LTC_DES3_EncryptOfb(LTC_Type * base,const uint8_t * plaintext,uint8_t * ciphertext,uint32_t size,const uint8_t iv[LTC_DES_IV_SIZE],const uint8_t key1[LTC_DES_KEY_SIZE],const uint8_t key2[LTC_DES_KEY_SIZE],const uint8_t key3[LTC_DES_KEY_SIZE])2881 status_t LTC_DES3_EncryptOfb(LTC_Type *base,
2882                              const uint8_t *plaintext,
2883                              uint8_t *ciphertext,
2884                              uint32_t size,
2885                              const uint8_t iv[LTC_DES_IV_SIZE],
2886                              const uint8_t key1[LTC_DES_KEY_SIZE],
2887                              const uint8_t key2[LTC_DES_KEY_SIZE],
2888                              const uint8_t key3[LTC_DES_KEY_SIZE])
2889 {
2890     return ltc_3des_process(base, plaintext, ciphertext, size, iv, key1, key2, key3, kLTC_ModeOFB, kLTC_ModeEncrypt);
2891 }
2892 
2893 /*!
2894  * brief Decrypts triple DES using OFB block mode with two keys.
2895  *
2896  * Decrypts triple DES using OFB block mode with two keys.
2897  *
2898  * param base LTC peripheral base address
2899  * param ciphertext Input ciphertext to decrypt
2900  * param[out] plaintext Output plaintext
2901  * param size Size of input and output data in bytes
2902  * param iv Input unique input vector. The OFB mode requires that the IV be unique
2903  *           for each execution of the mode under the given key.
2904  * param key1 First input key for key bundle
2905  * param key2 Second input key for key bundle
2906  * return Status from encrypt/decrypt operation
2907  */
LTC_DES2_DecryptOfb(LTC_Type * base,const uint8_t * ciphertext,uint8_t * plaintext,uint32_t size,const uint8_t iv[LTC_DES_IV_SIZE],const uint8_t key1[LTC_DES_KEY_SIZE],const uint8_t key2[LTC_DES_KEY_SIZE])2908 status_t LTC_DES2_DecryptOfb(LTC_Type *base,
2909                              const uint8_t *ciphertext,
2910                              uint8_t *plaintext,
2911                              uint32_t size,
2912                              const uint8_t iv[LTC_DES_IV_SIZE],
2913                              const uint8_t key1[LTC_DES_KEY_SIZE],
2914                              const uint8_t key2[LTC_DES_KEY_SIZE])
2915 {
2916     return ltc_3des_process(base, ciphertext, plaintext, size, iv, key1, key2, NULL, kLTC_ModeOFB, kLTC_ModeDecrypt);
2917 }
2918 
2919 /*!
2920  * brief Decrypts triple DES using OFB block mode with three keys.
2921  *
2922  * Decrypts triple DES using OFB block mode with three keys.
2923  *
2924  * param base LTC peripheral base address
2925  * param ciphertext Input ciphertext to decrypt
2926  * param[out] plaintext Output plaintext
2927  * param size Size of input and output data in bytes
2928  * param iv Input unique input vector. The OFB mode requires that the IV be unique
2929  *           for each execution of the mode under the given key.
2930  * param key1 First input key for key bundle
2931  * param key2 Second input key for key bundle
2932  * param key3 Third input key for key bundle
2933  * return Status from encrypt/decrypt operation
2934  */
LTC_DES3_DecryptOfb(LTC_Type * base,const uint8_t * ciphertext,uint8_t * plaintext,uint32_t size,const uint8_t iv[LTC_DES_IV_SIZE],const uint8_t key1[LTC_DES_KEY_SIZE],const uint8_t key2[LTC_DES_KEY_SIZE],const uint8_t key3[LTC_DES_KEY_SIZE])2935 status_t LTC_DES3_DecryptOfb(LTC_Type *base,
2936                              const uint8_t *ciphertext,
2937                              uint8_t *plaintext,
2938                              uint32_t size,
2939                              const uint8_t iv[LTC_DES_IV_SIZE],
2940                              const uint8_t key1[LTC_DES_KEY_SIZE],
2941                              const uint8_t key2[LTC_DES_KEY_SIZE],
2942                              const uint8_t key3[LTC_DES_KEY_SIZE])
2943 {
2944     return ltc_3des_process(base, ciphertext, plaintext, size, iv, key1, key2, key3, kLTC_ModeOFB, kLTC_ModeDecrypt);
2945 }
2946 #endif /* FSL_FEATURE_LTC_HAS_DES */
2947 
2948 /*******************************************************************************
2949  * HASH Definitions
2950  ******************************************************************************/
2951 #if defined(FSL_FEATURE_LTC_HAS_SHA) && FSL_FEATURE_LTC_HAS_SHA
2952 #define LTC_SHA_BLOCK_SIZE  64                 /*!< SHA-1, SHA-224 & SHA-256 block size  */
2953 #define LTC_HASH_BLOCK_SIZE LTC_SHA_BLOCK_SIZE /*!< LTC hash block size  */
2954 
2955 enum _ltc_sha_digest_len
2956 {
2957     kLTC_RunLenSha1   = 28u,
2958     kLTC_OutLenSha1   = 20u,
2959     kLTC_RunLenSha224 = 40u,
2960     kLTC_OutLenSha224 = 28u,
2961     kLTC_RunLenSha256 = 40u,
2962     kLTC_OutLenSha256 = 32u,
2963 };
2964 #else
2965 #define LTC_HASH_BLOCK_SIZE LTC_AES_BLOCK_SIZE /*!< LTC hash block size  */
2966 #endif                                         /* FSL_FEATURE_LTC_HAS_SHA */
2967 
2968 /*! Internal states of the HASH creation process */
2969 typedef enum _ltc_hash_algo_state
2970 {
2971     kLTC_HashInit = 1u, /*!< Key in the HASH context is the input key. */
2972     kLTC_HashUpdate,    /*!< HASH context has algorithm specific context: MAC, K2 and K3 (XCBC-MAC), MAC and L (CMAC),
2973                            running digest (MDHA). Key in the HASH context is the derived key. */
2974 } ltc_hash_algo_state_t;
2975 
2976 /*! 16/64-byte block represented as byte array or 4/16 32-bit words */
2977 typedef union _ltc_hash_block
2978 {
2979     uint32_t w[LTC_HASH_BLOCK_SIZE / 4]; /*!< array of 32-bit words */
2980     uint8_t b[LTC_HASH_BLOCK_SIZE];      /*!< byte array */
2981 } ltc_hash_block_t;
2982 
2983 /*! Definitions of indexes into hash context array */
2984 typedef enum _ltc_hash_ctx_indexes
2985 {
2986     kLTC_HashCtxKeyStartIdx = 12, /*!< context word array index where key is stored */
2987     kLTC_HashCtxKeySize     = 20, /*!< context word array index where key size is stored */
2988     kLTC_HashCtxNumWords    = 21, /*!< number of context array 32-bit words  */
2989 } ltc_hash_ctx_indexes;
2990 
2991 typedef struct _ltc_hash_ctx_internal
2992 {
2993     ltc_hash_block_t blk; /*!< memory buffer. only full 64/16-byte blocks are written to LTC during hash updates */
2994     uint32_t blksz;       /*!< number of valid bytes in memory buffer */
2995     LTC_Type *base;       /*!< LTC peripheral base address */
2996     ltc_hash_algo_t algo; /*!< selected algorithm from the set of supported algorithms in ltc_drv_hash_algo */
2997     ltc_hash_algo_state_t state;         /*!< finite machine state of the hash software process */
2998     uint32_t word[kLTC_HashCtxNumWords]; /*!< LTC module context that needs to be saved/restored between LTC jobs */
2999 } ltc_hash_ctx_internal_t;
3000 
3001 /*******************************************************************************
3002  * HASH Code static
3003  ******************************************************************************/
ltc_hash_check_input_alg(ltc_hash_algo_t algo)3004 static status_t ltc_hash_check_input_alg(ltc_hash_algo_t algo)
3005 {
3006     if ((algo != kLTC_XcbcMac) && (algo != kLTC_Cmac)
3007 #if defined(FSL_FEATURE_LTC_HAS_SHA) && FSL_FEATURE_LTC_HAS_SHA
3008         && (algo != kLTC_Sha1) && (algo != kLTC_Sha224) && (algo != kLTC_Sha256)
3009 #endif /* FSL_FEATURE_LTC_HAS_SHA */
3010     )
3011     {
3012         return kStatus_InvalidArgument;
3013     }
3014     return kStatus_Success;
3015 }
3016 
ltc_hash_alg_is_cmac(ltc_hash_algo_t algo)3017 static inline bool ltc_hash_alg_is_cmac(ltc_hash_algo_t algo)
3018 {
3019     return ((algo == kLTC_XcbcMac) || (algo == kLTC_Cmac));
3020 }
3021 
3022 #if defined(FSL_FEATURE_LTC_HAS_SHA) && FSL_FEATURE_LTC_HAS_SHA
ltc_hash_alg_is_sha(ltc_hash_algo_t algo)3023 static inline bool ltc_hash_alg_is_sha(ltc_hash_algo_t algo)
3024 {
3025     return ((algo == kLTC_Sha1) || (algo == kLTC_Sha224) || (algo == kLTC_Sha256));
3026 }
3027 #endif /* FSL_FEATURE_LTC_HAS_SHA */
3028 
ltc_hash_check_input_args(LTC_Type * base,ltc_hash_ctx_t * ctx,ltc_hash_algo_t algo,const uint8_t * key,uint32_t keySize)3029 static status_t ltc_hash_check_input_args(
3030     LTC_Type *base, ltc_hash_ctx_t *ctx, ltc_hash_algo_t algo, const uint8_t *key, uint32_t keySize)
3031 {
3032     /* Check validity of input algorithm */
3033     if (kStatus_Success != ltc_hash_check_input_alg(algo))
3034     {
3035         return kStatus_InvalidArgument;
3036     }
3037 
3038     if ((NULL == ctx) || (NULL == base))
3039     {
3040         return kStatus_InvalidArgument;
3041     }
3042 
3043     if (ltc_hash_alg_is_cmac(algo))
3044     {
3045         if ((NULL == key) || (!ltc_check_key_size(keySize)))
3046         {
3047             return kStatus_InvalidArgument;
3048         }
3049     }
3050 
3051     return kStatus_Success;
3052 }
3053 
ltc_hash_check_context(ltc_hash_ctx_internal_t * ctxInternal,const uint8_t * data)3054 static status_t ltc_hash_check_context(ltc_hash_ctx_internal_t *ctxInternal, const uint8_t *data)
3055 {
3056     if ((NULL == data) || (NULL == ctxInternal) || (NULL == ctxInternal->base) ||
3057         (kStatus_Success != ltc_hash_check_input_alg(ctxInternal->algo)))
3058     {
3059         return kStatus_InvalidArgument;
3060     }
3061     return kStatus_Success;
3062 }
3063 
ltc_hash_algo2mode(ltc_hash_algo_t algo,ltc_mode_algorithm_state_t asMode,uint32_t * algOutSize)3064 static uint32_t ltc_hash_algo2mode(ltc_hash_algo_t algo, ltc_mode_algorithm_state_t asMode, uint32_t *algOutSize)
3065 {
3066     uint32_t modeReg = 0u;
3067     uint32_t outSize = 0u;
3068 
3069     /* Set LTC algorithm */
3070     switch (algo)
3071     {
3072         case kLTC_XcbcMac:
3073             modeReg = (uint32_t)kLTC_AlgorithmAES | (uint32_t)kLTC_ModeXCBCMAC;
3074             outSize = 16u;
3075             break;
3076         case kLTC_Cmac:
3077             modeReg = (uint32_t)kLTC_AlgorithmAES | (uint32_t)kLTC_ModeCMAC;
3078             outSize = 16u;
3079             break;
3080 #if defined(FSL_FEATURE_LTC_HAS_SHA) && FSL_FEATURE_LTC_HAS_SHA
3081         case kLTC_Sha1:
3082             modeReg = (uint32_t)kLTC_AlgorithmSHA1;
3083             outSize = kLTC_OutLenSha1;
3084             break;
3085         case kLTC_Sha224:
3086             modeReg = (uint32_t)kLTC_AlgorithmSHA224;
3087             outSize = kLTC_OutLenSha224;
3088             break;
3089         case kLTC_Sha256:
3090             modeReg = (uint32_t)kLTC_AlgorithmSHA256;
3091             outSize = kLTC_OutLenSha256;
3092             break;
3093 #endif /* FSL_FEATURE_LTC_HAS_SHA */
3094         default:
3095             break;
3096     }
3097 
3098     modeReg |= (uint32_t)asMode;
3099     if (NULL != algOutSize)
3100     {
3101         *algOutSize = outSize;
3102     }
3103 
3104     return modeReg;
3105 }
3106 
ltc_hash_engine_init(ltc_hash_ctx_internal_t * ctx)3107 static void ltc_hash_engine_init(ltc_hash_ctx_internal_t *ctx)
3108 {
3109     uint8_t *key;
3110     uint32_t keySize;
3111     LTC_Type *base;
3112     ltc_mode_symmetric_alg_t algo;
3113 
3114     base = ctx->base;
3115 #if defined(FSL_FEATURE_LTC_HAS_SHA) && FSL_FEATURE_LTC_HAS_SHA
3116     if (ltc_hash_alg_is_cmac(ctx->algo))
3117     {
3118 #endif /* FSL_FEATURE_LTC_HAS_SHA */
3119         /*
3120          *  word[kLtcCmacCtxKeySize] = key_length
3121          *  word[1-8] = key
3122          */
3123         keySize = ctx->word[kLTC_HashCtxKeySize];
3124         key     = (uint8_t *)&ctx->word[kLTC_HashCtxKeyStartIdx];
3125 
3126         /* set LTC mode register to INITIALIZE */
3127         algo = (ctx->algo == kLTC_XcbcMac) ? kLTC_ModeXCBCMAC : kLTC_ModeCMAC;
3128         (void)ltc_symmetric_init(base, key, (uint8_t)keySize, kLTC_AlgorithmAES, algo, kLTC_ModeEncrypt);
3129 #if defined(FSL_FEATURE_LTC_HAS_SHA) && FSL_FEATURE_LTC_HAS_SHA
3130     }
3131     else if (ltc_hash_alg_is_sha(ctx->algo))
3132     {
3133         /* Clear internal register states. */
3134         base->CW = (uint32_t)kLTC_ClearAll;
3135 
3136         /* Set byte swap on for several registers we will be reading and writing
3137          * user data to/from. */
3138         base->CTL |= kLTC_CtrlSwapAll;
3139     }
3140     else
3141     {
3142         /* do nothing in this case */
3143     }
3144 #endif /* FSL_FEATURE_LTC_HAS_SHA */
3145 }
3146 
ltc_hash_save_context(ltc_hash_ctx_internal_t * ctx)3147 static void ltc_hash_save_context(ltc_hash_ctx_internal_t *ctx)
3148 {
3149     uint32_t sz;
3150     LTC_Type *base;
3151 
3152     base = ctx->base;
3153     /* Get context size */
3154     switch (ctx->algo)
3155     {
3156         case kLTC_XcbcMac:
3157             /*
3158              *  word[0-3] = mac
3159              *  word[3-7] = k3
3160              *  word[8-11] = k2
3161              *  word[kLtcCmacCtxKeySize] = keySize
3162              */
3163             sz = 12U * sizeof(uint32_t);
3164             break;
3165         case kLTC_Cmac:
3166             /*
3167              *  word[0-3] = mac
3168              *  word[3-7] = L */
3169             sz = 8u * sizeof(uint32_t);
3170             break;
3171 #if defined(FSL_FEATURE_LTC_HAS_SHA) && FSL_FEATURE_LTC_HAS_SHA
3172         case kLTC_Sha1:
3173             sz = (kLTC_RunLenSha1);
3174             break;
3175         case kLTC_Sha224:
3176             sz = (kLTC_RunLenSha224);
3177             break;
3178         case kLTC_Sha256:
3179             sz = (kLTC_RunLenSha256);
3180             break;
3181 #endif /* FSL_FEATURE_LTC_HAS_SHA */
3182         default:
3183             sz = 0;
3184             break;
3185     }
3186 
3187     (void)ltc_get_context(base, (uint8_t *)&ctx->word[0], (uint8_t)sz, 0);
3188 
3189     if (true == ltc_hash_alg_is_cmac(ctx->algo))
3190     {
3191         /* word[12-19] = key */
3192         ltc_get_key(base, (uint8_t *)&ctx->word[kLTC_HashCtxKeyStartIdx],
3193                     (uint8_t)ctx->word[(uint8_t)kLTC_HashCtxKeySize]);
3194     }
3195 }
3196 
ltc_hash_restore_context(ltc_hash_ctx_internal_t * ctx)3197 static void ltc_hash_restore_context(ltc_hash_ctx_internal_t *ctx)
3198 {
3199     uint32_t sz;
3200     uint32_t keySize;
3201     LTC_Type *base;
3202 
3203     base = ctx->base;
3204     /* Get context size */
3205     switch (ctx->algo)
3206     {
3207         case kLTC_XcbcMac:
3208             /*
3209              *  word[0-3] = mac
3210              *  word[3-7] = k3
3211              *  word[8-11] = k2
3212              *  word[kLtcCmacCtxKeySize] = keySize
3213              */
3214             sz = 12U * sizeof(uint32_t);
3215             break;
3216         case kLTC_Cmac:
3217             /*
3218              *  word[0-3] = mac
3219              *  word[3-7] = L */
3220             sz = 8u * sizeof(uint32_t);
3221             break;
3222 #if defined(FSL_FEATURE_LTC_HAS_SHA) && FSL_FEATURE_LTC_HAS_SHA
3223         case kLTC_Sha1:
3224             sz = (kLTC_RunLenSha1);
3225             break;
3226         case kLTC_Sha224:
3227             sz = (kLTC_RunLenSha224);
3228             break;
3229         case kLTC_Sha256:
3230             sz = (kLTC_RunLenSha256);
3231             break;
3232 #endif /* FSL_FEATURE_LTC_HAS_SHA */
3233         default:
3234             sz = 0;
3235             break;
3236     }
3237 
3238     (void)ltc_set_context(base, (const uint8_t *)&ctx->word[0], (uint8_t)sz, 0);
3239 
3240     if (ltc_hash_alg_is_cmac(ctx->algo))
3241     {
3242         /*
3243          *  word[12-19] = key
3244          *  word[kLtcCmacCtxKeySize] = keySize
3245          */
3246         base->CW = (uint32_t)kLTC_ClearKey; /* clear Key and Key Size registers */
3247 
3248         keySize = ctx->word[kLTC_HashCtxKeySize];
3249         /* Write the key in place. */
3250         ltc_set_key(base, (const uint8_t *)&ctx->word[kLTC_HashCtxKeyStartIdx], (uint8_t)keySize);
3251 
3252         /* Write the key size.  This must be done after writing the key, and this
3253          * action locks the ability to modify the key registers. */
3254         base->KS = keySize;
3255     }
3256 }
3257 
ltc_hash_prepare_context_switch(LTC_Type * base)3258 static void ltc_hash_prepare_context_switch(LTC_Type *base)
3259 {
3260     base->CW  = (uint32_t)kLTC_ClearDataSize | (uint32_t)kLTC_ClearMode;
3261     base->STA = (uint32_t)kLTC_StatusDoneIsr;
3262 }
3263 
ltc_hash_get_block_size(ltc_hash_algo_t algo)3264 static uint32_t ltc_hash_get_block_size(ltc_hash_algo_t algo)
3265 {
3266     if ((algo == kLTC_XcbcMac) || (algo == kLTC_Cmac))
3267     {
3268         return (uint32_t)LTC_AES_BLOCK_SIZE;
3269     }
3270 #if defined(FSL_FEATURE_LTC_HAS_SHA) && FSL_FEATURE_LTC_HAS_SHA
3271     else if ((algo == kLTC_Sha1) || (algo == kLTC_Sha224) || (algo == kLTC_Sha256))
3272     {
3273         return (uint32_t)LTC_SHA_BLOCK_SIZE;
3274     }
3275     else
3276     {
3277         return 0;
3278     }
3279 #else
3280     return 0;
3281 #endif
3282 }
3283 
ltc_hash_block_to_ififo(LTC_Type * base,const ltc_hash_block_t * blk,uint32_t numBytes,uint32_t blockSize)3284 static void ltc_hash_block_to_ififo(LTC_Type *base, const ltc_hash_block_t *blk, uint32_t numBytes, uint32_t blockSize)
3285 {
3286     uint32_t i = 0;
3287     uint32_t words;
3288 
3289     words = numBytes / 4u;
3290     if (0U != (numBytes % 4u))
3291     {
3292         words++;
3293     }
3294 
3295     if (words > blockSize / 4u)
3296     {
3297         words = blockSize / 4u;
3298     }
3299 
3300     while (i < words)
3301     {
3302         if (0U == (base->FIFOSTA & LTC_FIFOSTA_IFF_MASK))
3303         {
3304             /* Copy data to the input FIFO. */
3305             base->IFIFO = blk->w[i++];
3306         }
3307     }
3308 }
3309 
ltc_hash_move_to_ififo(ltc_hash_ctx_internal_t * ctx,const uint8_t * data,uint32_t dataSize,uint32_t blockSize)3310 static void ltc_hash_move_to_ififo(ltc_hash_ctx_internal_t *ctx,
3311                                    const uint8_t *data,
3312                                    uint32_t dataSize,
3313                                    uint32_t blockSize)
3314 {
3315     ltc_hash_block_t blkZero;
3316     uint32_t i;
3317 
3318     for (i = 0; i < ARRAY_SIZE(blkZero.w); i++)
3319     {
3320         blkZero.w[i] = 0;
3321     }
3322 
3323     while (0U != dataSize)
3324     {
3325         if (dataSize >= blockSize)
3326         {
3327             ltc_memcpy(&ctx->blk, data, blockSize);
3328             ltc_hash_block_to_ififo(ctx->base, (const ltc_hash_block_t *)(uint32_t)&ctx->blk, blockSize, blockSize);
3329             dataSize -= blockSize;
3330             data = &data[blockSize];
3331         }
3332         else
3333         {
3334             /* last incomplete 16/64-bytes block of this message chunk */
3335             ltc_memcpy(&ctx->blk, &blkZero, sizeof(ctx->blk));
3336             ltc_memcpy(&ctx->blk, data, dataSize);
3337             ctx->blksz = dataSize;
3338             dataSize   = 0;
3339         }
3340     }
3341 }
3342 
ltc_hash_merge_and_flush_buf(ltc_hash_ctx_internal_t * ctx,const uint8_t * input,uint32_t inputSize,ltc_mode_t modeReg,uint32_t blockSize,uint32_t * consumedSize)3343 static status_t ltc_hash_merge_and_flush_buf(ltc_hash_ctx_internal_t *ctx,
3344                                              const uint8_t *input,
3345                                              uint32_t inputSize,
3346                                              ltc_mode_t modeReg,
3347                                              uint32_t blockSize,
3348                                              uint32_t *consumedSize)
3349 {
3350     uint32_t sz;
3351     LTC_Type *base;
3352     status_t status = kStatus_Success;
3353 
3354     base = ctx->base;
3355     sz   = 0;
3356     if (0U != ctx->blksz)
3357     {
3358         sz = blockSize - ctx->blksz;
3359         if (sz > inputSize)
3360         {
3361             sz = inputSize;
3362         }
3363         ltc_memcpy(ctx->blk.b + ctx->blksz, input, sz);
3364         input = &input[sz];
3365         inputSize -= sz;
3366         ctx->blksz += sz;
3367 
3368         if (ctx->blksz == blockSize)
3369         {
3370             base->DS = blockSize;
3371             ltc_hash_block_to_ififo(base, (const ltc_hash_block_t *)(uint32_t)&ctx->blk, blockSize, blockSize);
3372             ctx->blksz = 0;
3373 
3374             status = ltc_wait(base);
3375             if (kStatus_Success != status)
3376             {
3377                 return status;
3378             }
3379 
3380             /* if there is still inputSize left, make sure LTC alg.state is set to UPDATE and continue */
3381             if (0U != inputSize)
3382             {
3383                 /* set algorithm state to UPDATE */
3384                 modeReg &= ~LTC_MD_AS_MASK;
3385                 modeReg |= (uint32_t)kLTC_ModeUpdate;
3386                 base->MD = modeReg;
3387             }
3388         }
3389     }
3390     if (NULL != consumedSize)
3391     {
3392         *consumedSize = sz;
3393     }
3394     return status;
3395 }
3396 
ltc_hash_move_rest_to_context(ltc_hash_ctx_internal_t * ctx,const uint8_t * data,uint32_t dataSize,ltc_mode_t modeReg,uint32_t blockSize)3397 static status_t ltc_hash_move_rest_to_context(
3398     ltc_hash_ctx_internal_t *ctx, const uint8_t *data, uint32_t dataSize, ltc_mode_t modeReg, uint32_t blockSize)
3399 {
3400     status_t status = kStatus_Success;
3401     ltc_hash_block_t blkZero;
3402     uint32_t i;
3403 
3404     /* make blkZero clear */
3405     for (i = 0; i < ARRAY_SIZE(blkZero.w); i++)
3406     {
3407         blkZero.w[i] = 0;
3408     }
3409 
3410     while (0U != dataSize)
3411     {
3412         if (dataSize > blockSize)
3413         {
3414             dataSize -= blockSize;
3415             data = &data[blockSize];
3416         }
3417         else
3418         {
3419             if (dataSize + ctx->blksz > blockSize)
3420             {
3421                 uint32_t sz = 0;
3422                 status      = ltc_hash_merge_and_flush_buf(ctx, data, dataSize, modeReg, blockSize, &sz);
3423                 if (kStatus_Success != status)
3424                 {
3425                     return status;
3426                 }
3427                 data = &data[sz];
3428                 dataSize -= sz;
3429             }
3430             /* last incomplete 16/64-bytes block of this message chunk */
3431             ltc_memcpy(&ctx->blk, &blkZero, blockSize);
3432             ltc_memcpy(&ctx->blk, data, dataSize);
3433             ctx->blksz = dataSize;
3434             dataSize   = 0;
3435         }
3436     }
3437     return status;
3438 }
3439 
ltc_hash_process_input_data(ltc_hash_ctx_internal_t * ctx,const uint8_t * input,uint32_t inputSize,ltc_mode_t modeReg)3440 static status_t ltc_hash_process_input_data(ltc_hash_ctx_internal_t *ctx,
3441                                             const uint8_t *input,
3442                                             uint32_t inputSize,
3443                                             ltc_mode_t modeReg)
3444 {
3445     uint32_t sz = 0;
3446     LTC_Type *base;
3447     uint32_t blockSize = 0;
3448     status_t status    = kStatus_Success;
3449 
3450     blockSize = ltc_hash_get_block_size(ctx->algo);
3451     if (blockSize == 0u)
3452     {
3453         return kStatus_Fail;
3454     }
3455     base = ctx->base;
3456 
3457     /* fill context struct blk and flush to LTC ififo in case it is full block */
3458     status = ltc_hash_merge_and_flush_buf(ctx, input, inputSize, modeReg, blockSize, &sz);
3459     if (kStatus_Success != status)
3460     {
3461         return status;
3462     }
3463     input = &input[sz];
3464     inputSize -= sz;
3465 
3466     /* if there is still more than or equal to 64 bytes, move each 64 bytes through LTC */
3467     sz = LTC_DS_DS_MASK + 1u - LTC_HASH_BLOCK_SIZE;
3468     while (0U != inputSize)
3469     {
3470         if (inputSize < sz)
3471         {
3472             uint32_t lastSize;
3473 
3474             lastSize = inputSize % blockSize;
3475             if (lastSize == 0u)
3476             {
3477                 lastSize = blockSize;
3478             }
3479             inputSize -= lastSize;
3480             if (0U != inputSize)
3481             {
3482                 /* move all complete blocks to ififo. */
3483                 base->DS = inputSize;
3484                 ltc_hash_move_to_ififo(ctx, input, inputSize, blockSize);
3485 
3486                 status = ltc_wait(base);
3487                 if (kStatus_Success != status)
3488                 {
3489                     return status;
3490                 }
3491 
3492                 input = &input[inputSize];
3493             }
3494             /* keep last (in)complete 16-bytes block in context struct. */
3495             /* when 3rd argument of cmac_move_to_ififo() is <= 16 bytes, it only stores the data to context struct */
3496             status = ltc_hash_move_rest_to_context(ctx, input, lastSize, modeReg, blockSize);
3497             if (kStatus_Success != status)
3498             {
3499                 return status;
3500             }
3501             inputSize = 0;
3502         }
3503         else
3504         {
3505             base->DS = sz;
3506             ltc_hash_move_to_ififo(ctx, input, sz, blockSize);
3507             inputSize -= sz;
3508             input = &input[sz];
3509 
3510             status = ltc_wait(base);
3511             if (kStatus_Success != status)
3512             {
3513                 return status;
3514             }
3515 
3516             /* set algorithm state to UPDATE */
3517             modeReg &= ~LTC_MD_AS_MASK;
3518             modeReg |= (uint32_t)kLTC_ModeUpdate;
3519             base->MD = modeReg;
3520         }
3521     } /* end while */
3522 
3523     return status;
3524 }
3525 
3526 /*******************************************************************************
3527  * HASH Code public
3528  ******************************************************************************/
3529 /*!
3530  * brief Initialize HASH context
3531  *
3532  * This function initialize the HASH.
3533  * Key shall be supplied if the underlaying algoritm is AES XCBC-MAC or CMAC.
3534  * Key shall be NULL if the underlaying algoritm is SHA.
3535  *
3536  * For XCBC-MAC, the key length must be 16. For CMAC, the key length can be
3537  * the AES key lengths supported by AES engine. For MDHA the key length argument
3538  * is ignored.
3539  *
3540  * param base LTC peripheral base address
3541  * param[out] ctx Output hash context
3542  * param algo Underlaying algorithm to use for hash computation.
3543  * param key Input key (NULL if underlaying algorithm is SHA)
3544  * param keySize Size of input key in bytes
3545  * return Status of initialization
3546  */
LTC_HASH_Init(LTC_Type * base,ltc_hash_ctx_t * ctx,ltc_hash_algo_t algo,const uint8_t * key,uint32_t keySize)3547 status_t LTC_HASH_Init(LTC_Type *base, ltc_hash_ctx_t *ctx, ltc_hash_algo_t algo, const uint8_t *key, uint32_t keySize)
3548 {
3549     status_t ret;
3550     ltc_hash_ctx_internal_t *ctxInternal;
3551     uint32_t i;
3552 
3553     ret = ltc_hash_check_input_args(base, ctx, algo, key, keySize);
3554     if (ret != kStatus_Success)
3555     {
3556         return ret;
3557     }
3558 
3559     /* set algorithm in context struct for later use */
3560     ctxInternal       = (ltc_hash_ctx_internal_t *)(uint32_t)ctx;
3561     ctxInternal->algo = algo;
3562     for (i = 0; i < (uint32_t)kLTC_HashCtxNumWords; i++)
3563     {
3564         ctxInternal->word[i] = 0u;
3565     }
3566 
3567     /* Steps required only using AES engine */
3568     if (ltc_hash_alg_is_cmac(algo))
3569     {
3570         /* store input key and key length in context struct for later use */
3571         ctxInternal->word[kLTC_HashCtxKeySize] = keySize;
3572         ltc_memcpy(&ctxInternal->word[kLTC_HashCtxKeyStartIdx], key, keySize);
3573     }
3574     ctxInternal->blksz = 0u;
3575     uint32_t j;
3576     j = sizeof(ctxInternal->blk.w) / sizeof(ctxInternal->blk.w[0]);
3577     for (i = 0; i < j; i++)
3578     {
3579         ctxInternal->blk.w[0] = 0u;
3580     }
3581     ctxInternal->state = kLTC_HashInit;
3582     ctxInternal->base  = base;
3583 
3584     return kStatus_Success;
3585 }
3586 
3587 /*!
3588  * brief Add data to current HASH
3589  *
3590  * Add data to current HASH. This can be called repeatedly with an arbitrary amount of data to be
3591  * hashed.
3592  *
3593  * param[in,out] ctx HASH context
3594  * param input Input data
3595  * param inputSize Size of input data in bytes
3596  * return Status of the hash update operation
3597  */
LTC_HASH_Update(ltc_hash_ctx_t * ctx,const uint8_t * input,uint32_t inputSize)3598 status_t LTC_HASH_Update(ltc_hash_ctx_t *ctx, const uint8_t *input, uint32_t inputSize)
3599 {
3600     bool isUpdateState;
3601     ltc_mode_t modeReg = 0; /* read and write LTC mode register */
3602     LTC_Type *base;
3603     status_t status;
3604     ltc_hash_ctx_internal_t *ctxInternal;
3605     uint32_t blockSize;
3606 
3607     ctxInternal = (ltc_hash_ctx_internal_t *)(uint32_t)ctx;
3608     status      = ltc_hash_check_context(ctxInternal, input);
3609     if (kStatus_Success != status)
3610     {
3611         return status;
3612     }
3613 
3614     base      = ctxInternal->base;
3615     blockSize = ltc_hash_get_block_size(ctxInternal->algo);
3616     /* if we are still less than 64 bytes, keep only in context */
3617     if ((ctxInternal->blksz + inputSize) <= blockSize)
3618     {
3619         ltc_memcpy((&ctxInternal->blk.b[0]) + ctxInternal->blksz, input, inputSize);
3620         ctxInternal->blksz += inputSize;
3621         return status;
3622     }
3623     else
3624     {
3625         isUpdateState = ctxInternal->state == kLTC_HashUpdate;
3626         if (ctxInternal->state == kLTC_HashInit)
3627         {
3628             /* set LTC mode register to INITIALIZE job */
3629             ltc_hash_engine_init(ctxInternal);
3630 
3631 #if defined(FSL_FEATURE_LTC_HAS_SHA) && FSL_FEATURE_LTC_HAS_SHA
3632             if (ltc_hash_alg_is_cmac(ctxInternal->algo))
3633             {
3634 #endif /* FSL_FEATURE_LTC_HAS_SHA */
3635                 ctxInternal->state = kLTC_HashUpdate;
3636                 isUpdateState      = true;
3637                 base->DS           = 0u;
3638                 status             = ltc_wait(base);
3639 #if defined(FSL_FEATURE_LTC_HAS_SHA) && FSL_FEATURE_LTC_HAS_SHA
3640             }
3641             else
3642             {
3643                 /* Set the proper block and algorithm mode. */
3644                 modeReg  = ltc_hash_algo2mode(ctxInternal->algo, kLTC_ModeInit, NULL);
3645                 base->MD = modeReg;
3646 
3647                 ctxInternal->state = kLTC_HashUpdate;
3648                 status             = ltc_hash_process_input_data(ctxInternal, input, inputSize, modeReg);
3649                 ltc_hash_save_context(ctxInternal);
3650             }
3651 #endif /* FSL_FEATURE_LTC_HAS_SHA */
3652         }
3653         else if (isUpdateState)
3654         {
3655             /* restore LTC context from context struct */
3656             ltc_hash_restore_context(ctxInternal);
3657         }
3658         else
3659         {
3660             /* nothing special at this place */
3661         }
3662     }
3663 
3664     if (kStatus_Success != status)
3665     {
3666         return status;
3667     }
3668 
3669     if (isUpdateState)
3670     {
3671         /* set LTC mode register to UPDATE job */
3672         ltc_hash_prepare_context_switch(base);
3673         base->CW = (uint32_t)kLTC_ClearDataSize;
3674         modeReg  = ltc_hash_algo2mode(ctxInternal->algo, kLTC_ModeUpdate, NULL);
3675         base->MD = modeReg;
3676 
3677         /* process input data and save LTC context to context structure */
3678         status = ltc_hash_process_input_data(ctxInternal, input, inputSize, modeReg);
3679         ltc_hash_save_context(ctxInternal);
3680     }
3681     ltc_clear_all(base, false);
3682     return status;
3683 }
3684 
3685 /*!
3686  * brief Finalize hashing
3687  *
3688  * Outputs the final hash and erases the context.
3689  *
3690  * param[in,out] ctx Input hash context
3691  * param[out] output Output hash data
3692  * param[out] outputSize Output parameter storing the size of the output hash in bytes
3693  * return Status of the hash finish operation
3694  */
LTC_HASH_Finish(ltc_hash_ctx_t * ctx,uint8_t * output,uint32_t * outputSize)3695 status_t LTC_HASH_Finish(ltc_hash_ctx_t *ctx, uint8_t *output, uint32_t *outputSize)
3696 {
3697     ltc_mode_t modeReg; /* read and write LTC mode register */
3698     LTC_Type *base;
3699     uint32_t algOutSize = 0;
3700     status_t status;
3701     ltc_hash_ctx_internal_t *ctxInternal;
3702     uint32_t *ctxW;
3703     uint32_t i;
3704 
3705     ctxInternal = (ltc_hash_ctx_internal_t *)(uint32_t)ctx;
3706     status      = ltc_hash_check_context(ctxInternal, output);
3707     if (kStatus_Success != status)
3708     {
3709         return status;
3710     }
3711 
3712     base = ctxInternal->base;
3713     ltc_hash_prepare_context_switch(base);
3714 
3715     base->CW = (uint32_t)kLTC_ClearDataSize;
3716     if (ctxInternal->state == kLTC_HashInit)
3717     {
3718         ltc_hash_engine_init(ctxInternal);
3719 #if defined(FSL_FEATURE_LTC_HAS_SHA) && FSL_FEATURE_LTC_HAS_SHA
3720         if (ltc_hash_alg_is_cmac(ctxInternal->algo))
3721         {
3722 #endif /* FSL_FEATURE_LTC_HAS_SHA */
3723             base->DS = 0u;
3724             status   = ltc_wait(base);
3725             if (kStatus_Success != status)
3726             {
3727                 return status;
3728             }
3729             modeReg = ltc_hash_algo2mode(ctxInternal->algo, kLTC_ModeFinalize, &algOutSize);
3730 #if defined(FSL_FEATURE_LTC_HAS_SHA) && FSL_FEATURE_LTC_HAS_SHA
3731         }
3732         else
3733         {
3734             modeReg = ltc_hash_algo2mode(ctxInternal->algo, kLTC_ModeInitFinal, &algOutSize);
3735         }
3736 #endif /* FSL_FEATURE_LTC_HAS_SHA */
3737         base->MD = modeReg;
3738     }
3739     else
3740     {
3741         modeReg  = ltc_hash_algo2mode(ctxInternal->algo, kLTC_ModeFinalize, &algOutSize);
3742         base->MD = modeReg;
3743 
3744         /* restore LTC context from context struct */
3745         ltc_hash_restore_context(ctxInternal);
3746     }
3747 
3748     /* flush message last incomplete block, if there is any, or write zero to data size register. */
3749     base->DS = ctxInternal->blksz;
3750     ltc_hash_block_to_ififo(base, (const ltc_hash_block_t *)(uint32_t)&ctxInternal->blk, ctxInternal->blksz,
3751                             ltc_hash_get_block_size(ctxInternal->algo));
3752     /* Wait for finish of the encryption */
3753     status = ltc_wait(base);
3754 
3755     if (NULL != outputSize)
3756     {
3757         if (algOutSize < *outputSize)
3758         {
3759             *outputSize = algOutSize;
3760         }
3761         else
3762         {
3763             algOutSize = *outputSize;
3764         }
3765     }
3766 
3767     (void)ltc_get_context(base, &output[0], (uint8_t)algOutSize, 0u);
3768 
3769     ctxW = (uint32_t *)(uint32_t)ctx;
3770     for (i = 0; i < (uint32_t)LTC_HASH_CTX_SIZE; i++)
3771     {
3772         ctxW[i] = 0u;
3773     }
3774 
3775     ltc_clear_all(base, false);
3776     return status;
3777 }
3778 
3779 /*!
3780  * brief Create HASH on given data
3781  *
3782  * Perform the full keyed HASH in one function call.
3783  *
3784  * param base LTC peripheral base address
3785  * param algo Block cipher algorithm to use for CMAC creation
3786  * param input Input data
3787  * param inputSize Size of input data in bytes
3788  * param key Input key
3789  * param keySize Size of input key in bytes
3790  * param[out] output Output hash data
3791  * param[out] outputSize Output parameter storing the size of the output hash in bytes
3792  * return Status of the one call hash operation.
3793  */
LTC_HASH(LTC_Type * base,ltc_hash_algo_t algo,const uint8_t * input,uint32_t inputSize,const uint8_t * key,uint32_t keySize,uint8_t * output,uint32_t * outputSize)3794 status_t LTC_HASH(LTC_Type *base,
3795                   ltc_hash_algo_t algo,
3796                   const uint8_t *input,
3797                   uint32_t inputSize,
3798                   const uint8_t *key,
3799                   uint32_t keySize,
3800                   uint8_t *output,
3801                   uint32_t *outputSize)
3802 {
3803     status_t status;
3804     ltc_hash_ctx_t ctx;
3805 
3806     status = LTC_HASH_Init(base, &ctx, algo, key, keySize);
3807     if (status != kStatus_Success)
3808     {
3809         return status;
3810     }
3811     status = LTC_HASH_Update(&ctx, input, inputSize);
3812     if (status != kStatus_Success)
3813     {
3814         return status;
3815     }
3816     status = LTC_HASH_Finish(&ctx, output, outputSize);
3817     return status;
3818 }
3819 
3820 /*******************************************************************************
3821  * PKHA Code static
3822  ******************************************************************************/
3823 #if defined(FSL_FEATURE_LTC_HAS_PKHA) && FSL_FEATURE_LTC_HAS_PKHA
ltc_pkha_clear_regabne(LTC_Type * base,bool A,bool B,bool N,bool E)3824 static status_t ltc_pkha_clear_regabne(LTC_Type *base, bool A, bool B, bool N, bool E)
3825 {
3826     ltc_mode_t mode;
3827 
3828     /* Set the PKHA algorithm and the appropriate function. */
3829     mode = (uint32_t)kLTC_AlgorithmPKHA | 1U;
3830 
3831     /* Set ram area to clear. Clear all. */
3832     if (A)
3833     {
3834         mode |= ((uint32_t)1U << 19U);
3835     }
3836     if (B)
3837     {
3838         mode |= ((uint32_t)1U << 18U);
3839     }
3840     if (N)
3841     {
3842         mode |= ((uint32_t)1U << 16U);
3843     }
3844     if (E)
3845     {
3846         mode |= ((uint32_t)1U << 17U);
3847     }
3848 
3849     /* Write the mode register to the hardware.
3850      * NOTE: This will begin the operation. */
3851     base->MDPK = mode;
3852 
3853     /* Wait for 'done' */
3854     return ltc_wait(base);
3855 }
3856 
ltc_pkha_default_parms(ltc_pkha_mode_params_t * params)3857 static void ltc_pkha_default_parms(ltc_pkha_mode_params_t *params)
3858 {
3859     params->func        = (ltc_pkha_func_t)0;
3860     params->arithType   = kLTC_PKHA_IntegerArith;
3861     params->montFormIn  = kLTC_PKHA_NormalValue;
3862     params->montFormOut = kLTC_PKHA_NormalValue;
3863     params->srcReg      = kLTC_PKHA_RegAll;
3864     params->srcQuad     = kLTC_PKHA_Quad0;
3865     params->dstReg      = kLTC_PKHA_RegAll;
3866     params->dstQuad     = kLTC_PKHA_Quad0;
3867     params->equalTime   = kLTC_PKHA_NoTimingEqualized;
3868     params->r2modn      = kLTC_PKHA_CalcR2;
3869 }
3870 
ltc_pkha_write_word(LTC_Type * base,ltc_pkha_reg_area_t reg,uint8_t index,uint32_t data)3871 static void ltc_pkha_write_word(LTC_Type *base, ltc_pkha_reg_area_t reg, uint8_t index, uint32_t data)
3872 {
3873     switch (reg)
3874     {
3875         case kLTC_PKHA_RegA:
3876             base->PKA[index] = data;
3877             break;
3878 
3879         case kLTC_PKHA_RegB:
3880             base->PKB[index] = data;
3881             break;
3882 
3883         case kLTC_PKHA_RegN:
3884             base->PKN[index] = data;
3885             break;
3886 
3887         case kLTC_PKHA_RegE:
3888             base->PKE[index] = data;
3889             break;
3890 
3891         default:
3892             break;
3893     }
3894 }
3895 
ltc_pkha_read_word(LTC_Type * base,ltc_pkha_reg_area_t reg,uint8_t index)3896 static uint32_t ltc_pkha_read_word(LTC_Type *base, ltc_pkha_reg_area_t reg, uint8_t index)
3897 {
3898     uint32_t retval;
3899 
3900     switch (reg)
3901     {
3902         case kLTC_PKHA_RegA:
3903             retval = base->PKA[index];
3904             break;
3905 
3906         case kLTC_PKHA_RegB:
3907             retval = base->PKB[index];
3908             break;
3909 
3910         case kLTC_PKHA_RegN:
3911             retval = base->PKN[index];
3912             break;
3913 
3914         case kLTC_PKHA_RegE:
3915             retval = base->PKE[index];
3916             break;
3917 
3918         default:
3919             retval = 0;
3920             break;
3921     }
3922     return retval;
3923 }
3924 
ltc_pkha_write_reg(LTC_Type * base,ltc_pkha_reg_area_t reg,uint8_t quad,const uint8_t * data,uint16_t dataSize)3925 static status_t ltc_pkha_write_reg(
3926     LTC_Type *base, ltc_pkha_reg_area_t reg, uint8_t quad, const uint8_t *data, uint16_t dataSize)
3927 {
3928     /* Select the word-based start index for each quadrant of 64 bytes. */
3929     uint8_t startIndex = (quad * 16u);
3930     uint32_t outWord;
3931 
3932     while (dataSize > 0U)
3933     {
3934         if (dataSize >= sizeof(uint32_t))
3935         {
3936             ltc_pkha_write_word(base, reg, startIndex++, ltc_get_word_from_unaligned(data));
3937             dataSize -= sizeof(uint32_t);
3938             data += sizeof(uint32_t);
3939         }
3940         else /* (dataSize > 0) && (dataSize < 4) */
3941         {
3942             outWord = 0;
3943             ltc_memcpy(&outWord, data, dataSize);
3944             ltc_pkha_write_word(base, reg, startIndex, outWord);
3945             dataSize = 0;
3946         }
3947     }
3948 
3949     return kStatus_Success;
3950 }
3951 
ltc_pkha_read_reg(LTC_Type * base,ltc_pkha_reg_area_t reg,uint8_t quad,uint8_t * data,uint16_t dataSize)3952 static void ltc_pkha_read_reg(LTC_Type *base, ltc_pkha_reg_area_t reg, uint8_t quad, uint8_t *data, uint16_t dataSize)
3953 {
3954     /* Select the word-based start index for each quadrant of 64 bytes. */
3955     uint8_t startIndex = (quad * 16u);
3956     uint16_t calcSize;
3957     uint32_t word;
3958 
3959     while (dataSize > 0U)
3960     {
3961         word = ltc_pkha_read_word(base, reg, startIndex++);
3962 
3963         calcSize = (dataSize >= sizeof(uint32_t)) ? sizeof(uint32_t) : dataSize;
3964         ltc_memcpy(data, &word, calcSize);
3965 
3966         data += calcSize;
3967         dataSize -= calcSize;
3968     }
3969 }
3970 
ltc_pkha_init_data(LTC_Type * base,const uint8_t * A,uint16_t sizeA,const uint8_t * B,uint16_t sizeB,const uint8_t * N,uint16_t sizeN,const uint8_t * E,uint16_t sizeE)3971 static void ltc_pkha_init_data(LTC_Type *base,
3972                                const uint8_t *A,
3973                                uint16_t sizeA,
3974                                const uint8_t *B,
3975                                uint16_t sizeB,
3976                                const uint8_t *N,
3977                                uint16_t sizeN,
3978                                const uint8_t *E,
3979                                uint16_t sizeE)
3980 {
3981     uint32_t clearMask = (uint32_t)kLTC_ClearMode; /* clear Mode Register */
3982 
3983     /* Clear internal register states. */
3984     if (0U != sizeA)
3985     {
3986         clearMask |= (uint32_t)kLTC_ClearPkhaSizeA;
3987     }
3988     if (0U != sizeB)
3989     {
3990         clearMask |= (uint32_t)kLTC_ClearPkhaSizeB;
3991     }
3992     if (0U != sizeN)
3993     {
3994         clearMask |= (uint32_t)kLTC_ClearPkhaSizeN;
3995     }
3996     if (0U != sizeE)
3997     {
3998         clearMask |= (uint32_t)kLTC_ClearPkhaSizeE;
3999     }
4000 
4001     base->CW  = clearMask;
4002     base->STA = (uint32_t)kLTC_StatusDoneIsr;
4003     (void)ltc_pkha_clear_regabne(base, (bool)(uintptr_t)A, (bool)(uintptr_t)B, (bool)(uintptr_t)N, (bool)(uintptr_t)E);
4004 
4005     /* Write register sizes. */
4006     /* Write modulus (N) and A and B register arguments. */
4007     if (0U != sizeN)
4008     {
4009         base->PKNSZ = sizeN;
4010         if (NULL != N)
4011         {
4012             (void)ltc_pkha_write_reg(base, kLTC_PKHA_RegN, 0, N, sizeN);
4013         }
4014     }
4015 
4016     if (0U != sizeA)
4017     {
4018         base->PKASZ = sizeA;
4019         if (NULL != A)
4020         {
4021             (void)ltc_pkha_write_reg(base, kLTC_PKHA_RegA, 0, A, sizeA);
4022         }
4023     }
4024 
4025     if (0U != sizeB)
4026     {
4027         base->PKBSZ = sizeB;
4028         if (NULL != B)
4029         {
4030             (void)ltc_pkha_write_reg(base, kLTC_PKHA_RegB, 0, B, sizeB);
4031         }
4032     }
4033 
4034     if (0U != sizeE)
4035     {
4036         base->PKESZ = sizeE;
4037         if (NULL != E)
4038         {
4039             (void)ltc_pkha_write_reg(base, kLTC_PKHA_RegE, 0, E, sizeE);
4040         }
4041     }
4042 }
4043 
ltc_pkha_mode_set_src_reg_copy(ltc_mode_t * outMode,ltc_pkha_reg_area_t reg)4044 static void ltc_pkha_mode_set_src_reg_copy(ltc_mode_t *outMode, ltc_pkha_reg_area_t reg)
4045 {
4046     int i = 0;
4047 
4048     do
4049     {
4050         reg = (ltc_pkha_reg_area_t)(uint32_t)(((uint32_t)reg) >> 1u);
4051         i++;
4052     } while (0U != (uint32_t)reg);
4053 
4054     i = 4 - i;
4055     /* Source register must not be E. */
4056     if (i != 2)
4057     {
4058         *outMode |= ((uint32_t)i << 17u);
4059     }
4060 }
4061 
ltc_pkha_mode_set_dst_reg_copy(ltc_mode_t * outMode,ltc_pkha_reg_area_t reg)4062 static void ltc_pkha_mode_set_dst_reg_copy(ltc_mode_t *outMode, ltc_pkha_reg_area_t reg)
4063 {
4064     int i = 0;
4065 
4066     do
4067     {
4068         reg = (ltc_pkha_reg_area_t)(uint32_t)(((uint32_t)reg) >> 1u);
4069         i++;
4070     } while (0U != (uint32_t)reg);
4071 
4072     i = 4 - i;
4073     *outMode |= ((uint32_t)i << 10u);
4074 }
4075 
ltc_pkha_mode_set_src_seg_copy(ltc_mode_t * outMode,const ltc_pkha_quad_area_t quad)4076 static void ltc_pkha_mode_set_src_seg_copy(ltc_mode_t *outMode, const ltc_pkha_quad_area_t quad)
4077 {
4078     *outMode |= ((uint32_t)quad << 8u);
4079 }
4080 
ltc_pkha_mode_set_dst_seg_copy(ltc_mode_t * outMode,const ltc_pkha_quad_area_t quad)4081 static void ltc_pkha_mode_set_dst_seg_copy(ltc_mode_t *outMode, const ltc_pkha_quad_area_t quad)
4082 {
4083     *outMode |= ((uint32_t)quad << 6u);
4084 }
4085 
4086 /*!
4087  * @brief Starts the PKHA operation.
4088  *
4089  * This function starts an operation configured by the params parameter.
4090  *
4091  * @param base LTC peripheral base address
4092  * @param params Configuration structure containing all settings required for PKHA operation.
4093  */
ltc_pkha_init_mode(LTC_Type * base,const ltc_pkha_mode_params_t * params)4094 static status_t ltc_pkha_init_mode(LTC_Type *base, const ltc_pkha_mode_params_t *params)
4095 {
4096     ltc_mode_t modeReg;
4097     status_t retval;
4098 
4099     /* Set the PKHA algorithm and the appropriate function. */
4100     modeReg = (uint32_t)kLTC_AlgorithmPKHA;
4101     modeReg |= (uint32_t)params->func;
4102 
4103     if ((params->func == kLTC_PKHA_CopyMemSizeN) || (params->func == kLTC_PKHA_CopyMemSizeSrc))
4104     {
4105         /* Set source and destination registers and quads. */
4106         ltc_pkha_mode_set_src_reg_copy(&modeReg, params->srcReg);
4107         ltc_pkha_mode_set_dst_reg_copy(&modeReg, params->dstReg);
4108         ltc_pkha_mode_set_src_seg_copy(&modeReg, params->srcQuad);
4109         ltc_pkha_mode_set_dst_seg_copy(&modeReg, params->dstQuad);
4110     }
4111     else
4112     {
4113         /* Set the arithmetic type - integer or binary polynomial (F2m). */
4114         modeReg |= ((uint32_t)params->arithType << 17u);
4115 
4116         /* Set to use Montgomery form of inputs and/or outputs. */
4117         modeReg |= ((uint32_t)params->montFormIn << 19u);
4118         modeReg |= ((uint32_t)params->montFormOut << 18u);
4119 
4120         /* Set to use pre-computed R2modN */
4121         modeReg |= ((uint32_t)params->r2modn << 16u);
4122     }
4123 
4124     modeReg |= ((uint32_t)params->equalTime << 10u);
4125 
4126     /* Write the mode register to the hardware.
4127      * NOTE: This will begin the operation. */
4128     base->MDPK = modeReg;
4129 
4130     retval = ltc_wait(base);
4131     return (retval);
4132 }
4133 
ltc_pkha_modR2(LTC_Type * base,const uint8_t * N,uint16_t sizeN,uint8_t * result,uint16_t * resultSize,ltc_pkha_f2m_t arithType)4134 static status_t ltc_pkha_modR2(
4135     LTC_Type *base, const uint8_t *N, uint16_t sizeN, uint8_t *result, uint16_t *resultSize, ltc_pkha_f2m_t arithType)
4136 {
4137     status_t status;
4138     ltc_pkha_mode_params_t params;
4139 
4140     ltc_pkha_default_parms(&params);
4141     params.func      = kLTC_PKHA_ArithModR2;
4142     params.arithType = arithType;
4143 
4144     ltc_pkha_init_data(base, NULL, 0, NULL, 0, N, sizeN, NULL, 0);
4145     status = ltc_pkha_init_mode(base, &params);
4146 
4147     if (status == kStatus_Success)
4148     {
4149         /* Read the result and size from register B0. */
4150         if ((NULL != resultSize) && (NULL != result))
4151         {
4152             *resultSize = (uint16_t)base->PKBSZ;
4153             /* Read the data from the result register into place. */
4154             ltc_pkha_read_reg(base, kLTC_PKHA_RegB, 0, result, *resultSize);
4155         }
4156     }
4157 
4158     return status;
4159 }
4160 
ltc_pkha_modmul(LTC_Type * base,const uint8_t * A,uint16_t sizeA,const uint8_t * B,uint16_t sizeB,const uint8_t * N,uint16_t sizeN,uint8_t * result,uint16_t * resultSize,ltc_pkha_f2m_t arithType,ltc_pkha_montgomery_form_t montIn,ltc_pkha_montgomery_form_t montOut,ltc_pkha_timing_t equalTime)4161 static status_t ltc_pkha_modmul(LTC_Type *base,
4162                                 const uint8_t *A,
4163                                 uint16_t sizeA,
4164                                 const uint8_t *B,
4165                                 uint16_t sizeB,
4166                                 const uint8_t *N,
4167                                 uint16_t sizeN,
4168                                 uint8_t *result,
4169                                 uint16_t *resultSize,
4170                                 ltc_pkha_f2m_t arithType,
4171                                 ltc_pkha_montgomery_form_t montIn,
4172                                 ltc_pkha_montgomery_form_t montOut,
4173                                 ltc_pkha_timing_t equalTime)
4174 {
4175     ltc_pkha_mode_params_t params;
4176     status_t status;
4177 
4178     if (arithType == kLTC_PKHA_IntegerArith)
4179     {
4180         if (LTC_PKHA_CompareBigNum(A, sizeA, N, sizeN) >= 0)
4181         {
4182             return (kStatus_InvalidArgument);
4183         }
4184 
4185         if (LTC_PKHA_CompareBigNum(B, sizeB, N, sizeN) >= 0)
4186         {
4187             return (kStatus_InvalidArgument);
4188         }
4189     }
4190 
4191     ltc_pkha_default_parms(&params);
4192     params.func        = kLTC_PKHA_ArithModMul;
4193     params.arithType   = arithType;
4194     params.montFormIn  = montIn;
4195     params.montFormOut = montOut;
4196     params.equalTime   = equalTime;
4197 
4198     ltc_pkha_init_data(base, A, sizeA, B, sizeB, N, sizeN, NULL, 0);
4199     status = ltc_pkha_init_mode(base, &params);
4200 
4201     if (status == kStatus_Success)
4202     {
4203         /* Read the result and size from register B0. */
4204         if ((NULL != resultSize) && (NULL != result))
4205         {
4206             *resultSize = (uint16_t)base->PKBSZ;
4207             /* Read the data from the result register into place. */
4208             ltc_pkha_read_reg(base, kLTC_PKHA_RegB, 0, result, *resultSize);
4209         }
4210     }
4211 
4212     return status;
4213 }
4214 
4215 /*******************************************************************************
4216  * PKHA Code public
4217  ******************************************************************************/
4218 /*!
4219  * brief Compare two PKHA big numbers.
4220  *
4221  * Compare two PKHA big numbers. Return 1 for a > b, -1 for a < b and 0 if they are same.
4222  * PKHA big number is lsbyte first. Thus the comparison starts at msbyte which is the last member of tested arrays.
4223  *
4224  * param a First integer represented as an array of bytes, lsbyte first.
4225  * param sizeA Size in bytes of the first integer.
4226  * param b Second integer represented as an array of bytes, lsbyte first.
4227  * param sizeB Size in bytes of the second integer.
4228  * return 1 if a > b.
4229  * return -1 if a < b.
4230  * return 0 if a = b.
4231  */
LTC_PKHA_CompareBigNum(const uint8_t * a,size_t sizeA,const uint8_t * b,size_t sizeB)4232 int LTC_PKHA_CompareBigNum(const uint8_t *a, size_t sizeA, const uint8_t *b, size_t sizeB)
4233 {
4234     int retval = 0;
4235 
4236     /* skip zero msbytes - integer a */
4237     while ((0U != sizeA) && (0u == a[sizeA - 1U]))
4238     {
4239         sizeA--;
4240     }
4241 
4242     /* skip zero msbytes - integer b */
4243     while ((0U != sizeB) && (0u == b[sizeB - 1U]))
4244     {
4245         sizeB--;
4246     }
4247 
4248     if (sizeA > sizeB)
4249     {
4250         retval = 1;
4251     } /* int a has more non-zero bytes, thus it is bigger than b */
4252     else if (sizeA < sizeB)
4253     {
4254         retval = -1;
4255     } /* int b has more non-zero bytes, thus it is bigger than a */
4256     else if (sizeA == 0U)
4257     {
4258         retval = 0;
4259     } /* sizeA = sizeB = 0 */
4260     else
4261     {
4262         int n;
4263         int i;
4264         int val;
4265         uint32_t equal;
4266 
4267         n     = (int)sizeA - 1;
4268         i     = 0;
4269         equal = 0;
4270 
4271         while (n >= 0)
4272         {
4273             uint32_t chXor = ((uint32_t)a[i] ^ (uint32_t)b[i]);
4274 
4275             equal |= chXor;
4276             val = (int)chXor * ((int)a[i] - (int)b[i]);
4277 
4278             if (val < 0)
4279             {
4280                 *(volatile int *)&retval = -1;
4281             }
4282 
4283             if (val > 0)
4284             {
4285                 *(volatile int *)&retval = 1;
4286             }
4287 
4288             if (val == 0)
4289             {
4290                 *(volatile int *)&val = 1;
4291             }
4292 
4293             i++;
4294             n--;
4295         }
4296 
4297         if (0U == equal)
4298         {
4299             retval = 0;
4300         }
4301     }
4302     return (retval);
4303 }
4304 
4305 /*!
4306  * brief Converts from integer to Montgomery format.
4307  *
4308  * This function computes R2 mod N and optionally converts A or B into Montgomery format of A or B.
4309  *
4310  * param base LTC peripheral base address
4311  * param N modulus
4312  * param sizeN size of N in bytes
4313  * param[in,out] A The first input in non-Montgomery format. Output Montgomery format of the first input.
4314  * param[in,out] sizeA pointer to size variable. On input it holds size of input A in bytes. On output it holds size of
4315  *                Montgomery format of A in bytes.
4316  * param[in,out] B Second input in non-Montgomery format. Output Montgomery format of the second input.
4317  * param[in,out] sizeB pointer to size variable. On input it holds size of input B in bytes. On output it holds size of
4318  *                Montgomery format of B in bytes.
4319  * param[out] R2 Output Montgomery factor R2 mod N.
4320  * param[out] sizeR2 pointer to size variable. On output it holds size of Montgomery factor R2 mod N in bytes.
4321  * param equalTime Run the function time equalized or no timing equalization.
4322  * param arithType Type of arithmetic to perform (integer or F2m)
4323  * return Operation status.
4324  */
LTC_PKHA_NormalToMontgomery(LTC_Type * base,const uint8_t * N,uint16_t sizeN,uint8_t * A,uint16_t * sizeA,uint8_t * B,uint16_t * sizeB,uint8_t * R2,uint16_t * sizeR2,ltc_pkha_timing_t equalTime,ltc_pkha_f2m_t arithType)4325 status_t LTC_PKHA_NormalToMontgomery(LTC_Type *base,
4326                                      const uint8_t *N,
4327                                      uint16_t sizeN,
4328                                      uint8_t *A,
4329                                      uint16_t *sizeA,
4330                                      uint8_t *B,
4331                                      uint16_t *sizeB,
4332                                      uint8_t *R2,
4333                                      uint16_t *sizeR2,
4334                                      ltc_pkha_timing_t equalTime,
4335                                      ltc_pkha_f2m_t arithType)
4336 {
4337     status_t status;
4338 
4339     /* need to convert our Integer inputs into Montgomery format */
4340     if ((NULL != N) && (0U != sizeN) && (NULL != R2) && (NULL != sizeR2))
4341     {
4342         /* 1. R2 = MOD_R2(N) */
4343         status = ltc_pkha_modR2(base, N, sizeN, R2, sizeR2, arithType);
4344         if (status != kStatus_Success)
4345         {
4346             return status;
4347         }
4348 
4349         /* 2. A(Montgomery) = MOD_MUL_IM_OM(A, R2, N) */
4350         if ((NULL != A) && (NULL != sizeA))
4351         {
4352             status = ltc_pkha_modmul(base, A, *sizeA, R2, *sizeR2, N, sizeN, A, sizeA, arithType,
4353                                      kLTC_PKHA_MontgomeryFormat, kLTC_PKHA_MontgomeryFormat, equalTime);
4354             if (status != kStatus_Success)
4355             {
4356                 return status;
4357             }
4358         }
4359 
4360         /* 2. B(Montgomery) = MOD_MUL_IM_OM(B, R2, N) */
4361         if ((NULL != B) && (NULL != sizeB))
4362         {
4363             status = ltc_pkha_modmul(base, B, *sizeB, R2, *sizeR2, N, sizeN, B, sizeB, arithType,
4364                                      kLTC_PKHA_MontgomeryFormat, kLTC_PKHA_MontgomeryFormat, equalTime);
4365             if (status != kStatus_Success)
4366             {
4367                 return status;
4368             }
4369         }
4370 
4371         ltc_clear_all(base, true);
4372     }
4373     else
4374     {
4375         status = kStatus_InvalidArgument;
4376     }
4377 
4378     return status;
4379 }
4380 
4381 /*!
4382  * brief Converts from Montgomery format to int.
4383  *
4384  * This function converts Montgomery format of A or B into int A or B.
4385  *
4386  * param base LTC peripheral base address
4387  * param N modulus.
4388  * param sizeN size of N modulus in bytes.
4389  * param[in,out] A Input first number in Montgomery format. Output is non-Montgomery format.
4390  * param[in,out] sizeA pointer to size variable. On input it holds size of the input A in bytes. On output it holds
4391  * size of non-Montgomery A in bytes.
4392  * param[in,out] B Input first number in Montgomery format. Output is non-Montgomery format.
4393  * param[in,out] sizeB pointer to size variable. On input it holds size of the input B in bytes. On output it holds
4394  * size of non-Montgomery B in bytes.
4395  * param equalTime Run the function time equalized or no timing equalization.
4396  * param arithType Type of arithmetic to perform (integer or F2m)
4397  * return Operation status.
4398  */
LTC_PKHA_MontgomeryToNormal(LTC_Type * base,const uint8_t * N,uint16_t sizeN,uint8_t * A,uint16_t * sizeA,uint8_t * B,uint16_t * sizeB,ltc_pkha_timing_t equalTime,ltc_pkha_f2m_t arithType)4399 status_t LTC_PKHA_MontgomeryToNormal(LTC_Type *base,
4400                                      const uint8_t *N,
4401                                      uint16_t sizeN,
4402                                      uint8_t *A,
4403                                      uint16_t *sizeA,
4404                                      uint8_t *B,
4405                                      uint16_t *sizeB,
4406                                      ltc_pkha_timing_t equalTime,
4407                                      ltc_pkha_f2m_t arithType)
4408 {
4409     uint8_t one     = 1;
4410     status_t status = kStatus_InvalidArgument;
4411 
4412     /* A = MOD_MUL_IM_OM(A(Montgomery), 1, N) */
4413     if ((NULL != A) && (NULL != sizeA))
4414     {
4415         status = ltc_pkha_modmul(base, A, *sizeA, &one, (uint16_t)sizeof(one), N, sizeN, A, sizeA, arithType,
4416                                  kLTC_PKHA_MontgomeryFormat, kLTC_PKHA_MontgomeryFormat, equalTime);
4417         if (kStatus_Success != status)
4418         {
4419             return status;
4420         }
4421     }
4422 
4423     /* B = MOD_MUL_IM_OM(B(Montgomery), 1, N) */
4424     if ((NULL != B) && (NULL != sizeB))
4425     {
4426         status = ltc_pkha_modmul(base, B, *sizeB, &one, (uint16_t)sizeof(one), N, sizeN, B, sizeB, arithType,
4427                                  kLTC_PKHA_MontgomeryFormat, kLTC_PKHA_MontgomeryFormat, equalTime);
4428         if (kStatus_Success != status)
4429         {
4430             return status;
4431         }
4432     }
4433 
4434     ltc_clear_all(base, true);
4435     return status;
4436 }
4437 
4438 /*!
4439  * brief Performs modular addition - (A + B) mod N.
4440  *
4441  * This function performs modular addition of (A + B) mod N, with either
4442  * integer or binary polynomial (F2m) inputs.  In the F2m form, this function is
4443  * equivalent to a bitwise XOR and it is functionally the same as subtraction.
4444  *
4445  * param base LTC peripheral base address
4446  * param A first addend (integer or binary polynomial)
4447  * param sizeA Size of A in bytes
4448  * param B second addend (integer or binary polynomial)
4449  * param sizeB Size of B in bytes
4450  * param N modulus. For F2m operation this can be NULL, as N is ignored during F2m polynomial addition.
4451  * param sizeN Size of N in bytes. This must be given for both integer and F2m polynomial additions.
4452  * param[out] result Output array to store result of operation
4453  * param[out] resultSize Output size of operation in bytes
4454  * param arithType Type of arithmetic to perform (integer or F2m)
4455  * return Operation status.
4456  */
LTC_PKHA_ModAdd(LTC_Type * base,const uint8_t * A,uint16_t sizeA,const uint8_t * B,uint16_t sizeB,const uint8_t * N,uint16_t sizeN,uint8_t * result,uint16_t * resultSize,ltc_pkha_f2m_t arithType)4457 status_t LTC_PKHA_ModAdd(LTC_Type *base,
4458                          const uint8_t *A,
4459                          uint16_t sizeA,
4460                          const uint8_t *B,
4461                          uint16_t sizeB,
4462                          const uint8_t *N,
4463                          uint16_t sizeN,
4464                          uint8_t *result,
4465                          uint16_t *resultSize,
4466                          ltc_pkha_f2m_t arithType)
4467 {
4468     ltc_pkha_mode_params_t params;
4469     status_t status;
4470 
4471     if (arithType == kLTC_PKHA_IntegerArith)
4472     {
4473         if (LTC_PKHA_CompareBigNum(A, sizeA, N, sizeN) >= 0)
4474         {
4475             return (kStatus_InvalidArgument);
4476         }
4477 
4478         if (LTC_PKHA_CompareBigNum(B, sizeB, N, sizeN) >= 0)
4479         {
4480             return (kStatus_InvalidArgument);
4481         }
4482     }
4483 
4484     ltc_pkha_default_parms(&params);
4485     params.func      = kLTC_PKHA_ArithModAdd;
4486     params.arithType = arithType;
4487 
4488     ltc_pkha_init_data(base, A, sizeA, B, sizeB, N, sizeN, NULL, 0);
4489     status = ltc_pkha_init_mode(base, &params);
4490 
4491     if (status == kStatus_Success)
4492     {
4493         /* Read the result and size from register B0. */
4494         if ((NULL != resultSize) && (NULL != result))
4495         {
4496             *resultSize = (uint16_t)base->PKBSZ;
4497             /* Read the data from the result register into place. */
4498             ltc_pkha_read_reg(base, kLTC_PKHA_RegB, 0, result, *resultSize);
4499         }
4500     }
4501 
4502     ltc_clear_all(base, true);
4503     return status;
4504 }
4505 
4506 /*!
4507  * brief Performs modular subtraction - (A - B) mod N.
4508  *
4509  * This function performs modular subtraction of (A - B) mod N with
4510  * integer inputs.
4511  *
4512  * param base LTC peripheral base address
4513  * param A first addend (integer or binary polynomial)
4514  * param sizeA Size of A in bytes
4515  * param B second addend (integer or binary polynomial)
4516  * param sizeB Size of B in bytes
4517  * param N modulus
4518  * param sizeN Size of N in bytes
4519  * param[out] result Output array to store result of operation
4520  * param[out] resultSize Output size of operation in bytes
4521  * return Operation status.
4522  */
LTC_PKHA_ModSub1(LTC_Type * base,const uint8_t * A,uint16_t sizeA,const uint8_t * B,uint16_t sizeB,const uint8_t * N,uint16_t sizeN,uint8_t * result,uint16_t * resultSize)4523 status_t LTC_PKHA_ModSub1(LTC_Type *base,
4524                           const uint8_t *A,
4525                           uint16_t sizeA,
4526                           const uint8_t *B,
4527                           uint16_t sizeB,
4528                           const uint8_t *N,
4529                           uint16_t sizeN,
4530                           uint8_t *result,
4531                           uint16_t *resultSize)
4532 {
4533     ltc_pkha_mode_params_t params;
4534     status_t status;
4535 
4536     if (LTC_PKHA_CompareBigNum(A, sizeA, N, sizeN) >= 0)
4537     {
4538         return (kStatus_InvalidArgument);
4539     }
4540 
4541     if (LTC_PKHA_CompareBigNum(B, sizeB, N, sizeN) >= 0)
4542     {
4543         return (kStatus_InvalidArgument);
4544     }
4545 
4546     ltc_pkha_default_parms(&params);
4547     params.func = kLTC_PKHA_ArithModSub1;
4548     ltc_pkha_init_data(base, A, sizeA, B, sizeB, N, sizeN, NULL, 0);
4549 
4550     status = ltc_pkha_init_mode(base, &params);
4551 
4552     if (status == kStatus_Success)
4553     {
4554         /* Read the result and size from register B0. */
4555         if ((NULL != resultSize) && (NULL != result))
4556         {
4557             *resultSize = (uint16_t)base->PKBSZ;
4558             /* Read the data from the result register into place. */
4559             ltc_pkha_read_reg(base, kLTC_PKHA_RegB, 0, result, *resultSize);
4560         }
4561     }
4562 
4563     ltc_clear_all(base, true);
4564     return status;
4565 }
4566 
4567 /*!
4568  * brief Performs modular subtraction - (B - A) mod N.
4569  *
4570  * This function performs modular subtraction of (B - A) mod N,
4571  * with integer inputs.
4572  *
4573  * param base LTC peripheral base address
4574  * param A first addend (integer or binary polynomial)
4575  * param sizeA Size of A in bytes
4576  * param B second addend (integer or binary polynomial)
4577  * param sizeB Size of B in bytes
4578  * param N modulus
4579  * param sizeN Size of N in bytes
4580  * param[out] result Output array to store result of operation
4581  * param[out] resultSize Output size of operation in bytes
4582  * return Operation status.
4583  */
LTC_PKHA_ModSub2(LTC_Type * base,const uint8_t * A,uint16_t sizeA,const uint8_t * B,uint16_t sizeB,const uint8_t * N,uint16_t sizeN,uint8_t * result,uint16_t * resultSize)4584 status_t LTC_PKHA_ModSub2(LTC_Type *base,
4585                           const uint8_t *A,
4586                           uint16_t sizeA,
4587                           const uint8_t *B,
4588                           uint16_t sizeB,
4589                           const uint8_t *N,
4590                           uint16_t sizeN,
4591                           uint8_t *result,
4592                           uint16_t *resultSize)
4593 {
4594     ltc_pkha_mode_params_t params;
4595     status_t status;
4596 
4597     ltc_pkha_default_parms(&params);
4598     params.func = kLTC_PKHA_ArithModSub2;
4599 
4600     ltc_pkha_init_data(base, A, sizeA, B, sizeB, N, sizeN, NULL, 0);
4601     status = ltc_pkha_init_mode(base, &params);
4602 
4603     if (status == kStatus_Success)
4604     {
4605         /* Read the result and size from register B0. */
4606         if ((NULL != resultSize) && (NULL != result))
4607         {
4608             *resultSize = (uint16_t)base->PKBSZ;
4609             /* Read the data from the result register into place. */
4610             ltc_pkha_read_reg(base, kLTC_PKHA_RegB, 0, result, *resultSize);
4611         }
4612     }
4613 
4614     ltc_clear_all(base, true);
4615     return status;
4616 }
4617 
4618 /*!
4619  * brief Performs modular multiplication - (A x B) mod N.
4620  *
4621  * This function performs modular multiplication with either integer or
4622  * binary polynomial (F2m) inputs.  It can optionally specify whether inputs
4623  * and/or outputs will be in Montgomery form or not.
4624  *
4625  * param base LTC peripheral base address
4626  * param A first addend (integer or binary polynomial)
4627  * param sizeA Size of A in bytes
4628  * param B second addend (integer or binary polynomial)
4629  * param sizeB Size of B in bytes
4630  * param N modulus.
4631  * param sizeN Size of N in bytes
4632  * param[out] result Output array to store result of operation
4633  * param[out] resultSize Output size of operation in bytes
4634  * param arithType Type of arithmetic to perform (integer or F2m)
4635  * param montIn Format of inputs
4636  * param montOut Format of output
4637  * param equalTime Run the function time equalized or no timing equalization. This argument is ignored for F2m modular
4638  * multiplication.
4639  * return Operation status.
4640  */
LTC_PKHA_ModMul(LTC_Type * base,const uint8_t * A,uint16_t sizeA,const uint8_t * B,uint16_t sizeB,const uint8_t * N,uint16_t sizeN,uint8_t * result,uint16_t * resultSize,ltc_pkha_f2m_t arithType,ltc_pkha_montgomery_form_t montIn,ltc_pkha_montgomery_form_t montOut,ltc_pkha_timing_t equalTime)4641 status_t LTC_PKHA_ModMul(LTC_Type *base,
4642                          const uint8_t *A,
4643                          uint16_t sizeA,
4644                          const uint8_t *B,
4645                          uint16_t sizeB,
4646                          const uint8_t *N,
4647                          uint16_t sizeN,
4648                          uint8_t *result,
4649                          uint16_t *resultSize,
4650                          ltc_pkha_f2m_t arithType,
4651                          ltc_pkha_montgomery_form_t montIn,
4652                          ltc_pkha_montgomery_form_t montOut,
4653                          ltc_pkha_timing_t equalTime)
4654 {
4655     status_t status;
4656 
4657     status =
4658         ltc_pkha_modmul(base, A, sizeA, B, sizeB, N, sizeN, result, resultSize, arithType, montIn, montOut, equalTime);
4659 
4660     ltc_clear_all(base, true);
4661     return status;
4662 }
4663 
4664 /*!
4665  * brief Performs modular exponentiation - (A^E) mod N.
4666  *
4667  * This function performs modular exponentiation with either integer or
4668  * binary polynomial (F2m) inputs.
4669  *
4670  * param base LTC peripheral base address
4671  * param A first addend (integer or binary polynomial)
4672  * param sizeA Size of A in bytes
4673  * param N modulus
4674  * param sizeN Size of N in bytes
4675  * param E exponent
4676  * param sizeE Size of E in bytes
4677  * param[out] result Output array to store result of operation
4678  * param[out] resultSize Output size of operation in bytes
4679  * param montIn Format of A input (normal or Montgomery)
4680  * param arithType Type of arithmetic to perform (integer or F2m)
4681  * param equalTime Run the function time equalized or no timing equalization.
4682  * return Operation status.
4683  */
LTC_PKHA_ModExp(LTC_Type * base,const uint8_t * A,uint16_t sizeA,const uint8_t * N,uint16_t sizeN,const uint8_t * E,uint16_t sizeE,uint8_t * result,uint16_t * resultSize,ltc_pkha_f2m_t arithType,ltc_pkha_montgomery_form_t montIn,ltc_pkha_timing_t equalTime)4684 status_t LTC_PKHA_ModExp(LTC_Type *base,
4685                          const uint8_t *A,
4686                          uint16_t sizeA,
4687                          const uint8_t *N,
4688                          uint16_t sizeN,
4689                          const uint8_t *E,
4690                          uint16_t sizeE,
4691                          uint8_t *result,
4692                          uint16_t *resultSize,
4693                          ltc_pkha_f2m_t arithType,
4694                          ltc_pkha_montgomery_form_t montIn,
4695                          ltc_pkha_timing_t equalTime)
4696 {
4697     ltc_pkha_mode_params_t params;
4698     status_t status;
4699 
4700     if (arithType == kLTC_PKHA_IntegerArith)
4701     {
4702         if (LTC_PKHA_CompareBigNum(A, sizeA, N, sizeN) >= 0)
4703         {
4704             return (kStatus_InvalidArgument);
4705         }
4706     }
4707 
4708     ltc_pkha_default_parms(&params);
4709     params.func       = kLTC_PKHA_ArithModExp;
4710     params.arithType  = arithType;
4711     params.montFormIn = montIn;
4712     params.equalTime  = equalTime;
4713 
4714     ltc_pkha_init_data(base, A, sizeA, NULL, 0, N, sizeN, E, sizeE);
4715     status = ltc_pkha_init_mode(base, &params);
4716 
4717     if (status == kStatus_Success)
4718     {
4719         /* Read the result and size from register B0. */
4720         if ((NULL != resultSize) && (NULL != result))
4721         {
4722             *resultSize = (uint16_t)base->PKBSZ;
4723             /* Read the data from the result register into place. */
4724             ltc_pkha_read_reg(base, kLTC_PKHA_RegB, 0, result, *resultSize);
4725         }
4726     }
4727 
4728     ltc_clear_all(base, true);
4729     return status;
4730 }
4731 
4732 /*!
4733  * brief Performs modular reduction - (A) mod N.
4734  *
4735  * This function performs modular reduction with either integer or
4736  * binary polynomial (F2m) inputs.
4737  *
4738  * param base LTC peripheral base address
4739  * param A first addend (integer or binary polynomial)
4740  * param sizeA Size of A in bytes
4741  * param N modulus
4742  * param sizeN Size of N in bytes
4743  * param[out] result Output array to store result of operation
4744  * param[out] resultSize Output size of operation in bytes
4745  * param arithType Type of arithmetic to perform (integer or F2m)
4746  * return Operation status.
4747  */
LTC_PKHA_ModRed(LTC_Type * base,const uint8_t * A,uint16_t sizeA,const uint8_t * N,uint16_t sizeN,uint8_t * result,uint16_t * resultSize,ltc_pkha_f2m_t arithType)4748 status_t LTC_PKHA_ModRed(LTC_Type *base,
4749                          const uint8_t *A,
4750                          uint16_t sizeA,
4751                          const uint8_t *N,
4752                          uint16_t sizeN,
4753                          uint8_t *result,
4754                          uint16_t *resultSize,
4755                          ltc_pkha_f2m_t arithType)
4756 {
4757     ltc_pkha_mode_params_t params;
4758     status_t status;
4759 
4760     ltc_pkha_default_parms(&params);
4761     params.func      = kLTC_PKHA_ArithModRed;
4762     params.arithType = arithType;
4763 
4764     ltc_pkha_init_data(base, A, sizeA, NULL, 0, N, sizeN, NULL, 0);
4765     status = ltc_pkha_init_mode(base, &params);
4766 
4767     if (status == kStatus_Success)
4768     {
4769         /* Read the result and size from register B0. */
4770         if ((NULL != resultSize) && (NULL != result))
4771         {
4772             *resultSize = (uint16_t)base->PKBSZ;
4773             /* Read the data from the result register into place. */
4774             ltc_pkha_read_reg(base, kLTC_PKHA_RegB, 0, result, *resultSize);
4775         }
4776     }
4777 
4778     ltc_clear_all(base, true);
4779     return status;
4780 }
4781 
4782 /*!
4783  * brief Performs modular inversion - (A^-1) mod N.
4784  *
4785  * This function performs modular inversion with either integer or
4786  * binary polynomial (F2m) inputs.
4787  *
4788  * param base LTC peripheral base address
4789  * param A first addend (integer or binary polynomial)
4790  * param sizeA Size of A in bytes
4791  * param N modulus
4792  * param sizeN Size of N in bytes
4793  * param[out] result Output array to store result of operation
4794  * param[out] resultSize Output size of operation in bytes
4795  * param arithType Type of arithmetic to perform (integer or F2m)
4796  * return Operation status.
4797  */
LTC_PKHA_ModInv(LTC_Type * base,const uint8_t * A,uint16_t sizeA,const uint8_t * N,uint16_t sizeN,uint8_t * result,uint16_t * resultSize,ltc_pkha_f2m_t arithType)4798 status_t LTC_PKHA_ModInv(LTC_Type *base,
4799                          const uint8_t *A,
4800                          uint16_t sizeA,
4801                          const uint8_t *N,
4802                          uint16_t sizeN,
4803                          uint8_t *result,
4804                          uint16_t *resultSize,
4805                          ltc_pkha_f2m_t arithType)
4806 {
4807     ltc_pkha_mode_params_t params;
4808     status_t status;
4809 
4810     /* A must be less than N -> LTC_PKHA_CompareBigNum() must return -1 */
4811     if (arithType == kLTC_PKHA_IntegerArith)
4812     {
4813         if (LTC_PKHA_CompareBigNum(A, sizeA, N, sizeN) >= 0)
4814         {
4815             return (kStatus_InvalidArgument);
4816         }
4817     }
4818 
4819     ltc_pkha_default_parms(&params);
4820     params.func      = kLTC_PKHA_ArithModInv;
4821     params.arithType = arithType;
4822 
4823     ltc_pkha_init_data(base, A, sizeA, NULL, 0, N, sizeN, NULL, 0);
4824     status = ltc_pkha_init_mode(base, &params);
4825 
4826     if (status == kStatus_Success)
4827     {
4828         /* Read the result and size from register B0. */
4829         if ((NULL != resultSize) && (NULL != result))
4830         {
4831             *resultSize = (uint16_t)base->PKBSZ;
4832             /* Read the data from the result register into place. */
4833             ltc_pkha_read_reg(base, kLTC_PKHA_RegB, 0, result, *resultSize);
4834         }
4835     }
4836 
4837     ltc_clear_all(base, true);
4838     return status;
4839 }
4840 
4841 /*!
4842  * brief Computes integer Montgomery factor R^2 mod N.
4843  *
4844  * This function computes a constant to assist in converting operands
4845  * into the Montgomery residue system representation.
4846  *
4847  * param base LTC peripheral base address
4848  * param N modulus
4849  * param sizeN Size of N in bytes
4850  * param[out] result Output array to store result of operation
4851  * param[out] resultSize Output size of operation in bytes
4852  * param arithType Type of arithmetic to perform (integer or F2m)
4853  * return Operation status.
4854  */
LTC_PKHA_ModR2(LTC_Type * base,const uint8_t * N,uint16_t sizeN,uint8_t * result,uint16_t * resultSize,ltc_pkha_f2m_t arithType)4855 status_t LTC_PKHA_ModR2(
4856     LTC_Type *base, const uint8_t *N, uint16_t sizeN, uint8_t *result, uint16_t *resultSize, ltc_pkha_f2m_t arithType)
4857 {
4858     status_t status;
4859     status = ltc_pkha_modR2(base, N, sizeN, result, resultSize, arithType);
4860     ltc_clear_all(base, true);
4861     return status;
4862 }
4863 
4864 /*!
4865  * brief Calculates the greatest common divisor - GCD (A, N).
4866  *
4867  * This function calculates the greatest common divisor of two inputs with
4868  * either integer or binary polynomial (F2m) inputs.
4869  *
4870  * param base LTC peripheral base address
4871  * param A first value (must be smaller than or equal to N)
4872  * param sizeA Size of A in bytes
4873  * param N second value (must be non-zero)
4874  * param sizeN Size of N in bytes
4875  * param[out] result Output array to store result of operation
4876  * param[out] resultSize Output size of operation in bytes
4877  * param arithType Type of arithmetic to perform (integer or F2m)
4878  * return Operation status.
4879  */
LTC_PKHA_GCD(LTC_Type * base,const uint8_t * A,uint16_t sizeA,const uint8_t * N,uint16_t sizeN,uint8_t * result,uint16_t * resultSize,ltc_pkha_f2m_t arithType)4880 status_t LTC_PKHA_GCD(LTC_Type *base,
4881                       const uint8_t *A,
4882                       uint16_t sizeA,
4883                       const uint8_t *N,
4884                       uint16_t sizeN,
4885                       uint8_t *result,
4886                       uint16_t *resultSize,
4887                       ltc_pkha_f2m_t arithType)
4888 {
4889     ltc_pkha_mode_params_t params;
4890     status_t status;
4891 
4892     ltc_pkha_default_parms(&params);
4893     params.func      = kLTC_PKHA_ArithGcd;
4894     params.arithType = arithType;
4895 
4896     ltc_pkha_init_data(base, A, sizeA, NULL, 0, N, sizeN, NULL, 0);
4897     status = ltc_pkha_init_mode(base, &params);
4898 
4899     if (status == kStatus_Success)
4900     {
4901         /* Read the result and size from register B0. */
4902         if ((NULL != resultSize) && (NULL != result))
4903         {
4904             *resultSize = (uint16_t)base->PKBSZ;
4905             /* Read the data from the result register into place. */
4906             ltc_pkha_read_reg(base, kLTC_PKHA_RegB, 0, result, *resultSize);
4907         }
4908     }
4909 
4910     ltc_clear_all(base, true);
4911     return status;
4912 }
4913 
4914 /*!
4915  * brief Executes Miller-Rabin primality test.
4916  *
4917  * This function calculates whether or not a candidate prime number is likely
4918  * to be a prime.
4919  *
4920  * param base LTC peripheral base address
4921  * param A initial random seed
4922  * param sizeA Size of A in bytes
4923  * param B number of trial runs
4924  * param sizeB Size of B in bytes
4925  * param N candidate prime integer
4926  * param sizeN Size of N in bytes
4927  * param[out] res True if the value is likely prime or false otherwise
4928  * return Operation status.
4929  */
LTC_PKHA_PrimalityTest(LTC_Type * base,const uint8_t * A,uint16_t sizeA,const uint8_t * B,uint16_t sizeB,const uint8_t * N,uint16_t sizeN,bool * res)4930 status_t LTC_PKHA_PrimalityTest(LTC_Type *base,
4931                                 const uint8_t *A,
4932                                 uint16_t sizeA,
4933                                 const uint8_t *B,
4934                                 uint16_t sizeB,
4935                                 const uint8_t *N,
4936                                 uint16_t sizeN,
4937                                 bool *res)
4938 {
4939     uint8_t result;
4940     ltc_pkha_mode_params_t params;
4941     status_t status;
4942 
4943     ltc_pkha_default_parms(&params);
4944     params.func = kLTC_PKHA_ArithPrimalityTest;
4945     ltc_pkha_init_data(base, A, sizeA, B, sizeB, N, sizeN, NULL, 0);
4946     status = ltc_pkha_init_mode(base, &params);
4947 
4948     if (status == kStatus_Success)
4949     {
4950         /* Read the data from the result register into place. */
4951         ltc_pkha_read_reg(base, kLTC_PKHA_RegB, 0, &result, 1);
4952 
4953         *res = (bool)result;
4954     }
4955 
4956     ltc_clear_all(base, true);
4957     return status;
4958 }
4959 
4960 /*!
4961  * brief Adds elliptic curve points - A + B.
4962  *
4963  * This function performs ECC point addition over a prime field (Fp) or binary field (F2m) using
4964  * affine coordinates.
4965  *
4966  * param base LTC peripheral base address
4967  * param A Left-hand point
4968  * param B Right-hand point
4969  * param N Prime modulus of the field
4970  * param R2modN NULL (the function computes R2modN internally) or pointer to pre-computed R2modN (obtained from
4971  *               LTC_PKHA_ModR2() function).
4972  * param aCurveParam A parameter from curve equation
4973  * param bCurveParam B parameter from curve equation (constant)
4974  * param size Size in bytes of curve points and parameters
4975  * param arithType Type of arithmetic to perform (integer or F2m)
4976  * param[out] result Result point
4977  * return Operation status.
4978  */
LTC_PKHA_ECC_PointAdd(LTC_Type * base,const ltc_pkha_ecc_point_t * A,const ltc_pkha_ecc_point_t * B,const uint8_t * N,const uint8_t * R2modN,const uint8_t * aCurveParam,const uint8_t * bCurveParam,uint8_t size,ltc_pkha_f2m_t arithType,ltc_pkha_ecc_point_t * result)4979 status_t LTC_PKHA_ECC_PointAdd(LTC_Type *base,
4980                                const ltc_pkha_ecc_point_t *A,
4981                                const ltc_pkha_ecc_point_t *B,
4982                                const uint8_t *N,
4983                                const uint8_t *R2modN,
4984                                const uint8_t *aCurveParam,
4985                                const uint8_t *bCurveParam,
4986                                uint8_t size,
4987                                ltc_pkha_f2m_t arithType,
4988                                ltc_pkha_ecc_point_t *result)
4989 {
4990     ltc_pkha_mode_params_t params;
4991     uint32_t clearMask;
4992     status_t status;
4993 
4994     ltc_pkha_default_parms(&params);
4995     params.func      = kLTC_PKHA_ArithEccAdd;
4996     params.arithType = arithType;
4997     params.r2modn    = (R2modN != NULL) ? kLTC_PKHA_InputR2 : kLTC_PKHA_CalcR2;
4998 
4999     clearMask = (uint32_t)kLTC_ClearMode;
5000 
5001     /* Clear internal register states. */
5002     clearMask |= (uint32_t)kLTC_ClearPkhaSizeA;
5003     clearMask |= (uint32_t)kLTC_ClearPkhaSizeB;
5004     clearMask |= (uint32_t)kLTC_ClearPkhaSizeN;
5005     clearMask |= (uint32_t)kLTC_ClearPkhaSizeE;
5006 
5007     base->CW  = clearMask;
5008     base->STA = (uint32_t)kLTC_StatusDoneIsr;
5009     (void)ltc_pkha_clear_regabne(base, true, true, true, false);
5010 
5011     /* sizeN should be less than 64 bytes. */
5012     base->PKNSZ = size;
5013     (void)ltc_pkha_write_reg(base, kLTC_PKHA_RegN, 0, N, size);
5014 
5015     base->PKASZ = size;
5016     (void)ltc_pkha_write_reg(base, kLTC_PKHA_RegA, 0, A->X, size);
5017     (void)ltc_pkha_write_reg(base, kLTC_PKHA_RegA, 1, A->Y, size);
5018     (void)ltc_pkha_write_reg(base, kLTC_PKHA_RegA, 3, aCurveParam, size);
5019 
5020     base->PKBSZ = size;
5021     (void)ltc_pkha_write_reg(base, kLTC_PKHA_RegB, 0, bCurveParam, size);
5022     (void)ltc_pkha_write_reg(base, kLTC_PKHA_RegB, 1, B->X, size);
5023     (void)ltc_pkha_write_reg(base, kLTC_PKHA_RegB, 2, B->Y, size);
5024     if (NULL != R2modN)
5025     {
5026         (void)ltc_pkha_write_reg(base, kLTC_PKHA_RegB, 3, R2modN, size);
5027     }
5028 
5029     status = ltc_pkha_init_mode(base, &params);
5030 
5031     if (status == kStatus_Success)
5032     {
5033         /* Read the data from the result register into place. */
5034         ltc_pkha_read_reg(base, kLTC_PKHA_RegB, 1, result->X, size);
5035         ltc_pkha_read_reg(base, kLTC_PKHA_RegB, 2, result->Y, size);
5036     }
5037 
5038     ltc_clear_all(base, true);
5039     return status;
5040 }
5041 
5042 /*!
5043  * brief Doubles elliptic curve points - B + B.
5044  *
5045  * This function performs ECC point doubling over a prime field (Fp) or binary field (F2m) using
5046  * affine coordinates.
5047  *
5048  * param base LTC peripheral base address
5049  * param B Point to double
5050  * param N Prime modulus of the field
5051  * param aCurveParam A parameter from curve equation
5052  * param bCurveParam B parameter from curve equation (constant)
5053  * param size Size in bytes of curve points and parameters
5054  * param arithType Type of arithmetic to perform (integer or F2m)
5055  * param[out] result Result point
5056  * return Operation status.
5057  */
LTC_PKHA_ECC_PointDouble(LTC_Type * base,const ltc_pkha_ecc_point_t * B,const uint8_t * N,const uint8_t * aCurveParam,const uint8_t * bCurveParam,uint8_t size,ltc_pkha_f2m_t arithType,ltc_pkha_ecc_point_t * result)5058 status_t LTC_PKHA_ECC_PointDouble(LTC_Type *base,
5059                                   const ltc_pkha_ecc_point_t *B,
5060                                   const uint8_t *N,
5061                                   const uint8_t *aCurveParam,
5062                                   const uint8_t *bCurveParam,
5063                                   uint8_t size,
5064                                   ltc_pkha_f2m_t arithType,
5065                                   ltc_pkha_ecc_point_t *result)
5066 {
5067     ltc_pkha_mode_params_t params;
5068     uint32_t clearMask;
5069     status_t status;
5070 
5071     ltc_pkha_default_parms(&params);
5072     params.func      = kLTC_PKHA_ArithEccDouble;
5073     params.arithType = arithType;
5074 
5075     clearMask = (uint32_t)kLTC_ClearMode;
5076 
5077     /* Clear internal register states. */
5078     clearMask |= (uint32_t)kLTC_ClearPkhaSizeA;
5079     clearMask |= (uint32_t)kLTC_ClearPkhaSizeB;
5080     clearMask |= (uint32_t)kLTC_ClearPkhaSizeN;
5081     clearMask |= (uint32_t)kLTC_ClearPkhaSizeE;
5082 
5083     base->CW  = clearMask;
5084     base->STA = (uint32_t)kLTC_StatusDoneIsr;
5085     (void)ltc_pkha_clear_regabne(base, true, true, true, false);
5086 
5087     /* sizeN should be less than 64 bytes. */
5088     base->PKNSZ = size;
5089     (void)ltc_pkha_write_reg(base, kLTC_PKHA_RegN, 0, N, size);
5090 
5091     base->PKASZ = size;
5092     (void)ltc_pkha_write_reg(base, kLTC_PKHA_RegA, 3, aCurveParam, size);
5093 
5094     base->PKBSZ = size;
5095     (void)ltc_pkha_write_reg(base, kLTC_PKHA_RegB, 0, bCurveParam, size);
5096     (void)ltc_pkha_write_reg(base, kLTC_PKHA_RegB, 1, B->X, size);
5097     (void)ltc_pkha_write_reg(base, kLTC_PKHA_RegB, 2, B->Y, size);
5098     status = ltc_pkha_init_mode(base, &params);
5099 
5100     if (status == kStatus_Success)
5101     {
5102         /* Read the data from the result register into place. */
5103         ltc_pkha_read_reg(base, kLTC_PKHA_RegB, 1, result->X, size);
5104         ltc_pkha_read_reg(base, kLTC_PKHA_RegB, 2, result->Y, size);
5105     }
5106 
5107     ltc_clear_all(base, true);
5108     return status;
5109 }
5110 
5111 /*!
5112  * brief Multiplies an elliptic curve point by a scalar - E x (A0, A1).
5113  *
5114  * This function performs ECC point multiplication to multiply an ECC point by
5115  * a scalar integer multiplier over a prime field (Fp) or a binary field (F2m).
5116  *
5117  * param base LTC peripheral base address
5118  * param A Point as multiplicand
5119  * param E Scalar multiple
5120  * param sizeE The size of E, in bytes
5121  * param N Modulus, a prime number for the Fp field or Irreducible polynomial for F2m field.
5122  * param R2modN NULL (the function computes R2modN internally) or pointer to pre-computed R2modN (obtained from
5123  *        LTC_PKHA_ModR2() function).
5124  * param aCurveParam A parameter from curve equation
5125  * param bCurveParam B parameter from curve equation (C parameter for operation over F2m).
5126  * param size Size in bytes of curve points and parameters
5127  * param equalTime Run the function time equalized or no timing equalization.
5128  * param arithType Type of arithmetic to perform (integer or F2m)
5129  * param[out] result Result point
5130  * param[out] infinity Output true if the result is point of infinity, and false otherwise. Writing of this output will
5131  * be ignored if the argument is NULL.
5132  * return Operation status.
5133  */
LTC_PKHA_ECC_PointMul(LTC_Type * base,const ltc_pkha_ecc_point_t * A,const uint8_t * E,uint8_t sizeE,const uint8_t * N,const uint8_t * R2modN,const uint8_t * aCurveParam,const uint8_t * bCurveParam,uint8_t size,ltc_pkha_timing_t equalTime,ltc_pkha_f2m_t arithType,ltc_pkha_ecc_point_t * result,bool * infinity)5134 status_t LTC_PKHA_ECC_PointMul(LTC_Type *base,
5135                                const ltc_pkha_ecc_point_t *A,
5136                                const uint8_t *E,
5137                                uint8_t sizeE,
5138                                const uint8_t *N,
5139                                const uint8_t *R2modN,
5140                                const uint8_t *aCurveParam,
5141                                const uint8_t *bCurveParam,
5142                                uint8_t size,
5143                                ltc_pkha_timing_t equalTime,
5144                                ltc_pkha_f2m_t arithType,
5145                                ltc_pkha_ecc_point_t *result,
5146                                bool *infinity)
5147 {
5148     ltc_pkha_mode_params_t params;
5149     uint32_t clearMask;
5150     status_t status;
5151 
5152     ltc_pkha_default_parms(&params);
5153     params.func      = kLTC_PKHA_ArithEccMul;
5154     params.equalTime = equalTime;
5155     params.arithType = arithType;
5156     params.r2modn    = (R2modN != NULL) ? kLTC_PKHA_InputR2 : kLTC_PKHA_CalcR2;
5157 
5158     clearMask = (uint32_t)kLTC_ClearMode;
5159 
5160     /* Clear internal register states. */
5161     clearMask |= (uint32_t)kLTC_ClearPkhaSizeA;
5162     clearMask |= (uint32_t)kLTC_ClearPkhaSizeB;
5163     clearMask |= (uint32_t)kLTC_ClearPkhaSizeN;
5164     clearMask |= (uint32_t)kLTC_ClearPkhaSizeE;
5165 
5166     base->CW  = clearMask;
5167     base->STA = (uint32_t)kLTC_StatusDoneIsr;
5168     (void)ltc_pkha_clear_regabne(base, true, true, true, true);
5169 
5170     /* sizeN should be less than 64 bytes. */
5171     base->PKNSZ = size;
5172     (void)ltc_pkha_write_reg(base, kLTC_PKHA_RegN, 0, N, size);
5173 
5174     base->PKESZ = sizeE;
5175     (void)ltc_pkha_write_reg(base, kLTC_PKHA_RegE, 0, E, sizeE);
5176 
5177     base->PKASZ = size;
5178     (void)ltc_pkha_write_reg(base, kLTC_PKHA_RegA, 0, A->X, size);
5179     (void)ltc_pkha_write_reg(base, kLTC_PKHA_RegA, 1, A->Y, size);
5180     (void)ltc_pkha_write_reg(base, kLTC_PKHA_RegA, 3, aCurveParam, size);
5181 
5182     base->PKBSZ = size;
5183     (void)ltc_pkha_write_reg(base, kLTC_PKHA_RegB, 0, bCurveParam, size);
5184     if (NULL != R2modN)
5185     {
5186         (void)ltc_pkha_write_reg(base, kLTC_PKHA_RegB, 1, R2modN, size);
5187     }
5188 
5189     status = ltc_pkha_init_mode(base, &params);
5190 
5191     if (status == kStatus_Success)
5192     {
5193         /* Read the data from the result register into place. */
5194         ltc_pkha_read_reg(base, kLTC_PKHA_RegB, 1, result->X, size);
5195         ltc_pkha_read_reg(base, kLTC_PKHA_RegB, 2, result->Y, size);
5196 
5197         if (NULL != infinity)
5198         {
5199             *infinity = (bool)(base->STA & (uint32_t)kLTC_StatusPublicKeyOpZero);
5200         }
5201     }
5202 
5203     ltc_clear_all(base, true);
5204     return status;
5205 }
5206 
5207 #endif /* FSL_FEATURE_LTC_HAS_PKHA */
5208