/* renesas_common.c
 *
 * Copyright (C) 2006-2026 wolfSSL Inc.
 *
 * This file is part of wolfSSL.
 *
 * wolfSSL is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * wolfSSL is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
 */

#ifdef HAVE_CONFIG_H
    #include <config.h>
#endif

#include <wolfssl/wolfcrypt/settings.h>

#if defined(WOLFSSL_RENESAS_FSPSM_TLS) || \
    defined(WOLFSSL_RENESAS_FSPSM_CRYPTONLY) || \
    defined(WOLFSSL_RENESAS_TSIP_TLS) || \
    defined(WOLFSSL_RENESAS_TSIP_CRYPTONLY)

#if defined(WOLFSSL_RENESAS_FSPSM_TLS) || \
    defined(WOLFSSL_RENESAS_FSPSM_CRYPTONLY)

    #include <wolfssl/wolfcrypt/port/Renesas/renesas_fspsm_internal.h>
    #define cmn_hw_lock    wc_fspsm_hw_lock
    #define cmn_hw_unlock  wc_fspsm_hw_unlock

#elif defined(WOLFSSL_RENESAS_TSIP_TLS) || \
      defined(WOLFSSL_RENESAS_TSIP_CRYPTONLY)

    #include <wolfssl/wolfcrypt/port/Renesas/renesas_tsip_internal.h>
    #define cmn_hw_lock    tsip_hw_lock
    #define cmn_hw_unlock  tsip_hw_unlock

    #define FSPSM_ST            TsipUserCtx
    #define FSPSM_ST_Internal   TsipUserCtx_Internal

#endif

#include <wolfssl/wolfcrypt/wc_port.h>
#include <wolfssl/wolfcrypt/types.h>
#include <wolfssl/wolfcrypt/asn.h>
#ifdef NO_INLINE
    #include <wolfssl/wolfcrypt/misc.h>
#else
    #define WOLFSSL_MISC_INCLUDED
    #include <wolfcrypt/src/misc.c>
#endif
#include <wolfssl/internal.h>
#include <wolfssl/error-ssl.h>
#include <wolfssl/wolfcrypt/error-crypt.h>
#include <wolfssl/wolfcrypt/logging.h>
#include <wolfssl/wolfcrypt/port/Renesas/renesas_cmn.h>

#define INITIAL_DEVID 7890

uint32_t   g_CAscm_Idx = (uint32_t)-1; /* index of CM table    */
static int gdevId = INITIAL_DEVID;     /* initial dev Id for Crypt Callback */

#ifdef WOLF_CRYPTO_CB

#define     MAX_FSPSM_CBINDEX 5
FSPSM_ST    *gCbCtx[MAX_FSPSM_CBINDEX];

#include <wolfssl/wolfcrypt/cryptocb.h>


WOLFSSL_LOCAL int Renesas_cmn_Cleanup(struct WOLFSSL* ssl)
{
    int ret = 0;
    WOLFSSL_ENTER("Renesas_cmn_Cleanup");
    (void) ssl;

#if defined(WOLFSSL_RENESAS_TSIP_TLS)
    ret = tsip_TlsCleanup(ssl);
#elif defined(WOLFSSL_RENESAS_FSPSM_TLS)
    ret = wc_fspsm_TlsCleanup(ssl);
#endif

    WOLFSSL_LEAVE("Renesas_cmn_Cleanup", ret);
    return ret;
}

#if defined(WOLFSSL_RENESAS_TSIP_TLS)
WOLFSSL_LOCAL int Renesas_cmn_RsaSignCb(WOLFSSL* ssl,
                                const unsigned char* in, unsigned int inSz,
                                unsigned char* out, word32* outSz,
                                const unsigned char* keyDer, unsigned int keySz,
                                void* ctx)
{
    int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE);
    WOLFSSL_ENTER("Renesas_cmn_RsaSignCb");

    /* This is just a stub function that provides no logic */

    WOLFSSL_LEAVE("Renesas_cmn_RsaSignCb", ret);
    return ret;
}
/* This function is a callback passed to wolfSSL_CTX_SetRsaSignCheckCb.
 * It tries to verify the signature passed to it by decrypting with a public
 * key.
 * returns 0 on success, CRYPTOCB_UNAVAILABLE when public key is not set.
 */
WOLFSSL_LOCAL int Renesas_cmn_RsaSignCheckCb(WOLFSSL* ssl,
                                unsigned char* sig, unsigned int sigSz,
                                unsigned char** out,
                                const unsigned char* keyDer, unsigned int keySz,
                                void* ctx)
{
    int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE);
    WOLFSSL_ENTER("Renesas_cmn_RsaSignCheckCb");

#if defined(WOLFSSL_RENESAS_TSIP)
    ret = tsip_VerifyRsaPkcsCb(ssl, sig, sigSz, out, keyDer, keySz, ctx);
#endif /* WOLFSSL_RENESAS_TSIP */

    WOLFSSL_LEAVE("Renesas_cmn_RsaSignCheckCb", ret);
    return ret;
}

WOLFSSL_LOCAL int Renesas_cmn_EccSignCb(WOLFSSL* ssl,
                                const unsigned char* in, unsigned int inSz,
                                unsigned char* out, word32* outSz,
                                const unsigned char* keyDer, unsigned int keySz,
                                void* ctx)
{
    int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE);
    WOLFSSL_ENTER("Renesas_cmn_EccSignCb");

    /* This is just a stub function that provides no logic */

    WOLFSSL_LEAVE("Renesas_cmn_EccSignCb", ret);
    return ret;
}
#endif /* WOLFSSL_RENESAS_TSIP_TLS */

/* Renesas Security Library Common Callback
 * For Crypto Callbacks
 *
 * devIdArg device Id
 * info     pointer to wc_CryptInfo
 * ctx      Crypto Callback context
 * return  0 on success, otherwise MEMORY_E or BAD_FUNC_ARG on failure
 */
