/* * @author NXP Semiconductors * @version 1.0 * @par License * * Copyright 2016,2020 NXP * SPDX-License-Identifier: Apache-2.0 * * @par History * *****************************************************************************/ /** * @file a71_debug.c * @par Description * Wrap Debug Mode specific APDU's of A71CH. */ #include #include #include #include "scp.h" #include "sm_apdu.h" #include "sm_errors.h" #include "ax_api.h" #include "ax_common.h" #include "a71_debug.h" /** * Resets the Secure Module to the initial state. * @retval ::SW_OK Upon successful execution */ U16 A71_DbgReset(void) { U16 rv = 0; apdu_t apdu; apdu_t * pApdu = (apdu_t *) &apdu; pApdu->cla = AX_CLA; pApdu->ins = A71XX_INS_ERASE_MODULE; pApdu->p1 = P1_RESET; pApdu->p2 = P2_RESET; AllocateAPDUBuffer(pApdu); SetApduHeader(pApdu, USE_STANDARD_APDU_LEN); rv = (U16)scp_Transceive(NULL, pApdu, NO_C_MAC_NO_C_ENC_NO_R_MAC_NO_R_ENC); // no response data expected if (rv == SMCOM_OK) { // No response data expected rv = CheckNoResponseData(pApdu); } FreeAPDUBuffer(pApdu); return rv; } /** * Permanently disables the Debug API. * @retval ::SW_OK Upon successful execution */ U16 A71_DbgDisableDebug(void) { U16 rv = 0; apdu_t apdu; apdu_t * pApdu = (apdu_t *) &apdu; pApdu->cla = AX_CLA; pApdu->ins = A71XX_INS_FREEZE_MODULE; pApdu->p1 = P1_DISABLE_DEBUG; pApdu->p2 = P2_DISABLE_DEBUG; AllocateAPDUBuffer(pApdu); SetApduHeader(pApdu, USE_STANDARD_APDU_LEN); rv = (U16)scp_Transceive(NULL, pApdu, NO_C_MAC_NO_C_ENC_NO_R_MAC_NO_R_ENC); // no response data expected if (rv == SMCOM_OK) { // No response data expected rv = CheckNoResponseData(pApdu); } FreeAPDUBuffer(pApdu); return rv; } /// @cond static U16 DBG_GetFreeMem(U8 type, S16 *freeMem) { U16 rv = 0; apdu_t apdu; apdu_t * pApdu = (apdu_t *) &apdu; U8 buf[256]; U16 bufLen = sizeof(buf); U8 isOk; #ifndef A71_IGNORE_PARAM_CHECK if (freeMem == NULL) { return ERR_API_ERROR; } #endif pApdu->cla = AX_CLA; pApdu->ins = A71XX_INS_GET_MODULE; pApdu->p1 = type; pApdu->p2 = P2_FREE_MEMORY; AllocateAPDUBuffer(pApdu); SetApduHeader(pApdu, USE_STANDARD_APDU_LEN); *freeMem = 0; rv = (U16)scp_Transceive(NULL, pApdu, NO_C_MAC_NO_C_ENC_NO_R_MAC_NO_R_ENC); if (rv == SMCOM_OK) { rv = smGetSw(pApdu, &isOk); if (isOk) { rv = smApduGetResponseBody(pApdu, buf, &bufLen); if (rv == SW_OK) { if (bufLen == 2) { *freeMem = (S16)((buf[0] << 8) + (buf[1] & 0x000000FF)); } } } } FreeAPDUBuffer(pApdu); return rv; } /// @endcond /** * Reports the available persistent memory in the Security Module. * @retval ::SW_OK Upon successful execution */ U16 A71_DbgGetFreePersistentMemory(S16 *freeMem) { return DBG_GetFreeMem(P1_EEPROM, freeMem); } /** * Reports the available transient memory in the Security Module. * @retval ::SW_OK Upon successful execution */ U16 A71_DbgGetFreeTransientMemory(S16 *freeMem) { return DBG_GetFreeMem(P1_TRANSIENT_MEMORY, freeMem); } /** * Invokes data reflection APDU (facilitates link testing). No check of data payload returned * @param[in] sndBuf * @param[in] sndBufLen * @param[in,out] rcvBuf * @param[in,out] rcvBufLen * @return */ U16 A71_DbgReflect(U8 *sndBuf, U16 sndBufLen, U8 *rcvBuf, U16 *rcvBufLen) { U16 err = 0; apdu_t apdu; apdu_t * pApdu = (apdu_t *) &apdu; U8 isOk = 0x00; #ifndef A71_IGNORE_PARAM_CHECK if ((sndBuf == NULL) || (rcvBuf== NULL) || (rcvBufLen == NULL)) { return ERR_API_ERROR; } #endif pApdu->cla = A71XX_CLA; pApdu->ins = A71XX_INS_REFLECT; pApdu->p1 = 0x00; pApdu->p2 = 0x00; AllocateAPDUBuffer(pApdu); SetApduHeader(pApdu, USE_STANDARD_APDU_LEN); smApduAppendCmdData(pApdu, sndBuf, sndBufLen); err = (U16)scp_Transceive(NULL, pApdu, SCP_MODE); if (err == SMCOM_OK) { err = smGetSw( pApdu, &isOk); if (isOk) { if ( (pApdu->rxlen-2) > *rcvBufLen ) { *rcvBufLen = 0; return ERR_BUF_TOO_SMALL; } else { *rcvBufLen = pApdu->rxlen-2; memcpy(rcvBuf, pApdu->pBuf, *rcvBufLen); } } } return err; }