1 //-----------------------------------------------------------------------------
2 // Copyright (C) Merlok - 2017
4 // This code is licensed to you under the terms of the GNU GPL, version 2 or,
5 // at your option, any later version. See the LICENSE.txt file for the text of
7 //-----------------------------------------------------------------------------
8 // Command: hf mf list. It shows data from arm buffer.
9 //-----------------------------------------------------------------------------
11 #include "cmdhflist.h"
21 #include "iso14443crc.h"
23 #include "protocols.h"
24 #include "crapto1/crapto1.h"
25 #include "mifarehost.h"
38 static enum MifareAuthSeq MifareAuthState
;
39 static TAuthData AuthData
;
41 void ClearAuthData() {
44 AuthData
.first_auth
= true;
48 * @brief iso14443A_CRC_check Checks CRC in command or response
52 * @return 0 : CRC-command, CRC not ok
53 * 1 : CRC-command, CRC ok
56 uint8_t iso14443A_CRC_check(bool isResponse
, uint8_t* data
, uint8_t len
)
60 if(len
<= 2) return 2;
62 if(isResponse
& (len
< 6)) return 2;
64 ComputeCrc14443(CRC_14443_A
, data
, len
-2, &b1
, &b2
);
65 if (b1
!= data
[len
-2] || b2
!= data
[len
-1]) {
72 uint8_t mifare_CRC_check(bool isResponse
, uint8_t* data
, uint8_t len
)
74 switch(MifareAuthState
) {
77 return iso14443A_CRC_check(isResponse
, data
, len
);
83 void annotateIso14443a(char *exp
, size_t size
, uint8_t* cmd
, uint8_t cmdsize
)
87 case ISO14443A_CMD_WUPA
:
88 snprintf(exp
,size
,"WUPA");
89 MifareAuthState
= masNone
;
91 case ISO14443A_CMD_ANTICOLL_OR_SELECT
:{
92 // 93 20 = Anticollision (usage: 9320 - answer: 4bytes UID+1byte UID-bytes-xor)
93 // 93 70 = Select (usage: 9370+5bytes 9320 answer - answer: 1byte SAK)
96 snprintf(exp
,size
,"SELECT_UID"); break;
99 snprintf(exp
,size
,"ANTICOLL"); break;
102 case ISO14443A_CMD_ANTICOLL_OR_SELECT_2
:{
103 //95 20 = Anticollision of cascade level2
104 //95 70 = Select of cascade level2
107 snprintf(exp
,size
,"SELECT_UID-2"); break;
110 snprintf(exp
,size
,"ANTICOLL-2"); break;
113 case ISO14443A_CMD_REQA
:
114 snprintf(exp
,size
,"REQA");
115 MifareAuthState
= masNone
;
117 case ISO14443A_CMD_READBLOCK
: snprintf(exp
,size
,"READBLOCK(%d)",cmd
[1]); break;
118 case ISO14443A_CMD_WRITEBLOCK
: snprintf(exp
,size
,"WRITEBLOCK(%d)",cmd
[1]); break;
119 case ISO14443A_CMD_HALT
:
120 snprintf(exp
,size
,"HALT");
121 MifareAuthState
= masNone
;
123 case ISO14443A_CMD_RATS
: snprintf(exp
,size
,"RATS"); break;
124 case MIFARE_CMD_INC
: snprintf(exp
,size
,"INC(%d)",cmd
[1]); break;
125 case MIFARE_CMD_DEC
: snprintf(exp
,size
,"DEC(%d)",cmd
[1]); break;
126 case MIFARE_CMD_RESTORE
: snprintf(exp
,size
,"RESTORE(%d)",cmd
[1]); break;
127 case MIFARE_CMD_TRANSFER
: snprintf(exp
,size
,"TRANSFER(%d)",cmd
[1]); break;
128 case MIFARE_AUTH_KEYA
:
130 snprintf(exp
,size
,"AUTH-A(%d)",cmd
[1]);
131 MifareAuthState
= masNt
;
133 // case MIFARE_ULEV1_VERSION : both 0x60.
134 snprintf(exp
,size
,"EV1 VERSION");
137 case MIFARE_AUTH_KEYB
:
138 MifareAuthState
= masNt
;
139 snprintf(exp
,size
,"AUTH-B(%d)",cmd
[1]);
141 case MIFARE_MAGICWUPC1
: snprintf(exp
,size
,"MAGIC WUPC1"); break;
142 case MIFARE_MAGICWUPC2
: snprintf(exp
,size
,"MAGIC WUPC2"); break;
143 case MIFARE_MAGICWIPEC
: snprintf(exp
,size
,"MAGIC WIPEC"); break;
144 case MIFARE_ULC_AUTH_1
: snprintf(exp
,size
,"AUTH "); break;
145 case MIFARE_ULC_AUTH_2
: snprintf(exp
,size
,"AUTH_ANSW"); break;
146 case MIFARE_ULEV1_AUTH
:
148 snprintf(exp
,size
,"PWD-AUTH KEY: 0x%02x%02x%02x%02x", cmd
[1], cmd
[2], cmd
[3], cmd
[4] );
150 snprintf(exp
,size
,"PWD-AUTH");
152 case MIFARE_ULEV1_FASTREAD
:{
153 if ( cmdsize
>=3 && cmd
[2] <= 0xE6)
154 snprintf(exp
,size
,"READ RANGE (%d-%d)",cmd
[1],cmd
[2]);
156 snprintf(exp
,size
,"?");
159 case MIFARE_ULC_WRITE
:{
161 snprintf(exp
,size
,"WRITEBLOCK(%d)",cmd
[1]);
163 snprintf(exp
,size
,"?");
166 case MIFARE_ULEV1_READ_CNT
:{
168 snprintf(exp
,size
,"READ CNT(%d)",cmd
[1]);
170 snprintf(exp
,size
,"?");
173 case MIFARE_ULEV1_INCR_CNT
:{
175 snprintf(exp
,size
,"INCR(%d)",cmd
[1]);
177 snprintf(exp
,size
,"?");
180 case MIFARE_ULEV1_READSIG
: snprintf(exp
,size
,"READ_SIG"); break;
181 case MIFARE_ULEV1_CHECKTEAR
: snprintf(exp
,size
,"CHK_TEARING(%d)",cmd
[1]); break;
182 case MIFARE_ULEV1_VCSL
: snprintf(exp
,size
,"VCSL"); break;
183 default: snprintf(exp
,size
,"?"); break;
188 void annotateMifare(char *exp
, size_t size
, uint8_t* cmd
, uint8_t cmdsize
, uint8_t* parity
, uint8_t paritysize
, bool isResponse
) {
190 if (MifareAuthState
== masNone
) {
191 if (cmdsize
== 9 && cmd
[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT
&& cmd
[1] == 0x70) {
193 AuthData
.uid
= bytes_to_num(&cmd
[2], 4);
195 if (cmdsize
== 9 && cmd
[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2
&& cmd
[1] == 0x70) {
197 AuthData
.uid
= bytes_to_num(&cmd
[2], 4);
201 switch(MifareAuthState
) {
203 if (cmdsize
== 4 && isResponse
) {
204 snprintf(exp
,size
,"AUTH: nt %s", (AuthData
.first_auth
) ? "" : "(enc)");
205 MifareAuthState
= masNrAr
;
206 if (AuthData
.first_auth
)
207 AuthData
.nt
= bytes_to_num(cmd
, 4);
209 AuthData
.nt_enc
= bytes_to_num(cmd
, 4);
210 AuthData
.nt_enc_par
= parity
[0];
213 MifareAuthState
= masError
;
217 if (cmdsize
== 8 && !isResponse
) {
218 snprintf(exp
,size
,"AUTH: nr ar (enc)");
219 MifareAuthState
= masAt
;
220 AuthData
.nr_enc
= bytes_to_num(cmd
, 4);
221 AuthData
.ar_enc
= bytes_to_num(&cmd
[4], 4);
222 AuthData
.ar_enc_par
= parity
[0] << 4;
225 MifareAuthState
= masError
;
229 if (cmdsize
== 4 && isResponse
) {
230 snprintf(exp
,size
,"AUTH: at (enc)");
231 MifareAuthState
= masAuthComplete
;
232 AuthData
.at_enc
= bytes_to_num(cmd
, 4);
233 AuthData
.at_enc_par
= parity
[0];
236 MifareAuthState
= masError
;
243 if (!isResponse
&& ((MifareAuthState
== masNone
) || (MifareAuthState
== masError
)))
244 annotateIso14443a(exp
, size
, cmd
, cmdsize
);
248 bool DecodeMifareData(uint8_t *cmd
, uint8_t cmdsize
, bool isResponse
, uint8_t *mfData
, size_t *mfDataLen
) {
249 static struct Crypto1State
*traceCrypto1
;
254 if (MifareAuthState
== masAuthComplete
) {
256 crypto1_destroy(traceCrypto1
);
259 MifareAuthState
= masFirstData
;
266 if (MifareAuthState
== masFirstData
) {
267 if (AuthData
.first_auth
) {
268 uint32_t ks2
= AuthData
.ar_enc
^ prng_successor(AuthData
.nt
, 64);
269 uint32_t ks3
= AuthData
.at_enc
^ prng_successor(AuthData
.nt
, 96);
270 struct Crypto1State
*revstate
= lfsr_recovery64(ks2
, ks3
);
271 lfsr_rollback_word(revstate
, 0, 0);
272 lfsr_rollback_word(revstate
, 0, 0);
273 lfsr_rollback_word(revstate
, AuthData
.nr_enc
, 1);
274 lfsr_rollback_word(revstate
, AuthData
.uid
^ AuthData
.nt
, 0);
277 crypto1_get_lfsr(revstate
, &lfsr
);
278 crypto1_destroy(revstate
);
280 PrintAndLog(" | * | key | probable key:%x%x Prng:%s ks2:%08x ks3:%08x | |",
281 (unsigned int)((lfsr
& 0xFFFFFFFF00000000) >> 32), (unsigned int)(lfsr
& 0xFFFFFFFF),
282 validate_prng_nonce(AuthData
.nt
) ? "WEAK": "HARD",
286 AuthData
.first_auth
= false;
288 traceCrypto1
= lfsr_recovery64(ks2
, ks3
);
290 printf("uid:%x nt:%x ar_enc:%x at_enc:%x\n", AuthData
.uid
, AuthData
.nt
, AuthData
.ar_enc
, AuthData
.at_enc
);
292 // check last used key
297 // check default keys
300 if (validate_prng_nonce(AuthData
.nt
)) {
308 MifareAuthState
= masData
;
311 if (MifareAuthState
== masData
&& traceCrypto1
) {
312 memcpy(mfData
, cmd
, cmdsize
);
313 mf_crypto1_decrypt(traceCrypto1
, mfData
, cmdsize
, 0);
314 *mfDataLen
= cmdsize
;
317 return *mfDataLen
> 0;