static int Renesas_cmn_CryptoDevCb(int devIdArg, wc_CryptoInfo* info, void* ctx)
{
    int ret = WC_NO_ERR_TRACE(NOT_COMPILED_IN); /* return this to bypass HW and use SW */

    WOLFSSL_ENTER("Renesas_cmn_CryptoDevCb");

#if defined(WOLFSSL_RENESAS_TSIP_TLS) || \
    defined(WOLFSSL_RENESAS_TSIP_CRYPTONLY)
    TsipUserCtx* cbInfo = (TsipUserCtx*)ctx;
#elif defined(WOLFSSL_RENESAS_FSPSM_TLS) || \
      defined(WOLFSSL_RENESAS_FSPSM_CRYPTONLY)
    FSPSM_ST* cbInfo = (FSPSM_ST*)ctx;
    (void)cbInfo;
#endif

    if (info == NULL || ctx == NULL)
        return BAD_FUNC_ARG;

#if defined(DEBUG_CRYPTOCB)
    wc_CryptoCb_InfoString(info);
#endif

#if defined(WOLFSSL_RENESAS_TSIP) || \
    defined(WOLFSSL_RENESAS_TSIP_CRYPTONLY)
    ret = CRYPTOCB_UNAVAILABLE;

    if (info->algo_type == WC_ALGO_TYPE_CIPHER) {
    #if !defined(NO_AES)
         ret = wc_tsip_AesCipher(devIdArg, info, ctx);
    #endif /* !NO_AES */
    }

    if (info->algo_type == WC_ALGO_TYPE_PK) {
    #if !defined(NO_RSA)
    #if defined(WOLFSSL_KEY_GEN) && defined(WOLFSSL_RENESAS_TSIP_CRYPTONLY)
        if (info->pk.type == WC_PK_TYPE_RSA_KEYGEN) {
            ret = wc_tsip_MakeRsaKey(info->pk.rsakg.size, (void*)ctx);
            if (ret == 0) {
                TsipUserCtx* tsipCtx = (TsipUserCtx*)ctx;
                RsaKey* key = info->pk.rsakg.key;
            #if (defined(TSIP_RSAES_1024) && TSIP_RSAES_1024 == 1) || \
                (defined(TSIP_RSASSA_1024) && TSIP_RSASSA_1024 == 1)
                if (info->pk.rsakg.size == 1024) {
                    /* export generated public key to the RsaKey structure */
                    ret = wc_RsaPublicKeyDecodeRaw(
                        tsipCtx->rsa1024pub_keyIdx->value.key_n,
                            R_TSIP_RSA_1024_KEY_N_LENGTH_BYTE_SIZE,
                        tsipCtx->rsa1024pub_keyIdx->value.key_e,
                            R_TSIP_RSA_1024_KEY_E_LENGTH_BYTE_SIZE,
                        key
                    );
                }
            #endif
            #if (defined(TSIP_RSAES_2048) && TSIP_RSAES_2048 == 1) || \
                (defined(TSIP_RSASSA_2048) && TSIP_RSASSA_2048 == 1)
                if (info->pk.rsakg.size == 2048) {
                    /* export generated public key to the RsaKey structure */
                    ret = wc_RsaPublicKeyDecodeRaw(
                        tsipCtx->rsa2048pub_keyIdx->value.key_n,
                            R_TSIP_RSA_2048_KEY_N_LENGTH_BYTE_SIZE,
                        tsipCtx->rsa2048pub_keyIdx->value.key_e,
                            R_TSIP_RSA_2048_KEY_E_LENGTH_BYTE_SIZE,
                        key
                    );
                }
            #endif
            }
        }
    #endif
        /* tsip only supports PKCSV15 padding scheme */
        if (info->pk.type == WC_PK_TYPE_RSA_PKCS) {
            RsaPadding* pad = info->pk.rsa.padding;
            if (pad && pad->pad_value == RSA_BLOCK_TYPE_1) {
                /* sign / verify */
                if (info->pk.rsa.type == RSA_PRIVATE_ENCRYPT ||
                    info->pk.rsa.type == RSA_PRIVATE_DECRYPT) {
                    ret = tsip_SignRsaPkcs(info, cbInfo);
                }
            #ifdef WOLFSSL_RENESAS_TSIP_CRYPTONLY
                else {
                    ret = wc_tsip_RsaVerifyPkcs(info, cbInfo);
                }
            #endif
            }
        #ifdef WOLFSSL_RENESAS_TSIP_CRYPTONLY
            else if (pad && pad->pad_value == RSA_BLOCK_TYPE_2) {
                /* encrypt/decrypt */
                ret = wc_tsip_RsaFunction(info, cbInfo);
            }
        #endif
        }
        if (info->pk.type == WC_PK_TYPE_RSA_GET_SIZE) {
            if (cbInfo->wrappedKeyType == TSIP_KEY_TYPE_RSA2048) {
                *info->pk.rsa_get_size.keySize = 256;
                ret = 0;
            }
        #ifdef WOLFSSL_RENESAS_TSIP_CRYPTONLY
            else if (cbInfo->wrappedKeyType == TSIP_KEY_TYPE_RSA1024) {
                *info->pk.rsa_get_size.keySize = 128;
                ret = 0;
            }
        #endif
        }
    #endif /* !NO_RSA */
    #if defined(HAVE_ECC)
        #if defined(WOLFSSL_RENESAS_TSIP_TLS)
        if (info->pk.type == WC_PK_TYPE_ECDSA_SIGN) {
            ret = tsip_SignEcdsa(info, cbInfo);
        }
        #endif
        #if defined(WOLFSSL_RENESAS_TSIP_CRYPTONLY)
        if (info->pk.type == WC_PK_TYPE_ECDSA_VERIFY) {
            ret = tsip_VerifyEcdsa(info, cbInfo);
        }
        #endif
    #endif /* HAVE_ECC */
    }

#elif (defined(WOLFSSL_RENESAS_FSPSM_TLS) || \
      defined(WOLFSSL_RENESAS_FSPSM_CRYPTONLY))\
    && !defined(NO_WOLFSSL_RENESAS_FSPSM_AES)

    if (info->algo_type == WC_ALGO_TYPE_CIPHER) {
    #if !defined(NO_AES)
         ret = wc_fspsm_AesCipher(devIdArg, info, ctx);
    #endif /* !NO_AES */
    }

