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