Files
NxpNfcRdLib/.svn/pristine/08/083e970d376c356b242b1599bc4e02646d143c8d.svn-base
2024-07-08 21:03:06 +08:00

558 lines
16 KiB
Plaintext

/*
* Copyright (c), NXP Semiconductors Gratkorn / Austria
*
* (C)NXP Semiconductors
* All rights are reserved. Reproduction in whole or in part is
* prohibited without the written consent of the copyright owner.
* NXP reserves the right to make changes without notice at any time.
* NXP makes no warranty, expressed, implied or statutory, including but
* not limited to any implied warranty of merchantability or fitness for any
*particular purpose, or that the use will not infringe any third party patent,
* copyright or trademark. NXP must not be liable for any loss or damage
* arising from its use.
*/
/** \file
* Generic MIFARE Plus contactless IC Application Component of Reader Library Framework.
* $Author$
* $Revision$ (v07.10.00)
* $Date$
*
* History:
* CHu: Generated 31. July 2009
*
*/
#include <ph_Status.h>
#include <phpalMifare.h>
#include <phalMfp.h>
#include "phalMfp_Int.h"
#include <ph_RefDefs.h>
#ifdef NXPBUILD__PHAL_MFP
phStatus_t phalMfp_Int_ComputeErrorResponse(
uint16_t wNumBytesReceived,
uint8_t bStatus,
uint8_t bLayer4Comm
)
{
phStatus_t PH_MEMLOC_REM status;
/* Invalid error response */
if (wNumBytesReceived == 0U)
{
return PH_ADD_COMPCODE_FIXED(PH_ERR_PROTOCOL_ERROR, PH_COMP_AL_MFP);
}
/* validate received response */
if (wNumBytesReceived == 1U)
{
if (0U != (bLayer4Comm))
{
switch (bStatus)
{
case PHAL_MFP_RESP_ACK_ISO4:
status = PH_ERR_SUCCESS;
break;
case PHAL_MFP_RESP_ERR_AUTH:
status = PHAL_MFP_ERR_AUTH;
break;
case PHAL_MFP_RESP_ERR_CMD_OVERFLOW:
status = PHAL_MFP_ERR_CMD_OVERFLOW;
break;
case PHAL_MFP_RESP_ERR_MAC_PCD:
status = PHAL_MFP_ERR_MAC_PCD;
break;
case PHAL_MFP_RESP_ERR_BNR:
status = PHAL_MFP_ERR_BNR;
break;
case PHAL_MFP_RESP_ERR_CMD_INVALID:
status = PHAL_MFP_ERR_CMD_INVALID;
break;
case PHAL_MFP_RESP_ERR_FORMAT:
status = PHAL_MFP_ERR_FORMAT;
break;
case PHAL_MFP_RESP_ERR_GEN_FAILURE:
status = PHAL_MFP_ERR_GEN_FAILURE;
break;
case PHAL_MFP_RESP_ERR_EXT:
status = PHAL_MFP_ERR_EXT;
break;
default:
status = PH_ERR_PROTOCOL_ERROR;
break;
}
return PH_ADD_COMPCODE(status, PH_COMP_AL_MFP);
}else
{
switch(bStatus)
{
case PHAL_MFP_RESP_ACK_ISO3:
case PHAL_MFP_RESP_ACK_ISO4:
status = PH_ERR_SUCCESS;
break;
/* Mapping of NAK codes: */
case PHAL_MFP_RESP_NACK0:
status = PHPAL_MIFARE_ERR_NAK0;
break;
case PHAL_MFP_RESP_NACK1:
status = PHPAL_MIFARE_ERR_NAK1;
break;
case PHAL_MFP_RESP_NACK4:
status = PHPAL_MIFARE_ERR_NAK4;
break;
case PHAL_MFP_RESP_NACK5:
status = PHPAL_MIFARE_ERR_NAK5;
break;
default:
status = PH_ERR_PROTOCOL_ERROR;
break;
}
return PH_ADD_COMPCODE(status, PH_COMP_PAL_MIFARE); /* For compatibility reasons with SW stack we use here PAL MIFARE product */
}
}
/* validate received response with wNumBytesReceived > 1 */
if (bStatus != PHAL_MFP_RESP_ACK_ISO4)
{
return PH_ADD_COMPCODE_FIXED(PH_ERR_PROTOCOL_ERROR, PH_COMP_AL_MFP);
}
/* proper error response */
return PH_ERR_SUCCESS;
}
phStatus_t phalMfp_Int_WritePerso(
void * pPalMifareDataParams,
uint8_t bLayer4Comm,
uint16_t wBlockNr,
uint8_t * pValue
)
{
phStatus_t PH_MEMLOC_REM statusTmp;
uint8_t PH_MEMLOC_REM aCmd[3];
uint8_t * PH_MEMLOC_REM pResponse = NULL;
uint16_t PH_MEMLOC_REM wRxLength = 0;
/* parameter checking */
if (pValue == NULL)
{
return PH_ADD_COMPCODE_FIXED(PH_ERR_INVALID_PARAMETER, PH_COMP_AL_MFP);
}
/* command frame */
aCmd[0] = PHAL_MFP_CMD_WRITEPERSO;
aCmd[1] = (uint8_t)(wBlockNr & 0xFFU); /* LSB */
aCmd[2] = (uint8_t)(wBlockNr >> 8U); /* MSB */
/* exchange command/response */
if (0U != (bLayer4Comm))
{
/* command header */
PH_CHECK_SUCCESS_FCT(statusTmp, phpalMifare_ExchangeL4(
pPalMifareDataParams,
PH_EXCHANGE_BUFFER_FIRST,
aCmd,
3,
&pResponse,
&wRxLength));
/* command exchange */
PH_CHECK_SUCCESS_FCT(statusTmp, phpalMifare_ExchangeL4(
pPalMifareDataParams,
PH_EXCHANGE_BUFFER_LAST,
pValue,
PHAL_MFP_MIFARE_BLOCK_SIZE,
&pResponse,
&wRxLength));
}
else
{
/* command header */
PH_CHECK_SUCCESS_FCT(statusTmp, phpalMifare_ExchangeL3(
pPalMifareDataParams,
PH_EXCHANGE_BUFFER_FIRST,
aCmd,
3,
&pResponse,
&wRxLength));
/* command exchange */
PH_CHECK_SUCCESS_FCT(statusTmp, phpalMifare_ExchangeL3(
pPalMifareDataParams,
PH_EXCHANGE_BUFFER_LAST,
pValue,
PHAL_MFP_MIFARE_BLOCK_SIZE,
&pResponse,
&wRxLength));
}
/* check response */
if (wRxLength == 1U)
{
PH_CHECK_SUCCESS_FCT(statusTmp, phalMfp_Int_ComputeErrorResponse(wRxLength, pResponse[0], bLayer4Comm));
}
else
{
return PH_ADD_COMPCODE_FIXED(PH_ERR_PROTOCOL_ERROR, PH_COMP_AL_MFP);
}
return PH_ERR_SUCCESS;
}
phStatus_t phalMfp_Int_CommitPerso(
void * pPalMifareDataParams,
uint8_t bLayer4Comm
)
{
phStatus_t PH_MEMLOC_REM statusTmp;
uint8_t PH_MEMLOC_REM aCmd[1];
uint8_t * PH_MEMLOC_REM pResponse = NULL;
uint16_t PH_MEMLOC_REM wRxLength = 0;
/* command code */
aCmd[0] = PHAL_MFP_CMD_COMMITPERSO;
/* exchange command/response */
if (0U != (bLayer4Comm))
{
/* command exchange */
PH_CHECK_SUCCESS_FCT(statusTmp, phpalMifare_ExchangeL4(
pPalMifareDataParams,
PH_EXCHANGE_DEFAULT,
aCmd,
1,
&pResponse,
&wRxLength));
}
else
{
/* command exchange */
PH_CHECK_SUCCESS_FCT(statusTmp, phpalMifare_ExchangeL3(
pPalMifareDataParams,
PH_EXCHANGE_DEFAULT,
aCmd,
1,
&pResponse,
&wRxLength));
}
/* check response */
if (wRxLength == 1U)
{
PH_CHECK_SUCCESS_FCT(statusTmp, phalMfp_Int_ComputeErrorResponse(wRxLength, pResponse[0], bLayer4Comm));
}
else
{
return PH_ADD_COMPCODE_FIXED(PH_ERR_PROTOCOL_ERROR, PH_COMP_AL_MFP);
}
return PH_ERR_SUCCESS;
}
phStatus_t phalMfp_Int_ResetAuth(void * pPalMifareDataParams)
{
phStatus_t PH_MEMLOC_REM statusTmp;
uint8_t PH_MEMLOC_REM aCmd[1 /* command code */];
uint8_t * PH_MEMLOC_REM pResponse = NULL;
uint16_t PH_MEMLOC_REM wRxLength = 0;
/* command code */
aCmd[0] = PHAL_MFP_CMD_RAUTH;
/* command exchange */
PH_CHECK_SUCCESS_FCT(statusTmp, phpalMifare_ExchangeL4(
pPalMifareDataParams,
PH_EXCHANGE_DEFAULT,
aCmd,
1,
&pResponse,
&wRxLength));
/* check response */
PH_CHECK_SUCCESS_FCT(statusTmp, phalMfp_Int_ComputeErrorResponse(wRxLength, pResponse[0], 1));
return PH_ERR_SUCCESS;
}
phStatus_t phalMfp_Int_PrepareProximityCheck(
void * pPalMifareDataParams
)
{
phStatus_t PH_MEMLOC_REM statusTmp;
uint8_t PH_MEMLOC_REM aCmd[1];
uint8_t * PH_MEMLOC_REM pResponse = NULL;
uint16_t PH_MEMLOC_REM wRxLength = 0;
/* command code */
aCmd[0] = PHAL_MFP_CMD_PPC;
/* command exchange */
PH_CHECK_SUCCESS_FCT(statusTmp, phpalMifare_ExchangeL4(
pPalMifareDataParams,
PH_EXCHANGE_DEFAULT,
aCmd,
1,
&pResponse,
&wRxLength));
/* check response */
if (wRxLength == 1U)
{
PH_CHECK_SUCCESS_FCT(statusTmp, phalMfp_Int_ComputeErrorResponse(wRxLength, pResponse[0], 1));
}
else
{
return PH_ADD_COMPCODE_FIXED(PH_ERR_PROTOCOL_ERROR, PH_COMP_AL_MFP);
}
return PH_ERR_SUCCESS;
}
phStatus_t phalMfp_Int_ProximityCheck(
void * pPalMifareDataParams,
uint8_t bNumSteps,
uint8_t * pRndC,
uint8_t * pRndRC
)
{
phStatus_t PH_MEMLOC_REM statusTmp = 0;
uint8_t PH_MEMLOC_REM aCmd[1 /* command code */ + 1 /* length */ + 7 /* max RndC length */];
uint8_t * PH_MEMLOC_REM pResponse = NULL;
uint16_t PH_MEMLOC_REM wRxLength = 0;
uint8_t PH_MEMLOC_REM bPayloadLen;
uint8_t PH_MEMLOC_REM bRndCLen = 0;
uint8_t PH_MEMLOC_REM bRndRCLen = 0;
phStatus_t PH_MEMLOC_REM status = PH_ERR_SUCCESS;
/* parameter checking */
if ((bNumSteps == 0U) || (bNumSteps > PHAL_MFP_PC_RND_LEN) || (pRndC == NULL) || (pRndRC == NULL))
{
return PH_ADD_COMPCODE_FIXED(PH_ERR_INVALID_PARAMETER, PH_COMP_AL_MFP);
}
/*Enabling Min FDT for PC*/
PH_CHECK_SUCCESS_FCT(status, phpalMifare_SetMinFdtPc(pPalMifareDataParams, 1));
/* command code */
aCmd[0] = PHAL_MFP_CMD_PC;
/* Proximity Check loop */
while (0U != (bNumSteps--))
{
/* RndC length */
if (0U != (bNumSteps))
{
bPayloadLen = 1;
}
else
{
bPayloadLen = PHAL_MFP_PC_RND_LEN - bRndCLen;
}
/* Length */
aCmd[1] = bPayloadLen;
/* RndC */
(void)memcpy(&aCmd[2], &pRndC[bRndCLen], bPayloadLen);
/* command exchange */
statusTmp = phpalMifare_ExchangePc( pPalMifareDataParams,
PH_EXCHANGE_DEFAULT,
aCmd,
2u + bPayloadLen,
&pResponse,
&wRxLength);
if (statusTmp == PH_ERR_SUCCESS)
{
/* check response */
if (wRxLength == (uint16_t)bPayloadLen)
{
/* copy RndR */
(void)memcpy(&pRndRC[bRndRCLen], pResponse, wRxLength);
bRndRCLen = bRndRCLen + (uint8_t)wRxLength;
/* copy RndC */
(void)memcpy(&pRndRC[bRndRCLen], &pRndC[bRndCLen], wRxLength);
bRndRCLen = bRndRCLen + (uint8_t)wRxLength;
bRndCLen = bRndCLen + (uint8_t)wRxLength;
}
else
{
statusTmp = phalMfp_Int_ComputeErrorResponse(wRxLength,
pResponse[0], 1);
}
}
}
/*Disabling Min FDT for PC*/
PH_CHECK_SUCCESS_FCT(status, phpalMifare_SetMinFdtPc(pPalMifareDataParams, 0));
PH_CHECK_SUCCESS(statusTmp);
/* We expect to have exactly 7 bytes RndR + 7 bytes RndC */
if (bRndRCLen != (PHAL_MFP_PC_RND_LEN * 2U))
{
return PH_ADD_COMPCODE_FIXED(PH_ERR_PROTOCOL_ERROR, PH_COMP_AL_MFP);
}
return PH_ERR_SUCCESS;
}
phStatus_t phalMfp_Int_MultiBlockRead(
void * pPalMifareDataParams,
uint8_t bBlockNr,
uint8_t bNumBlocks,
uint8_t * pBlocks
)
{
phStatus_t PH_MEMLOC_REM statusTmp;
uint8_t PH_MEMLOC_REM aCmd[1 /* command code */ + 1 /* wBlockNr */ + 1 /* bNumBlocks */];
uint8_t * PH_MEMLOC_REM pResponse = NULL;
uint16_t PH_MEMLOC_REM wRxLength = 0;
/* parameter checking */
if (pBlocks == NULL)
{
return PH_ADD_COMPCODE_FIXED(PH_ERR_INVALID_PARAMETER, PH_COMP_AL_MFP);
}
/* command frame */
aCmd[0] = PHAL_MFP_CMD_MBREAD;
aCmd[1] = bBlockNr;
aCmd[2] = bNumBlocks;
/* command exchange */
PH_CHECK_SUCCESS_FCT(statusTmp, phpalMifare_ExchangeL3(
pPalMifareDataParams,
PH_EXCHANGE_DEFAULT,
aCmd,
3,
&pResponse,
&wRxLength));
/* check response */
if (((wRxLength % PHAL_MFP_MIFARE_BLOCK_SIZE) == 0U) && (wRxLength <= (uint16_t)(3u * PHAL_MFP_MIFARE_BLOCK_SIZE)))
{
/* pass back read bytes */
(void)memcpy(pBlocks, pResponse, wRxLength);
}
else
{
PH_CHECK_SUCCESS_FCT(statusTmp, phalMfp_Int_ComputeErrorResponse(wRxLength, pResponse[0], 0));
}
return PH_ERR_SUCCESS;
}
phStatus_t phalMfp_Int_MultiBlockWrite(
void * pPalMifareDataParams,
uint8_t bBlockNr,
uint8_t bNumBlocks,
uint8_t * pBlocks
)
{
phStatus_t PH_MEMLOC_REM statusTmp;
uint8_t PH_MEMLOC_REM aCmd[1 /* command code */ + 1 /* wBlockNr */ + 1 /* bNumBlocks */];
uint8_t * PH_MEMLOC_REM pResponse = NULL;
uint16_t PH_MEMLOC_REM wRxLength = 0;
/* parameter checking */
if (pBlocks == NULL)
{
return PH_ADD_COMPCODE_FIXED(PH_ERR_INVALID_PARAMETER, PH_COMP_AL_MFP);
}
/* command frame */
aCmd[0] = PHAL_MFP_CMD_MBWRITE;
aCmd[1] = bBlockNr;
aCmd[2] = bNumBlocks;
/* command exchange */
PH_CHECK_SUCCESS_FCT(statusTmp, phpalMifare_ExchangeL3(
pPalMifareDataParams,
PH_EXCHANGE_DEFAULT,
aCmd,
3,
&pResponse,
&wRxLength));
/* command exchange */
PH_CHECK_SUCCESS_FCT(statusTmp, phpalMifare_ExchangeL3(
pPalMifareDataParams,
PH_EXCHANGE_DEFAULT,
pBlocks,
(uint16_t)(bNumBlocks * PHAL_MFP_MIFARE_BLOCK_SIZE),
&pResponse,
&wRxLength));
return PH_ERR_SUCCESS;
}
phStatus_t phalMfp_Int_CreateValueBlock(
uint8_t * pValue,
uint8_t bAddrData,
uint8_t * pBlock
)
{
pBlock[0] = (uint8_t)(pValue[0]);
pBlock[1] = (uint8_t)(pValue[1]);
pBlock[2] = (uint8_t)(pValue[2]);
pBlock[3] = (uint8_t)(pValue[3]);
pBlock[4] = (uint8_t)(~pBlock[0]);
pBlock[5] = (uint8_t)(~pBlock[1]);
pBlock[6] = (uint8_t)(~pBlock[2]);
pBlock[7] = (uint8_t)(~pBlock[3]);
pBlock[8] = (uint8_t)(pBlock[0]);
pBlock[9] = (uint8_t)(pBlock[1]);
pBlock[10] = (uint8_t)(pBlock[2]);
pBlock[11] = (uint8_t)(pBlock[3]);
pBlock[12] = (uint8_t)bAddrData;
pBlock[13] = (uint8_t)~bAddrData;
pBlock[14] = (uint8_t)bAddrData;
pBlock[15] = (uint8_t)~bAddrData;
return PH_ERR_SUCCESS;
}
phStatus_t phalMfp_Int_CheckValueBlockFormat(
uint8_t * pBlock
)
{
/* check format of value block */
if ((pBlock[0] != pBlock[8]) ||
(pBlock[1] != pBlock[9]) ||
(pBlock[2] != pBlock[10]) ||
(pBlock[3] != pBlock[11]) ||
(pBlock[4] != (pBlock[0] ^ 0xFFU)) ||
(pBlock[5] != (pBlock[1] ^ 0xFFU)) ||
(pBlock[6] != (pBlock[2] ^ 0xFFU)) ||
(pBlock[7] != (pBlock[3] ^ 0xFFU)) ||
(pBlock[12] != pBlock[14]) ||
(pBlock[13] != pBlock[15]) ||
(pBlock[12] != (pBlock[13]^ 0xFFU)))
{
return PH_ADD_COMPCODE_FIXED(PH_ERR_PROTOCOL_ERROR, PH_COMP_AL_MFP);
}
return PH_ERR_SUCCESS;
}
#endif /* NXPBUILD__PHAL_MFP */