mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-07-06 04:51:36 -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:
parent
6bb7199a7b
commit
cef07dedf6
57 changed files with 672 additions and 521 deletions
7
.github/workflows/codeql-analysis.yml
vendored
7
.github/workflows/codeql-analysis.yml
vendored
|
@ -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
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
@ -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: {
|
||||
|
|
|
@ -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,7 +279,8 @@ 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);
|
||||
|
@ -278,14 +288,6 @@ void Desfire_session_key_new(const uint8_t rnda[], const uint8_t rndb[], desfire
|
|||
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,14 +414,16 @@ 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
size_t block_size = DESFIRE(tag)->session_key ? key_block_size(DESFIRE(tag)->session_key) : 1;
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -499,9 +512,10 @@ void *mifare_cryto_preprocess_data(desfiretag_t tag, void *data, size_t *nbytes,
|
|||
}
|
||||
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,16 +542,18 @@ 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
|
||||
memset(res + *nbytes, 0, edl - *nbytes);
|
||||
|
||||
|
@ -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,10 +763,11 @@ 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (verified) {
|
||||
|
||||
|
@ -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,28 +835,32 @@ 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);
|
||||
|
@ -841,17 +868,20 @@ void mifare_cypher_single_block(desfirekey_t key, uint8_t *data, uint8_t *ivect,
|
|||
// 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);
|
||||
|
@ -859,31 +889,34 @@ void mifare_cypher_single_block(desfirekey_t key, uint8_t *data, uint8_t *ivect,
|
|||
// 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);
|
||||
|
||||
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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,41 +2963,37 @@ 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 (res) {
|
||||
if (memcmp(buf, "\x09\x78\x00\x91\x02\xDA\xBC\x19\x10", 9) == 0) {
|
||||
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(buf, "\x0D\x78\x00\x71\x02\x88\x49\xA1\x30\x20\x15\x06\x08\x56\x3D", 15) == 0) {
|
||||
} 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(buf, "\x0A\x78\x00\x81\x02\xDB\xA0\xC1\x19\x40\x2A\xB5", 12) == 0) {
|
||||
} 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(buf, "\x85\x00\x00\xA0\x00\x00\x0A\xC3\x00\x04\x03\x01\x01\x00\x0B\x03\x41\xDF", 18) == 0) {
|
||||
} 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(buf, "\x85\x00\x00\xA0\x0A\x00\x0A\xC3\x00\x04\x03\x01\x01\x00\x0B\x03\x16\xD7", 18) == 0) {
|
||||
} 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(buf, "\x85\x00\x00\xA0\x0A\x00\x0A\xB0\x00\x00\x00\x00\x00\x00\x00\x00\x18\x4D", 18) == 0) {
|
||||
} 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(buf, "\x85\x00\x00\xA0\x00\x00\x0A\xA5\x00\x04\x04\x02\x01\x00\x0F\x03\x79\x0C", 18) == 0) {
|
||||
} 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;
|
||||
|
@ -3064,6 +3032,7 @@ void MifareCIdent(bool is_mfc, uint8_t keytype, uint8_t *key) {
|
|||
flag |= MAGIC_FLAG_NTAG21X;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
struct Crypto1State mpcs = {0, 0};
|
||||
|
@ -3122,13 +3091,13 @@ void MifareCIdent(bool is_mfc, uint8_t keytype, uint8_t *key) {
|
|||
|
||||
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);
|
||||
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
} else if ((block0[8] & 0xc0) == 0x40) {
|
||||
// Check for 7 bytes UID: double size uid bits in ATQA
|
||||
else if ((block0[8] & 0xc0) == 0x40) {
|
||||
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
|
||||
|
|
|
@ -756,14 +756,16 @@ uint8_t FirstBlockOfSector(uint8_t sectorNo) {
|
|||
}
|
||||
|
||||
// work with emulator memory
|
||||
void emlSetMem_xt(uint8_t *data, int blockNum, int blocksCount, int block_width) {
|
||||
void emlSetMem_xt(uint8_t *data, uint16_t blockNum, uint8_t blocksCount, uint8_t block_width) {
|
||||
uint32_t offset = blockNum * block_width;
|
||||
uint32_t len = blocksCount * block_width;
|
||||
emlSet(data, offset, len);
|
||||
}
|
||||
|
||||
void emlGetMem(uint8_t *data, int blockNum, int blocksCount) {
|
||||
emlGet(data, (blockNum * 16), (blocksCount * 16));
|
||||
void emlGetMem_xt(uint8_t *data, uint16_t blockNum, uint8_t blocksCount, uint8_t block_width) {
|
||||
uint32_t offset = blockNum * block_width;
|
||||
uint32_t len = blocksCount * block_width;
|
||||
emlGet(data, offset, len);
|
||||
}
|
||||
|
||||
bool emlCheckValBl(int blockNum) {
|
||||
|
@ -817,10 +819,11 @@ uint64_t emlGetKey(int sectorNum, int keyType) {
|
|||
}
|
||||
|
||||
void emlClearMem(void) {
|
||||
|
||||
BigBuf_Clear_EM();
|
||||
|
||||
const uint8_t trailer[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x80, 0x69, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
|
||||
const uint8_t uid[] = {0xe6, 0x84, 0x87, 0xf3, 0x16, 0x88, 0x04, 0x00, 0x46, 0x8e, 0x45, 0x55, 0x4d, 0x70, 0x41, 0x04};
|
||||
uint8_t *mem = BigBuf_get_EM_addr();
|
||||
memset(mem, 0, CARD_MEMORY_SIZE);
|
||||
|
||||
// fill sectors trailer data
|
||||
for (uint16_t b = 3; b < MIFARE_4K_MAXBLOCK; ((b < MIFARE_2K_MAXBLOCK - 4) ? (b += 4) : (b += 16))) {
|
||||
|
|
|
@ -131,8 +131,9 @@ uint8_t SectorTrailer(uint8_t blockNo);
|
|||
|
||||
// emulator functions
|
||||
void emlClearMem(void);
|
||||
void emlSetMem_xt(uint8_t *data, int blockNum, int blocksCount, int block_width);
|
||||
void emlGetMem(uint8_t *data, int blockNum, int blocksCount);
|
||||
void emlSetMem_xt(uint8_t *data, uint16_t blockNum, uint8_t blocksCount, uint8_t block_width);
|
||||
void emlGetMem_xt(uint8_t *data, uint16_t blockNum, uint8_t blocksCount, uint8_t block_width);
|
||||
|
||||
uint64_t emlGetKey(int sectorNum, int keyType);
|
||||
int emlGetValBl(uint32_t *blReg, uint8_t *blBlock, int blockNum);
|
||||
void emlSetValBl(uint32_t blReg, uint8_t blBlock, int blockNum);
|
||||
|
|
|
@ -49,9 +49,9 @@ static int sam_send_request_iso15(const uint8_t *const request, const uint8_t re
|
|||
if (g_dbglevel >= DBG_DEBUG)
|
||||
DbpString("start sam_send_request_iso14a");
|
||||
|
||||
uint8_t * buf1 = BigBuf_malloc(ISO7816_MAX_FRAME);
|
||||
uint8_t * buf2 = BigBuf_malloc(ISO7816_MAX_FRAME);
|
||||
if(buf1 == NULL || buf2 == NULL){
|
||||
uint8_t *buf1 = BigBuf_malloc(ISO7816_MAX_FRAME);
|
||||
uint8_t *buf2 = BigBuf_malloc(ISO7816_MAX_FRAME);
|
||||
if (buf1 == NULL || buf2 == NULL) {
|
||||
res = PM3_EMALLOC;
|
||||
goto out;
|
||||
}
|
||||
|
@ -103,19 +103,19 @@ static int sam_send_request_iso15(const uint8_t *const request, const uint8_t re
|
|||
nfc_tx_len = sam_copy_payload_sam2nfc(nfc_tx_buf, sam_rx_buf);
|
||||
|
||||
bool is_cmd_check = (nfc_tx_buf[0] & 0x0F) == ICLASS_CMD_CHECK;
|
||||
if(is_cmd_check && break_on_nr_mac){
|
||||
if (is_cmd_check && break_on_nr_mac) {
|
||||
memcpy(response, nfc_tx_buf, nfc_tx_len);
|
||||
*response_len = nfc_tx_len;
|
||||
if (g_dbglevel >= DBG_INFO) {
|
||||
DbpString("NR-MAC: ");
|
||||
Dbhexdump((*response_len)-1, response+1, false);
|
||||
Dbhexdump((*response_len) - 1, response + 1, false);
|
||||
}
|
||||
res = PM3_SUCCESS;
|
||||
goto out;
|
||||
}
|
||||
|
||||
bool is_cmd_update = (nfc_tx_buf[0] & 0x0F) == ICLASS_CMD_UPDATE;
|
||||
if(is_cmd_update && prevent_epurse_update && nfc_tx_buf[0] == 0x87 && nfc_tx_buf[1] == 0x02){
|
||||
if (is_cmd_update && prevent_epurse_update && nfc_tx_buf[0] == 0x87 && nfc_tx_buf[1] == 0x02) {
|
||||
// block update(2) command and fake the response to prevent update of epurse
|
||||
|
||||
// NFC TX BUFFERS PREPARED BY SAM LOOKS LIKE:
|
||||
|
@ -124,8 +124,8 @@ static int sam_send_request_iso15(const uint8_t *const request, const uint8_t re
|
|||
// NFC RX BUFFERS EXPECTED BY SAM WOULD LOOK LIKE:
|
||||
// #2(FF FF FF FF) #1(C9 FD FF FF) 3A 47
|
||||
|
||||
memcpy(nfc_rx_buf+0, nfc_tx_buf+6, 4);
|
||||
memcpy(nfc_rx_buf+4, nfc_tx_buf+0, 4);
|
||||
memcpy(nfc_rx_buf + 0, nfc_tx_buf + 6, 4);
|
||||
memcpy(nfc_rx_buf + 4, nfc_tx_buf + 0, 4);
|
||||
AddCrc(nfc_rx_buf, 8);
|
||||
nfc_rx_len = 10;
|
||||
|
||||
|
@ -155,7 +155,7 @@ static int sam_send_request_iso15(const uint8_t *const request, const uint8_t re
|
|||
}
|
||||
|
||||
|
||||
if (res != PM3_SUCCESS ) {
|
||||
if (res != PM3_SUCCESS) {
|
||||
res = PM3_ECARDEXCHANGE;
|
||||
goto out;
|
||||
}
|
||||
|
@ -358,7 +358,7 @@ int sam_picopass_get_pacs(PacketCommandNG *c) {
|
|||
|
||||
// implicit StartSspClk() happens here
|
||||
Iso15693InitReader();
|
||||
if(!select_iclass_tag(&card_a_info, false, &eof_time, shallow_mod)){
|
||||
if (!select_iclass_tag(&card_a_info, false, &eof_time, shallow_mod)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
|
|
|
@ -129,9 +129,9 @@ static int sam_send_request_iso14a(const uint8_t *const request, const uint8_t r
|
|||
if (g_dbglevel >= DBG_DEBUG)
|
||||
DbpString("start sam_send_request_iso14a");
|
||||
|
||||
uint8_t * buf1 = BigBuf_malloc(ISO7816_MAX_FRAME);
|
||||
uint8_t * buf2 = BigBuf_malloc(ISO7816_MAX_FRAME);
|
||||
if(buf1 == NULL || buf2 == NULL){
|
||||
uint8_t *buf1 = BigBuf_malloc(ISO7816_MAX_FRAME);
|
||||
uint8_t *buf2 = BigBuf_malloc(ISO7816_MAX_FRAME);
|
||||
if (buf1 == NULL || buf2 == NULL) {
|
||||
res = PM3_EMALLOC;
|
||||
goto out;
|
||||
}
|
||||
|
|
|
@ -548,7 +548,7 @@ static s32_t spiffs_page_consistency_check_i(spiffs *fs) {
|
|||
SPIFFS_API_CHECK_RES(fs, SPIFFS_ERR_INTERNAL);
|
||||
}
|
||||
// this checks for overflow of the multiplication of block_count+1 with SPIFFS_PAGES_PER_BLOCK(fs)
|
||||
if (((uint32_t)(-1)) / SPIFFS_PAGES_PER_BLOCK(fs) > (block_count+1)) {
|
||||
if (((uint32_t)(-1)) / SPIFFS_PAGES_PER_BLOCK(fs) > (block_count + 1)) {
|
||||
// checking with +1 block count to avoid overflow also in inner loop, which adds one page...
|
||||
// would exceed value storable in uint32_t
|
||||
SPIFFS_DBG("Overflow: pages per block %04x with block count "_SPIPRIbl" results in overflow\n", SPIFFS_PAGES_PER_BLOCK(fs), block_count);
|
||||
|
@ -556,13 +556,13 @@ static s32_t spiffs_page_consistency_check_i(spiffs *fs) {
|
|||
}
|
||||
// because loop indices are using spiffs_page_ix type,
|
||||
// that type can hold a large enough value
|
||||
if (total_blocks > ((spiffs_page_ix)-1)) {
|
||||
if (total_blocks > ((spiffs_page_ix) - 1)) {
|
||||
SPIFFS_DBG("Avoiding infinite loop, total_blocks "_SPIPRIpg" too large for spiffs_page_ix type\n", total_blocks);
|
||||
SPIFFS_CHECK_RES(SPIFFS_ERR_INTERNAL);
|
||||
}
|
||||
// because loop indices are using spiffs_page_ix type,
|
||||
// that type can hold a large enough value
|
||||
if (total_blocks_plus_one_page > ((spiffs_page_ix)-1) || total_blocks_plus_one_page < total_blocks) {
|
||||
if (total_blocks_plus_one_page > ((spiffs_page_ix) - 1) || total_blocks_plus_one_page < total_blocks) {
|
||||
SPIFFS_DBG("Avoiding infinite loop, total_blocks_plus_one_page "_SPIPRIpg" too large for spiffs_page_ix type\n", total_blocks_plus_one_page);
|
||||
SPIFFS_CHECK_RES(SPIFFS_ERR_INTERNAL);
|
||||
}
|
||||
|
@ -586,7 +586,7 @@ static s32_t spiffs_page_consistency_check_i(spiffs *fs) {
|
|||
0);
|
||||
// traverse each page except for lookup pages
|
||||
spiffs_page_ix cur_pix = SPIFFS_OBJ_LOOKUP_PAGES(fs) + SPIFFS_PAGES_PER_BLOCK(fs) * cur_block;
|
||||
while (!restart && cur_pix < SPIFFS_PAGES_PER_BLOCK(fs) * (cur_block+1)) {
|
||||
while (!restart && cur_pix < SPIFFS_PAGES_PER_BLOCK(fs) * (cur_block + 1)) {
|
||||
//if ((cur_pix & 0xff) == 0)
|
||||
// SPIFFS_CHECK_DBG("PA: processing pix "_SPIPRIpg", block "_SPIPRIbl" of pix "_SPIPRIpg", block "_SPIPRIbl"\n",
|
||||
// cur_pix, cur_block, total_blocks, block_count);
|
||||
|
|
|
@ -3857,14 +3857,17 @@ int CmdHF14AAIDSim(const char *Cmd) {
|
|||
bool keypress = kbd_enter_pressed();
|
||||
while (keypress == false) {
|
||||
|
||||
if (WaitForResponseTimeout(CMD_HF_MIFARE_SIMULATE, &resp, 1500) == 0)
|
||||
if (WaitForResponseTimeout(CMD_HF_MIFARE_SIMULATE, &resp, 1500) == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (resp.status != PM3_SUCCESS)
|
||||
if (resp.status != PM3_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
|
||||
if ((flags & FLAG_NR_AR_ATTACK) != FLAG_NR_AR_ATTACK)
|
||||
if ((flags & FLAG_NR_AR_ATTACK) != FLAG_NR_AR_ATTACK) {
|
||||
break;
|
||||
}
|
||||
|
||||
keypress = kbd_enter_pressed();
|
||||
}
|
||||
|
|
|
@ -282,9 +282,9 @@ static const productName_t uidmapping[] = {
|
|||
static int CmdHF15Help(const char *Cmd);
|
||||
|
||||
static int nxp_15693_print_signature(uint8_t *uid, uint8_t *signature) {
|
||||
|
||||
int reason = 0;
|
||||
int index = -1;
|
||||
index = originality_check_verify(uid, 8, signature, 32, PK_MFC);
|
||||
int index = originality_check_verify(uid, 8, signature, 32, PK_MFC);
|
||||
if (index >= 0) {
|
||||
reason = 1;
|
||||
} else {
|
||||
|
@ -306,11 +306,12 @@ static int nxp_15693_print_signature(uint8_t *uid, uint8_t *signature) {
|
|||
}
|
||||
}
|
||||
}
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
|
||||
int ret = originality_check_print(signature, 32, index);
|
||||
if (ret != PM3_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
switch (reason) {
|
||||
case 1:
|
||||
PrintAndLogEx(INFO, " Params used: UID and signature, plain");
|
||||
|
|
|
@ -3246,7 +3246,7 @@ void print_iclass_sio(uint8_t *iclass_dump, size_t dump_len, bool verbose) {
|
|||
}
|
||||
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(INFO, "---------------------------- " _CYAN_("SIO - RAW") " ----------------------------");
|
||||
PrintAndLogEx(INFO, "--------------------------- " _CYAN_("SIO - RAW") " -----------------------------");
|
||||
print_hex_noascii_break(sio_start, sio_length, 32);
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
if (verbose) {
|
||||
|
@ -3869,7 +3869,7 @@ static int CmdHFiClassCheckKeys(const char *Cmd) {
|
|||
arg_lit0(NULL, "vb6kdf", "use the VB6 elite KDF instead of a file"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
||||
int fnlen = 0;
|
||||
char filename[FILE_PATH_SIZE] = {0};
|
||||
|
@ -5425,7 +5425,7 @@ static int CmdHFiClassSAM(const char *Cmd) {
|
|||
data[0] = flags;
|
||||
|
||||
int cmdlen = 0;
|
||||
if (CLIParamHexToBuf(arg_get_str(ctx, 8), data+1, PM3_CMD_DATA_SIZE-1, &cmdlen) != PM3_SUCCESS){
|
||||
if (CLIParamHexToBuf(arg_get_str(ctx, 8), data + 1, PM3_CMD_DATA_SIZE - 1, &cmdlen) != PM3_SUCCESS) {
|
||||
CLIParserFree(ctx);
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
@ -5437,7 +5437,7 @@ static int CmdHFiClassSAM(const char *Cmd) {
|
|||
}
|
||||
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_HF_SAM_PICOPASS, data, cmdlen+1);
|
||||
SendCommandNG(CMD_HF_SAM_PICOPASS, data, cmdlen + 1);
|
||||
PacketResponseNG resp;
|
||||
if (WaitForResponseTimeout(CMD_HF_SAM_PICOPASS, &resp, 4000) == false) {
|
||||
PrintAndLogEx(WARNING, "SAM timeout");
|
||||
|
@ -5495,11 +5495,11 @@ static int CmdHFiClassSAM(const char *Cmd) {
|
|||
const uint8_t *mediaType = oid + 2 + oid_length;
|
||||
const uint8_t mediaType_data = mediaType[2];
|
||||
PrintAndLogEx(SUCCESS, "SIO Media Type: " _GREEN_("%s"), getSioMediaTypeInfo(mediaType_data));
|
||||
} else if(breakOnNrMac && d[0] == 0x05) {
|
||||
PrintAndLogEx(SUCCESS, "Nr-MAC: " _GREEN_("%s"), sprint_hex_inrow(d+1, 8));
|
||||
if(verbose){
|
||||
} else if (breakOnNrMac && d[0] == 0x05) {
|
||||
PrintAndLogEx(SUCCESS, "Nr-MAC: " _GREEN_("%s"), sprint_hex_inrow(d + 1, 8));
|
||||
if (verbose) {
|
||||
PrintAndLogEx(INFO, "Replay Nr-MAC to dump SIO:");
|
||||
PrintAndLogEx(SUCCESS, " hf iclass dump -k \"%s\" --nr", sprint_hex_inrow(d+1, 8));
|
||||
PrintAndLogEx(SUCCESS, " hf iclass dump -k \"%s\" --nr", sprint_hex_inrow(d + 1, 8));
|
||||
}
|
||||
} else {
|
||||
print_hex(d, resp.length);
|
||||
|
|
|
@ -70,7 +70,6 @@ static int usage_hf14_keybrute(void) {
|
|||
|
||||
int mfc_ev1_print_signature(uint8_t *uid, uint8_t uidlen, uint8_t *signature, int signature_len) {
|
||||
int index = originality_check_verify(uid, uidlen, signature, signature_len, PK_MFC);
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
return originality_check_print(signature, signature_len, index);
|
||||
}
|
||||
|
||||
|
@ -746,6 +745,7 @@ static int mfc_read_tag(iso14a_card_select_t *card, uint8_t *carddata, uint8_t n
|
|||
free(fptr);
|
||||
free(keyA);
|
||||
free(keyB);
|
||||
|
||||
PrintAndLogEx(SUCCESS, "\nSucceeded in dumping all blocks");
|
||||
return PM3_SUCCESS ;
|
||||
}
|
||||
|
@ -2138,7 +2138,7 @@ static int CmdHF14AMfNestedStatic(const char *Cmd) {
|
|||
e_sector[sectorNo].foundKey[trgKeyType] = 1;
|
||||
e_sector[sectorNo].Key[trgKeyType] = bytes_to_num(keyBlock, 6);
|
||||
|
||||
// mfCheckKeys_fast(SectorsCnt, true, true, 2, 1, keyBlock, e_sector, false, false);
|
||||
// mf_check_keys_fast(SectorsCnt, true, true, 2, 1, keyBlock, e_sector, false, false);
|
||||
continue;
|
||||
default :
|
||||
PrintAndLogEx(ERR, "unknown error.\n");
|
||||
|
@ -2955,7 +2955,7 @@ noValidKeyFound:
|
|||
|
||||
// Try the found keys are reused
|
||||
if (bytes_to_num(tmp_key, MIFARE_KEY_SIZE) != 0) {
|
||||
// <!> The fast check --> mfCheckKeys_fast(sector_cnt, true, true, 2, 1, tmp_key, e_sector, false, verbose);
|
||||
// <!> The fast check --> mf_check_keys_fast(sector_cnt, true, true, 2, 1, tmp_key, e_sector, false, verbose);
|
||||
// <!> Returns false keys, so we just stick to the slower mfchk.
|
||||
for (int i = 0; i < sector_cnt; i++) {
|
||||
for (int j = MF_KEY_A; j <= MF_KEY_B; j++) {
|
||||
|
@ -4251,6 +4251,7 @@ static int CmdHF14AMfSim(const char *Cmd) {
|
|||
PrintAndLogEx(INFO, "Note: option -e implies -i");
|
||||
flags |= FLAG_INTERACTIVE;
|
||||
}
|
||||
|
||||
if ((flags & FLAG_NR_AR_ATTACK) != FLAG_NR_AR_ATTACK) {
|
||||
PrintAndLogEx(WARNING, "Option -e requires -x or -y");
|
||||
return PM3_EINVARG;
|
||||
|
@ -4278,22 +4279,27 @@ static int CmdHF14AMfSim(const char *Cmd) {
|
|||
|
||||
payload.flags = flags;
|
||||
payload.exitAfter = exitAfterNReads;
|
||||
|
||||
memcpy(payload.uid, uid, uidlen);
|
||||
|
||||
payload.atqa = (atqa[1] << 8) | atqa[0];
|
||||
payload.sak = sak[0];
|
||||
|
||||
clearCommandBuffer();
|
||||
|
||||
if (flags & FLAG_INTERACTIVE) {
|
||||
if ((flags & FLAG_INTERACTIVE) == FLAG_INTERACTIVE) {
|
||||
PrintAndLogEx(INFO, "Press " _GREEN_("pm3 button") " or a key to abort simulation");
|
||||
} else {
|
||||
PrintAndLogEx(INFO, "Press " _GREEN_("pm3 button") " or send another cmd to abort simulation");
|
||||
}
|
||||
|
||||
bool cont;
|
||||
do {
|
||||
|
||||
cont = false;
|
||||
SendCommandNG(CMD_HF_MIFARE_SIMULATE, (uint8_t *)&payload, sizeof(payload));
|
||||
if (flags & FLAG_INTERACTIVE) {
|
||||
|
||||
if ((flags & FLAG_INTERACTIVE) == FLAG_INTERACTIVE) {
|
||||
PacketResponseNG resp;
|
||||
sector_t *k_sector = NULL;
|
||||
|
||||
|
@ -4305,19 +4311,24 @@ static int CmdHF14AMfSim(const char *Cmd) {
|
|||
continue;
|
||||
}
|
||||
|
||||
if (resp.status != PM3_SUCCESS)
|
||||
if (resp.status != PM3_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
|
||||
if ((flags & FLAG_NR_AR_ATTACK) != FLAG_NR_AR_ATTACK)
|
||||
if ((flags & FLAG_NR_AR_ATTACK) != FLAG_NR_AR_ATTACK) {
|
||||
break;
|
||||
}
|
||||
|
||||
const nonces_t *data = (nonces_t *)resp.data.asBytes;
|
||||
readerAttack(k_sector, k_sectors_cnt, data[0], setEmulatorMem, verbose);
|
||||
|
||||
if (setEmulatorMem) {
|
||||
cont = true;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (keypress) {
|
||||
if ((flags & FLAG_NR_AR_ATTACK) == FLAG_NR_AR_ATTACK) {
|
||||
// inform device to break the sim loop since client has exited
|
||||
|
@ -9623,7 +9634,7 @@ static int CmdHF14AMfInfo(const char *Cmd) {
|
|||
PacketResponseNG resp;
|
||||
if (WaitForResponseTimeout(CMD_ACK, &resp, 2500) == false) {
|
||||
PrintAndLogEx(DEBUG, "iso14443a card select timeout");
|
||||
return 0;
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
|
||||
iso14a_card_select_t card;
|
||||
|
@ -9721,9 +9732,9 @@ static int CmdHF14AMfInfo(const char *Cmd) {
|
|||
}
|
||||
}
|
||||
|
||||
uint8_t k08s[6] = {0xA3, 0x96, 0xEF, 0xA4, 0xE2, 0x4F};
|
||||
uint8_t k08[6] = {0xA3, 0x16, 0x67, 0xA8, 0xCE, 0xC1};
|
||||
uint8_t k32[6] = {0x51, 0x8B, 0x33, 0x54, 0xE7, 0x60};
|
||||
uint8_t k08s[MIFARE_KEY_SIZE] = {0xA3, 0x96, 0xEF, 0xA4, 0xE2, 0x4F};
|
||||
uint8_t k08[MIFARE_KEY_SIZE] = {0xA3, 0x16, 0x67, 0xA8, 0xCE, 0xC1};
|
||||
uint8_t k32[MIFARE_KEY_SIZE] = {0x51, 0x8B, 0x33, 0x54, 0xE7, 0x60};
|
||||
if (mf_read_block(0, 4, k08s, blockdata) == PM3_SUCCESS) {
|
||||
PrintAndLogEx(SUCCESS, "Backdoor key..... " _YELLOW_("%s"), sprint_hex_inrow(k08s, sizeof(k08s)));
|
||||
fKeyType = MF_KEY_BD;
|
||||
|
|
|
@ -192,7 +192,6 @@ static nxp_cardtype_t getCardType(uint8_t type, uint8_t major, uint8_t minor) {
|
|||
// --- GET SIGNATURE
|
||||
static int plus_print_signature(uint8_t *uid, uint8_t uidlen, uint8_t *signature, int signature_len) {
|
||||
int index = originality_check_verify(uid, uidlen, signature, signature_len, PK_MFP);
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
return originality_check_print(signature, signature_len, index);
|
||||
}
|
||||
|
||||
|
|
|
@ -1417,7 +1417,6 @@ static int ulev1_print_signature(uint64_t tagtype, uint8_t *uid, uint8_t *signat
|
|||
} else if (signature_len == 48) {
|
||||
index = originality_check_verify(uid, 7, signature, signature_len, PK_MFULAES);
|
||||
}
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
return originality_check_print(signature, signature_len, index);
|
||||
}
|
||||
|
||||
|
@ -2451,7 +2450,6 @@ static int CmdHF14AMfUInfo(const char *Cmd) {
|
|||
}
|
||||
// check signature
|
||||
int index = originality_check_verify_ex(card.uid, 7, signature, sizeof(signature), PK_ST25TN, false, true);
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
originality_check_print(signature, sizeof(signature), index);
|
||||
}
|
||||
|
||||
|
|
|
@ -558,7 +558,7 @@ static int select_DF_verify(uint8_t *response, uint8_t response_length, uint8_t
|
|||
}
|
||||
}
|
||||
if (res != PM3_SUCCESS) {
|
||||
goto out;
|
||||
return res;
|
||||
}
|
||||
|
||||
// ----------------- MAC Key Generation -----------------
|
||||
|
@ -579,7 +579,6 @@ static int select_DF_verify(uint8_t *response, uint8_t response_length, uint8_t
|
|||
// PrintAndLogEx(INFO, "Supp MAC......................... " _YELLOW_("%s"), sprint_hex_inrow(MAC_value, MAC_value_len));
|
||||
// PrintAndLogEx(INFO, "Calc MAC......................... " _YELLOW_("%s"), sprint_hex_inrow(cmac, sizeof(cmac)));
|
||||
|
||||
out:
|
||||
PrintAndLogEx(INFO, "--- " _CYAN_("MAC") " ---------------------------");
|
||||
PrintAndLogEx(ERR, _RED_("MAC Verification Failed"));
|
||||
return PM3_ESOFT;
|
||||
|
@ -760,9 +759,8 @@ static int seos_mutual_auth(uint8_t *randomICC, uint8_t *CRYPTOGRAM_Diversifier,
|
|||
uint8_t response[PM3_CMD_DATA_SIZE];
|
||||
|
||||
// ---------------- Diversify Keys ----------------
|
||||
uint8_t undiversified_key[16] = { 0x00 };
|
||||
memcpy(undiversified_key, keys[key_index].readKey, 16);
|
||||
|
||||
uint8_t mk[16] = { 0x00 };
|
||||
memcpy(mk, keys[key_index].readKey, 16);
|
||||
uint8_t keyslot = 0x01; // up to 0x0F
|
||||
uint8_t AES_key[24] = {0x00};
|
||||
uint8_t MAC_key[24] = {0x00};
|
||||
|
@ -776,8 +774,8 @@ static int seos_mutual_auth(uint8_t *randomICC, uint8_t *CRYPTOGRAM_Diversifier,
|
|||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
seos_kdf(true, undiversified_key, keyslot, adfOID, sizeof(adfOID), CRYPTOGRAM_Diversifier, diversifier_len, AES_key, encryption_algorithm, hash_algorithm);
|
||||
seos_kdf(false, undiversified_key, keyslot, adfOID, sizeof(adfOID), CRYPTOGRAM_Diversifier, diversifier_len, MAC_key, encryption_algorithm, hash_algorithm);
|
||||
seos_kdf(true, mk, keyslot, adfOID, sizeof(adfOID), CRYPTOGRAM_Diversifier, diversifier_len, AES_key, encryption_algorithm, hash_algorithm);
|
||||
seos_kdf(false, mk, keyslot, adfOID, sizeof(adfOID), CRYPTOGRAM_Diversifier, diversifier_len, MAC_key, encryption_algorithm, hash_algorithm);
|
||||
|
||||
memcpy(&MAC_key[16], &MAC_key[0], 8);
|
||||
memcpy(&AES_key[16], &AES_key[0], 8);
|
||||
|
@ -976,7 +974,9 @@ static int seos_aid_select(void) {
|
|||
// if we made it here, its a success and we break :)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == ARRAYLEN(known_AID_map)) {
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
return res;
|
||||
};
|
||||
|
||||
|
@ -1668,7 +1668,7 @@ static int CmdHfSeosSAM(const char *Cmd) {
|
|||
data[0] = flags;
|
||||
|
||||
int cmdlen = 0;
|
||||
if (CLIParamHexToBuf(arg_get_str(ctx, 5), data+1, PM3_CMD_DATA_SIZE-1, &cmdlen) != PM3_SUCCESS){
|
||||
if (CLIParamHexToBuf(arg_get_str(ctx, 5), data + 1, PM3_CMD_DATA_SIZE - 1, &cmdlen) != PM3_SUCCESS) {
|
||||
CLIParserFree(ctx);
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
@ -1680,7 +1680,7 @@ static int CmdHfSeosSAM(const char *Cmd) {
|
|||
}
|
||||
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_HF_SAM_SEOS, data, cmdlen+1);
|
||||
SendCommandNG(CMD_HF_SAM_SEOS, data, cmdlen + 1);
|
||||
PacketResponseNG resp;
|
||||
if (WaitForResponseTimeout(CMD_HF_SAM_SEOS, &resp, 4000) == false) {
|
||||
PrintAndLogEx(WARNING, "SAM timeout");
|
||||
|
|
|
@ -150,7 +150,6 @@ static void print_st25ta_system_info(uint8_t *d, uint8_t n) {
|
|||
|
||||
static int print_st25ta_signature(uint8_t *uid, uint8_t *signature) {
|
||||
int index = originality_check_verify_ex(uid, 7, signature, 32, PK_ST25TA, false, true);
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
return originality_check_print(signature, 32, index);
|
||||
}
|
||||
|
||||
|
|
|
@ -136,25 +136,28 @@ const ecdsa_publickey_ng_t manufacturer_public_keys[] = {
|
|||
};
|
||||
|
||||
|
||||
// return pk if match index else -1
|
||||
// returns index of pk if match else -1
|
||||
int originality_check_verify(uint8_t *data, uint8_t data_len, uint8_t *signature, uint8_t signature_len, pk_type_t type) {
|
||||
return originality_check_verify_ex(data, data_len, signature, signature_len, type, false, false);
|
||||
}
|
||||
|
||||
int originality_check_verify_ex(uint8_t *data, uint8_t data_len, uint8_t *signature, uint8_t signature_len, pk_type_t type, bool reverse, bool hash) {
|
||||
// test if signature is null
|
||||
// test if signature is all zeros
|
||||
bool is_zero = true;
|
||||
for (uint8_t i = 0; i < signature_len; i++) {
|
||||
if (signature[i] != 0) {
|
||||
is_zero = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_zero) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint8_t tmp_data[data_len];
|
||||
uint8_t tmp_signature[signature_len];
|
||||
|
||||
if (reverse) {
|
||||
reverse_array_copy(data, data_len, tmp_data);
|
||||
reverse_array_copy(signature, signature_len, tmp_signature);
|
||||
|
@ -180,17 +183,24 @@ int originality_check_verify_ex(uint8_t *data, uint8_t data_len, uint8_t *signat
|
|||
}
|
||||
|
||||
int originality_check_print(uint8_t *signature, int signature_len, int index) {
|
||||
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
|
||||
if ((index < 0) || (index >= ARRAYLEN(manufacturer_public_keys))) {
|
||||
|
||||
PrintAndLogEx(INFO, " TAG IC Signature: %s", sprint_hex_inrow(signature, 16));
|
||||
if (signature_len > 16) {
|
||||
PrintAndLogEx(INFO, " : %s", sprint_hex_inrow(signature + 16, 16));
|
||||
}
|
||||
|
||||
if (signature_len > 32) {
|
||||
PrintAndLogEx(INFO, " : %s", sprint_hex_inrow(signature + 32, 16));
|
||||
}
|
||||
|
||||
if (signature_len > 48) {
|
||||
PrintAndLogEx(INFO, " : %s", sprint_hex_inrow(signature + 48, signature_len - 48));
|
||||
}
|
||||
|
||||
PrintAndLogEx(SUCCESS, " Signature verification: " _RED_("failed"));
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
@ -200,23 +210,30 @@ int originality_check_print(uint8_t *signature, int signature_len, int index) {
|
|||
if (manufacturer_public_keys[index].keylen > 16) {
|
||||
PrintAndLogEx(INFO, " : %.32s", manufacturer_public_keys[index].value + 32);
|
||||
}
|
||||
|
||||
if (manufacturer_public_keys[index].keylen > 32) {
|
||||
PrintAndLogEx(INFO, " : %.32s", manufacturer_public_keys[index].value + 64);
|
||||
}
|
||||
|
||||
if (manufacturer_public_keys[index].keylen > 48) {
|
||||
PrintAndLogEx(INFO, " : %.32s", manufacturer_public_keys[index].value + 96);
|
||||
}
|
||||
|
||||
PrintAndLogEx(INFO, " Elliptic curve parameters: %s", mbedtls_ecp_curve_info_from_grp_id(manufacturer_public_keys[index].grp_id)->name);
|
||||
PrintAndLogEx(INFO, " TAG IC Signature: %s", sprint_hex_inrow(signature, 16));
|
||||
|
||||
if (signature_len > 16) {
|
||||
PrintAndLogEx(INFO, " : %s", sprint_hex_inrow(signature + 16, 16));
|
||||
}
|
||||
|
||||
if (signature_len > 32) {
|
||||
PrintAndLogEx(INFO, " : %s", sprint_hex_inrow(signature + 32, 16));
|
||||
}
|
||||
|
||||
if (signature_len > 48) {
|
||||
PrintAndLogEx(INFO, " : %s", sprint_hex_inrow(signature + 48, signature_len - 48));
|
||||
}
|
||||
|
||||
PrintAndLogEx(SUCCESS, " Signature verification: " _GREEN_("successful"));
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -188,7 +188,7 @@ static uint16_t madGetAID(const uint8_t *sector, bool swapmad, int MADver, int s
|
|||
}
|
||||
}
|
||||
|
||||
int MADCheck(uint8_t *sector0, uint8_t *sector10, bool verbose, bool *haveMAD2) {
|
||||
int MADCheck(uint8_t *sector0, uint8_t *sector16, bool verbose, bool *haveMAD2) {
|
||||
|
||||
if (sector0 == NULL)
|
||||
return PM3_EINVARG;
|
||||
|
@ -222,13 +222,13 @@ int MADCheck(uint8_t *sector0, uint8_t *sector10, bool verbose, bool *haveMAD2)
|
|||
PrintAndLogEx(SUCCESS, "CRC8...... 0x%02X ( %s )", sector0[16], _GREEN_("ok"));
|
||||
}
|
||||
|
||||
if (mad_ver == 2 && sector10) {
|
||||
int res2 = madCRCCheck(sector10, true, 2);
|
||||
if (mad_ver == 2 && sector16) {
|
||||
int res2 = madCRCCheck(sector16, true, 2);
|
||||
if (res == PM3_SUCCESS)
|
||||
res = res2;
|
||||
|
||||
if (verbose && !res2)
|
||||
PrintAndLogEx(SUCCESS, "CRC8...... 0x%02X ( %s )", sector10[0], _GREEN_("ok"));
|
||||
PrintAndLogEx(SUCCESS, "CRC8...... 0x%02X ( %s )", sector16[0], _GREEN_("ok"));
|
||||
}
|
||||
|
||||
// MA (multi-application card)
|
||||
|
@ -241,27 +241,30 @@ int MADCheck(uint8_t *sector0, uint8_t *sector10, bool verbose, bool *haveMAD2)
|
|||
return res;
|
||||
}
|
||||
|
||||
int MADDecode(uint8_t *sector0, uint8_t *sector10, uint16_t *mad, size_t *madlen, bool swapmad) {
|
||||
int MADDecode(uint8_t *sector0, uint8_t *sector16, uint16_t *mad, size_t *madlen, bool swapmad) {
|
||||
*madlen = 0;
|
||||
bool haveMAD2 = false;
|
||||
int res = MADCheck(sector0, sector10, false, &haveMAD2);
|
||||
int res = MADCheck(sector0, sector16, false, &haveMAD2);
|
||||
if (res != PM3_SUCCESS) {
|
||||
PrintAndLogEx(WARNING, "Not a valid MAD");
|
||||
return res;
|
||||
}
|
||||
|
||||
for (int i = 1; i < 16; i++) {
|
||||
// 7 + 8 == 15
|
||||
for (int i = 1; i <= 16; i++) {
|
||||
mad[*madlen] = madGetAID(sector0, swapmad, 1, i);
|
||||
(*madlen)++;
|
||||
}
|
||||
|
||||
if (haveMAD2) {
|
||||
// mad2 sector (0x10 == 16dec) here
|
||||
// mad2 sector (0x10 == 16) here
|
||||
mad[*madlen] = 0x0005;
|
||||
(*madlen)++;
|
||||
|
||||
// 7 + 8 + 8 == 23
|
||||
for (int i = 1; i < 24; i++) {
|
||||
mad[*madlen] = madGetAID(sector10, swapmad, 2, i);
|
||||
mad[*madlen] = madGetAID(sector16, swapmad, 2, i);
|
||||
|
||||
(*madlen)++;
|
||||
}
|
||||
}
|
||||
|
@ -462,16 +465,16 @@ int convert_mad_to_arr(uint8_t *in, uint16_t ilen, uint8_t *out, uint16_t *olen)
|
|||
}
|
||||
|
||||
uint8_t sector0[MFBLOCK_SIZE * 4] = {0};
|
||||
uint8_t sector10[MFBLOCK_SIZE * 4] = {0};
|
||||
uint8_t sector16[MFBLOCK_SIZE * 4] = {0};
|
||||
|
||||
memcpy(sector0, in, sizeof(sector0));
|
||||
if (ilen == MIFARE_4K_MAX_BYTES) {
|
||||
memcpy(sector10, in + (MF_MAD2_SECTOR * 4 * MFBLOCK_SIZE), sizeof(sector10));
|
||||
memcpy(sector16, in + (MF_MAD2_SECTOR * 4 * MFBLOCK_SIZE), sizeof(sector16));
|
||||
}
|
||||
|
||||
uint16_t mad[7 + 8 + 8 + 8 + 8] = {0};
|
||||
size_t madlen = 0;
|
||||
if (MADDecode(sector0, sector10, mad, &madlen, false)) {
|
||||
if (MADDecode(sector0, sector16, mad, &madlen, false)) {
|
||||
PrintAndLogEx(ERR, "can't decode MAD");
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
|
|
@ -21,8 +21,8 @@
|
|||
|
||||
#include "common.h"
|
||||
|
||||
int MADCheck(uint8_t *sector0, uint8_t *sector10, bool verbose, bool *haveMAD2);
|
||||
int MADDecode(uint8_t *sector0, uint8_t *sector10, uint16_t *mad, size_t *madlen, bool swapmad);
|
||||
int MADCheck(uint8_t *sector0, uint8_t *sector16, bool verbose, bool *haveMAD2);
|
||||
int MADDecode(uint8_t *sector0, uint8_t *sector16, uint16_t *mad, size_t *madlen, bool swapmad);
|
||||
int MAD1DecodeAndPrint(uint8_t *sector, bool swapmad, bool verbose, bool *haveMAD2);
|
||||
int MAD2DecodeAndPrint(uint8_t *sector, bool swapmad, bool verbose);
|
||||
int MADDFDecodeAndPrint(uint32_t short_aid, bool verbose);
|
||||
|
|
|
@ -1036,19 +1036,25 @@ int mf_write_sector(uint8_t sectorNo, uint8_t keyType, const uint8_t *key, uint8
|
|||
|
||||
// EMULATOR
|
||||
int mf_eml_get_mem(uint8_t *data, int blockNum, int blocksCount) {
|
||||
return mf_eml_get_mem_xt(data, blockNum, blocksCount, MFBLOCK_SIZE);
|
||||
}
|
||||
|
||||
size_t size = blocksCount * MFBLOCK_SIZE;
|
||||
int mf_eml_get_mem_xt(uint8_t *data, int blockNum, int blocksCount, int blockBtWidth) {
|
||||
|
||||
size_t size = ((size_t) blocksCount) * blockBtWidth;
|
||||
if (size > PM3_CMD_DATA_SIZE) {
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
struct {
|
||||
uint8_t blockno;
|
||||
uint16_t blockno;
|
||||
uint8_t blockcnt;
|
||||
uint8_t blockwidth;
|
||||
} PACKED payload;
|
||||
|
||||
payload.blockno = blockNum;
|
||||
payload.blockcnt = blocksCount;
|
||||
payload.blockwidth = blockBtWidth;
|
||||
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_HF_MIFARE_EML_MEMGET, (uint8_t *)&payload, sizeof(payload));
|
||||
|
@ -1059,8 +1065,9 @@ int mf_eml_get_mem(uint8_t *data, int blockNum, int blocksCount) {
|
|||
return PM3_ETIMEOUT;
|
||||
}
|
||||
|
||||
if (resp.status == PM3_SUCCESS)
|
||||
if (resp.status == PM3_SUCCESS) {
|
||||
memcpy(data, resp.data.asBytes, size);
|
||||
}
|
||||
|
||||
return resp.status;
|
||||
}
|
||||
|
@ -1072,7 +1079,7 @@ int mf_elm_set_mem(uint8_t *data, int blockNum, int blocksCount) {
|
|||
int mf_eml_set_mem_xt(uint8_t *data, int blockNum, int blocksCount, int blockBtWidth) {
|
||||
|
||||
struct p {
|
||||
uint8_t blockno;
|
||||
uint16_t blockno;
|
||||
uint8_t blockcnt;
|
||||
uint8_t blockwidth;
|
||||
uint8_t data[];
|
||||
|
@ -1226,7 +1233,7 @@ int mf_chinese_set_block(uint8_t blockNo, uint8_t *data, uint8_t *uid, uint8_t p
|
|||
if (!isOK) {
|
||||
|
||||
uint8_t reason = (resp.oldarg[1] & 0xFF);
|
||||
if ( reason == 4) {
|
||||
if (reason == 4) {
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(WARNING, "GDM magic write signature block failed");
|
||||
} else if (reason == 5) {
|
||||
|
|
|
@ -92,6 +92,7 @@ int mf_write_block(uint8_t blockno, uint8_t keyType, const uint8_t *key, uint8_t
|
|||
int mf_write_sector(uint8_t sectorNo, uint8_t keyType, const uint8_t *key, uint8_t *sector);
|
||||
|
||||
int mf_eml_get_mem(uint8_t *data, int blockNum, int blocksCount);
|
||||
int mf_eml_get_mem_xt(uint8_t *data, int blockNum, int blocksCount, int blockBtWidth);
|
||||
int mf_elm_set_mem(uint8_t *data, int blockNum, int blocksCount);
|
||||
int mf_eml_set_mem_xt(uint8_t *data, int blockNum, int blocksCount, int blockBtWidth);
|
||||
|
||||
|
|
|
@ -1528,7 +1528,7 @@ int HIDFindCardFormat(const char *format) {
|
|||
static bool validate_card_limit(int format_idx, wiegand_card_t *card) {
|
||||
cardformatdescriptor_t card_descriptor = FormatTable[format_idx].Fields;
|
||||
return !((card->FacilityCode > card_descriptor.MaxFC) ||
|
||||
(card->CardNumber > card_descriptor.MaxCN)||
|
||||
(card->CardNumber > card_descriptor.MaxCN) ||
|
||||
(card->IssueLevel > card_descriptor.MaxIL) ||
|
||||
(card->OEM > card_descriptor.MaxOEM));
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
#include "commonutil.h"
|
||||
#include <string.h>
|
||||
#include "stdbool.h"
|
||||
|
||||
/* Similar to FpgaGatherVersion this formats stored version information
|
||||
* into a string representation. It takes a pointer to the struct version_information_t,
|
||||
|
@ -403,25 +404,34 @@ void Uint8byteToMemBe(uint8_t *data, uint64_t value) {
|
|||
}
|
||||
|
||||
// Rotate Left - Ultralight, Desfire
|
||||
void rol(uint8_t *data, const size_t len) {
|
||||
void rol(uint8_t *data, const size_t n) {
|
||||
uint8_t first = data[0];
|
||||
for (size_t i = 0; i < len - 1; i++) {
|
||||
for (size_t i = 0; i < n - 1; i++) {
|
||||
data[i] = data[i + 1];
|
||||
}
|
||||
data[len - 1] = first;
|
||||
data[n - 1] = first;
|
||||
}
|
||||
|
||||
// Rotate Right - Ultralight, Desfire
|
||||
void ror(uint8_t *data, const size_t len) {
|
||||
uint8_t last = data[len - 1];
|
||||
void ror(uint8_t *data, const size_t n) {
|
||||
uint8_t last = data[n - 1];
|
||||
|
||||
for (int i = len - 1; i > 0; i--) {
|
||||
for (int i = n - 1; i > 0; i--) {
|
||||
data[i] = data[i - 1];
|
||||
}
|
||||
|
||||
data[0] = last;
|
||||
}
|
||||
|
||||
void xor(uint8_t *dest, const uint8_t *src, size_t n) {
|
||||
|
||||
const uint8_t *s = src;
|
||||
uint8_t *d = dest;
|
||||
|
||||
for (; n > 0; n--) {
|
||||
*d++ ^= *s++;
|
||||
}
|
||||
}
|
||||
|
||||
void lsl(uint8_t *data, size_t len) {
|
||||
for (size_t n = 0; n < len - 1; n++) {
|
||||
|
|
|
@ -128,8 +128,9 @@ void Uint7byteToMemBe(uint8_t *data, uint64_t value);
|
|||
void Uint8byteToMemBe(uint8_t *data, uint64_t value);
|
||||
|
||||
// rotate left byte array
|
||||
void rol(uint8_t *data, const size_t len);
|
||||
void ror(uint8_t *data, const size_t len);
|
||||
void rol(uint8_t *data, const size_t n);
|
||||
void ror(uint8_t *data, const size_t n);
|
||||
void xor(uint8_t *dest, const uint8_t *src, size_t n);
|
||||
|
||||
void lsl(uint8_t *data, size_t len);
|
||||
uint32_t le24toh(const uint8_t data[3]);
|
||||
|
|
|
@ -321,11 +321,11 @@ static int asn1_get_sequence_of_cb(void *ctx,
|
|||
cb_ctx->cur;
|
||||
|
||||
if (cur->buf.p != NULL) {
|
||||
cur->next =
|
||||
mbedtls_calloc(1, sizeof(mbedtls_asn1_sequence));
|
||||
cur->next = mbedtls_calloc(1, sizeof(mbedtls_asn1_sequence));
|
||||
|
||||
if (cur->next == NULL)
|
||||
if (cur->next == NULL) {
|
||||
return (MBEDTLS_ERR_ASN1_ALLOC_FAILED);
|
||||
}
|
||||
|
||||
cur = cur->next;
|
||||
}
|
||||
|
|
|
@ -180,8 +180,7 @@ int mbedtls_cipher_cmac_starts(mbedtls_cipher_context_t *ctx,
|
|||
if (ctx == NULL || ctx->cipher_info == NULL || key == NULL)
|
||||
return (MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA);
|
||||
|
||||
if ((retval = mbedtls_cipher_setkey(ctx, key, (int)keybits,
|
||||
MBEDTLS_ENCRYPT)) != 0)
|
||||
if ((retval = mbedtls_cipher_setkey(ctx, key, (int)keybits, MBEDTLS_ENCRYPT)) != 0)
|
||||
return (retval);
|
||||
|
||||
type = ctx->cipher_info->type;
|
||||
|
@ -405,14 +404,12 @@ int mbedtls_aes_cmac_prf_128(const unsigned char *key, size_t key_length,
|
|||
} else {
|
||||
memset(zero_key, 0, MBEDTLS_AES_BLOCK_SIZE);
|
||||
|
||||
ret = mbedtls_cipher_cmac(cipher_info, zero_key, 128, key,
|
||||
key_length, int_key);
|
||||
ret = mbedtls_cipher_cmac(cipher_info, zero_key, 128, key, key_length, int_key);
|
||||
if (ret != 0)
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ret = mbedtls_cipher_cmac(cipher_info, int_key, 128, input, in_len,
|
||||
output);
|
||||
ret = mbedtls_cipher_cmac(cipher_info, int_key, 128, input, in_len, output);
|
||||
|
||||
exit:
|
||||
mbedtls_platform_zeroize(int_key, sizeof(int_key));
|
||||
|
|
|
@ -920,7 +920,7 @@
|
|||
},
|
||||
"emv help": {
|
||||
"command": "emv help",
|
||||
"description": "----------- ----------------------- General ----------------------- help This help list List ISO7816 history test Crypto logic selftest --------------------------------------------------------------------------------------- emv list available offline: yes Alias of `trace list -t 7816` with selected protocol data to annotate trace buffer You can load a trace from file (see `trace load -h`) or it be downloaded from device by default It accepts all other arguments of `trace list`. Note that some might not be relevant for this specific protocol",
|
||||
"description": "----------- ----------------------- General ----------------------- help This help list List ISO7816 history test Perform crypto logic self tests --------------------------------------------------------------------------------------- emv list available offline: yes Alias of `trace list -t 7816` with selected protocol data to annotate trace buffer You can load a trace from file (see `trace load -h`) or it be downloaded from device by default It accepts all other arguments of `trace list`. Note that some might not be relevant for this specific protocol",
|
||||
"notes": [
|
||||
"emv list --frame -> show frame delay times",
|
||||
"emv list -1 -> use trace buffer"
|
||||
|
@ -1025,11 +1025,11 @@
|
|||
"offline": false,
|
||||
"options": [
|
||||
"-h, --help This help",
|
||||
"-t, --selftest Self test",
|
||||
"--test Perform self tests",
|
||||
"-a, --apdu Show APDU requests and responses",
|
||||
"-w, --wired Send data via contact (iso7816) interface. (def: Contactless interface)"
|
||||
],
|
||||
"usage": "emv roca [-htaw]"
|
||||
"usage": "emv roca [-haw] [--test]"
|
||||
},
|
||||
"emv scan": {
|
||||
"command": "emv scan",
|
||||
|
@ -1410,19 +1410,19 @@
|
|||
"hf 14a simaid -t 3 -> MIFARE Desfire",
|
||||
"hf 14a simaid -t 4 -> ISO/IEC 14443-4",
|
||||
"hf 14a simaid -t 11 -> Javacard (JCOP)",
|
||||
"hf 14a simaid -t 3 --aid a000000000000000000000 --response 9000 --apdu 9000 -> AID, Response and APDU",
|
||||
"hf 14a simaid -t 3 --rats 05788172220101 --response 01009000 --apdu 86009000 -> Custom RATS Added",
|
||||
"hf 14a simaid -t 3 --rats 05788172220101 -x -> Enumerate AID Values"
|
||||
"hf 14a simaid -t 3 --aid a000000000000000000000 --selectaid_response 9000 --getdata_response 9000 -> Custom AID and responses",
|
||||
"hf 14a simaid -t 3 --ats 0578817222 --selectaid_response 01009000 --getdata_response 86009000 -> Custom ATS and responses",
|
||||
"hf 14a simaid -t 3 --ats 0578817222 -x -> Enumerate AID Values"
|
||||
],
|
||||
"offline": false,
|
||||
"options": [
|
||||
"-h, --help This help",
|
||||
"-t, --type <1-12> Simulation type to use",
|
||||
"-u, --uid <hex> <4|7|10> hex bytes UID",
|
||||
"-r, --rats <hex> <0-20> hex bytes RATS",
|
||||
"-a, --aid <hex> <0-100> hex bytes for AID to respond to (Default: A000000000000000000000)",
|
||||
"-e, --response <hex> <0-100> hex bytes for APDU Response to AID Select (Default: 9000)",
|
||||
"-p, --apdu <hex> <0-100> hex bytes for APDU Response to Get Data request after AID (Default: 9000)",
|
||||
"-r, --ats <hex> <0-20> hex bytes ATS",
|
||||
"-a, --aid <hex> <0-30> hex bytes for AID to respond to (Default: A000000000000000000000)",
|
||||
"-e, --selectaid_response <hex> <0-100> hex bytes for APDU Response to AID Select (Default: 9000)",
|
||||
"-p, --getdata_response <hex> <0-100> hex bytes for APDU Response to Get Data request after AID (Default: 9000)",
|
||||
"-x, --enumerate Enumerate all AID values via returning Not Found and print them to console"
|
||||
],
|
||||
"usage": "hf 14a simaid [-hx] -t <1-12> [-u <hex>] [-r <hex>] [-a <hex>] [-e <hex>] [-p <hex>]"
|
||||
|
@ -3657,14 +3657,23 @@
|
|||
"command": "hf iclass sam",
|
||||
"description": "Extract PACS via a HID SAM",
|
||||
"notes": [
|
||||
"hf iclass sam"
|
||||
"hf iclass sam",
|
||||
"hf iclass sam -p -d a005a103800104 -> get PACS data, but ensure that epurse will stay unchanged",
|
||||
"hf iclass sam --break-on-nr-mac -> get Nr-MAC for extracting encrypted SIO"
|
||||
],
|
||||
"offline": false,
|
||||
"options": [
|
||||
"-h, --help This help",
|
||||
"-v, --verbose verbose output"
|
||||
"-v, --verbose verbose output",
|
||||
"-k, --keep keep the field active after command executed",
|
||||
"-n, --nodetect skip selecting the card and sending card details to SAM",
|
||||
"-t, --tlv decode TLV",
|
||||
"--break-on-nr-mac stop tag interaction on nr-mac",
|
||||
"-p, --prevent-epurse-update fake epurse update",
|
||||
"--shallow shallow mod",
|
||||
"-d, --data <hex> DER encoded command to send to SAM"
|
||||
],
|
||||
"usage": "hf iclass sam [-hv]"
|
||||
"usage": "hf iclass sam [-hvkntp] [--break-on-nr-mac] [--shallow] [-d <hex>]..."
|
||||
},
|
||||
"hf iclass sim": {
|
||||
"command": "hf iclass sim",
|
||||
|
@ -4486,12 +4495,13 @@
|
|||
"-f, --file <fn> Specify a filename for dump file",
|
||||
"--mini MIFARE Classic Mini / S20",
|
||||
"--1k MIFARE Classic 1k / S50 (def)",
|
||||
"--1k+ MIFARE Classic Ev1 1k / S50",
|
||||
"--2k MIFARE Classic/Plus 2k",
|
||||
"--4k MIFARE Classic 4k / S70",
|
||||
"--emu from emulator memory",
|
||||
"--gdm use gdm alt (20/23) magic wakeup"
|
||||
],
|
||||
"usage": "hf mf cload [-h] [-f <fn>] [--mini] [--1k] [--2k] [--4k] [--emu] [--gdm]"
|
||||
"usage": "hf mf cload [-h] [-f <fn>] [--mini] [--1k] [--1k+] [--2k] [--4k] [--emu] [--gdm]"
|
||||
},
|
||||
"hf mf csave": {
|
||||
"command": "hf mf csave",
|
||||
|
@ -7693,7 +7703,7 @@
|
|||
"description": "Extract PACS via a HID SAM",
|
||||
"notes": [
|
||||
"hf seos sam",
|
||||
"hd seos sam -d a005a103800104 -> get PACS data"
|
||||
"hf seos sam -d a005a103800104 -> get PACS data"
|
||||
],
|
||||
"offline": false,
|
||||
"options": [
|
||||
|
@ -9851,8 +9861,8 @@
|
|||
"command": "lf hitag chk",
|
||||
"description": "Run dictionary key or password recovery against Hitag card.",
|
||||
"notes": [
|
||||
"lf hitag chk",
|
||||
"-> checks for both pwd / crypto keyslf hitag chk --crypto -> use def dictionary",
|
||||
"lf hitag chk -> checks for both pwd / crypto keys",
|
||||
"lf hitag chk --crypto -> use def dictionary",
|
||||
"lf hitag chk --pwd -f my.dic -> pwd mode, custom dictionary"
|
||||
],
|
||||
"offline": false,
|
||||
|
@ -13202,6 +13212,6 @@
|
|||
"metadata": {
|
||||
"commands_extracted": 759,
|
||||
"extracted_by": "PM3Help2JSON v1.00",
|
||||
"extracted_on": "2025-01-14T15:42:02"
|
||||
"extracted_on": "2025-02-21T14:36:13"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -150,7 +150,7 @@ Check column "offline" for their availability.
|
|||
|------- |------- |-----------
|
||||
|`emv help `|Y |`This help`
|
||||
|`emv list `|Y |`List ISO7816 history`
|
||||
|`emv test `|Y |`Crypto logic selftest`
|
||||
|`emv test `|Y |`Perform crypto logic self tests`
|
||||
|`emv challenge `|N |`Generate challenge`
|
||||
|`emv exec `|N |`Executes EMV contactless transaction`
|
||||
|`emv genac `|N |`Generate ApplicationCryptogram`
|
||||
|
|
|
@ -924,6 +924,9 @@ typedef struct {
|
|||
// No key available client/pm3: no cryptographic key available.
|
||||
#define PM3_ENOKEY -28
|
||||
|
||||
// Cryptographic error client/pm3: cryptographic operation failed
|
||||
#define PM3_ECRYPTO -29
|
||||
|
||||
// No data client/pm3: no data available, no host frame available (not really an error)
|
||||
#define PM3_ENODATA -98
|
||||
// Quit program client: reserved, order to quit the program
|
||||
|
|
|
@ -205,6 +205,12 @@ ISO 7816-4 Basic interindustry commands. For command APDU's.
|
|||
#define MIFARE_EV1_UIDF1 0x40
|
||||
#define MIFARE_EV1_UIDF2 0x20
|
||||
#define MIFARE_EV1_UIDF3 0x60
|
||||
#define MIFARE_EV1_SELECT_APP 0x5A
|
||||
#define MIFARE_EV1_AUTH_AES 0xAA
|
||||
#define MIFARE_EV1_AUTH_AES_2 0xAF
|
||||
#define MIFARE_EV1_GET_FILE_INFO 0xF5
|
||||
#define MIFARE_EV1_READ_DATA 0xBD
|
||||
|
||||
|
||||
#define MIFARE_ULC_WRITE 0xA2
|
||||
#define MIFARE_ULC_COMP_WRITE 0xA0
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue