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