blob: eabcf0456b70511966ea7b1c35082e684c229db6 [file] [log] [blame]
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* Mifare Standard Format implementation
*/
#ifndef PHFRINFC_MIFSTDFORMAT_H
#define PHFRINFC_MIFSTDFORMAT_H
#include <phFriNfc.h>
#include <phFriNfc_SmtCrdFmt.h>
#include <phNfcStatus.h>
#include <phNfcTypes.h>
/********************* Definitions and structures *****************************/
/*
* Mifare standard -progress states
*/
#define PH_FRINFC_MFSTD_FMT_RESET_INIT 0 /* Reset state */
#define PH_FRINFC_MFSTD_FMT_AUTH_SECT \
1 /* Sector authentication is in progress */
#define PH_FRINFC_MFSTD_FMT_DIS_CON 2 /* Disconnect is in progress */
#define PH_FRINFC_MFSTD_FMT_CON 3 /* Connect is in progress */
#define PH_FRINFC_MFSTD_FMT_POLL 4 /* Poll is in progress */
#define PH_FRINFC_MFSTD_FMT_RD_SECT_TR \
5 /* Read sector trailer is in progress */
#define PH_FRINFC_MFSTD_FMT_WR_SECT_TR \
6 /* Write sector trailer is in progress */
#define PH_FRINFC_MFSTD_FMT_WR_TLV 7 /* Write sector trailer is in progress */
#define PH_FRINFC_MFSTD_FMT_WR_MAD_BLK 8 /* Write MAD is in progress */
#define PH_FRINFC_MFSTD_FMT_UPD_MAD_BLK 9 /* Write MAD is in progress */
/*
* Mifare standard -Authenticate states
*/
#define PH_FRINFC_MFSTD_FMT_AUTH_DEF_KEY \
0 /* Trying to authenticate with the default key */
#define PH_FRINFC_MFSTD_FMT_AUTH_NFC_KEY \
1 /* Trying to authenticate with the MAD key */
#define PH_FRINFC_MFSTD_FMT_AUTH_MAD_KEY \
2 /* Trying to authenticate with the NFC forum key */
#define PH_FRINFC_MFSTD_FMT_AUTH_KEYB \
3 /* Trying to authenticate with key B \
*/
#define PH_FRINFC_MFSTD_FMT_AUTH_SCRT_KEYB \
4 /* Trying to authenticate with secret key B */
/*
* Mifare standard - Update MAD block flag
*/
#define PH_FRINFC_MFSTD_FMT_NOT_A_MAD_BLK 0 /* Not a MAD block */
#define PH_FRINFC_MFSTD_FMT_MAD_BLK_1 1 /* MAD block number 1 */
#define PH_FRINFC_MFSTD_FMT_MAD_BLK_2 2 /* MAD block number 2 */
#define PH_FRINFC_MFSTD_FMT_MAD_BLK_64 \
64 /* MAD block number 64 (only used for Mifare 4k card) */
#define PH_FRINFC_MFSTD_FMT_MAD_BLK_65 \
65 /* MAD block number 65 (only used for Mifare 4k card) */
#define PH_FRINFC_MFSTD_FMT_MAD_BLK_66 \
66 /* MAD block number 66 (only used for Mifare 4k card) */
/*
* Mifare standard - Update MAD block flag
*/
#define PH_FRINFC_SMTCRDFMT_MSTD_MADSECT_KEYA_ACS_BIT_1K \
{ 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0x78, 0x77, 0x88, 0xC1 }
#define PH_FRINFC_SMTCRDFMT_MSTD_MADSECT_KEYA_ACS_BIT_2K \
{ 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0x78, 0x77, 0x88, 0xC1 }
#define PH_FRINFC_SMTCRDFMT_MSTD_MADSECT_KEYA_ACS_BIT_4K \
{ 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0x78, 0x77, 0x88, 0xC2 }
#define PH_FRINFC_SMTCRDFMT_NFCFORUMSECT_KEYA_ACS_BIT \
{ 0xD3, 0xF7, 0xD3, 0xF7, 0xD3, 0xF7, 0x7F, 0x07, 0x88, 0x40 }
/*
* Mifare standard - Key and access bit constants
*/
#define PH_FRINFC_MFSTD_FMT_NFC_SECT_KEYA0 0xD3 /* NFC forum sector key A */
#define PH_FRINFC_MFSTD_FMT_NFC_SECT_KEYA1 0xF7 /* NFC forum sector key A */
#define PH_FRINFC_MFSTD_FMT_MAD_SECT_KEYA0 0xA0 /* MAD sector key A */
#define PH_FRINFC_MFSTD_FMT_MAD_SECT_KEYA1 0xA1 /* MAD sector key A */
#define PH_FRINFC_MFSTD_FMT_MAD_SECT_KEYA2 0xA2 /* MAD sector key A */
#define PH_FRINFC_MFSTD_FMT_MAD_SECT_KEYA3 0xA3 /* MAD sector key A */
#define PH_FRINFC_MFSTD_FMT_MAD_SECT_KEYA4 0xA4 /* MAD sector key A */
#define PH_FRINFC_MFSTD_FMT_MAD_SECT_KEYA5 0xA5 /* MAD sector key A */
#define PH_FRINFC_MFSTD_FMT_DEFAULT_KEY 0xFF /* Default key A or B */
#define PH_FRINFC_MFSTD_FMT_MAD_SECT_ACS6 0x78 /* MAD sector access bits 6 */
#define PH_FRINFC_MFSTD_FMT_MAD_SECT_ACS7 0x77 /* MAD sector access bits 7 */
#define PH_FRINFC_MFSTD_FMT_MAD_SECT_ACS8 0x88 /* MAD sector access bits 8 */
#define PH_FRINFC_MFSTD_FMT_MAD_SECT_GPB 0xC1 /* MAD sector GPB */
#define PH_FRINFC_MFSTD_FMT_NFC_SECT_ACS_RW6 \
0x7F /* NFC forum sector access bits 6 for read write */
#define PH_FRINFC_MFSTD_FMT_NFC_SECT_ACS_RW7 \
0x07 /* NFC forum sector access bits 7 for read write */
#define PH_FRINFC_MFSTD_FMT_NFC_SECT_ACS_RW8 \
0x88 /* NFC forum sector access bits 8 for read write */
#define PH_FRINFC_MFSTD_FMT_NFC_SECT_GPB_RW \
0x40 /* NFC forum sector GPB for read write */
#define PH_FRINFC_MFSTD_FMT_NFC_SECT_ACS_RO6 \
0x07 /* NFC forum sector access bits 6 for read only */
#define PH_FRINFC_MFSTD_FMT_NFC_SECT_ACS_RO7 \
0x8F /* NFC forum sector access bits 7 for read only */
#define PH_FRINFC_MFSTD_FMT_NFC_SECT_ACS_RO8 \
0x0F /* NFC forum sector access bits 8 for read only */
#define PH_FRINFC_MFSTD_FMT_NFC_SECT_GPB_R0 \
0x43 /* NFC forum sector GPB for read only */
/*
* Enum definition contains Mifare standard values
*/
typedef enum {
PH_FRINFC_MFSTD_FMT_VAL_0,
PH_FRINFC_MFSTD_FMT_VAL_1,
PH_FRINFC_MFSTD_FMT_VAL_2,
PH_FRINFC_MFSTD_FMT_VAL_3,
PH_FRINFC_MFSTD_FMT_VAL_4,
PH_FRINFC_MFSTD_FMT_VAL_5,
PH_FRINFC_MFSTD_FMT_VAL_6,
PH_FRINFC_MFSTD_FMT_VAL_7,
PH_FRINFC_MFSTD_FMT_VAL_8,
PH_FRINFC_MFSTD_FMT_VAL_9,
PH_FRINFC_MFSTD_FMT_VAL_10,
PH_FRINFC_MFSTD_FMT_VAL_11
} phFriNfc_MfStdVal;
/*
* Mifare standard - NDEF information constants
*/
#define PH_FRINFC_MFSTD_FMT_NON_NDEF_COMPL \
0 /* Sector is not ndef compliant \
*/
#define PH_FRINFC_MFSTD_FMT_NDEF_COMPL 1 /* Sector is ndef compliant */
#define PH_FRINFC_MFSTD_FMT_NDEF_INFO1 \
0x03 /* If sector is ndef compliant, then one of the MAD \
sector byte is 0x03 */
#define PH_FRINFC_MFSTD_FMT_NDEF_INFO2 \
0xE1 /* If sector is ndef compliant, then one of the MAD \
sector byte is 0xE1 */
/*
* Mifare standard - constants
*/
#define PH_FRINFC_MFSTD_FMT_MAX_RECV_LENGTH 252 /* Maximum receive length */
#define PH_FRINFC_MFSTD_FMT_WR_SEND_LENGTH 17 /* Send length for write */
#define PH_FRINFC_MFSTD_FMT_MAX_SECT_IND_1K \
16 /* Maximum sector index for Mifare 1k = 16 */
#define PH_FRINFC_MFSTD_FMT_MAX_SECT_IND_2K \
32 /* Maximum sector index for Mifare 2k = 32 */
#define PH_FRINFC_MFSTD_FMT_MAX_SECT_IND_4K \
40 /* Maximum sector index for Mifare 4k = 40 */
#define PH_FRINFC_MFSTD_FMT_MAX_BLOCKS_1K \
64 /* Maximum Number of Blocks for Mifare 1k = 64 */
#define PH_FRINFC_MFSTD_FMT_MAX_BLOCKS_2K \
128 /* Maximum Number of Blocks for Mifare 2k = 128 */
#define PH_FRINFC_MFSTD_FMT_MAX_BLOCKS_4K \
256 /* Maximum Number of Blocks for Mifare 4k = 256*/
/*
* Copy default keyA to send buffer
*/
#define PH_FRINFC_MFSTD_FMT_AUTH_SEND_BUF_DEF(mem) \
do { \
memset(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFSTD_FMT_VAL_1], \
PH_FRINFC_MFSTD_FMT_DEFAULT_KEY, PH_FRINFC_MFSTD_FMT_VAL_6); \
NdefSmtCrdFmt->Cmd.MfCmd = ((NdefSmtCrdFmt->AddInfo.MfStdInfo.AuthState == \
PH_FRINFC_MFSTD_FMT_AUTH_DEF_KEY) \
? phHal_eMifareAuthentA \
: phHal_eMifareAuthentB); \
NdefSmtCrdFmt->SendLength = PH_FRINFC_MFSTD_FMT_VAL_7; \
} while (0)
/*
* NFC forum sector keyA to send buffer
*/
#define PH_FRINFC_MFSTD_FMT_AUTH_SEND_BUF_NFCSECT_KEYA(mem) \
do { \
memcpy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFSTD_FMT_VAL_1], \
NdefSmtCrdFmt->AddInfo.MfStdInfo.NFCForumSect_KeyA, \
PH_FRINFC_MFSTD_FMT_VAL_6); \
NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareAuthentA; \
NdefSmtCrdFmt->SendLength = PH_FRINFC_MFSTD_FMT_VAL_7; \
} while (0)
/*
* Copy MAD sector keyA to send buffer
*/
#define PH_FRINFC_MFSTD_FMT_AUTH_SEND_BUF_MADSECT_KEYA(mem) \
do { \
memcpy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFSTD_FMT_VAL_1], \
NdefSmtCrdFmt->AddInfo.MfStdInfo.MADSect_KeyA, \
PH_FRINFC_MFSTD_FMT_VAL_6); \
NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareAuthentA; \
NdefSmtCrdFmt->SendLength = PH_FRINFC_MFSTD_FMT_VAL_7; \
} while (0)
/*
* Copy MAD sector keyB to send buffer
*/
#define PH_FRINFC_MFSTD_FMT_AUTH_SEND_BUF_SCRT_KEY(mem) \
do { \
(void)memcpy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFSTD_FMT_VAL_1], \
NdefSmtCrdFmt->AddInfo.MfStdInfo.ScrtKeyB, \
PH_FRINFC_MFSTD_FMT_VAL_6); \
NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareAuthentB; \
NdefSmtCrdFmt->SendLength = PH_FRINFC_MFSTD_FMT_VAL_7; \
} while (0)
/*
* Get the next block
*/
#define PH_FRINFC_MFSTD_FMT_CUR_BLK_INC() \
NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock += \
((NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock >= 127) ? 16 : 4)
/*
* Get the sector index
*/
#define PH_FRINFC_MFSTD_FMT_SECT_INDEX_CALC \
((NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock >= 128) \
? (32 + ((NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock - 128) / 16)) \
: (NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock / 4))
/*
* Check the sector block
*/
#define PH_FRINFC_MFSTD_FMT_CUR_BLK_CHK \
(((NdefSmtCrdFmt->CardType == PH_FRINFC_SMTCRDFMT_MFSTD_1K_CRD) && \
(NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock >= \
PH_FRINFC_MFSTD_FMT_MAX_BLOCKS_1K)) || \
((NdefSmtCrdFmt->CardType == PH_FRINFC_SMTCRDFMT_MFSTD_4K_CRD) && \
(NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock >= \
PH_FRINFC_MFSTD_FMT_MAX_BLOCKS_4K)) || \
((NdefSmtCrdFmt->CardType == PH_FRINFC_SMTCRDFMT_MFSTD_2K_CRD) && \
(NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock >= \
PH_FRINFC_MFSTD_FMT_MAX_BLOCKS_2K)))
/*
* Get the next authenticate state
*/
#define PH_FRINFC_MFSTD_FMT_NXT_AUTH_STATE() \
do { \
switch (NdefSmtCrdFmt->AddInfo.MfStdInfo.AuthState) { \
case PH_FRINFC_MFSTD_FMT_AUTH_DEF_KEY: { \
NdefSmtCrdFmt->AddInfo.MfStdInfo.AuthState = (uint8_t)( \
(((NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock <= 3) || \
((NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock > 63) && \
(NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock < 67)))) \
? PH_FRINFC_MFSTD_FMT_AUTH_MAD_KEY \
: PH_FRINFC_MFSTD_FMT_AUTH_NFC_KEY); \
} break; \
case PH_FRINFC_MFSTD_FMT_AUTH_NFC_KEY: { \
NdefSmtCrdFmt->AddInfo.MfStdInfo.AuthState = \
PH_FRINFC_MFSTD_FMT_AUTH_KEYB; \
} break; \
case PH_FRINFC_MFSTD_FMT_AUTH_MAD_KEY: { \
NdefSmtCrdFmt->AddInfo.MfStdInfo.AuthState = \
PH_FRINFC_MFSTD_FMT_AUTH_NFC_KEY; \
} break; \
case PH_FRINFC_MFSTD_FMT_AUTH_KEYB: { \
NdefSmtCrdFmt->AddInfo.MfStdInfo.AuthState = \
PH_FRINFC_MFSTD_FMT_AUTH_SCRT_KEYB; \
} break; \
case PH_FRINFC_MFSTD_FMT_AUTH_SCRT_KEYB: \
default: { \
NdefSmtCrdFmt->AddInfo.MfStdInfo.AuthState = \
PH_FRINFC_MFSTD_FMT_AUTH_DEF_KEY; \
} break; \
} \
} while (0)
/*
* Increment the sector index
*/
#define PH_FRINFC_MFSTD_FMT_INCR_SECT \
do { \
SectIndex++; \
SectIndex = \
(uint8_t)((SectIndex == 16) ? (SectIndex + PH_FRINFC_MFSTD_FMT_VAL_1) \
: SectIndex); \
} while (0)
/*
* Increment the sector index
*/
#define PH_FRINFC_MFSTD_FMT_CHK_SECT_ARRAY \
do { \
while ((index < PH_FRINFC_MFSTD_FMT_MAX_SECT_IND_4K) && \
(memcompare != PH_FRINFC_MFSTD_FMT_VAL_0)) { \
/* Compare any one among the sectors is NDEF COMPLIANT */ \
memcompare = (uint32_t)phFriNfc_MfStd_MemCompare( \
&Buffer[PH_FRINFC_MFSTD_FMT_VAL_0], \
&NdefSmtCrdFmt->AddInfo.MfStdInfo.SectCompl[index], \
PH_FRINFC_MFSTD_FMT_VAL_1); \
/* increment the index */ \
index += (uint8_t)((index == (PH_FRINFC_MFSTD_FMT_MAX_SECT_IND_1K - \
PH_FRINFC_MFSTD_FMT_VAL_1)) \
? PH_FRINFC_MFSTD_FMT_VAL_2 \
: PH_FRINFC_MFSTD_FMT_VAL_1); \
} \
} while (0)
/*
* Complete the sector
*/
#define PH_FRINFC_MFSTD_FMT_CHK_END_OF_CARD() \
do { \
phFriNfc_MfStd_H_NdefComplSect( \
NdefSmtCrdFmt->CardType, NdefSmtCrdFmt->AddInfo.MfStdInfo.SectCompl); \
PH_FRINFC_MFSTD_FMT_CHK_SECT_ARRAY; \
if (memcompare == PH_FRINFC_MFSTD_FMT_VAL_0) { \
phFriNfc_MfStd_H_StrNdefData(NdefSmtCrdFmt); \
NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock = \
PH_FRINFC_MFSTD_FMT_VAL_1; \
NdefSmtCrdFmt->AddInfo.MfStdInfo.UpdMADBlk = \
PH_FRINFC_MFSTD_FMT_MAD_BLK_1; \
NdefSmtCrdFmt->AddInfo.MfStdInfo.AuthState = \
PH_FRINFC_MFSTD_FMT_AUTH_SCRT_KEYB; \
NdefSmtCrdFmt->State = PH_FRINFC_MFSTD_FMT_AUTH_SECT; \
Result = phFriNfc_MfStd_H_WrRdAuth(NdefSmtCrdFmt); \
} else { \
Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT, NFCSTATUS_FORMAT_ERROR); \
} \
} while (0)
void phFriNfc_MfStd_Reset(phFriNfc_sNdefSmtCrdFmt_t* NdefSmtCrdFmt);
NFCSTATUS phFriNfc_MfStd_Format(phFriNfc_sNdefSmtCrdFmt_t* NdefSmtCrdFmt,
const uint8_t* ScrtKeyB);
void phFriNfc_MfStd_Process(void* Context, NFCSTATUS Status);
#endif /* PHFRINFC_MIFSTDFMT_H */