#if !defined(NO_RSA) && defined(WOLFSSL_RENESAS_FSPSM_CRYPTONLY)
    else if (info->algo_type == WC_ALGO_TYPE_PK) {
        if (info->pk.type == WC_PK_TYPE_RSA_GET_SIZE) {
            if (cbInfo->keyflgs_crypt.bits.rsapri2048_installedkey_set ||
                cbInfo->keyflgs_crypt.bits.rsapub2048_installedkey_set )
            {
               *info->pk.rsa_get_size.keySize = 256;
               ret = 0;
            } else if (
                cbInfo->keyflgs_crypt.bits.rsapri1024_installedkey_set ||
                cbInfo->keyflgs_crypt.bits.rsapub1024_installedkey_set )
            {
                *info->pk.rsa_get_size.keySize = 128;
                ret = 0;
            }
        }
    #if defined(WOLFSSL_KEY_GEN)
        if (info->pk.type == WC_PK_TYPE_RSA_KEYGEN) {
            ret = wc_fspsm_MakeRsaKey(info->pk.rsakg.key,
                    info->pk.rsakg.size, (void*)ctx);
        }
    #endif
        if (info->pk.type == WC_PK_TYPE_RSA_PKCS) {
            /* to perform RSA on SCE, wrapped keys should be installed
             * in advance. SCE supports 1024 or 2048 bits key size.
             * otherwise, falls-through happens.
             */
            if (cbInfo->keyflgs_crypt.bits.rsapri2048_installedkey_set ||
                cbInfo->keyflgs_crypt.bits.rsapub2048_installedkey_set ||
                cbInfo->keyflgs_crypt.bits.rsapri1024_installedkey_set ||
                cbInfo->keyflgs_crypt.bits.rsapub1024_installedkey_set ) {

                if (info->pk.rsa.type == RSA_PRIVATE_DECRYPT ||
                    info->pk.rsa.type == RSA_PUBLIC_ENCRYPT  )
                    {
                        ret = wc_fspsm_RsaFunction(info->pk.rsa.in,
                                        info->pk.rsa.inLen,
                                        info->pk.rsa.out,
                                        info->pk.rsa.outLen,
                                        info->pk.rsa.type,
                                        info->pk.rsa.key,
                                        info->pk.rsa.rng);
                }
                else if (info->pk.rsa.type == RSA_PRIVATE_ENCRYPT /* sign */){
                   ret = wc_fspsm_RsaSign(info->pk.rsa.in,
                                        info->pk.rsa.inLen,
                                        info->pk.rsa.out,
                                        info->pk.rsa.outLen,
                                        info->pk.rsa.key,
                                        (void*)ctx);
                }
                else if (info->pk.rsa.type == RSA_PUBLIC_DECRYPT /* verify */) {
                    ret = wc_fspsm_RsaVerify(info->pk.rsa.in,
                                        info->pk.rsa.inLen,
                                        info->pk.rsa.out,
                                        info->pk.rsa.outLen,
                                        info->pk.rsa.key,
                                        (void*)ctx);
                }
            }
            else {
                WOLFSSL_MSG(
                    "SCE can handle 1024 or 2048 bit key size. "
                    "key size is not either 1024 or 2048. "
                    "Or wrapped key is not installed. "
                    "RSA operation falls through to SW operation.");
            }
        }
    }
    #endif /* !NO_RSA */
#endif /* TSIP or SCE */

    (void)devIdArg;
    (void)ctx;
    WOLFSSL_LEAVE("Renesas_cmn_CryptoDevCb", ret);
    return ret;
}

/* Renesas Security Library Common Entry Point
 * For usable method
 *
 * ssl     : a pointer to WOLFSSL object
 * session_key_generated : if session key has been generated
 * return  1 for usable, 0 for unusable
 */
int Renesas_cmn_usable(const struct WOLFSSL* ssl, byte session_key_generated)
{
    int ret = 0;

    #if defined(WOLFSSL_RENESAS_TSIP_TLS)
        ret = tsip_usable(ssl, session_key_generated);
    #elif defined(WOLFSSL_RENESAS_FSPSM_TLS) ||\
          defined(WOLFSSL_RENESAS_FSPSM_CRYPTONLY)
        ret = wc_fspsm_usable(ssl, session_key_generated);
    #endif

    (void)ssl;
    (void)session_key_generated;

    return ret;
}

/* Renesas Security Library Common Method
 * Get Callback ctx by devId
 *
 * devId   : devId to get its CTX
 * return  associated CTX when the method is successfully called.
 *         otherwise, NULL
 */
WOLFSSL_LOCAL void *Renesas_cmn_GetCbCtxBydevId(int devId)
{
    if (devId >= INITIAL_DEVID && devId <= (MAX_FSPSM_CBINDEX + INITIAL_DEVID))
        return gCbCtx[devId - INITIAL_DEVID];
    else
        return NULL;
}

/* Renesas Security Library Common Method
 * Crypt Callback initialization
 *
 * ssl     : a pointer to WOLFSSL object
 * ctx     : callback context
 * return  valid device Id on success, otherwise INVALID_DEVIID
 *         device Id starts from 7890, and increases + 1 its number
 *         when the method is successfully called.
 */
int wc_CryptoCb_CryptInitRenesasCmn(struct WOLFSSL* ssl, void* ctx)
{
    (void)ssl;
    (void)ctx;

    FSPSM_ST* cbInfo = (FSPSM_ST*)ctx;
    size_t internal_sz = sizeof(FSPSM_ST_Internal);

    if (cbInfo == NULL
   #if (!defined(WOLFSSL_RENESAS_FSPSM_CRYPTONLY) && \
        !defined(WOLFSSL_RENESAS_TSIP_CRYPTONLY)) && \
        !defined(HAVE_RENESAS_SYNC)
        || ssl == NULL
   #endif
    ) {
        WOLFSSL_MSG("Invalid devId\n");
        return INVALID_DEVID;
    }
    /* On Crypt Only mode, it is possible to call this method
     * first. On that time, internal instance has not yet been allocated.
     */
    if (cbInfo->internal == NULL) {
        if (ssl)
            cbInfo->internal =
                (FSPSM_ST_Internal*)XMALLOC(internal_sz, ssl->heap,
                                        DYNAMIC_TYPE_TMP_BUFFER);
        else
            cbInfo->internal = (FSPSM_ST_Internal*)XMALLOC(internal_sz, NULL,
                                        DYNAMIC_TYPE_TMP_BUFFER);
        if (cbInfo->internal == NULL) {
            return MEMORY_E;
        }
        ForceZero(cbInfo->internal, internal_sz);
       #if defined(WOLFSSL_RENESAS_FSPSM_TLS) ||\
            defined(WOLFSSL_RENESAS_TSIP_TLS)
        if (ssl)
            cbInfo->internal->heap = ssl->heap;
       #endif
    }
    /* need exclusive control because of static variable */
    if ((cmn_hw_lock()) == 0) {
        /* sanity check for overflow */
        if (gdevId < 0) {
            gdevId = INITIAL_DEVID;
        }
        cbInfo->devId = gdevId++;
        cmn_hw_unlock();
    }
    else {
        WOLFSSL_MSG("Failed to lock tsip hw");
        return INVALID_DEVID;
    }

    if (wc_CryptoCb_RegisterDevice(cbInfo->devId,
                            Renesas_cmn_CryptoDevCb, cbInfo) < 0) {
        /* undo devId number */
        gdevId--;
        return INVALID_DEVID;
    }

   #if !defined(WOLFSSL_RENESAS_FSPSM_CRYPTONLY) && \
       !defined(WOLFSSL_RENESAS_TSIP_CRYPTONLY) && \
       !defined(HAVE_RENESAS_SYNC)
    if (ssl)
        wolfSSL_SetDevId(ssl, cbInfo->devId);
   #endif

    gCbCtx[cbInfo->devId - INITIAL_DEVID] = (void*)cbInfo;

    return cbInfo->devId;
}

