mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2026-05-12 11:18:11 -07:00
code style, code clean up of redundant functions, comments, its many minor fixes across the platform. Sorry for not making 20 commits
This commit is contained in:
@@ -45,6 +45,13 @@ jobs:
|
||||
- name: Install dependencies
|
||||
run: sudo apt-get install -yqq make autoconf build-essential ca-certificates pkg-config libreadline-dev gcc-arm-none-eabi libnewlib-dev qtbase5-dev libbz2-dev liblz4-dev libbluetooth-dev libpython3-dev python3 python3-dev libpython3-all-dev liblua5.4-dev liblua5.4-0 lua5.4 sed libssl-dev
|
||||
|
||||
- name: Install Python dependencies
|
||||
run: |
|
||||
python3 -m pip install --upgrade pip
|
||||
python3 -m pip install setuptools
|
||||
python3 -m pip install ansicolors sslcrypto
|
||||
if [ -f requirements.txt ]; then python3 -m pip install -r requirements.txt; fi
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
|
||||
+4
-2
@@ -321,9 +321,10 @@ bool RAMFUNC LogTraceBits(const uint8_t *btBytes, uint16_t bitLen, uint32_t time
|
||||
// Emulator memory
|
||||
int emlSet(const uint8_t *data, uint32_t offset, uint32_t length) {
|
||||
uint8_t *mem = BigBuf_get_EM_addr();
|
||||
if (!mem) {
|
||||
if (mem == NULL) {
|
||||
return PM3_EMALLOC;
|
||||
}
|
||||
|
||||
if (offset + length <= CARD_MEMORY_SIZE) {
|
||||
memcpy(mem + offset, data, length);
|
||||
return PM3_SUCCESS;
|
||||
@@ -335,9 +336,10 @@ int emlSet(const uint8_t *data, uint32_t offset, uint32_t length) {
|
||||
|
||||
int emlGet(uint8_t *out, uint32_t offset, uint32_t length) {
|
||||
uint8_t *mem = BigBuf_get_EM_addr();
|
||||
if (!mem) {
|
||||
if (mem == NULL) {
|
||||
return PM3_EMALLOC;
|
||||
}
|
||||
|
||||
if (offset + length <= CARD_MEMORY_SIZE) {
|
||||
memcpy(out, mem + offset, length);
|
||||
return PM3_SUCCESS;
|
||||
|
||||
@@ -311,7 +311,7 @@ void WriteTagToFlash(uint32_t uid, size_t size) {
|
||||
uint32_t len = size;
|
||||
uint8_t data[(size * (16 * 64)) / 1024];
|
||||
|
||||
emlGetMem(data, 0, (size * 64) / 1024);
|
||||
emlGetMem_xt(data, 0, (size * 64) / 1024, MIFARE_BLOCK_SIZE);
|
||||
|
||||
char dest[SPIFFS_OBJ_NAME_LEN];
|
||||
uint8_t buid[4];
|
||||
@@ -646,7 +646,7 @@ failtag:
|
||||
emlClearMem();
|
||||
uint8_t mblock[16];
|
||||
for (uint8_t sectorNo = 0; sectorNo < sectorsCnt; sectorNo++) {
|
||||
emlGetMem(mblock, FirstBlockOfSector(sectorNo) + NumBlocksPerSector(sectorNo) - 1, 1);
|
||||
emlGetMem_xt(mblock, FirstBlockOfSector(sectorNo) + NumBlocksPerSector(sectorNo) - 1, 1, MIFARE_BLOCK_SIZE);
|
||||
for (uint8_t t = 0; t < 2; t++) {
|
||||
memcpy(mblock + t * 10, foundKey[t][sectorNo], 6);
|
||||
}
|
||||
@@ -807,7 +807,7 @@ int e_MifareECardLoad(uint32_t numofsectors, uint8_t keytype) {
|
||||
emlSetMem_xt(dataoutbuf, FirstBlockOfSector(s) + blockNo, 1, 16);
|
||||
} else {
|
||||
// sector trailer, keep the keys, set only the AC
|
||||
emlGetMem(dataoutbuf2, FirstBlockOfSector(s) + blockNo, 1);
|
||||
emlGetMem_xt(dataoutbuf2, FirstBlockOfSector(s) + blockNo, 1, MIFARE_BLOCK_SIZE);
|
||||
memcpy(&dataoutbuf2[6], &dataoutbuf[6], 4);
|
||||
emlSetMem_xt(dataoutbuf2, FirstBlockOfSector(s) + blockNo, 1, 16);
|
||||
}
|
||||
@@ -878,7 +878,7 @@ void saMifareMakeTag(void) {
|
||||
int flags = 0;
|
||||
for (int blockNum = 0; blockNum < 16 * 4; blockNum++) {
|
||||
uint8_t mblock[16];
|
||||
emlGetMem(mblock, blockNum, 1);
|
||||
emlGetMem_xt(mblock, blockNum, 1, MIFARE_BLOCK_SIZE);
|
||||
// switch on field and send magic sequence
|
||||
if (blockNum == 0)
|
||||
flags = 0x08 + 0x02;
|
||||
|
||||
@@ -500,7 +500,7 @@ void RunMod(void) {
|
||||
uint8_t mblock[MIFARE_BLOCK_SIZE];
|
||||
for (uint8_t sectorNo = 0; sectorNo < sectorsCnt; ++sectorNo) {
|
||||
if (validKey[0][sectorNo] || validKey[1][sectorNo]) {
|
||||
emlGetMem(mblock, FirstBlockOfSector(sectorNo) + NumBlocksPerSector(sectorNo) - 1, 1);
|
||||
emlGetMem_xt(mblock, FirstBlockOfSector(sectorNo) + NumBlocksPerSector(sectorNo) - 1, 1, MIFARE_BLOCK_SIZE);
|
||||
for (uint8_t keyType = 0; keyType < 2; ++keyType) {
|
||||
if (validKey[keyType][sectorNo]) {
|
||||
memcpy(mblock + keyType * 10, foundKey[keyType][sectorNo], 6);
|
||||
|
||||
@@ -150,7 +150,7 @@ void RunMod(void) {
|
||||
} else if (playing && selected == 2) {
|
||||
// Now it work only with HID Corporate 1000 (35bit), but is easily extensible to others RFID.
|
||||
// It is necessary only to calculate the correct parity.
|
||||
|
||||
|
||||
// Brute force code
|
||||
// Check if the badge is an HID Corporate 1000
|
||||
if ((high[selected] & 0xFFFFFFF8) != 0x28) {
|
||||
|
||||
@@ -46,7 +46,7 @@ void RunMod(void) {
|
||||
StandAloneMode();
|
||||
Dbprintf(">> LF HID proxII bruteforce v2 a.k.a Prox2Brute Started <<");
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
|
||||
uint32_t high = 0, low = 0;
|
||||
uint32_t high = 0;
|
||||
|
||||
uint32_t fac = FACILITY_CODE, cardnum = 0;
|
||||
|
||||
@@ -78,7 +78,7 @@ void RunMod(void) {
|
||||
if (BUTTON_HELD(1000) == BUTTON_HOLD) break; // long button press (>=1sec) exit
|
||||
|
||||
// calculate the new LF low value including Card number, Facility code and checksum
|
||||
low = (cardnum << 1) | (fac << 17);
|
||||
uint32_t low = (cardnum << 1) | (fac << 17);
|
||||
low |= oddparity32((low >> 1) & 0xFFF);
|
||||
low |= evenparity32((low >> 13) & 0xFFF) << 25;
|
||||
add_HID_preamble(NULL, &high, &low, 26);
|
||||
|
||||
+45
-12
@@ -1370,7 +1370,11 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||
// involved in dealing with emulator memory. But if it is called later, it might
|
||||
// destroy the Emulator Memory.
|
||||
//-----------------------------------------------------------------------------
|
||||
EmlClearIso15693();
|
||||
// Resetting the bitstream also frees the BigBuf memory, so we do this here to prevent
|
||||
// an inconvenient reset in the future by Iso15693InitTag
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF_15);
|
||||
BigBuf_Clear_EM();
|
||||
reply_ng(CMD_HF_ISO15693_EML_CLEAR, PM3_SUCCESS, NULL, 0);
|
||||
break;
|
||||
}
|
||||
case CMD_HF_ISO15693_EML_SETMEM: {
|
||||
@@ -1402,7 +1406,7 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t *buf = BigBuf_malloc(payload->length);
|
||||
uint8_t *buf = BigBuf_calloc(payload->length);
|
||||
emlGet(buf, payload->offset, payload->length);
|
||||
LED_B_ON();
|
||||
reply_ng(CMD_HF_ISO15693_EML_GETMEM, PM3_SUCCESS, buf, payload->length);
|
||||
@@ -1677,7 +1681,7 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||
EMVsim(payload->flags, payload->exitAfter, payload->uid, payload->atqa, payload->sak);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
case CMD_HF_ISO14443A_SIMULATE: {
|
||||
struct p {
|
||||
uint8_t tagtype;
|
||||
@@ -1890,36 +1894,65 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||
break;
|
||||
}
|
||||
case CMD_HF_MIFARE_EML_MEMCLR: {
|
||||
MifareEMemClr();
|
||||
reply_ng(CMD_HF_MIFARE_EML_MEMCLR, PM3_SUCCESS, NULL, 0);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Work with emulator memory
|
||||
//
|
||||
// Note: we call FpgaDownloadAndGo(FPGA_BITSTREAM_HF) here although FPGA is not
|
||||
// involved in dealing with emulator memory. But if it is called later, it might
|
||||
// destroy the Emulator Memory.
|
||||
//-----------------------------------------------------------------------------
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||
|
||||
// Not only clears the emulator memory,
|
||||
// also sets default MIFARE values for sector trailers.
|
||||
emlClearMem();
|
||||
reply_ng(CMD_HF_MIFARE_EML_MEMCLR, PM3_SUCCESS, NULL, 0);
|
||||
break;
|
||||
}
|
||||
case CMD_HF_MIFARE_EML_MEMSET: {
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||
struct p {
|
||||
uint8_t blockno;
|
||||
uint16_t blockno;
|
||||
uint8_t blockcnt;
|
||||
uint8_t blockwidth;
|
||||
uint8_t data[];
|
||||
} PACKED;
|
||||
struct p *payload = (struct p *) packet->data.asBytes;
|
||||
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||
|
||||
// backwards compat... default bytewidth
|
||||
if (payload->blockwidth == 0)
|
||||
payload->blockwidth = 16;
|
||||
if (payload->blockwidth == 0) {
|
||||
payload->blockwidth = MIFARE_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
emlSetMem_xt(payload->data, payload->blockno, payload->blockcnt, payload->blockwidth);
|
||||
break;
|
||||
}
|
||||
case CMD_HF_MIFARE_EML_MEMGET: {
|
||||
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||
struct p {
|
||||
uint8_t blockno;
|
||||
uint16_t blockno;
|
||||
uint8_t blockcnt;
|
||||
uint8_t blockwidth;
|
||||
} PACKED;
|
||||
struct p *payload = (struct p *) packet->data.asBytes;
|
||||
MifareEMemGet(payload->blockno, payload->blockcnt);
|
||||
|
||||
//
|
||||
size_t size = payload->blockno * payload->blockwidth;
|
||||
if (size > PM3_CMD_DATA_SIZE) {
|
||||
reply_ng(CMD_HF_MIFARE_EML_MEMGET, PM3_EMALLOC, NULL, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t *buf = BigBuf_calloc(size);
|
||||
|
||||
emlGetMem_xt(buf, payload->blockno, payload->blockcnt, payload->blockwidth); // data, block num, blocks count (max 4)
|
||||
|
||||
LED_B_ON();
|
||||
reply_ng(CMD_HF_MIFARE_EML_MEMGET, PM3_SUCCESS, buf, size);
|
||||
LED_B_OFF();
|
||||
BigBuf_free_keep_EM();
|
||||
break;
|
||||
}
|
||||
case CMD_HF_MIFARE_EML_LOAD: {
|
||||
|
||||
+107
-74
@@ -133,7 +133,9 @@ void tdes_nxp_send(const void *in, void *out, size_t length, const void *key, ui
|
||||
}
|
||||
|
||||
void aes128_nxp_receive(const void *in, void *out, size_t length, const void *key, unsigned char iv[16]) {
|
||||
if (length % 8) return;
|
||||
if (length % 8) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t *tin = (uint8_t *) in;
|
||||
uint8_t *tout = (uint8_t *) out;
|
||||
@@ -143,7 +145,9 @@ void aes128_nxp_receive(const void *in, void *out, size_t length, const void *ke
|
||||
}
|
||||
|
||||
void aes128_nxp_send(const void *in, void *out, size_t length, const void *key, unsigned char iv[16]) {
|
||||
if (length % 8) return;
|
||||
if (length % 8) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t *tin = (uint8_t *) in;
|
||||
uint8_t *tout = (uint8_t *) out;
|
||||
@@ -152,12 +156,15 @@ void aes128_nxp_send(const void *in, void *out, size_t length, const void *key,
|
||||
mbedtls_aes_crypt_cbc(&actx, MBEDTLS_AES_ENCRYPT, length, iv, tin, tout);
|
||||
}
|
||||
|
||||
void Desfire_des_key_new(const uint8_t value[8], desfirekey_t key) {
|
||||
uint8_t data[8];
|
||||
memcpy(data, value, 8);
|
||||
for (int n = 0; n < 8; n++) {
|
||||
void Desfire_des_key_new(const uint8_t *value, desfirekey_t key) {
|
||||
|
||||
uint8_t data[8] = {0};
|
||||
memcpy(data, value, sizeof(data));
|
||||
|
||||
for (size_t n = 0; n < sizeof(data); n++) {
|
||||
data[n] &= 0xFE;
|
||||
}
|
||||
|
||||
Desfire_des_key_new_with_version(data, key);
|
||||
}
|
||||
|
||||
@@ -246,22 +253,24 @@ void Desfire_key_set_version(desfirekey_t key, uint8_t version) {
|
||||
|
||||
void Desfire_session_key_new(const uint8_t rnda[], const uint8_t rndb[], desfirekey_t authkey, desfirekey_t key) {
|
||||
|
||||
uint8_t buffer[24];
|
||||
uint8_t buffer[24] = {0};
|
||||
|
||||
switch (authkey->type) {
|
||||
case T_DES:
|
||||
case T_DES: {
|
||||
memcpy(buffer, rnda, 4);
|
||||
memcpy(buffer + 4, rndb, 4);
|
||||
Desfire_des_key_new_with_version(buffer, key);
|
||||
break;
|
||||
case T_3DES:
|
||||
}
|
||||
case T_3DES: {
|
||||
memcpy(buffer, rnda, 4);
|
||||
memcpy(buffer + 4, rndb, 4);
|
||||
memcpy(buffer + 8, rnda + 4, 4);
|
||||
memcpy(buffer + 12, rndb + 4, 4);
|
||||
Desfire_3des_key_new_with_version(buffer, key);
|
||||
break;
|
||||
case T_3K3DES:
|
||||
}
|
||||
case T_3K3DES: {
|
||||
memcpy(buffer, rnda, 4);
|
||||
memcpy(buffer + 4, rndb, 4);
|
||||
memcpy(buffer + 8, rnda + 6, 4);
|
||||
@@ -270,22 +279,15 @@ void Desfire_session_key_new(const uint8_t rnda[], const uint8_t rndb[], desfire
|
||||
memcpy(buffer + 20, rndb + 12, 4);
|
||||
Desfire_3k3des_key_new(buffer, key);
|
||||
break;
|
||||
case T_AES:
|
||||
}
|
||||
case T_AES: {
|
||||
memcpy(buffer, rnda, 4);
|
||||
memcpy(buffer + 4, rndb, 4);
|
||||
memcpy(buffer + 8, rnda + 12, 4);
|
||||
memcpy(buffer + 12, rndb + 12, 4);
|
||||
Desfire_aes_key_new(buffer, key);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static size_t key_macing_length(desfirekey_t key);
|
||||
|
||||
// iceman, see memxor inside string.c, dest/src swapped..
|
||||
static void xor(const uint8_t *ivect, uint8_t *data, const size_t len) {
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
data[i] ^= ivect[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -306,7 +308,7 @@ void cmac_generate_subkeys(desfirekey_t key) {
|
||||
// Used to compute CMAC on complete blocks
|
||||
memcpy(key->cmac_sk1, l, kbs);
|
||||
|
||||
txor = l[0] & 0x80;
|
||||
txor = (l[0] & 0x80);
|
||||
|
||||
lsl(key->cmac_sk1, kbs);
|
||||
|
||||
@@ -317,7 +319,7 @@ void cmac_generate_subkeys(desfirekey_t key) {
|
||||
// Used to compute CMAC on the last block if non-complete
|
||||
memcpy(key->cmac_sk2, key->cmac_sk1, kbs);
|
||||
|
||||
txor = key->cmac_sk1[0] & 0x80;
|
||||
txor = (key->cmac_sk1[0] & 0x80);
|
||||
|
||||
lsl(key->cmac_sk2, kbs);
|
||||
|
||||
@@ -341,15 +343,14 @@ void cmac(const desfirekey_t key, uint8_t *ivect, const uint8_t *data, size_t le
|
||||
while (len % kbs) {
|
||||
buffer[len++] = 0x00;
|
||||
}
|
||||
xor(key->cmac_sk2, buffer + len - kbs, kbs);
|
||||
xor(buffer + len - kbs, key->cmac_sk2, kbs);
|
||||
} else {
|
||||
xor(key->cmac_sk1, buffer + len - kbs, kbs);
|
||||
xor(buffer + len - kbs, key->cmac_sk1, kbs);
|
||||
}
|
||||
|
||||
mifare_cypher_blocks_chained(NULL, key, ivect, buffer, len, MCD_SEND, MCO_ENCYPHER);
|
||||
|
||||
memcpy(cmac, ivect, kbs);
|
||||
//free(buffer);
|
||||
}
|
||||
|
||||
size_t key_block_size(const desfirekey_t key) {
|
||||
@@ -374,7 +375,7 @@ size_t key_block_size(const desfirekey_t key) {
|
||||
/*
|
||||
* Size of MACing produced with the key.
|
||||
*/
|
||||
static size_t key_macing_length(const desfirekey_t key) {
|
||||
size_t key_macing_length(const desfirekey_t key) {
|
||||
size_t mac_length = DESFIRE_MAC_LENGTH;
|
||||
switch (key->type) {
|
||||
case T_DES:
|
||||
@@ -393,10 +394,11 @@ static size_t key_macing_length(const desfirekey_t key) {
|
||||
* Size required to store nbytes of data in a buffer of size n*block_size.
|
||||
*/
|
||||
size_t padded_data_length(const size_t nbytes, const size_t block_size) {
|
||||
if ((!nbytes) || (nbytes % block_size))
|
||||
if ((!nbytes) || (nbytes % block_size)) {
|
||||
return ((nbytes / block_size) + 1) * block_size;
|
||||
else
|
||||
} else {
|
||||
return nbytes;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -412,12 +414,14 @@ size_t enciphered_data_length(const desfiretag_t tag, const size_t nbytes, int c
|
||||
size_t crc_length = 0;
|
||||
if (!(communication_settings & NO_CRC)) {
|
||||
switch (DESFIRE(tag)->authentication_scheme) {
|
||||
case AS_LEGACY:
|
||||
case AS_LEGACY: {
|
||||
crc_length = 2;
|
||||
break;
|
||||
case AS_NEW:
|
||||
}
|
||||
case AS_NEW: {
|
||||
crc_length = 4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -428,18 +432,20 @@ size_t enciphered_data_length(const desfiretag_t tag, const size_t nbytes, int c
|
||||
|
||||
void *mifare_cryto_preprocess_data(desfiretag_t tag, void *data, size_t *nbytes, size_t offset, int communication_settings) {
|
||||
uint8_t *res = data;
|
||||
uint8_t mac[4];
|
||||
uint8_t mac[4] = {0};
|
||||
size_t edl;
|
||||
bool append_mac = true;
|
||||
desfirekey_t key = DESFIRE(tag)->session_key;
|
||||
|
||||
if (!key)
|
||||
desfirekey_t key = DESFIRE(tag)->session_key;
|
||||
if (!key) {
|
||||
return data;
|
||||
}
|
||||
|
||||
switch (communication_settings & MDCM_MASK) {
|
||||
case MDCM_PLAIN:
|
||||
if (AS_LEGACY == DESFIRE(tag)->authentication_scheme)
|
||||
case MDCM_PLAIN: {
|
||||
if (AS_LEGACY == DESFIRE(tag)->authentication_scheme) {
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* When using new authentication methods, PLAIN data transmission from
|
||||
@@ -452,13 +458,16 @@ void *mifare_cryto_preprocess_data(desfiretag_t tag, void *data, size_t *nbytes,
|
||||
*/
|
||||
|
||||
append_mac = false;
|
||||
|
||||
}
|
||||
/* pass through */
|
||||
case MDCM_MACED:
|
||||
case MDCM_MACED: {
|
||||
switch (DESFIRE(tag)->authentication_scheme) {
|
||||
case AS_LEGACY:
|
||||
if (!(communication_settings & MAC_COMMAND))
|
||||
case AS_LEGACY: {
|
||||
|
||||
if (!(communication_settings & MAC_COMMAND)) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
/* pass through */
|
||||
edl = padded_data_length(*nbytes - offset, key_block_size(DESFIRE(tag)->session_key)) + offset;
|
||||
@@ -475,8 +484,9 @@ void *mifare_cryto_preprocess_data(desfiretag_t tag, void *data, size_t *nbytes,
|
||||
// Copy again provided data (was overwritten by mifare_cypher_blocks_chained)
|
||||
memcpy(res, data, *nbytes);
|
||||
|
||||
if (!(communication_settings & MAC_COMMAND))
|
||||
if (!(communication_settings & MAC_COMMAND)) {
|
||||
break;
|
||||
}
|
||||
// Append MAC
|
||||
size_t bla = maced_data_length(DESFIRE(tag)->session_key, *nbytes - offset) + offset;
|
||||
(void)bla++;
|
||||
@@ -485,9 +495,12 @@ void *mifare_cryto_preprocess_data(desfiretag_t tag, void *data, size_t *nbytes,
|
||||
|
||||
*nbytes += 4;
|
||||
break;
|
||||
case AS_NEW:
|
||||
if (!(communication_settings & CMAC_COMMAND))
|
||||
}
|
||||
case AS_NEW: {
|
||||
if (!(communication_settings & CMAC_COMMAND)) {
|
||||
break;
|
||||
}
|
||||
|
||||
cmac(key, DESFIRE(tag)->ivect, res, *nbytes, DESFIRE(tag)->cmac);
|
||||
|
||||
if (append_mac) {
|
||||
@@ -498,10 +511,11 @@ void *mifare_cryto_preprocess_data(desfiretag_t tag, void *data, size_t *nbytes,
|
||||
*nbytes += DESFIRE_CMAC_LENGTH;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case MDCM_ENCIPHERED:
|
||||
}
|
||||
case MDCM_ENCIPHERED: {
|
||||
/* |<-------------- data -------------->|
|
||||
* |<--- offset -->| |
|
||||
* +---------------+--------------------+-----+---------+
|
||||
@@ -517,8 +531,10 @@ void *mifare_cryto_preprocess_data(desfiretag_t tag, void *data, size_t *nbytes,
|
||||
* encypher()/decypher()
|
||||
*/
|
||||
|
||||
if (!(communication_settings & ENC_COMMAND))
|
||||
if (!(communication_settings & ENC_COMMAND)) {
|
||||
break;
|
||||
}
|
||||
|
||||
edl = enciphered_data_length(tag, *nbytes - offset, communication_settings) + offset;
|
||||
|
||||
// Fill in the crypto buffer with data ...
|
||||
@@ -526,14 +542,16 @@ void *mifare_cryto_preprocess_data(desfiretag_t tag, void *data, size_t *nbytes,
|
||||
if (!(communication_settings & NO_CRC)) {
|
||||
// ... CRC ...
|
||||
switch (DESFIRE(tag)->authentication_scheme) {
|
||||
case AS_LEGACY:
|
||||
case AS_LEGACY: {
|
||||
AddCrc14A(res + offset, *nbytes - offset);
|
||||
*nbytes += 2;
|
||||
break;
|
||||
case AS_NEW:
|
||||
}
|
||||
case AS_NEW: {
|
||||
crc32_append(res, *nbytes);
|
||||
*nbytes += 4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// ... and padding
|
||||
@@ -543,32 +561,34 @@ void *mifare_cryto_preprocess_data(desfiretag_t tag, void *data, size_t *nbytes,
|
||||
|
||||
mifare_cypher_blocks_chained(tag, NULL, NULL, res + offset, *nbytes - offset, MCD_SEND, (AS_NEW == DESFIRE(tag)->authentication_scheme) ? MCO_ENCYPHER : MCO_DECYPHER);
|
||||
break;
|
||||
default:
|
||||
|
||||
}
|
||||
default: {
|
||||
*nbytes = -1;
|
||||
res = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
|
||||
}
|
||||
|
||||
void *mifare_cryto_postprocess_data(desfiretag_t tag, void *data, size_t *nbytes, int communication_settings) {
|
||||
|
||||
void *res = data;
|
||||
uint8_t first_cmac_byte = 0x00;
|
||||
|
||||
desfirekey_t key = DESFIRE(tag)->session_key;
|
||||
|
||||
if (!key) {
|
||||
return data;
|
||||
}
|
||||
|
||||
// Return directly if we just have a status code.
|
||||
if (1 == *nbytes) {
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
desfirekey_t key = DESFIRE(tag)->session_key;
|
||||
if (!key) {
|
||||
return data;
|
||||
}
|
||||
|
||||
uint8_t first_cmac_byte = 0x00;
|
||||
|
||||
switch (communication_settings & MDCM_MASK) {
|
||||
case MDCM_PLAIN: {
|
||||
|
||||
@@ -659,11 +679,12 @@ void *mifare_cryto_postprocess_data(desfiretag_t tag, void *data, size_t *nbytes
|
||||
break;
|
||||
}
|
||||
case MDCM_ENCIPHERED: {
|
||||
|
||||
(*nbytes)--;
|
||||
|
||||
bool verified = false;
|
||||
int crc_pos = 0x00;
|
||||
int end_crc_pos = 0x00;
|
||||
uint8_t x;
|
||||
|
||||
/*
|
||||
* AS_LEGACY:
|
||||
@@ -742,8 +763,9 @@ void *mifare_cryto_postprocess_data(desfiretag_t tag, void *data, size_t *nbytes
|
||||
verified = true;
|
||||
for (int n = end_crc_pos; n < *nbytes - 1; n++) {
|
||||
uint8_t byte = ((uint8_t *)res)[n];
|
||||
if (!((0x00 == byte) || ((0x80 == byte) && (n == end_crc_pos))))
|
||||
if (!((0x00 == byte) || ((0x80 == byte) && (n == end_crc_pos)))) {
|
||||
verified = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -768,7 +790,7 @@ void *mifare_cryto_postprocess_data(desfiretag_t tag, void *data, size_t *nbytes
|
||||
break;
|
||||
}
|
||||
case AS_NEW: {
|
||||
x = ((uint8_t *)res)[crc_pos - 1];
|
||||
uint8_t x = ((uint8_t *)res)[crc_pos - 1];
|
||||
((uint8_t *)res)[crc_pos - 1] = ((uint8_t *)res)[crc_pos];
|
||||
((uint8_t *)res)[crc_pos] = x;
|
||||
break;
|
||||
@@ -802,9 +824,10 @@ void *mifare_cryto_postprocess_data(desfiretag_t tag, void *data, size_t *nbytes
|
||||
|
||||
|
||||
void mifare_cypher_single_block(desfirekey_t key, uint8_t *data, uint8_t *ivect, MifareCryptoDirection direction, MifareCryptoOperation operation, size_t block_size) {
|
||||
|
||||
uint8_t ovect[DESFIRE_MAX_CRYPTO_BLOCK_SIZE];
|
||||
if (direction == MCD_SEND) {
|
||||
xor(ivect, data, block_size);
|
||||
xor(data, ivect, block_size);
|
||||
} else {
|
||||
memcpy(ovect, data, block_size);
|
||||
}
|
||||
@@ -812,70 +835,80 @@ void mifare_cypher_single_block(desfirekey_t key, uint8_t *data, uint8_t *ivect,
|
||||
uint8_t edata[DESFIRE_MAX_CRYPTO_BLOCK_SIZE] = {0};
|
||||
|
||||
switch (key->type) {
|
||||
case T_DES:
|
||||
case T_DES: {
|
||||
switch (operation) {
|
||||
case MCO_ENCYPHER:
|
||||
case MCO_ENCYPHER: {
|
||||
//DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_ENCRYPT);
|
||||
des_encrypt(edata, data, key->data);
|
||||
break;
|
||||
case MCO_DECYPHER:
|
||||
}
|
||||
case MCO_DECYPHER: {
|
||||
//DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_DECRYPT);
|
||||
des_decrypt(edata, data, key->data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case T_3DES:
|
||||
}
|
||||
case T_3DES: {
|
||||
switch (operation) {
|
||||
case MCO_ENCYPHER:
|
||||
case MCO_ENCYPHER: {
|
||||
mbedtls_des3_set2key_enc(&ctx3, key->data);
|
||||
mbedtls_des3_crypt_ecb(&ctx3, data, edata);
|
||||
// DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_ENCRYPT);
|
||||
// DES_ecb_encrypt ((DES_cblock *) edata, (DES_cblock *) data, &(key->ks2), DES_DECRYPT);
|
||||
// DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_ENCRYPT);
|
||||
break;
|
||||
case MCO_DECYPHER:
|
||||
}
|
||||
case MCO_DECYPHER: {
|
||||
mbedtls_des3_set2key_dec(&ctx3, key->data);
|
||||
mbedtls_des3_crypt_ecb(&ctx3, data, edata);
|
||||
// DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_DECRYPT);
|
||||
// DES_ecb_encrypt ((DES_cblock *) edata, (DES_cblock *) data, &(key->ks2), DES_ENCRYPT);
|
||||
// DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_DECRYPT);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case T_3K3DES:
|
||||
}
|
||||
case T_3K3DES: {
|
||||
switch (operation) {
|
||||
case MCO_ENCYPHER:
|
||||
case MCO_ENCYPHER: {
|
||||
mbedtls_des3_set3key_enc(&ctx3, key->data);
|
||||
mbedtls_des3_crypt_ecb(&ctx3, data, edata);
|
||||
// DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_ENCRYPT);
|
||||
// DES_ecb_encrypt ((DES_cblock *) edata, (DES_cblock *) data, &(key->ks2), DES_DECRYPT);
|
||||
// DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks3), DES_ENCRYPT);
|
||||
break;
|
||||
case MCO_DECYPHER:
|
||||
}
|
||||
case MCO_DECYPHER: {
|
||||
mbedtls_des3_set3key_dec(&ctx3, key->data);
|
||||
mbedtls_des3_crypt_ecb(&ctx3, data, edata);
|
||||
// DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks3), DES_DECRYPT);
|
||||
// DES_ecb_encrypt ((DES_cblock *) edata, (DES_cblock *) data, &(key->ks2), DES_ENCRYPT);
|
||||
// DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_DECRYPT);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case T_AES:
|
||||
}
|
||||
case T_AES: {
|
||||
switch (operation) {
|
||||
case MCO_ENCYPHER: {
|
||||
mbedtls_aes_init(&actx);
|
||||
mbedtls_aes_setkey_enc(&actx, key->data, 128);
|
||||
mbedtls_aes_crypt_cbc(&actx, MBEDTLS_AES_ENCRYPT, sizeof(edata), ivect, data, edata);
|
||||
mbedtls_aes_crypt_ecb(&actx, MBEDTLS_AES_ENCRYPT, data, edata);
|
||||
break;
|
||||
}
|
||||
case MCO_DECYPHER: {
|
||||
mbedtls_aes_init(&actx);
|
||||
mbedtls_aes_setkey_dec(&actx, key->data, 128);
|
||||
mbedtls_aes_crypt_cbc(&actx, MBEDTLS_AES_DECRYPT, sizeof(edata), ivect, edata, data);
|
||||
mbedtls_aes_crypt_ecb(&actx, MBEDTLS_AES_DECRYPT, data, edata);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(data, edata, block_size);
|
||||
@@ -883,7 +916,7 @@ void mifare_cypher_single_block(desfirekey_t key, uint8_t *data, uint8_t *ivect,
|
||||
if (direction == MCD_SEND) {
|
||||
memcpy(ivect, data, block_size);
|
||||
} else {
|
||||
xor(ivect, data, block_size);
|
||||
xor(data, ivect, block_size);
|
||||
memcpy(ivect, ovect, block_size);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -183,7 +183,7 @@ void tdes_nxp_send(const void *in, void *out, size_t length, const void *key, ui
|
||||
void aes128_nxp_receive(const void *in, void *out, size_t length, const void *key, unsigned char iv[16]);
|
||||
void aes128_nxp_send(const void *in, void *out, size_t length, const void *key, unsigned char iv[16]);
|
||||
|
||||
void Desfire_des_key_new(const uint8_t value[8], desfirekey_t key);
|
||||
void Desfire_des_key_new(const uint8_t *value, desfirekey_t key);
|
||||
void Desfire_3des_key_new(const uint8_t value[16], desfirekey_t key);
|
||||
void Desfire_des_key_new_with_version(const uint8_t value[8], desfirekey_t key);
|
||||
void Desfire_3des_key_new_with_version(const uint8_t value[16], desfirekey_t key);
|
||||
@@ -207,4 +207,6 @@ size_t enciphered_data_length(const desfiretag_t tag, const size_t nbytes, int c
|
||||
void cmac_generate_subkeys(desfirekey_t key);
|
||||
void cmac(const desfirekey_t key, uint8_t *ivect, const uint8_t *data, size_t len, uint8_t *cmac);
|
||||
|
||||
size_t key_macing_length(desfirekey_t key);
|
||||
|
||||
#endif
|
||||
|
||||
+4
-3
@@ -125,7 +125,7 @@ void ExecuteEMVSim(uint8_t *receivedCmd, uint16_t receivedCmd_len, uint8_t *rece
|
||||
Dbprintf("");
|
||||
|
||||
// use annotate to give some hints about the command
|
||||
annotate(&receivedCmd[1], receivedCmd_len-1);
|
||||
annotate(&receivedCmd[1], receivedCmd_len - 1);
|
||||
|
||||
// This is a common request from the reader which we can just immediately respond to since we know we can't
|
||||
// handle it.
|
||||
@@ -141,7 +141,7 @@ void ExecuteEMVSim(uint8_t *receivedCmd, uint16_t receivedCmd_len, uint8_t *rece
|
||||
|
||||
currentState = GENERATE_AC;
|
||||
|
||||
memcpy(receivedCmd, (unsigned char[]){ 0x03, 0x80, 0xae, 0x80, 0x00, 0x1d }, 6);
|
||||
memcpy(receivedCmd, (unsigned char[]) { 0x03, 0x80, 0xae, 0x80, 0x00, 0x1d }, 6);
|
||||
|
||||
for (int i = 0; i < 29; i++) {
|
||||
receivedCmd[6 + i] = receivedCmd[12 + i];
|
||||
@@ -240,7 +240,8 @@ void ExecuteEMVSim(uint8_t *receivedCmd, uint16_t receivedCmd_len, uint8_t *rece
|
||||
0x20, 0x00, 0x9f, 0x26, 0x08, 0x56, 0xcb, 0x4e, 0xe1, 0xa4,
|
||||
0xef, 0xac, 0x74, 0x9f, 0x27, 0x01, 0x80, 0x9f, 0x36, 0x02,
|
||||
0x00, 0x07, 0x9f, 0x6c, 0x02, 0x3e, 0x00, 0x9f, 0x6e, 0x04,
|
||||
0x20, 0x70, 0x00, 0x00, 0x90, 0x00, 0xff, 0xff};
|
||||
0x20, 0x70, 0x00, 0x00, 0x90, 0x00, 0xff, 0xff
|
||||
};
|
||||
|
||||
// do the replacement
|
||||
template[0] = responseToReader[0]; // class bit 0
|
||||
|
||||
+1
-1
@@ -1035,7 +1035,7 @@ static int hts_send_receive(const uint8_t *tx, size_t txlen, uint8_t *rx, size_t
|
||||
Dbhexdump(*rxlen, response_bit, false);
|
||||
Dbprintf("htS: skipping %d bit SOF", sof_bits);
|
||||
|
||||
if ((rx[0] >> (8 - sof_bits)) != ((1 << sof_bits) - 1)) {
|
||||
if ((rx[0] >> (8 - sof_bits)) != ((1 << sof_bits) - 1)) {
|
||||
DBG DbpString("htS: Warning, not all bits of SOF are 1");
|
||||
}
|
||||
}
|
||||
|
||||
+10
-10
@@ -1455,7 +1455,7 @@ bool SimulateIso14443aInit(uint8_t tagType, uint16_t flags, uint8_t *data,
|
||||
// response to send, and send it.
|
||||
// 'hf 14a sim'
|
||||
//-----------------------------------------------------------------------------
|
||||
void SimulateIso14443aTag(uint8_t tagType, uint16_t flags, uint8_t *data, uint8_t exitAfterNReads,
|
||||
void SimulateIso14443aTag(uint8_t tagType, uint16_t flags, uint8_t *useruid, uint8_t exitAfterNReads,
|
||||
uint8_t *ats, size_t ats_len) {
|
||||
|
||||
#define ATTACK_KEY_COUNT 16
|
||||
@@ -1508,7 +1508,7 @@ void SimulateIso14443aTag(uint8_t tagType, uint16_t flags, uint8_t *data, uint8_
|
||||
.modulation_n = 0
|
||||
};
|
||||
|
||||
if (SimulateIso14443aInit(tagType, flags, data, ats, ats_len, &responses, &cuid, counters, tearings, &pages) == false) {
|
||||
if (SimulateIso14443aInit(tagType, flags, useruid, ats, ats_len, &responses, &cuid, counters, tearings, &pages) == false) {
|
||||
BigBuf_free_keep_EM();
|
||||
reply_ng(CMD_HF_MIFARE_SIMULATE, PM3_EINIT, NULL, 0);
|
||||
return;
|
||||
@@ -1684,8 +1684,8 @@ void SimulateIso14443aTag(uint8_t tagType, uint16_t flags, uint8_t *data, uint8_
|
||||
// first blocks of emu are header
|
||||
uint16_t start = block * 4 + MFU_DUMP_PREFIX_LENGTH;
|
||||
uint8_t emdata[MAX_MIFARE_FRAME_SIZE];
|
||||
emlGet(emdata, start, 16);
|
||||
AddCrc14A(emdata, 16);
|
||||
emlGet(emdata, start, MIFARE_BLOCK_SIZE);
|
||||
AddCrc14A(emdata, MIFARE_BLOCK_SIZE);
|
||||
EmSendCmd(emdata, sizeof(emdata));
|
||||
numReads++; // Increment number of times reader requested a block
|
||||
|
||||
@@ -1703,8 +1703,8 @@ void SimulateIso14443aTag(uint8_t tagType, uint16_t flags, uint8_t *data, uint8_
|
||||
p_response = &responses[RESP_INDEX_UIDC1];
|
||||
} else { // all other tags (16 byte block tags)
|
||||
uint8_t emdata[MAX_MIFARE_FRAME_SIZE] = {0};
|
||||
emlGet(emdata, block, 16);
|
||||
AddCrc14A(emdata, 16);
|
||||
emlGet(emdata, block, MIFARE_BLOCK_SIZE);
|
||||
AddCrc14A(emdata, MIFARE_BLOCK_SIZE);
|
||||
EmSendCmd(emdata, sizeof(emdata));
|
||||
// We already responded, do not send anything with the EmSendCmd14443aRaw() that is called below
|
||||
p_response = NULL;
|
||||
@@ -1847,7 +1847,7 @@ void SimulateIso14443aTag(uint8_t tagType, uint16_t flags, uint8_t *data, uint8_
|
||||
}
|
||||
|
||||
if (memcmp(pwd, "\x00\x00\x00\x00", 4) == 0) {
|
||||
Uint4byteToMemLe(pwd, ul_ev1_pwdgenB(data));
|
||||
Uint4byteToMemLe(pwd, ul_ev1_pwdgenB(useruid));
|
||||
if (g_dbglevel >= DBG_DEBUG) Dbprintf("Calc pwd... %02X %02X %02X %02X", pwd[0], pwd[1], pwd[2], pwd[3]);
|
||||
}
|
||||
|
||||
@@ -4080,7 +4080,7 @@ void SimulateIso14443aTagAID(uint8_t tagType, uint16_t flags, uint8_t *uid,
|
||||
dynamic_response_info.response[0] = receivedCmd[0];
|
||||
dynamic_response_info.response[1] = 0x00;
|
||||
|
||||
switch (receivedCmd[2+offset]) { // APDU Class Byte
|
||||
switch (receivedCmd[2 + offset]) { // APDU Class Byte
|
||||
// receivedCmd in this case is expecting to structured with possibly a CID, then the APDU command for SelectFile
|
||||
// | IBlock (CID) | CID | APDU Command | CRC |
|
||||
// or | IBlock (noCID) | APDU Command | CRC |
|
||||
@@ -4092,8 +4092,8 @@ void SimulateIso14443aTagAID(uint8_t tagType, uint16_t flags, uint8_t *uid,
|
||||
// xx in this case is len of the AID value in hex
|
||||
|
||||
// aid len is found as a hex value in receivedCmd[6] (Index Starts at 0)
|
||||
int received_aid_len = receivedCmd[5+offset];
|
||||
uint8_t *received_aid = &receivedCmd[6+offset];
|
||||
int received_aid_len = receivedCmd[5 + offset];
|
||||
uint8_t *received_aid = &receivedCmd[6 + offset];
|
||||
|
||||
// aid enumeration flag
|
||||
if ((flags & FLAG_ENUMERATE_AID) == FLAG_ENUMERATE_AID) {
|
||||
|
||||
+1
-1
@@ -142,7 +142,7 @@ RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time);
|
||||
RAMFUNC int ManchesterDecoding(uint8_t bit, uint16_t offset, uint32_t non_real_time);
|
||||
|
||||
void RAMFUNC SniffIso14443a(uint8_t param);
|
||||
void SimulateIso14443aTag(uint8_t tagType, uint16_t flags, uint8_t *data, uint8_t exitAfterNReads,
|
||||
void SimulateIso14443aTag(uint8_t tagType, uint16_t flags, uint8_t *useruid, uint8_t exitAfterNReads,
|
||||
uint8_t *iRATs, size_t irats_len);
|
||||
|
||||
void SimulateIso14443aTagAID(uint8_t tagType, uint16_t flags, uint8_t *uid,
|
||||
|
||||
@@ -2117,14 +2117,6 @@ void Iso15693InitTag(void) {
|
||||
StartCountSspClk();
|
||||
}
|
||||
|
||||
void EmlClearIso15693(void) {
|
||||
// Resetting the bitstream also frees the BigBuf memory, so we do this here to prevent
|
||||
// an inconvenient reset in the future by Iso15693InitTag
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF_15);
|
||||
BigBuf_Clear_EM();
|
||||
reply_ng(CMD_HF_ISO15693_EML_CLEAR, PM3_SUCCESS, NULL, 0);
|
||||
}
|
||||
|
||||
// Simulate an ISO15693 TAG, perform anti-collision and then print any reader commands
|
||||
// all demodulation performed in arm rather than host. - greg
|
||||
void SimTagIso15693(const uint8_t *uid, uint8_t block_size) {
|
||||
|
||||
@@ -46,7 +46,6 @@ int GetIso15693AnswerFromTag(uint8_t *response, uint16_t max_len, uint16_t timeo
|
||||
//void RecordRawAdcSamplesIso15693(void);
|
||||
void AcquireRawAdcSamplesIso15693(void);
|
||||
void ReaderIso15693(iso15_card_select_t *p_card); // ISO15693 reader
|
||||
void EmlClearIso15693(void);
|
||||
void SimTagIso15693(const uint8_t *uid, uint8_t block_size); // simulate an ISO15693 tag
|
||||
void BruteforceIso15693Afi(uint32_t flags); // find an AFI of a tag
|
||||
void SendRawCommand15693(iso15_raw_cmd_t *packet); // send arbitrary commands from CLI
|
||||
|
||||
+2
-2
@@ -944,7 +944,7 @@ static void fcAll(uint8_t fc, int *n, uint8_t clock, int16_t *remainder) {
|
||||
}
|
||||
}
|
||||
|
||||
bool add_HID_preamble(uint32_t *hi2, uint32_t *hi, uint32_t *lo, uint8_t length){
|
||||
bool add_HID_preamble(uint32_t *hi2, uint32_t *hi, uint32_t *lo, uint8_t length) {
|
||||
// Invalid value
|
||||
if (length > 84 || length == 0)
|
||||
return false;
|
||||
@@ -963,7 +963,7 @@ bool add_HID_preamble(uint32_t *hi2, uint32_t *hi, uint32_t *lo, uint8_t length)
|
||||
// No header bits added to 37-bit cards
|
||||
} else if (length >= 32) {
|
||||
*hi |= 0x20; // Bit 37; standard header
|
||||
*hi |= 1U << (length - 32); // leading 1: start bit
|
||||
*hi |= 1U << (length - 32); // leading 1: start bit
|
||||
} else {
|
||||
*hi |= 0x20; // Bit 37; standard header
|
||||
*lo |= 1U << length; // leading 1: start bit
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@
|
||||
void ModThenAcquireRawAdcSamples125k(uint32_t delay_off, uint16_t period_0, uint16_t period_1,
|
||||
const uint8_t *symbol_extra, uint16_t *period_extra, uint8_t *command, bool verbose,
|
||||
bool keep_field_on, uint32_t samples, bool ledcontrol);
|
||||
|
||||
|
||||
void ReadTItag(bool ledcontrol);
|
||||
void WriteTItag(uint32_t idhi, uint32_t idlo, uint16_t crc, bool ledcontrol);
|
||||
|
||||
|
||||
+131
-162
@@ -2223,7 +2223,7 @@ OUT:
|
||||
blockno = (32 * 4 + (i - 32) * 16) ^ 0xF;
|
||||
}
|
||||
// get ST
|
||||
emlGetMem(block, blockno, 1);
|
||||
emlGetMem_xt(block, blockno, 1, MIFARE_BLOCK_SIZE);
|
||||
|
||||
memcpy(block, k_sector[i].keyA, 6);
|
||||
memcpy(block + 10, k_sector[i].keyB, 6);
|
||||
@@ -2427,39 +2427,6 @@ void MifarePersonalizeUID(uint8_t keyType, uint8_t perso_option, uint64_t key) {
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Work with emulator memory
|
||||
//
|
||||
// Note: we call FpgaDownloadAndGo(FPGA_BITSTREAM_HF) here although FPGA is not
|
||||
// involved in dealing with emulator memory. But if it is called later, it might
|
||||
// destroy the Emulator Memory.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void MifareEMemClr(void) {
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||
emlClearMem();
|
||||
}
|
||||
|
||||
void MifareEMemGet(uint8_t blockno, uint8_t blockcnt) {
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||
|
||||
//
|
||||
size_t size = blockcnt * 16;
|
||||
if (size > PM3_CMD_DATA_SIZE) {
|
||||
reply_ng(CMD_HF_MIFARE_EML_MEMGET, PM3_EMALLOC, NULL, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t *buf = BigBuf_malloc(size);
|
||||
|
||||
emlGetMem(buf, blockno, blockcnt); // data, block num, blocks count (max 4)
|
||||
|
||||
LED_B_ON();
|
||||
reply_ng(CMD_HF_MIFARE_EML_MEMGET, PM3_SUCCESS, buf, size);
|
||||
LED_B_OFF();
|
||||
BigBuf_free_keep_EM();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Load a card into the emulator memory
|
||||
//
|
||||
@@ -2471,12 +2438,15 @@ int MifareECardLoadExt(uint8_t sectorcnt, uint8_t keytype, uint8_t *key) {
|
||||
}
|
||||
|
||||
int MifareECardLoad(uint8_t sectorcnt, uint8_t keytype, uint8_t *key) {
|
||||
|
||||
if ((keytype > MF_KEY_B) && (key == NULL)) {
|
||||
|
||||
if (g_dbglevel >= DBG_ERROR) {
|
||||
Dbprintf("Error, missing key");
|
||||
}
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
LED_A_ON();
|
||||
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
|
||||
|
||||
@@ -2510,10 +2480,10 @@ int MifareECardLoad(uint8_t sectorcnt, uint8_t keytype, uint8_t *key) {
|
||||
// MFC 1K EV1, skip sector 16 since its lockdown
|
||||
if (s == 16) {
|
||||
// unknown sector trailer, keep the keys, set only the AC
|
||||
uint8_t st[16] = {0x00};
|
||||
emlGetMem(st, FirstBlockOfSector(s) + 3, 1);
|
||||
uint8_t st[MIFARE_BLOCK_SIZE] = {0x00};
|
||||
emlGetMem_xt(st, FirstBlockOfSector(s) + 3, 1, MIFARE_BLOCK_SIZE);
|
||||
memcpy(st + 6, "\x70\xF0\xF8\x69", 4);
|
||||
emlSetMem_xt(st, FirstBlockOfSector(s) + 3, 1, 16);
|
||||
emlSetMem_xt(st, FirstBlockOfSector(s) + 3, 1, MIFARE_BLOCK_SIZE);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -2556,7 +2526,8 @@ int MifareECardLoad(uint8_t sectorcnt, uint8_t keytype, uint8_t *key) {
|
||||
}
|
||||
have_uid = true;
|
||||
} else { // no need for anticollision. We can directly select the card
|
||||
if (!bd_authenticated) { // no need to select if bd_authenticated with backdoor
|
||||
|
||||
if (bd_authenticated == false) { // no need to select if bd_authenticated with backdoor
|
||||
if (iso14443a_fast_select_card(uid, cascade_levels) == 0) {
|
||||
continue;
|
||||
}
|
||||
@@ -2565,7 +2536,7 @@ int MifareECardLoad(uint8_t sectorcnt, uint8_t keytype, uint8_t *key) {
|
||||
|
||||
// Auth
|
||||
if (keytype > MF_KEY_B) {
|
||||
if (! bd_authenticated) {
|
||||
if (bd_authenticated == false) {
|
||||
ui64Key = bytes_to_num(key, 6);
|
||||
if (mifare_classic_auth(pcs, cuid, 0, keytype, ui64Key, AUTH_FIRST)) {
|
||||
retval = PM3_EFAILED;
|
||||
@@ -2592,7 +2563,7 @@ int MifareECardLoad(uint8_t sectorcnt, uint8_t keytype, uint8_t *key) {
|
||||
|
||||
#define MAX_RETRIES 2
|
||||
|
||||
uint8_t data[16] = {0x00};
|
||||
uint8_t data[MIFARE_BLOCK_SIZE] = {0x00};
|
||||
for (uint8_t b = 0; b < NumBlocksPerSector(s); b++) {
|
||||
|
||||
memset(data, 0x00, sizeof(data));
|
||||
@@ -2614,18 +2585,18 @@ int MifareECardLoad(uint8_t sectorcnt, uint8_t keytype, uint8_t *key) {
|
||||
}
|
||||
|
||||
// No need to copy empty
|
||||
if (memcmp(data, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16) == 0) {
|
||||
if (memcmp(data, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", sizeof(data)) == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (IsSectorTrailer(b)) {
|
||||
// sector trailer, keep the keys, set only the AC
|
||||
uint8_t st[16] = {0x00};
|
||||
emlGetMem(st, tb, 1);
|
||||
uint8_t st[MIFARE_BLOCK_SIZE] = {0x00};
|
||||
emlGetMem_xt(st, tb, 1, MIFARE_BLOCK_SIZE);
|
||||
memcpy(st + 6, data + 6, 4);
|
||||
emlSetMem_xt(st, tb, 1, 16);
|
||||
emlSetMem_xt(st, tb, 1, MIFARE_BLOCK_SIZE);
|
||||
} else {
|
||||
emlSetMem_xt(data, tb, 1, 16);
|
||||
emlSetMem_xt(data, tb, 1, MIFARE_BLOCK_SIZE);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -2927,7 +2898,6 @@ void MifareCIdent(bool is_mfc, uint8_t keytype, uint8_t *key) {
|
||||
// variables
|
||||
uint8_t rec[1] = {0x00};
|
||||
uint8_t recpar[1] = {0x00};
|
||||
uint8_t rats[4] = {ISO14443A_CMD_RATS, 0x80, 0x31, 0x73};
|
||||
uint8_t rdblf0[4] = {ISO14443A_CMD_READBLOCK, 0xF0, 0x8D, 0x5f};
|
||||
uint8_t rdbl00[4] = {ISO14443A_CMD_READBLOCK, 0x00, 0x02, 0xa8};
|
||||
uint8_t gen4gdmAuth[4] = {MIFARE_MAGIC_GDM_AUTH_KEY, 0x00, 0x6C, 0x92};
|
||||
@@ -2940,6 +2910,8 @@ void MifareCIdent(bool is_mfc, uint8_t keytype, uint8_t *key) {
|
||||
uint8_t *par = BigBuf_calloc(MAX_PARITY_SIZE);
|
||||
uint8_t *buf = BigBuf_calloc(PM3_CMD_DATA_SIZE);
|
||||
uint8_t *uid = BigBuf_calloc(10);
|
||||
iso14a_card_select_t *card = (iso14a_card_select_t *) BigBuf_calloc(sizeof(iso14a_card_select_t));
|
||||
|
||||
uint16_t flag = MAGIC_FLAG_NONE;
|
||||
uint32_t cuid = 0;
|
||||
int res = 0;
|
||||
@@ -2991,144 +2963,141 @@ void MifareCIdent(bool is_mfc, uint8_t keytype, uint8_t *key) {
|
||||
// reset card
|
||||
mf_reset_card();
|
||||
|
||||
res = iso14443a_select_card(uid, NULL, &cuid, true, 0, false);
|
||||
res = iso14443a_select_card(uid, card, &cuid, true, 0, false);
|
||||
if (res) {
|
||||
if (cuid == 0xAA55C396) {
|
||||
flag |= MAGIC_FLAG_GEN_UNFUSED;
|
||||
}
|
||||
|
||||
ReaderTransmit(rats, sizeof(rats), NULL);
|
||||
res = ReaderReceive(buf, PM3_CMD_DATA_SIZE, par);
|
||||
if (memcmp(card->ats, "\x09\x78\x00\x91\x02\xDA\xBC\x19\x10", 9) == 0) {
|
||||
// test for some MFC gen2
|
||||
isGen2 = true;
|
||||
flag |= MAGIC_FLAG_GEN_2;
|
||||
} else if (memcmp(card->ats, "\x0D\x78\x00\x71\x02\x88\x49\xA1\x30\x20\x15\x06\x08\x56\x3D", 15) == 0) {
|
||||
// test for some MFC 7b gen2
|
||||
isGen2 = true;
|
||||
flag |= MAGIC_FLAG_GEN_2;
|
||||
} else if (memcmp(card->ats, "\x0A\x78\x00\x81\x02\xDB\xA0\xC1\x19\x40\x2A\xB5", 12) == 0) {
|
||||
// test for Ultralight magic gen2
|
||||
isGen2 = true;
|
||||
flag |= MAGIC_FLAG_GEN_2;
|
||||
} else if (memcmp(card->ats, "\x85\x00\x00\xA0\x00\x00\x0A\xC3\x00\x04\x03\x01\x01\x00\x0B\x03\x41\xDF", 18) == 0) {
|
||||
// test for Ultralight EV1 magic gen2
|
||||
isGen2 = true;
|
||||
flag |= MAGIC_FLAG_GEN_2;
|
||||
} else if (memcmp(card->ats, "\x85\x00\x00\xA0\x0A\x00\x0A\xC3\x00\x04\x03\x01\x01\x00\x0B\x03\x16\xD7", 18) == 0) {
|
||||
// test for some other Ultralight EV1 magic gen2
|
||||
isGen2 = true;
|
||||
flag |= MAGIC_FLAG_GEN_2;
|
||||
} else if (memcmp(card->ats, "\x85\x00\x00\xA0\x0A\x00\x0A\xB0\x00\x00\x00\x00\x00\x00\x00\x00\x18\x4D", 18) == 0) {
|
||||
// test for some other Ultralight magic gen2
|
||||
isGen2 = true;
|
||||
flag |= MAGIC_FLAG_GEN_2;
|
||||
} else if (memcmp(card->ats, "\x85\x00\x00\xA0\x00\x00\x0A\xA5\x00\x04\x04\x02\x01\x00\x0F\x03\x79\x0C", 18) == 0) {
|
||||
// test for NTAG213 magic gen2
|
||||
isGen2 = true;
|
||||
flag |= MAGIC_FLAG_GEN_2;
|
||||
}
|
||||
|
||||
if (res) {
|
||||
if (memcmp(buf, "\x09\x78\x00\x91\x02\xDA\xBC\x19\x10", 9) == 0) {
|
||||
// test for some MFC gen2
|
||||
isGen2 = true;
|
||||
flag |= MAGIC_FLAG_GEN_2;
|
||||
} else if (memcmp(buf, "\x0D\x78\x00\x71\x02\x88\x49\xA1\x30\x20\x15\x06\x08\x56\x3D", 15) == 0) {
|
||||
// test for some MFC 7b gen2
|
||||
isGen2 = true;
|
||||
flag |= MAGIC_FLAG_GEN_2;
|
||||
} else if (memcmp(buf, "\x0A\x78\x00\x81\x02\xDB\xA0\xC1\x19\x40\x2A\xB5", 12) == 0) {
|
||||
// test for Ultralight magic gen2
|
||||
isGen2 = true;
|
||||
flag |= MAGIC_FLAG_GEN_2;
|
||||
} else if (memcmp(buf, "\x85\x00\x00\xA0\x00\x00\x0A\xC3\x00\x04\x03\x01\x01\x00\x0B\x03\x41\xDF", 18) == 0) {
|
||||
// test for Ultralight EV1 magic gen2
|
||||
isGen2 = true;
|
||||
flag |= MAGIC_FLAG_GEN_2;
|
||||
} else if (memcmp(buf, "\x85\x00\x00\xA0\x0A\x00\x0A\xC3\x00\x04\x03\x01\x01\x00\x0B\x03\x16\xD7", 18) == 0) {
|
||||
// test for some other Ultralight EV1 magic gen2
|
||||
isGen2 = true;
|
||||
flag |= MAGIC_FLAG_GEN_2;
|
||||
} else if (memcmp(buf, "\x85\x00\x00\xA0\x0A\x00\x0A\xB0\x00\x00\x00\x00\x00\x00\x00\x00\x18\x4D", 18) == 0) {
|
||||
// test for some other Ultralight magic gen2
|
||||
isGen2 = true;
|
||||
flag |= MAGIC_FLAG_GEN_2;
|
||||
} else if (memcmp(buf, "\x85\x00\x00\xA0\x00\x00\x0A\xA5\x00\x04\x04\x02\x01\x00\x0F\x03\x79\x0C", 18) == 0) {
|
||||
// test for NTAG213 magic gen2
|
||||
isGen2 = true;
|
||||
flag |= MAGIC_FLAG_GEN_2;
|
||||
// test for super card
|
||||
ReaderTransmit(superGen1, sizeof(superGen1), NULL);
|
||||
res = ReaderReceive(buf, PM3_CMD_DATA_SIZE, par);
|
||||
if (res == 22) {
|
||||
uint8_t isGen = MAGIC_FLAG_SUPER_GEN1;
|
||||
|
||||
// check for super card gen2
|
||||
// not available after RATS, reset card before executing
|
||||
mf_reset_card();
|
||||
|
||||
iso14443a_select_card(uid, NULL, &cuid, true, 0, true);
|
||||
ReaderTransmit(rdbl00, sizeof(rdbl00), NULL);
|
||||
res = ReaderReceive(buf, PM3_CMD_DATA_SIZE, par);
|
||||
if (res == 18) {
|
||||
isGen = MAGIC_FLAG_SUPER_GEN2;
|
||||
}
|
||||
|
||||
// test for super card
|
||||
ReaderTransmit(superGen1, sizeof(superGen1), NULL);
|
||||
flag |= isGen;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_mfc == false) {
|
||||
// magic ntag test
|
||||
mf_reset_card();
|
||||
|
||||
res = iso14443a_select_card(uid, NULL, &cuid, true, 0, true);
|
||||
if (res == 2) {
|
||||
ReaderTransmit(rdblf0, sizeof(rdblf0), NULL);
|
||||
res = ReaderReceive(buf, PM3_CMD_DATA_SIZE, par);
|
||||
if (res == 22) {
|
||||
uint8_t isGen = MAGIC_FLAG_SUPER_GEN1;
|
||||
|
||||
// check for super card gen2
|
||||
// not available after RATS, reset card before executing
|
||||
mf_reset_card();
|
||||
|
||||
iso14443a_select_card(uid, NULL, &cuid, true, 0, true);
|
||||
ReaderTransmit(rdbl00, sizeof(rdbl00), NULL);
|
||||
res = ReaderReceive(buf, PM3_CMD_DATA_SIZE, par);
|
||||
if (res == 18) {
|
||||
isGen = MAGIC_FLAG_SUPER_GEN2;
|
||||
}
|
||||
|
||||
flag |= isGen;
|
||||
if (res == 18) {
|
||||
flag |= MAGIC_FLAG_NTAG21X;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_mfc == false) {
|
||||
// magic ntag test
|
||||
} else {
|
||||
|
||||
struct Crypto1State mpcs = {0, 0};
|
||||
struct Crypto1State *pcs;
|
||||
pcs = &mpcs;
|
||||
|
||||
// CUID (with default sector 0 B key) test
|
||||
// regular cards will NAK the WRITEBLOCK(0) command, while DirectWrite will ACK it
|
||||
// if we do get an ACK, we immediately abort to ensure nothing is ever actually written
|
||||
// only perform test if we haven't already identified Gen2. No need test if we have a positive identification already
|
||||
if (isGen2 == false) {
|
||||
mf_reset_card();
|
||||
|
||||
res = iso14443a_select_card(uid, NULL, &cuid, true, 0, true);
|
||||
if (res == 2) {
|
||||
ReaderTransmit(rdblf0, sizeof(rdblf0), NULL);
|
||||
res = ReaderReceive(buf, PM3_CMD_DATA_SIZE, par);
|
||||
if (res == 18) {
|
||||
flag |= MAGIC_FLAG_NTAG21X;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (res) {
|
||||
|
||||
struct Crypto1State mpcs = {0, 0};
|
||||
struct Crypto1State *pcs;
|
||||
pcs = &mpcs;
|
||||
uint64_t tmpkey = bytes_to_num(key, 6);
|
||||
if (mifare_classic_authex(pcs, cuid, 0, keytype, tmpkey, AUTH_FIRST, NULL, NULL) == 0) {
|
||||
|
||||
// CUID (with default sector 0 B key) test
|
||||
// regular cards will NAK the WRITEBLOCK(0) command, while DirectWrite will ACK it
|
||||
// if we do get an ACK, we immediately abort to ensure nothing is ever actually written
|
||||
// only perform test if we haven't already identified Gen2. No need test if we have a positive identification already
|
||||
if (isGen2 == false) {
|
||||
mf_reset_card();
|
||||
|
||||
res = iso14443a_select_card(uid, NULL, &cuid, true, 0, true);
|
||||
if (res) {
|
||||
|
||||
uint64_t tmpkey = bytes_to_num(key, 6);
|
||||
if (mifare_classic_authex(pcs, cuid, 0, keytype, tmpkey, AUTH_FIRST, NULL, NULL) == 0) {
|
||||
|
||||
if ((mifare_sendcmd_short(pcs, 1, ISO14443A_CMD_WRITEBLOCK, 0, buf, PM3_CMD_DATA_SIZE, par, NULL) == 1) && (buf[0] == 0x0A)) {
|
||||
flag |= MAGIC_FLAG_GEN_2;
|
||||
// turn off immediately to ensure nothing ever accidentally writes to the block
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
}
|
||||
if ((mifare_sendcmd_short(pcs, 1, ISO14443A_CMD_WRITEBLOCK, 0, buf, PM3_CMD_DATA_SIZE, par, NULL) == 1) && (buf[0] == 0x0A)) {
|
||||
flag |= MAGIC_FLAG_GEN_2;
|
||||
// turn off immediately to ensure nothing ever accidentally writes to the block
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
}
|
||||
crypto1_deinit(pcs);
|
||||
}
|
||||
}
|
||||
|
||||
// magic MFC Gen3 test 1
|
||||
mf_reset_card();
|
||||
|
||||
res = iso14443a_select_card(uid, NULL, &cuid, true, 0, true);
|
||||
if (res) {
|
||||
ReaderTransmit(rdbl00, sizeof(rdbl00), NULL);
|
||||
res = ReaderReceive(buf, PM3_CMD_DATA_SIZE, par);
|
||||
if (res == 18) {
|
||||
flag |= MAGIC_FLAG_GEN_3;
|
||||
}
|
||||
}
|
||||
|
||||
// magic MFC Gen4 GDM magic auth test
|
||||
mf_reset_card();
|
||||
|
||||
res = iso14443a_select_card(uid, NULL, &cuid, true, 0, true);
|
||||
if (res) {
|
||||
ReaderTransmit(gen4gdmAuth, sizeof(gen4gdmAuth), NULL);
|
||||
res = ReaderReceive(buf, PM3_CMD_DATA_SIZE, par);
|
||||
if (res == 4) {
|
||||
flag |= MAGIC_FLAG_GDM_AUTH;
|
||||
}
|
||||
}
|
||||
|
||||
// QL88 test
|
||||
mf_reset_card();
|
||||
|
||||
res = iso14443a_select_card(uid, NULL, &cuid, true, 0, true);
|
||||
if (res) {
|
||||
if (mifare_classic_authex(pcs, cuid, 68, MF_KEY_B, 0x707B11FC1481, AUTH_FIRST, NULL, NULL) == 0) {
|
||||
flag |= MAGIC_FLAG_QL88;
|
||||
}
|
||||
crypto1_deinit(pcs);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// magic MFC Gen3 test 1
|
||||
mf_reset_card();
|
||||
|
||||
res = iso14443a_select_card(uid, NULL, &cuid, true, 0, true);
|
||||
if (res) {
|
||||
ReaderTransmit(rdbl00, sizeof(rdbl00), NULL);
|
||||
res = ReaderReceive(buf, PM3_CMD_DATA_SIZE, par);
|
||||
if (res == 18) {
|
||||
flag |= MAGIC_FLAG_GEN_3;
|
||||
}
|
||||
}
|
||||
|
||||
// magic MFC Gen4 GDM magic auth test
|
||||
mf_reset_card();
|
||||
|
||||
res = iso14443a_select_card(uid, NULL, &cuid, true, 0, true);
|
||||
if (res) {
|
||||
ReaderTransmit(gen4gdmAuth, sizeof(gen4gdmAuth), NULL);
|
||||
res = ReaderReceive(buf, PM3_CMD_DATA_SIZE, par);
|
||||
if (res == 4) {
|
||||
flag |= MAGIC_FLAG_GDM_AUTH;
|
||||
}
|
||||
}
|
||||
|
||||
// QL88 test
|
||||
mf_reset_card();
|
||||
|
||||
res = iso14443a_select_card(uid, NULL, &cuid, true, 0, true);
|
||||
if (res) {
|
||||
|
||||
if (mifare_classic_authex(pcs, cuid, 68, MF_KEY_B, 0x707B11FC1481, AUTH_FIRST, NULL, NULL) == 0) {
|
||||
flag |= MAGIC_FLAG_QL88;
|
||||
}
|
||||
crypto1_deinit(pcs);
|
||||
}
|
||||
}
|
||||
|
||||
// GDM alt magic wakeup (20)
|
||||
ReaderTransmitBitsPar(wupGDM1, 7, NULL, NULL);
|
||||
|
||||
@@ -43,8 +43,6 @@ void MifareChkKeys(uint8_t *datain, uint8_t reserved_mem);
|
||||
void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
|
||||
void MifareChkKeys_file(uint8_t *fn);
|
||||
|
||||
void MifareEMemClr(void);
|
||||
void MifareEMemGet(uint8_t blockno, uint8_t blockcnt);
|
||||
int MifareECardLoad(uint8_t sectorcnt, uint8_t keytype, uint8_t *key);
|
||||
int MifareECardLoadExt(uint8_t sectorcnt, uint8_t keytype, uint8_t *key);
|
||||
|
||||
|
||||
+86
-41
@@ -48,8 +48,8 @@
|
||||
#include "parity.h"
|
||||
|
||||
static bool IsKeyBReadable(uint8_t blockNo) {
|
||||
uint8_t sector_trailer[16];
|
||||
emlGetMem(sector_trailer, SectorTrailer(blockNo), 1);
|
||||
uint8_t sector_trailer[MIFARE_BLOCK_SIZE] = {0};
|
||||
emlGetMem_xt(sector_trailer, SectorTrailer(blockNo), 1, MIFARE_BLOCK_SIZE);
|
||||
uint8_t AC = ((sector_trailer[7] >> 5) & 0x04)
|
||||
| ((sector_trailer[8] >> 2) & 0x02)
|
||||
| ((sector_trailer[8] >> 7) & 0x01);
|
||||
@@ -57,55 +57,64 @@ static bool IsKeyBReadable(uint8_t blockNo) {
|
||||
}
|
||||
|
||||
static bool IsTrailerAccessAllowed(uint8_t blockNo, uint8_t keytype, uint8_t action) {
|
||||
uint8_t sector_trailer[16];
|
||||
emlGetMem(sector_trailer, blockNo, 1);
|
||||
uint8_t sector_trailer[MIFARE_BLOCK_SIZE] = {0};
|
||||
emlGetMem_xt(sector_trailer, blockNo, 1, MIFARE_BLOCK_SIZE);
|
||||
|
||||
uint8_t AC = ((sector_trailer[7] >> 5) & 0x04)
|
||||
| ((sector_trailer[8] >> 2) & 0x02)
|
||||
| ((sector_trailer[8] >> 7) & 0x01);
|
||||
|
||||
switch (action) {
|
||||
case AC_KEYA_READ: {
|
||||
if (g_dbglevel >= DBG_EXTENDED)
|
||||
if (g_dbglevel >= DBG_EXTENDED) {
|
||||
Dbprintf("IsTrailerAccessAllowed: AC_KEYA_READ");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
case AC_KEYA_WRITE: {
|
||||
if (g_dbglevel >= DBG_EXTENDED)
|
||||
if (g_dbglevel >= DBG_EXTENDED) {
|
||||
Dbprintf("IsTrailerAccessAllowed: AC_KEYA_WRITE");
|
||||
}
|
||||
return ((keytype == AUTHKEYA && (AC == 0x00 || AC == 0x01))
|
||||
|| (keytype == AUTHKEYB && (AC == 0x04 || AC == 0x03)));
|
||||
}
|
||||
case AC_KEYB_READ: {
|
||||
if (g_dbglevel >= DBG_EXTENDED)
|
||||
if (g_dbglevel >= DBG_EXTENDED) {
|
||||
Dbprintf("IsTrailerAccessAllowed: AC_KEYB_READ");
|
||||
}
|
||||
return (keytype == AUTHKEYA && (AC == 0x00 || AC == 0x02 || AC == 0x01));
|
||||
}
|
||||
case AC_KEYB_WRITE: {
|
||||
if (g_dbglevel >= DBG_EXTENDED)
|
||||
if (g_dbglevel >= DBG_EXTENDED) {
|
||||
Dbprintf("IsTrailerAccessAllowed: AC_KEYB_WRITE");
|
||||
}
|
||||
return ((keytype == AUTHKEYA && (AC == 0x00 || AC == 0x01))
|
||||
|| (keytype == AUTHKEYB && (AC == 0x04 || AC == 0x03)));
|
||||
}
|
||||
case AC_AC_READ: {
|
||||
if (g_dbglevel >= DBG_EXTENDED)
|
||||
if (g_dbglevel >= DBG_EXTENDED) {
|
||||
Dbprintf("IsTrailerAccessAllowed: AC_AC_READ");
|
||||
}
|
||||
return ((keytype == AUTHKEYA)
|
||||
|| (keytype == AUTHKEYB && !(AC == 0x00 || AC == 0x02 || AC == 0x01)));
|
||||
}
|
||||
case AC_AC_WRITE: {
|
||||
if (g_dbglevel >= DBG_EXTENDED)
|
||||
if (g_dbglevel >= DBG_EXTENDED) {
|
||||
Dbprintf("IsTrailerAccessAllowed: AC_AC_WRITE");
|
||||
}
|
||||
return ((keytype == AUTHKEYA && (AC == 0x01))
|
||||
|| (keytype == AUTHKEYB && (AC == 0x03 || AC == 0x05)));
|
||||
}
|
||||
default:
|
||||
default: {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool IsDataAccessAllowed(uint8_t blockNo, uint8_t keytype, uint8_t action) {
|
||||
|
||||
uint8_t sector_trailer[16];
|
||||
emlGetMem(sector_trailer, SectorTrailer(blockNo), 1);
|
||||
uint8_t sector_trailer[MIFARE_BLOCK_SIZE] = {0};
|
||||
emlGetMem_xt(sector_trailer, SectorTrailer(blockNo), 1, MIFARE_BLOCK_SIZE);
|
||||
|
||||
uint8_t sector_block;
|
||||
if (blockNo <= MIFARE_2K_MAXBLOCK) {
|
||||
@@ -120,54 +129,62 @@ static bool IsDataAccessAllowed(uint8_t blockNo, uint8_t keytype, uint8_t action
|
||||
AC = ((sector_trailer[7] >> 2) & 0x04)
|
||||
| ((sector_trailer[8] << 1) & 0x02)
|
||||
| ((sector_trailer[8] >> 4) & 0x01);
|
||||
if (g_dbglevel >= DBG_EXTENDED)
|
||||
if (g_dbglevel >= DBG_EXTENDED) {
|
||||
Dbprintf("IsDataAccessAllowed: case 0x00 - %02x", AC);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 0x01: {
|
||||
AC = ((sector_trailer[7] >> 3) & 0x04)
|
||||
| ((sector_trailer[8] >> 0) & 0x02)
|
||||
| ((sector_trailer[8] >> 5) & 0x01);
|
||||
if (g_dbglevel >= DBG_EXTENDED)
|
||||
if (g_dbglevel >= DBG_EXTENDED) {
|
||||
Dbprintf("IsDataAccessAllowed: case 0x01 - %02x", AC);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 0x02: {
|
||||
AC = ((sector_trailer[7] >> 4) & 0x04)
|
||||
| ((sector_trailer[8] >> 1) & 0x02)
|
||||
| ((sector_trailer[8] >> 6) & 0x01);
|
||||
if (g_dbglevel >= DBG_EXTENDED)
|
||||
if (g_dbglevel >= DBG_EXTENDED) {
|
||||
Dbprintf("IsDataAccessAllowed: case 0x02 - %02x", AC);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
if (g_dbglevel >= DBG_EXTENDED)
|
||||
if (g_dbglevel >= DBG_EXTENDED) {
|
||||
Dbprintf("IsDataAccessAllowed: Error");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (action) {
|
||||
case AC_DATA_READ: {
|
||||
if (g_dbglevel >= DBG_EXTENDED)
|
||||
if (g_dbglevel >= DBG_EXTENDED) {
|
||||
Dbprintf("IsDataAccessAllowed - AC_DATA_READ: OK");
|
||||
}
|
||||
return ((keytype == AUTHKEYA && !(AC == 0x03 || AC == 0x05 || AC == 0x07))
|
||||
|| (keytype == AUTHKEYB && !(AC == 0x07)));
|
||||
}
|
||||
case AC_DATA_WRITE: {
|
||||
if (g_dbglevel >= DBG_EXTENDED)
|
||||
if (g_dbglevel >= DBG_EXTENDED) {
|
||||
Dbprintf("IsDataAccessAllowed - AC_DATA_WRITE: OK");
|
||||
}
|
||||
return ((keytype == AUTHKEYA && (AC == 0x00))
|
||||
|| (keytype == AUTHKEYB && (AC == 0x00 || AC == 0x04 || AC == 0x06 || AC == 0x03)));
|
||||
}
|
||||
case AC_DATA_INC: {
|
||||
if (g_dbglevel >= DBG_EXTENDED)
|
||||
if (g_dbglevel >= DBG_EXTENDED) {
|
||||
Dbprintf("IsDataAccessAllowed - AC_DATA_INC: OK");
|
||||
}
|
||||
return ((keytype == AUTHKEYA && (AC == 0x00))
|
||||
|| (keytype == AUTHKEYB && (AC == 0x00 || AC == 0x06)));
|
||||
}
|
||||
case AC_DATA_DEC_TRANS_REST: {
|
||||
if (g_dbglevel >= DBG_EXTENDED)
|
||||
if (g_dbglevel >= DBG_EXTENDED) {
|
||||
Dbprintf("AC_DATA_DEC_TRANS_REST: OK");
|
||||
}
|
||||
return ((keytype == AUTHKEYA && (AC == 0x00 || AC == 0x06 || AC == 0x01))
|
||||
|| (keytype == AUTHKEYB && (AC == 0x00 || AC == 0x06 || AC == 0x01)));
|
||||
}
|
||||
@@ -252,29 +269,33 @@ bool MifareSimInit(uint16_t flags, uint8_t *uid, uint16_t atqa, uint8_t sak, tag
|
||||
// Length: 4,7,or 10 bytes
|
||||
|
||||
if (IS_FLAG_UID_IN_EMUL(flags)) {
|
||||
|
||||
if (uid == NULL) {
|
||||
uid = uid_tmp;
|
||||
}
|
||||
// Get UID, SAK, ATQA from EMUL
|
||||
uint8_t block0[16];
|
||||
emlGet(block0, 0, 16);
|
||||
uint8_t block0[MIFARE_BLOCK_SIZE];
|
||||
emlGet(block0, 0, MIFARE_BLOCK_SIZE);
|
||||
|
||||
// Check for 4 bytes uid: bcc corrected and single size uid bits in ATQA
|
||||
if ((block0[0] ^ block0[1] ^ block0[2] ^ block0[3]) == block0[4] && (block0[6] & 0xc0) == 0) {
|
||||
FLAG_SET_UID_IN_DATA(flags, 4);
|
||||
memcpy(uid, block0, 4);
|
||||
rSAK[0] = block0[5];
|
||||
memcpy(rATQA, &block0[6], sizeof(rATQA));
|
||||
}
|
||||
// Check for 7 bytes UID: double size uid bits in ATQA
|
||||
else if ((block0[8] & 0xc0) == 0x40) {
|
||||
|
||||
} else if ((block0[8] & 0xc0) == 0x40) {
|
||||
// Check for 7 bytes UID: double size uid bits in ATQA
|
||||
FLAG_SET_UID_IN_DATA(flags, 7);
|
||||
memcpy(uid, block0, 7);
|
||||
rSAK[0] = block0[7];
|
||||
memcpy(rATQA, &block0[8], sizeof(rATQA));
|
||||
|
||||
} else {
|
||||
Dbprintf("ERROR: " _RED_("Invalid dump. UID/SAK/ATQA not found"));
|
||||
return false;
|
||||
}
|
||||
|
||||
} else {
|
||||
if (uid == NULL) {
|
||||
Dbprintf("ERROR: " _RED_("Missing UID"));
|
||||
@@ -288,16 +309,19 @@ bool MifareSimInit(uint16_t flags, uint8_t *uid, uint16_t atqa, uint8_t sak, tag
|
||||
memcpy(rATQA, rATQA_Mini, sizeof(rATQA));
|
||||
rSAK[0] = rSAK_Mini;
|
||||
if (g_dbglevel > DBG_NONE) Dbprintf("Enforcing Mifare Mini ATQA/SAK");
|
||||
|
||||
} else if (IS_FLAG_MF_SIZE(flags, MIFARE_1K_MAX_BYTES)) {
|
||||
memcpy(rATQA, rATQA_1k, sizeof(rATQA));
|
||||
rSAK[0] = rSAK_1k;
|
||||
if (g_dbglevel > DBG_NONE) Dbprintf("Enforcing Mifare 1K ATQA/SAK");
|
||||
|
||||
} else if (IS_FLAG_MF_SIZE(flags, MIFARE_2K_MAX_BYTES)) {
|
||||
memcpy(rATQA, rATQA_2k, sizeof(rATQA));
|
||||
rSAK[0] = rSAK_2k;
|
||||
*rats = rRATS;
|
||||
*rats_len = sizeof(rRATS);
|
||||
if (g_dbglevel > DBG_NONE) Dbprintf("Enforcing Mifare 2K ATQA/SAK with RATS support");
|
||||
|
||||
} else if (IS_FLAG_MF_SIZE(flags, MIFARE_4K_MAX_BYTES)) {
|
||||
memcpy(rATQA, rATQA_4k, sizeof(rATQA));
|
||||
rSAK[0] = rSAK_4k;
|
||||
@@ -825,8 +849,8 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *uid, uint16_t
|
||||
// if key not known and FLAG_NESTED_AUTH_ATTACK and we have nt/nt_enc/parity, send recorded nt_enc and parity
|
||||
if ((flags & FLAG_NESTED_AUTH_ATTACK) == FLAG_NESTED_AUTH_ATTACK) {
|
||||
if (emlGetKey(cardAUTHSC, cardAUTHKEY) == 0) {
|
||||
uint8_t buf[16] = {0};
|
||||
emlGetMem(buf, (CARD_MEMORY_RF08S_OFFSET / MIFARE_BLOCK_SIZE) + cardAUTHSC, 1);
|
||||
uint8_t buf[MIFARE_BLOCK_SIZE] = {0};
|
||||
emlGetMem_xt(buf, (CARD_MEMORY_RF08S_OFFSET / MIFARE_BLOCK_SIZE) + cardAUTHSC, 1, MIFARE_BLOCK_SIZE);
|
||||
if (buf[(cardAUTHKEY * 8) + 3] == 0xAA) { // extra check to tell we have nt/nt_enc/par_err
|
||||
running_nested_auth_attack = true;
|
||||
// nt
|
||||
@@ -955,7 +979,7 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *uid, uint16_t
|
||||
// first block
|
||||
if (blockNo == 4) {
|
||||
|
||||
p_em += blockNo * 16;
|
||||
p_em += (blockNo * MIFARE_BLOCK_SIZE);
|
||||
// TLV in NDEF, flip length between
|
||||
// 4 | 03 21 D1 02 1C 53 70 91 01 09 54 02 65 6E 4C 69
|
||||
// 0xFF means long length
|
||||
@@ -970,7 +994,7 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *uid, uint16_t
|
||||
}
|
||||
}
|
||||
|
||||
emlGetMem(response, blockNo, 1);
|
||||
emlGetMem_xt(response, blockNo, 1, MIFARE_BLOCK_SIZE);
|
||||
|
||||
if (g_dbglevel >= DBG_EXTENDED) {
|
||||
Dbprintf("[MFEMUL_WORK - ISO14443A_CMD_READBLOCK] Data Block[%d]: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", blockNo,
|
||||
@@ -1010,11 +1034,11 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *uid, uint16_t
|
||||
}
|
||||
} else {
|
||||
if (IsAccessAllowed(blockNo, cardAUTHKEY, AC_DATA_READ) == false) {
|
||||
memset(response, 0x00, 16); // datablock cannot be read
|
||||
memset(response, 0x00, MIFARE_BLOCK_SIZE); // datablock cannot be read
|
||||
if (g_dbglevel >= DBG_EXTENDED) Dbprintf("[MFEMUL_WORK - IsAccessAllowed] Data block %d (0x%02x) cannot be read", blockNo, blockNo);
|
||||
}
|
||||
}
|
||||
AddCrc14A(response, 16);
|
||||
AddCrc14A(response, MIFARE_BLOCK_SIZE);
|
||||
mf_crypto1_encrypt(pcs, response, MAX_MIFARE_FRAME_SIZE, response_par);
|
||||
EmSendCmdPar(response, MAX_MIFARE_FRAME_SIZE, response_par);
|
||||
FpgaDisableTracing();
|
||||
@@ -1109,7 +1133,9 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *uid, uint16_t
|
||||
|
||||
// case MFEMUL_WORK => CMD RATS
|
||||
if (receivedCmd_len == 4 && receivedCmd_dec[0] == ISO14443A_CMD_RATS && (receivedCmd_dec[1] & 0xF0) <= 0x80 && (receivedCmd_dec[1] & 0x0F) <= 0x0e) {
|
||||
|
||||
if (rats && rats_len) {
|
||||
|
||||
if (encrypted_data) {
|
||||
memcpy(response, rats, rats_len);
|
||||
mf_crypto1_encrypt(pcs, response, rats_len, response_par);
|
||||
@@ -1117,46 +1143,58 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *uid, uint16_t
|
||||
} else {
|
||||
EmSendCmd(rats, rats_len);
|
||||
}
|
||||
|
||||
FpgaDisableTracing();
|
||||
if (g_dbglevel >= DBG_EXTENDED)
|
||||
|
||||
if (g_dbglevel >= DBG_EXTENDED) {
|
||||
Dbprintf("[MFEMUL_WORK] RCV RATS => ACK");
|
||||
}
|
||||
|
||||
} else {
|
||||
EmSend4bit(encrypted_data ? mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA) : CARD_NACK_NA);
|
||||
FpgaDisableTracing();
|
||||
cardSTATE_TO_IDLE();
|
||||
if (g_dbglevel >= DBG_EXTENDED)
|
||||
if (g_dbglevel >= DBG_EXTENDED) {
|
||||
Dbprintf("[MFEMUL_WORK] RCV RATS => NACK");
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// case MFEMUL_WORK => ISO14443A_CMD_NXP_DESELECT
|
||||
if (receivedCmd_len == 3 && receivedCmd_dec[0] == ISO14443A_CMD_NXP_DESELECT) {
|
||||
|
||||
if (rats && rats_len) {
|
||||
|
||||
// response back NXP_DESELECT
|
||||
if (encrypted_data) {
|
||||
memcpy(response, receivedCmd_dec, receivedCmd_len);
|
||||
mf_crypto1_encrypt(pcs, response, receivedCmd_len, response_par);
|
||||
EmSendCmdPar(response, receivedCmd_len, response_par);
|
||||
} else
|
||||
} else {
|
||||
EmSendCmd(receivedCmd_dec, receivedCmd_len);
|
||||
}
|
||||
|
||||
FpgaDisableTracing();
|
||||
if (g_dbglevel >= DBG_EXTENDED)
|
||||
if (g_dbglevel >= DBG_EXTENDED) {
|
||||
Dbprintf("[MFEMUL_WORK] RCV NXP DESELECT => ACK");
|
||||
}
|
||||
|
||||
} else {
|
||||
EmSend4bit(encrypted_data ? mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA) : CARD_NACK_NA);
|
||||
FpgaDisableTracing();
|
||||
cardSTATE_TO_IDLE();
|
||||
if (g_dbglevel >= DBG_EXTENDED)
|
||||
if (g_dbglevel >= DBG_EXTENDED) {
|
||||
Dbprintf("[MFEMUL_WORK] RCV NXP DESELECT => NACK");
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// case MFEMUL_WORK => command not allowed
|
||||
if (g_dbglevel >= DBG_EXTENDED)
|
||||
if (g_dbglevel >= DBG_EXTENDED) {
|
||||
Dbprintf("Received command not allowed, nacking");
|
||||
}
|
||||
EmSend4bit(encrypted_data ? mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA) : CARD_NACK_NA);
|
||||
FpgaDisableTracing();
|
||||
break;
|
||||
@@ -1164,14 +1202,16 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *uid, uint16_t
|
||||
|
||||
// AUTH1
|
||||
case MFEMUL_AUTH1: {
|
||||
if (g_dbglevel >= DBG_EXTENDED)
|
||||
if (g_dbglevel >= DBG_EXTENDED) {
|
||||
Dbprintf("[MFEMUL_AUTH1] Enter case");
|
||||
}
|
||||
|
||||
if (receivedCmd_len != 8) {
|
||||
cardSTATE_TO_IDLE();
|
||||
LogTrace(uart->output, uart->len, uart->startTime * 16 - DELAY_AIR2ARM_AS_TAG, uart->endTime * 16 - DELAY_AIR2ARM_AS_TAG, uart->parity, true);
|
||||
if (g_dbglevel >= DBG_EXTENDED)
|
||||
if (g_dbglevel >= DBG_EXTENDED) {
|
||||
Dbprintf("MFEMUL_AUTH1: receivedCmd_len != 8 (%d) => cardSTATE_TO_IDLE())", receivedCmd_len);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1191,6 +1231,7 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *uid, uint16_t
|
||||
ar_nr_resp[0].state = NESTED;
|
||||
finished = true;
|
||||
}
|
||||
|
||||
if ((flags & FLAG_NR_AR_ATTACK) == FLAG_NR_AR_ATTACK) {
|
||||
|
||||
for (uint8_t i = 0; i < ATTACK_KEY_COUNT; i++) {
|
||||
@@ -1267,12 +1308,16 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *uid, uint16_t
|
||||
|
||||
// WRITE BL2
|
||||
case MFEMUL_WRITEBL2: {
|
||||
|
||||
if (receivedCmd_len == MAX_MIFARE_FRAME_SIZE) {
|
||||
|
||||
mf_crypto1_decryptEx(pcs, receivedCmd, receivedCmd_len, receivedCmd_dec);
|
||||
|
||||
if (CheckCrc14A(receivedCmd_dec, receivedCmd_len)) {
|
||||
|
||||
if (IsSectorTrailer(cardWRBL)) {
|
||||
|
||||
emlGetMem(response, cardWRBL, 1);
|
||||
emlGetMem_xt(response, cardWRBL, 1, MIFARE_BLOCK_SIZE);
|
||||
|
||||
if (IsAccessAllowed(cardWRBL, cardAUTHKEY, AC_KEYA_WRITE) == false) {
|
||||
memcpy(receivedCmd_dec, response, 6); // don't change KeyA
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user