MCUXpresso SDK Documentation

middleware/wireless/framework/services/SecLib_RNG/SecLib_sss.c

middleware/wireless/framework/services/SecLib_RNG/SecLib_sss.c#

   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, &ltkBlobByteLen,
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}