Home | History | Annotate | Download | only in mifare
      1 /*
      2  * Copyright (C) 2015 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 /*
     18  * Mifare Standard Format implementation
     19  */
     20 
     21 #ifndef PHFRINFC_MIFSTDFORMAT_H
     22 #define PHFRINFC_MIFSTDFORMAT_H
     23 
     24 #include <phFriNfc.h>
     25 #include <phFriNfc_SmtCrdFmt.h>
     26 #include <phNfcStatus.h>
     27 #include <phNfcTypes.h>
     28 
     29 /********************* Definitions and structures *****************************/
     30 
     31 /*
     32  * Mifare standard -progress states
     33  */
     34 #define PH_FRINFC_MFSTD_FMT_RESET_INIT 0 /* Reset state */
     35 #define PH_FRINFC_MFSTD_FMT_AUTH_SECT \
     36   1                                   /* Sector authentication is in progress */
     37 #define PH_FRINFC_MFSTD_FMT_DIS_CON 2 /* Disconnect is in progress */
     38 #define PH_FRINFC_MFSTD_FMT_CON 3     /* Connect is in progress */
     39 #define PH_FRINFC_MFSTD_FMT_POLL 4    /* Poll is in progress */
     40 #define PH_FRINFC_MFSTD_FMT_RD_SECT_TR \
     41   5 /* Read sector trailer is in progress */
     42 #define PH_FRINFC_MFSTD_FMT_WR_SECT_TR \
     43   6                                  /* Write sector trailer is in progress */
     44 #define PH_FRINFC_MFSTD_FMT_WR_TLV 7 /* Write sector trailer is in progress */
     45 #define PH_FRINFC_MFSTD_FMT_WR_MAD_BLK 8  /* Write MAD is in progress */
     46 #define PH_FRINFC_MFSTD_FMT_UPD_MAD_BLK 9 /* Write MAD is in progress */
     47 
     48 /*
     49  * Mifare standard -Authenticate states
     50  */
     51 #define PH_FRINFC_MFSTD_FMT_AUTH_DEF_KEY \
     52   0 /* Trying to authenticate with the default key */
     53 #define PH_FRINFC_MFSTD_FMT_AUTH_NFC_KEY \
     54   1 /* Trying to authenticate with the MAD key */
     55 #define PH_FRINFC_MFSTD_FMT_AUTH_MAD_KEY \
     56   2 /* Trying to authenticate with the NFC forum key */
     57 #define PH_FRINFC_MFSTD_FMT_AUTH_KEYB    \
     58   3 /* Trying to authenticate with key B \
     59      */
     60 #define PH_FRINFC_MFSTD_FMT_AUTH_SCRT_KEYB \
     61   4 /* Trying to authenticate with secret key B */
     62 
     63 /*
     64  * Mifare standard - Update MAD block flag
     65  */
     66 #define PH_FRINFC_MFSTD_FMT_NOT_A_MAD_BLK 0 /* Not a MAD block */
     67 #define PH_FRINFC_MFSTD_FMT_MAD_BLK_1 1     /* MAD block number 1 */
     68 #define PH_FRINFC_MFSTD_FMT_MAD_BLK_2 2     /* MAD block number 2 */
     69 #define PH_FRINFC_MFSTD_FMT_MAD_BLK_64 \
     70   64 /* MAD block number 64 (only used for Mifare 4k card) */
     71 #define PH_FRINFC_MFSTD_FMT_MAD_BLK_65 \
     72   65 /* MAD block number 65 (only used for Mifare 4k card) */
     73 #define PH_FRINFC_MFSTD_FMT_MAD_BLK_66 \
     74   66 /* MAD block number 66 (only used for Mifare 4k card) */
     75 
     76 /*
     77  * Mifare standard - Update MAD block flag
     78  */
     79 #define PH_FRINFC_SMTCRDFMT_MSTD_MADSECT_KEYA_ACS_BIT_1K \
     80   { 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0x78, 0x77, 0x88, 0xC1 }
     81 #define PH_FRINFC_SMTCRDFMT_MSTD_MADSECT_KEYA_ACS_BIT_2K \
     82   { 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0x78, 0x77, 0x88, 0xC1 }
     83 #define PH_FRINFC_SMTCRDFMT_MSTD_MADSECT_KEYA_ACS_BIT_4K \
     84   { 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0x78, 0x77, 0x88, 0xC2 }
     85 #define PH_FRINFC_SMTCRDFMT_NFCFORUMSECT_KEYA_ACS_BIT \
     86   { 0xD3, 0xF7, 0xD3, 0xF7, 0xD3, 0xF7, 0x7F, 0x07, 0x88, 0x40 }
     87 
     88 /*
     89  * Mifare standard - Key and access bit constants
     90  */
     91 #define PH_FRINFC_MFSTD_FMT_NFC_SECT_KEYA0 0xD3 /* NFC forum sector key A */
     92 #define PH_FRINFC_MFSTD_FMT_NFC_SECT_KEYA1 0xF7 /* NFC forum sector key A */
     93 
     94 #define PH_FRINFC_MFSTD_FMT_MAD_SECT_KEYA0 0xA0 /* MAD sector key A */
     95 #define PH_FRINFC_MFSTD_FMT_MAD_SECT_KEYA1 0xA1 /* MAD sector key A */
     96 #define PH_FRINFC_MFSTD_FMT_MAD_SECT_KEYA2 0xA2 /* MAD sector key A */
     97 #define PH_FRINFC_MFSTD_FMT_MAD_SECT_KEYA3 0xA3 /* MAD sector key A */
     98 #define PH_FRINFC_MFSTD_FMT_MAD_SECT_KEYA4 0xA4 /* MAD sector key A */
     99 #define PH_FRINFC_MFSTD_FMT_MAD_SECT_KEYA5 0xA5 /* MAD sector key A */
    100 
    101 #define PH_FRINFC_MFSTD_FMT_DEFAULT_KEY 0xFF /* Default key A or B */
    102 
    103 #define PH_FRINFC_MFSTD_FMT_MAD_SECT_ACS6 0x78 /* MAD sector access bits 6 */
    104 #define PH_FRINFC_MFSTD_FMT_MAD_SECT_ACS7 0x77 /* MAD sector access bits 7 */
    105 #define PH_FRINFC_MFSTD_FMT_MAD_SECT_ACS8 0x88 /* MAD sector access bits 8 */
    106 #define PH_FRINFC_MFSTD_FMT_MAD_SECT_GPB 0xC1  /* MAD sector GPB */
    107 
    108 #define PH_FRINFC_MFSTD_FMT_NFC_SECT_ACS_RW6 \
    109   0x7F /* NFC forum sector access bits 6 for read write */
    110 #define PH_FRINFC_MFSTD_FMT_NFC_SECT_ACS_RW7 \
    111   0x07 /* NFC forum sector access bits 7 for read write */
    112 #define PH_FRINFC_MFSTD_FMT_NFC_SECT_ACS_RW8 \
    113   0x88 /* NFC forum sector access bits 8 for read write */
    114 #define PH_FRINFC_MFSTD_FMT_NFC_SECT_GPB_RW \
    115   0x40 /* NFC forum sector GPB for read write */
    116 
    117 #define PH_FRINFC_MFSTD_FMT_NFC_SECT_ACS_RO6 \
    118   0x07 /* NFC forum sector access bits 6 for read only */
    119 #define PH_FRINFC_MFSTD_FMT_NFC_SECT_ACS_RO7 \
    120   0x8F /* NFC forum sector access bits 7 for read only */
    121 #define PH_FRINFC_MFSTD_FMT_NFC_SECT_ACS_RO8 \
    122   0x0F /* NFC forum sector access bits 8 for read only */
    123 #define PH_FRINFC_MFSTD_FMT_NFC_SECT_GPB_R0 \
    124   0x43 /* NFC forum sector GPB for read only */
    125 
    126 /*
    127  * Enum definition contains Mifare standard values
    128  */
    129 typedef enum {
    130   PH_FRINFC_MFSTD_FMT_VAL_0,
    131   PH_FRINFC_MFSTD_FMT_VAL_1,
    132   PH_FRINFC_MFSTD_FMT_VAL_2,
    133   PH_FRINFC_MFSTD_FMT_VAL_3,
    134   PH_FRINFC_MFSTD_FMT_VAL_4,
    135   PH_FRINFC_MFSTD_FMT_VAL_5,
    136   PH_FRINFC_MFSTD_FMT_VAL_6,
    137   PH_FRINFC_MFSTD_FMT_VAL_7,
    138   PH_FRINFC_MFSTD_FMT_VAL_8,
    139   PH_FRINFC_MFSTD_FMT_VAL_9,
    140   PH_FRINFC_MFSTD_FMT_VAL_10,
    141   PH_FRINFC_MFSTD_FMT_VAL_11
    142 } phFriNfc_MfStdVal;
    143 
    144 /*
    145  * Mifare standard - NDEF information constants
    146  */
    147 #define PH_FRINFC_MFSTD_FMT_NON_NDEF_COMPL                               \
    148   0                                      /* Sector is not ndef compliant \
    149                                           */
    150 #define PH_FRINFC_MFSTD_FMT_NDEF_COMPL 1 /* Sector is ndef compliant */
    151 #define PH_FRINFC_MFSTD_FMT_NDEF_INFO1                     \
    152   0x03 /* If sector is ndef compliant, then one of the MAD \
    153          sector byte is 0x03 */
    154 #define PH_FRINFC_MFSTD_FMT_NDEF_INFO2                     \
    155   0xE1 /* If sector is ndef compliant, then one of the MAD \
    156          sector byte is 0xE1 */
    157 
    158 /*
    159  * Mifare standard - constants
    160  */
    161 #define PH_FRINFC_MFSTD_FMT_MAX_RECV_LENGTH 252 /* Maximum receive length */
    162 #define PH_FRINFC_MFSTD_FMT_WR_SEND_LENGTH 17   /* Send length for write */
    163 #define PH_FRINFC_MFSTD_FMT_MAX_SECT_IND_1K \
    164   16 /* Maximum sector index for Mifare 1k = 16 */
    165 #define PH_FRINFC_MFSTD_FMT_MAX_SECT_IND_2K \
    166   32 /* Maximum sector index for Mifare 2k = 32 */
    167 #define PH_FRINFC_MFSTD_FMT_MAX_SECT_IND_4K \
    168   40 /* Maximum sector index for Mifare 4k = 40 */
    169 #define PH_FRINFC_MFSTD_FMT_MAX_BLOCKS_1K \
    170   64 /* Maximum Number of Blocks for Mifare 1k = 64 */
    171 #define PH_FRINFC_MFSTD_FMT_MAX_BLOCKS_2K \
    172   128 /* Maximum Number of Blocks for Mifare 2k = 128 */
    173 #define PH_FRINFC_MFSTD_FMT_MAX_BLOCKS_4K \
    174   256 /* Maximum Number of Blocks for Mifare 4k = 256*/
    175 
    176 /*
    177  * Copy default keyA to send buffer
    178  */
    179 #define PH_FRINFC_MFSTD_FMT_AUTH_SEND_BUF_DEF(mem)                             \
    180   do {                                                                         \
    181     memset(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFSTD_FMT_VAL_1],             \
    182            PH_FRINFC_MFSTD_FMT_DEFAULT_KEY, PH_FRINFC_MFSTD_FMT_VAL_6);        \
    183     NdefSmtCrdFmt->Cmd.MfCmd = ((NdefSmtCrdFmt->AddInfo.MfStdInfo.AuthState == \
    184                                  PH_FRINFC_MFSTD_FMT_AUTH_DEF_KEY)             \
    185                                     ? phHal_eMifareAuthentA                    \
    186                                     : phHal_eMifareAuthentB);                  \
    187     NdefSmtCrdFmt->SendLength = PH_FRINFC_MFSTD_FMT_VAL_7;                     \
    188   } while (0)
    189 
    190 /*
    191  * NFC forum sector keyA to send buffer
    192  */
    193 #define PH_FRINFC_MFSTD_FMT_AUTH_SEND_BUF_NFCSECT_KEYA(mem)        \
    194   do {                                                             \
    195     memcpy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFSTD_FMT_VAL_1], \
    196            NdefSmtCrdFmt->AddInfo.MfStdInfo.NFCForumSect_KeyA,     \
    197            PH_FRINFC_MFSTD_FMT_VAL_6);                             \
    198     NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareAuthentA;              \
    199     NdefSmtCrdFmt->SendLength = PH_FRINFC_MFSTD_FMT_VAL_7;         \
    200   } while (0)
    201 
    202 /*
    203  * Copy MAD sector keyA to send buffer
    204  */
    205 #define PH_FRINFC_MFSTD_FMT_AUTH_SEND_BUF_MADSECT_KEYA(mem)        \
    206   do {                                                             \
    207     memcpy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFSTD_FMT_VAL_1], \
    208            NdefSmtCrdFmt->AddInfo.MfStdInfo.MADSect_KeyA,          \
    209            PH_FRINFC_MFSTD_FMT_VAL_6);                             \
    210     NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareAuthentA;              \
    211     NdefSmtCrdFmt->SendLength = PH_FRINFC_MFSTD_FMT_VAL_7;         \
    212   } while (0)
    213 
    214 /*
    215  * Copy MAD sector keyB to send buffer
    216  */
    217 #define PH_FRINFC_MFSTD_FMT_AUTH_SEND_BUF_SCRT_KEY(mem)                  \
    218   do {                                                                   \
    219     (void)memcpy(&NdefSmtCrdFmt->SendRecvBuf[PH_FRINFC_MFSTD_FMT_VAL_1], \
    220                  NdefSmtCrdFmt->AddInfo.MfStdInfo.ScrtKeyB,              \
    221                  PH_FRINFC_MFSTD_FMT_VAL_6);                             \
    222     NdefSmtCrdFmt->Cmd.MfCmd = phHal_eMifareAuthentB;                    \
    223     NdefSmtCrdFmt->SendLength = PH_FRINFC_MFSTD_FMT_VAL_7;               \
    224   } while (0)
    225 
    226 /*
    227  * Get the next block
    228  */
    229 #define PH_FRINFC_MFSTD_FMT_CUR_BLK_INC()          \
    230   NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock += \
    231       ((NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock >= 127) ? 16 : 4)
    232 
    233 /*
    234  * Get the sector index
    235  */
    236 #define PH_FRINFC_MFSTD_FMT_SECT_INDEX_CALC                                  \
    237   ((NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock >= 128)                    \
    238        ? (32 + ((NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock - 128) / 16)) \
    239        : (NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock / 4))
    240 
    241 /*
    242  * Check the sector block
    243  */
    244 #define PH_FRINFC_MFSTD_FMT_CUR_BLK_CHK                              \
    245   (((NdefSmtCrdFmt->CardType == PH_FRINFC_SMTCRDFMT_MFSTD_1K_CRD) && \
    246     (NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock >=                \
    247      PH_FRINFC_MFSTD_FMT_MAX_BLOCKS_1K)) ||                          \
    248    ((NdefSmtCrdFmt->CardType == PH_FRINFC_SMTCRDFMT_MFSTD_4K_CRD) && \
    249     (NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock >=                \
    250      PH_FRINFC_MFSTD_FMT_MAX_BLOCKS_4K)) ||                          \
    251    ((NdefSmtCrdFmt->CardType == PH_FRINFC_SMTCRDFMT_MFSTD_2K_CRD) && \
    252     (NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock >=                \
    253      PH_FRINFC_MFSTD_FMT_MAX_BLOCKS_2K)))
    254 
    255 /*
    256  * Get the next authenticate state
    257  */
    258 #define PH_FRINFC_MFSTD_FMT_NXT_AUTH_STATE()                           \
    259   do {                                                                 \
    260     switch (NdefSmtCrdFmt->AddInfo.MfStdInfo.AuthState) {              \
    261       case PH_FRINFC_MFSTD_FMT_AUTH_DEF_KEY: {                         \
    262         NdefSmtCrdFmt->AddInfo.MfStdInfo.AuthState = (uint8_t)(        \
    263             (((NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock <= 3) ||  \
    264               ((NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock > 63) && \
    265                (NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock < 67)))) \
    266                 ? PH_FRINFC_MFSTD_FMT_AUTH_MAD_KEY                     \
    267                 : PH_FRINFC_MFSTD_FMT_AUTH_NFC_KEY);                   \
    268       } break;                                                         \
    269       case PH_FRINFC_MFSTD_FMT_AUTH_NFC_KEY: {                         \
    270         NdefSmtCrdFmt->AddInfo.MfStdInfo.AuthState =                   \
    271             PH_FRINFC_MFSTD_FMT_AUTH_KEYB;                             \
    272       } break;                                                         \
    273       case PH_FRINFC_MFSTD_FMT_AUTH_MAD_KEY: {                         \
    274         NdefSmtCrdFmt->AddInfo.MfStdInfo.AuthState =                   \
    275             PH_FRINFC_MFSTD_FMT_AUTH_NFC_KEY;                          \
    276       } break;                                                         \
    277       case PH_FRINFC_MFSTD_FMT_AUTH_KEYB: {                            \
    278         NdefSmtCrdFmt->AddInfo.MfStdInfo.AuthState =                   \
    279             PH_FRINFC_MFSTD_FMT_AUTH_SCRT_KEYB;                        \
    280       } break;                                                         \
    281       case PH_FRINFC_MFSTD_FMT_AUTH_SCRT_KEYB:                         \
    282       default: {                                                       \
    283         NdefSmtCrdFmt->AddInfo.MfStdInfo.AuthState =                   \
    284             PH_FRINFC_MFSTD_FMT_AUTH_DEF_KEY;                          \
    285       } break;                                                         \
    286     }                                                                  \
    287   } while (0)
    288 
    289 /*
    290  * Increment the sector index
    291  */
    292 #define PH_FRINFC_MFSTD_FMT_INCR_SECT                                         \
    293   do {                                                                        \
    294     SectIndex++;                                                              \
    295     SectIndex =                                                               \
    296         (uint8_t)((SectIndex == 16) ? (SectIndex + PH_FRINFC_MFSTD_FMT_VAL_1) \
    297                                     : SectIndex);                             \
    298   } while (0)
    299 
    300 /*
    301  * Increment the sector index
    302  */
    303 #define PH_FRINFC_MFSTD_FMT_CHK_SECT_ARRAY                                \
    304   do {                                                                    \
    305     while ((index < PH_FRINFC_MFSTD_FMT_MAX_SECT_IND_4K) &&               \
    306            (memcompare != PH_FRINFC_MFSTD_FMT_VAL_0)) {                   \
    307       /* Compare any one among the sectors is NDEF COMPLIANT */           \
    308       memcompare = (uint32_t)phFriNfc_MfStd_MemCompare(                   \
    309           &Buffer[PH_FRINFC_MFSTD_FMT_VAL_0],                             \
    310           &NdefSmtCrdFmt->AddInfo.MfStdInfo.SectCompl[index],             \
    311           PH_FRINFC_MFSTD_FMT_VAL_1);                                     \
    312       /* increment the index */                                           \
    313       index += (uint8_t)((index == (PH_FRINFC_MFSTD_FMT_MAX_SECT_IND_1K - \
    314                                     PH_FRINFC_MFSTD_FMT_VAL_1))           \
    315                              ? PH_FRINFC_MFSTD_FMT_VAL_2                  \
    316                              : PH_FRINFC_MFSTD_FMT_VAL_1);                \
    317     }                                                                     \
    318   } while (0)
    319 
    320 /*
    321  * Complete the sector
    322  */
    323 #define PH_FRINFC_MFSTD_FMT_CHK_END_OF_CARD()                                  \
    324   do {                                                                         \
    325     phFriNfc_MfStd_H_NdefComplSect(                                            \
    326         NdefSmtCrdFmt->CardType, NdefSmtCrdFmt->AddInfo.MfStdInfo.SectCompl);  \
    327     PH_FRINFC_MFSTD_FMT_CHK_SECT_ARRAY;                                        \
    328     if (memcompare == PH_FRINFC_MFSTD_FMT_VAL_0) {                             \
    329       phFriNfc_MfStd_H_StrNdefData(NdefSmtCrdFmt);                             \
    330       NdefSmtCrdFmt->AddInfo.MfStdInfo.CurrentBlock =                          \
    331           PH_FRINFC_MFSTD_FMT_VAL_1;                                           \
    332       NdefSmtCrdFmt->AddInfo.MfStdInfo.UpdMADBlk =                             \
    333           PH_FRINFC_MFSTD_FMT_MAD_BLK_1;                                       \
    334       NdefSmtCrdFmt->AddInfo.MfStdInfo.AuthState =                             \
    335           PH_FRINFC_MFSTD_FMT_AUTH_SCRT_KEYB;                                  \
    336       NdefSmtCrdFmt->State = PH_FRINFC_MFSTD_FMT_AUTH_SECT;                    \
    337       Result = phFriNfc_MfStd_H_WrRdAuth(NdefSmtCrdFmt);                       \
    338     } else {                                                                   \
    339       Result = PHNFCSTVAL(CID_FRI_NFC_NDEF_SMTCRDFMT, NFCSTATUS_FORMAT_ERROR); \
    340     }                                                                          \
    341   } while (0)
    342 
    343 void phFriNfc_MfStd_Reset(phFriNfc_sNdefSmtCrdFmt_t* NdefSmtCrdFmt);
    344 NFCSTATUS phFriNfc_MfStd_Format(phFriNfc_sNdefSmtCrdFmt_t* NdefSmtCrdFmt,
    345                                 const uint8_t* ScrtKeyB);
    346 void phFriNfc_MfStd_Process(void* Context, NFCSTATUS Status);
    347 
    348 #endif /* PHFRINFC_MIFSTDFMT_H */
    349