1/*
2 * Copyright 2022-2026 NXP
3 * SPDX-License-Identifier: BSD-3-Clause
4 */
5/*! *********************************************************************************
6 * \file
7 *
8 * This is the source file for the security module used by the connectivity stacks. The Security
9 * Module SecLib provides an abstraction from the Hardware to the upper layer.
10 * In this file, a wrapper to SSS component is implemented.
11 *
12 ********************************************************************************** */
13
14/*! *********************************************************************************
15*************************************************************************************
16* Include
17*************************************************************************************
18********************************************************************************** */
19
20#include "fsl_device_registers.h"
21#include "fsl_os_abstraction.h"
22#include "fsl_component_mem_manager.h"
23#include "fsl_sss_sscp.h"
24#include "sss_crypto.h"
25
26#include "FunctionLib.h"
27#include "fwk_platform.h"
28#include "SecLib.h"
29#include "RNG_Interface.h"
30#include "fsl_debug_console.h"
31
32#include "SecLib_ecp256.h"
33#include "CryptoLibSW.h"
34
35#include "fwk_config.h"
36
37#include <assert.h>
38
39/*! *********************************************************************************
40*************************************************************************************
41* Private macros
42*************************************************************************************
43********************************************************************************** */
44
45#if defined __IAR_SYSTEMS_ICC__
46#define STATIC_ASSERT static_assert
47#else
48#define STATIC_ASSERT _Static_assert
49#endif
50
51#if (defined(USE_RTOS) && (USE_RTOS > 0))
52/* On ELE Sentinel, the mutex is mandatory */
53#define gSecLibUseMutex_c TRUE
54#else
55#define gSecLibUseMutex_c FALSE
56#endif
57
58secResultType_t SecLibMutexCreate(void);
59
60#define SECLIB_MUTEX_LOCK() (void)SecLibMutexLock()
61#define SECLIB_MUTEX_UNLOCK() (void)SecLibMutexUnlock()
62
63#define KEY_ID_BLE0 0x426c6530
64#define ELE_S200_KEY_STORE_USER_ID_GENERIC 0
65
66#ifndef gSecLibAllowLtkFromBlob_c
67#define gSecLibAllowLtkFromBlob_c 0
68#endif
69
70/* Set all crypto operations needed */
71#define mSecLibKeyPropCryptoAlgoAll_c \
72 SSS_KEYPROP_OPERATION_AES | SSS_KEYPROP_OPERATION_MAC | SSS_KEYPROP_OPERATION_AEAD | SSS_KEYPROP_OPERATION_ASYM | \
73 SSS_KEYPROP_OPERATION_KDF
74
75/*
76 * __DSP_PRESENT is defined in the device specific file, however avoid use of __DSP_PRESENT to avoid
77 * a dependency with SDK.
78 * It is likely to be present on all Core M33, Core M7 and Core M4 devices.
79 * Nonetheless RW61x was designed without ARM DSP extension, in which case avoid defining
80 * gSecLibUseDspExtension_d.
81 */
82
83#ifndef gSecLibUseDspExtension_d
84#define gSecLibUseDspExtension_d 0
85#endif
86
87#define AES_BLOCK_ALIGN_MASK (0x0000000fUL)
88/* Compute number of whole AES block bytes */
89#define AES_WHOLE_BLOCK_BYTES(_LEN_) ((uint32_t)(_LEN_) & ~AES_BLOCK_ALIGN_MASK)
90/* Compute number of residual bytes constituting a partial AES block */
91#define AES_PARTIAL_BLOCK_BYTES(_LEN_) ((uint32_t)(_LEN_)&AES_BLOCK_ALIGN_MASK)
92
93/*! *********************************************************************************
94*************************************************************************************
95* Private type definitions
96*************************************************************************************
97********************************************************************************** */
98
99/************************************************************************************
100*************************************************************************************
101* Private memory declarations
102*************************************************************************************
103************************************************************************************/
104#if gSecLibUseMutex_c
105/*! Mutex used to protect the AES Context when an RTOS is used. */
106static OSA_MUTEX_HANDLE_DEFINE(mSecLibSssMutexId);
107#endif /* gSecLibUseMutex_c */
108
109static sss_ecp256_context_t g_ECP_KeyPair;
110static sss_ecp256_context_t *pECPKeyPair = ((void *)0);
111
112static size_t ecdhKeyPairBlobSize = (3 * ECP256_COORDINATE_LEN) + BLOB_DATA_OVERLAY_BYTE_LEN;
113static uint8_t ecdhKeyPairBlob[(3 * ECP256_COORDINATE_LEN) + BLOB_DATA_OVERLAY_BYTE_LEN];
114
115static bool_t IsSecLibEcdhContextInit = false;
116#if (gSecLibUseBleDebugKeys_d == 1)
117/*! Bluetooth LE debug keys as specified in section 2.3.5.6.1 vol. 3, part H of the Bluetooth Core specification version 5.4 */
118static const ecp256KeyPair_t mBleDebugKeyPair = {
119 .public_key.components_8bit.x = {0x20, 0xb0, 0x03, 0xd2, 0xf2, 0x97, 0xbe, 0x2c, 0x5e, 0x2c, 0x83,
120 0xa7, 0xe9, 0xf9, 0xa5, 0xb9, 0xef, 0xf4, 0x91, 0x11, 0xac, 0xf4,
121 0xfd, 0xdb, 0xcc, 0x03, 0x01, 0x48, 0x0e, 0x35, 0x9d, 0xe6},
122 .public_key.components_8bit.y = {0xdc, 0x80, 0x9c, 0x49, 0x65, 0x2a, 0xeb, 0x6d, 0x63, 0x32, 0x9a,
123 0xbf, 0x5a, 0x52, 0x15, 0x5c, 0x76, 0x63, 0x45, 0xc2, 0x8f, 0xed,
124 0x30, 0x24, 0x74, 0x1c, 0x8e, 0xd0, 0x15, 0x89, 0xd2, 0x8b},
125 .private_key.raw_8bit = {0x3f, 0x49, 0xf6, 0xd4, 0xa3, 0xc5, 0x5f, 0x38, 0x74, 0xc9, 0xb3,
126 0xe3, 0xd2, 0x10, 0x3f, 0x50, 0x4a, 0xff, 0x60, 0x7b, 0xeb, 0x40,
127 0xb7, 0x99, 0x58, 0x99, 0xb8, 0xa6, 0xcd, 0x3c, 0x1a, 0xbd}};
128#endif /* gSecLibUseBleDebugKeys_d */
129/*! *********************************************************************************
130*************************************************************************************
131* Public prototypes
132*************************************************************************************
133********************************************************************************** */
134
135/*! *********************************************************************************
136*************************************************************************************
137* Private prototypes
138*************************************************************************************
139********************************************************************************** */
140
141static sss_status_t ELKE_BLE_SM_F5_DeriveKeysSecure(const uint8_t *pPubDhKeyObj,
142 const uint8_t *pDerivationDataMacKey,
143 const uint8_t *pDerivationDataLTK,
144 uint8_t *pMacKey,
145 uint8_t *pLTKBlob);
146
147static uint8_t SecLib_Padding(const uint8_t *lastb, uint8_t pad_block[AES_BLOCK_SIZE], uint8_t length);
148static uint8_t SecLib_DePadding(const uint8_t pad_block[AES_BLOCK_SIZE]);
149static bool ECP256_LePointValid(const ecp256Point_t *P);
150
151/*! *********************************************************************************
152*************************************************************************************
153* Public functions
154*************************************************************************************
155********************************************************************************** */
156secResultType_t SecLibMutexCreate(void)
157{
158 secResultType_t st = gSecSuccess_c;
159#if gSecLibUseMutex_c
160 static bool seclib_mutex_created = false;
161
162 if (!seclib_mutex_created)
163 {
164 /*! Initialize the SecLib Mutex here. If not already done by RNG module */
165 osa_status_t ret = OSA_MutexCreate((osa_mutex_handle_t)mSecLibSssMutexId);
166
167 if (KOSA_StatusSuccess != ret)
168 {
169 st = gSecAllocError_c;
170 assert(false);
171 }
172 else
173 {
174 seclib_mutex_created = true;
175 }
176 }
177#endif
178 return st;
179}
180secResultType_t SecLibMutexLock(void)
181{
182#if gSecLibUseMutex_c
183 osa_status_t ret = OSA_MutexLock((osa_mutex_handle_t)mSecLibSssMutexId, osaWaitForever_c);
184 return (ret == KOSA_StatusSuccess) ? gSecSuccess_c : gSecError_c;
185#else
186 return gSecSuccess_c;
187#endif
188}
189
190secResultType_t SecLibMutexUnlock(void)
191{
192#if gSecLibUseMutex_c
193 osa_status_t ret = OSA_MutexUnlock((osa_mutex_handle_t)mSecLibSssMutexId);
194 return (ret == KOSA_StatusSuccess) ? gSecSuccess_c : gSecError_c;
195#else
196 return gSecSuccess_c;
197#endif
198}
199
200/*! *********************************************************************************
201 * \brief This function performs initialization of the cryptographic HW acceleration.
202 *
203 ********************************************************************************** */
204
205void SecLib_Init(void)
206{
207 /* Initialize cryptographic hardware.*/
208 CLOCK_EnableClock(kCLOCK_Secsubsys);
209
210 (void)SecLibMutexCreate();
211}
212
213/*! *********************************************************************************
214 * \brief This function performs initialization of the cryptografic HW acceleration.
215 *
216 ********************************************************************************** */
217void SecLib_ReInit(void)
218{
219 IsSecLibEcdhContextInit = false;
220 CRYPTO_ELEMU_reset();
221 (void)CRYPTO_ReinitHardware();
222}
223
224/*! *********************************************************************************
225 * \brief This function will allow reinitizialize the cryptographic HW acceleration
226 * next time we need it, typically after lowpower mode.
227 *
228 ********************************************************************************** */
229void SecLib_DeInit(void)
230{
231 IsSecLibEcdhContextInit = false;
232 CRYPTO_DeinitHardware();
233}
234
235/*! *********************************************************************************
236 * \brief This function performs AES-128-ECB encryption on a message block.
237 * This function only accepts input lengths which are multiple
238 * of 16 bytes (AES 128 block size).
239 *
240 * \param[in] pInput Pointer to the location of the input message.
241 *
242 * \param[in] inputLen Input message length in bytes.
243 *
244 * \param[in] pKey Pointer to the location of the 128-bit key.
245 *
246 * \param[out] pOutput Pointer to the location to store the ciphered output.
247 *
248 * \pre All Input/Output pointers must refer to a memory address aligned to 4 bytes!
249 *
250 ********************************************************************************** */
251static int SecLib_AES_128_cipher(
252 const uint8_t *pInput, uint32_t inputLen, const uint8_t *pKey, uint8_t *pOutput, bool cipherNdecipher)
253{
254 status_t st;
255 aes_context_t ctx;
256 SECLIB_MUTEX_LOCK();
257 st = SSS_aes_operation(&ctx, pInput, inputLen, NULL, pKey, AES_128_KEY_BITS, pOutput, cipherNdecipher,
258 kAlgorithm_SSS_AES_ECB);
259 SECLIB_MUTEX_UNLOCK();
260
261 return st;
262}
263
264/*! *********************************************************************************
265 * \brief This function performs AES-128 encryption on a single 16-byte block.
266 *
267 * \param[in] pInput Pointer to the location of the 16-byte plain text block.
268 *
269 * \param[in] pKey Pointer to the location of the 128-bit key.
270 *
271 * \param[out] pOutput Pointer to the location to store the 16-byte ciphered output.
272 *
273 * \pre All Input/Output pointers must refer to a memory address aligned to 4 bytes!
274 *
275 ********************************************************************************** */
276secResultType_t SecLib_AES_128_Encrypt(const uint8_t *pInput, const uint8_t *pKey, uint8_t *pOutput)
277{
278 secResultType_t result;
279 int st = 0;
280 do
281 {
282 /* Validate input parameters */
283 if ((NULL == pInput) || (NULL == pKey) || (NULL == pOutput))
284 {
285 result = gSecBadArgument_c;
286 break;
287 }
288
289 st = SecLib_AES_128_cipher(pInput, AES_BLOCK_SIZE, pKey, pOutput, true);
290 if (st != kStatus_Success)
291 {
292 result = gSecError_c;
293 break;
294 }
295 result = gSecSuccess_c;
296 } while (false);
297
298 return result;
299}
300
301/*! *********************************************************************************
302 * \brief This function performs AES-128 decryption on a singlr 16-byte block.
303 *
304 * \param[in] pInput Pointer to the location of the 16-byte plain text block.
305 *
306 * \param[in] pKey Pointer to the location of the 128-bit key.
307 *
308 * \param[out] pOutput Pointer to the location to store the 16-byte ciphered output.
309 *
310 * \pre All Input/Output pointers must refer to a memory address aligned to 4 bytes!
311 *
312 ********************************************************************************** */
313secResultType_t SecLib_AES_128_Decrypt(const uint8_t *pInput, const uint8_t *pKey, uint8_t *pOutput)
314{
315 secResultType_t result;
316 int st = 0;
317 do
318 {
319 /* Validate input parameters */
320 if ((NULL == pInput) || (NULL == pKey) || (NULL == pOutput))
321 {
322 result = gSecBadArgument_c;
323 break;
324 }
325
326 st = SecLib_AES_128_cipher(pInput, AES_BLOCK_SIZE, pKey, pOutput, false);
327 if (st != kStatus_Success)
328 {
329 result = gSecError_c;
330 break;
331 }
332 result = gSecSuccess_c;
333 } while (false);
334
335 return result;
336}
337
338/*! *********************************************************************************
339 * \brief This function performs AES-128-ECB encryption on a message block.
340 *
341 * \param[in] pInput Pointer to the location of the input message.
342 *
343 * \param[in] inputLen Input message length in bytes - must be a multiple of AES_BLOCK_SIZE
344 *
345 * \param[in] pKey Pointer to the location of the 128-bit key.
346 *
347 * \param[out] pOutput Pointer to the location to store the encrypted output.
348 *
349 * \return : gSecSuccess_c if no error,
350 * gSecBadArgument_c in case of bad arguments,
351 * gSecError_c in case of internal error.
352 *
353 ********************************************************************************** */
354secResultType_t SecLib_AES_128_ECB_Encrypt(const uint8_t *pInput,
355 uint32_t inputLen,
356 const uint8_t *pKey,
357 uint8_t *pOutput)
358{
359 secResultType_t res;
360 do
361 {
362 status_t st;
363 /* Validate input parameters: check for NULL pointers, zero length, and proper block alignment */
364 if ((pInput == NULL) || (pKey == NULL) || (pOutput == NULL) || (inputLen == 0U) ||
365 ((inputLen % AES_BLOCK_SIZE) != 0U))
366 {
367 RAISE_ERROR(res, gSecBadArgument_c);
368 }
369 /* Perform AES-128 ECB encryption using the cipher function with encrypt flag set to true */
370 st = SecLib_AES_128_cipher(pInput, inputLen, pKey, pOutput, true);
371 if (st != kStatus_Success)
372 {
373 RAISE_ERROR(res, gSecError_c);
374 }
375 res = gSecSuccess_c;
376
377 } while (false);
378 return res;
379}
380
381/*! *********************************************************************************
382 * \brief This function performs AES-128-ECB decryption on a message block.
383 *
384 * \param[in] pInput Pointer to the location of the input message.
385 *
386 * \param[in] inputLen Input message length in bytes - must be a multiple of AES_BLOCK_SIZE
387 *
388 * \param[in] pKey Pointer to the location of the 128-bit key.
389 *
390 * \param[out] pOutput Pointer to the location to store the decrypted output.
391 *
392 * \return : gSecSuccess_c if no error,
393 * gSecBadArgument_c in case of bad arguments,
394 * gSecError_c in case of internal error.
395 *
396 ********************************************************************************** */
397secResultType_t SecLib_AES_128_ECB_Decrypt(const uint8_t *pInput,
398 uint32_t inputLen,
399 const uint8_t *pKey,
400 uint8_t *pOutput)
401{
402 secResultType_t res;
403 do
404 {
405 status_t st;
406 /* Validate input parameters: check for NULL pointers, zero length, and proper block alignment */
407 if ((pInput == NULL) || (pKey == NULL) || (pOutput == NULL) || (inputLen == 0U) ||
408 ((inputLen % AES_BLOCK_SIZE) != 0U))
409 {
410 RAISE_ERROR(res, gSecBadArgument_c);
411 }
412 /* Perform AES-128 ECB decryption using the cipher function with decrypt flag set to false */
413 st = SecLib_AES_128_cipher(pInput, inputLen, pKey, pOutput, false);
414 if (st != kStatus_Success)
415 {
416 RAISE_ERROR(res, gSecError_c);
417 }
418 res = gSecSuccess_c;
419
420 } while (false);
421 return res;
422}
423
424/*! *********************************************************************************
425 * \brief This function performs AES-128-CBC encryption on a message block.
426 *
427 *
428 * \param[in] pInput Pointer to the location of the input message.
429 *
430 * \param[in] inputLen Input message length in bytes - must be a multiple of AES_BLOCK_SIZE
431 *
432 * \param[in, out] pInitVector Pointer to the location of the 128-bit initialization vector.
433 * On exit the IV content is updated with ciphered output to be injected as next block IV.
434 * Because IV is modifiable, it cannot be RO (const).
435 *
436 * \param[in] pKey Pointer to the location of the 128-bit key.
437 *
438 * \param[out] pOutput Pointer to the location to store the ciphered output.
439 *
440 * \return : gSecSuccess_c if no error,
441 * gSecBadArgument_c in case of bad arguments,
442 * gSecError_c in case of internal error.
443 *
444 ********************************************************************************** */
445secResultType_t SecLib_AES_128_CBC_Encrypt(
446 const uint8_t *pInput, uint32_t inputLen, uint8_t *pInitVector, const uint8_t *pKey, uint8_t *pOutput)
447{
448 secResultType_t ret;
449
450 do
451 {
452 status_t st;
453 aes_context_t ctx;
454 if ((pInput == NULL) || (pInitVector == NULL) || (pKey == NULL) || (pOutput == NULL) ||
455 /* If the input length is not a non zero multiple of AES 128 block size, return */
456 (inputLen < AES_BLOCK_SIZE) || (AES_PARTIAL_BLOCK_BYTES(inputLen) != 0U))
457 {
458 ret = gSecBadArgument_c;
459 break;
460 }
461
462 SECLIB_MUTEX_LOCK();
463
464 st = SSS_aes_operation(&ctx, pInput, inputLen, pInitVector, pKey, AES_128_KEY_BITS, pOutput, true,
465 kAlgorithm_SSS_AES_CBC);
466 SECLIB_MUTEX_UNLOCK();
467
468 if (st != kStatus_Success)
469 {
470 ret = gSecError_c;
471 break;
472 }
473 /* Update IV with last ciphered block to be injected at next call */
474 /* Note that inputLen is greater than or equal to AES_BLOCK_SIZE, otherwise would have exited
475 with gSecBadArgument_c, so difference cannot be negative */
476 FLib_MemCpy(pInitVector, &pOutput[inputLen - AES_BLOCK_SIZE], AES_BLOCK_SIZE);
477
478 ret = gSecSuccess_c;
479 } while (false);
480
481 return ret;
482}
483
484/*! *********************************************************************************
485 * \brief This function performs AES-128-CBC decryption on a message block.
486 *
487 * \param[in] pInput Pointer to the location of the input ciphered message.
488 *
489 * \param[in] inputLen Input message length in bytes - must be a multiple of AES_BLOCK_SIZE.
490 *
491 * \param[in, out] pInitVector Pointer to the location of the 128-bit initialization vector.
492 * On exit the IV content is updated with ciphered output to be injected as next block IV.
493 * Because IV is modifiable, it cannot be RO (const).
494 *
495 * \param[in] pKey Pointer to the location of the 128-bit key.
496 *
497 * \param[out] pOutput Pointer to the location to store the plain text output.
498 *
499 * \return : gSecSuccess_c if no error,
500 * gSecBadArgument_c in case of bad arguments,
501 * gSecError_c in case of internal error.
502 *
503 ********************************************************************************** */
504secResultType_t SecLib_AES_128_CBC_Decrypt(
505 const uint8_t *pInput, uint32_t inputLen, uint8_t *pInitVector, const uint8_t *pKey, uint8_t *pOutput)
506{
507 secResultType_t ret;
508 do
509 {
510 status_t st;
511 aes_context_t ctx;
512 if ((pInput == NULL) || (pInitVector == NULL) || (pKey == NULL) || (pOutput == NULL) ||
513 /* If the input length is not a non zero multiple of AES 128 block size, return */
514 (inputLen < AES_BLOCK_SIZE) || (AES_PARTIAL_BLOCK_BYTES(inputLen) != 0U))
515 {
516 RAISE_ERROR(ret, gSecBadArgument_c);
517 }
518
519 SECLIB_MUTEX_LOCK();
520 st = SSS_aes_operation(&ctx, pInput, inputLen, pInitVector, pKey, AES_128_KEY_BITS, pOutput, false,
521 kAlgorithm_SSS_AES_CBC);
522 SECLIB_MUTEX_UNLOCK();
523
524 if (st != kStatus_Success)
525 {
526 RAISE_ERROR(ret, gSecError_c);
527 }
528 /* Update IV with last ciphered block to be injected at next call */
529 /* Note that inputLen is greater than or equal to AES_BLOCK_SIZE, otherwise would have exited
530 with gSecBadArgument_c, so difference cannot be negative */
531 FLib_MemCpy(pInitVector, &pInput[inputLen - AES_BLOCK_SIZE], AES_BLOCK_SIZE);
532
533 ret = gSecSuccess_c;
534
535 } while (false);
536 return ret;
537}
538
539/*! *********************************************************************************
540 * \brief This function performs AES-128-CBC encryption on a message block after
541 * padding until AES block completion.
542 *
543 * Padding scheme is ISO/IEC 7816-4: one 80h byte (1 bit), followed by as many 00h as
544 * required to fill a 128 bit block. Note that if the message length is a multiple of
545 * AES block size already, another block is appended to the original message.
546 *
547 * \param[in] pInput Pointer to the location of the input message.
548 *
549 * \param[in] inputLen Input message length in bytes - no specific constraint.
550 *
551 * IMPORTANT: User must make sure output buffer has at least inputLen + 16 bytes size.
552 * This constraint does not apply to input buffer (any longer).
553 *
554 * \param[in, out] pInitVector Pointer to the location of the 128-bit initialization vector.
555 * On exit the IV content is updated with ciphered output to be injected as next block IV.
556 * Because it is modifiable it cannot be RO (const).
557 *
558 * \param[in] pKey Pointer to the location of the 128-bit key.
559 *
560 * \param[out] pOutput Pointer to the location to store the ciphered output.
561 *
562 * \return size of output message after padding is appended.
563 *
564 ********************************************************************************** */
565uint32_t AES_128_CBC_Encrypt_And_Pad(
566 uint8_t *pInput, uint32_t inputLen, uint8_t *pInitVector, const uint8_t *pKey, uint8_t *pOutput)
567{
568 uint32_t roundedLen = 0u;
569
570 do
571 {
572 uint8_t last_blk_msg_sz;
573 uint8_t last_block[AES_BLOCK_SIZE]; /* Buffer used to generate last block containing padding */
574 /* compute new length */
575 roundedLen = AES_WHOLE_BLOCK_BYTES(inputLen);
576 last_blk_msg_sz = (uint8_t)(AES_PARTIAL_BLOCK_BYTES(inputLen));
577 /* Perform AES-CBC operation on whole AES blocks */
578 if (SecLib_AES_128_CBC_Encrypt(pInput, roundedLen, pInitVector, pKey, pOutput) != gSecSuccess_c)
579 {
580 roundedLen = 0u;
581 break;
582 }
583 pInput += roundedLen;
584 pOutput += roundedLen;
585 /* There may be a remainder modulus 16 : copy it to last_block on stack */
586 /* then add padding so as to fill the last_block array */
587 if (SecLib_Padding(pInput, last_block, last_blk_msg_sz) == 0u)
588 {
589 roundedLen = 0u;
590 break;
591 }
592 if (SecLib_AES_128_CBC_Encrypt(last_block, AES_BLOCK_SIZE, pInitVector, pKey, pOutput) != gSecSuccess_c)
593 {
594 roundedLen = 0u;
595 break;
596 }
597 roundedLen += AES_BLOCK_SIZE;
598 } while (false);
599
600 return roundedLen;
601}
602
603/*! *********************************************************************************
604 * \brief This function performs AES_128_CBC_Decrypt_And_Depad decryption on a message.
605 *
606 * \param[in] pInput Pointer to the location of the input ciphered message.
607 *
608 * \param[in] inputLen Input message length in bytes must be a multiple of AES block size
609 *
610 * \param[in] pInitVector Pointer to the location of the 128-bit initialization vector.
611 *
612 * \param[in] pKey Pointer to the location of the 128-bit key.
613 *
614 * \param[out] pOutput Pointer to the location to store the plain text output.
615 *
616 * \return size of output buffer (after depadding the 0x80 [0x00 .. ]. padding sequence)
617 *
618 ********************************************************************************** */
619uint32_t AES_128_CBC_Decrypt_And_Depad(
620 const uint8_t *pInput, uint32_t inputLen, uint8_t *pInitVector, const uint8_t *pKey, uint8_t *pOutput)
621{
622 uint32_t newLen = 0uL;
623
624 if (inputLen > 0u)
625 {
626 if (AES_128_CBC_Decrypt(pInput, inputLen, pInitVector, pKey, pOutput) == gSecSuccess_c)
627 {
628 uint8_t padding_len;
629 /* If we are here inputLen is a non 0 multiple of AES_BLOCK_SIZE, otherwise AES_128_CBC_Decrypt would have
630 returned an error.
631 Yet the test below is to prevent a false MISRA error detection.
632 */
633 if ((inputLen >= AES_BLOCK_SIZE) && (AES_PARTIAL_BLOCK_BYTES(inputLen) == 0u))
634 {
635 uint8_t *p_last_block = &pOutput[inputLen - AES_BLOCK_SIZE];
636 padding_len = SecLib_DePadding(p_last_block);
637 if ((padding_len > 0u) && (padding_len <= AES_BLOCK_SIZE))
638 {
639 /* Safe: inputLen is a multiple of AES_BLOCK_SIZE and >= AES_BLOCK_SIZE,
640 padding_len is in [1..AES_BLOCK_SIZE], so subtraction cannot underflow */
641 newLen = inputLen - (uint32_t)padding_len;
642 }
643 }
644 }
645 }
646 /* coverity [return_overflow:FALSE] see above */
647 return newLen;
648}
649
650/*! *********************************************************************************
651 * \brief This function performs AES-128-CTR encryption on a message block.
652 * This function only accepts input lengths which are multiple
653 * of 16 bytes (AES 128 block size).
654 *
655 * \param[in] pInput Pointer to the location of the input message.
656 *
657 * \param[in] inputLen Input message length in bytes.
658 *
659 * \param[in] pCounter Pointer to the location of the 128-bit counter.
660 *
661 * \param[in] pKey Pointer to the location of the 128-bit key.
662 *
663 * \param[out] pOutput Pointer to the location to store the ciphered output.
664 *
665 ********************************************************************************** */
666secResultType_t SecLib_AES_128_CTR(
667 const uint8_t *pInput, uint32_t inputLen, uint8_t *pCounter, const uint8_t *pKey, uint8_t *pOutput)
668{
669 secResultType_t ret;
670
671 do
672 {
673 int st;
674 aes_context_t ctx;
675
676 /* Validate input parameters */
677 if ((pInput == NULL) || (pOutput == NULL) || (pKey == NULL) || (pCounter == NULL) || (inputLen == 0UL))
678 {
679 RAISE_ERROR(ret, gSecBadArgument_c);
680 }
681
682 SECLIB_MUTEX_LOCK();
683
684 /* Perform AES-128-CTR encryption operation */
685 /* The length of the input does not need to be a multiple of AES 128 block size */
686 st = SSS_aes128_CTR_operation(&ctx, pInput, inputLen, pCounter, pKey, pOutput, true);
687 SECLIB_MUTEX_UNLOCK();
688
689 if (st != kStatus_Success)
690 {
691 RAISE_ERROR(ret, gSecError_c);
692 }
693
694 ret = gSecSuccess_c;
695
696 } while (false);
697 return ret;
698}
699
700/*! *********************************************************************************
701 * \brief This function calculates XOR of individual byte pairs in two uint8_t arrays.
702 * pDst[i] := pDst[i] ^ pSrc[i] for i=0 to n-1
703 *
704 * \param[in] pDst First byte array operand for XOR and destination byte array
705 *
706 * \param[in] pSrc Second byte array operand for XOR
707 *
708 * \param[in] n Length of the byte array which will be XORed
709 *
710 ********************************************************************************** */
711void SecLib_XorN(uint8_t *pDst, const uint8_t *pSrc, uint8_t n)
712{
713 while (n != 0U)
714 {
715 *pDst = *pDst ^ *pSrc;
716 pDst = pDst + 1;
717 pSrc = pSrc + 1;
718 n--;
719 }
720}
721
722/*! *********************************************************************************
723 * \brief This function performs AES-128-CMAC on a message block.
724 *
725 * \param[in] pInput Pointer to the location of the input message.
726 *
727 * \param[in] inputLen Length of the input message in bytes. The input data must be provided MSB first.
728 *
729 * \param[in] pKey Pointer to the location of the 128-bit key. The key must be provided MSB first.
730 *
731 * \param[out] pOutput Pointer to the location to store the 16-byte authentication code. The code will be generated MSB
732 *first.
733 *
734 * \remarks This is public open source code! Terms of use must be checked before use!
735 *
736 ********************************************************************************** */
737secResultType_t SecLib_AES_128_CMAC(const uint8_t *pInput,
738 const uint32_t inputLen,
739 const uint8_t *pKey,
740 uint8_t *pOutput)
741{
742 secResultType_t ret;
743 do
744 {
745 status_t st;
746 cmac_aes_context_t cmac_ctx;
747 if ((pInput == NULL) || (pKey == NULL) || (pOutput == NULL))
748 {
749 RAISE_ERROR(ret, gSecBadArgument_c);
750 }
751
752 /* Perform AES-128-CMAC operation with mutex protection */
753 SECLIB_MUTEX_LOCK();
754 st = SSS_aes_cmac(&cmac_ctx, pKey, AES_128_KEY_BITS, pInput, inputLen, pOutput);
755 SECLIB_MUTEX_UNLOCK();
756
757 if (st != kStatus_Success)
758 {
759 RAISE_ERROR(ret, gSecError_c);
760 }
761
762 /* Operation completed successfully */
763 ret = gSecSuccess_c;
764 } while (false);
765 return ret;
766}
767
768#if defined(ELE_FEATURE_MAC_MULTIPART) && (ELE_FEATURE_MAC_MULTIPART != 0)
769static secResultType_t SecLib_ProcessCmacBlock(cmac_aes_context_t *cmac_ctx,
770 const uint8_t **ppInput,
771 uint32_t *inputLen,
772 uint8_t *reversedBlock)
773{
774 secResultType_t ret;
775 uint32_t currentCmacInputBlkLen = 0;
776
777 /* Determine the size of the current block to process */
778 if (*inputLen < AES_128_BLOCK_SIZE)
779 {
780 currentCmacInputBlkLen = *inputLen;
781 }
782 else
783 {
784 currentCmacInputBlkLen = AES_128_BLOCK_SIZE;
785 }
786
787 *ppInput -= currentCmacInputBlkLen;
788 *inputLen -= currentCmacInputBlkLen;
789
790 /* Copy the input block to the reversed CMAC input buffer */
791 FLib_MemCpyReverseOrder(reversedBlock, *ppInput, currentCmacInputBlkLen);
792
793 /* Update CMAC with the reversed block (protected by mutex) */
794 SECLIB_MUTEX_LOCK();
795 status_t st = SSS_aes_cmac_update(cmac_ctx, (const unsigned char *)reversedBlock, currentCmacInputBlkLen);
796 SECLIB_MUTEX_UNLOCK();
797
798 if (st != kStatus_Success)
799 {
800 ret = gSecError_c;
801 }
802 else
803 {
804 ret = gSecSuccess_c;
805 }
806
807 return ret;
808}
809
810/*! *********************************************************************************
811 * \brief Performs AES-128-CMAC on a message block with LSB-first input using multipart operations.
812 *
813 * \param[in] pInput Pointer to the input data buffer (LSB-first format)
814 * \param[in] inputLen Length of the input data in bytes
815 * \param[in] pKey Pointer to the AES-128 key (16 bytes)
816 * \param[out] pOutput Pointer to the output buffer for the CMAC result
817 * \param[in] reversedBlock Pointer to a temporary buffer for block reversal operations
818 *
819 * \return secResultType_t gSecSuccess_c if successful, gSecError_c otherwise
820 *
821 ********************************************************************************** */
822static secResultType_t SecLib_AES_128_CMAC_LsbFirstInput_Multipart(
823 const uint8_t *pInput, uint32_t inputLen, const uint8_t *pKey, uint8_t *pOutput, uint8_t *reversedBlock)
824{
825 secResultType_t ret;
826 status_t st;
827 cmac_aes_context_t cmac_ctx = {0};
828
829 do
830 {
831 /* Initialize context */
832 st = SSS_aes_cmac_starts(&cmac_ctx, pKey, AES_128_KEY_BYTE_LEN);
833 if (st != kStatus_Success)
834 {
835 RAISE_ERROR(ret, gSecError_c);
836 }
837
838 /* Initialize CMAC multipart operation */
839 st = SSS_aes_cmac_init(&cmac_ctx);
840 if (st != kStatus_Success)
841 {
842 RAISE_ERROR(ret, gSecError_c);
843 }
844
845 /* Walk the input buffer from the end to the start and reverse the blocks */
846 pInput += inputLen;
847 while (inputLen != 0U)
848 {
849 ret = SecLib_ProcessCmacBlock(&cmac_ctx, &pInput, &inputLen, reversedBlock);
850 if (ret != gSecSuccess_c)
851 {
852 break;
853 }
854 }
855
856 /* finish cmac */
857 SECLIB_MUTEX_LOCK();
858 st = SSS_aes_cmac_finish(&cmac_ctx, pOutput);
859 SECLIB_MUTEX_UNLOCK();
860 if (st != kStatus_Success)
861 {
862 RAISE_ERROR(ret, gSecError_c);
863 }
864 ret = gSecSuccess_c;
865 /* free context */
866 SSS_aes_cmac_free(&cmac_ctx);
867 } while (false);
868
869 return ret;
870}
871
872#else /* ELE_FEATURE_MAC_MULTIPART */
873
874/*! *********************************************************************************
875 * \brief Computes the AES-128-CMAC of a given input with LSB-first block order (single part)
876 *
877 * \param[in] pInput Pointer to the input buffer
878 * \param[in] inputLen Length of the input buffer in bytes
879 * \param[in] pKey Pointer to the 128-bit AES key
880 * \param[out] pOutput Pointer to the output buffer (16 bytes)
881 * \param[in] reversedBlock Pointer to a temporary buffer for block reversal (16 bytes)
882 *
883 * \return secResultType_t Result of the operation (gSecSuccess_c on success)
884 *
885 ********************************************************************************** */
886static secResultType_t SecLib_AES_128_CMAC_LsbFirstInput_SinglePart(
887 const uint8_t *pInput, uint32_t inputLen, const uint8_t *pKey, uint8_t *pOutput, uint8_t *reversedBlock)
888{
889 secResultType_t ret;
890 uint8_t *reversedMsg = NULL;
891 uint8_t *p;
892 uint32_t cnt;
893
894 do
895 {
896 /* Workaround to compensate for issue with CMAC partial update not working */
897 /* Requires the allocation of a buffer the size of the input : normally called with 32 byte input */
898 if (inputLen <= AES_128_BLOCK_SIZE)
899 {
900 reversedMsg = reversedBlock;
901 }
902 else
903 {
904 /* Round allocated size to the upper multiple of AES_128_BLOCK_SIZE */
905 reversedMsg = (uint8_t *)MEM_BufferAlloc(((inputLen + 15U) >> 4) << 4);
906 /* Some MEM_BufferAlloc implementations return a NULL pointer for a 0 length allocation */
907 if (reversedMsg == NULL)
908 {
909 RAISE_ERROR(ret, gSecAllocError_c);
910 }
911 }
912
913 p = reversedMsg;
914 cnt = inputLen;
915 pInput += cnt;
916 do
917 {
918 uint32_t currentCmacInputBlkLen = 0UL;
919 if (cnt < AES_128_BLOCK_SIZE)
920 {
921 /* If this is the first and single block it is legal for it to have an input length of 0
922 * in which case nothing will be copied in the reversed CMAC input buffer. */
923 currentCmacInputBlkLen = cnt;
924 }
925 else
926 {
927 currentCmacInputBlkLen = AES_128_BLOCK_SIZE;
928 }
929 pInput -= currentCmacInputBlkLen;
930 /* Coverity [overflow_const:FALSE] : it is safe, currentCmacInputBlkLen is always <= cnt */
931 cnt -= currentCmacInputBlkLen;
932 /* Copy the input block to the reversed CMAC input buffer */
933 FLib_MemCpyReverseOrder(p, pInput, currentCmacInputBlkLen);
934
935 p += currentCmacInputBlkLen;
936 } while (cnt != 0U);
937
938 ret = SecLib_AES_128_CMAC(reversedMsg, inputLen, pKey, pOutput);
939 /* CALL THIS AT THE END whther error was detected of not */
940 if (inputLen > AES_128_BLOCK_SIZE)
941 {
942 /* reversedMsg was allocated */
943 (void)MEM_BufferFree(reversedMsg);
944 }
945 } while (false);
946
947 return ret;
948}
949#endif /* ELE_FEATURE_MAC_MULTIPART */
950
951/*! *********************************************************************************
952 * \brief This function performs AES-128-CMAC on a message block accepting input data
953 * which is in LSB first format and computing the authentication code
954 * starting from the end of the data.
955 *
956 * \param[in] pInput Pointer to the location of the input message.
957 *
958 * \param[in] inputLen Length of the input message in bytes.
959 * The input data must be provided LSB first.
960 *
961 * \param[in] pKey Pointer to the location of the 128-bit key.
962 * The key must be provided MSB first.
963 *
964 * \param[out] pOutput Pointer to the location to store the 16-byte authentication code.
965 * The code will be generated MSB first.
966 *
967 ********************************************************************************** */
968secResultType_t SecLib_AES_128_CMAC_LsbFirstInput(const uint8_t *pInput,
969 uint32_t inputLen,
970 const uint8_t *pKey,
971 uint8_t *pOutput)
972{
973 secResultType_t ret;
974 do
975 {
976 uint8_t reversedBlock[AES_128_BLOCK_SIZE] = {0};
977
978 if ((pInput == NULL) || (pKey == NULL) || (pOutput == NULL))
979 {
980 RAISE_ERROR(ret, gSecBadArgument_c);
981 }
982
983#if defined(ELE_FEATURE_MAC_MULTIPART) && (ELE_FEATURE_MAC_MULTIPART != 0)
984 ret = SecLib_AES_128_CMAC_LsbFirstInput_Multipart(pInput, inputLen, pKey, pOutput, reversedBlock);
985#else /* ELE_FEATURE_MAC_MULTIPART */
986 ret = SecLib_AES_128_CMAC_LsbFirstInput_SinglePart(pInput, inputLen, pKey, pOutput, reversedBlock);
987#endif /* ELE_FEATURE_MAC_MULTIPART */
988 } while (false);
989
990 return ret;
991}
992
993/*! *********************************************************************************
994 * \brief This function performs AES 128 CMAC Pseudo-Random Function (AES-CMAC-PRF-128),
995 * according to rfc4615, on a message block.
996 * \details The AES-CMAC-PRF-128 algorithm behaves similar to teh AES CMAC 128 algorithm
997 * but removes 128 bit key size restriction.
998 * \param[in] pInput Pointer to the location of the input message.
999 * \param[in] inputLen Length of the input message in bytes.
1000 * \param[in] pVarKey Pointer to the location of the variable length key.
1001 * \param[in] varKeyLen Length of the input key in bytes
1002 * \param[out] pOutput Pointer to the location to store the 16-byte pseudo random variable.
1003 *
1004 ********************************************************************************** */
1005secResultType_t SecLib_AES_CMAC_PRF_128(
1006 const uint8_t *pInput, uint32_t inputLen, const uint8_t *pVarKey, uint32_t varKeyLen, uint8_t *pOutput)
1007{
1008 secResultType_t ret;
1009
1010 do
1011 {
1012 int st;
1013 cmac_aes_context_t cmac_ctx;
1014
1015 /* Validate input parameters - ensure no NULL pointers are passed */
1016 if ((pInput == NULL) || (pVarKey == NULL) || (pOutput == NULL))
1017 {
1018 RAISE_ERROR(ret, gSecBadArgument_c);
1019 }
1020 if (varKeyLen == 0u)
1021 {
1022 /* NIST SP 800‑38B and RFC 4493 allow empty message input.
1023 * RFC 4615 could mathematically accepts variable-length to be 0, nonetheless it is strongly discouraged
1024 * and ought to be rejected because of the lack of entropy. Using it could let the PRF be predictable
1025 * */
1026 RAISE_ERROR(ret, gSecBadArgument_c);
1027 }
1028
1029 SECLIB_MUTEX_LOCK();
1030
1031 /* Perform AES-CMAC-PRF-128 operation using the SSS library */
1032 st = SSS_aes_cmac_prf_128(&cmac_ctx, pVarKey, varKeyLen, pInput, inputLen, pOutput);
1033
1034 /* Release mutex lock after operation completes */
1035 SECLIB_MUTEX_UNLOCK();
1036
1037 if (st != kStatus_Success)
1038 {
1039 RAISE_ERROR(ret, gSecError_c);
1040 }
1041
1042 /* Operation completed successfully */
1043 ret = gSecSuccess_c;
1044 } while (false);
1045 return ret;
1046}
1047
1048/*! *********************************************************************************
1049 * \brief This function performs AES-128-CCM on a message block.
1050 *
1051 * \param[in] pInput Pointer to the location of the input message (plaintext or ciphertext).
1052 * \param[in] inputLen Length of the input plaintext in bytes when encrypting.
1053 * Length of the input ciphertext without the MAC length when decrypting.
1054 * \param[in] pAuthData Pointer to the additional authentication data.
1055 * \param[in] authDataLen Length of additional authentication data.
1056 * \param[in] pNonce Pointer to the Nonce.
1057 * \param[in] nonceSize The size of the nonce (7-13).
1058 * \param[in] pKey Pointer to the location of the 128-bit key.
1059 * \param[out] pOutput Pointer to the location to store the plaintext data when decrypting.
1060 * Pointer to the location to store the ciphertext data when encrypting.
1061 * \param[out] pCbcMac Pointer to the location to store the Message Authentication Code (MAC) when encrypting.
1062 * Pointer to the location where the received MAC can be found when decrypting.
1063 * \param[out] macSize The size of the MAC.
1064 * \param[out] flags Select encrypt/decrypt operations (gSecLib_CCM_Encrypt_c, gSecLib_CCM_Decrypt_c)
1065 *
1066 * \return 0 if encryption/decryption was successful; otherwise, error code for failed encryption/decryption
1067 *
1068 * \remarks At decryption, MIC fail is also signaled by returning a non-zero value.
1069 *
1070 ********************************************************************************** */
1071secResultType_t SecLib_AES_128_CCM(const uint8_t *pInput,
1072 uint16_t inputLen,
1073 const uint8_t *pAuthData,
1074 uint16_t authDataLen,
1075 const uint8_t *pNonce,
1076 uint8_t nonceSize,
1077 const uint8_t *pKey,
1078 uint8_t *pOutput,
1079 uint8_t *pCbcMac,
1080 uint8_t macSize,
1081 uint32_t flags)
1082{
1083 secResultType_t ret = gSecError_c;
1084 sss_ccm_context_t ccm_ctx;
1085
1086 /* Initialize CCM context to zero */
1087 FLib_MemSet(&ccm_ctx, 0, sizeof(sss_ccm_context_t));
1088
1089 do
1090 {
1091 int32_t status;
1092
1093 /* Validate input parameters - all pointers must be non-NULL */
1094 if ((pInput == NULL) || (pAuthData == NULL) || (pNonce == NULL) || (pOutput == NULL) || (pKey == NULL) ||
1095 (pCbcMac == NULL))
1096 {
1097 RAISE_ERROR(ret, gSecBadArgument_c);
1098 }
1099
1100 /* Set the 128-bit AES key in the CCM context */
1101 status = SSS_ccm_setkey(&ccm_ctx, pKey, 128);
1102 if (status != kStatus_Success)
1103 {
1104 break;
1105 }
1106
1107 SECLIB_MUTEX_LOCK();
1108
1109 /* Perform decryption or encryption based on flags */
1110 if ((flags & gSecLib_CCM_Decrypt_c) != 0U)
1111 {
1112 /* Decrypt and authenticate the input data */
1113 status = SSS_ccm_auth_decrypt(&ccm_ctx, inputLen, pNonce, nonceSize, pAuthData, authDataLen, pInput,
1114 pOutput, pCbcMac, macSize);
1115 }
1116 else
1117 {
1118 /* Encrypt the input data and generate authentication tag */
1119 status = SSS_ccm_encrypt_and_tag(&ccm_ctx, inputLen, pNonce, nonceSize, pAuthData, authDataLen, pInput,
1120 pOutput, pCbcMac, macSize);
1121 }
1122
1123 SECLIB_MUTEX_UNLOCK();
1124
1125 /* Free CCM context resources */
1126 SSS_ccm_free(&ccm_ctx);
1127 if (status != kStatus_Success)
1128 {
1129 break;
1130 }
1131
1132 /* Operation completed successfully */
1133 ret = gSecSuccess_c;
1134 } while (false);
1135 return ret;
1136}
1137
1138/*! *********************************************************************************
1139 * \brief This function allocates a memory buffer for a SHA256 context structure
1140 *
1141 * \return Address of the SHA256 context buffer
1142 * Deallocate using SHA256_FreeCtx()
1143 *
1144 ********************************************************************************** */
1145void *SecLib_SHA256_AllocCtx(void)
1146{
1147 void *p_ctx = MEM_BufferAlloc(sizeof(sss_sha256_context_t));
1148
1149 return p_ctx;
1150}
1151
1152/*! *********************************************************************************
1153 * \brief This function deallocates the memory buffer for the SHA256 context structure
1154 *
1155 * \param [in] pContext Address of the SHA256 context buffer
1156 *
1157 ********************************************************************************** */
1158void SecLib_SHA256_FreeCtx(void *pContext)
1159{
1160 (void)MEM_BufferFree(pContext);
1161}
1162/*! *********************************************************************************
1163 * \brief This function clones SHA256 context.
1164 * Make sure the size of the allocated destination context buffer is appropriate.
1165 *
1166 * \param [in] pDestCtx Address of the destination SHA256 context
1167 * \param [in] pSourceCtx Address of the source SHA256 context
1168 *
1169 ********************************************************************************** */
1170void SecLib_SHA256_CloneCtx(void *pDestCtx, void *pSourceCtx)
1171{
1172 SSS_sha256_clone(pDestCtx, pSourceCtx);
1173}
1174
1175/*! *********************************************************************************
1176 * \brief This function initializes the SHA256 context data
1177 *
1178 * \param [in] pContext Pointer to the SHA256 context data
1179 * Allocated using SHA256_AllocCtx()
1180 *
1181 ********************************************************************************** */
1182secResultType_t SecLib_SHA256_Init(void *pContext)
1183{
1184 secResultType_t st;
1185 if (pContext != NULL)
1186 {
1187 status_t result;
1188 sss_sha256_context_t *pSha256Ctx = (sss_sha256_context_t *)pContext;
1189
1190 SECLIB_MUTEX_LOCK();
1191
1192 SSS_sha256_init(pSha256Ctx);
1193
1194 /* Start the SHA256 operation */
1195 result = SSS_sha256_starts_ret(pSha256Ctx, false);
1196 st = (result != kStatus_Success) ? gSecError_c : gSecSuccess_c;
1197
1198 SECLIB_MUTEX_UNLOCK();
1199 }
1200 else
1201 {
1202 /* Invalid context pointer provided */
1203 st = gSecBadArgument_c;
1204 }
1205 return st;
1206}
1207
1208/*! *********************************************************************************
1209 * \brief This function performs SHA256 on multiple bytes and updates the context data
1210 *
1211 * \param [in] pContext Pointer to the SHA256 context data
1212 * Allocated using SHA256_AllocCtx()
1213 * \param [in] pData Pointer to the input data
1214 * \param [in] numBytes Number of bytes to hash
1215 *
1216 ********************************************************************************** */
1217secResultType_t SecLib_SHA256_HashUpdate(void *pContext, const uint8_t *pData, uint32_t numBytes)
1218{
1219 secResultType_t st;
1220
1221 do
1222 {
1223 status_t result;
1224 sss_sha256_context_t *pSha256Ctx = (sss_sha256_context_t *)pContext;
1225 if (pContext == NULL)
1226 {
1227 st = gSecBadArgument_c;
1228 break;
1229 }
1230
1231 SECLIB_MUTEX_LOCK();
1232
1233 /* Update the SHA256 hash with the provided data */
1234 result = SSS_sha256_update_ret(pSha256Ctx, pData, numBytes);
1235 if (result != kStatus_Success)
1236 {
1237 st = gSecError_c;
1238 SECLIB_MUTEX_UNLOCK();
1239 break;
1240 }
1241
1242 /* Operation completed successfully */
1243 st = gSecSuccess_c;
1244 SECLIB_MUTEX_UNLOCK();
1245
1246 } while (false);
1247 return st;
1248}
1249
1250/*! *********************************************************************************
1251 * \brief This function performs SHA256 on the last bytes of data and updates the context data.
1252 * The final hash value is stored at the provided output location.
1253 *
1254 * \param [in] pContext Pointer to the SHA256 context data
1255 * Allocated using SHA256_AllocCtx()
1256 * \param [in,out] pOutput Pointer to the output location
1257 *
1258 ********************************************************************************** */
1259secResultType_t SecLib_SHA256_HashFinish(void *pContext, uint8_t *pOutput)
1260{
1261 secResultType_t st;
1262
1263 do
1264 {
1265 status_t result;
1266 sss_sha256_context_t *pSha256Ctx = (sss_sha256_context_t *)pContext;
1267 if (pContext == NULL)
1268 {
1269 st = gSecBadArgument_c;
1270 break;
1271 }
1272
1273 SECLIB_MUTEX_LOCK();
1274
1275 /* Finalize the SHA256 hash and store result in output buffer */
1276 result = SSS_sha256_finish_ret(pSha256Ctx, pOutput);
1277 if (result != kStatus_Success)
1278 {
1279 st = gSecError_c;
1280 }
1281 else
1282 {
1283 st = gSecSuccess_c;
1284 }
1285 SECLIB_MUTEX_UNLOCK();
1286
1287 /* Free the SHA256 context */
1288 SSS_sha256_free(pSha256Ctx);
1289
1290 } while (false);
1291
1292 return st;
1293}
1294
1295/*! *********************************************************************************
1296 * \brief This function performs all SHA256 steps on multiple bytes: initialize,
1297 * update, finish, and update context data.
1298 * The final hash value is stored at the provided output location.
1299 *
1300 * \param [in] pData Pointer to the input data
1301 * \param [in] numBytes Number of bytes to hash
1302 * \param [in,out] pOutput Pointer to the output location
1303 *
1304 ********************************************************************************** */
1305secResultType_t SecLib_SHA256_Hash(const uint8_t *pData, uint32_t numBytes, uint8_t *pOutput)
1306{
1307 secResultType_t st;
1308 status_t result;
1309 do
1310 {
1311 /* Validate input parameters */
1312 if ((pData == NULL) || (pOutput == NULL))
1313 {
1314 RAISE_ERROR(st, gSecBadArgument_c);
1315 }
1316 SECLIB_MUTEX_LOCK();
1317
1318 /* Perform the complete SHA256 hash operation in one call */
1319 result = SSS_sha256_ret(pData, numBytes, pOutput, false);
1320 st = (result != kStatus_Success) ? gSecError_c : gSecSuccess_c;
1321
1322 SECLIB_MUTEX_UNLOCK();
1323 } while (false);
1324 return st;
1325}
1326
1327/* HMAC_SHA256 is used by the Gen FSK AKE controller */
1328
1329/*! *********************************************************************************
1330 * \brief This function allocates a memory buffer for a HMAC SHA256 context structure
1331 *
1332 * \return Address of the HMAC SHA256 context buffer
1333 * Deallocate using HMAC_SHA256_FreeCtx()
1334 *
1335 ********************************************************************************** */
1336void *SecLib_HMAC_SHA256_AllocCtx(void)
1337{
1338 void *mdhmac_sha256Ctx = MEM_BufferAlloc(sizeof(sss_hmac_sha256_context_t));
1339
1340 return mdhmac_sha256Ctx;
1341}
1342
1343/*! *********************************************************************************
1344 * \brief This function deallocates the memory buffer for the HMAC SHA256 context structure
1345 *
1346 * \param [in] pContext Address of the HMAC SHA256 context buffer
1347 *
1348 ********************************************************************************** */
1349void SecLib_HMAC_SHA256_FreeCtx(void *pContext)
1350{
1351 FLib_MemSet(pContext, 0, sizeof(sss_hmac_sha256_context_t));
1352 (void)MEM_BufferFree(pContext);
1353}
1354
1355/*! *********************************************************************************
1356 * \brief This function performs the initialization of the HMAC SHA256 context data
1357 *
1358 * \param [in] pContext Pointer to the HMAC SHA256 context data
1359 * Allocated using HMAC_SHA256_AllocCtx()
1360 * \param [in] pKey Pointer to the HMAC key
1361 * \param [in] keyLen Length of the HMAC key in bytes
1362 *
1363 ********************************************************************************** */
1364secResultType_t SecLib_HMAC_SHA256_Init(void *pContext, const uint8_t *pKey, uint32_t keyLen)
1365{
1366 secResultType_t st = gSecError_c;
1367 do
1368 {
1369 /* Validate input parameters */
1370 if ((pContext == NULL) || (pKey == NULL))
1371 {
1372 RAISE_ERROR(st, gSecBadArgument_c);
1373 }
1374
1375 SECLIB_MUTEX_LOCK();
1376
1377 /* Initialize HMAC SHA256 context with the provided key */
1378 if (SSS_md_hmac_sha256_starts((sss_hmac_sha256_context_t *)pContext, pKey, keyLen) == kStatus_Success)
1379 {
1380 st = gSecSuccess_c;
1381 }
1382
1383 SECLIB_MUTEX_UNLOCK();
1384 } while (false);
1385 return st;
1386}
1387
1388/*! *********************************************************************************
1389 * \brief This function performs HMAC update with the input data.
1390 *
1391 * \param [in] pContext Pointer to the HMAC SHA256 context data
1392 * Allocated using HMAC_SHA256_AllocCtx()
1393 * \param [in] pData Pointer to the input data
1394 * \param [in] numBytes Number of bytes to hash
1395 *
1396 ********************************************************************************** */
1397secResultType_t SecLib_HMAC_SHA256_Update(void *pContext, const uint8_t *pData, uint32_t numBytes)
1398{
1399 secResultType_t st = gSecError_c;
1400
1401 do
1402 {
1403 /* Validate input parameters */
1404 if ((pContext == NULL) || (pData == NULL))
1405 {
1406 RAISE_ERROR(st, gSecBadArgument_c);
1407 }
1408
1409 SECLIB_MUTEX_LOCK();
1410
1411 /* Update HMAC SHA256 context with the provided data */
1412 if (SSS_md_hmac_sha256_update((sss_hmac_sha256_context_t *)pContext, pData, numBytes) == kStatus_Success)
1413 {
1414 st = gSecSuccess_c;
1415 }
1416
1417 SECLIB_MUTEX_UNLOCK();
1418 } while (false);
1419 return st;
1420}
1421
1422/*! *********************************************************************************
1423 * \brief This function finalizes the HMAC SHA256 computation and clears the context data.
1424 * The final hash value is stored at the provided output location.
1425 *
1426 * \param [in] pContext Pointer to the HMAC SHA256 context data
1427 * Allocated using HMAC_SHA256_AllocCtx()
1428 * \param [in,out] pOutput Pointer to the output location
1429 *
1430 ********************************************************************************** */
1431secResultType_t SecLib_HMAC_SHA256_Finish(void *pContext, uint8_t *pOutput)
1432{
1433 secResultType_t st = gSecError_c;
1434 do
1435 {
1436 /* Validate input parameters */
1437 if ((pContext == NULL) || (pOutput == NULL))
1438 {
1439 RAISE_ERROR(st, gSecBadArgument_c);
1440 }
1441
1442 SECLIB_MUTEX_LOCK();
1443
1444 /* Finalize HMAC SHA256 computation and store result in output buffer */
1445 if (SSS_md_hmac_sha256_finish((sss_hmac_sha256_context_t *)pContext, pOutput) == kStatus_Success)
1446 {
1447 st = gSecSuccess_c;
1448 }
1449 SECLIB_MUTEX_UNLOCK();
1450 } while (false);
1451
1452 return st;
1453}
1454
1455/*! *********************************************************************************
1456 * \brief This function performs all HMAC SHA256 steps on multiple bytes: initialize,
1457 * update, finish, and update context data.
1458 * The final HMAC value is stored at the provided output location.
1459 *
1460 * \param [in] pKey Pointer to the HMAC key
1461 * \param [in] keyLen Length of the HMAC key in bytes
1462 * \param [in] pData Pointer to the input data
1463 * \param [in] numBytes Number of bytes to perform HMAC on
1464 * \param [in,out] pOutput Pointer to the output location
1465 *
1466 ********************************************************************************** */
1467secResultType_t SecLib_HMAC_SHA256(
1468 const uint8_t *pKey, uint32_t keyLen, const uint8_t *pData, uint32_t numBytes, uint8_t *pOutput)
1469{
1470 secResultType_t st = gSecError_c;
1471
1472 do
1473 {
1474 /* Validate input parameters */
1475 if ((pKey == NULL) || (pData == NULL) || (pOutput == NULL))
1476 {
1477 RAISE_ERROR(st, gSecBadArgument_c);
1478 }
1479
1480 SECLIB_MUTEX_LOCK();
1481 sss_hmac_sha256_context_t hmac_ctx;
1482 /* Perform complete HMAC SHA256 operation in one call */
1483 if (SSS_md_hmac_sha256(&hmac_ctx, pKey, keyLen, pData, numBytes, pOutput) == kStatus_Success)
1484 {
1485 st = gSecSuccess_c;
1486 }
1487 SECLIB_MUTEX_UNLOCK();
1488 } while (false);
1489
1490 return st;
1491}
1492
1493/************************************************************************************
1494 * \brief Generates a new ECDH P256 Private/Public key pair
1495 *
1496 * \return gSecSuccess_c or error
1497 *
1498 ************************************************************************************/
1499secResultType_t ECDH_P256_GenerateKeys(ecdhPublicKey_t *pOutPublicKey, ecdhPrivateKey_t *pOutPrivateKey)
1500{
1501 secResultType_t ret = gSecSuccess_c;
1502#if !(defined(gSecLibUseBleDebugKeys_d) && (gSecLibUseBleDebugKeys_d > 0))
1503 uint8_t *wrk_buf = NULL;
1504
1505 SECLIB_MUTEX_LOCK();
1506 do
1507 {
1508 size_t wrk_buf_sz;
1509 if ((pOutPublicKey == NULL) || (pOutPrivateKey == NULL))
1510 {
1511 RAISE_ERROR(ret, gSecBadArgument_c);
1512 }
1513 if (pECPKeyPair != NULL)
1514 {
1515 /* Once the key oject gets destroyed context is not ready anymore */
1516 IsSecLibEcdhContextInit = false;
1517 /* need to release previous allocated key */
1518 (void)SSS_KEY_OBJ_FREE(&pECPKeyPair->OwnKey);
1519 FLib_MemSet(pECPKeyPair, 0, sizeof(sss_ecp256_context_t));
1520 pECPKeyPair = NULL;
1521 }
1522
1523 wrk_buf_sz = sizeof(ecdhPublicKey_t); /* 2 * ECP256_COORDINATE_LEN */
1524 wrk_buf = MEM_BufferAlloc(wrk_buf_sz);
1525 if (wrk_buf == NULL)
1526 {
1527 RAISE_ERROR(ret, gSecAllocError_c);
1528 }
1529 g_ECP_KeyPair.keyId = KEY_ID_BLE0;
1530
1531 if (sss_ecdh_make_public_ecp256_key(&g_ECP_KeyPair, wrk_buf, wrk_buf_sz) != kStatus_Success)
1532 {
1533 RAISE_ERROR(ret, gSecError_c);
1534 }
1535 pECPKeyPair = &g_ECP_KeyPair;
1536
1537 if (sss_sscp_key_store_export_key(&g_keyStore, &pECPKeyPair->OwnKey, ecdhKeyPairBlob, &ecdhKeyPairBlobSize,
1538 kSSS_blobType_ELKE_blob) != kStatus_SSS_Success)
1539 {
1540 RAISE_ERROR(ret, gSecError_c);
1541 }
1542
1543 IsSecLibEcdhContextInit = true;
1544
1545 /* pubKey returned by SSS in Big-Endian format: return it as Low Endian */
1546 ECP256_PointCopy_and_change_endianness(pOutPublicKey->raw, &wrk_buf[0]);
1547 /* From S200 A1 on, the private key is not passed in plain text so the pOutPrivateKey remains uninitialized */
1548 FLib_MemCpy(pOutPrivateKey->raw_8bit, &pECPKeyPair->PrivateKey, sizeof(ecdhPrivateKey_t));
1549
1550 } while (false);
1551 SECLIB_MUTEX_UNLOCK();
1552 (void)MEM_BufferFree(wrk_buf);
1553#else /* gSecLibUseBleDebugKeys_d */
1554 SECLIB_MUTEX_LOCK();
1555 do
1556 {
1557 if (pECPKeyPair != NULL)
1558 {
1559 break;
1560 }
1561
1562 g_ECP_KeyPair.keyId = KEY_ID_BLE0;
1563 pECPKeyPair = &g_ECP_KeyPair;
1564
1565 if ((CRYPTO_InitHardware()) != kStatus_Success)
1566 {
1567 break;
1568 }
1569
1570 if (sss_sscp_key_object_init(&pECPKeyPair->OwnKey, &g_keyStore) != kStatus_SSS_Success)
1571 {
1572 break;
1573 }
1574
1575 if (sss_sscp_key_object_allocate_handle(&pECPKeyPair->OwnKey, KEY_ID_BLE0, kSSS_KeyPart_Pair,
1576 kSSS_CipherType_EC_NIST_P, 96u,
1577 mSecLibKeyPropCryptoAlgoAll_c) != kStatus_SSS_Success)
1578 {
1579 break;
1580 }
1581
1582 if (sss_sscp_key_store_set_key(&g_keyStore, &pECPKeyPair->OwnKey, (const uint8_t *)&mBleDebugKeyPair, 96u, 256u,
1583 kSSS_KeyPart_Pair) != kStatus_SSS_Success)
1584 {
1585 break;
1586 }
1587
1588 if (sss_sscp_key_store_export_key(&g_keyStore, &pECPKeyPair->OwnKey, ecdhKeyPairBlob, &ecdhKeyPairBlobSize,
1589 kSSS_blobType_ELKE_blob) != kStatus_SSS_Success)
1590 {
1591 RAISE_ERROR(ret, gSecError_c);
1592 }
1593
1594 IsSecLibEcdhContextInit = true;
1595 } while (false);
1596 SECLIB_MUTEX_UNLOCK();
1597
1598 /* The NCCL output is BE and BLE expected LE */
1599 ECP256_PointCopy_and_change_endianness((uint8_t *)pOutPublicKey, (const uint8_t *)&mBleDebugKeyPair.public_key);
1600 ECP256_coordinate_copy_and_change_endianness((uint8_t *)pOutPrivateKey,
1601 (const uint8_t *)&mBleDebugKeyPair.private_key);
1602 (void)g_ECP_KeyPair;
1603#endif /* gSecLibUseBleDebugKeys_d */
1604
1605 return ret;
1606}
1607
1608/************************************************************************************
1609 * \brief Generates a public key from a scalar given as input
1610 *
1611 * This function performs the multiplication of the scalar by the EC P 256 G point.
1612 * The resulting point is the public key corresponding to the private key constituted by the scalar.
1613 * This calculation is also involved in the compute L stage in the SPAKE2+ where the W1 argument
1614 * plays the role of the private key argument after modular reduction.
1615 * S200 does not support scalar multiplication in hardware so this function uses software implementation.
1616 *
1617 * \return gSecEcp256Success_c or error
1618 *
1619 ************************************************************************************/
1620secEcp256Status_t ECP256_GeneratePublicKey(uint8_t *pOutPublicKey,
1621 const uint8_t *pInPrivateKey,
1622 void *pMultiplicationBuffer)
1623{
1624 secEcp256Status_t ret = gSecEcp256BadParameters_c;
1625 if ((pOutPublicKey != NULL) && (pInPrivateKey != NULL))
1626 {
1627#if !(defined gSecLibUseDspExtension_d && (gSecLibUseDspExtension_d != 0))
1628 if (pMultiplicationBuffer != NULL)
1629 {
1630 big_int256_t privKey;
1631 ecp256Point_t out;
1632 FLib_MemCpyReverseOrder((uint8_t *)&privKey, pInPrivateKey, sizeof(big_int256_t));
1633 ret = ECP256_GeneratePublicKeySeg(&out.raw[0], (uint8_t *)&privKey, pMultiplicationBuffer);
1634 ECP256_PointCopy_and_change_endianness((uint8_t *)pOutPublicKey, &out.raw[0]);
1635 }
1636#else
1637 NOT_USED(pMultiplicationBuffer);
1638 ret = ECP256_GeneratePublicKeyUltraFast(pOutPublicKey, pInPrivateKey);
1639#endif
1640 }
1641 return ret;
1642}
1643
1644/************************************************************************************
1645 * \brief Checks whether a public key is valid (point is on the curve).
1646 *
1647 * \return TRUE if valid, FALSE if not
1648 *
1649 ************************************************************************************/
1650bool_t ECP256_IsKeyValid(const ecp256Point_t *pKey)
1651{
1652 bool_t ret = false;
1653
1654 if (ECP256_LePointValid(pKey))
1655 {
1656 ret = true;
1657 }
1658
1659 return ret;
1660}
1661
1662/************************************************************************************
1663 * \brief Generates a new ECDH P256 Private/Public key pair
1664 *
1665 * \return gSecSuccess_c or error
1666 *
1667 ************************************************************************************/
1668secResultType_t ECDH_P256_GenerateKeysSeg(computeDhKeyParam_t *pDhKeyData)
1669{
1670 secResultType_t res = gSecBadArgument_c;
1671 if (pDhKeyData != NULL)
1672 {
1673 res = ECDH_P256_GenerateKeys(&pDhKeyData->outPoint, &pDhKeyData->privateKey);
1674 }
1675 return res;
1676}
1677
1678/************************************************************************************
1679 * \brief Computes the Diffie-Hellman Key for an ECDH P256 key pair.
1680 *
1681 * \return gSecSuccess_c or error
1682 *
1683 ************************************************************************************/
1684secResultType_t ECDH_P256_ComputeDhKey(const ecdhPrivateKey_t *pInPrivateKey,
1685 const ecdhPublicKey_t *pInPeerPublicKey,
1686 ecdhDhKey_t *pOutDhKey,
1687 const bool_t keepBlobDhKey)
1688
1689{
1690 secResultType_t ret = gSecSuccess_c;
1691 uint8_t *wrk_buf = NULL;
1692 SECLIB_MUTEX_LOCK();
1693 sss_ecdh_context_t ecdh_ctx = {0};
1694
1695 ecdh_ctx.keepSharedSecret = keepBlobDhKey;
1696 do
1697 {
1698 ecdhPoint_t EcdhPubKey = {0U};
1699 size_t wrk_buf_sz;
1700
1701 if ((pInPrivateKey == NULL) || (pInPeerPublicKey == NULL) || (pOutDhKey == NULL))
1702 {
1703 ret = gSecBadArgument_c;
1704 break;
1705 }
1706 if (pECPKeyPair == NULL)
1707 {
1708 ret = gSecError_c;
1709 break;
1710 }
1711 if (!ECP256_LePointValid(pInPeerPublicKey))
1712 {
1713 ret = gSecInvalidPublicKey_c;
1714 break;
1715 }
1716
1717 if (IsSecLibEcdhContextInit == false)
1718 {
1719 if ((sss_ecdh_init_key(pECPKeyPair)) != kStatus_Success)
1720 {
1721 break;
1722 }
1723
1724 if (kStatus_SSS_Success != sss_sscp_key_store_import_key(&g_keyStore, &pECPKeyPair->OwnKey, ecdhKeyPairBlob,
1725 ecdhKeyPairBlobSize, 3U * ECP256_COORDINATE_BITLEN,
1726 kSSS_blobType_ELKE_blob))
1727 {
1728 break;
1729 }
1730 IsSecLibEcdhContextInit = true;
1731 }
1732 wrk_buf_sz = 3u * ECP256_COORDINATE_LEN;
1733 wrk_buf = MEM_BufferAlloc(wrk_buf_sz);
1734 if (wrk_buf == NULL)
1735 {
1736 RAISE_ERROR(ret, gSecAllocError_c);
1737 }
1738 ecdh_ctx.ecdh_key_pair = pECPKeyPair;
1739
1740 uint8_t *pubkey = &EcdhPubKey.raw[0];
1741 ECP256_PointCopy_and_change_endianness(pubkey, (const uint8_t *)&pInPeerPublicKey->raw[0]);
1742
1743 FLib_MemCpy(&ecdh_ctx.Qp, &EcdhPubKey, sizeof(ecdhPoint_t));
1744
1745 if (sss_ecdh_calc_secret(&ecdh_ctx, wrk_buf, wrk_buf_sz) != kStatus_Success)
1746 {
1747 RAISE_ERROR(ret, gSecError_c);
1748 }
1749 ECP256_PointCopy_and_change_endianness(pOutDhKey->raw, wrk_buf);
1750
1751 (void)MEM_BufferFree(wrk_buf);
1752 } while (false);
1753
1754 SECLIB_MUTEX_UNLOCK();
1755
1756 if (ret == gSecSuccess_c)
1757 {
1758 /* Keep DHKey object for later use */
1759 if (ecdh_ctx.keepSharedSecret == true)
1760 {
1761 /* We store the sss_sscp_object_t structure as the DH Key :
1762 * this is assuming the structure is not larger than the DHKey (32 bytes) */
1763 FLib_MemCpy(pOutDhKey->raw, (void *)&ecdh_ctx.sharedSecret, sizeof(sss_sscp_object_t));
1764 }
1765 }
1766 return ret;
1767}
1768
1769/************************************************************************************
1770 * \brief Computes the Diffie-Hellman Key for an ECDH P256 key pair.
1771 *
1772 * \return gSecSuccess_c or error
1773 *
1774 ************************************************************************************/
1775secResultType_t ECDH_P256_ComputeDhKeySeg(computeDhKeyParam_t *pDhKeyData)
1776{
1777 secResultType_t res = gSecBadArgument_c;
1778 if (pDhKeyData != NULL)
1779 {
1780 res = ECDH_P256_ComputeDhKey(&pDhKeyData->privateKey, &pDhKeyData->peerPublicKey, &pDhKeyData->outPoint,
1781 pDhKeyData->keepInternalBlob);
1782 }
1783 return res;
1784}
1785
1786/************************************************************************************
1787 * \brief Free any data allocated in the input structure.
1788 *
1789 * \param[in] pDhKeyData Pointer to the structure holding information about the
1790 * multiplication
1791 *
1792 * \return gSecSuccess_c or error
1793 *
1794 ************************************************************************************/
1795void ECDH_P256_FreeDhKeyDataSecure(computeDhKeyParam_t *pDhKeyData)
1796{
1797 /* turn into void* first to avoid MISRA 11.3 */
1798 void *pKeyData = &pDhKeyData->outPoint;
1799 (void)sss_sscp_key_object_free((sss_sscp_object_t *)pKeyData, kSSS_keyObjFree_KeysStoreDefragment);
1800}
1801
1802/************************************************************************************
1803 * \brief Function used to create the mac key and LTK using Bluetooth F5 algorithm.
1804 * Higher security version all keys remain on security bus.
1805 *
1806 * \param [out] pMacKey 128 bit MacKey output location (pointer)
1807 * \param [out] pLtk 128 bit LTK output location (pointer)
1808 * \param [in] pW 256 bit W (pointer) (DHKey) in the non secure version, but a pointer to
1809 * sss_sscp_object describing the DH Key in the secure version (28 bytes)
1810 * \param [in] pN1 128 bit N1 (pointer) (Na)
1811 * \param [in] pN2 128 bit N2 (pointer) (Nb)
1812 * \param [in] a1at 8 bit A1 address type, 0 = Public, 1 = Random
1813 * \param [in] pA1 48 bit A1 (pointer) (A)
1814 * \param [in] a2at 8 bit A2 address type, 0 = Public, 1 = Random
1815 * \param [in] pA2 48 bit A2 (pointer) (B)
1816 *
1817 * \retval gSecSuccess_c operation succeeded
1818 * \retval gSecError_c operation failed
1819 *
1820 ************************************************************************************/
1821secResultType_t SecLib_GenerateBluetoothF5KeysSecure(uint8_t *pMacKey,
1822 uint8_t *pLtk,
1823 const uint8_t *pW,
1824 const uint8_t *pN1,
1825 const uint8_t *pN2,
1826 const uint8_t a1at,
1827 const uint8_t *pA1,
1828 const uint8_t a2at,
1829 const uint8_t *pA2)
1830{
1831 secResultType_t result = gSecError_c;
1832 const uint8_t f5KeyId[4] = {0x62, 0x74, 0x6c, 0x65}; /*!< Big Endian, "btle" */
1833 uint8_t f5CmacBuffer[1 + 4 + 16 + 16 + 7 + 7 +
1834 2]; /* Counter[1] || keyId[4] || N1[16] || N2[16] || A1[7] || A2[7] || Length[2] = 53 */
1835
1836 uint8_t f5CmacBuffer_Counter1[1 + 4 + 16 + 16 + 7 + 7 + 2]; /* Counter[1] || keyId[4] || N1[16] || N2[16] ||
1837 A1[7] || A2[7] || Length[2] = 53 */
1838
1839 /*! Check for NULL output pointers and return with proper status if this is the case. */
1840 do
1841 {
1842 if ((NULL == pMacKey) || (NULL == pLtk) || (NULL == pW) || (NULL == pN1) || (NULL == pN2) || (NULL == pA1) ||
1843 (NULL == pA2))
1844 {
1845#if defined(gSmDebugEnabled_d) && (gSmDebugEnabled_d == 1U)
1846 SmDebug_Log(gSmDebugFileSmCrypto_c, __LINE__, smDebugLogTypeError_c, 0);
1847#endif /* gSmDebugEnabled_d */
1848 RAISE_ERROR(result, gSecBadArgument_c);
1849 }
1850 /*! Build the most significant part of the f5 input data to compute the MacKey */
1851 f5CmacBuffer[0] = 0; /* Counter = 0 */
1852 FLib_MemCpy(&f5CmacBuffer[1], (const uint8_t *)f5KeyId, 4);
1853 FLib_MemCpyReverseOrder(&f5CmacBuffer[5], (const uint8_t *)pN1, 16);
1854 FLib_MemCpyReverseOrder(&f5CmacBuffer[21], (const uint8_t *)pN2, 16);
1855 f5CmacBuffer[37] = 0x01U & a1at;
1856 FLib_MemCpyReverseOrder(&f5CmacBuffer[38], (const uint8_t *)pA1, 6);
1857 f5CmacBuffer[44] = 0x01U & a2at;
1858 FLib_MemCpyReverseOrder(&f5CmacBuffer[45], (const uint8_t *)pA2, 6);
1859 f5CmacBuffer[51] = 0x01; /* Length msB big endian = 0x01, Length = 256 */
1860 f5CmacBuffer[52] = 0x00; /* Length lsB big endian = 0x00, Length = 256 */
1861
1862 /*! Build the least significant part of the f5 input data to compute the LTK.
1863 * It is identical to the most significant part with the exception of the counter. */
1864 FLib_MemCpy(f5CmacBuffer_Counter1, f5CmacBuffer, 53u);
1865 f5CmacBuffer_Counter1[0] = 1; /* Counter = 1 */
1866 /* pW here is actually an sss_sscp_object */
1867 if (kStatus_SSS_Success !=
1868 ELKE_BLE_SM_F5_DeriveKeysSecure(pW, f5CmacBuffer, f5CmacBuffer_Counter1, pMacKey, pLtk))
1869 {
1870 RAISE_ERROR(result, gSecError_c);
1871 }
1872 result = gSecSuccess_c;
1873 } while (false);
1874
1875 return result;
1876}
1877
1878static void SecLib_BuildF5CmacBuffer(uint8_t *pBuffer,
1879 uint8_t counter,
1880 const uint8_t *pN1,
1881 const uint8_t *pN2,
1882 const uint8_t a1at,
1883 const uint8_t *pA1,
1884 const uint8_t a2at,
1885 const uint8_t *pA2)
1886{
1887 const uint8_t f5KeyId[4] = {0x62, 0x74, 0x6c, 0x65}; /*!< Big Endian, "btle" */
1888
1889 pBuffer[0] = counter;
1890 FLib_MemCpy(&pBuffer[1], (const uint8_t *)f5KeyId, 4u);
1891 FLib_MemCpyReverseOrder(&pBuffer[5], (const uint8_t *)pN1, 16u);
1892 FLib_MemCpyReverseOrder(&pBuffer[21], (const uint8_t *)pN2, 16u);
1893 pBuffer[37] = 0x01U & a1at;
1894 FLib_MemCpyReverseOrder(&pBuffer[38], (const uint8_t *)pA1, 6u);
1895 pBuffer[44] = 0x01U & a2at;
1896 FLib_MemCpyReverseOrder(&pBuffer[45], (const uint8_t *)pA2, 6u);
1897 pBuffer[51] = 0x01; /* Length msB big endian = 0x01, Length = 256 */
1898 pBuffer[52] = 0x00; /* Length lsB big endian = 0x00, Length = 256 */
1899}
1900
1901/************************************************************************************
1902 * \brief Function used to create the mac key and LTK using Bluetooth F5 algorithm.
1903 * Less secure version not using secure bus.
1904 *
1905 * \param [out] pMacKey 128 bit MacKey output location (pointer)
1906 * \param [out] pLtk 128 bit LTK output location (pointer)
1907 * \param [in] pW 256 bit W (pointer) (DHKey)
1908 * \param [in] pN1 128 bit N1 (pointer) (Na)
1909 * \param [in] pN2 128 bit N2 (pointer) (Nb)
1910 * \param [in] a1at 8 bit A1 address type, 0 = Public, 1 = Random
1911 * \param [in] pA1 48 bit A1 (pointer) (A)
1912 * \param [in] a2at 8 bit A2 address type, 0 = Public, 1 = Random
1913 * \param [in] pA2 48 bit A2 (pointer) (B)
1914 *
1915 * \retval gSecSuccess_c operation succeeded
1916 * \retval gSecError_c operation failed
1917 *
1918 ************************************************************************************/
1919secResultType_t SecLib_GenerateBluetoothF5Keys(uint8_t *pMacKey,
1920 uint8_t *pLtk,
1921 const uint8_t *pW,
1922 const uint8_t *pN1,
1923 const uint8_t *pN2,
1924 const uint8_t a1at,
1925 const uint8_t *pA1,
1926 const uint8_t a2at,
1927 const uint8_t *pA2)
1928{
1929 secResultType_t result = gSecError_c;
1930 uint8_t f5CmacBuffer[1 + 4 + 16 + 16 + 7 + 7 + 2];
1931 /* Counter[1] || keyId[4] || N1[16] || N2[16] || A1[7] || A2[7] || Length[2] = 53 */
1932
1933 uint8_t f5T[16] = {0};
1934 const uint8_t f5Salt[16] = {0x6C, 0x88, 0x83, 0x91, 0xAA, 0xF5, 0xA5, 0x38,
1935 0x60, 0x37, 0x0B, 0xDB, 0x5A, 0x60, 0x83, 0xBE}; /*!< Big endian */
1936
1937 do
1938 {
1939 uint8_t tempOut[16] = {0u};
1940
1941 /*! Check for NULL output pointers and return with proper status if this is the case. */
1942 if ((NULL == pMacKey) || (NULL == pLtk) || (NULL == pW) || (NULL == pN1) || (NULL == pN2) || (NULL == pA1) ||
1943 (NULL == pA2))
1944 {
1945#if defined(gSmDebugEnabled_d) && (gSmDebugEnabled_d == 1U)
1946 SmDebug_Log(gSmDebugFileSmCrypto_c, __LINE__, smDebugLogTypeError_c, 0);
1947#endif /* gSmDebugEnabled_d */
1948 RAISE_ERROR(result, gSecBadArgument_c);
1949 }
1950
1951 /*! Compute the f5 function key T using the predefined salt as key for AES-128-CMAC */
1952 result = SecLib_AES_128_CMAC_LsbFirstInput((const uint8_t *)pW, 32, (const uint8_t *)f5Salt, f5T);
1953 if (result != gSecSuccess_c)
1954 {
1955 break;
1956 }
1957
1958 /*! Build the most significant part of the f5 input data to compute the MacKey */
1959 SecLib_BuildF5CmacBuffer(f5CmacBuffer, 0, pN1, pN2, a1at, pA1, a2at, pA2);
1960
1961 /*! Compute the MacKey into the temporary buffer. */
1962 result = SecLib_AES_128_CMAC(f5CmacBuffer, sizeof(f5CmacBuffer), f5T, tempOut);
1963 if (result != gSecSuccess_c)
1964 {
1965 break;
1966 }
1967
1968 /*! Copy the MacKey to the output location
1969 * in reverse order. The CMAC result is generated MSB first. */
1970 FLib_MemCpyReverseOrder(pMacKey, (const uint8_t *)tempOut, 16u);
1971
1972 /*! Build the least significant part of the f5 input data to compute the MacKey.
1973 * It is identical to the most significant part with the exception of the counter. */
1974 f5CmacBuffer[0] = 1u; /* Counter = 1 */
1975
1976 /*! Compute the LTK into the temporary buffer. */
1977 result = SecLib_AES_128_CMAC(f5CmacBuffer, sizeof(f5CmacBuffer), f5T, tempOut);
1978 if (result != gSecSuccess_c)
1979 {
1980 break;
1981 }
1982 /*! Copy the LTK to the output location
1983 * in reverse order. The CMAC result is generated MSB first. */
1984 FLib_MemCpyReverseOrder(pLtk, (const uint8_t *)tempOut, 16u);
1985
1986 result = gSecSuccess_c;
1987
1988 } while (false);
1989
1990 return result;
1991}
1992
1993/************************************************************************************
1994 * \brief Function used to derive the Bluetooth SKD used in LL encryption.
1995 * Only to be called for applications activating encrypted key blobs.
1996 *
1997 * \param [in] pInSKD pointer to the received SKD (16-byte array)
1998 * \param [in] pLtkBlob pointer to the blob (40-byte array)
1999 * \param [in] bOpenKey if TRUE sends derived key to NBU
2000 * \param [out] pOutSKD pointer to the resulted SKD (16-byte array)
2001 *
2002 * \retval gSecSuccess_c operation succeeded
2003 * \retval gSecError_c operation failed
2004 ************************************************************************************/
2005secResultType_t SecLib_DeriveBluetoothSKDSecure(const uint8_t *pInSKD,
2006 const uint8_t *pLtkBlob,
2007 bool_t bOpenKey,
2008 uint8_t *pOutSKD)
2009{
2010 secResultType_t result = gSecError_c;
2011 size_t eskByteLen = 16U;
2012 size_t keyBitLen = 128U;
2013 sss_sscp_object_t keyObjLTK;
2014 sss_sscp_object_t keyObjSK;
2015 sss_sscp_derive_key_t ctxDeriveKey;
2016 uint8_t aInSKD[16];
2017 bool bLTKObjectInitialized = false;
2018 bool bSKObjectInitialized = false;
2019 bool bDeriveKeyContextInitialized = false;
2020
2021 SECLIB_MUTEX_LOCK();
2022
2023 FLib_MemCpyReverseOrder(aInSKD, pInSKD, 16);
2024 do
2025 {
2026 if ((pInSKD == NULL) || (pLtkBlob == NULL) || (pOutSKD == NULL))
2027 {
2028 result = gSecBadArgument_c;
2029 break;
2030 }
2031 if ((CRYPTO_InitHardware()) != kStatus_Success)
2032 {
2033 break;
2034 }
2035
2036 /* allocate LTK key object */
2037 if (sss_sscp_key_object_init(&keyObjLTK, &g_keyStore) != kStatus_SSS_Success)
2038 {
2039 break;
2040 }
2041 bLTKObjectInitialized = true;
2042
2043 if (sss_sscp_key_object_allocate_handle(
2044 &keyObjLTK, ELE_S200_KEY_STORE_USER_ID_GENERIC, kSSS_KeyPart_Default, kSSS_CipherType_SYMMETRIC, 16u,
2045 kSSS_KeyProp_NoPlainRead | kSSS_KeyProp_NoPlainWrite | kSSS_KeyProp_CryptoAlgo_KDF) !=
2046 kStatus_SSS_Success)
2047 {
2048 break;
2049 }
2050
2051 /* Allocate SK object */
2052 if (sss_sscp_key_object_init(&keyObjSK, &g_keyStore) != kStatus_SSS_Success)
2053 {
2054 break;
2055 }
2056 bSKObjectInitialized = true;
2057
2058 if (sss_sscp_key_object_allocate_handle(
2059 &keyObjSK, ELE_S200_KEY_STORE_USER_ID_GENERIC, kSSS_KeyPart_Default, kSSS_CipherType_SYMMETRIC, 16u,
2060 kSSS_KeyProp_NoPlainRead | kSSS_KeyProp_NoPlainWrite) != kStatus_SSS_Success)
2061 {
2062 break;
2063 }
2064
2065 /* import LTK blob into S200 */
2066 if (sss_sscp_key_store_import_key(&g_keyStore, &keyObjLTK, pLtkBlob, 40, keyBitLen, kSSS_blobType_ELKE_blob) !=
2067 kStatus_SSS_Success)
2068 {
2069 break;
2070 }
2071
2072 /* compute encrypted sessionKey from LTK */
2073 if (sss_sscp_derive_key_context_init(&ctxDeriveKey, &g_sssSession, &keyObjLTK, kAlgorithm_SSS_AES_ECB,
2074 kMode_SSS_SymmetricKDF) != kStatus_SSS_Success)
2075 {
2076 break;
2077 }
2078 bDeriveKeyContextInitialized = true;
2079
2080 if (sss_sscp_derive_key(&ctxDeriveKey, aInSKD, eskByteLen, &keyObjSK, 0U) != kStatus_SSS_Success)
2081 {
2082 break;
2083 }
2084
2085 if (bOpenKey == TRUE)
2086 {
2087 sss_status_t ret;
2088 /* Generate random NBU_DKEY_SK and send it to NBU */
2089 PLATFORM_RemoteActiveReq();
2090 ret = sss_sscp_key_store_open_internal_key(&g_keyStore, kSSS_internalKey_NBU_DKEY_SK);
2091 PLATFORM_RemoteActiveRel();
2092 if (kStatus_SSS_Success != ret)
2093 {
2094 break;
2095 }
2096 }
2097
2098 if (sss_sscp_key_store_export_key(&g_keyStore, &keyObjSK, pOutSKD, &eskByteLen, kSSS_blobType_NBU_ESK_blob) !=
2099 kStatus_SSS_Success)
2100 {
2101 break;
2102 }
2103
2104 result = gSecSuccess_c;
2105 } while (false);
2106
2107 /* de-allocate derive context and keys in S200 */
2108 if (bDeriveKeyContextInitialized == true)
2109 {
2110 (void)sss_sscp_derive_key_context_free(&ctxDeriveKey);
2111 }
2112 if (bLTKObjectInitialized == true)
2113 {
2114 (void)sss_sscp_key_object_free(&keyObjLTK, kSSS_keyObjFree_KeysStoreDefragment);
2115 }
2116 if (bSKObjectInitialized == true)
2117 {
2118 (void)sss_sscp_key_object_free(&keyObjSK, kSSS_keyObjFree_KeysStoreDefragment);
2119 }
2120
2121 SECLIB_MUTEX_UNLOCK();
2122 return result;
2123}
2124
2125/************************************************************************************
2126 * \brief Converts a plaintext symmetric key into a blob of blobType. Reverses key beforehand.
2127 *
2128 * \param[in] pKey Pointer to the key.
2129 *
2130 * \param[out] pBlob Pointer to the blob (shall be allocated, 40 or 16, depending on blobType)
2131 *
2132 * \param[in] blobType Blob type.
2133 * 1: kSSS_blobType_ELKE_blob ELKE die unique blob,
2134 * 2: kSSS_blobType_E2E_blob Edge 2 Edge blob
2135 * 3: kSSS_blobType_NBU_ESK_blob NBU ESK blob
2136 * 4: kSSS_blobType_NBU_EIRK_blob NBU EIRK blob
2137 *
2138 * Note that blob types above kSSS_blobType_NBU_EIRK_blob are unsupported.
2139 *
2140 * \return gSecSuccess_c or error
2141 *
2142 ************************************************************************************/
2143secResultType_t SecLib_ObfuscateKeySecure(const uint8_t *pKey, uint8_t *pBlob, const uint8_t blobType)
2144{
2145 secResultType_t result = gSecError_c;
2146 size_t blobByteLen;
2147 sss_sscp_object_t keyObj;
2148 bool_t keyInit = false;
2149 uint8_t tempKey[16];
2150
2151 FLib_MemCpyReverseOrder(tempKey, pKey, 16U);
2152
2153 SECLIB_MUTEX_LOCK();
2154 do
2155 {
2156 if ((pKey == NULL) || (pBlob == NULL) || (blobType < kSSS_blobType_ELKE_blob) ||
2157 (blobType > kSSS_blobType_NBU_EIRK_blob))
2158 {
2159 RAISE_ERROR(result, gSecBadArgument_c);
2160 }
2161
2162 blobByteLen = (blobType == kSSS_blobType_ELKE_blob) ? 40U : 16U;
2163
2164 if ((CRYPTO_InitHardware()) != kStatus_Success)
2165 {
2166 break;
2167 }
2168
2169 if (sss_sscp_key_object_init(&keyObj, &g_keyStore) != kStatus_SSS_Success)
2170 {
2171 break;
2172 }
2173 keyInit = true;
2174
2175 if (sss_sscp_key_object_allocate_handle(&keyObj, ELE_S200_KEY_STORE_USER_ID_GENERIC, kSSS_KeyPart_Default,
2176 kSSS_CipherType_NONE, 16u,
2177 mSecLibKeyPropCryptoAlgoAll_c) != kStatus_SSS_Success)
2178 {
2179 break;
2180 }
2181
2182 if (sss_sscp_key_store_set_key(&g_keyStore, &keyObj, (const uint8_t *)tempKey, 16u, 128u,
2183 kSSS_KeyPart_Default) != kStatus_SSS_Success)
2184 {
2185 break;
2186 }
2187
2188 if (sss_sscp_key_store_export_key(&g_keyStore, &keyObj, pBlob, &blobByteLen, blobType) != kStatus_SSS_Success)
2189 {
2190 break;
2191 }
2192
2193 result = gSecSuccess_c;
2194 } while (false);
2195
2196 if (keyInit == true)
2197 {
2198 (void)sss_sscp_key_object_free(&keyObj, kSSS_keyObjFree_KeysStoreDefragment);
2199 }
2200 SECLIB_MUTEX_UNLOCK();
2201 return result;
2202}
2203
2204/************************************************************************************
2205 * \brief Converts a blob of a symmetric key into the plaintext. Reverses key afterwards.
2206 *
2207 * \param[in] pBlob Pointer to the blob.
2208 *
2209 * \param[out] pKey Pointer to the key.
2210 *
2211 * \return gSecSuccess_c or error
2212 *
2213 ************************************************************************************/
2214secResultType_t SecLib_DeobfuscateKeySecure(const uint8_t *pBlob, uint8_t *pKey)
2215{
2216 secResultType_t result = gSecError_c;
2217 size_t keyBitLen = 128U, keyByteLen = 16U;
2218 sss_sscp_object_t keyObj;
2219 bool_t keyInit = false;
2220 uint8_t tempKey[16];
2221 SECLIB_MUTEX_LOCK();
2222 do
2223 {
2224 if ((pKey == NULL) || (pBlob == NULL))
2225 {
2226 RAISE_ERROR(result, gSecBadArgument_c);
2227 }
2228
2229 if ((CRYPTO_InitHardware()) != kStatus_Success)
2230 {
2231 break;
2232 }
2233
2234 if (sss_sscp_key_object_init(&keyObj, &g_keyStore) != kStatus_SSS_Success)
2235 {
2236 break;
2237 }
2238 keyInit = true;
2239
2240 if (sss_sscp_key_object_allocate_handle(&keyObj, ELE_S200_KEY_STORE_USER_ID_GENERIC, kSSS_KeyPart_Default,
2241 kSSS_CipherType_NONE, 16u,
2242 mSecLibKeyPropCryptoAlgoAll_c) != kStatus_SSS_Success)
2243 {
2244 break;
2245 }
2246
2247 if (sss_sscp_key_store_import_key(&g_keyStore, &keyObj, pBlob, 40U, 8U * 40U, kSSS_blobType_ELKE_blob) !=
2248 kStatus_SSS_Success)
2249 {
2250 break;
2251 }
2252
2253 if (sss_sscp_key_store_get_key(&g_keyStore, &keyObj, tempKey, &keyByteLen, &keyBitLen, kSSS_KeyPart_Default) !=
2254 kStatus_SSS_Success)
2255 {
2256 break;
2257 }
2258
2259 result = gSecSuccess_c;
2260 FLib_MemCpyReverseOrder(pKey, tempKey, 16U);
2261 } while (false);
2262
2263 if (keyInit == true)
2264 {
2265 (void)sss_sscp_key_object_free(&keyObj, kSSS_keyObjFree_KeysStoreDefragment);
2266 }
2267 SECLIB_MUTEX_UNLOCK();
2268 return result;
2269}
2270
2271/*! *********************************************************************************
2272 * \brief This function implements the SMP ah cryptographic toolbox function which
2273 calculates the hash part of a Resolvable Private Address.
2274 * The key is kept in plaintext.
2275 *
2276 * \param[out] pHash Pointer where the 24 bit hash of a Resolvable Private Address value
2277 * will be written.
2278 *
2279 * \param[in] pKey Pointer to the 128 bit key.
2280 *
2281 * \param[in] pR Pointer to the 24 bit random value (Prand) of a Resolvable private Address.
2282 * The most significant bits of this field must be 0b01 for Resolvable Private
2283 * Addresses.
2284 *
2285 * \retval gSecSuccess_c All operations were successful.
2286 * \retval gSecError_c The call failed.
2287 *
2288 ********************************************************************************** */
2289secResultType_t SecLib_VerifyBluetoothAh(uint8_t *pHash, const uint8_t *pKey, const uint8_t *pR)
2290{
2291 secResultType_t result = gSecError_c;
2292 uint8_t tempAddrPart[AES_BLOCK_SIZE] = {0u};
2293 uint8_t tempOutHash[AES_BLOCK_SIZE] = {0u};
2294 uint8_t tempKey[AES_128_KEY_BYTE_LEN];
2295 do
2296 {
2297 /*! Check for NULL output pointers and return with proper status if this is the case. */
2298 if ((NULL == pHash) || (NULL == pKey) || (NULL == pR))
2299 {
2300 RAISE_ERROR(result, gSecBadArgument_c);
2301 }
2302 /* Initialize the r' value in the temporary location. 3 bytes of random value.
2303 * Initialize it reversed for AES.
2304 */
2305 for (uint8_t i = 0; i < 3u; i++)
2306 {
2307 tempAddrPart[AES_BLOCK_SIZE - 1u - i] = pR[i];
2308 }
2309 /* Regular operation with plaintext key */
2310 /*! Reverse the Key and place it in a temporary location. */
2311 FLib_MemCpyReverseOrder(tempKey, (const uint8_t *)pKey, AES_128_KEY_BYTE_LEN);
2312
2313 /*! Compute the hash. */
2314 AES_128_Encrypt(tempAddrPart, tempKey, tempOutHash);
2315
2316 /*! Copy the relevant bytes to the output. */
2317 for (uint8_t i = 0; i < 3u; i++)
2318 {
2319 pHash[i] = tempOutHash[AES_BLOCK_SIZE - 1u - i];
2320 }
2321 result = gSecSuccess_c;
2322
2323 } while (false);
2324
2325 return result;
2326}
2327
2328/*! *********************************************************************************
2329 * \brief This function implements the SMP ah cryptographic toolbox function which calculates the
2330 * hash part of a Resolvable Private Address.
2331 * The key is kept in a secure blob. It is never exposed on non secure bus.
2332 *
2333 * \param[out] pHash Pointer where the 24 bit hash value will be written.
2334 * 24 bit hash field of a Resolvable Private Address (output)
2335 *
2336 * \param[in] pKey Pointer to the 128 bit key.
2337 *
2338 * \param[in] pR Pointer to the 24 bit random value (Prand). 24 bit random part of a Resolvable private Address.
2339 * The most significant bits of this field must be 0b01 for Resolvable Private Addresses.
2340 *
2341 * \retval gSecSuccess_c All operations were successful.
2342 * \retval gSecError_c The call failed.
2343 *
2344 ********************************************************************************** */
2345secResultType_t SecLib_VerifyBluetoothAhSecure(uint8_t *pHash, const uint8_t *pKey, const uint8_t *pR)
2346{
2347 secResultType_t result = gSecError_c;
2348
2349 sss_sscp_object_t keyObj;
2350 sss_sscp_symmetric_t context;
2351 bool_t keyInit = false;
2352 bool_t contextInit = false;
2353 uint8_t tempAddrPart[16] = {0};
2354 uint8_t tempFullHash[16] = {0};
2355 SECLIB_MUTEX_LOCK();
2356 do
2357 {
2358 /*! Check for NULL output pointers and return with proper status if this is the case. */
2359 if ((NULL == pHash) || (NULL == pR) || (NULL == pKey))
2360 {
2361 result = gSecBadArgument_c;
2362 break;
2363 }
2364 if ((CRYPTO_InitHardware()) != kStatus_Success)
2365 {
2366 break;
2367 }
2368
2369 if (sss_sscp_key_object_init(&keyObj, &g_keyStore) != kStatus_SSS_Success)
2370 {
2371 break;
2372 }
2373 keyInit = true;
2374
2375 if (sss_sscp_key_object_allocate_handle(&keyObj, 0, kSSS_KeyPart_Default, kSSS_CipherType_NONE, 16u,
2376 SSS_KEYPROP_OPERATION_AES) != kStatus_SSS_Success)
2377 {
2378 break;
2379 }
2380
2381 if (sss_sscp_key_store_import_key(&g_keyStore, &keyObj, pKey, 40U, 8U * 40U, kSSS_blobType_ELKE_blob) !=
2382 kStatus_SSS_Success)
2383 {
2384 break;
2385 }
2386
2387 if (sss_sscp_symmetric_context_init(&context, g_keyStore.session, &keyObj, kAlgorithm_SSS_AES_ECB,
2388 kMode_SSS_Encrypt) != kStatus_SSS_Success)
2389 {
2390 break;
2391 }
2392 contextInit = true;
2393
2394 /* Initialize the r' value in the temporary location. 3 bytes of random value.
2395 * Initialize it reversed for AES.
2396 */
2397 for (uint8_t i = 0u; i < 3u; i++)
2398 {
2399 tempAddrPart[AES_BLOCK_SIZE - 1u - i] = pR[i];
2400 }
2401
2402 if (sss_sscp_cipher_one_go(&context, NULL, 0, tempAddrPart, tempFullHash, 16U) != kStatus_SSS_Success)
2403 {
2404 break;
2405 }
2406
2407 /*! Copy the relevant bytes to the output. */
2408 for (uint8_t i = 0; i < 3u; i++)
2409 {
2410 pHash[i] = tempFullHash[AES_BLOCK_SIZE - 1u - i];
2411 }
2412
2413 result = gSecSuccess_c;
2414
2415 } while (false);
2416
2417 if (keyInit == true)
2418 {
2419 (void)sss_sscp_key_object_free(&keyObj, kSSS_keyObjFree_KeysStoreDefragment);
2420 }
2421 if (contextInit == true)
2422 {
2423 (void)sss_sscp_symmetric_context_free(&context);
2424 }
2425 SECLIB_MUTEX_UNLOCK();
2426 return result;
2427}
2428
2429/************************************************************************************
2430 * \brief Generates a symmetric key in ELKE blob or plain text form .
2431 *
2432 * \param[in] keySize the size of the generated key.
2433 *
2434 * \param[in] blobOutput true - blob, false - plain text output.
2435 *
2436 * \param[out] pOut the address of the buffer to store the key.
2437 * Storage for sss_sscp_object_t key reference
2438 *
2439 * \return gSecSuccess_c or error
2440 *
2441 ************************************************************************************/
2442secResultType_t SecLib_GenerateSymmetricKey(const uint32_t keySize, const bool_t blobOutput, void *pOut)
2443{
2444 secResultType_t result = gSecError_c;
2445 bool_t keyObjFree = false;
2446 sss_sscp_object_t keyObj;
2447 SECLIB_MUTEX_LOCK();
2448 do
2449 {
2450 if (NULL == pOut)
2451 {
2452 result = gSecBadArgument_c;
2453 break;
2454 }
2455 if ((CRYPTO_InitHardware()) != kStatus_Success)
2456 {
2457 break;
2458 }
2459
2460 if (kStatus_SSS_Success != sss_sscp_key_object_init(&keyObj, &g_keyStore))
2461 {
2462 break;
2463 }
2464 keyObjFree = true;
2465 if (kStatus_SSS_Success != sss_sscp_key_object_allocate_handle(&keyObj, ELE_S200_KEY_STORE_USER_ID_GENERIC,
2466 kSSS_KeyPart_Default, kSSS_CipherType_SYMMETRIC,
2467 keySize, mSecLibKeyPropCryptoAlgoAll_c))
2468 {
2469 break;
2470 }
2471 if (kStatus_SSS_Success != sss_sscp_key_store_generate_key(&g_keyStore, &keyObj, (size_t)(keySize << 3U), NULL))
2472 {
2473 break;
2474 }
2475 if (blobOutput == true)
2476 {
2477 size_t blobByteLen = gSecLibElkeBlobSize_c;
2478 if (kStatus_SSS_Success !=
2479 sss_sscp_key_store_export_key(&g_keyStore, &keyObj, pOut, &blobByteLen, kSSS_blobType_ELKE_blob))
2480 {
2481 break;
2482 }
2483 }
2484 else
2485 {
2486 size_t keyByteLen = (size_t)keySize;
2487 size_t keyBitLen = (size_t)(keySize << 3U);
2488 if (kStatus_SSS_Success !=
2489 sss_sscp_key_store_get_key(&g_keyStore, &keyObj, pOut, &keyByteLen, &keyBitLen, kSSS_KeyPart_Default))
2490 {
2491 break;
2492 }
2493 }
2494 result = gSecSuccess_c;
2495
2496 } while (false);
2497
2498 if (keyObjFree == true)
2499 {
2500 (void)sss_sscp_key_object_free(&keyObj, kSSS_keyObjFree_KeysStoreDefragment);
2501 }
2502 SECLIB_MUTEX_UNLOCK();
2503 return result;
2504}
2505
2506/************************************************************************************
2507 * \brief Generates an EIRK blob from an ELKE blob or plain text symmetric key.
2508 *
2509 * \param[in] pIRK pointer to the input IRK key.
2510 *
2511 * \param[in] blobInput true - pIRK points to an ELKE blob, false - pIRK points to a plain text key.
2512 *
2513 * \param[in] generateDKeyIRK true - DKeyIRK is slso generated and provided to NBU.
2514 *
2515 * \param[out] pOutEIRKblob the address of the buffer to store the EIRK blob.
2516 *
2517 * \return gSecSuccess_c or error
2518 *
2519 ************************************************************************************/
2520secResultType_t SecLib_GenerateBluetoothEIRKBlobSecure(const void *pIRK,
2521 const bool_t blobInput,
2522 const bool_t generateDKeyIRK,
2523 uint8_t *pOutEIRKblob)
2524{
2525 secResultType_t result = gSecError_c;
2526 bool_t keyObjFree = false;
2527 sss_sscp_object_t keyObj;
2528#ifdef REVERSE_EIRK
2529 uint8_t tempKey[16];
2530#endif
2531 SECLIB_MUTEX_LOCK();
2532 do
2533 {
2534 if ((NULL == pIRK) || (NULL == pOutEIRKblob))
2535 {
2536 result = gSecBadArgument_c;
2537 break;
2538 }
2539 if ((CRYPTO_InitHardware()) != kStatus_Success)
2540 {
2541 break;
2542 }
2543
2544 if (kStatus_SSS_Success != sss_sscp_key_object_init(&keyObj, &g_keyStore))
2545 {
2546 break;
2547 }
2548 keyObjFree = true;
2549 if (kStatus_SSS_Success != sss_sscp_key_object_allocate_handle(&keyObj, ELE_S200_KEY_STORE_USER_ID_GENERIC,
2550 kSSS_KeyPart_Default, kSSS_CipherType_SYMMETRIC,
2551 16U, mSecLibKeyPropCryptoAlgoAll_c))
2552 {
2553 break;
2554 }
2555 if (blobInput == true)
2556 {
2557 if (kStatus_SSS_Success != sss_sscp_key_store_import_key(&g_keyStore, &keyObj, pIRK, gSecLibElkeBlobSize_c,
2558 128U, kSSS_blobType_ELKE_blob))
2559 {
2560 break;
2561 }
2562 }
2563 else
2564 {
2565 if (kStatus_SSS_Success !=
2566 sss_sscp_key_store_set_key(&g_keyStore, &keyObj, pIRK, 16U, 128U, kSSS_KeyPart_Default))
2567 {
2568 break;
2569 }
2570 }
2571
2572 if (generateDKeyIRK == true)
2573 {
2574 sss_status_t ret;
2575 /* Generate random NBU_DKEY_IRK and send it to NBU */
2576 PLATFORM_RemoteActiveReq();
2577 ret = sss_sscp_key_store_open_internal_key(&g_keyStore, kSSS_internalKey_NBU_DKEY_IRK);
2578 PLATFORM_RemoteActiveRel();
2579 if (kStatus_SSS_Success != ret)
2580 {
2581 break;
2582 }
2583 }
2584
2585 size_t eirkBlobByteLen = gSecLibEirkBlobSize_c;
2586
2587#ifdef REVERSE_EIRK
2588 if (kStatus_SSS_Success !=
2589 sss_sscp_key_store_export_key(&g_keyStore, &keyObj, tempKey, &eirkBlobByteLen, kSSS_blobType_NBU_EIRK_blob))
2590#else
2591 if (kStatus_SSS_Success != sss_sscp_key_store_export_key(&g_keyStore, &keyObj, pOutEIRKblob, &eirkBlobByteLen,
2592 kSSS_blobType_NBU_EIRK_blob))
2593#endif
2594 {
2595 break;
2596 }
2597 result = gSecSuccess_c;
2598#ifdef REVERSE_EIRK
2599 FLib_MemCpyReverseOrder(pOutEIRKblob, tempKey, 16U);
2600#endif
2601 } while (false);
2602 if (keyObjFree == true)
2603 {
2604 (void)sss_sscp_key_object_free(&keyObj, kSSS_keyObjFree_KeysStoreDefragment);
2605 }
2606 SECLIB_MUTEX_UNLOCK();
2607 return result;
2608}
2609
2610/************************************************************************************
2611 * \brief Computes the Edgelock to Edgelock key for an ECDH P256 key pair.
2612 *
2613 * \param[in] pInPeerPublicKey pointer to the public key.
2614 * \param[out] pOutE2EKey pointer where the E2E key object is stored
2615 *
2616 * \return gSecSuccess_c or error
2617 *
2618 ************************************************************************************/
2619secResultType_t ECDH_P256_ComputeA2BKeySecure(const ecdhPublicKey_t *pInPeerPublicKey, ecdhDhKey_t *pOutE2EKey)
2620{
2621 secResultType_t ret = gSecError_c;
2622 uint8_t *wrk_buf = NULL;
2623 SECLIB_MUTEX_LOCK();
2624 sss_ecdh_context_t ecdh_ctx = {0};
2625 do
2626 {
2627 if ((NULL == pInPeerPublicKey) || (NULL == pOutE2EKey))
2628 {
2629 ret = gSecBadArgument_c;
2630 break;
2631 }
2632 if (pECPKeyPair == NULL)
2633 {
2634 ret = gSecError_c;
2635 break;
2636 }
2637
2638 size_t wrk_buf_sz = 3u * ECP256_COORDINATE_LEN;
2639 wrk_buf = MEM_BufferAlloc(wrk_buf_sz);
2640 if (wrk_buf == NULL)
2641 {
2642 RAISE_ERROR(ret, gSecAllocError_c);
2643 }
2644 ecdh_ctx.ecdh_key_pair = pECPKeyPair;
2645 ECP256_PointCopy_and_change_endianness((uint8_t *)&ecdh_ctx.Qp, (const uint8_t *)&pInPeerPublicKey->raw[0]);
2646 ecdh_ctx.keepSharedSecret = true;
2647
2648 if (sss_ecdh_calc_EL2EL_key(&ecdh_ctx, wrk_buf, wrk_buf_sz) != kStatus_Success)
2649 {
2650 RAISE_ERROR(ret, gSecError_c);
2651 }
2652 FLib_MemCpy(pOutE2EKey->raw, (void *)&ecdh_ctx.sharedSecret, sizeof(sss_sscp_object_t));
2653 (void)MEM_BufferFree(wrk_buf);
2654
2655 ret = gSecSuccess_c;
2656
2657 } while (false);
2658 SECLIB_MUTEX_UNLOCK();
2659 return ret;
2660}
2661
2662/************************************************************************************
2663 * \brief Free E2E key object
2664 *
2665 * \param[in] pE2EKeyData Pointer to the E2E key data to be freed.
2666 *
2667 * \return gSecSuccess_c or error
2668 *
2669 ************************************************************************************/
2670secResultType_t ECDH_P256_FreeE2EKeyDataSecure(ecdhDhKey_t *pE2EKeyData)
2671{
2672 secResultType_t result = gSecError_c;
2673 sscp_status_t status = kStatus_SSCP_Fail;
2674
2675 /* turn into void* first to avoid MISRA 11.3 */
2676 void *pKeyData = pE2EKeyData;
2677
2678 status = sss_sscp_key_object_free((sss_sscp_object_t *)pKeyData, kSSS_keyObjFree_KeysStoreDefragment);
2679
2680 if (kStatus_SSS_Success == status)
2681 {
2682 result = gSecSuccess_c;
2683 }
2684 return result;
2685}
2686
2687/************************************************************************************
2688 * \brief Generates an E2E blob from an ELKE blob or plain text symmetric key. This function needs to be preceded by
2689 *least one ECDH_P256_ComputeA2BKeySecure
2690 *
2691 * \param[in] pKey pointer to the input key.
2692 * \param[in] keyType input key type.
2693 * \param[out] pOutKey pointer to where the output E2E blob will be copied.
2694 *
2695 * \return gSecSuccess_c or error
2696 *
2697 ************************************************************************************/
2698secResultType_t SecLib_ExportA2BBlobSecure(const void *pKey, const secInputKeyType_t keyType, uint8_t *pOutKey)
2699{
2700 /* This function needs to be preceded by least one ECDH_P256_ComputeA2BKeySecure */
2701 secResultType_t result = gSecError_c;
2702 bool_t keyObjFree = false;
2703 sss_sscp_object_t keyObj;
2704
2705 SECLIB_MUTEX_LOCK();
2706 do
2707 {
2708 if ((NULL == pKey) || (NULL == pOutKey))
2709 {
2710 result = gSecBadArgument_c;
2711 break;
2712 }
2713 if ((CRYPTO_InitHardware()) != kStatus_Success)
2714 {
2715 break;
2716 }
2717
2718 if (kStatus_SSS_Success != sss_sscp_key_object_init(&keyObj, &g_keyStore))
2719 {
2720 break;
2721 }
2722 keyObjFree = true;
2723
2724 if (gSecPlainText_c == keyType)
2725 {
2726 uint8_t tempKey[16];
2727
2728 FLib_MemCpyReverseOrder(tempKey, pKey, 16U);
2729
2730 if (kStatus_SSS_Success != sss_sscp_key_object_allocate_handle(&keyObj, ELE_S200_KEY_STORE_USER_ID_GENERIC,
2731 kSSS_KeyPart_Default, kSSS_CipherType_NONE,
2732 16U, SSS_KEYPROP_OPERATION_AES))
2733 {
2734 break;
2735 }
2736
2737 if (kStatus_SSS_Success !=
2738 sss_sscp_key_store_set_key(&g_keyStore, &keyObj, tempKey, 16U, 128U, kSSS_KeyPart_Default))
2739 {
2740 break;
2741 }
2742 }
2743 else if (gSecElkeBlob_c == keyType)
2744 {
2745 if (kStatus_SSS_Success !=
2746 sss_sscp_key_object_allocate_handle(&keyObj, ELE_S200_KEY_STORE_USER_ID_GENERIC, kSSS_KeyPart_Default,
2747 kSSS_CipherType_SYMMETRIC, 16U, mSecLibKeyPropCryptoAlgoAll_c))
2748 {
2749 break;
2750 }
2751
2752 if (kStatus_SSS_Success != sss_sscp_key_store_import_key(&g_keyStore, &keyObj, pKey, gSecLibElkeBlobSize_c,
2753 128U, kSSS_blobType_ELKE_blob))
2754 {
2755 break;
2756 }
2757 }
2758 else if (gSecLtkElkeBlob_c == keyType)
2759 {
2760 if (kStatus_SSS_Success !=
2761 sss_sscp_key_object_allocate_handle(
2762 &keyObj, ELE_S200_KEY_STORE_USER_ID_GENERIC, kSSS_KeyPart_Default, kSSS_CipherType_SYMMETRIC, 16U,
2763 kSSS_KeyProp_NoPlainRead | kSSS_KeyProp_NoPlainWrite | kSSS_KeyProp_CryptoAlgo_KDF))
2764 {
2765 break;
2766 }
2767
2768 if (kStatus_SSS_Success != sss_sscp_key_store_import_key(&g_keyStore, &keyObj, pKey, gSecLibElkeBlobSize_c,
2769 128U, kSSS_blobType_ELKE_blob))
2770 {
2771 break;
2772 }
2773 }
2774 else
2775 {
2776 /* Invalid keyType. */
2777 result = gSecBadArgument_c;
2778 break;
2779 }
2780
2781 size_t e2eBlobByteLen = gSecLibElkeBlobSize_c;
2782
2783 if (kStatus_SSS_Success !=
2784 sss_sscp_key_store_export_key(&g_keyStore, &keyObj, pOutKey, &e2eBlobByteLen, kSSS_blobType_E2E_blob))
2785 {
2786 break;
2787 }
2788 result = gSecSuccess_c;
2789 } while (false);
2790 SECLIB_MUTEX_UNLOCK();
2791 if (keyObjFree == true)
2792 {
2793 (void)sss_sscp_key_object_free(&keyObj, kSSS_keyObjFree_KeysStoreDefragment);
2794 }
2795 return result;
2796}
2797
2798/************************************************************************************
2799 * \brief Generates a symmetric key in ELKE blob or plain text form from an E2E blob. This function needs to be preceded
2800 *by least one ECDH_P256_ComputeA2BKeySecure
2801 *
2802 * \param[in] pKey pointer to the input E2E blob.
2803 * \param[in] keyType output key type.
2804 * \param[out] pOutKey pointer to where the output key will be copied.
2805 *
2806 * \return gSecSuccess_c or error
2807 *
2808 ************************************************************************************/
2809secResultType_t SecLib_ImportA2BBlobSecure(const uint8_t *pKey, const secInputKeyType_t keyType, uint8_t *pOutKey)
2810{
2811 /* This function needs to be preceded by least one ECDH_P256_ComputeA2BKeySecure */
2812 secResultType_t result = gSecError_c;
2813 size_t keyBitLen = 128U, keyByteLen = 16U;
2814 sss_sscp_object_t keyObj;
2815 bool_t keyInit = false;
2816 uint8_t tempKey[16];
2817
2818 SECLIB_MUTEX_LOCK();
2819 do
2820 {
2821 if ((NULL == pKey) || (NULL == pOutKey))
2822 {
2823 result = gSecBadArgument_c;
2824 break;
2825 }
2826 if ((CRYPTO_InitHardware()) != kStatus_Success)
2827 {
2828 break;
2829 }
2830
2831 if (sss_sscp_key_object_init(&keyObj, &g_keyStore) != kStatus_SSS_Success)
2832 {
2833 break;
2834 }
2835 keyInit = true;
2836
2837 if (gSecPlainText_c == keyType)
2838 {
2839 if (sss_sscp_key_object_allocate_handle(&keyObj, ELE_S200_KEY_STORE_USER_ID_GENERIC, kSSS_KeyPart_Default,
2840 kSSS_CipherType_NONE, 16u,
2841 SSS_KEYPROP_OPERATION_AES) != kStatus_SSS_Success)
2842 {
2843 break;
2844 }
2845
2846 if (sss_sscp_key_store_import_key(&g_keyStore, &keyObj, pKey, 40U, 8U * 40U, kSSS_blobType_E2E_blob) !=
2847 kStatus_SSS_Success)
2848 {
2849 break;
2850 }
2851
2852 if (sss_sscp_key_store_get_key(&g_keyStore, &keyObj, tempKey, &keyByteLen, &keyBitLen,
2853 kSSS_KeyPart_Default) != kStatus_SSS_Success)
2854 {
2855 break;
2856 }
2857
2858 FLib_MemCpyReverseOrder(pOutKey, tempKey, 16U);
2859 }
2860 else if (gSecElkeBlob_c == keyType)
2861 {
2862 size_t e2eBlobByteLen = gSecLibElkeBlobSize_c;
2863
2864 if (kStatus_SSS_Success !=
2865 sss_sscp_key_object_allocate_handle(&keyObj, ELE_S200_KEY_STORE_USER_ID_GENERIC, kSSS_KeyPart_Default,
2866 kSSS_CipherType_SYMMETRIC, 16U, mSecLibKeyPropCryptoAlgoAll_c))
2867 {
2868 break;
2869 }
2870
2871 if (sss_sscp_key_store_import_key(&g_keyStore, &keyObj, pKey, 40U, 8U * 40U, kSSS_blobType_E2E_blob) !=
2872 kStatus_SSS_Success)
2873 {
2874 break;
2875 }
2876
2877 if (kStatus_SSS_Success !=
2878 sss_sscp_key_store_export_key(&g_keyStore, &keyObj, pOutKey, &e2eBlobByteLen, kSSS_blobType_ELKE_blob))
2879 {
2880 break;
2881 }
2882 }
2883 else if (gSecLtkElkeBlob_c == keyType)
2884 {
2885 size_t e2eBlobByteLen = gSecLibElkeBlobSize_c;
2886
2887 if (sss_sscp_key_object_allocate_handle(
2888 &keyObj, ELE_S200_KEY_STORE_USER_ID_GENERIC, kSSS_KeyPart_Default, kSSS_CipherType_SYMMETRIC, 16u,
2889 kSSS_KeyProp_NoPlainRead | kSSS_KeyProp_NoPlainWrite | kSSS_KeyProp_CryptoAlgo_KDF) !=
2890 kStatus_SSS_Success)
2891 {
2892 break;
2893 }
2894
2895 if (sss_sscp_key_store_import_key(&g_keyStore, &keyObj, pKey, 40U, 8U * 40U, kSSS_blobType_E2E_blob) !=
2896 kStatus_SSS_Success)
2897 {
2898 break;
2899 }
2900
2901 if (kStatus_SSS_Success !=
2902 sss_sscp_key_store_export_key(&g_keyStore, &keyObj, pOutKey, &e2eBlobByteLen, kSSS_blobType_ELKE_blob))
2903 {
2904 break;
2905 }
2906 }
2907 else
2908 {
2909 /* Invalid keyType */
2910 result = gSecBadArgument_c;
2911 break;
2912 }
2913
2914 result = gSecSuccess_c;
2915 } while (false);
2916 SECLIB_MUTEX_UNLOCK();
2917
2918 if (keyInit == true)
2919 {
2920 (void)sss_sscp_key_object_free(&keyObj, kSSS_keyObjFree_KeysStoreDefragment);
2921 }
2922 return result;
2923}
2924
2925/*! *********************************************************************************
2926*************************************************************************************
2927* Private functions
2928*************************************************************************************
2929********************************************************************************** */
2930
2931static bool ECP256_LePointValid(const ecp256Point_t *P)
2932{
2933#if gSecLibUseDspExtension_d
2934 ecp256Point_t tmp;
2935 ECP256_PointCopy_and_change_endianness(tmp.raw, P->raw);
2936 return ECP256_PointValid(&tmp);
2937#else
2938 extern bool_t EcP256_IsPointOnCurve(const uint32_t *X, const uint32_t *Y);
2939 return EcP256_IsPointOnCurve((const uint32_t *)&P->components_32bit.x[0],
2940 (const uint32_t *)&P->components_32bit.y[0]);
2941#endif
2942}
2943
2944/************************************************************************************
2945 * \private
2946 * \brief Function used to create the mac key and LTK using Bluetooth F5 algorithm
2947 * Only ever called in the secure (Key blobs) variant of the F5,
2948 *
2949 * \param [in] pPubDhKeyObj pointer to DH Key object
2950 * \param [in] pDerivationDataMacKey derivation data for MacKey
2951 * \param [in] pDerivationDataLTK derivation data for LTK
2952 * \param [out] pMacKey pointer to mac key
2953 * \param [out] pLTKBlob pointer to LTK blob
2954 *
2955 * \return sss_status_t
2956 ************************************************************************************/
2957static sss_status_t ELKE_BLE_SM_F5_DeriveKeysSecure(const uint8_t *pPubDhKeyObj,
2958 const uint8_t *pDerivationDataMacKey,
2959 const uint8_t *pDerivationDataLTK,
2960 uint8_t *pMacKey,
2961 uint8_t *pLTKBlob)
2962{
2963 sss_sscp_object_t keyObj__MacKey;
2964 sss_sscp_object_t keyObj__LTK;
2965 sss_sscp_object_t keyObj__DHKey;
2966
2967 sss_sscp_derive_key_t ctx_deriveKey;
2968
2969 bool bInitialized_MacKey = false;
2970 bool bInitialized_LTK = false;
2971
2972 sss_status_t result = kStatus_SSS_Fail;
2973
2974 SECLIB_MUTEX_LOCK();
2975 do
2976 {
2977 STATIC_ASSERT(sizeof(ec_p256_coordinate) == 32, "DH Key X coordinate is 32 bytes");
2978 STATIC_ASSERT(sizeof(sss_sscp_object_t) <= sizeof(ec_p256_coordinate),
2979 "sss_sscp_object_t must fit in a ec_p256_coordinate (32 bytes)");
2980 FLib_MemCpy((uint8_t *)&keyObj__DHKey, pPubDhKeyObj, sizeof(sss_sscp_object_t));
2981
2982 if ((CRYPTO_InitHardware()) != kStatus_Success)
2983 {
2984 break;
2985 }
2986
2987 if (sss_sscp_key_object_init(&keyObj__MacKey, &g_keyStore) != kStatus_SSS_Success)
2988 {
2989 break;
2990 }
2991 bInitialized_MacKey = true;
2992
2993 if (sss_sscp_key_object_allocate_handle(
2994 &keyObj__MacKey, ELE_S200_KEY_STORE_USER_ID_GENERIC, kSSS_KeyPart_Default, kSSS_CipherType_SYMMETRIC,
2995 16u, kSSS_KeyProp_NoPlainWrite | kSSS_KeyProp_CryptoAlgo_MAC) != kStatus_SSS_Success)
2996 {
2997 break;
2998 }
2999
3000 if (sss_sscp_key_object_init(&keyObj__LTK, &g_keyStore) != kStatus_SSS_Success)
3001 {
3002 break;
3003 }
3004 bInitialized_LTK = true;
3005
3006 if (sss_sscp_key_object_allocate_handle(
3007 &keyObj__LTK, ELE_S200_KEY_STORE_USER_ID_GENERIC, kSSS_KeyPart_Default, kSSS_CipherType_SYMMETRIC, 16u,
3008#if !gSecLibAllowLtkFromBlob_c
3009 kSSS_KeyProp_NoPlainRead |
3010#endif
3011 kSSS_KeyProp_NoPlainWrite | kSSS_KeyProp_CryptoAlgo_KDF) != kStatus_SSS_Success)
3012 {
3013 break;
3014 }
3015
3016 /* derive keys for f5() */
3017 if (sss_sscp_derive_key_context_init(&ctx_deriveKey, &g_sssSession, &keyObj__DHKey, kAlgorithm_SSS_BLE_F5,
3018 kMode_SSS_SymmetricKDF) != kStatus_SSS_Success)
3019 {
3020 break;
3021 }
3022
3023 do
3024 {
3025 if (sss_sscp_derive_key(&ctx_deriveKey, pDerivationDataMacKey, 53u, &keyObj__MacKey, 0U) !=
3026 kStatus_SSS_Success)
3027 {
3028 break;
3029 }
3030 if (sss_sscp_derive_key(&ctx_deriveKey, pDerivationDataLTK, 53u, &keyObj__LTK, 0U) != kStatus_SSS_Success)
3031 {
3032 break;
3033 }
3034 } while (false);
3035
3036 if (sss_sscp_derive_key_context_free(&ctx_deriveKey) != kStatus_SSS_Success)
3037 {
3038 break;
3039 }
3040
3041 /* export keys from S200 */
3042
3043 /* export MacKey */
3044 size_t bufLen = 16u;
3045 size_t keyBitLen = 128u;
3046 uint8_t macData[16];
3047 if (sss_sscp_key_store_get_key(&g_keyStore, &keyObj__MacKey, macData, &bufLen, &keyBitLen,
3048 kSSS_KeyPart_Default) != kStatus_SSS_Success)
3049 {
3050 break;
3051 }
3052 FLib_MemCpyReverseOrder(pMacKey, macData, 16);
3053
3054 /* export LTK blob */
3055 size_t ltkBlobByteLen = 40u;
3056 keyBitLen = 128u;
3057
3058 if (sss_sscp_key_store_export_key(&g_keyStore, &keyObj__LTK, pLTKBlob, <kBlobByteLen,
3059 kSSS_blobType_ELKE_blob) != kStatus_SSS_Success)
3060 {
3061 break;
3062 }
3063
3064 result = kStatus_SSS_Success;
3065 } while (false);
3066
3067 /* delete keys and contexts from S200 */
3068 if (bInitialized_MacKey)
3069 {
3070 (void)sss_sscp_key_object_free(&keyObj__MacKey, kSSS_keyObjFree_KeysStoreDefragment);
3071 }
3072
3073 if (bInitialized_LTK)
3074 {
3075 (void)sss_sscp_key_object_free(&keyObj__LTK, kSSS_keyObjFree_KeysStoreDefragment);
3076 }
3077
3078 /* DHkey object can be deleted here for SSS perspective */
3079 (void)sss_sscp_key_object_free(&keyObj__DHKey, kSSS_keyObjFree_KeysStoreDefragment);
3080
3081 SECLIB_MUTEX_UNLOCK();
3082
3083 return result;
3084}
3085
3086/*! *********************************************************************************
3087 * \brief This function pads an incomplete 16 byte block of data, where padding is
3088 * the concatenation of x and a single '1',
3089 * followed by the minimum number of '0's, so that the total length is equal to 128 bits.
3090 * Padding scheme is ISO/IEC 7816-4: one 80h byte (1 bit), followed by as many 00h as
3091 * required to fill a 128 bit block.
3092 *
3093 * \param[in, out] lastb Pointer to the last block of message to be padded
3094 *
3095 * \param[in] pad_block Padded block destination
3096 *
3097 * \param[in] length Number of message bytes in the block to be padded : must be in [0..AES_BLOCK_SIZE-1]
3098 *
3099 * \return length of padding [1..AES_BLOCK_SIZE] if ok, 0 otherwise
3100 *
3101 ********************************************************************************** */
3102static uint8_t SecLib_Padding(const uint8_t *lastb, uint8_t pad_block[AES_BLOCK_SIZE], uint8_t length)
3103{
3104 uint8_t padding_sz = 0;
3105 uint32_t j;
3106 if (length < AES_BLOCK_SIZE)
3107 {
3108 for (j = 0u; j < AES_BLOCK_SIZE; j++)
3109 {
3110 /* there may be 0 bytes to copy if message was a multiple of AES_BLOCK_SIZE */
3111 if (j < length)
3112 {
3113 /* original last block */
3114 pad_block[j] = lastb[j];
3115 }
3116 else if (j == length)
3117 {
3118 pad_block[j] = 0x80u;
3119 }
3120 else
3121 {
3122 pad_block[j] = 0x00u;
3123 }
3124 }
3125 padding_sz = AES_BLOCK_SIZE - length;
3126 }
3127 return padding_sz;
3128}
3129
3130/*! *********************************************************************************
3131 * \brief This function removes padding from an octet string (at most 16 bytes of data).
3132 *
3133 * \param[in] pIn Pointer to start of last AES block of a message to be depadded
3134 *
3135 * \return if > 0 Final size of padding to be removed : must be in [1..AES_BLOCK_SIZE].
3136 * if 0 : error occurred the last block does not contain expected padding patter.
3137 *
3138 ********************************************************************************** */
3139static uint8_t SecLib_DePadding(const uint8_t pad_block[AES_BLOCK_SIZE])
3140{
3141 uint8_t padding_sz = 0u;
3142
3143 for (uint8_t i = AES_BLOCK_SIZE; i > 0u; i--)
3144 {
3145 uint8_t ch = pad_block[i - 1u];
3146 if (ch == 0x80u)
3147 {
3148 padding_sz = AES_BLOCK_SIZE - i + 1u;
3149 break;
3150 }
3151 else if (ch != 0x00u)
3152 {
3153 /* not padding */
3154 padding_sz = 0u;
3155 break;
3156 }
3157 else
3158 {
3159 /* MISRA rule 15.7 but useless */
3160 continue;
3161 }
3162 }
3163 return padding_sz;
3164}