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)) || defined(__CC_ARM))
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 #else
362     *((uint32_t *)(uint32_t)dstAddr) = srcWord;
363 #endif
364 }
365 
366 /*!
367  * @brief Sets the LTC keys.
368  *
369  * This function writes the LTC keys into the key register.  The keys should
370  * be written before the key size.
371  *
372  * @param base LTC peripheral base address
373  * @param key Key
374  * @param keySize Number of bytes for all keys to be loaded (maximum 32, must be a
375  *                multiple of 4).
376  */
ltc_set_key(LTC_Type * base,const uint8_t * key,uint8_t keySize)377 static void ltc_set_key(LTC_Type *base, const uint8_t *key, uint8_t keySize)
378 {
379     uint32_t i;
380 
381     for (i = 0; i < ((uint32_t)keySize / 4u); i++)
382     {
383         base->KEY[i] = ltc_get_word_from_unaligned(&key[i * sizeof(uint32_t)]);
384     }
385 }
386 
387 /*!
388  * @brief Gets the LTC keys.
389  *
390  * This function retrieves the LTC keys from the key register.
391  *
392  * @param base LTC peripheral base address
393  * @param key Array of data to store keys
394  * @param keySize Number of bytes of keys to retrieve
395  */
ltc_get_key(LTC_Type * base,uint8_t * key,uint8_t keySize)396 static void ltc_get_key(LTC_Type *base, uint8_t *key, uint8_t keySize)
397 {
398     uint32_t i;
399 
400     for (i = 0; i < ((uint32_t)keySize / 4U); i++)
401     {
402         ltc_set_unaligned_from_word(base->KEY[i], &key[i * sizeof(uint32_t)]);
403     }
404 }
405 
406 /*!
407  * @brief Writes the LTC context register;
408  *
409  * The LTC context register is a 512 bit (64 byte) register that holds
410  * internal context for the crypto engine.  The meaning varies based on the
411  * algorithm and operating state being used.  This register is written by the
412  * driver/application to load state such as IV, counter, and so on. Then, it is
413  * updated by the internal crypto engine as needed.
414  *
415  * @param base LTC peripheral base address
416  * @param data Data to write
417  * @param dataSize Size of data to write in bytes
418  * @param startIndex Starting word (4-byte) index into the 16-word register.
419  * @return Status of write
420  */
ltc_set_context(LTC_Type * base,const uint8_t * data,uint8_t dataSize,uint8_t startIndex)421 status_t ltc_set_context(LTC_Type *base, const uint8_t *data, uint8_t dataSize, uint8_t startIndex)
422 {
423     uint32_t i;
424     uint8_t j;
425     uint8_t szLeft;
426 
427     /* Context register is 16 words in size (64 bytes).  Ensure we are only
428      * writing a valid amount of data. */
429     if (startIndex + (dataSize / 4u) >= 16u)
430     {
431         return kStatus_InvalidArgument;
432     }
433 
434     j      = 0;
435     szLeft = dataSize % 4u;
436     for (i = (uint32_t)startIndex; i < ((uint32_t)startIndex + (uint32_t)dataSize / 4u); i++)
437     {
438         base->CTX[i] = ltc_get_word_from_unaligned(&data[j]);
439         j += (uint8_t)sizeof(uint32_t);
440     }
441 
442     if (0U != szLeft)
443     {
444         uint32_t context_data = {0};
445         ltc_memcpy(&context_data, &data[j], (uint32_t)szLeft);
446         base->CTX[i] = context_data;
447     }
448     return kStatus_Success;
449 }
450 
451 /*!
452  * @brief Reads the LTC context register.
453  *
454  * The LTC context register is a 512 bit (64 byte) register that holds
455  * internal context for the crypto engine.  The meaning varies based on the
456  * algorithm and operating state being used.  This register is written by the
457  * driver/application to load state such as IV, counter, and so on. Then, it is
458  * updated by the internal crypto engine as needed.
459  *
460  * @param base LTC peripheral base address
461  * @param data Destination of read data
462  * @param dataSize Size of data to read in bytes
463  * @param startIndex Starting word (4-byte) index into the 16-word register.
464  * @return Status of read
465  */
ltc_get_context(LTC_Type * base,uint8_t * dest,uint8_t dataSize,uint8_t startIndex)466 status_t ltc_get_context(LTC_Type *base, uint8_t *dest, uint8_t dataSize, uint8_t startIndex)
467 {
468     uint32_t i;
469     int32_t j;
470     uint8_t szLeft;
471     uint32_t rdCtx;
472 
473     /* Context register is 16 words in size (64 bytes).  Ensure we are only
474      * writing a valid amount of data. */
475     if (startIndex + (dataSize / 4u) >= 16u)
476     {
477         return kStatus_InvalidArgument;
478     }
479 
480     j      = 0;
481     szLeft = dataSize % 4u;
482     for (i = (uint32_t)startIndex; i < ((uint32_t)startIndex + (uint32_t)dataSize / 4u); i++)
483     {
484         ltc_set_unaligned_from_word(base->CTX[i], &dest[j]);
485         j += (int32_t)sizeof(uint32_t);
486     }
487 
488     if (0U != szLeft)
489     {
490         rdCtx = base->CTX[i];
491         ltc_memcpy(&dest[j], &rdCtx, (uint32_t)szLeft);
492     }
493     return kStatus_Success;
494 }
495 
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)496 static status_t ltc_symmetric_alg_state(LTC_Type *base,
497                                         const uint8_t *key,
498                                         uint8_t keySize,
499                                         ltc_algorithm_t alg,
500                                         ltc_mode_symmetric_alg_t mode,
501                                         ltc_mode_encrypt_t enc,
502                                         ltc_mode_algorithm_state_t as)
503 {
504     ltc_mode_t modeReg;
505 
506     /* Clear internal register states. */
507     base->CW = (uint32_t)kLTC_ClearAll;
508 
509     /* Set byte swap on for several registers we will be reading and writing
510      * user data to/from. */
511     base->CTL |= (uint32_t)kLTC_CtrlSwapAll;
512 
513     /* Write the key in place. */
514     ltc_set_key(base, key, keySize);
515 
516     /* Write the key size.  This must be done after writing the key, and this
517      * action locks the ability to modify the key registers. */
518     base->KS = keySize;
519 
520     /* Clear the 'done' interrupt. */
521     base->STA = (uint32_t)kLTC_StatusDoneIsr;
522 
523     /* Set the proper block and algorithm mode. */
524     modeReg = (uint32_t)alg | (uint32_t)enc | (uint32_t)as | (uint32_t)mode;
525 
526     /* Write the mode register to the hardware. */
527     base->MD = modeReg;
528 
529     return kStatus_Success;
530 }
531 
532 /*!
533  * @brief Initializes the LTC for symmetric encrypt/decrypt operation. Mode is set to UPDATE.
534  *
535  * @param base LTC peripheral base address
536  * @param key Input key to use for encryption
537  * @param keySize Size of the input key, in bytes. Must be 8, 16, 24, or 32.
538  * @param alg Symmetric algorithm
539  * @param mode Symmetric block mode
540  * @param enc Encrypt/decrypt control
541  * @return Status
542  */
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)543 status_t ltc_symmetric_update(LTC_Type *base,
544                               const uint8_t *key,
545                               uint8_t keySize,
546                               ltc_algorithm_t alg,
547                               ltc_mode_symmetric_alg_t mode,
548                               ltc_mode_encrypt_t enc)
549 {
550     return ltc_symmetric_alg_state(base, key, keySize, alg, mode, enc, kLTC_ModeUpdate);
551 }
552 
553 #if defined(FSL_FEATURE_LTC_HAS_GCM) && FSL_FEATURE_LTC_HAS_GCM
554 /*!
555  * @brief Initializes the LTC for symmetric encrypt/decrypt operation. Mode is set to FINALIZE.
556  *
557  * @param base LTC peripheral base address
558  * @param key Input key to use for encryption
559  * @param keySize Size of the input key, in bytes. Must be 8, 16, 24, or 32.
560  * @param alg Symmetric algorithm
561  * @param mode Symmetric block mode
562  * @param enc Encrypt/decrypt control
563  * @return Status
564  */
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)565 static status_t ltc_symmetric_final(LTC_Type *base,
566                                     const uint8_t *key,
567                                     uint8_t keySize,
568                                     ltc_algorithm_t alg,
569                                     ltc_mode_symmetric_alg_t mode,
570                                     ltc_mode_encrypt_t enc)
571 {
572     return ltc_symmetric_alg_state(base, key, keySize, alg, mode, enc, kLTC_ModeFinalize);
573 }
574 #endif /* FSL_FEATURE_LTC_HAS_GCM */
575 
576 /*!
577  * @brief Initializes the LTC for symmetric encrypt/decrypt operation. Mode is set to INITIALIZE.
578  *
579  * @param base LTC peripheral base address
580  * @param key Input key to use for encryption
581  * @param keySize Size of the input key, in bytes. Must be 8, 16, 24, or 32.
582  * @param alg Symmetric algorithm
583  * @param mode Symmetric block mode
584  * @param enc Encrypt/decrypt control
585  * @return Status
586  */
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)587 static status_t ltc_symmetric_init(LTC_Type *base,
588                                    const uint8_t *key,
589                                    uint8_t keySize,
590                                    ltc_algorithm_t alg,
591                                    ltc_mode_symmetric_alg_t mode,
592                                    ltc_mode_encrypt_t enc)
593 {
594     return ltc_symmetric_alg_state(base, key, keySize, alg, mode, enc, kLTC_ModeInit);
595 }
596 
597 /*!
598  * @brief Initializes the LTC for symmetric encrypt/decrypt operation. Mode is set to INITIALIZE/FINALIZE.
599  *
600  * @param base LTC peripheral base address
601  * @param key Input key to use for encryption
602  * @param keySize Size of the input key, in bytes. Must be 8, 16, 24, or 32.
603  * @param alg Symmetric algorithm
604  * @param mode Symmetric block mode
605  * @param enc Encrypt/decrypt control
606  * @return Status
607  */
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)608 static status_t ltc_symmetric_init_final(LTC_Type *base,
609                                          const uint8_t *key,
610                                          uint8_t keySize,
611                                          ltc_algorithm_t alg,
612                                          ltc_mode_symmetric_alg_t mode,
613                                          ltc_mode_encrypt_t enc)
614 {
615     return ltc_symmetric_alg_state(base, key, keySize, alg, mode, enc, kLTC_ModeInitFinal);
616 }
617 
ltc_symmetric_process(LTC_Type * base,uint32_t inSize,const uint8_t ** inData,uint8_t ** outData)618 void ltc_symmetric_process(LTC_Type *base, uint32_t inSize, const uint8_t **inData, uint8_t **outData)
619 {
620     uint32_t outSize;
621     uint32_t fifoData;
622     uint32_t fifoStatus;
623 
624     register const uint8_t *in = *inData;
625     register uint8_t *out      = *outData;
626 
627     outSize = inSize;
628     while ((outSize > 0u) || (inSize > 0u))
629     {
630         fifoStatus = base->FIFOSTA;
631 
632         /* Check output FIFO level to make sure there is at least an entry
633          * ready to be read. */
634         if (0U != (fifoStatus & LTC_FIFOSTA_OFL_MASK))
635         {
636             /* Read data from the output FIFO. */
637             if (outSize > 0u)
638             {
639                 if (outSize >= sizeof(uint32_t))
640                 {
641                     ltc_set_unaligned_from_word(base->OFIFO, out);
642                     out = &out[sizeof(uint32_t)];
643                     outSize -= sizeof(uint32_t);
644                 }
645                 else /* (outSize > 0) && (outSize < 4) */
646                 {
647                     fifoData = base->OFIFO;
648                     ltc_memcpy(out, &fifoData, outSize);
649                     out     = &out[outSize];
650                     outSize = 0;
651                 }
652             }
653         }
654 
655         /* Check input FIFO status to see if it is full.  We can
656          * only write more data when both input and output FIFOs are not at a full state.
657          * At the same time we are sure Output FIFO is not full because we have poped at least one entry
658          * by the while loop above.
659          */
660         if (0U == (fifoStatus & LTC_FIFOSTA_IFF_MASK))
661         {
662             /* Copy data to the input FIFO.
663              * Data can only be copied one word at a time, so pad the data
664              * appropriately if it is less than this size. */
665             if (inSize > 0u)
666             {
667                 if (inSize >= sizeof(uint32_t))
668                 {
669                     base->IFIFO = ltc_get_word_from_unaligned(in);
670                     inSize -= sizeof(uint32_t);
671                     in = &in[sizeof(uint32_t)];
672                 }
673                 else /* (inSize > 0) && (inSize < 4) */
674                 {
675                     fifoData = 0;
676                     ltc_memcpy(&fifoData, in, inSize);
677                     base->IFIFO = fifoData;
678                     in          = &in[inSize];
679                     inSize      = 0;
680                 }
681             }
682         }
683     }
684     *inData  = in;
685     *outData = out;
686 }
687 
688 /*!
689  * @brief Processes symmetric data through LTC AES and DES engines.
690  *
691  * @param base LTC peripheral base address
692  * @param inData Input data
693  * @param inSize Size of input data, in bytes
694  * @param outData Output data
695  * @return Status from encrypt/decrypt operation
696  */
ltc_symmetric_process_data(LTC_Type * base,const uint8_t * inData,uint32_t inSize,uint8_t * outData)697 status_t ltc_symmetric_process_data(LTC_Type *base, const uint8_t *inData, uint32_t inSize, uint8_t *outData)
698 {
699     uint32_t lastSize;
700 
701     if ((NULL == inData) || (NULL == outData))
702     {
703         return kStatus_InvalidArgument;
704     }
705 
706     /* Write the data size. */
707     base->DS = inSize;
708 
709     /* Split the inSize into full 16-byte chunks and last incomplete block due to LTC AES OFIFO errata */
710     if (inSize <= 16u)
711     {
712         lastSize = inSize;
713         inSize   = 0;
714     }
715     else
716     {
717         /* Process all 16-byte data chunks. */
718         lastSize = inSize % 16u;
719         if (lastSize == 0u)
720         {
721             lastSize = 16;
722             inSize -= 16u;
723         }
724         else
725         {
726             inSize -= lastSize; /* inSize will be rounded down to 16 byte boundary. remaining bytes in lastSize */
727         }
728     }
729 
730     ltc_symmetric_process(base, inSize, &inData, &outData);
731     ltc_symmetric_process(base, lastSize, &inData, &outData);
732     return ltc_wait(base);
733 }
734 
735 /*!
736  * @brief Splits the LTC job into sessions. Used for CBC, CTR, CFB, OFB cipher block modes.
737  *
738  * @param base LTC peripheral base address
739  * @param inData Input data to process.
740  * @param inSize Input size of the input buffer.
741  * @param outData Output data buffer.
742  */
ltc_process_message_in_sessions(LTC_Type * base,const uint8_t * inData,uint32_t inSize,uint8_t * outData)743 static status_t ltc_process_message_in_sessions(LTC_Type *base,
744                                                 const uint8_t *inData,
745                                                 uint32_t inSize,
746                                                 uint8_t *outData)
747 {
748     uint32_t sz;
749     status_t retval;
750     ltc_mode_t modeReg; /* read and write LTC mode register */
751 
752     sz = LTC_FIFO_SZ_MAX_DOWN_ALGN;
753 
754     /* modeReg value will be used if message is split into multiple LTC_FIFO_SZ_MAX_DOWN_ALGN chunks */
755     /* in case of AES CBC and AES ECB decryption */
756     /* the conversion of AES forward key to AES reverse key happens with the 1st chunk */
757     /* so all the following chunks already have the reverse key */
758     /* thus we add the MD register bit 12 to the MD value to notify the AES engine
759        that the key is the AES reverse key */
760     /* This really needs to be done only for AES ECB and CBC Decrypt as these are the only */
761     /* cipher block modes that use AES reverse key */
762     modeReg = base->MD;
763     /* AES CBC Decrypt */
764     if (modeReg == 0x00100100u)
765     {
766         /* add MSB of AAI - DK (Decrypt Key) bit */
767         modeReg = 0x00101100u;
768     }
769     /* AES ECB Decrypt */
770     if (modeReg == 0x00100200u)
771     {
772         /* add MSB of AAI - DK (Decrypt Key) bit */
773         modeReg = 0x00101200u;
774     }
775 
776     retval = kStatus_Success;
777 
778     while (0U != inSize)
779     {
780         if (inSize <= sz)
781         {
782             retval = ltc_symmetric_process_data(base, inData, inSize, outData);
783             if (kStatus_Success != retval)
784             {
785                 return retval;
786             }
787             inSize = 0;
788         }
789         else
790         {
791             retval = ltc_symmetric_process_data(base, inData, sz, outData);
792             if (kStatus_Success != retval)
793             {
794                 return retval;
795             }
796             inData = &inData[sz];
797             inSize -= sz;
798             outData  = &outData[sz];
799             base->MD = modeReg;
800         }
801     }
802     return retval;
803 }
804 
ltc_move_block_to_ififo(LTC_Type * base,const ltc_xcm_block_t * blk,uint32_t num_bytes)805 static void ltc_move_block_to_ififo(LTC_Type *base, const ltc_xcm_block_t *blk, uint32_t num_bytes)
806 {
807     uint32_t i = 0;
808     uint32_t words;
809 
810     words = num_bytes / 4u;
811     if (0U != (num_bytes % 4u))
812     {
813         words++;
814     }
815 
816     if (words > 4u)
817     {
818         words = 4;
819     }
820 
821     while (i < words)
822     {
823         if (0U == (base->FIFOSTA & LTC_FIFOSTA_IFF_MASK))
824         {
825             /* Copy data to the input FIFO. */
826             base->IFIFO = blk->w[i++];
827         }
828     }
829 }
830 
ltc_move_to_ififo(LTC_Type * base,const uint8_t * data,uint32_t dataSize)831 static void ltc_move_to_ififo(LTC_Type *base, const uint8_t *data, uint32_t dataSize)
832 {
833     ltc_xcm_block_t blk;
834     ltc_xcm_block_t blkZero = {{0x0u, 0x0u, 0x0u, 0x0u}};
835 
836     while (0U != dataSize)
837     {
838         if (dataSize > 16u)
839         {
840             ltc_memcpy(&blk, data, 16u);
841             dataSize -= 16u;
842             data = &data[16];
843         }
844         else
845         {
846             ltc_memcpy(&blk, &blkZero, sizeof(ltc_xcm_block_t)); /* memset blk to zeroes */
847             ltc_memcpy(&blk, data, dataSize);
848             dataSize = 0;
849         }
850         ltc_move_block_to_ififo(base, (const ltc_xcm_block_t *)(uint32_t)&blk, sizeof(ltc_xcm_block_t));
851     }
852 }
853 
854 /*!
855  * @brief Processes symmetric data through LTC AES in multiple sessions.
856  *
857  * Specific for AES CCM and GCM modes as they need to update mode register.
858  *
859  * @param base LTC peripheral base address
860  * @param inData Input data
861  * @param inSize Size of input data, in bytes
862  * @param outData Output data
863  * @param lastAs The LTC Algorithm state to be set sup for last block during message processing in multiple sessions.
864  *               For CCM it is kLTC_ModeFinalize. For GCM it is kLTC_ModeInitFinal.
865  * @return Status from encrypt/decrypt operation
866  */
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)867 static status_t ltc_symmetric_process_data_multiple(LTC_Type *base,
868                                                     const uint8_t *inData,
869                                                     uint32_t inSize,
870                                                     uint8_t *outData,
871                                                     ltc_mode_t modeReg,
872                                                     ltc_mode_algorithm_state_t lastAs)
873 {
874     uint32_t fifoConsumed;
875     uint32_t lastSize;
876     uint32_t sz;
877     uint32_t max_ltc_fifo_size;
878     ltc_mode_algorithm_state_t fsm;
879     status_t status;
880 
881     if ((NULL == inData) || (NULL == outData))
882     {
883         return kStatus_InvalidArgument;
884     }
885 
886     if (!(((uint8_t)kLTC_ModeFinalize == (uint8_t)lastAs) || ((uint8_t)kLTC_ModeInitFinal == (uint8_t)lastAs)))
887     {
888         return kStatus_InvalidArgument;
889     }
890 
891     if (0u == inSize)
892     {
893         return kStatus_Success;
894     }
895 
896     if (inSize <= 16u)
897     {
898         fsm      = lastAs;
899         lastSize = inSize;
900     }
901     else
902     {
903         fsm = (ltc_mode_algorithm_state_t)(uint32_t)(
904             modeReg &
905             LTC_MD_AS_MASK); /* this will be either kLTC_ModeInit or kLTC_ModeUpdate, based on prior processing */
906 
907         /* Process all 16-byte data chunks. */
908         lastSize = inSize % 16u;
909         if (lastSize == 0u)
910         {
911             lastSize = 16u;
912             inSize -= 16u;
913         }
914         else
915         {
916             inSize -= lastSize; /* inSize will be rounded down to 16 byte boundary. remaining bytes in lastSize */
917         }
918     }
919 
920     max_ltc_fifo_size = LTC_FIFO_SZ_MAX_DOWN_ALGN;
921     fifoConsumed      = base->DS;
922 
923     while (0U != lastSize)
924     {
925         if ((fsm == kLTC_ModeUpdate) || (fsm == kLTC_ModeInit))
926         {
927             while (0U != inSize)
928             {
929                 if (inSize > (max_ltc_fifo_size - fifoConsumed))
930                 {
931                     sz = (max_ltc_fifo_size - fifoConsumed);
932                 }
933                 else
934                 {
935                     sz = inSize;
936                 }
937                 base->DS = sz;
938                 ltc_symmetric_process(base, sz, &inData, &outData);
939                 inSize -= sz;
940                 fifoConsumed = 0;
941 
942                 /* after we completed INITIALIZE job, are there still any data left? */
943                 if (0U != inSize)
944                 {
945                     fsm    = kLTC_ModeUpdate;
946                     status = ltc_wait(base);
947                     if (kStatus_Success != status)
948                     {
949                         return status;
950                     }
951                     modeReg &= ~LTC_MD_AS_MASK;
952                     modeReg |= (uint32_t)fsm;
953                     base->MD = modeReg;
954                 }
955                 else
956                 {
957                     fsm = lastAs;
958                 }
959             }
960         }
961 
962         else if ((fsm == kLTC_ModeFinalize) || (fsm == kLTC_ModeInitFinal))
963         {
964             /* process last block in FINALIZE */
965 
966             status = ltc_wait(base);
967             if (kStatus_Success != status)
968             {
969                 return status;
970             }
971 
972             modeReg &= ~LTC_MD_AS_MASK;
973             modeReg |= (uint32_t)lastAs;
974             base->MD = modeReg;
975 
976             base->DS = lastSize;
977             ltc_symmetric_process(base, lastSize, &inData, &outData);
978             lastSize = 0;
979         }
980         else
981         {
982             /*do nothing*/
983         }
984     }
985 
986     status = ltc_wait(base);
987     return status;
988 }
989 
990 /*!
991  * @brief Receives MAC compare.
992  *
993  * This function is a sub-process of CCM and GCM decryption.
994  * It compares received MAC with the MAC computed during decryption.
995  *
996  * @param base LTC peripheral base address
997  * @param tag Received MAC.
998  * @param tagSize Number of bytes in the received MAC.
999  * @param modeReg LTC Mode Register current value. It is modified and written to LTC Mode Register.
1000  */
ltc_aes_received_mac_compare(LTC_Type * base,const uint8_t * tag,uint32_t tagSize,ltc_mode_t modeReg)1001 static status_t ltc_aes_received_mac_compare(LTC_Type *base, const uint8_t *tag, uint32_t tagSize, ltc_mode_t modeReg)
1002 {
1003     ltc_xcm_block_t blk = {{0x0u, 0x0u, 0x0u, 0x0u}};
1004 
1005     base->CW  = (uint32_t)kLTC_ClearDataSize;
1006     base->STA = (uint32_t)kLTC_StatusDoneIsr;
1007 
1008     modeReg &= ~LTC_MD_AS_MASK;
1009     modeReg |= (uint32_t)kLTC_ModeUpdate | LTC_MD_ICV_TEST_MASK;
1010     base->MD = modeReg;
1011 
1012     base->DS   = 0u;
1013     base->ICVS = tagSize;
1014     ltc_memcpy(&blk.b[0], &tag[0], tagSize);
1015 
1016     ltc_move_block_to_ififo(base, (const ltc_xcm_block_t *)(uint32_t)&blk, tagSize);
1017     return ltc_wait(base);
1018 }
1019 
1020 /*!
1021  * @brief Processes tag during AES GCM and CCM.
1022  *
1023  * This function is a sub-process of CCM and GCM encryption and decryption.
1024  * For encryption, it writes computed MAC to the output tag.
1025  * For decryption, it compares the received MAC with the computed MAC.
1026  *
1027  * @param base LTC peripheral base address
1028  * @param[in,out] tag Output computed MAC during encryption or Input received MAC during decryption.
1029  * @param tagSize Size of MAC buffer in bytes.
1030  * @param modeReg LTC Mode Register current value. It is checked to read Enc/Dec bit.
1031  *                 It is modified and written to LTC Mode Register during decryption.
1032  * @param ctx Index to LTC context registers with computed MAC for encryption process.
1033  */
ltc_aes_process_tag(LTC_Type * base,uint8_t * tag,uint32_t tagSize,ltc_mode_t modeReg,uint32_t ctx)1034 static status_t ltc_aes_process_tag(LTC_Type *base, uint8_t *tag, uint32_t tagSize, ltc_mode_t modeReg, uint32_t ctx)
1035 {
1036     status_t status = kStatus_Success;
1037     if (NULL != tag)
1038     {
1039         /* For decrypt, compare received MAC with the computed MAC. */
1040         if ((uint32_t)kLTC_ModeDecrypt == (modeReg & LTC_MD_ENC_MASK))
1041         {
1042             status = ltc_aes_received_mac_compare(base, tag, tagSize, modeReg);
1043         }
1044         else /* FSL_AES_GCM_TYPE_ENCRYPT */
1045         {
1046             /* For encryption, write the computed and encrypted MAC to user buffer */
1047             status = ltc_get_context(base, &tag[0], (uint8_t)tagSize, (uint8_t)ctx);
1048         }
1049     }
1050     return status;
1051 }
1052 
1053 /*******************************************************************************
1054  * LTC Common code public
1055  ******************************************************************************/
1056 /*!
1057  * brief Initializes the LTC driver.
1058  * This function initializes the LTC driver.
1059  * param base LTC peripheral base address
1060  */
LTC_Init(LTC_Type * base)1061 void LTC_Init(LTC_Type *base)
1062 {
1063 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
1064 #if !(defined(FSL_FEATURE_LTC_HAS_NO_CLOCK_CONTROL_BIT) && FSL_FEATURE_LTC_HAS_NO_CLOCK_CONTROL_BIT)
1065     /* ungate clock */
1066     CLOCK_EnableClock(kCLOCK_Ltc0);
1067 #endif /* FSL_FEATURE_LTC_HAS_NO_CLOCK_CONTROL_BIT */
1068 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
1069 }
1070 
1071 /*!
1072  * brief Deinitializes the LTC driver.
1073  * This function deinitializes the LTC driver.
1074  * param base LTC peripheral base address
1075  */
LTC_Deinit(LTC_Type * base)1076 void LTC_Deinit(LTC_Type *base)
1077 {
1078 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
1079 #if !(defined(FSL_FEATURE_LTC_HAS_NO_CLOCK_CONTROL_BIT) && FSL_FEATURE_LTC_HAS_NO_CLOCK_CONTROL_BIT)
1080     /* gate clock */
1081     CLOCK_DisableClock(kCLOCK_Ltc0);
1082 #endif /* FSL_FEATURE_LTC_HAS_NO_CLOCK_CONTROL_BIT */
1083 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
1084 }
1085 
1086 #if defined(FSL_FEATURE_LTC_HAS_DPAMS) && FSL_FEATURE_LTC_HAS_DPAMS
1087 /*!
1088  * brief Sets the DPA Mask Seed register.
1089  *
1090  * The DPA Mask Seed register reseeds the mask that provides resistance against DPA (differential power analysis)
1091  * attacks on AES or DES keys.
1092  *
1093  * Differential Power Analysis Mask (DPA) resistance uses a randomly changing mask that introduces
1094  * "noise" into the power consumed by the AES or DES. This reduces the signal-to-noise ratio that differential
1095  * power analysis attacks use to "guess" bits of the key. This randomly changing mask should be
1096  * seeded at POR, and continues to provide DPA resistance from that point on. However, to provide even more
1097  * DPA protection it is recommended that the DPA mask be reseeded after every 50,000 blocks have
1098  * been processed. At that time, software can opt to write a new seed (preferably obtained from an RNG)
1099  * into the DPA Mask Seed register (DPAMS), or software can opt to provide the new seed earlier or
1100  * later, or not at all. DPA resistance continues even if the DPA mask is never reseeded.
1101  *
1102  * param base LTC peripheral base address
1103  * param mask The DPA mask seed.
1104  */
LTC_SetDpaMaskSeed(LTC_Type * base,uint32_t mask)1105 void LTC_SetDpaMaskSeed(LTC_Type *base, uint32_t mask)
1106 {
1107     base->DPAMS = mask;
1108     /* second write as workaround for DPA mask re-seed errata */
1109     base->DPAMS = mask;
1110 }
1111 #endif /* FSL_FEATURE_LTC_HAS_DPAMS */
1112 
1113 /*******************************************************************************
1114  * AES Code static
1115  ******************************************************************************/
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)1116 static status_t ltc_aes_decrypt_ecb(LTC_Type *base,
1117                                     const uint8_t *ciphertext,
1118                                     uint8_t *plaintext,
1119                                     uint32_t size,
1120                                     const uint8_t *key,
1121                                     uint32_t keySize,
1122                                     ltc_aes_key_t keyType)
1123 {
1124     status_t retval;
1125 
1126     /* Initialize algorithm state. */
1127     retval = ltc_symmetric_update(base, key, (uint8_t)keySize, kLTC_AlgorithmAES, kLTC_ModeECB, kLTC_ModeDecrypt);
1128     if (kStatus_Success != retval)
1129     {
1130         return retval;
1131     }
1132 
1133     /* set DK bit in the LTC Mode Register AAI field for directly loaded decrypt keys */
1134     if (keyType == kLTC_DecryptKey)
1135     {
1136         uint32_t u32mask = 1;
1137         base->MD |= (u32mask << (uint32_t)kLTC_ModeRegBitShiftDK);
1138     }
1139 
1140     /* Process data and return status. */
1141     retval = ltc_process_message_in_sessions(base, &ciphertext[0], size, &plaintext[0]);
1142     return retval;
1143 }
1144 
1145 /*******************************************************************************
1146  * AES Code public
1147  ******************************************************************************/
1148 /*!
1149  * brief Transforms an AES encrypt key (forward AES) into the decrypt key (inverse AES).
1150  *
1151  * Transforms the AES encrypt key (forward AES) into the decrypt key (inverse AES).
1152  * The key derived by this function can be used as a direct load decrypt key
1153  * for AES ECB and CBC decryption operations (keyType argument).
1154  *
1155  * param base LTC peripheral base address
1156  * param encryptKey Input key for decrypt key transformation
1157  * param[out] decryptKey Output key, the decrypt form of the AES key.
1158  * param keySize Size of the input key and output key in bytes. Must be 16, 24, or 32.
1159  * return Status from key generation operation
1160  */
LTC_AES_GenerateDecryptKey(LTC_Type * base,const uint8_t * encryptKey,uint8_t * decryptKey,uint32_t keySize)1161 status_t LTC_AES_GenerateDecryptKey(LTC_Type *base, const uint8_t *encryptKey, uint8_t *decryptKey, uint32_t keySize)
1162 {
1163     uint8_t plaintext[LTC_AES_BLOCK_SIZE]  = {0};
1164     uint8_t ciphertext[LTC_AES_BLOCK_SIZE] = {0};
1165     status_t status;
1166 
1167     if (!ltc_check_key_size(keySize))
1168     {
1169         return kStatus_InvalidArgument;
1170     }
1171 
1172     /* ECB decrypt with encrypt key will convert the key in LTC context into decrypt form of the key */
1173     status = ltc_aes_decrypt_ecb(base, ciphertext, plaintext, LTC_AES_BLOCK_SIZE, encryptKey, keySize, kLTC_EncryptKey);
1174     /* now there is decrypt form of the key in the LTC context, so take it */
1175     ltc_get_key(base, decryptKey, (uint8_t)keySize);
1176 
1177     ltc_clear_all(base, false);
1178 
1179     return status;
1180 }
1181 
1182 /*!
1183  * brief Encrypts AES using the ECB block mode.
1184  *
1185  * Encrypts AES using the ECB block mode.
1186  *
1187  * param base LTC peripheral base address
1188  * param plaintext Input plain text to encrypt
1189  * param[out] ciphertext Output cipher text
1190  * param size Size of input and output data in bytes. Must be multiple of 16 bytes.
1191  * param key Input key to use for encryption
1192  * param keySize Size of the input key, in bytes. Must be 16, 24, or 32.
1193  * return Status from encrypt operation
1194  */
LTC_AES_EncryptEcb(LTC_Type * base,const uint8_t * plaintext,uint8_t * ciphertext,uint32_t size,const uint8_t * key,uint32_t keySize)1195 status_t LTC_AES_EncryptEcb(
1196     LTC_Type *base, const uint8_t *plaintext, uint8_t *ciphertext, uint32_t size, const uint8_t *key, uint32_t keySize)
1197 {
1198     status_t retval;
1199 
1200     if (!ltc_check_key_size(keySize))
1201     {
1202         return kStatus_InvalidArgument;
1203     }
1204     /* ECB mode, size must be 16-byte multiple */
1205     if ((size < 16u) || (0U != (size % 16u)))
1206     {
1207         return kStatus_InvalidArgument;
1208     }
1209 
1210     /* Initialize algorithm state. */
1211     retval = ltc_symmetric_update(base, key, (uint8_t)keySize, kLTC_AlgorithmAES, kLTC_ModeECB, kLTC_ModeEncrypt);
1212     if (kStatus_Success != retval)
1213     {
1214         return retval;
1215     }
1216 
1217     /* Process data and return status. */
1218     retval = ltc_process_message_in_sessions(base, &plaintext[0], size, &ciphertext[0]);
1219     ltc_clear_all(base, false);
1220     return retval;
1221 }
1222 
1223 /*!
1224  * brief Decrypts AES using ECB block mode.
1225  *
1226  * Decrypts AES using ECB block mode.
1227  *
1228  * param base LTC peripheral base address
1229  * param ciphertext Input cipher text to decrypt
1230  * param[out] plaintext Output plain text
1231  * param size Size of input and output data in bytes. Must be multiple of 16 bytes.
1232  * param key Input key.
1233  * param keySize Size of the input key, in bytes. Must be 16, 24, or 32.
1234  * param keyType Input type of the key (allows to directly load decrypt key for AES ECB decrypt operation.)
1235  * return Status from decrypt operation
1236  */
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)1237 status_t LTC_AES_DecryptEcb(LTC_Type *base,
1238                             const uint8_t *ciphertext,
1239                             uint8_t *plaintext,
1240                             uint32_t size,
1241                             const uint8_t *key,
1242                             uint32_t keySize,
1243                             ltc_aes_key_t keyType)
1244 {
1245     status_t status;
1246 
1247     if (!ltc_check_key_size(keySize))
1248     {
1249         return kStatus_InvalidArgument;
1250     }
1251     /* ECB mode, size must be 16-byte multiple */
1252     if ((size < 16u) || (0U != (size % 16u)))
1253     {
1254         return kStatus_InvalidArgument;
1255     }
1256 
1257     status = ltc_aes_decrypt_ecb(base, ciphertext, plaintext, size, key, keySize, keyType);
1258     ltc_clear_all(base, false);
1259     return status;
1260 }
1261 
1262 /*!
1263  * brief Encrypts AES using CBC block mode.
1264  *
1265  * param base LTC peripheral base address
1266  * param plaintext Input plain text to encrypt
1267  * param[out] ciphertext Output cipher text
1268  * param size Size of input and output data in bytes. Must be multiple of 16 bytes.
1269  * param iv Input initial vector to combine with the first input block.
1270  * param key Input key to use for encryption
1271  * param keySize Size of the input key, in bytes. Must be 16, 24, or 32.
1272  * return Status from encrypt operation
1273  */
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)1274 status_t LTC_AES_EncryptCbc(LTC_Type *base,
1275                             const uint8_t *plaintext,
1276                             uint8_t *ciphertext,
1277                             uint32_t size,
1278                             const uint8_t iv[LTC_AES_IV_SIZE],
1279                             const uint8_t *key,
1280                             uint32_t keySize)
1281 {
1282     status_t retval;
1283 
1284     if (!ltc_check_key_size(keySize))
1285     {
1286         return kStatus_InvalidArgument;
1287     }
1288 
1289     /* CBC mode, size must be 16-byte multiple */
1290     if ((size < 16u) || (0U != (size % 16u)))
1291     {
1292         return kStatus_InvalidArgument;
1293     }
1294 
1295     /* Initialize algorithm state. */
1296     retval = ltc_symmetric_update(base, key, (uint8_t)keySize, kLTC_AlgorithmAES, kLTC_ModeCBC, kLTC_ModeEncrypt);
1297     if (kStatus_Success != retval)
1298     {
1299         return retval;
1300     }
1301 
1302     /* Write IV data to the context register. */
1303     retval = ltc_set_context(base, &iv[0], LTC_AES_IV_SIZE, 0);
1304     if (kStatus_Success != retval)
1305     {
1306         return retval;
1307     }
1308 
1309     /* Process data and return status. */
1310     retval = ltc_process_message_in_sessions(base, &plaintext[0], size, &ciphertext[0]);
1311     ltc_clear_all(base, false);
1312     return retval;
1313 }
1314 
1315 /*!
1316  * brief Decrypts AES using CBC block mode.
1317  *
1318  * param base LTC peripheral base address
1319  * param ciphertext Input cipher text to decrypt
1320  * param[out] plaintext Output plain text
1321  * param size Size of input and output data in bytes. Must be multiple of 16 bytes.
1322  * param iv Input initial vector to combine with the first input block.
1323  * param key Input key to use for decryption
1324  * param keySize Size of the input key, in bytes. Must be 16, 24, or 32.
1325  * param keyType Input type of the key (allows to directly load decrypt key for AES CBC decrypt operation.)
1326  * return Status from decrypt operation
1327  */
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)1328 status_t LTC_AES_DecryptCbc(LTC_Type *base,
1329                             const uint8_t *ciphertext,
1330                             uint8_t *plaintext,
1331                             uint32_t size,
1332                             const uint8_t iv[LTC_AES_IV_SIZE],
1333                             const uint8_t *key,
1334                             uint32_t keySize,
1335                             ltc_aes_key_t keyType)
1336 {
1337     status_t retval;
1338 
1339     if (!ltc_check_key_size(keySize))
1340     {
1341         return kStatus_InvalidArgument;
1342     }
1343     /* CBC mode, size must be 16-byte multiple */
1344     if ((size < 16u) || (0U != (size % 16u)))
1345     {
1346         return kStatus_InvalidArgument;
1347     }
1348 
1349     /* Initialize algorithm state. */
1350     retval = ltc_symmetric_update(base, key, (uint8_t)keySize, kLTC_AlgorithmAES, kLTC_ModeCBC, kLTC_ModeDecrypt);
1351     if (kStatus_Success != retval)
1352     {
1353         return retval;
1354     }
1355 
1356     /* Write IV data to the context register. */
1357     retval = ltc_set_context(base, &iv[0], LTC_AES_IV_SIZE, 0);
1358     if (kStatus_Success != retval)
1359     {
1360         return retval;
1361     }
1362 
1363     /* set DK bit in the LTC Mode Register AAI field for directly loaded decrypt keys */
1364     if (keyType == kLTC_DecryptKey)
1365     {
1366         uint32_t u32mask = 1;
1367         base->MD |= (u32mask << (uint8_t)kLTC_ModeRegBitShiftDK);
1368     }
1369 
1370     /* Process data and return status. */
1371     retval = ltc_process_message_in_sessions(base, &ciphertext[0], size, &plaintext[0]);
1372     ltc_clear_all(base, false);
1373     return retval;
1374 }
1375 
1376 /*!
1377  * brief Encrypts or decrypts AES using CTR block mode.
1378  *
1379  * Encrypts or decrypts AES using CTR block mode.
1380  * AES CTR mode uses only forward AES cipher and same algorithm for encryption and decryption.
1381  * The only difference between encryption and decryption is that, for encryption, the input argument
1382  * is plain text and the output argument is cipher text. For decryption, the input argument is cipher text
1383  * and the output argument is plain text.
1384  *
1385  * param base LTC peripheral base address
1386  * param input Input data for CTR block mode
1387  * param[out] output Output data for CTR block mode
1388  * param size Size of input and output data in bytes
1389  * param[in,out] counter Input counter (updates on return)
1390  * param key Input key to use for forward AES cipher
1391  * param keySize Size of the input key, in bytes. Must be 16, 24, or 32.
1392  * param[out] counterlast Output cipher of last counter, for chained CTR calls. NULL can be passed if chained calls are
1393  * not used.
1394  * param[out] szLeft Output number of bytes in left unused in counterlast block. NULL can be passed if chained calls
1395  * are not used.
1396  * return Status from encrypt operation
1397  */
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)1398 status_t LTC_AES_CryptCtr(LTC_Type *base,
1399                           const uint8_t *input,
1400                           uint8_t *output,
1401                           uint32_t size,
1402                           uint8_t counter[LTC_AES_BLOCK_SIZE],
1403                           const uint8_t *key,
1404                           uint32_t keySize,
1405                           uint8_t counterlast[LTC_AES_BLOCK_SIZE],
1406                           uint32_t *szLeft)
1407 {
1408     status_t retval;
1409     uint32_t lastSize;
1410 
1411     if (!ltc_check_key_size(keySize))
1412     {
1413         return kStatus_InvalidArgument;
1414     }
1415 
1416     lastSize = 0U;
1417     if (counterlast != NULL)
1418     {
1419         /* Split the size into full 16-byte chunks and last incomplete block due to LTC AES OFIFO errata */
1420         if (size <= 16U)
1421         {
1422             lastSize = size;
1423             size     = 0U;
1424         }
1425         else
1426         {
1427             /* Process all 16-byte data chunks. */
1428             lastSize = size % 16U;
1429             if (lastSize == 0U)
1430             {
1431                 lastSize = 16U;
1432                 size -= 16U;
1433             }
1434             else
1435             {
1436                 size -= lastSize; /* size will be rounded down to 16 byte boundary. remaining bytes in lastSize */
1437             }
1438         }
1439     }
1440 
1441     /* Initialize algorithm state. */
1442     retval = ltc_symmetric_update(base, key, (uint8_t)keySize, kLTC_AlgorithmAES, kLTC_ModeCTR, kLTC_ModeEncrypt);
1443     if (kStatus_Success != retval)
1444     {
1445         return retval;
1446     }
1447 
1448     /* Write initial counter data to the context register.
1449      * NOTE the counter values start at 4-bytes offset into the context. */
1450     retval = ltc_set_context(base, &counter[0], 16U, 4U);
1451     if (kStatus_Success != retval)
1452     {
1453         return retval;
1454     }
1455 
1456     /* Process data and return status. */
1457     retval = ltc_process_message_in_sessions(base, input, size, output);
1458     if (kStatus_Success != retval)
1459     {
1460         return retval;
1461     }
1462 
1463     input  = &input[size];
1464     output = &output[size];
1465 
1466     if ((counterlast != NULL) && (0U != lastSize))
1467     {
1468         uint8_t zeroes[16] = {0};
1469         ltc_mode_t modeReg;
1470 
1471         modeReg = (uint32_t)kLTC_AlgorithmAES | (uint32_t)kLTC_ModeCTR | (uint32_t)kLTC_ModeEncrypt;
1472         /* Write the mode register to the hardware. */
1473         base->MD = modeReg | (uint32_t)kLTC_ModeFinalize;
1474 
1475         /* context is re-used (CTRi) */
1476 
1477         /* Process data and return status. */
1478         retval = ltc_symmetric_process_data(base, input, lastSize, output);
1479         if (kStatus_Success != retval)
1480         {
1481             return retval;
1482         }
1483         if (NULL != szLeft)
1484         {
1485             *szLeft = 16U - lastSize;
1486         }
1487 
1488         /* Initialize algorithm state. */
1489         base->MD = modeReg | (uint32_t)kLTC_ModeUpdate;
1490 
1491         /* context is re-used (CTRi) */
1492 
1493         /* Process data and return status. */
1494         retval = ltc_symmetric_process_data(base, zeroes, 16U, counterlast);
1495     }
1496     (void)ltc_get_context(base, &counter[0], 16U, 4U);
1497     ltc_clear_all(base, false);
1498     return retval;
1499 }
1500 
1501 #if defined(FSL_FEATURE_LTC_HAS_GCM) && FSL_FEATURE_LTC_HAS_GCM
1502 /*******************************************************************************
1503  * GCM Code static
1504  ******************************************************************************/
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)1505 static status_t ltc_aes_gcm_check_input_args(LTC_Type *base,
1506                                              const uint8_t *src,
1507                                              const uint8_t *iv,
1508                                              const uint8_t *aad,
1509                                              const uint8_t *key,
1510                                              uint8_t *dst,
1511                                              uint32_t inputSize,
1512                                              uint32_t ivSize,
1513                                              uint32_t aadSize,
1514                                              uint32_t keySize,
1515                                              uint32_t tagSize)
1516 {
1517     if (NULL == base)
1518     {
1519         return kStatus_InvalidArgument;
1520     }
1521 
1522     /* tag can be NULL to skip tag processing */
1523     if ((NULL == key) || ((0U != ivSize) && (NULL == iv)) || ((0U != aadSize) && (NULL == aad)) ||
1524         ((0U != inputSize) && ((NULL == src) || (NULL == dst))))
1525     {
1526         return kStatus_InvalidArgument;
1527     }
1528 
1529     /* octet length of tag (tagSize) must be element of 4,8,12,13,14,15,16 */
1530     if (((tagSize > 16u) || (tagSize < 12u)) && (tagSize != 4u) && (tagSize != 8u))
1531     {
1532         return kStatus_InvalidArgument;
1533     }
1534 
1535     /* check if keySize is supported */
1536     if (!ltc_check_key_size(keySize))
1537     {
1538         return kStatus_InvalidArgument;
1539     }
1540 
1541     /* no IV AAD DATA makes no sense */
1542     if (0U == (inputSize + ivSize + aadSize))
1543     {
1544         return kStatus_InvalidArgument;
1545     }
1546 
1547     return kStatus_Success;
1548 }
1549 
1550 /*!
1551  * @brief Process Wrapper for void (*pfunc)(LTC_Type*, uint32_t, bool). Sets IV Size register.
1552  */
ivsize_next(LTC_Type * base,uint32_t ivSize,bool iv_only)1553 static void ivsize_next(LTC_Type *base, uint32_t ivSize, bool iv_only)
1554 {
1555     base->IVSZ = LTC_IVSZ_IL(iv_only) | ((ivSize)&LTC_DS_DS_MASK);
1556 }
1557 
1558 /*!
1559  * @brief Process Wrapper for void (*pfunc)(LTC_Type*, uint32_t, bool). Sets AAD Size register.
1560  */
aadsize_next(LTC_Type * base,uint32_t aadSize,bool aad_only)1561 static void aadsize_next(LTC_Type *base, uint32_t aadSize, bool aad_only)
1562 {
1563     base->AADSZ = LTC_AADSZ_AL(aad_only) | ((aadSize)&LTC_DS_DS_MASK);
1564 }
1565 
1566 /*!
1567  * @brief Process IV or AAD string in multi-session.
1568  *
1569  * @param base LTC peripheral base address
1570  * @param iv IV or AAD data
1571  * @param ivSize Size in bytes of IV or AAD data
1572  * @param modeReg LTC peripheral Mode register value
1573  * @param iv_only IV only or AAD only flag
1574  * @param type selects between IV or AAD
1575  */
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)1576 static status_t ltc_aes_gcm_process_iv_aad(
1577     LTC_Type *base, const uint8_t *iv, uint32_t ivSize, ltc_mode_t modeReg, bool iv_only, int type, ltc_mode_t modeLast)
1578 {
1579     uint32_t sz;
1580     status_t retval;
1581     void (*next_size_func)(LTC_Type * ltcBase, uint32_t nextSize, bool authOnly);
1582 
1583     if ((NULL == iv) || (ivSize == 0U))
1584     {
1585         return kStatus_InvalidArgument;
1586     }
1587 
1588     sz             = LTC_FIFO_SZ_MAX_DOWN_ALGN;
1589     next_size_func = type == LTC_AES_GCM_TYPE_AAD ? aadsize_next : ivsize_next;
1590 
1591     while (0U != ivSize)
1592     {
1593         if (ivSize < sz)
1594         {
1595             modeReg &= ~LTC_MD_AS_MASK;
1596             modeReg |= modeLast;
1597             base->MD = modeReg;
1598             next_size_func(base, ivSize, iv_only);
1599             ltc_move_to_ififo(base, iv, ivSize);
1600             ivSize = 0;
1601         }
1602         else
1603         {
1604             /* set algorithm state to UPDATE */
1605             modeReg &= ~LTC_MD_AS_MASK;
1606             modeReg |= (uint32_t)kLTC_ModeUpdate;
1607             base->MD = modeReg;
1608 
1609             next_size_func(base, (uint16_t)sz, true);
1610             ltc_move_to_ififo(base, iv, sz);
1611             ivSize -= sz;
1612             iv += sz;
1613         }
1614 
1615         retval = ltc_wait(base);
1616         if (kStatus_Success != retval)
1617         {
1618             return retval;
1619         }
1620     } /* end while */
1621     return kStatus_Success;
1622 }
1623 
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)1624 static status_t ltc_aes_gcm_process(LTC_Type *base,
1625                                     ltc_mode_encrypt_t encryptMode,
1626                                     const uint8_t *src,
1627                                     uint32_t inputSize,
1628                                     const uint8_t *iv,
1629                                     uint32_t ivSize,
1630                                     const uint8_t *aad,
1631                                     uint32_t aadSize,
1632                                     const uint8_t *key,
1633                                     uint32_t keySize,
1634                                     uint8_t *dst,
1635                                     uint8_t *tag,
1636                                     uint32_t tagSize)
1637 {
1638     status_t retval;          /* return value */
1639     uint32_t max_ltc_fifo_sz; /* maximum data size that we can put to LTC FIFO in one session. 12-bit limit. */
1640     ltc_mode_t modeReg;       /* read and write LTC mode register */
1641 
1642     bool single_ses_proc_all; /* iv, aad and src data can be processed in one session */
1643     bool iv_only;
1644     bool aad_only;
1645 
1646     retval = ltc_aes_gcm_check_input_args(base, src, iv, aad, key, dst, inputSize, ivSize, aadSize, keySize, tagSize);
1647 
1648     /* API input validation */
1649     if (kStatus_Success != retval)
1650     {
1651         return retval;
1652     }
1653 
1654     max_ltc_fifo_sz = LTC_DS_DS_MASK; /* 12-bit field limit */
1655 
1656     /*
1657      * Write value to LTC AADSIZE (rounded up to next 16 byte boundary)
1658      * plus the write value to LTC IV (rounded up to next 16 byte boundary)
1659      * plus the inputSize. If the result is less than max_ltc_fifo_sz
1660      * then all can be processed in one session FINALIZE.
1661      * Otherwise, we have to split into multiple session, going through UPDATE(s), INITIALIZE, UPDATE(s) and FINALIZE.
1662      */
1663     single_ses_proc_all =
1664         (((aadSize + 15u) & 0xfffffff0u) + ((ivSize + 15u) & 0xfffffff0u) + inputSize) <= max_ltc_fifo_sz;
1665 
1666     /* setup key, algorithm and set the alg.state */
1667     if (single_ses_proc_all)
1668     {
1669         (void)ltc_symmetric_final(base, key, (uint8_t)keySize, kLTC_AlgorithmAES, kLTC_ModeGCM, encryptMode);
1670         modeReg = base->MD;
1671 
1672         iv_only  = (aadSize == 0U) && (inputSize == 0U);
1673         aad_only = (inputSize == 0U);
1674 
1675         /* DS_MASK here is not a bug. IV size field can be written with more than 4-bits,
1676          * as the IVSZ write value, aligned to next 16 bytes boundary, is written also to the Data Size.
1677          * For example, I can write 22 to IVSZ, 32 will be written to Data Size and IVSZ will have value 6, which is 22
1678          * mod 16.
1679          */
1680         base->IVSZ = LTC_IVSZ_IL(iv_only) | ((ivSize)&LTC_DS_DS_MASK);
1681         ltc_move_to_ififo(base, iv, ivSize);
1682         if (iv_only && ivSize != 0U)
1683         {
1684             retval = ltc_wait(base);
1685             if (kStatus_Success != retval)
1686             {
1687                 return retval;
1688             }
1689         }
1690         base->AADSZ = LTC_AADSZ_AL(aad_only) | ((aadSize)&LTC_DS_DS_MASK);
1691         ltc_move_to_ififo(base, aad, aadSize);
1692         if (aad_only && (0U != aadSize))
1693         {
1694             retval = ltc_wait(base);
1695             if (kStatus_Success != retval)
1696             {
1697                 return retval;
1698             }
1699         }
1700 
1701         if (0U != inputSize)
1702         {
1703             /* Workaround for the LTC Data Size register update errata TKT261180 */
1704             while (16U < base->DS)
1705             {
1706             }
1707 
1708             (void)ltc_symmetric_process_data(base, &src[0], inputSize, &dst[0]);
1709         }
1710     }
1711     else
1712     {
1713         retval = ltc_symmetric_init(base, key, (uint8_t)keySize, kLTC_AlgorithmAES, kLTC_ModeGCM, encryptMode);
1714         if (kStatus_Success != retval)
1715         {
1716             return retval;
1717         }
1718         modeReg = base->MD;
1719 
1720         /* process IV */
1721         if (0U != ivSize)
1722         {
1723             /* last chunk of IV is always INITIALIZE (for GHASH to occur) */
1724             retval = ltc_aes_gcm_process_iv_aad(base, iv, ivSize, modeReg, true, LTC_AES_GCM_TYPE_IV,
1725                                                 (uint32_t)kLTC_ModeInit);
1726             if (kStatus_Success != retval)
1727             {
1728                 return retval;
1729             }
1730         }
1731 
1732         /* process AAD */
1733         if (0U != aadSize)
1734         {
1735             /* AS mode to process last chunk of AAD. it differs if we are in GMAC or GCM */
1736             ltc_mode_t lastModeReg;
1737             if (0U == inputSize)
1738             {
1739                 /* if there is no DATA, set mode to compute final MAC. this is GMAC mode */
1740                 lastModeReg = (uint32_t)kLTC_ModeInitFinal;
1741             }
1742             else
1743             {
1744                 /* there are confidential DATA. so process last chunk of AAD in UPDATE mode */
1745                 lastModeReg = (uint32_t)kLTC_ModeUpdate;
1746             }
1747             retval = ltc_aes_gcm_process_iv_aad(base, aad, aadSize, modeReg, true, LTC_AES_GCM_TYPE_AAD, lastModeReg);
1748             if (kStatus_Success != retval)
1749             {
1750                 return retval;
1751             }
1752         }
1753 
1754         /* there are DATA. */
1755         if (0U != inputSize)
1756         {
1757             /* set algorithm state to UPDATE */
1758             modeReg &= ~LTC_MD_AS_MASK;
1759             modeReg |= (uint32_t)kLTC_ModeUpdate;
1760             base->MD = modeReg;
1761             retval =
1762                 ltc_symmetric_process_data_multiple(base, &src[0], inputSize, &dst[0], modeReg, kLTC_ModeInitFinal);
1763         }
1764     }
1765     if (kStatus_Success != retval)
1766     {
1767         return retval;
1768     }
1769     retval = ltc_aes_process_tag(base, tag, tagSize, modeReg, LTC_GCM_TAG_IDX);
1770     return retval;
1771 }
1772 
1773 /*******************************************************************************
1774  * GCM Code public
1775  ******************************************************************************/
1776 /*!
1777  * brief Encrypts AES and tags using GCM block mode.
1778  *
1779  * Encrypts AES and optionally tags using GCM block mode. If plaintext is NULL, only the GHASH is calculated and output
1780  * in the 'tag' field.
1781  *
1782  * param base LTC peripheral base address
1783  * param plaintext Input plain text to encrypt
1784  * param[out] ciphertext Output cipher text.
1785  * param size Size of input and output data in bytes
1786  * param iv Input initial vector
1787  * param ivSize Size of the IV
1788  * param aad Input additional authentication data
1789  * param aadSize Input size in bytes of AAD
1790  * param key Input key to use for encryption
1791  * param keySize Size of the input key, in bytes. Must be 16, 24, or 32.
1792  * param[out] tag Output hash tag. Set to NULL to skip tag processing.
1793  * param tagSize Input size of the tag to generate, in bytes. Must be 4,8,12,13,14,15 or 16.
1794  * return Status from encrypt operation
1795  */
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)1796 status_t LTC_AES_EncryptTagGcm(LTC_Type *base,
1797                                const uint8_t *plaintext,
1798                                uint8_t *ciphertext,
1799                                uint32_t size,
1800                                const uint8_t *iv,
1801                                uint32_t ivSize,
1802                                const uint8_t *aad,
1803                                uint32_t aadSize,
1804                                const uint8_t *key,
1805                                uint32_t keySize,
1806                                uint8_t *tag,
1807                                uint32_t tagSize)
1808 {
1809     status_t status;
1810 
1811     status = ltc_aes_gcm_process(base, kLTC_ModeEncrypt, plaintext, size, iv, ivSize, aad, aadSize, key, keySize,
1812                                  ciphertext, tag, tagSize);
1813 
1814     ltc_clear_all(base, false);
1815     return status;
1816 }
1817 
1818 /*!
1819  * brief Decrypts AES and authenticates using GCM block mode.
1820  *
1821  * Decrypts AES and optionally authenticates using GCM block mode. If ciphertext is NULL, only the GHASH is calculated
1822  * and compared with the received GHASH in 'tag' field.
1823  *
1824  * param base LTC peripheral base address
1825  * param ciphertext Input cipher text to decrypt
1826  * param[out] plaintext Output plain text.
1827  * param size Size of input and output data in bytes
1828  * param iv Input initial vector
1829  * param ivSize Size of the IV
1830  * param aad Input additional authentication data
1831  * param aadSize Input size in bytes of AAD
1832  * param key Input key to use for encryption
1833  * param keySize Size of the input key, in bytes. Must be 16, 24, or 32.
1834  * param tag Input hash tag to compare. Set to NULL to skip tag processing.
1835  * param tagSize Input size of the tag, in bytes. Must be 4, 8, 12, 13, 14, 15, or 16.
1836  * return Status from decrypt operation
1837  */
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)1838 status_t LTC_AES_DecryptTagGcm(LTC_Type *base,
1839                                const uint8_t *ciphertext,
1840                                uint8_t *plaintext,
1841                                uint32_t size,
1842                                const uint8_t *iv,
1843                                uint32_t ivSize,
1844                                const uint8_t *aad,
1845                                uint32_t aadSize,
1846                                const uint8_t *key,
1847                                uint32_t keySize,
1848                                const uint8_t *tag,
1849                                uint32_t tagSize)
1850 {
1851     uint8_t temp_tag[16] = {0}; /* max. octet length of Integrity Check Value ICV (tag) is 16 */
1852     uint8_t *tag_ptr;
1853     status_t status;
1854 
1855     tag_ptr = NULL;
1856     if (NULL != tag)
1857     {
1858         ltc_memcpy(temp_tag, tag, tagSize);
1859         tag_ptr = &temp_tag[0];
1860     }
1861     status = ltc_aes_gcm_process(base, kLTC_ModeDecrypt, ciphertext, size, iv, ivSize, aad, aadSize, key, keySize,
1862                                  plaintext, tag_ptr, tagSize);
1863 
1864     ltc_clear_all(base, false);
1865     return status;
1866 }
1867 #endif /* FSL_FEATURE_LTC_HAS_GCM */
1868 
1869 /*******************************************************************************
1870  * CCM Code static
1871  ******************************************************************************/
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)1872 static status_t ltc_aes_ccm_check_input_args(LTC_Type *base,
1873                                              const uint8_t *src,
1874                                              const uint8_t *iv,
1875                                              const uint8_t *key,
1876                                              uint8_t *dst,
1877                                              uint32_t ivSize,
1878                                              uint32_t aadSize,
1879                                              uint32_t keySize,
1880                                              uint32_t tagSize)
1881 {
1882     if (NULL == base)
1883     {
1884         return kStatus_InvalidArgument;
1885     }
1886 
1887     /* tag can be NULL to skip tag processing */
1888     if ((NULL == src) || (NULL == iv) || (NULL == key) || (NULL == dst))
1889     {
1890         return kStatus_InvalidArgument;
1891     }
1892 
1893     /* size of Nonce (ivSize) must be element of 7,8,9,10,11,12,13 */
1894     if ((ivSize < 7u) || (ivSize > 13u))
1895     {
1896         return kStatus_InvalidArgument;
1897     }
1898     /* octet length of MAC (tagSize) must be element of 4,6,8,10,12,14,16 for tag processing or zero to skip tag
1899      * processing */
1900     if (((tagSize > 0u) && (tagSize < 4u)) || (tagSize > 16u) || (0U != (tagSize & 1u)))
1901     {
1902         return kStatus_InvalidArgument;
1903     }
1904 
1905     /* check if keySize is supported */
1906     if (!ltc_check_key_size(keySize))
1907     {
1908         return kStatus_InvalidArgument;
1909     }
1910 
1911     /* LTC does not support more AAD than this */
1912     if (aadSize >= 65280u)
1913     {
1914         return kStatus_InvalidArgument;
1915     }
1916     return kStatus_Success;
1917 }
1918 
swap_bytes(uint32_t in)1919 static uint32_t swap_bytes(uint32_t in)
1920 {
1921     return (((in & 0x000000ffu) << 24U) | ((in & 0x0000ff00u) << 8U) | ((in & 0x00ff0000u) >> 8U) |
1922             ((in & 0xff000000u) >> 24U));
1923 }
1924 
ltc_aes_ccm_context_init(LTC_Type * base,uint32_t inputSize,const uint8_t * iv,uint32_t ivSize,uint32_t aadSize,uint32_t tagSize)1925 static void ltc_aes_ccm_context_init(
1926     LTC_Type *base, uint32_t inputSize, const uint8_t *iv, uint32_t ivSize, uint32_t aadSize, uint32_t tagSize)
1927 {
1928     ltc_xcm_block_t blk;
1929     ltc_xcm_block_t blkZero = {{0x0u, 0x0u, 0x0u, 0x0u}};
1930 
1931     uint32_t q; /* octet length of binary representation of the octet length of the payload. computed as (15 - n), where
1932               n is length of nonce(=ivSize) */
1933     uint8_t flags; /* flags field in B0 and CTR0 */
1934 
1935     /* compute B0 */
1936     ltc_memcpy(&blk, &blkZero, sizeof(blk));
1937     /* tagSize - size of output MAC */
1938     q     = 15u - ivSize;
1939     flags = (uint8_t)(8u * ((tagSize - 2u) / 2u) + q - 1u); /* 8*M' + L' */
1940     if (0U != aadSize)
1941     {
1942         flags |= 0x40U; /* Adata */
1943     }
1944     blk.b[0] = flags;                  /* flags field */
1945     blk.w[3] = swap_bytes(inputSize);  /* message size, most significant byte first */
1946     ltc_memcpy(&blk.b[1], iv, ivSize); /* nonce field */
1947 
1948     /* Write B0 data to the context register.
1949      */
1950     (void)ltc_set_context(base, &blk.b[0], 16, 0);
1951 
1952     /* Write CTR0 to the context register.
1953      */
1954     ltc_memcpy(&blk, &blkZero, sizeof(blk)); /* ctr(0) field = zero */
1955     blk.b[0] = (uint8_t)(q - 1u);            /* flags field */
1956     ltc_memcpy(&blk.b[1], iv, ivSize);       /* nonce field */
1957     (void)ltc_set_context(base, &blk.b[0], 16, 4);
1958 }
1959 
ltc_aes_ccm_process_aad(LTC_Type * base,uint32_t inputSize,const uint8_t * aad,uint32_t aadSize,ltc_mode_t * modeReg)1960 static status_t ltc_aes_ccm_process_aad(
1961     LTC_Type *base, uint32_t inputSize, const uint8_t *aad, uint32_t aadSize, ltc_mode_t *modeReg)
1962 {
1963     ltc_xcm_block_t blk = {{0x0u, 0x0u, 0x0u, 0x0u}};
1964     uint32_t swapped; /* holds byte swap of uint32_t */
1965     status_t retval;
1966 
1967     if (0U != aadSize)
1968     {
1969         bool aad_only;
1970         bool aad_single_session;
1971 
1972         uint32_t sz = 0;
1973 
1974         aad_only           = inputSize == 0u;
1975         aad_single_session = (((aadSize + 2u) + 15u) & 0xfffffff0u) <= LTC_FIFO_SZ_MAX_DOWN_ALGN;
1976 
1977         /* limit by CCM spec: 2^16 - 2^8 = 65280 */
1978 
1979         /* encoding is two octets, msbyte first */
1980         swapped = swap_bytes(aadSize);
1981         ltc_memcpy(&blk.b[0], ((uint8_t *)&swapped) + sizeof(uint16_t), sizeof(uint16_t));
1982 
1983         sz = aadSize > 14u ? 14u : aadSize; /* limit aad to the end of 16 bytes blk */
1984         ltc_memcpy(&blk.b[2], aad, sz);     /* fill B1 with aad */
1985 
1986         if (aad_single_session)
1987         {
1988             base->AADSZ = LTC_AADSZ_AL((true == aad_only ? 1U : 0U)) | ((aadSize + 2U) & LTC_DS_DS_MASK);
1989             /* move first AAD block (16 bytes block B1) to FIFO */
1990             ltc_move_block_to_ififo(base, (const ltc_xcm_block_t *)(uint32_t)&blk, sizeof(blk));
1991         }
1992         else
1993         {
1994             base->AADSZ = LTC_AADSZ_AL(1U) | (16U);
1995             /* move first AAD block (16 bytes block B1) to FIFO */
1996             ltc_move_block_to_ififo(base, (const ltc_xcm_block_t *)(uint32_t)&blk, sizeof(blk));
1997         }
1998 
1999         /* track consumed AAD. sz bytes have been moved to fifo. */
2000         aadSize -= sz;
2001         aad = &aad[sz];
2002 
2003         if (aad_single_session)
2004         {
2005             /* move remaining AAD to FIFO, then return, to continue with MDATA */
2006             ltc_move_to_ififo(base, aad, aadSize);
2007         }
2008         else if (aadSize == 0u)
2009         {
2010             retval = ltc_wait(base);
2011             if (kStatus_Success != retval)
2012             {
2013                 return retval;
2014             }
2015         }
2016         else
2017         {
2018             while (0U != aadSize)
2019             {
2020                 retval = ltc_wait(base);
2021                 if (kStatus_Success != retval)
2022                 {
2023                     return retval;
2024                 }
2025 
2026                 *modeReg &= ~LTC_MD_AS_MASK;
2027                 *modeReg |= (uint32_t)kLTC_ModeUpdate;
2028                 base->MD = *modeReg;
2029 
2030                 sz = LTC_FIFO_SZ_MAX_DOWN_ALGN;
2031                 if (aadSize < sz)
2032                 {
2033                     base->AADSZ = LTC_AADSZ_AL((true == aad_only ? 1U : 0U)) | (aadSize & LTC_DS_DS_MASK);
2034                     ltc_move_to_ififo(base, aad, aadSize);
2035                     aadSize = 0;
2036                 }
2037                 else
2038                 {
2039                     base->AADSZ = LTC_AADSZ_AL(1U) | (sz & LTC_DS_DS_MASK);
2040                     ltc_move_to_ififo(base, aad, sz);
2041                     aadSize -= sz;
2042                     aad = &aad[sz];
2043                 }
2044             } /* end while */
2045         }     /* end else */
2046     }         /* end if */
2047     return kStatus_Success;
2048 }
2049 
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)2050 static status_t ltc_aes_ccm_process(LTC_Type *base,
2051                                     ltc_mode_encrypt_t encryptMode,
2052                                     const uint8_t *src,
2053                                     uint32_t inputSize,
2054                                     const uint8_t *iv,
2055                                     uint32_t ivSize,
2056                                     const uint8_t *aad,
2057                                     uint32_t aadSize,
2058                                     const uint8_t *key,
2059                                     uint32_t keySize,
2060                                     uint8_t *dst,
2061                                     uint8_t *tag,
2062                                     uint32_t tagSize)
2063 {
2064     status_t retval;          /* return value */
2065     uint32_t max_ltc_fifo_sz; /* maximum data size that we can put to LTC FIFO in one session. 12-bit limit. */
2066     ltc_mode_t modeReg;       /* read and write LTC mode register */
2067 
2068     bool single_ses_proc_all; /* aad and src data can be processed in one session */
2069 
2070     retval = ltc_aes_ccm_check_input_args(base, src, iv, key, dst, ivSize, aadSize, keySize, tagSize);
2071 
2072     /* API input validation */
2073     if (kStatus_Success != retval)
2074     {
2075         return retval;
2076     }
2077 
2078     max_ltc_fifo_sz = LTC_DS_DS_MASK; /* 12-bit field limit */
2079 
2080     /* Write value to LTC AADSIZE will be (aadSize+2) value.
2081      * The value will be rounded up to next 16 byte boundary and added to Data Size register.
2082      * We then add inputSize to Data Size register. If the resulting Data Size is less than max_ltc_fifo_sz
2083      * then all can be processed in one session INITIALIZE/FINALIZE.
2084      * Otherwise, we have to split into multiple session, going through INITIALIZE, UPDATE (if required) and FINALIZE.
2085      */
2086     single_ses_proc_all = ((((aadSize + 2u) + 15u) & 0xfffffff0u) + inputSize) <= max_ltc_fifo_sz;
2087 
2088     /* setup key, algorithm and set the alg.state to INITIALIZE */
2089     if (single_ses_proc_all)
2090     {
2091         retval = ltc_symmetric_init_final(base, key, (uint8_t)keySize, kLTC_AlgorithmAES, kLTC_ModeCCM, encryptMode);
2092         if (kStatus_Success != retval)
2093         {
2094             return retval;
2095         }
2096     }
2097     else
2098     {
2099         retval = ltc_symmetric_init(base, key, (uint8_t)keySize, kLTC_AlgorithmAES, kLTC_ModeCCM, encryptMode);
2100         if (kStatus_Success != retval)
2101         {
2102             return retval;
2103         }
2104     }
2105     modeReg = base->MD;
2106 
2107     /* Initialize LTC context for AES CCM: block B0 and initial counter CTR0 */
2108     ltc_aes_ccm_context_init(base, inputSize, iv, ivSize, aadSize, tagSize);
2109 
2110     /* Process additional authentication data, if there are any.
2111      * Need to split the job into individual sessions of up to 4096 bytes, due to LTC IFIFO data size limit.
2112      */
2113     retval = ltc_aes_ccm_process_aad(base, inputSize, aad, aadSize, &modeReg);
2114     if (kStatus_Success != retval)
2115     {
2116         return retval;
2117     }
2118 
2119     /* Workaround for the LTC Data Size register update errata TKT261180 */
2120     if (0U != inputSize)
2121     {
2122         while (16u < base->DS)
2123         {
2124         }
2125     }
2126 
2127     /* Process message */
2128     if (single_ses_proc_all)
2129     {
2130         retval = ltc_symmetric_process_data(base, &src[0], inputSize, &dst[0]);
2131     }
2132     else
2133     {
2134         retval = ltc_symmetric_process_data_multiple(base, &src[0], inputSize, &dst[0], modeReg, kLTC_ModeFinalize);
2135     }
2136     if (kStatus_Success != retval)
2137     {
2138         return retval;
2139     }
2140     retval = ltc_aes_process_tag(base, tag, tagSize, modeReg, LTC_CCM_TAG_IDX);
2141     return retval;
2142 }
2143 
2144 /*******************************************************************************
2145  * CCM Code public
2146  ******************************************************************************/
2147 /*!
2148  * brief Encrypts AES and tags using CCM block mode.
2149  *
2150  * Encrypts AES and optionally tags using CCM block mode.
2151  *
2152  * param base LTC peripheral base address
2153  * param plaintext Input plain text to encrypt
2154  * param[out] ciphertext Output cipher text.
2155  * param size Size of input and output data in bytes. Zero means authentication only.
2156  * param iv Nonce
2157  * param ivSize Length of the Nonce in bytes. Must be 7, 8, 9, 10, 11, 12, or 13.
2158  * param aad Input additional authentication data. Can be NULL if aadSize is zero.
2159  * param aadSize Input size in bytes of AAD. Zero means data mode only (authentication skipped).
2160  * param key Input key to use for encryption
2161  * param keySize Size of the input key, in bytes. Must be 16, 24, or 32.
2162  * param[out] tag Generated output tag. Set to NULL to skip tag processing.
2163  * param tagSize Input size of the tag to generate, in bytes. Must be 4, 6, 8, 10, 12, 14, or 16.
2164  * return Status from encrypt operation
2165  */
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)2166 status_t LTC_AES_EncryptTagCcm(LTC_Type *base,
2167                                const uint8_t *plaintext,
2168                                uint8_t *ciphertext,
2169                                uint32_t size,
2170                                const uint8_t *iv,
2171                                uint32_t ivSize,
2172                                const uint8_t *aad,
2173                                uint32_t aadSize,
2174                                const uint8_t *key,
2175                                uint32_t keySize,
2176                                uint8_t *tag,
2177                                uint32_t tagSize)
2178 {
2179     status_t status;
2180     status = ltc_aes_ccm_process(base, kLTC_ModeEncrypt, plaintext, size, iv, ivSize, aad, aadSize, key, keySize,
2181                                  ciphertext, tag, tagSize);
2182 
2183     ltc_clear_all(base, false);
2184     return status;
2185 }
2186 
2187 /*!
2188  * brief Decrypts AES and authenticates using CCM block mode.
2189  *
2190  * Decrypts AES and optionally authenticates using CCM block mode.
2191  *
2192  * param base LTC peripheral base address
2193  * param ciphertext Input cipher text to decrypt
2194  * param[out] plaintext Output plain text.
2195  * param size Size of input and output data in bytes. Zero means authentication only.
2196  * param iv Nonce
2197  * param ivSize Length of the Nonce in bytes. Must be 7, 8, 9, 10, 11, 12, or 13.
2198  * param aad Input additional authentication data. Can be NULL if aadSize is zero.
2199  * param aadSize Input size in bytes of AAD. Zero means data mode only (authentication skipped).
2200  * param key Input key to use for decryption
2201  * param keySize Size of the input key, in bytes. Must be 16, 24, or 32.
2202  * param tag Received tag. Set to NULL to skip tag processing.
2203  * param tagSize Input size of the received tag to compare with the computed tag, in bytes. Must be 4, 6, 8, 10, 12,
2204  * 14, or 16.
2205  * return Status from decrypt operation
2206  */
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)2207 status_t LTC_AES_DecryptTagCcm(LTC_Type *base,
2208                                const uint8_t *ciphertext,
2209                                uint8_t *plaintext,
2210                                uint32_t size,
2211                                const uint8_t *iv,
2212                                uint32_t ivSize,
2213                                const uint8_t *aad,
2214                                uint32_t aadSize,
2215                                const uint8_t *key,
2216                                uint32_t keySize,
2217                                const uint8_t *tag,
2218                                uint32_t tagSize)
2219 {
2220     uint8_t temp_tag[16] = {0}; /* max. octet length of MAC (tag) is 16 */
2221     uint8_t *tag_ptr;
2222     status_t status;
2223 
2224     tag_ptr = NULL;
2225     if (NULL != tag)
2226     {
2227         ltc_memcpy(temp_tag, tag, tagSize);
2228         tag_ptr = &temp_tag[0];
2229     }
2230 
2231     status = ltc_aes_ccm_process(base, kLTC_ModeDecrypt, ciphertext, size, iv, ivSize, aad, aadSize, key, keySize,
2232                                  plaintext, tag_ptr, tagSize);
2233 
2234     ltc_clear_all(base, false);
2235     return status;
2236 }
2237 
2238 #if defined(FSL_FEATURE_LTC_HAS_DES) && FSL_FEATURE_LTC_HAS_DES
2239 /*******************************************************************************
2240  * DES / 3DES Code static
2241  ******************************************************************************/
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)2242 static status_t ltc_des_process(LTC_Type *base,
2243                                 const uint8_t *input,
2244                                 uint8_t *output,
2245                                 uint32_t size,
2246                                 const uint8_t iv[LTC_DES_IV_SIZE],
2247                                 const uint8_t key[LTC_DES_KEY_SIZE],
2248                                 ltc_mode_symmetric_alg_t modeAs,
2249                                 ltc_mode_encrypt_t modeEnc)
2250 {
2251     status_t retval;
2252 
2253     /* all but OFB, size must be 8-byte multiple */
2254     if ((modeAs != kLTC_ModeOFB) && ((size < 8u) || (0U != (size % 8u))))
2255     {
2256         return kStatus_InvalidArgument;
2257     }
2258 
2259     /* Initialize algorithm state. */
2260     retval = ltc_symmetric_update(base, &key[0], LTC_DES_KEY_SIZE, kLTC_AlgorithmDES, modeAs, modeEnc);
2261     if (kStatus_Success != retval)
2262     {
2263         return retval;
2264     }
2265     if ((modeAs != kLTC_ModeECB))
2266     {
2267         retval = ltc_set_context(base, iv, LTC_DES_IV_SIZE, 0);
2268         if (kStatus_Success != retval)
2269         {
2270             return retval;
2271         }
2272     }
2273 
2274     /* Process data and return status. */
2275     retval = ltc_process_message_in_sessions(base, input, size, output);
2276     ltc_clear_all(base, false);
2277     return retval;
2278 }
2279 
ltc_3des_check_input_args(ltc_mode_symmetric_alg_t modeAs,uint32_t size,const uint8_t * key1,const uint8_t * key2)2280 status_t ltc_3des_check_input_args(ltc_mode_symmetric_alg_t modeAs,
2281                                    uint32_t size,
2282                                    const uint8_t *key1,
2283                                    const uint8_t *key2)
2284 {
2285     /* all but OFB, size must be 8-byte multiple */
2286     if ((modeAs != kLTC_ModeOFB) && ((size < 8u) || (0U != (size % 8u))))
2287     {
2288         return kStatus_InvalidArgument;
2289     }
2290 
2291     if ((key1 == NULL) || (key2 == NULL))
2292     {
2293         return kStatus_InvalidArgument;
2294     }
2295     return kStatus_Success;
2296 }
2297 
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)2298 static status_t ltc_3des_process(LTC_Type *base,
2299                                  const uint8_t *input,
2300                                  uint8_t *output,
2301                                  uint32_t size,
2302                                  const uint8_t iv[LTC_DES_IV_SIZE],
2303                                  const uint8_t key1[LTC_DES_KEY_SIZE],
2304                                  const uint8_t key2[LTC_DES_KEY_SIZE],
2305                                  const uint8_t key3[LTC_DES_KEY_SIZE],
2306                                  ltc_mode_symmetric_alg_t modeAs,
2307                                  ltc_mode_encrypt_t modeEnc)
2308 {
2309     status_t retval;
2310     uint8_t key[LTC_DES_KEY_SIZE * 3];
2311     uint8_t keySize = LTC_DES_KEY_SIZE * 2;
2312 
2313     retval = ltc_3des_check_input_args(modeAs, size, key1, key2);
2314     if (kStatus_Success != retval)
2315     {
2316         return retval;
2317     }
2318 
2319     ltc_memcpy(&key[0], &key1[0], LTC_DES_KEY_SIZE);
2320     ltc_memcpy(&key[LTC_DES_KEY_SIZE], &key2[0], LTC_DES_KEY_SIZE);
2321     if (NULL != key3)
2322     {
2323         ltc_memcpy(&key[LTC_DES_KEY_SIZE * 2], &key3[0], LTC_DES_KEY_SIZE);
2324         keySize = (uint8_t)sizeof(key);
2325     }
2326 
2327     /* Initialize algorithm state. */
2328     retval = ltc_symmetric_update(base, &key[0], keySize, kLTC_Algorithm3DES, modeAs, modeEnc);
2329     if (kStatus_Success != retval)
2330     {
2331         return retval;
2332     }
2333 
2334     if ((modeAs != kLTC_ModeECB))
2335     {
2336         retval = ltc_set_context(base, iv, LTC_DES_IV_SIZE, 0);
2337         if (kStatus_Success != retval)
2338         {
2339             return retval;
2340         }
2341     }
2342 
2343     /* Process data and return status. */
2344     retval = ltc_process_message_in_sessions(base, input, size, output);
2345     ltc_clear_all(base, false);
2346     return retval;
2347 }
2348 /*******************************************************************************
2349  * DES / 3DES Code public
2350  ******************************************************************************/
2351 /*!
2352  * brief Encrypts DES using ECB block mode.
2353  *
2354  * Encrypts DES using ECB block mode.
2355  *
2356  * param base LTC peripheral base address
2357  * param plaintext Input plaintext to encrypt
2358  * param[out] ciphertext Output ciphertext
2359  * param size Size of input and output data in bytes. Must be multiple of 8 bytes.
2360  * param key Input key to use for encryption
2361  * return Status from encrypt/decrypt operation
2362  */
LTC_DES_EncryptEcb(LTC_Type * base,const uint8_t * plaintext,uint8_t * ciphertext,uint32_t size,const uint8_t key[LTC_DES_KEY_SIZE])2363 status_t LTC_DES_EncryptEcb(
2364     LTC_Type *base, const uint8_t *plaintext, uint8_t *ciphertext, uint32_t size, const uint8_t key[LTC_DES_KEY_SIZE])
2365 {
2366     return ltc_des_process(base, plaintext, ciphertext, size, NULL, key, kLTC_ModeECB, kLTC_ModeEncrypt);
2367 }
2368 
2369 /*!
2370  * brief Decrypts DES using ECB block mode.
2371  *
2372  * Decrypts DES using ECB block mode.
2373  *
2374  * param base LTC peripheral base address
2375  * param ciphertext Input ciphertext to decrypt
2376  * param[out] plaintext Output plaintext
2377  * param size Size of input and output data in bytes. Must be multiple of 8 bytes.
2378  * param key Input key to use for decryption
2379  * return Status from encrypt/decrypt operation
2380  */
LTC_DES_DecryptEcb(LTC_Type * base,const uint8_t * ciphertext,uint8_t * plaintext,uint32_t size,const uint8_t key[LTC_DES_KEY_SIZE])2381 status_t LTC_DES_DecryptEcb(
2382     LTC_Type *base, const uint8_t *ciphertext, uint8_t *plaintext, uint32_t size, const uint8_t key[LTC_DES_KEY_SIZE])
2383 {
2384     return ltc_des_process(base, ciphertext, plaintext, size, NULL, key, kLTC_ModeECB, kLTC_ModeDecrypt);
2385 }
2386 
2387 /*!
2388  * brief Encrypts DES using CBC block mode.
2389  *
2390  * Encrypts DES using CBC block mode.
2391  *
2392  * param base LTC peripheral base address
2393  * param plaintext Input plaintext to encrypt
2394  * param[out] ciphertext Ouput ciphertext
2395  * param size Size of input and output data in bytes
2396  * param iv Input initial vector to combine with the first plaintext block.
2397  *           The iv does not need to be secret, but it must be unpredictable.
2398  * param key Input key to use for encryption
2399  * return Status from encrypt/decrypt operation
2400  */
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])2401 status_t LTC_DES_EncryptCbc(LTC_Type *base,
2402                             const uint8_t *plaintext,
2403                             uint8_t *ciphertext,
2404                             uint32_t size,
2405                             const uint8_t iv[LTC_DES_IV_SIZE],
2406                             const uint8_t key[LTC_DES_KEY_SIZE])
2407 {
2408     return ltc_des_process(base, plaintext, ciphertext, size, iv, key, kLTC_ModeCBC, kLTC_ModeEncrypt);
2409 }
2410 
2411 /*!
2412  * brief Decrypts DES using CBC block mode.
2413  *
2414  * Decrypts DES using CBC block mode.
2415  *
2416  * param base LTC peripheral base address
2417  * param ciphertext Input ciphertext to decrypt
2418  * param[out] plaintext Output plaintext
2419  * param size Size of input data in bytes
2420  * param iv Input initial vector to combine with the first plaintext block.
2421  *           The iv does not need to be secret, but it must be unpredictable.
2422  * param key Input key to use for decryption
2423  * return Status from encrypt/decrypt operation
2424  */
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])2425 status_t LTC_DES_DecryptCbc(LTC_Type *base,
2426                             const uint8_t *ciphertext,
2427                             uint8_t *plaintext,
2428                             uint32_t size,
2429                             const uint8_t iv[LTC_DES_IV_SIZE],
2430                             const uint8_t key[LTC_DES_KEY_SIZE])
2431 {
2432     return ltc_des_process(base, ciphertext, plaintext, size, iv, key, kLTC_ModeCBC, kLTC_ModeDecrypt);
2433 }
2434 
2435 /*!
2436  * brief Encrypts DES using CFB block mode.
2437  *
2438  * Encrypts DES using CFB block mode.
2439  *
2440  * param base LTC peripheral base address
2441  * param plaintext Input plaintext to encrypt
2442  * param size Size of input data in bytes
2443  * param iv Input initial block.
2444  * param key Input key to use for encryption
2445  * param[out] ciphertext Output ciphertext
2446  * return Status from encrypt/decrypt operation
2447  */
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])2448 status_t LTC_DES_EncryptCfb(LTC_Type *base,
2449                             const uint8_t *plaintext,
2450                             uint8_t *ciphertext,
2451                             uint32_t size,
2452                             const uint8_t iv[LTC_DES_IV_SIZE],
2453                             const uint8_t key[LTC_DES_KEY_SIZE])
2454 {
2455     return ltc_des_process(base, plaintext, ciphertext, size, iv, key, kLTC_ModeCFB, kLTC_ModeEncrypt);
2456 }
2457 
2458 /*!
2459  * brief Decrypts DES using CFB block mode.
2460  *
2461  * Decrypts DES using CFB block mode.
2462  *
2463  * param base LTC peripheral base address
2464  * param ciphertext Input ciphertext to decrypt
2465  * param[out] plaintext Output plaintext
2466  * param size Size of input and output data in bytes
2467  * param iv Input initial block.
2468  * param key Input key to use for decryption
2469  * return Status from encrypt/decrypt operation
2470  */
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])2471 status_t LTC_DES_DecryptCfb(LTC_Type *base,
2472                             const uint8_t *ciphertext,
2473                             uint8_t *plaintext,
2474                             uint32_t size,
2475                             const uint8_t iv[LTC_DES_IV_SIZE],
2476                             const uint8_t key[LTC_DES_KEY_SIZE])
2477 {
2478     return ltc_des_process(base, ciphertext, plaintext, size, iv, key, kLTC_ModeCFB, kLTC_ModeDecrypt);
2479 }
2480 
2481 /*!
2482  * brief Encrypts DES using OFB block mode.
2483  *
2484  * Encrypts DES using OFB block mode.
2485  *
2486  * param base LTC peripheral base address
2487  * param plaintext Input plaintext to encrypt
2488  * param[out] ciphertext Output ciphertext
2489  * param size Size of input and output data in bytes
2490  * param iv Input unique input vector. The OFB mode requires that the IV be unique
2491  *           for each execution of the mode under the given key.
2492  * param key Input key to use for encryption
2493  * return Status from encrypt/decrypt operation
2494  */
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])2495 status_t LTC_DES_EncryptOfb(LTC_Type *base,
2496                             const uint8_t *plaintext,
2497                             uint8_t *ciphertext,
2498                             uint32_t size,
2499                             const uint8_t iv[LTC_DES_IV_SIZE],
2500                             const uint8_t key[LTC_DES_KEY_SIZE])
2501 {
2502     return ltc_des_process(base, plaintext, ciphertext, size, iv, key, kLTC_ModeOFB, kLTC_ModeEncrypt);
2503 }
2504 
2505 /*!
2506  * brief Decrypts DES using OFB block mode.
2507  *
2508  * Decrypts DES using OFB block mode.
2509  *
2510  * param base LTC peripheral base address
2511  * param ciphertext Input ciphertext to decrypt
2512  * param[out] plaintext Output plaintext
2513  * param size Size of input and output data in bytes. Must be multiple of 8 bytes.
2514  * param iv Input unique input vector. The OFB mode requires that the IV be unique
2515  *           for each execution of the mode under the given key.
2516  * param key Input key to use for decryption
2517  * return Status from encrypt/decrypt operation
2518  */
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])2519 status_t LTC_DES_DecryptOfb(LTC_Type *base,
2520                             const uint8_t *ciphertext,
2521                             uint8_t *plaintext,
2522                             uint32_t size,
2523                             const uint8_t iv[LTC_DES_IV_SIZE],
2524                             const uint8_t key[LTC_DES_KEY_SIZE])
2525 {
2526     return ltc_des_process(base, ciphertext, plaintext, size, iv, key, kLTC_ModeOFB, kLTC_ModeDecrypt);
2527 }
2528 
2529 /*!
2530  * brief Encrypts triple DES using ECB block mode with two keys.
2531  *
2532  * Encrypts triple DES using ECB block mode with two keys.
2533  *
2534  * param base LTC peripheral base address
2535  * param plaintext Input plaintext to encrypt
2536  * param[out] ciphertext Output ciphertext
2537  * param size Size of input and output data in bytes. Must be multiple of 8 bytes.
2538  * param key1 First input key for key bundle
2539  * param key2 Second input key for key bundle
2540  * return Status from encrypt/decrypt operation
2541  */
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])2542 status_t LTC_DES2_EncryptEcb(LTC_Type *base,
2543                              const uint8_t *plaintext,
2544                              uint8_t *ciphertext,
2545                              uint32_t size,
2546                              const uint8_t key1[LTC_DES_KEY_SIZE],
2547                              const uint8_t key2[LTC_DES_KEY_SIZE])
2548 {
2549     return ltc_3des_process(base, plaintext, ciphertext, size, NULL, key1, key2, NULL, kLTC_ModeECB, kLTC_ModeEncrypt);
2550 }
2551 
2552 /*!
2553  * brief Encrypts triple DES using ECB block mode with three keys.
2554  *
2555  * Encrypts triple DES using ECB block mode with three keys.
2556  *
2557  * param base LTC peripheral base address
2558  * param plaintext Input plaintext to encrypt
2559  * param[out] ciphertext Output ciphertext
2560  * param size Size of input and output data in bytes. Must be multiple of 8 bytes.
2561  * param key1 First input key for key bundle
2562  * param key2 Second input key for key bundle
2563  * param key3 Third input key for key bundle
2564  * return Status from encrypt/decrypt operation
2565  */
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])2566 status_t LTC_DES3_EncryptEcb(LTC_Type *base,
2567                              const uint8_t *plaintext,
2568                              uint8_t *ciphertext,
2569                              uint32_t size,
2570                              const uint8_t key1[LTC_DES_KEY_SIZE],
2571                              const uint8_t key2[LTC_DES_KEY_SIZE],
2572                              const uint8_t key3[LTC_DES_KEY_SIZE])
2573 {
2574     return ltc_3des_process(base, plaintext, ciphertext, size, NULL, key1, key2, key3, kLTC_ModeECB, kLTC_ModeEncrypt);
2575 }
2576 
2577 /*!
2578  * brief Decrypts triple DES using ECB block mode with two keys.
2579  *
2580  * Decrypts triple DES using ECB block mode with two keys.
2581  *
2582  * param base LTC peripheral base address
2583  * param ciphertext Input ciphertext to decrypt
2584  * param[out] plaintext Output plaintext
2585  * param size Size of input and output data in bytes. Must be multiple of 8 bytes.
2586  * param key1 First input key for key bundle
2587  * param key2 Second input key for key bundle
2588  * return Status from encrypt/decrypt operation
2589  */
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])2590 status_t LTC_DES2_DecryptEcb(LTC_Type *base,
2591                              const uint8_t *ciphertext,
2592                              uint8_t *plaintext,
2593                              uint32_t size,
2594                              const uint8_t key1[LTC_DES_KEY_SIZE],
2595                              const uint8_t key2[LTC_DES_KEY_SIZE])
2596 {
2597     return ltc_3des_process(base, ciphertext, plaintext, size, NULL, key1, key2, NULL, kLTC_ModeECB, kLTC_ModeDecrypt);
2598 }
2599 
2600 /*!
2601  * brief Decrypts triple DES using ECB block mode with three keys.
2602  *
2603  * Decrypts triple DES using ECB block mode with three keys.
2604  *
2605  * param base LTC peripheral base address
2606  * param ciphertext Input ciphertext to decrypt
2607  * param[out] plaintext Output plaintext
2608  * param size Size of input and output data in bytes. Must be multiple of 8 bytes.
2609  * param key1 First input key for key bundle
2610  * param key2 Second input key for key bundle
2611  * param key3 Third input key for key bundle
2612  * return Status from encrypt/decrypt operation
2613  */
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])2614 status_t LTC_DES3_DecryptEcb(LTC_Type *base,
2615                              const uint8_t *ciphertext,
2616                              uint8_t *plaintext,
2617                              uint32_t size,
2618                              const uint8_t key1[LTC_DES_KEY_SIZE],
2619                              const uint8_t key2[LTC_DES_KEY_SIZE],
2620                              const uint8_t key3[LTC_DES_KEY_SIZE])
2621 {
2622     return ltc_3des_process(base, ciphertext, plaintext, size, NULL, key1, key2, key3, kLTC_ModeECB, kLTC_ModeDecrypt);
2623 }
2624 
2625 /*!
2626  * brief Encrypts triple DES using CBC block mode with two keys.
2627  *
2628  * Encrypts triple DES using CBC block mode with two keys.
2629  *
2630  * param base LTC peripheral base address
2631  * param plaintext Input plaintext to encrypt
2632  * param[out] ciphertext Output ciphertext
2633  * param size Size of input and output data in bytes
2634  * param iv Input initial vector to combine with the first plaintext block.
2635  *           The iv does not need to be secret, but it must be unpredictable.
2636  * param key1 First input key for key bundle
2637  * param key2 Second input key for key bundle
2638  * return Status from encrypt/decrypt operation
2639  */
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])2640 status_t LTC_DES2_EncryptCbc(LTC_Type *base,
2641                              const uint8_t *plaintext,
2642                              uint8_t *ciphertext,
2643                              uint32_t size,
2644                              const uint8_t iv[LTC_DES_IV_SIZE],
2645                              const uint8_t key1[LTC_DES_KEY_SIZE],
2646                              const uint8_t key2[LTC_DES_KEY_SIZE])
2647 {
2648     return ltc_3des_process(base, plaintext, ciphertext, size, iv, key1, key2, NULL, kLTC_ModeCBC, kLTC_ModeEncrypt);
2649 }
2650 
2651 /*!
2652  * brief Encrypts triple DES using CBC block mode with three keys.
2653  *
2654  * Encrypts triple DES using CBC block mode with three keys.
2655  *
2656  * param base LTC peripheral base address
2657  * param plaintext Input plaintext to encrypt
2658  * param[out] ciphertext Output ciphertext
2659  * param size Size of input data in bytes
2660  * param iv Input initial vector to combine with the first plaintext block.
2661  *           The iv does not need to be secret, but it must be unpredictable.
2662  * param key1 First input key for key bundle
2663  * param key2 Second input key for key bundle
2664  * param key3 Third input key for key bundle
2665  * return Status from encrypt/decrypt operation
2666  */
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])2667 status_t LTC_DES3_EncryptCbc(LTC_Type *base,
2668                              const uint8_t *plaintext,
2669                              uint8_t *ciphertext,
2670                              uint32_t size,
2671                              const uint8_t iv[LTC_DES_IV_SIZE],
2672                              const uint8_t key1[LTC_DES_KEY_SIZE],
2673                              const uint8_t key2[LTC_DES_KEY_SIZE],
2674                              const uint8_t key3[LTC_DES_KEY_SIZE])
2675 {
2676     return ltc_3des_process(base, plaintext, ciphertext, size, iv, key1, key2, key3, kLTC_ModeCBC, kLTC_ModeEncrypt);
2677 }
2678 
2679 /*!
2680  * brief Decrypts triple DES using CBC block mode with two keys.
2681  *
2682  * Decrypts triple DES using CBC block mode with two keys.
2683  *
2684  * param base LTC peripheral base address
2685  * param ciphertext Input ciphertext to decrypt
2686  * param[out] plaintext Output plaintext
2687  * param size Size of input and output data in bytes
2688  * param iv Input initial vector to combine with the first plaintext block.
2689  *           The iv does not need to be secret, but it must be unpredictable.
2690  * param key1 First input key for key bundle
2691  * param key2 Second input key for key bundle
2692  * return Status from encrypt/decrypt operation
2693  */
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])2694 status_t LTC_DES2_DecryptCbc(LTC_Type *base,
2695                              const uint8_t *ciphertext,
2696                              uint8_t *plaintext,
2697                              uint32_t size,
2698                              const uint8_t iv[LTC_DES_IV_SIZE],
2699                              const uint8_t key1[LTC_DES_KEY_SIZE],
2700                              const uint8_t key2[LTC_DES_KEY_SIZE])
2701 {
2702     return ltc_3des_process(base, ciphertext, plaintext, size, iv, key1, key2, NULL, kLTC_ModeCBC, kLTC_ModeDecrypt);
2703 }
2704 
2705 /*!
2706  * brief Decrypts triple DES using CBC block mode with three keys.
2707  *
2708  * Decrypts triple DES using CBC block mode with three keys.
2709  *
2710  * param base LTC peripheral base address
2711  * param ciphertext Input ciphertext to decrypt
2712  * param[out] plaintext Output plaintext
2713  * param size Size of input and output data in bytes
2714  * param iv Input initial vector to combine with the first plaintext block.
2715  *           The iv does not need to be secret, but it must be unpredictable.
2716  * param key1 First input key for key bundle
2717  * param key2 Second input key for key bundle
2718  * param key3 Third input key for key bundle
2719  * return Status from encrypt/decrypt operation
2720  */
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])2721 status_t LTC_DES3_DecryptCbc(LTC_Type *base,
2722                              const uint8_t *ciphertext,
2723                              uint8_t *plaintext,
2724                              uint32_t size,
2725                              const uint8_t iv[LTC_DES_IV_SIZE],
2726                              const uint8_t key1[LTC_DES_KEY_SIZE],
2727                              const uint8_t key2[LTC_DES_KEY_SIZE],
2728                              const uint8_t key3[LTC_DES_KEY_SIZE])
2729 {
2730     return ltc_3des_process(base, ciphertext, plaintext, size, iv, key1, key2, key3, kLTC_ModeCBC, kLTC_ModeDecrypt);
2731 }
2732 
2733 /*!
2734  * brief Encrypts triple DES using CFB block mode with two keys.
2735  *
2736  * Encrypts triple DES using CFB block mode with two keys.
2737  *
2738  * param base LTC peripheral base address
2739  * param plaintext Input plaintext to encrypt
2740  * param[out] ciphertext Output ciphertext
2741  * param size Size of input and output data in bytes
2742  * param iv Input initial block.
2743  * param key1 First input key for key bundle
2744  * param key2 Second input key for key bundle
2745  * return Status from encrypt/decrypt operation
2746  */
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])2747 status_t LTC_DES2_EncryptCfb(LTC_Type *base,
2748                              const uint8_t *plaintext,
2749                              uint8_t *ciphertext,
2750                              uint32_t size,
2751                              const uint8_t iv[LTC_DES_IV_SIZE],
2752                              const uint8_t key1[LTC_DES_KEY_SIZE],
2753                              const uint8_t key2[LTC_DES_KEY_SIZE])
2754 {
2755     return ltc_3des_process(base, plaintext, ciphertext, size, iv, key1, key2, NULL, kLTC_ModeCFB, kLTC_ModeEncrypt);
2756 }
2757 
2758 /*!
2759  * brief Encrypts triple DES using CFB block mode with three keys.
2760  *
2761  * Encrypts triple DES using CFB block mode with three keys.
2762  *
2763  * param base LTC peripheral base address
2764  * param plaintext Input plaintext to encrypt
2765  * param[out] ciphertext Output ciphertext
2766  * param size Size of input and ouput data in bytes
2767  * param iv Input initial block.
2768  * param key1 First input key for key bundle
2769  * param key2 Second input key for key bundle
2770  * param key3 Third input key for key bundle
2771  * return Status from encrypt/decrypt operation
2772  */
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])2773 status_t LTC_DES3_EncryptCfb(LTC_Type *base,
2774                              const uint8_t *plaintext,
2775                              uint8_t *ciphertext,
2776                              uint32_t size,
2777                              const uint8_t iv[LTC_DES_IV_SIZE],
2778                              const uint8_t key1[LTC_DES_KEY_SIZE],
2779                              const uint8_t key2[LTC_DES_KEY_SIZE],
2780                              const uint8_t key3[LTC_DES_KEY_SIZE])
2781 {
2782     return ltc_3des_process(base, plaintext, ciphertext, size, iv, key1, key2, key3, kLTC_ModeCFB, kLTC_ModeEncrypt);
2783 }
2784 
2785 /*!
2786  * brief Decrypts triple DES using CFB block mode with two keys.
2787  *
2788  * Decrypts triple DES using CFB block mode with two keys.
2789  *
2790  * param base LTC peripheral base address
2791  * param ciphertext Input ciphertext to decrypt
2792  * param[out] plaintext Output plaintext
2793  * param size Size of input and output data in bytes
2794  * param iv Input initial block.
2795  * param key1 First input key for key bundle
2796  * param key2 Second input key for key bundle
2797  * return Status from encrypt/decrypt operation
2798  */
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])2799 status_t LTC_DES2_DecryptCfb(LTC_Type *base,
2800                              const uint8_t *ciphertext,
2801                              uint8_t *plaintext,
2802                              uint32_t size,
2803                              const uint8_t iv[LTC_DES_IV_SIZE],
2804                              const uint8_t key1[LTC_DES_KEY_SIZE],
2805                              const uint8_t key2[LTC_DES_KEY_SIZE])
2806 {
2807     return ltc_3des_process(base, ciphertext, plaintext, size, iv, key1, key2, NULL, kLTC_ModeCFB, kLTC_ModeDecrypt);
2808 }
2809 
2810 /*!
2811  * brief Decrypts triple DES using CFB block mode with three keys.
2812  *
2813  * Decrypts triple DES using CFB block mode with three keys.
2814  *
2815  * param base LTC peripheral base address
2816  * param ciphertext Input ciphertext to decrypt
2817  * param[out] plaintext Output plaintext
2818  * param size Size of input data in bytes
2819  * param iv Input initial block.
2820  * param key1 First input key for key bundle
2821  * param key2 Second input key for key bundle
2822  * param key3 Third input key for key bundle
2823  * return Status from encrypt/decrypt operation
2824  */
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])2825 status_t LTC_DES3_DecryptCfb(LTC_Type *base,
2826                              const uint8_t *ciphertext,
2827                              uint8_t *plaintext,
2828                              uint32_t size,
2829                              const uint8_t iv[LTC_DES_IV_SIZE],
2830                              const uint8_t key1[LTC_DES_KEY_SIZE],
2831                              const uint8_t key2[LTC_DES_KEY_SIZE],
2832                              const uint8_t key3[LTC_DES_KEY_SIZE])
2833 {
2834     return ltc_3des_process(base, ciphertext, plaintext, size, iv, key1, key2, key3, kLTC_ModeCFB, kLTC_ModeDecrypt);
2835 }
2836 
2837 /*!
2838  * brief Encrypts triple DES using OFB block mode with two keys.
2839  *
2840  * Encrypts triple DES using OFB block mode with two keys.
2841  *
2842  * param base LTC peripheral base address
2843  * param plaintext Input plaintext to encrypt
2844  * param[out] ciphertext Output ciphertext
2845  * param size Size of input and output data in bytes
2846  * param iv Input unique input vector. The OFB mode requires that the IV be unique
2847  *           for each execution of the mode under the given key.
2848  * param key1 First input key for key bundle
2849  * param key2 Second input key for key bundle
2850  * return Status from encrypt/decrypt operation
2851  */
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])2852 status_t LTC_DES2_EncryptOfb(LTC_Type *base,
2853                              const uint8_t *plaintext,
2854                              uint8_t *ciphertext,
2855                              uint32_t size,
2856                              const uint8_t iv[LTC_DES_IV_SIZE],
2857                              const uint8_t key1[LTC_DES_KEY_SIZE],
2858                              const uint8_t key2[LTC_DES_KEY_SIZE])
2859 {
2860     return ltc_3des_process(base, plaintext, ciphertext, size, iv, key1, key2, NULL, kLTC_ModeOFB, kLTC_ModeEncrypt);
2861 }
2862 
2863 /*!
2864  * brief Encrypts triple DES using OFB block mode with three keys.
2865  *
2866  * Encrypts triple DES using OFB block mode with three keys.
2867  *
2868  * param base LTC peripheral base address
2869  * param plaintext Input plaintext to encrypt
2870  * param[out] ciphertext Output ciphertext
2871  * param size Size of input and output data in bytes
2872  * param iv Input unique input vector. The OFB mode requires that the IV be unique
2873  *           for each execution of the mode under the given key.
2874  * param key1 First input key for key bundle
2875  * param key2 Second input key for key bundle
2876  * param key3 Third input key for key bundle
2877  * return Status from encrypt/decrypt operation
2878  */
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])2879 status_t LTC_DES3_EncryptOfb(LTC_Type *base,
2880                              const uint8_t *plaintext,
2881                              uint8_t *ciphertext,
2882                              uint32_t size,
2883                              const uint8_t iv[LTC_DES_IV_SIZE],
2884                              const uint8_t key1[LTC_DES_KEY_SIZE],
2885                              const uint8_t key2[LTC_DES_KEY_SIZE],
2886                              const uint8_t key3[LTC_DES_KEY_SIZE])
2887 {
2888     return ltc_3des_process(base, plaintext, ciphertext, size, iv, key1, key2, key3, kLTC_ModeOFB, kLTC_ModeEncrypt);
2889 }
2890 
2891 /*!
2892  * brief Decrypts triple DES using OFB block mode with two keys.
2893  *
2894  * Decrypts triple DES using OFB block mode with two keys.
2895  *
2896  * param base LTC peripheral base address
2897  * param ciphertext Input ciphertext to decrypt
2898  * param[out] plaintext Output plaintext
2899  * param size Size of input and output data in bytes
2900  * param iv Input unique input vector. The OFB mode requires that the IV be unique
2901  *           for each execution of the mode under the given key.
2902  * param key1 First input key for key bundle
2903  * param key2 Second input key for key bundle
2904  * return Status from encrypt/decrypt operation
2905  */
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])2906 status_t LTC_DES2_DecryptOfb(LTC_Type *base,
2907                              const uint8_t *ciphertext,
2908                              uint8_t *plaintext,
2909                              uint32_t size,
2910                              const uint8_t iv[LTC_DES_IV_SIZE],
2911                              const uint8_t key1[LTC_DES_KEY_SIZE],
2912                              const uint8_t key2[LTC_DES_KEY_SIZE])
2913 {
2914     return ltc_3des_process(base, ciphertext, plaintext, size, iv, key1, key2, NULL, kLTC_ModeOFB, kLTC_ModeDecrypt);
2915 }
2916 
2917 /*!
2918  * brief Decrypts triple DES using OFB block mode with three keys.
2919  *
2920  * Decrypts triple DES using OFB block mode with three keys.
2921  *
2922  * param base LTC peripheral base address
2923  * param ciphertext Input ciphertext to decrypt
2924  * param[out] plaintext Output plaintext
2925  * param size Size of input and output data in bytes
2926  * param iv Input unique input vector. The OFB mode requires that the IV be unique
2927  *           for each execution of the mode under the given key.
2928  * param key1 First input key for key bundle
2929  * param key2 Second input key for key bundle
2930  * param key3 Third input key for key bundle
2931  * return Status from encrypt/decrypt operation
2932  */
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])2933 status_t LTC_DES3_DecryptOfb(LTC_Type *base,
2934                              const uint8_t *ciphertext,
2935                              uint8_t *plaintext,
2936                              uint32_t size,
2937                              const uint8_t iv[LTC_DES_IV_SIZE],
2938                              const uint8_t key1[LTC_DES_KEY_SIZE],
2939                              const uint8_t key2[LTC_DES_KEY_SIZE],
2940                              const uint8_t key3[LTC_DES_KEY_SIZE])
2941 {
2942     return ltc_3des_process(base, ciphertext, plaintext, size, iv, key1, key2, key3, kLTC_ModeOFB, kLTC_ModeDecrypt);
2943 }
2944 #endif /* FSL_FEATURE_LTC_HAS_DES */
2945 
2946 /*******************************************************************************
2947  * HASH Definitions
2948  ******************************************************************************/
2949 #if defined(FSL_FEATURE_LTC_HAS_SHA) && FSL_FEATURE_LTC_HAS_SHA
2950 #define LTC_SHA_BLOCK_SIZE  64                 /*!< SHA-1, SHA-224 & SHA-256 block size  */
2951 #define LTC_HASH_BLOCK_SIZE LTC_SHA_BLOCK_SIZE /*!< LTC hash block size  */
2952 
2953 enum _ltc_sha_digest_len
2954 {
2955     kLTC_RunLenSha1   = 28u,
2956     kLTC_OutLenSha1   = 20u,
2957     kLTC_RunLenSha224 = 40u,
2958     kLTC_OutLenSha224 = 28u,
2959     kLTC_RunLenSha256 = 40u,
2960     kLTC_OutLenSha256 = 32u,
2961 };
2962 #else
2963 #define LTC_HASH_BLOCK_SIZE LTC_AES_BLOCK_SIZE /*!< LTC hash block size  */
2964 #endif                                         /* FSL_FEATURE_LTC_HAS_SHA */
2965 
2966 /*! Internal states of the HASH creation process */
2967 typedef enum _ltc_hash_algo_state
2968 {
2969     kLTC_HashInit = 1u, /*!< Key in the HASH context is the input key. */
2970     kLTC_HashUpdate,    /*!< HASH context has algorithm specific context: MAC, K2 and K3 (XCBC-MAC), MAC and L (CMAC),
2971                            running digest (MDHA). Key in the HASH context is the derived key. */
2972 } ltc_hash_algo_state_t;
2973 
2974 /*! 16/64-byte block represented as byte array or 4/16 32-bit words */
2975 typedef union _ltc_hash_block
2976 {
2977     uint32_t w[LTC_HASH_BLOCK_SIZE / 4]; /*!< array of 32-bit words */
2978     uint8_t b[LTC_HASH_BLOCK_SIZE];      /*!< byte array */
2979 } ltc_hash_block_t;
2980 
2981 /*! Definitions of indexes into hash context array */
2982 typedef enum _ltc_hash_ctx_indexes
2983 {
2984     kLTC_HashCtxKeyStartIdx = 12, /*!< context word array index where key is stored */
2985     kLTC_HashCtxKeySize     = 20, /*!< context word array index where key size is stored */
2986     kLTC_HashCtxNumWords    = 21, /*!< number of context array 32-bit words  */
2987 } ltc_hash_ctx_indexes;
2988 
2989 typedef struct _ltc_hash_ctx_internal
2990 {
2991     ltc_hash_block_t blk; /*!< memory buffer. only full 64/16-byte blocks are written to LTC during hash updates */
2992     uint32_t blksz;       /*!< number of valid bytes in memory buffer */
2993     LTC_Type *base;       /*!< LTC peripheral base address */
2994     ltc_hash_algo_t algo; /*!< selected algorithm from the set of supported algorithms in ltc_drv_hash_algo */
2995     ltc_hash_algo_state_t state;         /*!< finite machine state of the hash software process */
2996     uint32_t word[kLTC_HashCtxNumWords]; /*!< LTC module context that needs to be saved/restored between LTC jobs */
2997 } ltc_hash_ctx_internal_t;
2998 
2999 /*******************************************************************************
3000  * HASH Code static
3001  ******************************************************************************/
ltc_hash_check_input_alg(ltc_hash_algo_t algo)3002 static status_t ltc_hash_check_input_alg(ltc_hash_algo_t algo)
3003 {
3004     if ((algo != kLTC_XcbcMac) && (algo != kLTC_Cmac)
3005 #if defined(FSL_FEATURE_LTC_HAS_SHA) && FSL_FEATURE_LTC_HAS_SHA
3006         && (algo != kLTC_Sha1) && (algo != kLTC_Sha224) && (algo != kLTC_Sha256)
3007 #endif /* FSL_FEATURE_LTC_HAS_SHA */
3008     )
3009     {
3010         return kStatus_InvalidArgument;
3011     }
3012     return kStatus_Success;
3013 }
3014 
ltc_hash_alg_is_cmac(ltc_hash_algo_t algo)3015 static inline bool ltc_hash_alg_is_cmac(ltc_hash_algo_t algo)
3016 {
3017     return ((algo == kLTC_XcbcMac) || (algo == kLTC_Cmac));
3018 }
3019 
3020 #if defined(FSL_FEATURE_LTC_HAS_SHA) && FSL_FEATURE_LTC_HAS_SHA
ltc_hash_alg_is_sha(ltc_hash_algo_t algo)3021 static inline bool ltc_hash_alg_is_sha(ltc_hash_algo_t algo)
3022 {
3023     return ((algo == kLTC_Sha1) || (algo == kLTC_Sha224) || (algo == kLTC_Sha256));
3024 }
3025 #endif /* FSL_FEATURE_LTC_HAS_SHA */
3026 
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)3027 static status_t ltc_hash_check_input_args(
3028     LTC_Type *base, ltc_hash_ctx_t *ctx, ltc_hash_algo_t algo, const uint8_t *key, uint32_t keySize)
3029 {
3030     /* Check validity of input algorithm */
3031     if (kStatus_Success != ltc_hash_check_input_alg(algo))
3032     {
3033         return kStatus_InvalidArgument;
3034     }
3035 
3036     if ((NULL == ctx) || (NULL == base))
3037     {
3038         return kStatus_InvalidArgument;
3039     }
3040 
3041     if (ltc_hash_alg_is_cmac(algo))
3042     {
3043         if ((NULL == key) || (!ltc_check_key_size(keySize)))
3044         {
3045             return kStatus_InvalidArgument;
3046         }
3047     }
3048 
3049     return kStatus_Success;
3050 }
3051 
ltc_hash_check_context(ltc_hash_ctx_internal_t * ctxInternal,const uint8_t * data)3052 static status_t ltc_hash_check_context(ltc_hash_ctx_internal_t *ctxInternal, const uint8_t *data)
3053 {
3054     if ((NULL == data) || (NULL == ctxInternal) || (NULL == ctxInternal->base) ||
3055         (kStatus_Success != ltc_hash_check_input_alg(ctxInternal->algo)))
3056     {
3057         return kStatus_InvalidArgument;
3058     }
3059     return kStatus_Success;
3060 }
3061 
ltc_hash_algo2mode(ltc_hash_algo_t algo,ltc_mode_algorithm_state_t asMode,uint32_t * algOutSize)3062 static uint32_t ltc_hash_algo2mode(ltc_hash_algo_t algo, ltc_mode_algorithm_state_t asMode, uint32_t *algOutSize)
3063 {
3064     uint32_t modeReg = 0u;
3065     uint32_t outSize = 0u;
3066 
3067     /* Set LTC algorithm */
3068     switch (algo)
3069     {
3070         case kLTC_XcbcMac:
3071             modeReg = (uint32_t)kLTC_AlgorithmAES | (uint32_t)kLTC_ModeXCBCMAC;
3072             outSize = 16u;
3073             break;
3074         case kLTC_Cmac:
3075             modeReg = (uint32_t)kLTC_AlgorithmAES | (uint32_t)kLTC_ModeCMAC;
3076             outSize = 16u;
3077             break;
3078 #if defined(FSL_FEATURE_LTC_HAS_SHA) && FSL_FEATURE_LTC_HAS_SHA
3079         case kLTC_Sha1:
3080             modeReg = (uint32_t)kLTC_AlgorithmSHA1;
3081             outSize = kLTC_OutLenSha1;
3082             break;
3083         case kLTC_Sha224:
3084             modeReg = (uint32_t)kLTC_AlgorithmSHA224;
3085             outSize = kLTC_OutLenSha224;
3086             break;
3087         case kLTC_Sha256:
3088             modeReg = (uint32_t)kLTC_AlgorithmSHA256;
3089             outSize = kLTC_OutLenSha256;
3090             break;
3091 #endif /* FSL_FEATURE_LTC_HAS_SHA */
3092         default:
3093             /* All the cases have been listed above, the default clause should not be reached. */
3094             break;
3095     }
3096 
3097     modeReg |= (uint32_t)asMode;
3098     if (NULL != algOutSize)
3099     {
3100         *algOutSize = outSize;
3101     }
3102 
3103     return modeReg;
3104 }
3105 
ltc_hash_engine_init(ltc_hash_ctx_internal_t * ctx)3106 static void ltc_hash_engine_init(ltc_hash_ctx_internal_t *ctx)
3107 {
3108     uint8_t *key;
3109     uint32_t keySize;
3110     LTC_Type *base;
3111     ltc_mode_symmetric_alg_t algo;
3112 
3113     base = ctx->base;
3114 #if defined(FSL_FEATURE_LTC_HAS_SHA) && FSL_FEATURE_LTC_HAS_SHA
3115     if (ltc_hash_alg_is_cmac(ctx->algo))
3116     {
3117 #endif /* FSL_FEATURE_LTC_HAS_SHA */
3118         /*
3119          *  word[kLtcCmacCtxKeySize] = key_length
3120          *  word[1-8] = key
3121          */
3122         keySize = ctx->word[kLTC_HashCtxKeySize];
3123         key     = (uint8_t *)&ctx->word[kLTC_HashCtxKeyStartIdx];
3124 
3125         /* set LTC mode register to INITIALIZE */
3126         algo = (ctx->algo == kLTC_XcbcMac) ? kLTC_ModeXCBCMAC : kLTC_ModeCMAC;
3127         (void)ltc_symmetric_init(base, key, (uint8_t)keySize, kLTC_AlgorithmAES, algo, kLTC_ModeEncrypt);
3128 #if defined(FSL_FEATURE_LTC_HAS_SHA) && FSL_FEATURE_LTC_HAS_SHA
3129     }
3130     else if (ltc_hash_alg_is_sha(ctx->algo))
3131     {
3132         /* Clear internal register states. */
3133         base->CW = (uint32_t)kLTC_ClearAll;
3134 
3135         /* Set byte swap on for several registers we will be reading and writing
3136          * user data to/from. */
3137         base->CTL |= kLTC_CtrlSwapAll;
3138     }
3139     else
3140     {
3141         /* do nothing in this case */
3142     }
3143 #endif /* FSL_FEATURE_LTC_HAS_SHA */
3144 }
3145 
ltc_hash_save_context(ltc_hash_ctx_internal_t * ctx)3146 static void ltc_hash_save_context(ltc_hash_ctx_internal_t *ctx)
3147 {
3148     uint32_t sz;
3149     LTC_Type *base;
3150 
3151     base = ctx->base;
3152     /* Get context size */
3153     switch (ctx->algo)
3154     {
3155         case kLTC_XcbcMac:
3156             /*
3157              *  word[0-3] = mac
3158              *  word[3-7] = k3
3159              *  word[8-11] = k2
3160              *  word[kLtcCmacCtxKeySize] = keySize
3161              */
3162             sz = 12U * sizeof(uint32_t);
3163             break;
3164         case kLTC_Cmac:
3165             /*
3166              *  word[0-3] = mac
3167              *  word[3-7] = L */
3168             sz = 8u * sizeof(uint32_t);
3169             break;
3170 #if defined(FSL_FEATURE_LTC_HAS_SHA) && FSL_FEATURE_LTC_HAS_SHA
3171         case kLTC_Sha1:
3172             sz = (kLTC_RunLenSha1);
3173             break;
3174         case kLTC_Sha224:
3175             sz = (kLTC_RunLenSha224);
3176             break;
3177         case kLTC_Sha256:
3178             sz = (kLTC_RunLenSha256);
3179             break;
3180 #endif /* FSL_FEATURE_LTC_HAS_SHA */
3181         default:
3182             sz = 0;
3183             break;
3184     }
3185 
3186     (void)ltc_get_context(base, (uint8_t *)&ctx->word[0], (uint8_t)sz, 0);
3187 
3188     if (true == ltc_hash_alg_is_cmac(ctx->algo))
3189     {
3190         /* word[12-19] = key */
3191         ltc_get_key(base, (uint8_t *)&ctx->word[kLTC_HashCtxKeyStartIdx],
3192                     (uint8_t)ctx->word[(uint8_t)kLTC_HashCtxKeySize]);
3193     }
3194 }
3195 
ltc_hash_restore_context(ltc_hash_ctx_internal_t * ctx)3196 static void ltc_hash_restore_context(ltc_hash_ctx_internal_t *ctx)
3197 {
3198     uint32_t sz;
3199     uint32_t keySize;
3200     LTC_Type *base;
3201 
3202     base = ctx->base;
3203     /* Get context size */
3204     switch (ctx->algo)
3205     {
3206         case kLTC_XcbcMac:
3207             /*
3208              *  word[0-3] = mac
3209              *  word[3-7] = k3
3210              *  word[8-11] = k2
3211              *  word[kLtcCmacCtxKeySize] = keySize
3212              */
3213             sz = 12U * sizeof(uint32_t);
3214             break;
3215         case kLTC_Cmac:
3216             /*
3217              *  word[0-3] = mac
3218              *  word[3-7] = L */
3219             sz = 8u * sizeof(uint32_t);
3220             break;
3221 #if defined(FSL_FEATURE_LTC_HAS_SHA) && FSL_FEATURE_LTC_HAS_SHA
3222         case kLTC_Sha1:
3223             sz = (kLTC_RunLenSha1);
3224             break;
3225         case kLTC_Sha224:
3226             sz = (kLTC_RunLenSha224);
3227             break;
3228         case kLTC_Sha256:
3229             sz = (kLTC_RunLenSha256);
3230             break;
3231 #endif /* FSL_FEATURE_LTC_HAS_SHA */
3232         default:
3233             sz = 0;
3234             break;
3235     }
3236 
3237     (void)ltc_set_context(base, (const uint8_t *)&ctx->word[0], (uint8_t)sz, 0);
3238 
3239     if (ltc_hash_alg_is_cmac(ctx->algo))
3240     {
3241         /*
3242          *  word[12-19] = key
3243          *  word[kLtcCmacCtxKeySize] = keySize
3244          */
3245         base->CW = (uint32_t)kLTC_ClearKey; /* clear Key and Key Size registers */
3246 
3247         keySize = ctx->word[kLTC_HashCtxKeySize];
3248         /* Write the key in place. */
3249         ltc_set_key(base, (const uint8_t *)&ctx->word[kLTC_HashCtxKeyStartIdx], (uint8_t)keySize);
3250 
3251         /* Write the key size.  This must be done after writing the key, and this
3252          * action locks the ability to modify the key registers. */
3253         base->KS = keySize;
3254     }
3255 }
3256 
ltc_hash_prepare_context_switch(LTC_Type * base)3257 static void ltc_hash_prepare_context_switch(LTC_Type *base)
3258 {
3259     base->CW  = (uint32_t)kLTC_ClearDataSize | (uint32_t)kLTC_ClearMode;
3260     base->STA = (uint32_t)kLTC_StatusDoneIsr;
3261 }
3262 
ltc_hash_get_block_size(ltc_hash_algo_t algo)3263 static uint32_t ltc_hash_get_block_size(ltc_hash_algo_t algo)
3264 {
3265     if ((algo == kLTC_XcbcMac) || (algo == kLTC_Cmac))
3266     {
3267         return (uint32_t)LTC_AES_BLOCK_SIZE;
3268     }
3269 #if defined(FSL_FEATURE_LTC_HAS_SHA) && FSL_FEATURE_LTC_HAS_SHA
3270     else if ((algo == kLTC_Sha1) || (algo == kLTC_Sha224) || (algo == kLTC_Sha256))
3271     {
3272         return (uint32_t)LTC_SHA_BLOCK_SIZE;
3273     }
3274     else
3275     {
3276         return 0;
3277     }
3278 #else
3279     return 0;
3280 #endif
3281 }
3282 
ltc_hash_block_to_ififo(LTC_Type * base,const ltc_hash_block_t * blk,uint32_t numBytes,uint32_t blockSize)3283 static void ltc_hash_block_to_ififo(LTC_Type *base, const ltc_hash_block_t *blk, uint32_t numBytes, uint32_t blockSize)
3284 {
3285     uint32_t i = 0;
3286     uint32_t words;
3287 
3288     words = numBytes / 4u;
3289     if (0U != (numBytes % 4u))
3290     {
3291         words++;
3292     }
3293 
3294     if (words > blockSize / 4u)
3295     {
3296         words = blockSize / 4u;
3297     }
3298 
3299     while (i < words)
3300     {
3301         if (0U == (base->FIFOSTA & LTC_FIFOSTA_IFF_MASK))
3302         {
3303             /* Copy data to the input FIFO. */
3304             base->IFIFO = blk->w[i++];
3305         }
3306     }
3307 }
3308 
ltc_hash_move_to_ififo(ltc_hash_ctx_internal_t * ctx,const uint8_t * data,uint32_t dataSize,uint32_t blockSize)3309 static void ltc_hash_move_to_ififo(ltc_hash_ctx_internal_t *ctx,
3310                                    const uint8_t *data,
3311                                    uint32_t dataSize,
3312                                    uint32_t blockSize)
3313 {
3314     ltc_hash_block_t blkZero;
3315     uint32_t i;
3316 
3317     for (i = 0; i < ARRAY_SIZE(blkZero.w); i++)
3318     {
3319         blkZero.w[i] = 0;
3320     }
3321 
3322     while (0U != dataSize)
3323     {
3324         if (dataSize >= blockSize)
3325         {
3326             ltc_memcpy(&ctx->blk, data, blockSize);
3327             ltc_hash_block_to_ififo(ctx->base, (const ltc_hash_block_t *)(uint32_t)&ctx->blk, blockSize, blockSize);
3328             dataSize -= blockSize;
3329             data = &data[blockSize];
3330         }
3331         else
3332         {
3333             /* last incomplete 16/64-bytes block of this message chunk */
3334             ltc_memcpy(&ctx->blk, &blkZero, sizeof(ctx->blk));
3335             ltc_memcpy(&ctx->blk, data, dataSize);
3336             ctx->blksz = dataSize;
3337             dataSize   = 0;
3338         }
3339     }
3340 }
3341 
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)3342 static status_t ltc_hash_merge_and_flush_buf(ltc_hash_ctx_internal_t *ctx,
3343                                              const uint8_t *input,
3344                                              uint32_t inputSize,
3345                                              ltc_mode_t modeReg,
3346                                              uint32_t blockSize,
3347                                              uint32_t *consumedSize)
3348 {
3349     uint32_t sz;
3350     LTC_Type *base;
3351     status_t status = kStatus_Success;
3352 
3353     base = ctx->base;
3354     sz   = 0;
3355     if (0U != ctx->blksz)
3356     {
3357         sz = blockSize - ctx->blksz;
3358         if (sz > inputSize)
3359         {
3360             sz = inputSize;
3361         }
3362         ltc_memcpy(ctx->blk.b + ctx->blksz, input, sz);
3363         input = &input[sz];
3364         inputSize -= sz;
3365         ctx->blksz += sz;
3366 
3367         if (ctx->blksz == blockSize)
3368         {
3369             base->DS = blockSize;
3370             ltc_hash_block_to_ififo(base, (const ltc_hash_block_t *)(uint32_t)&ctx->blk, blockSize, blockSize);
3371             ctx->blksz = 0;
3372 
3373             status = ltc_wait(base);
3374             if (kStatus_Success != status)
3375             {
3376                 return status;
3377             }
3378 
3379             /* if there is still inputSize left, make sure LTC alg.state is set to UPDATE and continue */
3380             if (0U != inputSize)
3381             {
3382                 /* set algorithm state to UPDATE */
3383                 modeReg &= ~LTC_MD_AS_MASK;
3384                 modeReg |= (uint32_t)kLTC_ModeUpdate;
3385                 base->MD = modeReg;
3386             }
3387         }
3388     }
3389     if (NULL != consumedSize)
3390     {
3391         *consumedSize = sz;
3392     }
3393     return status;
3394 }
3395 
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)3396 static status_t ltc_hash_move_rest_to_context(
3397     ltc_hash_ctx_internal_t *ctx, const uint8_t *data, uint32_t dataSize, ltc_mode_t modeReg, uint32_t blockSize)
3398 {
3399     status_t status = kStatus_Success;
3400     ltc_hash_block_t blkZero;
3401     uint32_t i;
3402 
3403     /* make blkZero clear */
3404     for (i = 0; i < ARRAY_SIZE(blkZero.w); i++)
3405     {
3406         blkZero.w[i] = 0;
3407     }
3408 
3409     while (0U != dataSize)
3410     {
3411         if (dataSize > blockSize)
3412         {
3413             dataSize -= blockSize;
3414             data = &data[blockSize];
3415         }
3416         else
3417         {
3418             if (dataSize + ctx->blksz > blockSize)
3419             {
3420                 uint32_t sz = 0;
3421                 status      = ltc_hash_merge_and_flush_buf(ctx, data, dataSize, modeReg, blockSize, &sz);
3422                 if (kStatus_Success != status)
3423                 {
3424                     return status;
3425                 }
3426                 data = &data[sz];
3427                 dataSize -= sz;
3428             }
3429             /* last incomplete 16/64-bytes block of this message chunk */
3430             ltc_memcpy(&ctx->blk, &blkZero, blockSize);
3431             ltc_memcpy(&ctx->blk, data, dataSize);
3432             ctx->blksz = dataSize;
3433             dataSize   = 0;
3434         }
3435     }
3436     return status;
3437 }
3438 
ltc_hash_process_input_data(ltc_hash_ctx_internal_t * ctx,const uint8_t * input,uint32_t inputSize,ltc_mode_t modeReg)3439 static status_t ltc_hash_process_input_data(ltc_hash_ctx_internal_t *ctx,
3440                                             const uint8_t *input,
3441                                             uint32_t inputSize,
3442                                             ltc_mode_t modeReg)
3443 {
3444     uint32_t sz = 0;
3445     LTC_Type *base;
3446     uint32_t blockSize = 0;
3447     status_t status    = kStatus_Success;
3448 
3449     blockSize = ltc_hash_get_block_size(ctx->algo);
3450     if (blockSize == 0u)
3451     {
3452         return kStatus_Fail;
3453     }
3454     base = ctx->base;
3455 
3456     /* fill context struct blk and flush to LTC ififo in case it is full block */
3457     status = ltc_hash_merge_and_flush_buf(ctx, input, inputSize, modeReg, blockSize, &sz);
3458     if (kStatus_Success != status)
3459     {
3460         return status;
3461     }
3462     input = &input[sz];
3463     inputSize -= sz;
3464 
3465     /* if there is still more than or equal to 64 bytes, move each 64 bytes through LTC */
3466     sz = LTC_DS_DS_MASK + 1u - LTC_HASH_BLOCK_SIZE;
3467     while (0U != inputSize)
3468     {
3469         if (inputSize < sz)
3470         {
3471             uint32_t lastSize;
3472 
3473             lastSize = inputSize % blockSize;
3474             if (lastSize == 0u)
3475             {
3476                 lastSize = blockSize;
3477             }
3478             inputSize -= lastSize;
3479             if (0U != inputSize)
3480             {
3481                 /* move all complete blocks to ififo. */
3482                 base->DS = inputSize;
3483                 ltc_hash_move_to_ififo(ctx, input, inputSize, blockSize);
3484 
3485                 status = ltc_wait(base);
3486                 if (kStatus_Success != status)
3487                 {
3488                     return status;
3489                 }
3490 
3491                 input = &input[inputSize];
3492             }
3493             /* keep last (in)complete 16-bytes block in context struct. */
3494             /* when 3rd argument of cmac_move_to_ififo() is <= 16 bytes, it only stores the data to context struct */
3495             status = ltc_hash_move_rest_to_context(ctx, input, lastSize, modeReg, blockSize);
3496             if (kStatus_Success != status)
3497             {
3498                 return status;
3499             }
3500             inputSize = 0;
3501         }
3502         else
3503         {
3504             base->DS = sz;
3505             ltc_hash_move_to_ififo(ctx, input, sz, blockSize);
3506             inputSize -= sz;
3507             input = &input[sz];
3508 
3509             status = ltc_wait(base);
3510             if (kStatus_Success != status)
3511             {
3512                 return status;
3513             }
3514 
3515             /* set algorithm state to UPDATE */
3516             modeReg &= ~LTC_MD_AS_MASK;
3517             modeReg |= (uint32_t)kLTC_ModeUpdate;
3518             base->MD = modeReg;
3519         }
3520     } /* end while */
3521 
3522     return status;
3523 }
3524 
3525 /*******************************************************************************
3526  * HASH Code public
3527  ******************************************************************************/
3528 /*!
3529  * brief Initialize HASH context
3530  *
3531  * This function initialize the HASH.
3532  * Key shall be supplied if the underlaying algoritm is AES XCBC-MAC or CMAC.
3533  * Key shall be NULL if the underlaying algoritm is SHA.
3534  *
3535  * For XCBC-MAC, the key length must be 16. For CMAC, the key length can be
3536  * the AES key lengths supported by AES engine. For MDHA the key length argument
3537  * is ignored.
3538  *
3539  * param base LTC peripheral base address
3540  * param[out] ctx Output hash context
3541  * param algo Underlaying algorithm to use for hash computation.
3542  * param key Input key (NULL if underlaying algorithm is SHA)
3543  * param keySize Size of input key in bytes
3544  * return Status of initialization
3545  */
LTC_HASH_Init(LTC_Type * base,ltc_hash_ctx_t * ctx,ltc_hash_algo_t algo,const uint8_t * key,uint32_t keySize)3546 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)
3547 {
3548     status_t ret;
3549     ltc_hash_ctx_internal_t *ctxInternal;
3550     uint32_t i;
3551 
3552     ret = ltc_hash_check_input_args(base, ctx, algo, key, keySize);
3553     if (ret != kStatus_Success)
3554     {
3555         return ret;
3556     }
3557 
3558     /* set algorithm in context struct for later use */
3559     ctxInternal       = (ltc_hash_ctx_internal_t *)(uint32_t)ctx;
3560     ctxInternal->algo = algo;
3561     for (i = 0; i < (uint32_t)kLTC_HashCtxNumWords; i++)
3562     {
3563         ctxInternal->word[i] = 0u;
3564     }
3565 
3566     /* Steps required only using AES engine */
3567     if (ltc_hash_alg_is_cmac(algo))
3568     {
3569         /* store input key and key length in context struct for later use */
3570         ctxInternal->word[kLTC_HashCtxKeySize] = keySize;
3571         ltc_memcpy(&ctxInternal->word[kLTC_HashCtxKeyStartIdx], key, keySize);
3572     }
3573     ctxInternal->blksz = 0u;
3574     uint32_t j;
3575     j = sizeof(ctxInternal->blk.w) / sizeof(ctxInternal->blk.w[0]);
3576     for (i = 0; i < j; i++)
3577     {
3578         ctxInternal->blk.w[0] = 0u;
3579     }
3580     ctxInternal->state = kLTC_HashInit;
3581     ctxInternal->base  = base;
3582 
3583     return kStatus_Success;
3584 }
3585 
3586 /*!
3587  * brief Add data to current HASH
3588  *
3589  * Add data to current HASH. This can be called repeatedly with an arbitrary amount of data to be
3590  * hashed.
3591  *
3592  * param[in,out] ctx HASH context
3593  * param input Input data
3594  * param inputSize Size of input data in bytes
3595  * return Status of the hash update operation
3596  */
LTC_HASH_Update(ltc_hash_ctx_t * ctx,const uint8_t * input,uint32_t inputSize)3597 status_t LTC_HASH_Update(ltc_hash_ctx_t *ctx, const uint8_t *input, uint32_t inputSize)
3598 {
3599     bool isUpdateState;
3600     ltc_mode_t modeReg = 0; /* read and write LTC mode register */
3601     LTC_Type *base;
3602     status_t status;
3603     ltc_hash_ctx_internal_t *ctxInternal;
3604     uint32_t blockSize;
3605 
3606     ctxInternal = (ltc_hash_ctx_internal_t *)(uint32_t)ctx;
3607     status      = ltc_hash_check_context(ctxInternal, input);
3608     if (kStatus_Success != status)
3609     {
3610         return status;
3611     }
3612 
3613     base      = ctxInternal->base;
3614     blockSize = ltc_hash_get_block_size(ctxInternal->algo);
3615     /* if we are still less than 64 bytes, keep only in context */
3616     if ((ctxInternal->blksz + inputSize) <= blockSize)
3617     {
3618         ltc_memcpy((&ctxInternal->blk.b[0]) + ctxInternal->blksz, input, inputSize);
3619         ctxInternal->blksz += inputSize;
3620         return status;
3621     }
3622     else
3623     {
3624         isUpdateState = ctxInternal->state == kLTC_HashUpdate;
3625         if (ctxInternal->state == kLTC_HashInit)
3626         {
3627             /* set LTC mode register to INITIALIZE job */
3628             ltc_hash_engine_init(ctxInternal);
3629 
3630 #if defined(FSL_FEATURE_LTC_HAS_SHA) && FSL_FEATURE_LTC_HAS_SHA
3631             if (ltc_hash_alg_is_cmac(ctxInternal->algo))
3632             {
3633 #endif /* FSL_FEATURE_LTC_HAS_SHA */
3634                 ctxInternal->state = kLTC_HashUpdate;
3635                 isUpdateState      = true;
3636                 base->DS           = 0u;
3637                 status             = ltc_wait(base);
3638 #if defined(FSL_FEATURE_LTC_HAS_SHA) && FSL_FEATURE_LTC_HAS_SHA
3639             }
3640             else
3641             {
3642                 /* Set the proper block and algorithm mode. */
3643                 modeReg  = ltc_hash_algo2mode(ctxInternal->algo, kLTC_ModeInit, NULL);
3644                 base->MD = modeReg;
3645 
3646                 ctxInternal->state = kLTC_HashUpdate;
3647                 status             = ltc_hash_process_input_data(ctxInternal, input, inputSize, modeReg);
3648                 ltc_hash_save_context(ctxInternal);
3649             }
3650 #endif /* FSL_FEATURE_LTC_HAS_SHA */
3651         }
3652         else if (isUpdateState)
3653         {
3654             /* restore LTC context from context struct */
3655             ltc_hash_restore_context(ctxInternal);
3656         }
3657         else
3658         {
3659             /* nothing special at this place */
3660         }
3661     }
3662 
3663     if (kStatus_Success != status)
3664     {
3665         return status;
3666     }
3667 
3668     if (isUpdateState)
3669     {
3670         /* set LTC mode register to UPDATE job */
3671         ltc_hash_prepare_context_switch(base);
3672         base->CW = (uint32_t)kLTC_ClearDataSize;
3673         modeReg  = ltc_hash_algo2mode(ctxInternal->algo, kLTC_ModeUpdate, NULL);
3674         base->MD = modeReg;
3675 
3676         /* process input data and save LTC context to context structure */
3677         status = ltc_hash_process_input_data(ctxInternal, input, inputSize, modeReg);
3678         ltc_hash_save_context(ctxInternal);
3679     }
3680     ltc_clear_all(base, false);
3681     return status;
3682 }
3683 
3684 /*!
3685  * brief Finalize hashing
3686  *
3687  * Outputs the final hash and erases the context.
3688  *
3689  * param[in,out] ctx Input hash context
3690  * param[out] output Output hash data
3691  * param[out] outputSize Output parameter storing the size of the output hash in bytes
3692  * return Status of the hash finish operation
3693  */
LTC_HASH_Finish(ltc_hash_ctx_t * ctx,uint8_t * output,uint32_t * outputSize)3694 status_t LTC_HASH_Finish(ltc_hash_ctx_t *ctx, uint8_t *output, uint32_t *outputSize)
3695 {
3696     ltc_mode_t modeReg; /* read and write LTC mode register */
3697     LTC_Type *base;
3698     uint32_t algOutSize = 0;
3699     status_t status;
3700     ltc_hash_ctx_internal_t *ctxInternal;
3701     uint32_t *ctxW;
3702     uint32_t i;
3703 
3704     ctxInternal = (ltc_hash_ctx_internal_t *)(uint32_t)ctx;
3705     status      = ltc_hash_check_context(ctxInternal, output);
3706     if (kStatus_Success != status)
3707     {
3708         return status;
3709     }
3710 
3711     base = ctxInternal->base;
3712     ltc_hash_prepare_context_switch(base);
3713 
3714     base->CW = (uint32_t)kLTC_ClearDataSize;
3715     if (ctxInternal->state == kLTC_HashInit)
3716     {
3717         ltc_hash_engine_init(ctxInternal);
3718 #if defined(FSL_FEATURE_LTC_HAS_SHA) && FSL_FEATURE_LTC_HAS_SHA
3719         if (ltc_hash_alg_is_cmac(ctxInternal->algo))
3720         {
3721 #endif /* FSL_FEATURE_LTC_HAS_SHA */
3722             base->DS = 0u;
3723             status   = ltc_wait(base);
3724             if (kStatus_Success != status)
3725             {
3726                 return status;
3727             }
3728             modeReg = ltc_hash_algo2mode(ctxInternal->algo, kLTC_ModeFinalize, &algOutSize);
3729 #if defined(FSL_FEATURE_LTC_HAS_SHA) && FSL_FEATURE_LTC_HAS_SHA
3730         }
3731         else
3732         {
3733             modeReg = ltc_hash_algo2mode(ctxInternal->algo, kLTC_ModeInitFinal, &algOutSize);
3734         }
3735 #endif /* FSL_FEATURE_LTC_HAS_SHA */
3736         base->MD = modeReg;
3737     }
3738     else
3739     {
3740         modeReg  = ltc_hash_algo2mode(ctxInternal->algo, kLTC_ModeFinalize, &algOutSize);
3741         base->MD = modeReg;
3742 
3743         /* restore LTC context from context struct */
3744         ltc_hash_restore_context(ctxInternal);
3745     }
3746 
3747     /* flush message last incomplete block, if there is any, or write zero to data size register. */
3748     base->DS = ctxInternal->blksz;
3749     ltc_hash_block_to_ififo(base, (const ltc_hash_block_t *)(uint32_t)&ctxInternal->blk, ctxInternal->blksz,
3750                             ltc_hash_get_block_size(ctxInternal->algo));
3751     /* Wait for finish of the encryption */
3752     status = ltc_wait(base);
3753 
3754     if (NULL != outputSize)
3755     {
3756         if (algOutSize < *outputSize)
3757         {
3758             *outputSize = algOutSize;
3759         }
3760         else
3761         {
3762             algOutSize = *outputSize;
3763         }
3764     }
3765 
3766     (void)ltc_get_context(base, &output[0], (uint8_t)algOutSize, 0u);
3767 
3768     ctxW = (uint32_t *)(uint32_t)ctx;
3769     for (i = 0; i < (uint32_t)LTC_HASH_CTX_SIZE; i++)
3770     {
3771         ctxW[i] = 0u;
3772     }
3773 
3774     ltc_clear_all(base, false);
3775     return status;
3776 }
3777 
3778 /*!
3779  * brief Create HASH on given data
3780  *
3781  * Perform the full keyed HASH in one function call.
3782  *
3783  * param base LTC peripheral base address
3784  * param algo Block cipher algorithm to use for CMAC creation
3785  * param input Input data
3786  * param inputSize Size of input data in bytes
3787  * param key Input key
3788  * param keySize Size of input key in bytes
3789  * param[out] output Output hash data
3790  * param[out] outputSize Output parameter storing the size of the output hash in bytes
3791  * return Status of the one call hash operation.
3792  */
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)3793 status_t LTC_HASH(LTC_Type *base,
3794                   ltc_hash_algo_t algo,
3795                   const uint8_t *input,
3796                   uint32_t inputSize,
3797                   const uint8_t *key,
3798                   uint32_t keySize,
3799                   uint8_t *output,
3800                   uint32_t *outputSize)
3801 {
3802     status_t status;
3803     ltc_hash_ctx_t ctx;
3804 
3805     status = LTC_HASH_Init(base, &ctx, algo, key, keySize);
3806     if (status != kStatus_Success)
3807     {
3808         return status;
3809     }
3810     status = LTC_HASH_Update(&ctx, input, inputSize);
3811     if (status != kStatus_Success)
3812     {
3813         return status;
3814     }
3815     status = LTC_HASH_Finish(&ctx, output, outputSize);
3816     return status;
3817 }
3818 
3819 /*******************************************************************************
3820  * PKHA Code static
3821  ******************************************************************************/
3822 #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)3823 static status_t ltc_pkha_clear_regabne(LTC_Type *base, bool A, bool B, bool N, bool E)
3824 {
3825     ltc_mode_t mode;
3826 
3827     /* Set the PKHA algorithm and the appropriate function. */
3828     mode = (uint32_t)kLTC_AlgorithmPKHA | 1U;
3829 
3830     /* Set ram area to clear. Clear all. */
3831     if (A)
3832     {
3833         mode |= ((uint32_t)1U << 19U);
3834     }
3835     if (B)
3836     {
3837         mode |= ((uint32_t)1U << 18U);
3838     }
3839     if (N)
3840     {
3841         mode |= ((uint32_t)1U << 16U);
3842     }
3843     if (E)
3844     {
3845         mode |= ((uint32_t)1U << 17U);
3846     }
3847 
3848     /* Write the mode register to the hardware.
3849      * NOTE: This will begin the operation. */
3850     base->MDPK = mode;
3851 
3852     /* Wait for 'done' */
3853     return ltc_wait(base);
3854 }
3855 
ltc_pkha_default_parms(ltc_pkha_mode_params_t * params)3856 static void ltc_pkha_default_parms(ltc_pkha_mode_params_t *params)
3857 {
3858     params->func        = (ltc_pkha_func_t)0;
3859     params->arithType   = kLTC_PKHA_IntegerArith;
3860     params->montFormIn  = kLTC_PKHA_NormalValue;
3861     params->montFormOut = kLTC_PKHA_NormalValue;
3862     params->srcReg      = kLTC_PKHA_RegAll;
3863     params->srcQuad     = kLTC_PKHA_Quad0;
3864     params->dstReg      = kLTC_PKHA_RegAll;
3865     params->dstQuad     = kLTC_PKHA_Quad0;
3866     params->equalTime   = kLTC_PKHA_NoTimingEqualized;
3867     params->r2modn      = kLTC_PKHA_CalcR2;
3868 }
3869 
ltc_pkha_write_word(LTC_Type * base,ltc_pkha_reg_area_t reg,uint8_t index,uint32_t data)3870 static void ltc_pkha_write_word(LTC_Type *base, ltc_pkha_reg_area_t reg, uint8_t index, uint32_t data)
3871 {
3872     switch (reg)
3873     {
3874         case kLTC_PKHA_RegA:
3875             base->PKA[index] = data;
3876             break;
3877 
3878         case kLTC_PKHA_RegB:
3879             base->PKB[index] = data;
3880             break;
3881 
3882         case kLTC_PKHA_RegN:
3883             base->PKN[index] = data;
3884             break;
3885 
3886         case kLTC_PKHA_RegE:
3887             base->PKE[index] = data;
3888             break;
3889 
3890         default:
3891             /* All the cases have been listed above, the default clause should not be reached. */
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