hf list mf 1st auth works

This commit is contained in:
Oleg Moiseenko 2018-02-10 22:33:32 +02:00
commit 747885a6ed
3 changed files with 44 additions and 12 deletions

View file

@ -434,11 +434,15 @@ uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, ui
} }
if (DecodeMifareData(frame, data_len, isResponse, mfData, &mfDataLen)) { if (DecodeMifareData(frame, data_len, isResponse, mfData, &mfDataLen)) {
annotateIso14443a(explanation, sizeof(explanation), mfData, mfDataLen); memset(explanation, 0x00, sizeof(explanation));
if (!isResponse) {
explanation[0] = '>';
annotateIso14443a(&explanation[1], sizeof(explanation) - 1, mfData, mfDataLen);
}
uint8_t crcc = iso14443A_CRC_check(isResponse, mfData, mfDataLen);
PrintAndLog(" | * | dec |%-64s | %-4s| %s", PrintAndLog(" | * | dec |%-64s | %-4s| %s",
sprint_hex(mfData, mfDataLen), sprint_hex(mfData, mfDataLen),
"", (crcc == 0 ? "!crc" : (crcc == 1 ? " ok " : " ")),
(true) ? explanation : ""); (true) ? explanation : "");
}; };

View file

@ -30,9 +30,9 @@ enum MifareAuthSeq {
masNt, masNt,
masNrAr, masNrAr,
masAt, masAt,
masAuthComplete,
masFirstData, masFirstData,
masData, masData,
masDataNested,
masError, masError,
}; };
static enum MifareAuthSeq MifareAuthState; static enum MifareAuthSeq MifareAuthState;
@ -73,9 +73,6 @@ uint8_t mifare_CRC_check(bool isResponse, uint8_t* data, uint8_t len)
{ {
switch(MifareAuthState) { switch(MifareAuthState) {
case masNone: case masNone:
case masFirstData:
case masData:
case masDataNested:
case masError: case masError:
return iso14443A_CRC_check(isResponse, data, len); return iso14443A_CRC_check(isResponse, data, len);
default: default:
@ -231,7 +228,7 @@ void annotateMifare(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize, uint8
case masAt: case masAt:
if (cmdsize == 4 && isResponse) { if (cmdsize == 4 && isResponse) {
snprintf(exp,size,"AUTH: at (enc)"); snprintf(exp,size,"AUTH: at (enc)");
MifareAuthState = masFirstData; MifareAuthState = masAuthComplete;
AuthData.at_enc = bytes_to_num(cmd, 4); AuthData.at_enc = bytes_to_num(cmd, 4);
AuthData.at_enc_par = parity[0]; AuthData.at_enc_par = parity[0];
return; return;
@ -243,14 +240,26 @@ void annotateMifare(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize, uint8
break; break;
} }
if (!isResponse) if (!isResponse && ((MifareAuthState == masNone) || (MifareAuthState == masError)))
annotateIso14443a(exp, size, cmd, cmdsize); annotateIso14443a(exp, size, cmd, cmdsize);
} }
bool DecodeMifareData(uint8_t *cmd, uint8_t cmdsize, bool isResponse, uint8_t *mfData, size_t *mfDataLen) { bool DecodeMifareData(uint8_t *cmd, uint8_t cmdsize, bool isResponse, uint8_t *mfData, size_t *mfDataLen) {
static struct Crypto1State *traceCrypto1;
uint64_t mfLastKey;
*mfDataLen = 0; *mfDataLen = 0;
if (MifareAuthState == masAuthComplete) {
if (traceCrypto1) {
crypto1_destroy(traceCrypto1);
}
MifareAuthState = masFirstData;
return false;
}
if (cmdsize > 32) if (cmdsize > 32)
return false; return false;
@ -267,7 +276,7 @@ bool DecodeMifareData(uint8_t *cmd, uint8_t cmdsize, bool isResponse, uint8_t *m
uint64_t lfsr = 0; uint64_t lfsr = 0;
crypto1_get_lfsr(revstate, &lfsr); crypto1_get_lfsr(revstate, &lfsr);
crypto1_destroy(revstate); crypto1_destroy(revstate);
// LastKey = lfsr; mfLastKey = lfsr;
PrintAndLog(" | * | key | probable key:%x%x Prng:%s ks2:%08x ks3:%08x | |", PrintAndLog(" | * | key | probable key:%x%x Prng:%s ks2:%08x ks3:%08x | |",
(unsigned int)((lfsr & 0xFFFFFFFF00000000) >> 32), (unsigned int)(lfsr & 0xFFFFFFFF), (unsigned int)((lfsr & 0xFFFFFFFF00000000) >> 32), (unsigned int)(lfsr & 0xFFFFFFFF),
validate_prng_nonce(AuthData.nt) ? "WEAK": "HARD", validate_prng_nonce(AuthData.nt) ? "WEAK": "HARD",
@ -275,17 +284,34 @@ bool DecodeMifareData(uint8_t *cmd, uint8_t cmdsize, bool isResponse, uint8_t *m
ks3); ks3);
AuthData.first_auth = false; AuthData.first_auth = false;
traceCrypto1 = lfsr_recovery64(ks2, ks3);
} else { } else {
printf("uid:%x nt:%x ar_enc:%x at_enc:%x\n", AuthData.uid, AuthData.nt, AuthData.ar_enc, AuthData.at_enc); printf("uid:%x nt:%x ar_enc:%x at_enc:%x\n", AuthData.uid, AuthData.nt, AuthData.ar_enc, AuthData.at_enc);
// check last used key
if (mfLastKey) {
}
// check default keys
// nested
if (validate_prng_nonce(AuthData.nt)) {
}
//hardnested
} }
MifareAuthState = masData; MifareAuthState = masData;
return true;
} }
if (MifareAuthState == masData) { if (MifareAuthState == masData && traceCrypto1) {
memcpy(mfData, cmd, cmdsize);
mf_crypto1_decrypt(traceCrypto1, mfData, cmdsize, 0);
*mfDataLen = cmdsize;
} }
return *mfDataLen > 0; return *mfDataLen > 0;

View file

@ -14,6 +14,7 @@
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
#include "data.h" #include "data.h"
#include "crapto1/crapto1.h"
// defaults // defaults
// timeout in units. (ms * 106)/10 or us*0.0106 // timeout in units. (ms * 106)/10 or us*0.0106
@ -62,5 +63,6 @@ extern int tryDecryptWord(uint32_t nt, uint32_t ar_enc, uint32_t at_enc, uint8_t
extern int mfCIdentify(); extern int mfCIdentify();
extern int DetectClassicPrng(void); extern int DetectClassicPrng(void);
extern bool validate_prng_nonce(uint32_t nonce); extern bool validate_prng_nonce(uint32_t nonce);
extern void mf_crypto1_decrypt(struct Crypto1State *pcs, uint8_t *data, int len, bool isEncrypted);
#endif #endif