/* Renesas Security Library Common Method
 * Clean up CryptCb
 *
 * id     : a pointer to device id to unregister
 * no return value
 */
void wc_CryptoCb_CleanupRenesasCmn(int* id)
{

    FSPSM_ST* cbInfo = NULL;

    if (*id < INITIAL_DEVID ||
       (*id  - INITIAL_DEVID) > MAX_FSPSM_CBINDEX)
        return;
    /* retrieve internal instance */
    cbInfo = (FSPSM_ST*)gCbCtx[*id - INITIAL_DEVID];

    if (cbInfo != NULL && cbInfo->internal != NULL) {
     #if defined(WOLFSSL_RENESAS_FSPSM_TLS) && \
        !defined(WOLFSSL_RENESAS_FSPSM_CRYPTONLY)
        XFREE(cbInfo->internal, cbInfo->internal->heap,
                                        DYNAMIC_TYPE_TMP_BUFFER);
     #else
        XFREE(cbInfo->internal, NULL, DYNAMIC_TYPE_TMP_BUFFER);
     #endif
        cbInfo->internal = NULL;
    }
    wc_CryptoCb_UnRegisterDevice(*id);
}

#endif /* WOLF_CRYPTO_CB */
#endif /* WOLFSSL_RENESAS_FSPSM_TLS || WOLFSSL_RENESAS_FSPSM_CRYPTONLY
          WOLFSSL_RENESAS_TSIP_TLS  || WOLFSSL_RENESAS_TSIP_CRYPTONLY */

#if defined(WOLFSSL_RENESAS_FSPSM_TLS) || defined(WOLFSSL_RENESAS_TSIP_TLS)

/* Renesas Security Library Common Method
 * Check CA index if CA can be used for SCE/TSIP because
 * the CA has been verified by SCE/TSIP
 *
 * cmdIdx : ca index
 * return 1 can be used, otherwise 0
 */
WOLFSSL_LOCAL byte Renesas_cmn_checkCA(word32 cmIdx)
{
    WOLFSSL_ENTER("Renesas_cmn_checkCA");
    return (cmIdx == g_CAscm_Idx? 1:0);
}

/* check if the root CA has been verified by TSIP/SCE,
 * and it exists in the CM table.
 */
static byte fspsm_tsip_rootCAverified(void)
{
    WOLFSSL_ENTER("fspsm_tsip_rootCAverified");
    return (g_CAscm_Idx != (uint32_t)-1 ? 1:0);
}
/* Renesas Security Library Common Callback
 * Callback for Rsa verify
 *
 * ssl      the WOLFSSL object
 * sig      Buffer holding signature
 * sigSz    Length of signature in bytes
 * out      Buffer to hold hash
 * key      Buffer to hold ecc key
 * keySz    Length of key in bytes
 * return FSP_SUCCESS(0) on success, otherwise FSP/TSIP error code
 */
WOLFSSL_LOCAL int Renesas_cmn_RsaVerify(WOLFSSL* ssl, unsigned char* sig,
          unsigned int sigSz, unsigned char** out,
          const unsigned char* key, unsigned int keySz, void* ctx)
{
    int ret = 0;

    WOLFSSL_ENTER("Renesas_cmn_RsaVerify");

#if defined(WOLFSSL_RENESAS_TSIP_TLS)
    ret = wc_tsip_RsaVerify(ssl, sig, sigSz, out, key, keySz, ctx);

    if (ret == 0) {
        /* Set Callback for SharedSecret when successful */
        wolfSSL_CTX_SetEccSharedSecretCb(ssl->ctx, wc_tsip_EccSharedSecret);
        wolfSSL_SetEccSharedSecretCtx(ssl, ctx);
    }
    else {
        WOLFSSL_MSG("failed wc_tsip_RsaVerify");
        wolfSSL_CTX_SetEccSharedSecretCb(ssl->ctx, NULL);
        wolfSSL_SetEccSharedSecretCtx(ssl, NULL);
    }

#elif defined(WOLFSSL_RENESAS_FSPSM_TLS)
    ret = wc_fspsm_RsaVerifyTLS(ssl, sig, sigSz, out,key, keySz, ctx);

    if (ret == 0) {
        /* Set Callback for SharedSecret when successful */
        wolfSSL_CTX_SetEccSharedSecretCb(ssl->ctx, fspsm_EccSharedSecret);
        wolfSSL_SetEccSharedSecretCtx(ssl, ctx);
    }
    else {
        WOLFSSL_MSG("failed R_XXX_TLS_ServerKeyExchangeVerify");
        wolfSSL_CTX_SetEccSharedSecretCb(ssl->ctx, NULL);
        wolfSSL_SetEccSharedSecretCtx(ssl, NULL);
    }
#endif

    return ret;
}
/* Renesas Security Library Common Callback
 * Callback for Ecc verify
 *
 * ssl      the WOLFSSL object
 * sig      Buffer holding signature
 * sigSz    Length of signature in bytes
 * hash     Buffer to hold hash
 * hashSz   Length of hash
 * key      Buffer to hold ecc key
 * keySz    Length of key in bytes
 * result   a pointer to int indicates if the verify is ok
 * return FSP_SUCCESS(0) on success, otherwise FSP/TSIP error code
 */
