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)<C_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)<C_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)<C_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)<C_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(¶ms);
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, ¶ms);
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(¶ms);
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, ¶ms);
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(¶ms);
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, ¶ms);
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(¶ms);
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, ¶ms);
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(¶ms);
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, ¶ms);
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(¶ms);
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, ¶ms);
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(¶ms);
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, ¶ms);
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(¶ms);
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, ¶ms);
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(¶ms);
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, ¶ms);
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(¶ms);
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, ¶ms);
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(¶ms);
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, ¶ms);
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(¶ms);
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, ¶ms);
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(¶ms);
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, ¶ms);
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