1/*
2 * Copyright 2025-2026 NXP
3 * SPDX-License-Identifier: BSD-3-Clause
4 */
5/*! *********************************************************************************
6 * \file
7 *
8 *
9 * This is the source file for the security module used by the connectivity stacks. The Security
10 * Module SecLib provides an abstraction from the Hardware to the upper layer.
11 * In this file, a wrapper to PSA API component is implemented.
12 ***********************************************************************************/
13
14/*! *********************************************************************************
15*************************************************************************************
16* Include
17*************************************************************************************
18********************************************************************************** */
19
20#include <stdint.h>
21#include "EmbeddedTypes.h"
22#include "fwk_config.h"
23#include "SecLib.h"
24#include "psa/crypto.h"
25#include "psa/crypto_types.h"
26#include "psa/crypto_values.h"
27#include "psa/crypto_extra.h"
28#include "fsl_component_mem_manager.h"
29#include "FunctionLib.h"
30#include "fwk_platform_crypto.h"
31#include "SecLib_ecp256.h"
32#include "CryptoLibSW.h"
33
34#if defined(PSA_CRYPTO_DRIVER_ELE_S2XX)
35#include "ele_s2xx.h"
36#endif /* PSA_CRYPTO_DRIVER_ELE_S2XX */
37
38/*! *********************************************************************************
39*************************************************************************************
40* Private macros
41*************************************************************************************
42********************************************************************************** */
43#define KEY_ID_BLE0 0x426c6530
44
45#define RAISE_ERROR(st, expected) \
46 if ((st) != (expected)) \
47 { \
48 if (PRINTF("\tassertion failed at %s:%d - " \
49 "actual:-%d expected:-%d\r\n", \
50 __FILE__, __LINE__, -(st), -(expected)) > -1) \
51 { \
52 break; \
53 } \
54 }
55
56/*! *********************************************************************************
57*************************************************************************************
58* Private type definitions
59*************************************************************************************
60********************************************************************************** */
61#define ECP256_COORDINATE_BITLEN 256u
62#define ECP256_COORDINATE_LEN (ECP256_COORDINATE_BITLEN >> 3)
63#define ECP256_COORDINATE_WLEN ((ECP256_COORDINATE_LEN) / 4U)
64
65/************************************************************************************
66*************************************************************************************
67* Private memory declarations
68*************************************************************************************
69************************************************************************************/
70typedef struct psa_ecp256_context_t
71{
72 big_int256_t PrivateKey[ECP256_COORDINATE_WLEN]; /*!< The private key : RNG output */
73 big_int256_t OwnPublicKey[2U * ECP256_COORDINATE_WLEN]; /*! Own Public computed from PrivateKey */
74 uint32_t keyId;
75 psa_key_id_t OwnKey; /*! Own Key object reference */
76} psa_ecp256_context_t;
77
78static psa_ecp256_context_t psa_g_ECP_KeyPair;
79static psa_ecp256_context_t *psa_pECPKeyPair = ((void *)0);
80
81/*! *********************************************************************************
82*************************************************************************************
83* Private functions
84*************************************************************************************
85********************************************************************************** */
86
87static bool ECP256_LePointValid(const ecp256Point_t *P)
88{
89#if defined gSecLibUseDspExtension_d && (gSecLibUseDspExtension_d != 0)
90 ecp256Point_t tmp;
91 ECP256_PointCopy_and_change_endianness(tmp.raw, P->raw);
92 return ECP256_PointValid(&tmp);
93#else
94 extern bool_t EcP256_IsPointOnCurve(const uint32_t *X, const uint32_t *Y);
95 return EcP256_IsPointOnCurve((const uint32_t *)&P->components_32bit.x[0],
96 (const uint32_t *)&P->components_32bit.y[0]);
97#endif
98}
99
100psa_key_location_t get_most_secure_key_location()
101{
102 /* default set to transparent location */
103 psa_key_location_t loc = PSA_KEY_LOCATION_LOCAL_STORAGE;
104
105#if defined(PSA_CRYPTO_DRIVER_ELE_S2XX)
106 loc = PSA_KEY_LOCATION_S200_KEY_STORAGE_NON_EL2GO;
107#endif /* PSA_CRYPTO_DRIVER_ELE_S2XX */
108
109 return loc;
110}
111
112/*! *********************************************************************************
113*************************************************************************************
114* Public functions
115*************************************************************************************
116********************************************************************************** */
117
118/*! *********************************************************************************
119 * \brief This function performs initialization of the cryptographic HW acceleration.
120 *
121 ********************************************************************************** */
122void SecLib_Init(void)
123{
124 psa_status_t status;
125 do
126 {
127 /* initialize psa crypto*/
128 status = psa_crypto_init();
129 RAISE_ERROR(status, PSA_SUCCESS);
130 } while (false);
131}
132
133void SecLib_ReInit(void)
134{
135 /* Initialize cryptographic hardware.*/
136 (void)PLATFORM_ReinitCrypto();
137}
138
139/*! *********************************************************************************
140 * \brief This function will allow reinitizialize the cryptographic HW acceleration
141 * next time we need it, typically after lowpower mode.
142 *
143 ********************************************************************************** */
144void SecLib_DeInit(void)
145{
146 /* Deinitialize cryptographic hardware.*/
147 (void)PLATFORM_TerminateCrypto();
148}
149
150/*! *********************************************************************************
151 * \brief This function performs all SHA256 steps on multiple bytes: initialize,
152 * update, finish, and update context data.
153 * The final hash value is stored at the provided output location.
154 *
155 * \param [in] pData Pointer to the input data
156 * \param [in] numBytes Number of bytes to hash
157 * \param [in,out] pOutput Pointer to the output location
158 *
159 ********************************************************************************** */
160secResultType_t SecLib_SHA256_Hash(const uint8_t *pData, uint32_t numBytes, uint8_t *pOutput)
161{
162 secResultType_t res = gSecError_c;
163 const psa_algorithm_t alg = PSA_ALG_SHA_256;
164 size_t hashLength = 0U; /* Initialize hash length to 0 */
165 psa_status_t status;
166
167 do
168 {
169 if ((pOutput == NULL) || (pData == NULL))
170 {
171 res = gSecBadArgument_c;
172 break;
173 }
174 /* SHA 256 computation */
175 status = psa_hash_compute(alg, pData, numBytes, pOutput, SHA256_HASH_SIZE, &hashLength);
176 RAISE_ERROR(status, PSA_SUCCESS);
177 res = gSecSuccess_c;
178 } while (false);
179 return res;
180}
181
182/*! *********************************************************************************
183 * \brief This function calculates XOR of individual byte pairs in two uint8_t arrays.
184 * pDst[i] := pDst[i] ^ pSrc[i] for i=0 to n-1
185 *
186 * \param[in] pDst First byte array operand for XOR and destination byte array
187 *
188 * \param[in] pSrc Second byte array operand for XOR
189 *
190 * \param[in] n Length of the byte array which will be XORed
191 *
192 ********************************************************************************** */
193void SecLib_XorN(uint8_t *pDst, const uint8_t *pSrc, uint8_t n)
194{
195 while (n != 0U)
196 {
197 *pDst = *pDst ^ *pSrc;
198 pDst = pDst + 1;
199 pSrc = pSrc + 1;
200 n--;
201 }
202}
203
204/*! *********************************************************************************
205 * \brief This function performs AES-128 encryption on a 16-byte block.
206 *
207 * \param[in] pInput Pointer to the location of the 16-byte plain text block.
208 *
209 * \param[in] pKey Pointer to the location of the 128-bit key.
210 *
211 * \param[out] pOutput Pointer to the location to store the 16-byte ciphered output.
212 *
213 * \pre All Input/Output pointers must refer to a memory address aligned to 4 bytes!
214 *
215 ********************************************************************************** */
216secResultType_t SecLib_AES_128_Encrypt(const uint8_t *pInput, const uint8_t *pKey, uint8_t *pOutput)
217{
218 secResultType_t res = gSecError_c;
219 size_t key_bits = AES_128_KEY_BYTE_LEN;
220 const psa_algorithm_t alg = PSA_ALG_ECB_NO_PADDING;
221 psa_status_t status;
222 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
223 psa_key_id_t key = 0U;
224 size_t output_len = 0U;
225
226 /* key initialisation before import */
227 psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
228 psa_set_key_algorithm(&attributes, alg);
229 psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT);
230 psa_set_key_bits(&attributes, AES_128_KEY_BITS);
231 psa_set_key_lifetime(&attributes, PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(PSA_KEY_LIFETIME_VOLATILE,
232 get_most_secure_key_location()));
233
234 do
235 {
236 if ((pInput == NULL) || (pKey == NULL) || (pOutput == NULL))
237 {
238 res = gSecBadArgument_c;
239 break;
240 }
241 status = psa_import_key(&attributes, pKey, key_bits, &key); /* import the key in psa and get its id */
242 RAISE_ERROR(status, PSA_SUCCESS);
243
244 /* execute encryption with ECB NO PADDING */
245 status = psa_cipher_encrypt(key, alg, pInput, AES_BLOCK_SIZE, pOutput, AES_BLOCK_SIZE, &output_len);
246 RAISE_ERROR(status, PSA_SUCCESS);
247
248 status = psa_destroy_key(key);
249 RAISE_ERROR(status, PSA_SUCCESS);
250 res = gSecSuccess_c;
251 } while (false);
252 return res;
253}
254
255/*! *********************************************************************************
256 * \brief This function performs AES-128-ECB encryption on a message block.
257 * This function only accepts input lengths which are multiple
258 * of 16 bytes (AES 128 block size).
259 *
260 * \param[in] pInput Pointer to the location of the input message.
261 *
262 * \param[in] inputLen Input message length in bytes.
263 *
264 * \param[in] pKey Pointer to the location of the 128-bit key.
265 *
266 * \param[out] pOutput Pointer to the location to store the ciphered output.
267 *
268 * \pre All Input/Output pointers must refer to a memory address aligned to 4 bytes!
269 *
270 ********************************************************************************** */
271secResultType_t SecLib_AES_128_ECB_Encrypt(const uint8_t *pInput,
272 uint32_t inputLen,
273 const uint8_t *pKey,
274 uint8_t *pOutput)
275{
276 secResultType_t res = gSecError_c;
277 size_t key_bits = AES_128_KEY_BYTE_LEN;
278 const psa_algorithm_t alg = PSA_ALG_ECB_NO_PADDING;
279 psa_status_t status;
280 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
281 psa_key_id_t key = 0U;
282 size_t output_len = 0U;
283
284 do
285 {
286 if ((pInput == NULL) || (pKey == NULL) || (pOutput == NULL) || (inputLen == 0) ||
287 ((inputLen % AES_BLOCK_SIZE) != 0U))
288 {
289 res = gSecBadArgument_c;
290 break;
291 }
292 /* key initialisation before import */
293 psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
294 psa_set_key_algorithm(&attributes, alg);
295 psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT);
296 psa_set_key_bits(&attributes, AES_128_KEY_BITS);
297 psa_set_key_lifetime(&attributes, PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(
298 PSA_KEY_LIFETIME_VOLATILE, get_most_secure_key_location()));
299
300 /* import pKey and get the address of the imported key */
301 status = psa_import_key(&attributes, pKey, key_bits, &key);
302 RAISE_ERROR(status, PSA_SUCCESS);
303
304 /* execute the encryption with our key*/
305 status = psa_cipher_encrypt(key, alg, pInput, inputLen, pOutput, inputLen, &output_len);
306 RAISE_ERROR(status, PSA_SUCCESS);
307
308 status = psa_destroy_key(key); /* destroy key after use */
309 RAISE_ERROR(status, PSA_SUCCESS);
310 res = gSecSuccess_c;
311 } while (false);
312 return res;
313}
314
315/*! *********************************************************************************
316 * \brief This function performs AES-128 decryption on a 16-byte block.
317 *
318 * \param[in] pInput Pointer to the location of the 16-byte plain text block.
319 *
320 * \param[in] pKey Pointer to the location of the 128-bit key.
321 *
322 * \param[out] pOutput Pointer to the location to store the 16-byte ciphered output.
323 *
324 * \pre All Input/Output pointers must refer to a memory address aligned to 4 bytes!
325 *
326 ********************************************************************************** */
327secResultType_t SecLib_AES_128_Decrypt(const uint8_t *pInput, const uint8_t *pKey, uint8_t *pOutput)
328{
329 secResultType_t res = gSecError_c;
330 size_t key_bits = AES_128_KEY_BYTE_LEN;
331 const psa_algorithm_t alg = PSA_ALG_ECB_NO_PADDING;
332 psa_status_t status;
333 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
334 psa_key_id_t key = 0U;
335 size_t output_len = 0U;
336
337 /* key initialisation before import */
338 psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
339 psa_set_key_algorithm(&attributes, alg);
340 psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DECRYPT);
341 psa_set_key_bits(&attributes, AES_128_KEY_BITS);
342 psa_set_key_lifetime(&attributes, PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(PSA_KEY_LIFETIME_VOLATILE,
343 get_most_secure_key_location()));
344
345 do
346 {
347 if ((pInput == NULL) || (pKey == NULL) || (pOutput == NULL))
348 {
349 res = gSecBadArgument_c;
350 break;
351 }
352 status = psa_import_key(&attributes, pKey, key_bits, &key);
353 RAISE_ERROR(status, PSA_SUCCESS);
354
355 /* decrypt using ECB NO PADDING */
356 status = psa_cipher_decrypt(key, alg, pInput, AES_BLOCK_SIZE, pOutput, AES_128_BLOCK_SIZE, &output_len);
357 RAISE_ERROR(status, PSA_SUCCESS);
358
359 /* destroy key after use */
360 status = psa_destroy_key(key);
361 RAISE_ERROR(status, PSA_SUCCESS);
362 res = gSecSuccess_c;
363 } while (false);
364 return res;
365}
366
367/*! *********************************************************************************
368 * \brief This function performs AES-128 decryption on a 16-byte block.
369 *
370 * \param[in] pInput Pointer to the location of the 16-byte plain text block.
371 *
372 * \param[in] inputLen Input message length in bytes.
373 *
374 * \param[in] pKey Pointer to the location of the 128-bit key.
375 *
376 * \param[out] pOutput Pointer to the location to store the 16-byte ciphered output.
377 *
378 * \pre All Input/Output pointers must refer to a memory address aligned to 4 bytes!
379 *
380 ********************************************************************************** */
381secResultType_t SecLib_AES_128_ECB_Decrypt(const uint8_t *pInput,
382 uint32_t inputLen,
383 const uint8_t *pKey,
384 uint8_t *pOutput)
385{
386 secResultType_t res = gSecError_c;
387
388 size_t key_bits = AES_128_KEY_BYTE_LEN;
389 const psa_algorithm_t alg = PSA_ALG_ECB_NO_PADDING;
390 psa_status_t status;
391 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
392 psa_key_id_t key = 0U;
393 size_t output_len = 0U;
394
395 do
396 {
397 if ((pInput == NULL) || (pKey == NULL) || (pOutput == NULL) || (inputLen == 0) ||
398 ((inputLen % AES_BLOCK_SIZE) != 0U))
399 {
400 res = gSecBadArgument_c;
401 break;
402 }
403 psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
404 psa_set_key_algorithm(&attributes, alg);
405 psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DECRYPT);
406 psa_set_key_bits(&attributes, AES_128_KEY_BITS);
407 psa_set_key_lifetime(&attributes, PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(
408 PSA_KEY_LIFETIME_VOLATILE, get_most_secure_key_location()));
409
410 status = psa_import_key(&attributes, pKey, key_bits, &key);
411 RAISE_ERROR(status, PSA_SUCCESS);
412
413 status = psa_cipher_decrypt(key, alg, pInput, inputLen, pOutput, inputLen, &output_len);
414 RAISE_ERROR(status, PSA_SUCCESS);
415
416 status = psa_destroy_key(key);
417 RAISE_ERROR(status, PSA_SUCCESS);
418 res = gSecSuccess_c;
419 } while (false);
420
421 return res;
422}
423
424/*! *********************************************************************************
425 * \brief This function performs AES-128-CMAC on a message block accepting input data
426 * which is in LSB first format and computing the authentication code
427 * starting from the end of the data.
428 *
429 * \param[in] pInput Pointer to the location of the input message.
430 *
431 * \param[in] inputLen Length of the input message in bytes.
432 * The input data must be provided LSB first.
433 *
434 * \param[in] pKey Pointer to the location of the 128-bit key.
435 * The key must be provided MSB first.
436 *
437 * \param[out] pOutput Pointer to the location to store the 16-byte authentication code.
438 * The code will be generated MSB first.
439 *
440 ********************************************************************************** */
441secResultType_t SecLib_AES_128_CMAC_LsbFirstInput(const uint8_t *pInput,
442 uint32_t inputLen,
443 const uint8_t *pKey,
444 uint8_t *pOutput)
445{
446 secResultType_t res = gSecError_c;
447 size_t key_bits = AES_128_KEY_BYTE_LEN;
448 const psa_algorithm_t alg = PSA_ALG_CMAC; /* Set algorithm to cmac */
449 psa_status_t status;
450 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
451 psa_key_id_t key = 0U;
452 size_t output_len = 0U;
453
454 do
455 {
456 if ((pInput == NULL) || (pKey == NULL) || (pOutput == NULL))
457 {
458 res = gSecBadArgument_c;
459 break;
460 }
461
462 /* key initialisation before import */
463 psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_MESSAGE);
464 psa_set_key_algorithm(&attributes, alg);
465 psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
466
467 status = psa_import_key(&attributes, pKey, key_bits, &key);
468 RAISE_ERROR(status, PSA_SUCCESS);
469
470 psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT; /* init cmac operation */
471
472 status = psa_mac_sign_setup(&operation, key, alg); /* setup function */
473 RAISE_ERROR(status, PSA_SUCCESS);
474
475 /* Walk the input buffer from the end to the start and reverse the blocks
476 * before calling the CMAC update function. */
477 uint8_t reversedBlock[AES_128_BLOCK_SIZE] = {0U};
478 pInput += inputLen;
479 do
480 {
481 uint32_t currentCmacInputBlkLen = 0U;
482 if (inputLen < AES_128_BLOCK_SIZE)
483 {
484 /* If this is the first and single block it is legal for it to have an input length of 0
485 * in which case nothing will be copied in the reversed CMAC input buffer. */
486 currentCmacInputBlkLen = inputLen;
487 }
488 else
489 {
490 currentCmacInputBlkLen = AES_128_BLOCK_SIZE;
491 }
492 pInput -= currentCmacInputBlkLen;
493 inputLen -= currentCmacInputBlkLen;
494 /* Copy the input block to the reversed CMAC input buffer */
495 FLib_MemCpyReverseOrder(reversedBlock, pInput, currentCmacInputBlkLen);
496
497 /* compute mac operation on a block */
498 status = psa_mac_update(&operation, reversedBlock, currentCmacInputBlkLen);
499 RAISE_ERROR(status, PSA_SUCCESS);
500
501 } while (inputLen != 0U);
502
503 size_t macLen =
504 16U; /* value of PSA_MAC_LENGTH(PSA_KEY_TYPE_AES, key_bits, alg) but macro has multiple misras; */
505 status = psa_mac_sign_finish(&operation, pOutput, macLen, &output_len);
506 RAISE_ERROR(status, PSA_SUCCESS);
507
508 status = psa_destroy_key(key); /* destroy key after use */
509 RAISE_ERROR(status, PSA_SUCCESS);
510 res = gSecSuccess_c;
511 } while (false);
512 return res;
513}
514
515/*! *********************************************************************************
516 * \brief This function performs AES-128-CMAC on a message block.
517 *
518 * \param[in] pInput Pointer to the location of the input message.
519 *
520 * \param[in] inputLen Length of the input message in bytes. The input data must be provided MSB first.
521 *
522 * \param[in] pKey Pointer to the location of the 128-bit key. The key must be provided MSB first.
523 *
524 * \param[out] pOutput Pointer to the location to store the 16-byte authentication code. The code will be generated MSB
525 *first.
526 *
527 * \remarks This is public open source code! Terms of use must be checked before use!
528 *
529 ********************************************************************************** */
530secResultType_t SecLib_AES_128_CMAC(const uint8_t *pInput,
531 const uint32_t inputLen,
532 const uint8_t *pKey,
533 uint8_t *pOutput)
534{
535 secResultType_t res = gSecError_c;
536 ;
537 size_t key_bits = AES_128_KEY_BYTE_LEN;
538 const psa_algorithm_t alg = PSA_ALG_CMAC; /* set algorithm to cmac */
539 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
540 psa_key_id_t key = 0U;
541 size_t output_len = 0U;
542
543 do
544 {
545 psa_status_t status;
546
547 if ((pInput == NULL) || (pKey == NULL) || (pOutput == NULL))
548 {
549 res = gSecBadArgument_c;
550 break;
551 }
552 /* key initialisation before import */
553 psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_MESSAGE);
554 psa_set_key_algorithm(&attributes, alg);
555 psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
556 psa_set_key_bits(&attributes, AES_128_KEY_BITS);
557 psa_set_key_lifetime(&attributes, PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(
558 PSA_KEY_LIFETIME_VOLATILE, get_most_secure_key_location()));
559
560 status = psa_import_key(&attributes, pKey, key_bits, &key);
561
562 RAISE_ERROR(status, PSA_SUCCESS);
563
564 /* compute mac operation on pInput */
565 status = psa_mac_compute(key, alg, pInput, inputLen, pOutput, AES_BLOCK_SIZE, &output_len);
566 RAISE_ERROR(status, PSA_SUCCESS);
567
568 status = psa_destroy_key(key); /* destroy key after use */
569 RAISE_ERROR(status, PSA_SUCCESS);
570
571 res = gSecSuccess_c;
572
573 } while (false);
574 return res;
575}
576
577/*! *********************************************************************************
578 * \brief This function performs AES-128-CCM on a message block.
579 *
580 * \param[in] pInput Pointer to the location of the input message (plaintext or ciphertext).
581 *
582 * \param[in] inputLen Length of the input plaintext in bytes when encrypting.
583 * Length of the input ciphertext without the MAC length when decrypting.
584 *
585 * \param[in] pAuthData Pointer to the additional authentication data.
586 *
587 * \param[in] authDataLen Length of additional authentication data.
588 *
589 * \param[in] pNonce Pointer to the Nonce.
590 *
591 * \param[in] nonceSize The size of the nonce (7-13).
592 *
593 * \param[in] pKey Pointer to the location of the 128-bit key.
594 *
595 * \param[out] pOutput Pointer to the location to store the plaintext data when decrypting.
596 * Pointer to the location to store the ciphertext data when encrypting.
597 *
598 * \param[out] pCbcMac Pointer to the location to store the Message Authentication Code (MAC) when encrypting.
599 * Pointer to the location where the received MAC can be found when decrypting.
600 *
601 * \param[in] macSize The size of the MAC.
602 *
603 * \param[in] flags Select encrypt/decrypt operations (gSecLib_CCM_Encrypt_c, gSecLib_CCM_Decrypt_c)
604 *
605 * \return 0 if encryption/decryption was successful; otherwise, error code for failed encryption/decryption
606 *
607 * \remarks At decryption, MIC fail is also signalled by returning a non-zero value.
608 *
609 ********************************************************************************** */
610secResultType_t SecLib_AES_128_CCM(const uint8_t *pInput,
611 uint16_t inputLen,
612 const uint8_t *pAuthData,
613 uint16_t authDataLen,
614 const uint8_t *pNonce,
615 uint8_t nonceSize,
616 const uint8_t *pKey,
617 uint8_t *pOutput,
618 uint8_t *pCbcMac,
619 uint8_t macSize,
620 uint32_t flags)
621{
622 secResultType_t ret = gSecError_c;
623
624 size_t key_bits = AES_128_KEY_BYTE_LEN;
625 psa_algorithm_t alg = PSA_ALG_CCM;
626 psa_status_t status = PSA_ERROR_GENERIC_ERROR;
627 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
628 psa_key_id_t key = 0U;
629 size_t output_len = 0U;
630
631 do
632 {
633 uint8_t *buff;
634 if ((pInput == NULL) || (pAuthData == NULL) || (pNonce == NULL) || (pOutput == NULL) || (pKey == NULL) ||
635 (pCbcMac == NULL))
636 {
637 ret = gSecBadArgument_c;
638 break;
639 }
640 buff = MEM_BufferAlloc((uint32_t)(inputLen + (uint32_t)macSize));
641 if (buff == NULL)
642 {
643 ret = gSecAllocError_c;
644 break;
645 }
646
647 /* set key usage depending on flags */
648 if ((flags & gSecLib_CCM_Decrypt_c) != 0U)
649 {
650 psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DECRYPT);
651 }
652 else
653 {
654 psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT);
655 }
656
657 /* set the mac size of the algorithm to macSize, without this default is 32 */
658 alg = PSA_ALG_AEAD_WITH_SHORTENED_TAG(alg, (uint32_t)macSize);
659
660 psa_set_key_algorithm(&attributes, alg);
661 psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
662 psa_set_key_bits(&attributes, AES_128_KEY_BITS);
663 psa_set_key_lifetime(&attributes, PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(
664 PSA_KEY_LIFETIME_VOLATILE, get_most_secure_key_location()));
665
666 status = psa_import_key(&attributes, pKey, key_bits, &key);
667 RAISE_ERROR(status, PSA_SUCCESS);
668
669 if ((flags & gSecLib_CCM_Decrypt_c) != 0U)
670 {
671 /* combine pInput and pCbcMac in a buffer to comply with PSA prototype psa_aead_decrypt */
672 FLib_MemCpy(buff, pInput, inputLen);
673 FLib_MemCpy(buff + inputLen, pCbcMac, macSize);
674 status = psa_aead_decrypt(key, alg, pNonce, nonceSize, pAuthData, authDataLen, buff,
675 (uint32_t)(inputLen + (uint32_t)macSize), pOutput,
676 PSA_AEAD_DECRYPT_OUTPUT_MAX_SIZE(inputLen), &output_len);
677 }
678 else
679 {
680 status = psa_aead_encrypt(key, alg, pNonce, nonceSize, pAuthData, authDataLen, pInput, inputLen, buff,
681 (uint32_t)(inputLen + (uint32_t)macSize), &output_len);
682 /* split output buffer in pOutput and pCbcMac */
683 FLib_MemCpy(pOutput, buff, inputLen);
684 FLib_MemCpy(pCbcMac, buff + inputLen, macSize);
685 }
686 RAISE_ERROR(status, PSA_SUCCESS);
687
688 status = psa_destroy_key(key); /* destroy key after use */
689 RAISE_ERROR(status, PSA_SUCCESS);
690
691 (void)MEM_BufferFree(buff);
692 ret = gSecSuccess_c;
693 } while (false);
694 return ret;
695}
696
697/************************************************************************************
698 * \brief Checks whether a public key is valid (point is on the curve).
699 *
700 * \return TRUE if valid, FALSE if not
701 *
702 ************************************************************************************/
703bool_t ECP256_IsKeyValid(const ecp256Point_t *pKey)
704{
705 bool_t ret = false;
706
707 if (ECP256_LePointValid(pKey))
708 {
709 ret = true;
710 }
711
712 return ret;
713}
714
715/************************************************************************************
716 * \brief Computes the Diffie-Hellman Key for an ECDH P256 key pair.
717 *
718 * \return gSecSuccess_c or error
719 *
720 ************************************************************************************/
721secResultType_t ECDH_P256_ComputeDhKeySeg(computeDhKeyParam_t *pDhKeyData)
722{
723 secResultType_t res = gSecBadArgument_c;
724 if (pDhKeyData != NULL)
725 {
726 res = ECDH_P256_ComputeDhKey(&pDhKeyData->privateKey, &pDhKeyData->peerPublicKey, &pDhKeyData->outPoint,
727 pDhKeyData->keepInternalBlob);
728 }
729 return res;
730}
731
732/************************************************************************************
733 * \brief Computes the Diffie-Hellman Key for an ECDH P256 key pair.
734 *
735 * \return gSecSuccess_c or error
736 *
737 ************************************************************************************/
738secResultType_t ECDH_P256_ComputeDhKey(const ecdhPrivateKey_t *pInPrivateKey,
739 const ecdhPublicKey_t *pInPeerPublicKey,
740 ecdhDhKey_t *pOutDhKey,
741 const bool_t keepBlobDhKey)
742{
743 secResultType_t ret = gSecError_c;
744 size_t output_len = 0U;
745 uint8_t bufPub[sizeof(ecdhPublicKey_t) + 1]; /* +1 for point format byte*/
746 uint8_t bufSecret[sizeof(ecdhDhKey_t)];
747 do
748 {
749 /* Check if output DH key pointer is valid */
750 if ((pInPrivateKey == NULL) || (pInPeerPublicKey == NULL) || (pOutDhKey == NULL))
751 {
752 ret = gSecBadArgument_c;
753 break;
754 }
755 if (psa_pECPKeyPair == NULL)
756 {
757 ret = gSecError_c;
758 break;
759 }
760 /* Validate that the peer public key is a valid point on the curve */
761 if (!ECP256_LePointValid(pInPeerPublicKey))
762 {
763 ret = gSecInvalidPublicKey_c;
764 break;
765 }
766
767 /* Convert little-endian to big-endian format for PSA API */
768 ECP256_PointWrite(bufPub, pInPeerPublicKey, true);
769
770 /* Perform ECDH key agreement using PSA crypto API */
771 psa_status_t status =
772 psa_raw_key_agreement(PSA_ALG_ECDH, psa_pECPKeyPair->OwnKey, bufPub, sizeof(ecdhPublicKey_t) + 1, bufSecret,
773 sizeof(ecdhDhKey_t), &output_len);
774 RAISE_ERROR(status, PSA_SUCCESS);
775
776 ret = gSecSuccess_c;
777
778 /* Convert big-endian to little-endian format for output */
779 ECP256_PointCopy_and_change_endianness(pOutDhKey->raw, bufSecret);
780
781 } while (false);
782 return ret;
783}
784
785/************************************************************************************
786 * \brief Generates a new ECDH P256 Private/Public key pair
787 *
788 * \return gSecSuccess_c or error
789 *
790 ************************************************************************************/
791secResultType_t ECDH_P256_GenerateKeysSeg(computeDhKeyParam_t *pDhKeyData)
792{
793 secResultType_t res = gSecBadArgument_c;
794 if (pDhKeyData != NULL)
795 {
796 res = ECDH_P256_GenerateKeys(&pDhKeyData->outPoint, &pDhKeyData->privateKey);
797 }
798 return res;
799}
800
801/************************************************************************************
802 * \brief Generates a new ECDH P256 Private/Public key pair
803 *
804 * \return gSecSuccess_c or error
805 *
806 ************************************************************************************/
807secResultType_t ECDH_P256_GenerateKeys(ecdhPublicKey_t *pOutPublicKey, ecdhPrivateKey_t *pOutPrivateKey)
808{
809 secResultType_t ret = gSecError_c;
810 psa_status_t st = PSA_SUCCESS;
811 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
812 psa_key_id_t key = 0U;
813 size_t output_len = 0U;
814 uint8_t bufPub[sizeof(ecdhPublicKey_t) + 1]; /* +1 for point format byte*/
815
816 do
817 {
818 if ((pOutPublicKey == NULL) || (pOutPrivateKey == NULL))
819 {
820 ret = gSecBadArgument_c;
821 break;
822 }
823 /* Check if there's an existing key pair and destroy it if present */
824 if (psa_pECPKeyPair != NULL)
825 {
826 /* Once the key oject gets destroyed context is not ready anymore */
827 st = psa_destroy_key(psa_pECPKeyPair->OwnKey);
828 RAISE_ERROR(st, PSA_SUCCESS)
829 FLib_MemSet(psa_pECPKeyPair, 0U, sizeof(psa_ecp256_context_t));
830 psa_pECPKeyPair = NULL;
831 }
832
833 /* psa_g_ECP_KeyPair.keyId = KEY_ID_BLE0; */
834
835 /* Set the global key pair context */
836 psa_pECPKeyPair = &psa_g_ECP_KeyPair;
837
838 /* Configure key attributes for ECC P-256 key pair generation */
839 psa_set_key_bits(&attributes, 256);
840 psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
841 psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DERIVE | PSA_KEY_USAGE_EXPORT);
842 psa_set_key_lifetime(&attributes, PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(
843 PSA_KEY_LIFETIME_VOLATILE, get_most_secure_key_location()));
844 psa_set_key_algorithm(&attributes, PSA_ALG_ECDH);
845
846 /* Generate the ECC P-256 key pair */
847 st = psa_generate_key(&attributes, &key);
848 RAISE_ERROR(st, PSA_SUCCESS);
849
850 /* Export the public key from the generated key pair */
851 st = psa_export_public_key(key, bufPub, sizeof(ecdhPublicKey_t) + 1, &output_len);
852 RAISE_ERROR(st, PSA_SUCCESS);
853
854 /* Store the key ID in the global context */
855 psa_pECPKeyPair->OwnKey = key;
856
857 /* Convert public key from big-endian to little-endian format and store in output */
858 ECP256_PointLoad(pOutPublicKey, bufPub, true);
859
860 ret = gSecSuccess_c;
861 } while (false);
862 return ret;
863}
864
865/************************************************************************************
866 * \brief Generates a public key from a scalar given as input
867 *
868 * This function performs the multiplication of the scalar by the EC P 256 G point.
869 * The resulting point is the public key corresponding to the private key constituted by the scalar.
870 * This calculation is also involved in the compute L stage in the SPAKE2+ where the W1 argument
871 * plays the role of the private key argument after modular reduction.
872 * PSA does not support scalar multiplication via ele200 in hardware so this function uses software
873 * implementation.
874 *
875 * \return gSecEcp256Success_c or error
876 *
877 ************************************************************************************/
878secEcp256Status_t ECP256_GeneratePublicKey(uint8_t *pOutPublicKey,
879 const uint8_t *pInPrivateKey,
880 void *pMultiplicationBuffer)
881{
882 secEcp256Status_t ret = gSecEcp256BadParameters_c;
883 if ((pOutPublicKey != NULL) && (pInPrivateKey != NULL))
884 {
885#if !(defined gSecLibUseDspExtension_d && (gSecLibUseDspExtension_d != 0))
886 if (pMultiplicationBuffer != NULL)
887 {
888 big_int256_t privKey;
889 ecp256Point_t out;
890 FLib_MemCpyReverseOrder((uint8_t *)&privKey, pInPrivateKey, sizeof(big_int256_t));
891 ret = ECP256_GeneratePublicKeySeg(&out.raw[0], (uint8_t *)&privKey, pMultiplicationBuffer);
892 ECP256_PointCopy_and_change_endianness((uint8_t *)pOutPublicKey, &out.raw[0]);
893 }
894#else
895 NOT_USED(pMultiplicationBuffer);
896 ret = ECP256_GeneratePublicKeyUltraFast(pOutPublicKey, pInPrivateKey);
897#endif
898 }
899 return ret;
900}
901
902/************************************************************************************
903 * \brief Function used to create the mac key and LTK using Bluetooth F5 algorithm.
904 * Less secure version not using secure bus.
905 *
906 * \param [out] pMacKey 128 bit MacKey output location (pointer)
907 * \param [out] pLtk 128 bit LTK output location (pointer)
908 * \param [in] pW 256 bit W (pointer) (DHKey)
909 * \param [in] pN1 128 bit N1 (pointer) (Na)
910 * \param [in] pN2 128 bit N2 (pointer) (Nb)
911 * \param [in] a1at 8 bit A1 address type, 0 = Public, 1 = Random
912 * \param [in] pA1 48 bit A1 (pointer) (A)
913 * \param [in] a2at 8 bit A2 address type, 0 = Public, 1 = Random
914 * \param [in] pA2 48 bit A2 (pointer) (B)
915 *
916 * \retval gSecSuccess_c operation succeeded
917 * \retval gSecError_c operation failed
918 *
919 ************************************************************************************/
920secResultType_t SecLib_GenerateBluetoothF5Keys(uint8_t *pMacKey,
921 uint8_t *pLtk,
922 const uint8_t *pW,
923 const uint8_t *pN1,
924 const uint8_t *pN2,
925 const uint8_t a1at,
926 const uint8_t *pA1,
927 const uint8_t a2at,
928 const uint8_t *pA2)
929{
930 secResultType_t result = gSecError_c;
931 const uint8_t f5KeyId[4] = {0x62, 0x74, 0x6c, 0x65}; /*!< Big Endian, "btle" */
932 uint8_t f5CmacBuffer[1 + 4 + 16 + 16 + 7 + 7 + 2];
933 /* Counter[1] || keyId[4] || N1[16] || N2[16] || A1[7] || A2[7] || Length[2] = 53 */
934
935 uint8_t f5T[16] = {0};
936 const uint8_t f5Salt[16] = {0x6C, 0x88, 0x83, 0x91, 0xAA, 0xF5, 0xA5, 0x38,
937 0x60, 0x37, 0x0B, 0xDB, 0x5A, 0x60, 0x83, 0xBE}; /*!< Big endian */
938
939 do
940 {
941 uint8_t tempOut[16] = {0u};
942
943 /*! Check for NULL output pointers and return with proper status if this is the case. */
944 if ((NULL == pMacKey) || (NULL == pLtk) || (NULL == pN1) || (NULL == pN2) || (NULL == pA1) || (NULL == pA2))
945 {
946 result = gSecBadArgument_c;
947 break;
948 }
949
950 /*! Compute the f5 function key T using the predefined salt as key for AES-128-CAMC */
951 result = SecLib_AES_128_CMAC_LsbFirstInput((const uint8_t *)pW, 32, (const uint8_t *)f5Salt, f5T);
952 if (result != gSecSuccess_c)
953 {
954 break;
955 }
956
957 /*! Build the most significant part of the f5 input data to compute the MacKey */
958 f5CmacBuffer[0] = 0; /* Counter = 0 */
959 FLib_MemCpy(&f5CmacBuffer[1], (const uint8_t *)f5KeyId, 4);
960 FLib_MemCpyReverseOrder(&f5CmacBuffer[5], (const uint8_t *)pN1, 16);
961 FLib_MemCpyReverseOrder(&f5CmacBuffer[21], (const uint8_t *)pN2, 16);
962 f5CmacBuffer[37] = 0x01U & a1at;
963 FLib_MemCpyReverseOrder(&f5CmacBuffer[38], (const uint8_t *)pA1, 6);
964 f5CmacBuffer[44] = 0x01U & a2at;
965 FLib_MemCpyReverseOrder(&f5CmacBuffer[45], (const uint8_t *)pA2, 6);
966 f5CmacBuffer[51] = 0x01; /* Length msB big endian = 0x01, Length = 256 */
967 f5CmacBuffer[52] = 0x00; /* Length lsB big endian = 0x00, Length = 256 */
968
969 /*! Compute the MacKey into the temporary buffer. */
970 result = SecLib_AES_128_CMAC(f5CmacBuffer, sizeof(f5CmacBuffer), f5T, tempOut);
971 if (result != gSecSuccess_c)
972 {
973 break;
974 }
975 /*! Copy the MacKey to the output location
976 * in reverse order. The CMAC result is generated MSB first. */
977 FLib_MemCpyReverseOrder(pMacKey, (const uint8_t *)tempOut, 16);
978
979 /*! Build the least significant part of the f5 input data to compute the MacKey.
980 * It is identical to the most significant part with the exception of the counter. */
981 f5CmacBuffer[0] = 1; /* Counter = 1 */
982
983 /*! Compute the LTK into the temporary buffer. */
984 result = SecLib_AES_128_CMAC(f5CmacBuffer, sizeof(f5CmacBuffer), f5T, tempOut);
985 if (result != gSecSuccess_c)
986 {
987 break;
988 }
989 /*! Copy the LTK to the output location
990 * in reverse order. The CMAC result is generated MSB first. */
991 FLib_MemCpyReverseOrder(pLtk, (const uint8_t *)tempOut, 16);
992
993 result = gSecSuccess_c;
994
995 } while (false);
996
997 return result;
998}
999
1000/*! *********************************************************************************
1001 * \brief This function implements the SMP ah cryptographic toolbox function which
1002 calculates the hash part of a Resolvable Private Address.
1003 * The key is kept in plaintext.
1004 *
1005 * \param[out] pHash Pointer where the 24 bit hash of a Resolvable Private Address value
1006 * will be written.
1007 *
1008 * \param[in] pKey Pointer to the 128 bit key.
1009 *
1010 * \param[in] pR Pointer to the 24 bit random value (Prand) of a Resolvable private Address.
1011 * The most significant bits of this field must be 0b01 for Resolvable Private
1012 * Addresses.
1013 *
1014 * \retval gSecSuccess_c All operations were successful.
1015 * \retval gSecError_c The call failed.
1016 *
1017 ********************************************************************************** */
1018secResultType_t SecLib_VerifyBluetoothAh(uint8_t *pHash, const uint8_t *pKey, const uint8_t *pR)
1019{
1020 secResultType_t result = gSecError_c;
1021 uint8_t tempAddrPart[16] = {0u};
1022 uint8_t tempOutHash[16] = {0u};
1023 uint8_t tempKey[16] = {0u};
1024 do
1025 {
1026 /*! Check for NULL output pointers and return with proper status if this is the case. */
1027 if ((NULL == pHash) || (NULL == pKey) || (NULL == pR))
1028 {
1029 result = gSecBadArgument_c;
1030 break;
1031 }
1032 /* Initialize the r' value in the temporary location. 3 bytes of ramdom value.
1033 * Initialize it reversed for AES.
1034 */
1035 for (int i = 0; i < 3; i++)
1036 {
1037 tempAddrPart[15 - i] = pR[i];
1038 }
1039 /* Regular operation with plaintext key */
1040 /*! Reverse the Key and place it in a temporary location. */
1041 FLib_MemCpyReverseOrder(tempKey, (const uint8_t *)pKey, 16);
1042
1043 /*! Compute the hash. */
1044 AES_128_Encrypt(tempAddrPart, tempKey, tempOutHash);
1045
1046 /*! Copy the relevant bytes to the output. */
1047 pHash[0] = tempOutHash[15];
1048 pHash[1] = tempOutHash[14];
1049 pHash[2] = tempOutHash[13];
1050
1051 result = gSecSuccess_c;
1052
1053 } while (false);
1054 return result;
1055}
1056
1057void ECDH_P256_FreeDhKeyDataSecure(computeDhKeyParam_t *pDhKeyData)
1058{
1059 NOT_USED(pDhKeyData);
1060}
1061
1062secResultType_t SecLib_DeriveBluetoothSKDSecure(const uint8_t *pInSKD,
1063 const uint8_t *pLtkBlob,
1064 bool_t bOpenKey,
1065 uint8_t *pOutSKD)
1066{
1067 NOT_USED(pInSKD);
1068 NOT_USED(pLtkBlob);
1069 NOT_USED(bOpenKey);
1070 NOT_USED(pOutSKD);
1071
1072 return gSecError_c;
1073}
1074
1075secResultType_t SecLib_ObfuscateKeySecure(const uint8_t *pKey, uint8_t *pBlob, const uint8_t blobType)
1076{
1077 NOT_USED(pKey);
1078 NOT_USED(pBlob);
1079 NOT_USED(blobType);
1080 return gSecError_c;
1081}
1082
1083secResultType_t SecLib_DeobfuscateKeySecure(const uint8_t *pBlob, uint8_t *pKey)
1084{
1085 NOT_USED(pBlob);
1086 NOT_USED(pKey);
1087 return gSecError_c;
1088}
1089
1090secResultType_t ECDH_P256_ComputeA2BKeySecure(const ecdhPublicKey_t *pInPeerPublicKey, ecdhDhKey_t *pOutE2EKey)
1091{
1092 NOT_USED(pInPeerPublicKey);
1093 NOT_USED(pOutE2EKey);
1094 return gSecError_c;
1095}
1096
1097secResultType_t ECDH_P256_FreeE2EKeyDataSecure(ecdhDhKey_t *pE2EKeyData)
1098{
1099 NOT_USED(pE2EKeyData);
1100 return gSecError_c;
1101}
1102
1103secResultType_t SecLib_ExportA2BBlobSecure(const void *pKey, const secInputKeyType_t keyType, uint8_t *pOutKey)
1104{
1105 NOT_USED(pKey);
1106 NOT_USED(keyType);
1107 NOT_USED(pOutKey);
1108 return gSecError_c;
1109}
1110
1111secResultType_t SecLib_ImportA2BBlobSecure(const uint8_t *pKey, const secInputKeyType_t keyType, uint8_t *pOutKey)
1112{
1113 NOT_USED(pKey);
1114 NOT_USED(keyType);
1115 NOT_USED(pOutKey);
1116 return gSecError_c;
1117}
1118
1119secResultType_t SecLib_GenerateBluetoothF5KeysSecure(uint8_t *pMacKey,
1120 uint8_t *pLtk,
1121 const uint8_t *pW,
1122 const uint8_t *pN1,
1123 const uint8_t *pN2,
1124 const uint8_t a1at,
1125 const uint8_t *pA1,
1126 const uint8_t a2at,
1127 const uint8_t *pA2)
1128{
1129 NOT_USED(pMacKey);
1130 NOT_USED(pLtk);
1131 NOT_USED(pW);
1132 NOT_USED(pN1);
1133 NOT_USED(pN2);
1134 NOT_USED(a1at);
1135 NOT_USED(pA1);
1136 NOT_USED(a2at);
1137 NOT_USED(pA2);
1138 return gSecError_c;
1139}
1140
1141secResultType_t SecLib_VerifyBluetoothAhSecure(uint8_t *pHash, const uint8_t *pKey, const uint8_t *pR)
1142{
1143 NOT_USED(pHash);
1144 NOT_USED(pKey);
1145 NOT_USED(pR);
1146 return gSecError_c;
1147}
1148
1149secResultType_t SecLib_GenerateBluetoothEIRKBlobSecure(const void *pIRK,
1150 const bool_t blobInput,
1151 const bool_t generateDKeyIRK,
1152 uint8_t *pOutEIRKblob)
1153{
1154 NOT_USED(pIRK);
1155 NOT_USED(blobInput);
1156 NOT_USED(generateDKeyIRK);
1157 NOT_USED(pOutEIRKblob);
1158 return gSecError_c;
1159}
1160
1161secResultType_t SecLib_GenerateSymmetricKey(const uint32_t keySize, const bool_t blobOutput, void *pOut)
1162{
1163 NOT_USED(keySize);
1164 NOT_USED(blobOutput);
1165 NOT_USED(pOut);
1166 return gSecError_c;
1167}