WOLFSSL_LOCAL int Renesas_cmn_EccVerify(WOLFSSL* ssl, const unsigned char* sig,
          unsigned int sigSz, const unsigned char* hash, unsigned int hashSz,
        const unsigned char* key, unsigned int keySz, int* result, void* ctx)
{
    int ret = 0;

    WOLFSSL_ENTER("Renesas_cmn_EccVerify");

#if defined(WOLFSSL_RENESAS_TSIP)
    ret = wc_tsip_EccVerify(ssl, sig, sigSz, hash, hashSz, key, keySz,
                                                        result, ctx);
    if (ret == 0 && *result == 1) {
        /* Set callback for SharedSecret when being successful */
        wolfSSL_CTX_SetEccSharedSecretCb(ssl->ctx, wc_tsip_EccSharedSecret);
        wolfSSL_SetEccSharedSecretCtx(ssl, ctx);
    }
    else {
        WOLFSSL_MSG("failed wc_tsip_EccVerify");
        wolfSSL_CTX_SetEccSharedSecretCb(ssl->ctx, NULL);
        wolfSSL_SetEccSharedSecretCtx(ssl, NULL);
    }
#elif defined(WOLFSSL_RENESAS_FSPSM_TLS)
    ret = wc_fspsm_EccVerifyTLS(ssl, sig, sigSz, hash, hashSz, key, keySz,
                                                        result, ctx);
    if (ret == 0 && *result == 1) {
        /* Set callback for SharedSecret when being successful */
        wolfSSL_CTX_SetEccSharedSecretCb(ssl->ctx, fspsm_EccSharedSecret);
        wolfSSL_SetEccSharedSecretCtx(ssl, ctx);
    }
    else {
        WOLFSSL_MSG("failed R_XXXX_TLS_ServerKeyExchangeVerify");
        wolfSSL_CTX_SetEccSharedSecretCb(ssl->ctx, NULL);
        wolfSSL_SetEccSharedSecretCtx(ssl, NULL);
    }
#endif

    return ret;
}
/* Renesas Security Library Common Entry Point
 * For ROOT CA verifycation
 *
 * cert     Buffer to hold cert
 * cert_len Length of cert
 * key_n_start Byte position of public key in cert
 * key_n_len   Length of public key in bytes
 * key_e_start Byte position of public key exponent in cert
 * key_e_len   Length of public key exponent
 * cm_row      CA index
 * return FSP_SUCCESS(0) on success, otherwise WOLFSSL_FATAL_ERROR
 */
int wc_Renesas_cmn_RootCertVerify(const byte* cert, word32 cert_len,
        word32 key_n_start, word32 key_n_len, word32 key_e_start,
        word32 key_e_len, word32 cm_row)
{
    int ret;

    WOLFSSL_ENTER("wc_Renesas_cmn_RootCertVerify");

    if (fspsm_tsip_rootCAverified() == 0) {

    #if defined(WOLFSSL_RENESAS_TSIP_TLS)
        ret = wc_tsip_tls_RootCertVerify(cert, cert_len, key_n_start,
                key_n_len, key_e_start, key_e_len, cm_row);
        if (ret != TSIP_SUCCESS) {
            ret = WOLFSSL_FATAL_ERROR;
        }
    #elif defined(WOLFSSL_RENESAS_FSPSM_TLS)

        ret = wc_fspsm_tls_RootCertVerify(cert, cert_len, key_n_start,
                key_n_len, key_e_start, key_e_len, cm_row);
        if (ret != FSP_SUCCESS) {
            ret = WOLFSSL_FATAL_ERROR;
        }
    #endif

    }
    else {
        /* already verified. skipped */
        ret = 0;
    }
    WOLFSSL_LEAVE("wc_Renesas_cmn_RootCertVerify", ret);
    return ret;
}

/* Renesas Security Library Common Callback
 * Callback for tls finished
 *
 * ssl      the WOLFSSL object
 * side     CLIENT or SERVER
 * handshake_hash hash while doing handshake
 * hashes  calculated data by SCE/TSIP pseudo random function
 * return FSP_SUCCESS(0) on success, otherwise FSP/TSIP error code
 */
WOLFSSL_LOCAL int Renesas_cmn_TlsFinished(WOLFSSL* ssl, const byte *side,
                            const byte *handshake_hash, word32 hashSz,
                            byte *hashes, void* ctx)
{
    int ret = -1;

    (void)hashSz;
    (void)ctx;

    WOLFSSL_ENTER("Renesas_cmn_TlsFinished");

    if (Renesas_cmn_usable(ssl, 1)) {
 #if defined(WOLFSSL_RENESAS_TSIP_TLS)
        ret = wc_tsip_generateVerifyData(ssl->arrays->tsip_masterSecret,
                            side, handshake_hash, hashes);
 #elif defined(WOLFSSL_RENESAS_FSPSM_TLS)
         ret = wc_fspsm_generateVerifyData(ssl->arrays->fspsm_masterSecret,
                   side, handshake_hash, hashes);
 #endif
    }
     else
         ret = PROTOCOLCB_UNAVAILABLE;

    return ret;
}

/* Renesas Security Library Common Callback
 * Callback for setting Encrypt Keys.
 * Register callback for setting Encrypt Keys when keys are generated
 * by SCE/TSIP
 *
 * ssl      the WOLFSSL object
 * ctx      Callback context
 * return 0 on success, -1 when keys are not generated by SCE/TSIP
 */
