/**
*   @file    hse_config.c
*
*   @brief   Example of HSE configuration
*   @details Example of services used for configuring HSE persistent attributes and key catalogs.
*
*   @addtogroup [HSE_CONFIG]
*   @{
*/

/*=============================================================================
*
*   Copyright 2020-2021 NXP.
*
*   This software is owned or controlled by NXP and may only be used strictly in accordance with
*   the applicable license terms. By expressly accepting such terms or by downloading, installing,
*   activating and/or otherwise using the software, you are agreeing that you have read, and that
*   you agree to comply with and are bound by, such license terms. If you do not agree to
*   be bound by the applicable license terms, then you may not retain, install, activate or
*   otherwise use the software.
=============================================================================*/

#ifdef __cplusplus
extern "C"
{
#endif

/*=============================================================================
*                                        INCLUDE FILES
* 1) system and project includes
* 2) needed interfaces from external units
* 3) internal and external interfaces from this unit
=============================================================================*/
#include "demo_app_services.h"
#include "global_variables.h"
#include "hse_host_attrs.h"
#include "hse_host_boot.h"
#include "hse_host_format_key_catalogs.h"
#include "hse_host_import_key.h"
#include "hse_host_mac.h"
//#include "hse_mu.h"
#include "hse_srv_attr.h"
#include "hse_host.h"
#include "hse_host_ecc.h"
#include "hse_host_sign.h"
#include "hse_default_config.h"
#include <string.h>

//#include "global_defs.h"

#if !defined(ARRAY_SIZE)
    #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
#endif

/*=============================================================================
 *                          LOCAL TYPEDEFS (STRUCTURES, UNIONS, ENUMS)
 * ==========================================================================*/

/*=============================================================================
 *                                       LOCAL MACROS
 * ==========================================================================*/

/*=============================================================================
 *                                      LOCAL CONSTANTS
 * ==========================================================================*/

/*============================================================================
 *                                      LOCAL VARIABLES
 * =========================================================================*/

/*=============================================================================
 *                                      GLOBAL CONSTANTS
 * ==========================================================================*/

/*=============================================================================
 *                                      GLOBAL VARIABLES
 * ==========================================================================*/

#define CRYPTO_START_SEC_VAR_CLEARED_UNSPECIFIED_NO_CACHEABLE
#include "Crypto_MemMap.h"

uint8_t ED25519PubKey[ ( HSE_KEY521_BITS / 8 ) + 1 ] = {0};

#define CRYPTO_STOP_SEC_VAR_CLEARED_UNSPECIFIED_NO_CACHEABLE
#include "Crypto_MemMap.h"

/*=============================================================================
 *                                   LOCAL FUNCTION PROTOTYPES
 * ==========================================================================*/
static hseSrvResponse_t HSE_ConfigKeyCatalogs( void );
/*=============================================================================
 *                                       LOCAL FUNCTIONS
 * ==========================================================================*/

/*
    Function: HSE_ConfigKeyCatalogs
    @brief    Format key catalogs
    @detailed Example of key catalog for SHE and SB format HSE service
              which defines the layout of the Key store memory space:
              (number of slots, number of keys/slot, key types,
              usage/MU and ownership).
              Key catalogs format will be part of the SYS_IMG
              that provides persistency of HSE configuration
 */
static hseSrvResponse_t HSE_ConfigKeyCatalogs( void )
{
    hseSrvResponse_t srvResponse;

    //Format HSE key catalogs
    srvResponse = FormatKeyCatalogs_W();
    return srvResponse;
}

/*
    Function: HSE_InstallNvmKeys
    @brief    NVM keys installation example
    @detailed Example of key catalog format HSE service which defines the
              layout of the Key store memory space:
              (number of slots, number of keys/slot, key types, usage/MU
              and ownership).NVM keys will be part of the SYS_IMG.
 */
static hseSrvResponse_t HSE_InstallNvmKeys(void)
{
    hseSrvResponse_t srvResponse;

    /* Import Authorization key */
    srvResponse = ImportPlainSymKeyReq
            (
                    NVM_AES128_AUTHORIZATION_KEY,
                    HSE_KEY_TYPE_AES,
                    (
                            HSE_KF_USAGE_AUTHORIZATION  |
                            HSE_KF_USAGE_VERIFY
                    ),
                    ARRAY_SIZE(gAES128AuthorizationKey),
                    gAES128AuthorizationKey
            );
    ASSERT( HSE_SRV_RSP_OK == srvResponse);
    return srvResponse;
}

/*=============================================================================
 *                                       GLOBAL FUNCTIONS
 * ==========================================================================*/
/******************************************************************************
 * Function:    HSE_Config
 * Description: Configure NVM attributes, key catalogs and install NVM keys
 *****************************************************************************/
hseSrvResponse_t HSE_Config(void)
{
    hseSrvResponse_t srvResponse = HSE_SRV_RSP_GENERAL_ERROR;

    /* check if the user have SU rights or not, if not then request for it */
    srvResponse = Sys_Auth();
    ASSERT(HSE_SRV_RSP_OK == srvResponse);

    /* format keys */
    srvResponse = HSE_ConfigKeyCatalogs();
    ASSERT(HSE_SRV_RSP_OK == srvResponse);

    /* import keys */
//    srvResponse = HSE_InstallNvmKeys();
//    ASSERT(HSE_SRV_RSP_OK == srvResponse);

    return srvResponse;
}

/******************************************************************************
 * Function:    Generic_ImportKeys
 * Description: Import all NVM keys required for crypto services and secure boot
 *****************************************************************************/
hseSrvResponse_t Generic_ImportKeys(void)
{
    hseSrvResponse_t srvResponse = HSE_SRV_RSP_GENERAL_ERROR;

    /* load AES keys for FAST CMAC operation*/
    srvResponse = LoadAesKey(NVM_AES256_KEY2, aesEcbKeyLength, aesEcbKey);
    if(HSE_SRV_RSP_OK != srvResponse)
            goto exit;
    /* import keys for ECC operation before calling HSE_Ecdsa_Example fn*/
    srvResponse = ImportEccKeyReq(
            NVM_ECC_KEY_HANDLE,
            HSE_KEY_TYPE_ECC_PAIR,
            (HSE_KF_USAGE_SIGN | HSE_KF_USAGE_VERIFY ),
            HSE_EC_SEC_SECP256R1,
            KeyBitLen(HSE_EC_SEC_SECP256R1),
            eccP256PubKey,
            eccP256PrivKey
            );
    ASSERT(HSE_SRV_RSP_OK == srvResponse );
    if(HSE_SRV_RSP_OK != srvResponse)
        goto exit;

    srvResponse = ImportEccKeyReq(
            NVM_ECC_KEY_HANDLE_PUBLIC,
            HSE_KEY_TYPE_ECC_PUB,
            (HSE_KF_USAGE_VERIFY ),
            HSE_EC_SEC_SECP256R1,
            KeyBitLen(HSE_EC_SEC_SECP256R1),
            eccP256PubKey,
            NULL
            );
    ASSERT(HSE_SRV_RSP_OK == srvResponse );
    if(HSE_SRV_RSP_OK != srvResponse)
        goto exit;

#if 1

    /*Generate an ECC key pair */
    srvResponse = GenerateEccKeyReq(
                NVM_ECC_KEY_HANDLE_PAIR_EDDSA,
                HSE_KEY_TYPE_ECC_PAIR ,
                (HSE_KF_USAGE_SIGN | HSE_KF_USAGE_VERIFY ) ,
                HSE_EC_25519_ED25519 ,
                KeyBitLen(HSE_EC_25519_ED25519) ,
                ED25519PubKey
                );
    ASSERT(HSE_SRV_RSP_OK == srvResponse );
    if(HSE_SRV_RSP_OK != srvResponse)
        goto exit;

    srvResponse = ImportEccKeyReq(
            NVM_ECC_KEY_HANDLE_PUBLIC_1,
            HSE_KEY_TYPE_ECC_PUB,
            HSE_KF_USAGE_VERIFY,
            HSE_EC_25519_ED25519,
            KeyBitLen(HSE_EC_25519_ED25519),
            ED25519PubKey,
            NULL
            );
    ASSERT(HSE_SRV_RSP_OK == srvResponse );
    if(HSE_SRV_RSP_OK != srvResponse)
        goto exit;
#endif

    /* import session keys before calling HSE_SessionKeys_Example fn */
    /*Generate an ECC key pair in RAM (ephemeral ECDH)*/
    srvResponse = GenerateEccKey(
                RAM_ECC_PAIR_KEY_HANDLE,
                HSE_EC_SEC_SECP256R1,
                HSE_KF_USAGE_EXCHANGE);
    ASSERT(HSE_SRV_RSP_OK == srvResponse );
    if(HSE_SRV_RSP_OK != srvResponse)
        goto exit;

    /*Import the peer public key*/
    srvResponse = ImportEccKeyReq(
            RAM_ECC_PUB_KEY_HANDLE, HSE_KEY_TYPE_ECC_PUB,
            HSE_KF_USAGE_EXCHANGE, HSE_EC_SEC_SECP256R1,
            KeyBitLen(HSE_EC_SEC_SECP256R1), eccP256PubKey, NULL);
    ASSERT(HSE_SRV_RSP_OK == srvResponse );
    if(HSE_SRV_RSP_OK != srvResponse)
        goto exit;

    /*Compute DH Shared Secret (ECDH)*/
    srvResponse = DHSharedSecretCompute(
            RAM_ECC_PUB_KEY_HANDLE,
            RAM_ECC_PAIR_KEY_HANDLE,
            DH_SHARED_SECRET_HANDLE);

    if(HSE_SRV_RSP_OK != srvResponse)
        goto exit;

    /* import keys before calling HSE_SysAuthorization_Example fn */
    srvResponse = SetCustAuthorizationKey();
    ASSERT(HSE_SRV_RSP_OK == srvResponse );
    if(HSE_SRV_RSP_OK != srvResponse)
            goto exit;

	/* import rsa key for secure boot */
    srvResponse = ImportPlainRsaKeyReq(
            NVM_RSA2048_PUB_CUSTAUTH_HANDLE1,
            HSE_KEY_TYPE_RSA_PUB,
            (HSE_KF_USAGE_VERIFY),
            (HOST_ADDR)rsa2048CustAuthKeyModulus,
            rsa2048CustAuthKeyModulusLength,
            (HOST_ADDR)rsa2048CustAuthKeyPubExp,
            rsa2048CustAuthKeyPubExpLength,
            (HOST_ADDR) NULL,
             0UL
            );
    ASSERT(HSE_SRV_RSP_OK == srvResponse );
    if(HSE_SRV_RSP_OK != srvResponse)
            goto exit;
    /* Set a copy of authorization key for signature generation using HSE
     * (over challenge) Intended use case - Sign challenge via external means
     */
    srvResponse = ImportPlainRsaKeyReq(
            NVM_RSA2048_PAIR_CUSTAUTH_HANDLE1,
            HSE_KEY_TYPE_RSA_PAIR,
            (HSE_KF_USAGE_ENCRYPT|HSE_KF_USAGE_DECRYPT|HSE_KF_USAGE_SIGN|HSE_KF_USAGE_VERIFY),
            (HOST_ADDR)rsa2048CustAuthKeyModulus,
            rsa2048CustAuthKeyModulusLength,
            (HOST_ADDR)rsa2048CustAuthKeyPubExp,
            rsa2048CustAuthKeyPubExpLength,
            (HOST_ADDR)rsa2048CustAuthKeyPrivExp,
            rsa2048CustAuthKeyPrivExpLength
            );
    ASSERT(HSE_SRV_RSP_OK == srvResponse );
    if(HSE_SRV_RSP_OK != srvResponse)
            goto exit;
	/* import rsa key for secure boot */

    /* import keys before calling HSE_UpdateNvmKey_Example fn */
    srvResponse = ImportPlainSymKeyReq(NVM_HMAC_KEY0, HSE_KEY_TYPE_HMAC,
            HSE_KF_USAGE_SIGN|HSE_KF_USAGE_VERIFY, hmacKeyInitialLength, hmacKeyInitial);
    ASSERT(HSE_SRV_RSP_OK == srvResponse );
    if(HSE_SRV_RSP_OK != srvResponse)
            goto exit;

    srvResponse = ImportPlainSymKeyReq(NVM_HMAC_KEY1, HSE_KEY_TYPE_HMAC,
            HSE_KF_USAGE_VERIFY, hmacKeyInitialLength, hmacKeyInitial);
    ASSERT(HSE_SRV_RSP_OK == srvResponse );
    if(HSE_SRV_RSP_OK != srvResponse)
            goto exit;

    srvResponse = ImportPlainSymKeyReq(
            RAM_AES128_KEY1,
            HSE_KEY_TYPE_AES,
            HSE_KF_USAGE_SIGN,
            gAESProvisionKeyLength,
            gAES128ProvisionKey
            );
    ASSERT(HSE_SRV_RSP_OK == srvResponse );
    if(HSE_SRV_RSP_OK != srvResponse)
        goto exit;
    /* load keys for Advanced secure boot */
    srvResponse = ImportPlainSymKeyReqMuChannel(
            MU0,
            1U,
            NVM_AES128_PROVISION_KEY,
            HSE_KEY_TYPE_AES,
            (HSE_KF_USAGE_SIGN|HSE_KF_USAGE_VERIFY),
            0U,
            aesEcbKeyLength,
            aesEcbKey,
            TRUE
            );
    ASSERT(HSE_SRV_RSP_OK == srvResponse );
    if(HSE_SRV_RSP_OK != srvResponse)
            goto exit;

    /*Import key linked with SMR#0*/
    srvResponse = ImportPlainSymKeyReqMuChannel(
            MU0,
            1U,
            NVM_AES128_BOOT_KEY,
            HSE_KEY_TYPE_AES,
            ( HSE_KF_USAGE_VERIFY ),
            0U,
            aesEcbKeyLength,
            aesEcbKey,
            TRUE
            );
    ASSERT(HSE_SRV_RSP_OK == srvResponse );
    if(HSE_SRV_RSP_OK != srvResponse)
            goto exit;

    /* load keys for SHE secure boot */
    srvResponse = LoadBootMacKey();
    ASSERT(HSE_SRV_RSP_OK == srvResponse );
    if(HSE_SRV_RSP_OK != srvResponse)
            goto exit;
exit:
    return srvResponse;
}

/******************************************************************************
 * Function:    HSE_EraseKeys
 * Description: Erase NVM attributes, key catalogs and NVM keys
 *****************************************************************************/
hseSrvResponse_t HSE_EraseKeys(void)
{
    hseSrvResponse_t srvResponse = HSE_SRV_RSP_GENERAL_ERROR;
    hseSrvDescriptor_t *pHseSrvDesc = &gHseSrvDesc[0U][1U];

    memset(pHseSrvDesc, 0, sizeof(hseSrvDescriptor_t));

    // re-format the NVM and RAM catalogs
    pHseSrvDesc->srvId = HSE_SRV_ID_ERASE_HSE_NVM_DATA;
    srvResponse = HSE_Send(0U, 1U, gSyncTxOption, pHseSrvDesc);

    ASSERT(HSE_SRV_RSP_OK == srvResponse);
    return srvResponse;
}

/******************************************************************************
 * Function:    Sys_Auth
 * Description: Grant Super user rights to user
 *****************************************************************************/
hseSrvResponse_t Sys_Auth( void )
{
    hseSrvResponse_t srvResponse = HSE_SRV_RSP_GENERAL_ERROR;
    /* read LC first */
    if( HSE_STATUS_CUST_SUPER_USER & HSE_GetStatus(MU0) )
    {
        /* user already have SU rights */
        srvResponse = HSE_SRV_RSP_OK;
        goto exit;
    }
    else
    {
        srvResponse = Grant_SuperUser_Rights();
    }
exit:
    return srvResponse;
}
#ifdef __cplusplus
}
#endif

/** @} */
