}
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",
sprint_hex(mfData, mfDataLen),
- "",
+ (crcc == 0 ? "!crc" : (crcc == 1 ? " ok " : " ")),
(true) ? explanation : "");
};
masNt,
masNrAr,
masAt,
+ masAuthComplete,
masFirstData,
masData,
- masDataNested,
masError,
};
static enum MifareAuthSeq MifareAuthState;
{
switch(MifareAuthState) {
case masNone:
- case masFirstData:
- case masData:
- case masDataNested:
case masError:
return iso14443A_CRC_check(isResponse, data, len);
default:
case masAt:
if (cmdsize == 4 && isResponse) {
snprintf(exp,size,"AUTH: at (enc)");
- MifareAuthState = masFirstData;
+ MifareAuthState = masAuthComplete;
AuthData.at_enc = bytes_to_num(cmd, 4);
AuthData.at_enc_par = parity[0];
return;
break;
}
- if (!isResponse)
+ if (!isResponse && ((MifareAuthState == masNone) || (MifareAuthState == masError)))
annotateIso14443a(exp, size, cmd, cmdsize);
}
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;
+ if (MifareAuthState == masAuthComplete) {
+ if (traceCrypto1) {
+ crypto1_destroy(traceCrypto1);
+ }
+
+ MifareAuthState = masFirstData;
+ return false;
+ }
+
if (cmdsize > 32)
return false;
uint64_t lfsr = 0;
crypto1_get_lfsr(revstate, &lfsr);
crypto1_destroy(revstate);
-// LastKey = lfsr;
+ mfLastKey = lfsr;
PrintAndLog(" | * | key | probable key:%x%x Prng:%s ks2:%08x ks3:%08x | |",
(unsigned int)((lfsr & 0xFFFFFFFF00000000) >> 32), (unsigned int)(lfsr & 0xFFFFFFFF),
validate_prng_nonce(AuthData.nt) ? "WEAK": "HARD",
ks3);
AuthData.first_auth = false;
+
+ traceCrypto1 = lfsr_recovery64(ks2, ks3);
} else {
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;
- 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;
#include <stdint.h>\r
#include <stdbool.h>\r
#include "data.h"\r
+#include "crapto1/crapto1.h"\r
\r
// defaults\r
// timeout in units. (ms * 106)/10 or us*0.0106\r
extern int mfCIdentify();\r
extern int DetectClassicPrng(void);\r
extern bool validate_prng_nonce(uint32_t nonce);\r
+extern void mf_crypto1_decrypt(struct Crypto1State *pcs, uint8_t *data, int len, bool isEncrypted);\r
\r
#endif\r