static int Renesas_cmn_EncryptKeys(WOLFSSL* ssl, void* ctx)
{
    int ret;

    WOLFSSL_ENTER("Renesas_cmn_EncryptKeys");

    /* sanity check */
    if (ssl == NULL || ctx == NULL)
        return BAD_FUNC_ARG;

 #if defined(WOLFSSL_RENESAS_TSIP_TLS)
    TsipUserCtx* cbInfo = (TsipUserCtx*)ctx;

    if (cbInfo->internal->session_key_set == 1) {
        switch(cbInfo->internal->key_side) {
 #elif defined(WOLFSSL_RENESAS_FSPSM_TLS)
    FSPSM_ST* cbInfo = (FSPSM_ST*)ctx;

    if (cbInfo != NULL && cbInfo->internal != NULL &&
        cbInfo->internal->keyflgs_tls.bits.session_key_set == 1) {
        switch(cbInfo->internal->side) {
 #endif
            case 1:/* ENCRYPT_SIDE_ONLY */
                ssl->encrypt.setup = 1;
                break;
            case 2:/* DECRYPT_SIDE_ONLY */
                ssl->decrypt.setup = 1;
                break;
            case 3:/* ENCRYPT AND DECRYPT */
                ssl->decrypt.setup = 1;
                ssl->encrypt.setup = 1;
                break;
            default:break;
        }

        ret = 0;
        wolfSSL_CTX_SetTlsFinishedCb(ssl->ctx, Renesas_cmn_TlsFinished);
        wolfSSL_SetTlsFinishedCtx(ssl, cbInfo);
    }
    else {
        wolfSSL_CTX_SetTlsFinishedCb(ssl->ctx, NULL);
        wolfSSL_SetTlsFinishedCtx(ssl, NULL);
        ret = -1;
    }

    return ret;
}

/* Renesas Security Library Common Callback
 * Callback for Session Key generation
 * Register callback for Set Keys when keys are successfully
 * generated by SCE/TSIP
 *
 * ssl      the WOLFSSL object
 * ctx      Callback context
 * return FSP_SUCCESS(0) on success, otherwise SCE/TSIP error code
 */
WOLFSSL_LOCAL int Renesas_cmn_generateSessionKey(WOLFSSL* ssl, void* ctx)
{
    int ret = -1;
#if defined(WOLFSSL_RENESAS_TSIP_TLS)
    TsipUserCtx*      cbInfo = (TsipUserCtx*)ctx;
#elif defined(WOLFSSL_RENESAS_FSPSM_TLS)
    FSPSM_ST* cbInfo = (FSPSM_ST*)ctx;
#endif
    (void)ctx;

    WOLFSSL_ENTER("Renesas_cmn_generateSessionKey");
    if (Renesas_cmn_usable(ssl, 0)) {
#if defined(WOLFSSL_RENESAS_TSIP_TLS)
        ret = wc_tsip_generateSessionKey(ssl, cbInfo,
                                                cbInfo->devId);
#elif defined(WOLFSSL_RENESAS_FSPSM_TLS)
        ret = wc_fspsm_generateSessionKey(ssl, ctx, cbInfo->devId);
#endif
    }
    else {
         ret = PROTOCOLCB_UNAVAILABLE;
    }

    if (ret == 0) {
        wolfSSL_CTX_SetEncryptKeysCb(ssl->ctx, Renesas_cmn_EncryptKeys);
        wolfSSL_SetEncryptKeysCtx(ssl, ctx);
    }
    else {
        wolfSSL_CTX_SetEncryptKeysCb(ssl->ctx, NULL);
        wolfSSL_SetEncryptKeysCtx(ssl, NULL);
    }

    return ret;
}

/* Renesas Security Library Common Callback
 * Callback for Premaster Secret generation
 * Register callback for Set Keys when keys are successfully
 * generated by SCE/TSIP
 *
 * ssl      the WOLFSSL object
 * premaster Buffer to hold pre master
 * preSz     Length of pre-master
 * ctx       Callback context
 * return FSP_SUCCESS(0) on success,
 * otherwise PROTOCOLCB_UNAVAILABLE
 *          so that caller could continue to process if want
 */
WOLFSSL_LOCAL int Renesas_cmn_generatePremasterSecret(WOLFSSL* ssl,
                            byte *premaster, word32 preSz, void* ctx)
{
    int ret;

    (void) ctx;
    (void) ssl;

    WOLFSSL_ENTER("Renesas_cmn_generatePremasterSecret");

#if defined(WOLFSSL_RENESAS_TSIP_TLS)
    if (Renesas_cmn_usable(ssl, 0)) {
        ret = wc_tsip_generatePremasterSecret(premaster, preSz);
        ssl->arrays->preMasterSz = preSz;
    }
    else
        ret = PROTOCOLCB_UNAVAILABLE;

#elif defined(WOLFSSL_RENESAS_FSPSM_TLS)
    if (Renesas_cmn_usable(ssl, 0)) {
        ret = wc_fspsm_generatePremasterSecret(premaster, preSz);
        ssl->arrays->preMasterSz = preSz;
    }
    else
        ret = PROTOCOLCB_UNAVAILABLE;
#endif

    return ret;
}

/* Renesas Security Library Common Callback
 * Callback for Master Secret generation
 * Register callback for Session Key Generation when master secret is
 * successfully generated by SCE/TSIP
 *
 * ssl       the WOLFSSL object
 * ctx       Callback context
 * return FSP_SUCCESS(0) on success,
 * otherwise PROTOCOLCB_UNAVAILABLE
 *          so that caller could continue to process if want
 */
WOLFSSL_LOCAL int Renesas_cmn_genMasterSecret(struct WOLFSSL* ssl, void* ctx)
{
    int ret = WC_NO_ERR_TRACE(WOLFSSL_NOT_IMPLEMENTED);

    (void) ret;
    (void) ctx;

    WOLFSSL_ENTER("Renesas_cmn_genMasterSecret");

 #if defined(WOLFSSL_RENESAS_TSIP_TLS)

    if (Renesas_cmn_usable(ssl, 0)) {
    #if (WOLFSSL_RENESAS_TSIP_VER >= 109)
        ret = wc_tsip_generateMasterSecretEx(
                            ssl->options.cipherSuite0,
                            ssl->options.cipherSuite,
                            ssl->arrays->preMasterSecret,
                            ssl->arrays->clientRandom,
                            ssl->arrays->serverRandom,
                            ssl->arrays->tsip_masterSecret);
    #else
        ret = wc_tsip_generateMasterSecret(
                            ssl->arrays->preMasterSecret,
                            ssl->arrays->clientRandom,
                            ssl->arrays->serverRandom,
                            ssl->arrays->tsip_masterSecret);
    #endif

        if (ret == 0) {
            wc_tsip_storeKeyCtx(ssl, (TsipUserCtx*)ctx);
            /* set Session Key generation Callback for use */
            wolfSSL_CTX_SetGenSessionKeyCb(ssl->ctx,
                                                Renesas_cmn_generateSessionKey);
            wolfSSL_SetGenSessionKeyCtx(ssl, ctx);
        }
        else {
            wolfSSL_CTX_SetGenSessionKeyCb(ssl->ctx, NULL);
            wolfSSL_SetGenSessionKeyCtx(ssl, NULL);
        }
    }
    else
        ret = PROTOCOLCB_UNAVAILABLE;

 #elif defined(WOLFSSL_RENESAS_FSPSM_TLS)
    if (Renesas_cmn_usable(ssl, 0)) {
        ret = wc_fspsm_generateMasterSecret(
                            ssl->options.cipherSuite0,
                            ssl->options.cipherSuite,
                            ssl->arrays->preMasterSecret,
                            ssl->arrays->clientRandom,
                            ssl->arrays->serverRandom,
                            ssl->arrays->fspsm_masterSecret);
        if (ret == 0) {
            wc_fspsm_storeKeyCtx(ssl, ctx);
            /* set Session Key generation Callback for use */
            wolfSSL_CTX_SetGenSessionKeyCb(ssl->ctx,
                                                Renesas_cmn_generateSessionKey);
            wolfSSL_SetGenSessionKeyCtx(ssl, ctx);
        }
        else {
            wolfSSL_CTX_SetGenSessionKeyCb(ssl->ctx, NULL);
            wolfSSL_SetGenSessionKeyCtx(ssl, NULL);
        }
    }
    else {
        WOLFSSL_MSG("PROTOCOLCB_UNAVAILABLE\n");
        ret = PROTOCOLCB_UNAVAILABLE;
    }

 #endif
    return ret;
}

/* Renesas Security Library Common Callback
 * Callback for Rsa Encryption
 *
 * ssl       the WOLFSSL object
 * in        Buffer to hold plain text
 * inSz      Length of plain text
 * out       Buffer to hold cipher text
 * outSz     Length of cipher text buffer
 * KeyDer    Buffer holding Key in der format
 * KeySz     Length of Key Der
 * ctx       Callback context
 * return FSP_SUCCESS(0) on success,
 * otherwise CRYPTOCB_UNAVAILABLE
 *          so that caller could continue to process if want
 */
WOLFSSL_LOCAL int Renesas_cmn_RsaEnc(WOLFSSL* ssl, const unsigned char* in,
       unsigned int inSz, unsigned char* out, word32* outSz,
       const unsigned char* keyDer, unsigned int keySz, void* ctx)
{
    int ret;
    int EncSz;

    (void)ctx;
    (void)in;
    (void)inSz;
    (void)keyDer;
    (void)keySz;
    (void)EncSz;

    WOLFSSL_ENTER("Renesas_cmn_RsaEnc");

    /* sanity check */
    if (ssl == NULL || in == NULL || out == NULL || keyDer == NULL ||
            ctx == NULL) {
        return BAD_FUNC_ARG;
    }

    EncSz = wc_RsaEncryptSize(ssl->peerRsaKey);

 #if defined(WOLFSSL_RENESAS_TSIP_TLS)
    if (tsip_usable(ssl, 0)) {
        if (EncSz == 256) {
            ret = wc_tsip_generateEncryptPreMasterSecret(ssl, out, outSz);
        }
        else {
            WOLFSSL_MSG("TSIP can only handle 256 bytes for RSA encrypt size.");
            ret = CRYPTOCB_UNAVAILABLE;
        }
    }
    else {
        ret = CRYPTOCB_UNAVAILABLE;
    }

 #elif defined(WOLFSSL_RENESAS_FSPSM_TLS)
    if (wc_fspsm_usable(ssl, 0) && EncSz == 256) {
        ret = wc_fspsm_generateEncryptPreMasterSecret(ssl, out,
                                                            (uint32_t*)outSz);
    }
    else {
        if (EncSz != 256)
            WOLFSSL_MSG("SCE cannot use"
                     "because Rsa Encrypt Size isn't 256 bytes(2048 bits).");

        ret = CRYPTOCB_UNAVAILABLE;
    }
 #endif
    return ret;
}

/* Renesas Security Library Common Callback
 * Callback for Verify hmac
 *
 * ssl       the WOLFSSL object
 * message   Buffer to hold message
 * inSz      Length of message
 * macSz     Length of mac size
 * content   content of inner data
 * ctx       Callback context
 * return FSP_SUCCESS(0) on success,
 * otherwise PROTOCOLCB_UNAVAILABLE
 *          so that caller could continue to process if want
 */
WOLFSSL_LOCAL int Renesas_cmn_VerifyHmac(WOLFSSL *ssl, const byte* message,
                    word32 messageSz, word32 macSz, word32 content, void* ctx)
{
    int ret;
    (void)ctx;

    WOLFSSL_ENTER("Renesas_cmn_VerifyHmac");

#if defined(WOLFSSL_RENESAS_TSIP_TLS)
    if (tsip_usable(ssl, 1)) {
        ret = wc_tsip_ShaXHmacVerify(ssl, message, messageSz, macSz, content);
    }
    else
        ret = PROTOCOLCB_UNAVAILABLE;
#elif defined(WOLFSSL_RENESAS_FSPSM_TLS)
    if (wc_fspsm_usable(ssl, 1)) {
        ret = wc_fspsm_Sha256VerifyHmac(ssl, message,
                                                messageSz, macSz, content);
    }
    else
        ret = PROTOCOLCB_UNAVAILABLE;
#endif

    return ret;
}

#ifndef WOLFSSL_AEAD_ONLY
/* Renesas Security Library Common Callback
 * Callback for TLS hmac
 *
 * ssl       the WOLFSSL object
 * digest    Buffer to hold digest by hmac
 * in        Buffer to hold in data
 * sz        Length of in data
 * padSz     Length of padding
 * content   content of inner data
 * epochOrder
 * return FSP_SUCCESS(0) on success, otherwise error code
 */
WOLFSSL_LOCAL int Renesas_cmn_TLS_hmac(WOLFSSL* ssl, byte* digest,
  const byte* in, word32 sz, int padSz, int content, int verify, int epochOrder)
{
    int ret;
    byte   myInner[WOLFSSL_TLS_HMAC_INNER_SZ];

    WOLFSSL_ENTER("Renesas_cmn_TLS_hmac");

#if defined(WOLFSSL_RENESAS_TSIP_TLS)
    if (Renesas_cmn_usable(ssl, 1)) {

        wolfSSL_SetTlsHmacInner(ssl, myInner, sz, content, verify);

        if (ssl->specs.hash_size == WC_SHA_DIGEST_SIZE) {
            ret = wc_tsip_Sha1HmacGenerate(ssl, myInner,
                                    WOLFSSL_TLS_HMAC_INNER_SZ, in, sz, digest);
        }
        else if (ssl->specs.hash_size == WC_SHA256_DIGEST_SIZE) {
            ret = wc_tsip_Sha256HmacGenerate(ssl, myInner,
                                    WOLFSSL_TLS_HMAC_INNER_SZ, in, sz, digest);
        }
        else {
            ret = TSIP_MAC_DIGSZ_E;
        }
    }
    else {
        WOLFSSL_MSG("TLS_hmac is used instead of TSIP");
        /* fall through to original TLS hmac method when TSIP cannot be used */
        ret = TLS_hmac(ssl, digest, in, sz, padSz, content, verify, epochOrder);

    }

#elif defined(WOLFSSL_RENESAS_FSPSM_TLS)
    if (Renesas_cmn_usable(ssl, 1)) {
        if (ssl->specs.hash_size == WC_SHA256_DIGEST_SIZE) {
            wolfSSL_SetTlsHmacInner(ssl, myInner, sz, content, verify);
            ret = wc_fspsm_Sha256GenerateHmac(ssl, myInner,
                                    WOLFSSL_TLS_HMAC_INNER_SZ, in, sz, digest);
        }
        else
            ret = TSIP_MAC_DIGSZ_E;
    }
    else {
        /* fall through to original TLS hmac method when SCE cannot be used */
        ret = TLS_hmac(ssl, digest, in, sz, padSz, content, verify, epochOrder);
    }

#endif

    return ret;
}
#endif /* !WOLFSSL_AEAD_ONLY */

/* Renesas Security Library Common Callback
 * Callback for Signature PK Rsa verify
 *
 * sig      Buffer holding signature
 * sigSz    Length of signature in bytes
 * out      Buffer to hold hash
 * keyDer   Buffer to hold rsa key
 * keySz    Length of key in bytes
 * ctx      Callback context
 * return FSP_SUCCESS(0) on success,
 * otherwise CRYPTOCB_UNAVAILABLE
 *          so that caller could continue to process if want
 */
WOLFSSL_LOCAL int Renesas_cmn_SigPkCbRsaVerify(unsigned char* sig,
        unsigned int sigSz, unsigned char** out, const unsigned char* keyDer,
        unsigned int keySz, void* ctx)
{
    int ret;
    CertAttribute*  CertAtt;

    (void)out;
    (void)keyDer;
    (void)keySz;

    WOLFSSL_ENTER("Renesas_cmn_SigPkCbRsaVerify");

    /* sanity check */
    if (sig == NULL || out == NULL || keyDer == NULL || ctx == NULL)
        return BAD_FUNC_ARG;

    CertAtt = (CertAttribute*)ctx;
    if (!CertAtt) {
        return CRYPTOCB_UNAVAILABLE;
    }

#if defined(WOLFSSL_RENESAS_TSIP_TLS)
    if (CertAtt->keyIndex != NULL) {
        ret = wc_tsip_tls_CertVerify(CertAtt->cert, CertAtt->certSz, sig, sigSz,
                                 CertAtt->pubkey_n_start - CertAtt->certBegin,
                                 CertAtt->pubkey_n_len - 1,
                                 CertAtt->pubkey_e_start - CertAtt->certBegin,
                                 CertAtt->pubkey_e_len -1,
                                 (uint8_t*)CertAtt->keyIndex);
        if (ret == 0) {
            CertAtt->verifyByTSIP_SCE = 1;
        }
        else {
            WOLFSSL_MSG("RSA Verify by TSIP didn't match");
            ret = ASN_SIG_CONFIRM_E;
        }
    }
    else
        ret = CRYPTOCB_UNAVAILABLE;

#elif defined(WOLFSSL_RENESAS_FSPSM_TLS)
    if (CertAtt->keyIndex != NULL) {
        ret = wc_fspsm_tls_CertVerify(CertAtt->cert, CertAtt->certSz,
                                 sig, sigSz,
                                 CertAtt->pubkey_n_start - CertAtt->certBegin,
                                 CertAtt->pubkey_n_len - 1,
                                 CertAtt->pubkey_e_start - CertAtt->certBegin,
                                 CertAtt->pubkey_e_len -1,
                                 (uint8_t*)CertAtt->keyIndex);
        if (ret == 0) {
            CertAtt->verifyByTSIP_SCE = 1;
        }
        else {
            WOLFSSL_MSG("RSA Verify by SCE didn't match");
            ret = ASN_SIG_CONFIRM_E;
        }
    }
    else
        ret = CRYPTOCB_UNAVAILABLE;
#endif

    return ret;
}

/* Renesas Security Library Common Callback
 * Callback for Signature PK Ecc verify
 *
 * sig      Buffer holding signature
 * sigSz    Length of signature in bytes
 * has      Buffer to hold hash
 * hashSz   Length of hash
 * keyDer   Buffer to hold rsa key
 * keySz    Length of key in bytes
 * result   A pointer to int indicates a result
 * ctx      Callback context
 * return FSP_SUCCESS(0) on success,
 * otherwise CRYPTOCB_UNAVAILABLE
 *          so that caller could continue to process if want
 */
WOLFSSL_LOCAL int Renesas_cmn_SigPkCbEccVerify(const unsigned char* sig,
        unsigned int sigSz, const unsigned char* hash, unsigned int hashSz,
       const unsigned char* keyDer, unsigned int keySz,
       int* result, void* ctx)
{
    int ret;
    CertAttribute*  CertAtt;

    (void)result;
    (void)keyDer;
    (void)keySz;
    (void)hash;
    (void)hashSz;

    WOLFSSL_ENTER("Renesas_cmn_SigPkCbEccVerify");

    /* sanity check */
    if (sig == NULL || keyDer == NULL || hash == NULL || ctx == NULL ||
        result == NULL)
        return BAD_FUNC_ARG;


    CertAtt = (CertAttribute*)ctx;
    if (!CertAtt) {
        return CRYPTOCB_UNAVAILABLE;
    }

#if defined(WOLFSSL_RENESAS_TSIP_TLS)
    if (CertAtt->keyIndex != NULL) {
        ret = wc_tsip_tls_CertVerify(CertAtt->cert, CertAtt->certSz, sig, sigSz,
                                 CertAtt->pubkey_n_start - CertAtt->certBegin,
                                 CertAtt->pubkey_n_len - 1,
                                 CertAtt->pubkey_e_start - CertAtt->certBegin,
                                 CertAtt->pubkey_e_len -1,
                                 (uint8_t*)CertAtt->keyIndex);
        if (ret == 0) {
            CertAtt->verifyByTSIP_SCE = 1;
            *result = 1;
        }
        else {
            WOLFSSL_MSG("RSA Verify by TSIP didn't match");
            ret = ASN_SIG_CONFIRM_E;
        }
    }
    else
        ret = CRYPTOCB_UNAVAILABLE;
#elif defined(WOLFSSL_RENESAS_FSPSM_TLS)
    if (CertAtt->keyIndex != NULL) {
        ret = wc_fspsm_tls_CertVerify(CertAtt->cert, CertAtt->certSz,
                                 sig, sigSz,
                                 CertAtt->pubkey_n_start - CertAtt->certBegin,
                                 CertAtt->pubkey_n_len - 1,
                                 CertAtt->pubkey_e_start - CertAtt->certBegin,
                                 CertAtt->pubkey_e_len -1,
                                 (uint8_t*)CertAtt->keyIndex);
        if (ret == 0) {
            CertAtt->verifyByTSIP_SCE = 1;
            *result = 1;
        }
        else {
            WOLFSSL_MSG("RSA Verify by SCE didn't match");
            ret = ASN_SIG_CONFIRM_E;
        }
    }
    else
        ret = CRYPTOCB_UNAVAILABLE;
#endif

    return ret;
}

#endif /* SCEPROTECT || TSIP */
