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"
26 #include "mifaredefault.h"
39 static enum MifareAuthSeq MifareAuthState
;
40 static TAuthData AuthData
;
42 void ClearAuthData() {
45 AuthData
.first_auth
= true;
51 * @brief iso14443A_CRC_check Checks CRC in command or response
55 * @return 0 : CRC-command, CRC not ok
56 * 1 : CRC-command, CRC ok
59 uint8_t iso14443A_CRC_check(bool isResponse
, uint8_t* data
, uint8_t len
)
63 if(len
<= 2) return 2;
65 if(isResponse
& (len
< 6)) return 2;
67 ComputeCrc14443(CRC_14443_A
, data
, len
-2, &b1
, &b2
);
68 if (b1
!= data
[len
-2] || b2
!= data
[len
-1]) {
75 uint8_t mifare_CRC_check(bool isResponse
, uint8_t* data
, uint8_t len
)
77 switch(MifareAuthState
) {
80 return iso14443A_CRC_check(isResponse
, data
, len
);
86 void annotateIso14443a(char *exp
, size_t size
, uint8_t* cmd
, uint8_t cmdsize
)
90 case ISO14443A_CMD_WUPA
:
91 snprintf(exp
,size
,"WUPA");
93 case ISO14443A_CMD_ANTICOLL_OR_SELECT
:{
94 // 93 20 = Anticollision (usage: 9320 - answer: 4bytes UID+1byte UID-bytes-xor)
95 // 93 70 = Select (usage: 9370+5bytes 9320 answer - answer: 1byte SAK)
98 snprintf(exp
,size
,"SELECT_UID"); break;
101 snprintf(exp
,size
,"ANTICOLL"); break;
104 case ISO14443A_CMD_ANTICOLL_OR_SELECT_2
:{
105 //95 20 = Anticollision of cascade level2
106 //95 70 = Select of cascade level2
109 snprintf(exp
,size
,"SELECT_UID-2"); break;
112 snprintf(exp
,size
,"ANTICOLL-2"); break;
115 case ISO14443A_CMD_REQA
:
116 snprintf(exp
,size
,"REQA");
118 case ISO14443A_CMD_READBLOCK
: snprintf(exp
,size
,"READBLOCK(%d)",cmd
[1]); break;
119 case ISO14443A_CMD_WRITEBLOCK
: snprintf(exp
,size
,"WRITEBLOCK(%d)",cmd
[1]); break;
120 case ISO14443A_CMD_HALT
:
121 snprintf(exp
,size
,"HALT");
122 MifareAuthState
= masNone
;
124 case ISO14443A_CMD_RATS
: snprintf(exp
,size
,"RATS"); break;
125 case MIFARE_CMD_INC
: snprintf(exp
,size
,"INC(%d)",cmd
[1]); break;
126 case MIFARE_CMD_DEC
: snprintf(exp
,size
,"DEC(%d)",cmd
[1]); break;
127 case MIFARE_CMD_RESTORE
: snprintf(exp
,size
,"RESTORE(%d)",cmd
[1]); break;
128 case MIFARE_CMD_TRANSFER
: snprintf(exp
,size
,"TRANSFER(%d)",cmd
[1]); break;
129 case MIFARE_AUTH_KEYA
:
131 snprintf(exp
,size
,"AUTH-A(%d)",cmd
[1]);
132 MifareAuthState
= masNt
;
134 // case MIFARE_ULEV1_VERSION : both 0x60.
135 snprintf(exp
,size
,"EV1 VERSION");
138 case MIFARE_AUTH_KEYB
:
139 MifareAuthState
= masNt
;
140 snprintf(exp
,size
,"AUTH-B(%d)",cmd
[1]);
142 case MIFARE_MAGICWUPC1
: snprintf(exp
,size
,"MAGIC WUPC1"); break;
143 case MIFARE_MAGICWUPC2
: snprintf(exp
,size
,"MAGIC WUPC2"); break;
144 case MIFARE_MAGICWIPEC
: snprintf(exp
,size
,"MAGIC WIPEC"); break;
145 case MIFARE_ULC_AUTH_1
: snprintf(exp
,size
,"AUTH "); break;
146 case MIFARE_ULC_AUTH_2
: snprintf(exp
,size
,"AUTH_ANSW"); break;
147 case MIFARE_ULEV1_AUTH
:
149 snprintf(exp
,size
,"PWD-AUTH KEY: 0x%02x%02x%02x%02x", cmd
[1], cmd
[2], cmd
[3], cmd
[4] );
151 snprintf(exp
,size
,"PWD-AUTH");
153 case MIFARE_ULEV1_FASTREAD
:{
154 if ( cmdsize
>=3 && cmd
[2] <= 0xE6)
155 snprintf(exp
,size
,"READ RANGE (%d-%d)",cmd
[1],cmd
[2]);
157 snprintf(exp
,size
,"?");
160 case MIFARE_ULC_WRITE
:{
162 snprintf(exp
,size
,"WRITEBLOCK(%d)",cmd
[1]);
164 snprintf(exp
,size
,"?");
167 case MIFARE_ULEV1_READ_CNT
:{
169 snprintf(exp
,size
,"READ CNT(%d)",cmd
[1]);
171 snprintf(exp
,size
,"?");
174 case MIFARE_ULEV1_INCR_CNT
:{
176 snprintf(exp
,size
,"INCR(%d)",cmd
[1]);
178 snprintf(exp
,size
,"?");
181 case MIFARE_ULEV1_READSIG
: snprintf(exp
,size
,"READ_SIG"); break;
182 case MIFARE_ULEV1_CHECKTEAR
: snprintf(exp
,size
,"CHK_TEARING(%d)",cmd
[1]); break;
183 case MIFARE_ULEV1_VCSL
: snprintf(exp
,size
,"VCSL"); break;
184 default: snprintf(exp
,size
,"?"); break;
189 void annotateMifare(char *exp
, size_t size
, uint8_t* cmd
, uint8_t cmdsize
, uint8_t* parity
, uint8_t paritysize
, bool isResponse
) {
190 if (!isResponse
&& cmdsize
== 1) {
192 case ISO14443A_CMD_WUPA
:
193 case ISO14443A_CMD_REQA
:
194 MifareAuthState
= masNone
;
202 if (MifareAuthState
== masNone
) {
203 if (cmdsize
== 9 && cmd
[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT
&& cmd
[1] == 0x70) {
205 AuthData
.uid
= bytes_to_num(&cmd
[2], 4);
207 if (cmdsize
== 9 && cmd
[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2
&& cmd
[1] == 0x70) {
209 AuthData
.uid
= bytes_to_num(&cmd
[2], 4);
213 switch(MifareAuthState
) {
215 if (cmdsize
== 4 && isResponse
) {
216 snprintf(exp
,size
,"AUTH: nt %s", (AuthData
.first_auth
) ? "" : "(enc)");
217 MifareAuthState
= masNrAr
;
218 if (AuthData
.first_auth
)
219 AuthData
.nt
= bytes_to_num(cmd
, 4);
221 AuthData
.nt_enc
= bytes_to_num(cmd
, 4);
222 AuthData
.nt_enc_par
= parity
[0];
225 MifareAuthState
= masError
;
229 if (cmdsize
== 8 && !isResponse
) {
230 snprintf(exp
,size
,"AUTH: nr ar (enc)");
231 MifareAuthState
= masAt
;
232 AuthData
.nr_enc
= bytes_to_num(cmd
, 4);
233 AuthData
.ar_enc
= bytes_to_num(&cmd
[4], 4);
234 AuthData
.ar_enc_par
= parity
[0] << 4;
237 MifareAuthState
= masError
;
241 if (cmdsize
== 4 && isResponse
) {
242 snprintf(exp
,size
,"AUTH: at (enc)");
243 MifareAuthState
= masAuthComplete
;
244 AuthData
.at_enc
= bytes_to_num(cmd
, 4);
245 AuthData
.at_enc_par
= parity
[0];
248 MifareAuthState
= masError
;
255 if (!isResponse
&& ((MifareAuthState
== masNone
) || (MifareAuthState
== masError
)))
256 annotateIso14443a(exp
, size
, cmd
, cmdsize
);
260 bool DecodeMifareData(uint8_t *cmd
, uint8_t cmdsize
, uint8_t *parity
, bool isResponse
, uint8_t *mfData
, size_t *mfDataLen
) {
261 static struct Crypto1State
*traceCrypto1
;
262 static uint64_t mfLastKey
;
266 if (MifareAuthState
== masAuthComplete
) {
268 crypto1_destroy(traceCrypto1
);
272 MifareAuthState
= masFirstData
;
279 if (MifareAuthState
== masFirstData
) {
280 if (AuthData
.first_auth
) {
281 AuthData
.ks2
= AuthData
.ar_enc
^ prng_successor(AuthData
.nt
, 64);
282 AuthData
.ks3
= AuthData
.at_enc
^ prng_successor(AuthData
.nt
, 96);
284 mfLastKey
= GetCrypto1ProbableKey(&AuthData
);
285 PrintAndLog(" | * | key | probable key:%010"PRIx64
" Prng:%s ks2:%08x ks3:%08x | |",
287 validate_prng_nonce(AuthData
.nt
) ? "WEAK": "HARD",
291 AuthData
.first_auth
= false;
293 traceCrypto1
= lfsr_recovery64(AuthData
.ks2
, AuthData
.ks3
);
296 crypto1_destroy(traceCrypto1
);
300 // check last used key
301 if (false && mfLastKey
) {
302 if (NestedCheckKey(mfLastKey
, &AuthData
, cmd
, cmdsize
, parity
)) {
303 PrintAndLog(" | * | key | last used key:%010"PRIx64
" ks2:%08x ks3:%08x | |",
308 traceCrypto1
= lfsr_recovery64(AuthData
.ks2
, AuthData
.ks3
);
312 // check default keys
313 if (false && !traceCrypto1
) {
314 for (int defaultKeyCounter
= 0; defaultKeyCounter
< MifareDefaultKeysSize
; defaultKeyCounter
++){
315 if (NestedCheckKey(MifareDefaultKeys
[defaultKeyCounter
], &AuthData
, cmd
, cmdsize
, parity
)) {
316 PrintAndLog(" | * | key | default key:%010"PRIx64
" ks2:%08x ks3:%08x | |",
317 MifareDefaultKeys
[defaultKeyCounter
],
321 mfLastKey
= MifareDefaultKeys
[defaultKeyCounter
];
322 traceCrypto1
= lfsr_recovery64(AuthData
.ks2
, AuthData
.ks3
);
329 if (!traceCrypto1
&& validate_prng_nonce(AuthData
.nt
)) {
330 uint32_t ntx
= prng_successor(AuthData
.nt
, 90);
331 for (int i
= 0; i
< 16383; i
++) {
332 ntx
= prng_successor(ntx
, 1);
333 if (NTParityChk(&AuthData
, ntx
)){
335 uint32_t ks2
= AuthData
.ar_enc
^ prng_successor(ntx
, 64);
336 uint32_t ks3
= AuthData
.at_enc
^ prng_successor(ntx
, 96);
337 struct Crypto1State
*pcs
= lfsr_recovery64(ks2
, ks3
);
338 memcpy(mfData
, cmd
, cmdsize
);
339 mf_crypto1_decrypt(pcs
, mfData
, cmdsize
, 0);
341 crypto1_destroy(pcs
);
342 if (CheckCrypto1Parity(cmd
, cmdsize
, mfData
, parity
) && CheckCrc14443(CRC_14443_A
, mfData
, cmdsize
)) {
347 mfLastKey
= GetCrypto1ProbableKey(&AuthData
);
348 PrintAndLog(" | * | key | nested probable key:%010"PRIx64
" ks2:%08x ks3:%08x | |",
353 traceCrypto1
= lfsr_recovery64(AuthData
.ks2
, AuthData
.ks3
);
362 printf("hardnested not implemented. uid:%x nt:%x ar_enc:%x at_enc:%x\n", AuthData
.uid
, AuthData
.nt
, AuthData
.ar_enc
, AuthData
.at_enc
);
368 MifareAuthState
= masData
;
371 if (MifareAuthState
== masData
&& traceCrypto1
) {
372 memcpy(mfData
, cmd
, cmdsize
);
373 mf_crypto1_decrypt(traceCrypto1
, mfData
, cmdsize
, 0);
374 *mfDataLen
= cmdsize
;
377 return *mfDataLen
> 0;
380 bool NTParityChk(TAuthData
*ad
, uint32_t ntx
) {
382 (oddparity8(ntx
>> 8 & 0xff) ^ (ntx
& 0x01) ^ ((ad
->nt_enc_par
>> 5) & 0x01) ^ (ad
->nt_enc
& 0x01)) ||
383 (oddparity8(ntx
>> 16 & 0xff) ^ (ntx
>> 8 & 0x01) ^ ((ad
->nt_enc_par
>> 6) & 0x01) ^ (ad
->nt_enc
>> 8 & 0x01)) ||
384 (oddparity8(ntx
>> 24 & 0xff) ^ (ntx
>> 16 & 0x01) ^ ((ad
->nt_enc_par
>> 7) & 0x01) ^ (ad
->nt_enc
>> 16 & 0x01))
388 uint32_t ar
= prng_successor(ntx
, 64);
390 (oddparity8(ar
>> 8 & 0xff) ^ (ar
& 0x01) ^ ((ad
->ar_enc_par
>> 5) & 0x01) ^ (ad
->ar_enc
& 0x01)) ||
391 (oddparity8(ar
>> 16 & 0xff) ^ (ar
>> 8 & 0x01) ^ ((ad
->ar_enc_par
>> 6) & 0x01) ^ (ad
->ar_enc
>> 8 & 0x01)) ||
392 (oddparity8(ar
>> 24 & 0xff) ^ (ar
>> 16 & 0x01) ^ ((ad
->ar_enc_par
>> 7) & 0x01) ^ (ad
->ar_enc
>> 16 & 0x01))
396 uint32_t at
= prng_successor(ntx
, 96);
398 (oddparity8(ar
& 0xff) ^ (at
>> 24 & 0x01) ^ ((ad
->ar_enc_par
>> 4) & 0x01) ^ (ad
->at_enc
>> 24 & 0x01)) ||
399 (oddparity8(at
>> 8 & 0xff) ^ (at
& 0x01) ^ ((ad
->at_enc_par
>> 5) & 0x01) ^ (ad
->at_enc
& 0x01)) ||
400 (oddparity8(at
>> 16 & 0xff) ^ (at
>> 8 & 0x01) ^ ((ad
->at_enc_par
>> 6) & 0x01) ^ (ad
->at_enc
>> 8 & 0x01)) ||
401 (oddparity8(at
>> 24 & 0xff) ^ (at
>> 16 & 0x01) ^ ((ad
->at_enc_par
>> 7) & 0x01) ^ (ad
->at_enc
>> 16 & 0x01))
408 bool NestedCheckKey(uint64_t key
, TAuthData
*ad
, uint8_t *cmd
, uint8_t cmdsize
, uint8_t *parity
) {
409 uint8_t buf
[32] = {0};
410 struct Crypto1State
*pcs
;
415 pcs
= crypto1_create(key
);
416 uint32_t nt1
= crypto1_word(pcs
, ad
->nt_enc
^ ad
->uid
, 1) ^ ad
->nt_enc
;
417 uint32_t ar
= prng_successor(nt1
, 64);
418 uint32_t at
= prng_successor(nt1
, 96);
420 crypto1_word(pcs
, ad
->nr_enc
, 1);
421 // uint32_t nr1 = crypto1_word(pcs, ad->nr_enc, 1) ^ ad->nr_enc; // if needs deciphered nr
422 uint32_t ar1
= crypto1_word(pcs
, 0, 0) ^ ad
->ar_enc
;
423 uint32_t at1
= crypto1_word(pcs
, 0, 0) ^ ad
->at_enc
;
425 if (!(ar
== ar1
&& at
== at1
&& NTParityChk(ad
, nt1
)))
428 memcpy(buf
, cmd
, cmdsize
);
429 mf_crypto1_decrypt(pcs
, buf
, cmdsize
, 0);
431 crypto1_destroy(pcs
);
433 if (!CheckCrypto1Parity(cmd
, cmdsize
, buf
, parity
))
436 if(!CheckCrc14443(CRC_14443_A
, buf
, cmdsize
))
440 AuthData
.ks2
= AuthData
.ar_enc
^ ar
;
441 AuthData
.ks3
= AuthData
.at_enc
^ at
;
446 bool CheckCrypto1Parity(uint8_t *cmd_enc
, uint8_t cmdsize
, uint8_t *cmd
, uint8_t *parity_enc
) {
447 for (int i
= 0; i
< cmdsize
- 1; i
++) {
448 if (oddparity8(cmd
[i
]) ^ (cmd
[i
+ 1] & 0x01) ^ ((parity_enc
[i
/ 8] >> (7 - i
% 8)) & 0x01) ^ (cmd_enc
[i
+ 1] & 0x01))
455 uint64_t GetCrypto1ProbableKey(TAuthData
*ad
) {
456 struct Crypto1State
*revstate
= lfsr_recovery64(ad
->ks2
, ad
->ks3
);
457 lfsr_rollback_word(revstate
, 0, 0);
458 lfsr_rollback_word(revstate
, 0, 0);
459 lfsr_rollback_word(revstate
, ad
->nr_enc
, 1);
460 lfsr_rollback_word(revstate
, ad
->uid
^ ad
->nt
, 0);
463 crypto1_get_lfsr(revstate
, &lfsr
);
464 crypto1_destroy(revstate
);