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