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:
iceman1001 2025-02-21 15:38:33 +01:00
parent 6bb7199a7b
commit cef07dedf6
57 changed files with 672 additions and 521 deletions

View file

@ -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

View file

@ -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;

View file

@ -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;

View file

@ -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);

View file

@ -150,7 +150,7 @@ void RunMod(void) {
} else if (playing && selected == 2) {
// Now it work only with HID Corporate 1000 (35bit), but is easily extensible to others RFID.
// It is necessary only to calculate the correct parity.
// Brute force code
// Check if the badge is an HID Corporate 1000
if ((high[selected] & 0xFFFFFFF8) != 0x28) {

View file

@ -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);

View file

@ -1370,7 +1370,11 @@ static void PacketReceived(PacketCommandNG *packet) {
// involved in dealing with emulator memory. But if it is called later, it might
// destroy the Emulator Memory.
//-----------------------------------------------------------------------------
EmlClearIso15693();
// Resetting the bitstream also frees the BigBuf memory, so we do this here to prevent
// an inconvenient reset in the future by Iso15693InitTag
FpgaDownloadAndGo(FPGA_BITSTREAM_HF_15);
BigBuf_Clear_EM();
reply_ng(CMD_HF_ISO15693_EML_CLEAR, PM3_SUCCESS, NULL, 0);
break;
}
case CMD_HF_ISO15693_EML_SETMEM: {
@ -1402,7 +1406,7 @@ static void PacketReceived(PacketCommandNG *packet) {
return;
}
uint8_t *buf = BigBuf_malloc(payload->length);
uint8_t *buf = BigBuf_calloc(payload->length);
emlGet(buf, payload->offset, payload->length);
LED_B_ON();
reply_ng(CMD_HF_ISO15693_EML_GETMEM, PM3_SUCCESS, buf, payload->length);
@ -1677,7 +1681,7 @@ static void PacketReceived(PacketCommandNG *packet) {
EMVsim(payload->flags, payload->exitAfter, payload->uid, payload->atqa, payload->sak);
break;
}
#endif
#endif
case CMD_HF_ISO14443A_SIMULATE: {
struct p {
uint8_t tagtype;
@ -1890,36 +1894,65 @@ static void PacketReceived(PacketCommandNG *packet) {
break;
}
case CMD_HF_MIFARE_EML_MEMCLR: {
MifareEMemClr();
reply_ng(CMD_HF_MIFARE_EML_MEMCLR, PM3_SUCCESS, NULL, 0);
//-----------------------------------------------------------------------------
// Work with emulator memory
//
// Note: we call FpgaDownloadAndGo(FPGA_BITSTREAM_HF) here although FPGA is not
// involved in dealing with emulator memory. But if it is called later, it might
// destroy the Emulator Memory.
//-----------------------------------------------------------------------------
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
// Not only clears the emulator memory,
// also sets default MIFARE values for sector trailers.
emlClearMem();
reply_ng(CMD_HF_MIFARE_EML_MEMCLR, PM3_SUCCESS, NULL, 0);
break;
}
case CMD_HF_MIFARE_EML_MEMSET: {
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
struct p {
uint8_t blockno;
uint16_t blockno;
uint8_t blockcnt;
uint8_t blockwidth;
uint8_t data[];
} PACKED;
struct p *payload = (struct p *) packet->data.asBytes;
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
// backwards compat... default bytewidth
if (payload->blockwidth == 0)
payload->blockwidth = 16;
if (payload->blockwidth == 0) {
payload->blockwidth = MIFARE_BLOCK_SIZE;
}
emlSetMem_xt(payload->data, payload->blockno, payload->blockcnt, payload->blockwidth);
break;
}
case CMD_HF_MIFARE_EML_MEMGET: {
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
struct p {
uint8_t blockno;
uint16_t blockno;
uint8_t blockcnt;
uint8_t blockwidth;
} PACKED;
struct p *payload = (struct p *) packet->data.asBytes;
MifareEMemGet(payload->blockno, payload->blockcnt);
//
size_t size = payload->blockno * payload->blockwidth;
if (size > PM3_CMD_DATA_SIZE) {
reply_ng(CMD_HF_MIFARE_EML_MEMGET, PM3_EMALLOC, NULL, 0);
return;
}
uint8_t *buf = BigBuf_calloc(size);
emlGetMem_xt(buf, payload->blockno, payload->blockcnt, payload->blockwidth); // data, block num, blocks count (max 4)
LED_B_ON();
reply_ng(CMD_HF_MIFARE_EML_MEMGET, PM3_SUCCESS, buf, size);
LED_B_OFF();
BigBuf_free_keep_EM();
break;
}
case CMD_HF_MIFARE_EML_LOAD: {

View file

@ -133,7 +133,9 @@ void tdes_nxp_send(const void *in, void *out, size_t length, const void *key, ui
}
void aes128_nxp_receive(const void *in, void *out, size_t length, const void *key, unsigned char iv[16]) {
if (length % 8) return;
if (length % 8) {
return;
}
uint8_t *tin = (uint8_t *) in;
uint8_t *tout = (uint8_t *) out;
@ -143,7 +145,9 @@ void aes128_nxp_receive(const void *in, void *out, size_t length, const void *ke
}
void aes128_nxp_send(const void *in, void *out, size_t length, const void *key, unsigned char iv[16]) {
if (length % 8) return;
if (length % 8) {
return;
}
uint8_t *tin = (uint8_t *) in;
uint8_t *tout = (uint8_t *) out;
@ -152,12 +156,15 @@ void aes128_nxp_send(const void *in, void *out, size_t length, const void *key,
mbedtls_aes_crypt_cbc(&actx, MBEDTLS_AES_ENCRYPT, length, iv, tin, tout);
}
void Desfire_des_key_new(const uint8_t value[8], desfirekey_t key) {
uint8_t data[8];
memcpy(data, value, 8);
for (int n = 0; n < 8; n++) {
void Desfire_des_key_new(const uint8_t *value, desfirekey_t key) {
uint8_t data[8] = {0};
memcpy(data, value, sizeof(data));
for (size_t n = 0; n < sizeof(data); n++) {
data[n] &= 0xFE;
}
Desfire_des_key_new_with_version(data, key);
}
@ -246,22 +253,24 @@ void Desfire_key_set_version(desfirekey_t key, uint8_t version) {
void Desfire_session_key_new(const uint8_t rnda[], const uint8_t rndb[], desfirekey_t authkey, desfirekey_t key) {
uint8_t buffer[24];
uint8_t buffer[24] = {0};
switch (authkey->type) {
case T_DES:
case T_DES: {
memcpy(buffer, rnda, 4);
memcpy(buffer + 4, rndb, 4);
Desfire_des_key_new_with_version(buffer, key);
break;
case T_3DES:
}
case T_3DES: {
memcpy(buffer, rnda, 4);
memcpy(buffer + 4, rndb, 4);
memcpy(buffer + 8, rnda + 4, 4);
memcpy(buffer + 12, rndb + 4, 4);
Desfire_3des_key_new_with_version(buffer, key);
break;
case T_3K3DES:
}
case T_3K3DES: {
memcpy(buffer, rnda, 4);
memcpy(buffer + 4, rndb, 4);
memcpy(buffer + 8, rnda + 6, 4);
@ -270,22 +279,15 @@ void Desfire_session_key_new(const uint8_t rnda[], const uint8_t rndb[], desfire
memcpy(buffer + 20, rndb + 12, 4);
Desfire_3k3des_key_new(buffer, key);
break;
case T_AES:
}
case T_AES: {
memcpy(buffer, rnda, 4);
memcpy(buffer + 4, rndb, 4);
memcpy(buffer + 8, rnda + 12, 4);
memcpy(buffer + 12, rndb + 12, 4);
Desfire_aes_key_new(buffer, key);
break;
}
}
static size_t key_macing_length(desfirekey_t key);
// iceman, see memxor inside string.c, dest/src swapped..
static void xor(const uint8_t *ivect, uint8_t *data, const size_t len) {
for (size_t i = 0; i < len; i++) {
data[i] ^= ivect[i];
}
}
}
@ -306,7 +308,7 @@ void cmac_generate_subkeys(desfirekey_t key) {
// Used to compute CMAC on complete blocks
memcpy(key->cmac_sk1, l, kbs);
txor = l[0] & 0x80;
txor = (l[0] & 0x80);
lsl(key->cmac_sk1, kbs);
@ -317,7 +319,7 @@ void cmac_generate_subkeys(desfirekey_t key) {
// Used to compute CMAC on the last block if non-complete
memcpy(key->cmac_sk2, key->cmac_sk1, kbs);
txor = key->cmac_sk1[0] & 0x80;
txor = (key->cmac_sk1[0] & 0x80);
lsl(key->cmac_sk2, kbs);
@ -341,15 +343,14 @@ void cmac(const desfirekey_t key, uint8_t *ivect, const uint8_t *data, size_t le
while (len % kbs) {
buffer[len++] = 0x00;
}
xor(key->cmac_sk2, buffer + len - kbs, kbs);
xor(buffer + len - kbs, key->cmac_sk2, kbs);
} else {
xor(key->cmac_sk1, buffer + len - kbs, kbs);
xor(buffer + len - kbs, key->cmac_sk1, kbs);
}
mifare_cypher_blocks_chained(NULL, key, ivect, buffer, len, MCD_SEND, MCO_ENCYPHER);
memcpy(cmac, ivect, kbs);
//free(buffer);
}
size_t key_block_size(const desfirekey_t key) {
@ -374,7 +375,7 @@ size_t key_block_size(const desfirekey_t key) {
/*
* Size of MACing produced with the key.
*/
static size_t key_macing_length(const desfirekey_t key) {
size_t key_macing_length(const desfirekey_t key) {
size_t mac_length = DESFIRE_MAC_LENGTH;
switch (key->type) {
case T_DES:
@ -393,10 +394,11 @@ static size_t key_macing_length(const desfirekey_t key) {
* Size required to store nbytes of data in a buffer of size n*block_size.
*/
size_t padded_data_length(const size_t nbytes, const size_t block_size) {
if ((!nbytes) || (nbytes % block_size))
if ((!nbytes) || (nbytes % block_size)) {
return ((nbytes / block_size) + 1) * block_size;
else
} else {
return nbytes;
}
}
/*
@ -412,12 +414,14 @@ size_t enciphered_data_length(const desfiretag_t tag, const size_t nbytes, int c
size_t crc_length = 0;
if (!(communication_settings & NO_CRC)) {
switch (DESFIRE(tag)->authentication_scheme) {
case AS_LEGACY:
case AS_LEGACY: {
crc_length = 2;
break;
case AS_NEW:
}
case AS_NEW: {
crc_length = 4;
break;
}
}
}
@ -428,18 +432,20 @@ size_t enciphered_data_length(const desfiretag_t tag, const size_t nbytes, int c
void *mifare_cryto_preprocess_data(desfiretag_t tag, void *data, size_t *nbytes, size_t offset, int communication_settings) {
uint8_t *res = data;
uint8_t mac[4];
uint8_t mac[4] = {0};
size_t edl;
bool append_mac = true;
desfirekey_t key = DESFIRE(tag)->session_key;
if (!key)
desfirekey_t key = DESFIRE(tag)->session_key;
if (!key) {
return data;
}
switch (communication_settings & MDCM_MASK) {
case MDCM_PLAIN:
if (AS_LEGACY == DESFIRE(tag)->authentication_scheme)
case MDCM_PLAIN: {
if (AS_LEGACY == DESFIRE(tag)->authentication_scheme) {
break;
}
/*
* When using new authentication methods, PLAIN data transmission from
@ -452,13 +458,16 @@ void *mifare_cryto_preprocess_data(desfiretag_t tag, void *data, size_t *nbytes,
*/
append_mac = false;
}
/* pass through */
case MDCM_MACED:
case MDCM_MACED: {
switch (DESFIRE(tag)->authentication_scheme) {
case AS_LEGACY:
if (!(communication_settings & MAC_COMMAND))
case AS_LEGACY: {
if (!(communication_settings & MAC_COMMAND)) {
break;
}
/* pass through */
edl = padded_data_length(*nbytes - offset, key_block_size(DESFIRE(tag)->session_key)) + offset;
@ -475,8 +484,9 @@ void *mifare_cryto_preprocess_data(desfiretag_t tag, void *data, size_t *nbytes,
// Copy again provided data (was overwritten by mifare_cypher_blocks_chained)
memcpy(res, data, *nbytes);
if (!(communication_settings & MAC_COMMAND))
if (!(communication_settings & MAC_COMMAND)) {
break;
}
// Append MAC
size_t bla = maced_data_length(DESFIRE(tag)->session_key, *nbytes - offset) + offset;
(void)bla++;
@ -485,9 +495,12 @@ void *mifare_cryto_preprocess_data(desfiretag_t tag, void *data, size_t *nbytes,
*nbytes += 4;
break;
case AS_NEW:
if (!(communication_settings & CMAC_COMMAND))
}
case AS_NEW: {
if (!(communication_settings & CMAC_COMMAND)) {
break;
}
cmac(key, DESFIRE(tag)->ivect, res, *nbytes, DESFIRE(tag)->cmac);
if (append_mac) {
@ -498,10 +511,11 @@ void *mifare_cryto_preprocess_data(desfiretag_t tag, void *data, size_t *nbytes,
*nbytes += DESFIRE_CMAC_LENGTH;
}
break;
}
}
break;
case MDCM_ENCIPHERED:
}
case MDCM_ENCIPHERED: {
/* |<-------------- data -------------->|
* |<--- offset -->| |
* +---------------+--------------------+-----+---------+
@ -517,8 +531,10 @@ void *mifare_cryto_preprocess_data(desfiretag_t tag, void *data, size_t *nbytes,
* encypher()/decypher()
*/
if (!(communication_settings & ENC_COMMAND))
if (!(communication_settings & ENC_COMMAND)) {
break;
}
edl = enciphered_data_length(tag, *nbytes - offset, communication_settings) + offset;
// Fill in the crypto buffer with data ...
@ -526,14 +542,16 @@ void *mifare_cryto_preprocess_data(desfiretag_t tag, void *data, size_t *nbytes,
if (!(communication_settings & NO_CRC)) {
// ... CRC ...
switch (DESFIRE(tag)->authentication_scheme) {
case AS_LEGACY:
case AS_LEGACY: {
AddCrc14A(res + offset, *nbytes - offset);
*nbytes += 2;
break;
case AS_NEW:
}
case AS_NEW: {
crc32_append(res, *nbytes);
*nbytes += 4;
break;
}
}
}
// ... and padding
@ -543,32 +561,34 @@ void *mifare_cryto_preprocess_data(desfiretag_t tag, void *data, size_t *nbytes,
mifare_cypher_blocks_chained(tag, NULL, NULL, res + offset, *nbytes - offset, MCD_SEND, (AS_NEW == DESFIRE(tag)->authentication_scheme) ? MCO_ENCYPHER : MCO_DECYPHER);
break;
default:
}
default: {
*nbytes = -1;
res = NULL;
break;
}
}
return res;
}
void *mifare_cryto_postprocess_data(desfiretag_t tag, void *data, size_t *nbytes, int communication_settings) {
void *res = data;
uint8_t first_cmac_byte = 0x00;
desfirekey_t key = DESFIRE(tag)->session_key;
if (!key) {
return data;
}
// Return directly if we just have a status code.
if (1 == *nbytes) {
return res;
}
desfirekey_t key = DESFIRE(tag)->session_key;
if (!key) {
return data;
}
uint8_t first_cmac_byte = 0x00;
switch (communication_settings & MDCM_MASK) {
case MDCM_PLAIN: {
@ -659,11 +679,12 @@ void *mifare_cryto_postprocess_data(desfiretag_t tag, void *data, size_t *nbytes
break;
}
case MDCM_ENCIPHERED: {
(*nbytes)--;
bool verified = false;
int crc_pos = 0x00;
int end_crc_pos = 0x00;
uint8_t x;
/*
* AS_LEGACY:
@ -742,8 +763,9 @@ void *mifare_cryto_postprocess_data(desfiretag_t tag, void *data, size_t *nbytes
verified = true;
for (int n = end_crc_pos; n < *nbytes - 1; n++) {
uint8_t byte = ((uint8_t *)res)[n];
if (!((0x00 == byte) || ((0x80 == byte) && (n == end_crc_pos))))
if (!((0x00 == byte) || ((0x80 == byte) && (n == end_crc_pos)))) {
verified = false;
}
}
}
@ -768,7 +790,7 @@ void *mifare_cryto_postprocess_data(desfiretag_t tag, void *data, size_t *nbytes
break;
}
case AS_NEW: {
x = ((uint8_t *)res)[crc_pos - 1];
uint8_t x = ((uint8_t *)res)[crc_pos - 1];
((uint8_t *)res)[crc_pos - 1] = ((uint8_t *)res)[crc_pos];
((uint8_t *)res)[crc_pos] = x;
break;
@ -802,9 +824,10 @@ void *mifare_cryto_postprocess_data(desfiretag_t tag, void *data, size_t *nbytes
void mifare_cypher_single_block(desfirekey_t key, uint8_t *data, uint8_t *ivect, MifareCryptoDirection direction, MifareCryptoOperation operation, size_t block_size) {
uint8_t ovect[DESFIRE_MAX_CRYPTO_BLOCK_SIZE];
if (direction == MCD_SEND) {
xor(ivect, data, block_size);
xor(data, ivect, block_size);
} else {
memcpy(ovect, data, block_size);
}
@ -812,70 +835,80 @@ void mifare_cypher_single_block(desfirekey_t key, uint8_t *data, uint8_t *ivect,
uint8_t edata[DESFIRE_MAX_CRYPTO_BLOCK_SIZE] = {0};
switch (key->type) {
case T_DES:
case T_DES: {
switch (operation) {
case MCO_ENCYPHER:
case MCO_ENCYPHER: {
//DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_ENCRYPT);
des_encrypt(edata, data, key->data);
break;
case MCO_DECYPHER:
}
case MCO_DECYPHER: {
//DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_DECRYPT);
des_decrypt(edata, data, key->data);
break;
}
}
break;
case T_3DES:
}
case T_3DES: {
switch (operation) {
case MCO_ENCYPHER:
case MCO_ENCYPHER: {
mbedtls_des3_set2key_enc(&ctx3, key->data);
mbedtls_des3_crypt_ecb(&ctx3, data, edata);
// DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_ENCRYPT);
// DES_ecb_encrypt ((DES_cblock *) edata, (DES_cblock *) data, &(key->ks2), DES_DECRYPT);
// DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_ENCRYPT);
break;
case MCO_DECYPHER:
}
case MCO_DECYPHER: {
mbedtls_des3_set2key_dec(&ctx3, key->data);
mbedtls_des3_crypt_ecb(&ctx3, data, edata);
// DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_DECRYPT);
// DES_ecb_encrypt ((DES_cblock *) edata, (DES_cblock *) data, &(key->ks2), DES_ENCRYPT);
// DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_DECRYPT);
break;
}
}
break;
case T_3K3DES:
}
case T_3K3DES: {
switch (operation) {
case MCO_ENCYPHER:
case MCO_ENCYPHER: {
mbedtls_des3_set3key_enc(&ctx3, key->data);
mbedtls_des3_crypt_ecb(&ctx3, data, edata);
// DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_ENCRYPT);
// DES_ecb_encrypt ((DES_cblock *) edata, (DES_cblock *) data, &(key->ks2), DES_DECRYPT);
// DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks3), DES_ENCRYPT);
break;
case MCO_DECYPHER:
}
case MCO_DECYPHER: {
mbedtls_des3_set3key_dec(&ctx3, key->data);
mbedtls_des3_crypt_ecb(&ctx3, data, edata);
// DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks3), DES_DECRYPT);
// DES_ecb_encrypt ((DES_cblock *) edata, (DES_cblock *) data, &(key->ks2), DES_ENCRYPT);
// DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_DECRYPT);
break;
}
}
break;
case T_AES:
}
case T_AES: {
switch (operation) {
case MCO_ENCYPHER: {
mbedtls_aes_init(&actx);
mbedtls_aes_setkey_enc(&actx, key->data, 128);
mbedtls_aes_crypt_cbc(&actx, MBEDTLS_AES_ENCRYPT, sizeof(edata), ivect, data, edata);
mbedtls_aes_crypt_ecb(&actx, MBEDTLS_AES_ENCRYPT, data, edata);
break;
}
case MCO_DECYPHER: {
mbedtls_aes_init(&actx);
mbedtls_aes_setkey_dec(&actx, key->data, 128);
mbedtls_aes_crypt_cbc(&actx, MBEDTLS_AES_DECRYPT, sizeof(edata), ivect, edata, data);
mbedtls_aes_crypt_ecb(&actx, MBEDTLS_AES_DECRYPT, data, edata);
break;
}
}
break;
}
}
memcpy(data, edata, block_size);
@ -883,7 +916,7 @@ void mifare_cypher_single_block(desfirekey_t key, uint8_t *data, uint8_t *ivect,
if (direction == MCD_SEND) {
memcpy(ivect, data, block_size);
} else {
xor(ivect, data, block_size);
xor(data, ivect, block_size);
memcpy(ivect, ovect, block_size);
}
}

View file

@ -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

View file

@ -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

View file

@ -1035,7 +1035,7 @@ static int hts_send_receive(const uint8_t *tx, size_t txlen, uint8_t *rx, size_t
Dbhexdump(*rxlen, response_bit, false);
Dbprintf("htS: skipping %d bit SOF", sof_bits);
if ((rx[0] >> (8 - sof_bits)) != ((1 << sof_bits) - 1)) {
if ((rx[0] >> (8 - sof_bits)) != ((1 << sof_bits) - 1)) {
DBG DbpString("htS: Warning, not all bits of SOF are 1");
}
}

View file

@ -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) {

View file

@ -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,

View file

@ -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) {

View file

@ -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

View file

@ -944,7 +944,7 @@ static void fcAll(uint8_t fc, int *n, uint8_t clock, int16_t *remainder) {
}
}
bool add_HID_preamble(uint32_t *hi2, uint32_t *hi, uint32_t *lo, uint8_t length){
bool add_HID_preamble(uint32_t *hi2, uint32_t *hi, uint32_t *lo, uint8_t length) {
// Invalid value
if (length > 84 || length == 0)
return false;
@ -963,7 +963,7 @@ bool add_HID_preamble(uint32_t *hi2, uint32_t *hi, uint32_t *lo, uint8_t length)
// No header bits added to 37-bit cards
} else if (length >= 32) {
*hi |= 0x20; // Bit 37; standard header
*hi |= 1U << (length - 32); // leading 1: start bit
*hi |= 1U << (length - 32); // leading 1: start bit
} else {
*hi |= 0x20; // Bit 37; standard header
*lo |= 1U << length; // leading 1: start bit

View file

@ -24,7 +24,7 @@
void ModThenAcquireRawAdcSamples125k(uint32_t delay_off, uint16_t period_0, uint16_t period_1,
const uint8_t *symbol_extra, uint16_t *period_extra, uint8_t *command, bool verbose,
bool keep_field_on, uint32_t samples, bool ledcontrol);
void ReadTItag(bool ledcontrol);
void WriteTItag(uint32_t idhi, uint32_t idlo, uint16_t crc, bool ledcontrol);

View file

@ -2223,7 +2223,7 @@ OUT:
blockno = (32 * 4 + (i - 32) * 16) ^ 0xF;
}
// get ST
emlGetMem(block, blockno, 1);
emlGetMem_xt(block, blockno, 1, MIFARE_BLOCK_SIZE);
memcpy(block, k_sector[i].keyA, 6);
memcpy(block + 10, k_sector[i].keyB, 6);
@ -2427,39 +2427,6 @@ void MifarePersonalizeUID(uint8_t keyType, uint8_t perso_option, uint64_t key) {
}
//-----------------------------------------------------------------------------
// Work with emulator memory
//
// Note: we call FpgaDownloadAndGo(FPGA_BITSTREAM_HF) here although FPGA is not
// involved in dealing with emulator memory. But if it is called later, it might
// destroy the Emulator Memory.
//-----------------------------------------------------------------------------
void MifareEMemClr(void) {
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
emlClearMem();
}
void MifareEMemGet(uint8_t blockno, uint8_t blockcnt) {
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
//
size_t size = blockcnt * 16;
if (size > PM3_CMD_DATA_SIZE) {
reply_ng(CMD_HF_MIFARE_EML_MEMGET, PM3_EMALLOC, NULL, 0);
return;
}
uint8_t *buf = BigBuf_malloc(size);
emlGetMem(buf, blockno, blockcnt); // data, block num, blocks count (max 4)
LED_B_ON();
reply_ng(CMD_HF_MIFARE_EML_MEMGET, PM3_SUCCESS, buf, size);
LED_B_OFF();
BigBuf_free_keep_EM();
}
//-----------------------------------------------------------------------------
// Load a card into the emulator memory
//
@ -2471,12 +2438,15 @@ int MifareECardLoadExt(uint8_t sectorcnt, uint8_t keytype, uint8_t *key) {
}
int MifareECardLoad(uint8_t sectorcnt, uint8_t keytype, uint8_t *key) {
if ((keytype > MF_KEY_B) && (key == NULL)) {
if (g_dbglevel >= DBG_ERROR) {
Dbprintf("Error, missing key");
}
return PM3_EINVARG;
}
LED_A_ON();
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
@ -2510,10 +2480,10 @@ int MifareECardLoad(uint8_t sectorcnt, uint8_t keytype, uint8_t *key) {
// MFC 1K EV1, skip sector 16 since its lockdown
if (s == 16) {
// unknown sector trailer, keep the keys, set only the AC
uint8_t st[16] = {0x00};
emlGetMem(st, FirstBlockOfSector(s) + 3, 1);
uint8_t st[MIFARE_BLOCK_SIZE] = {0x00};
emlGetMem_xt(st, FirstBlockOfSector(s) + 3, 1, MIFARE_BLOCK_SIZE);
memcpy(st + 6, "\x70\xF0\xF8\x69", 4);
emlSetMem_xt(st, FirstBlockOfSector(s) + 3, 1, 16);
emlSetMem_xt(st, FirstBlockOfSector(s) + 3, 1, MIFARE_BLOCK_SIZE);
continue;
}
@ -2556,7 +2526,8 @@ int MifareECardLoad(uint8_t sectorcnt, uint8_t keytype, uint8_t *key) {
}
have_uid = true;
} else { // no need for anticollision. We can directly select the card
if (!bd_authenticated) { // no need to select if bd_authenticated with backdoor
if (bd_authenticated == false) { // no need to select if bd_authenticated with backdoor
if (iso14443a_fast_select_card(uid, cascade_levels) == 0) {
continue;
}
@ -2565,7 +2536,7 @@ int MifareECardLoad(uint8_t sectorcnt, uint8_t keytype, uint8_t *key) {
// Auth
if (keytype > MF_KEY_B) {
if (! bd_authenticated) {
if (bd_authenticated == false) {
ui64Key = bytes_to_num(key, 6);
if (mifare_classic_auth(pcs, cuid, 0, keytype, ui64Key, AUTH_FIRST)) {
retval = PM3_EFAILED;
@ -2592,7 +2563,7 @@ int MifareECardLoad(uint8_t sectorcnt, uint8_t keytype, uint8_t *key) {
#define MAX_RETRIES 2
uint8_t data[16] = {0x00};
uint8_t data[MIFARE_BLOCK_SIZE] = {0x00};
for (uint8_t b = 0; b < NumBlocksPerSector(s); b++) {
memset(data, 0x00, sizeof(data));
@ -2614,18 +2585,18 @@ int MifareECardLoad(uint8_t sectorcnt, uint8_t keytype, uint8_t *key) {
}
// No need to copy empty
if (memcmp(data, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16) == 0) {
if (memcmp(data, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", sizeof(data)) == 0) {
break;
}
if (IsSectorTrailer(b)) {
// sector trailer, keep the keys, set only the AC
uint8_t st[16] = {0x00};
emlGetMem(st, tb, 1);
uint8_t st[MIFARE_BLOCK_SIZE] = {0x00};
emlGetMem_xt(st, tb, 1, MIFARE_BLOCK_SIZE);
memcpy(st + 6, data + 6, 4);
emlSetMem_xt(st, tb, 1, 16);
emlSetMem_xt(st, tb, 1, MIFARE_BLOCK_SIZE);
} else {
emlSetMem_xt(data, tb, 1, 16);
emlSetMem_xt(data, tb, 1, MIFARE_BLOCK_SIZE);
}
break;
}
@ -2927,7 +2898,6 @@ void MifareCIdent(bool is_mfc, uint8_t keytype, uint8_t *key) {
// variables
uint8_t rec[1] = {0x00};
uint8_t recpar[1] = {0x00};
uint8_t rats[4] = {ISO14443A_CMD_RATS, 0x80, 0x31, 0x73};
uint8_t rdblf0[4] = {ISO14443A_CMD_READBLOCK, 0xF0, 0x8D, 0x5f};
uint8_t rdbl00[4] = {ISO14443A_CMD_READBLOCK, 0x00, 0x02, 0xa8};
uint8_t gen4gdmAuth[4] = {MIFARE_MAGIC_GDM_AUTH_KEY, 0x00, 0x6C, 0x92};
@ -2940,6 +2910,8 @@ void MifareCIdent(bool is_mfc, uint8_t keytype, uint8_t *key) {
uint8_t *par = BigBuf_calloc(MAX_PARITY_SIZE);
uint8_t *buf = BigBuf_calloc(PM3_CMD_DATA_SIZE);
uint8_t *uid = BigBuf_calloc(10);
iso14a_card_select_t *card = (iso14a_card_select_t *) BigBuf_calloc(sizeof(iso14a_card_select_t));
uint16_t flag = MAGIC_FLAG_NONE;
uint32_t cuid = 0;
int res = 0;
@ -2991,144 +2963,141 @@ void MifareCIdent(bool is_mfc, uint8_t keytype, uint8_t *key) {
// reset card
mf_reset_card();
res = iso14443a_select_card(uid, NULL, &cuid, true, 0, false);
res = iso14443a_select_card(uid, card, &cuid, true, 0, false);
if (res) {
if (cuid == 0xAA55C396) {
flag |= MAGIC_FLAG_GEN_UNFUSED;
}
ReaderTransmit(rats, sizeof(rats), NULL);
res = ReaderReceive(buf, PM3_CMD_DATA_SIZE, par);
if (memcmp(card->ats, "\x09\x78\x00\x91\x02\xDA\xBC\x19\x10", 9) == 0) {
// test for some MFC gen2
isGen2 = true;
flag |= MAGIC_FLAG_GEN_2;
} else if (memcmp(card->ats, "\x0D\x78\x00\x71\x02\x88\x49\xA1\x30\x20\x15\x06\x08\x56\x3D", 15) == 0) {
// test for some MFC 7b gen2
isGen2 = true;
flag |= MAGIC_FLAG_GEN_2;
} else if (memcmp(card->ats, "\x0A\x78\x00\x81\x02\xDB\xA0\xC1\x19\x40\x2A\xB5", 12) == 0) {
// test for Ultralight magic gen2
isGen2 = true;
flag |= MAGIC_FLAG_GEN_2;
} else if (memcmp(card->ats, "\x85\x00\x00\xA0\x00\x00\x0A\xC3\x00\x04\x03\x01\x01\x00\x0B\x03\x41\xDF", 18) == 0) {
// test for Ultralight EV1 magic gen2
isGen2 = true;
flag |= MAGIC_FLAG_GEN_2;
} else if (memcmp(card->ats, "\x85\x00\x00\xA0\x0A\x00\x0A\xC3\x00\x04\x03\x01\x01\x00\x0B\x03\x16\xD7", 18) == 0) {
// test for some other Ultralight EV1 magic gen2
isGen2 = true;
flag |= MAGIC_FLAG_GEN_2;
} else if (memcmp(card->ats, "\x85\x00\x00\xA0\x0A\x00\x0A\xB0\x00\x00\x00\x00\x00\x00\x00\x00\x18\x4D", 18) == 0) {
// test for some other Ultralight magic gen2
isGen2 = true;
flag |= MAGIC_FLAG_GEN_2;
} else if (memcmp(card->ats, "\x85\x00\x00\xA0\x00\x00\x0A\xA5\x00\x04\x04\x02\x01\x00\x0F\x03\x79\x0C", 18) == 0) {
// test for NTAG213 magic gen2
isGen2 = true;
flag |= MAGIC_FLAG_GEN_2;
}
if (res) {
if (memcmp(buf, "\x09\x78\x00\x91\x02\xDA\xBC\x19\x10", 9) == 0) {
// test for some MFC gen2
isGen2 = true;
flag |= MAGIC_FLAG_GEN_2;
} else if (memcmp(buf, "\x0D\x78\x00\x71\x02\x88\x49\xA1\x30\x20\x15\x06\x08\x56\x3D", 15) == 0) {
// test for some MFC 7b gen2
isGen2 = true;
flag |= MAGIC_FLAG_GEN_2;
} else if (memcmp(buf, "\x0A\x78\x00\x81\x02\xDB\xA0\xC1\x19\x40\x2A\xB5", 12) == 0) {
// test for Ultralight magic gen2
isGen2 = true;
flag |= MAGIC_FLAG_GEN_2;
} else if (memcmp(buf, "\x85\x00\x00\xA0\x00\x00\x0A\xC3\x00\x04\x03\x01\x01\x00\x0B\x03\x41\xDF", 18) == 0) {
// test for Ultralight EV1 magic gen2
isGen2 = true;
flag |= MAGIC_FLAG_GEN_2;
} else if (memcmp(buf, "\x85\x00\x00\xA0\x0A\x00\x0A\xC3\x00\x04\x03\x01\x01\x00\x0B\x03\x16\xD7", 18) == 0) {
// test for some other Ultralight EV1 magic gen2
isGen2 = true;
flag |= MAGIC_FLAG_GEN_2;
} else if (memcmp(buf, "\x85\x00\x00\xA0\x0A\x00\x0A\xB0\x00\x00\x00\x00\x00\x00\x00\x00\x18\x4D", 18) == 0) {
// test for some other Ultralight magic gen2
isGen2 = true;
flag |= MAGIC_FLAG_GEN_2;
} else if (memcmp(buf, "\x85\x00\x00\xA0\x00\x00\x0A\xA5\x00\x04\x04\x02\x01\x00\x0F\x03\x79\x0C", 18) == 0) {
// test for NTAG213 magic gen2
isGen2 = true;
flag |= MAGIC_FLAG_GEN_2;
// test for super card
ReaderTransmit(superGen1, sizeof(superGen1), NULL);
res = ReaderReceive(buf, PM3_CMD_DATA_SIZE, par);
if (res == 22) {
uint8_t isGen = MAGIC_FLAG_SUPER_GEN1;
// check for super card gen2
// not available after RATS, reset card before executing
mf_reset_card();
iso14443a_select_card(uid, NULL, &cuid, true, 0, true);
ReaderTransmit(rdbl00, sizeof(rdbl00), NULL);
res = ReaderReceive(buf, PM3_CMD_DATA_SIZE, par);
if (res == 18) {
isGen = MAGIC_FLAG_SUPER_GEN2;
}
// test for super card
ReaderTransmit(superGen1, sizeof(superGen1), NULL);
flag |= isGen;
}
}
if (is_mfc == false) {
// magic ntag test
mf_reset_card();
res = iso14443a_select_card(uid, NULL, &cuid, true, 0, true);
if (res == 2) {
ReaderTransmit(rdblf0, sizeof(rdblf0), NULL);
res = ReaderReceive(buf, PM3_CMD_DATA_SIZE, par);
if (res == 22) {
uint8_t isGen = MAGIC_FLAG_SUPER_GEN1;
// check for super card gen2
// not available after RATS, reset card before executing
mf_reset_card();
iso14443a_select_card(uid, NULL, &cuid, true, 0, true);
ReaderTransmit(rdbl00, sizeof(rdbl00), NULL);
res = ReaderReceive(buf, PM3_CMD_DATA_SIZE, par);
if (res == 18) {
isGen = MAGIC_FLAG_SUPER_GEN2;
}
flag |= isGen;
if (res == 18) {
flag |= MAGIC_FLAG_NTAG21X;
}
}
if (is_mfc == false) {
// magic ntag test
} else {
struct Crypto1State mpcs = {0, 0};
struct Crypto1State *pcs;
pcs = &mpcs;
// CUID (with default sector 0 B key) test
// regular cards will NAK the WRITEBLOCK(0) command, while DirectWrite will ACK it
// if we do get an ACK, we immediately abort to ensure nothing is ever actually written
// only perform test if we haven't already identified Gen2. No need test if we have a positive identification already
if (isGen2 == false) {
mf_reset_card();
res = iso14443a_select_card(uid, NULL, &cuid, true, 0, true);
if (res == 2) {
ReaderTransmit(rdblf0, sizeof(rdblf0), NULL);
res = ReaderReceive(buf, PM3_CMD_DATA_SIZE, par);
if (res == 18) {
flag |= MAGIC_FLAG_NTAG21X;
}
}
} else {
if (res) {
struct Crypto1State mpcs = {0, 0};
struct Crypto1State *pcs;
pcs = &mpcs;
uint64_t tmpkey = bytes_to_num(key, 6);
if (mifare_classic_authex(pcs, cuid, 0, keytype, tmpkey, AUTH_FIRST, NULL, NULL) == 0) {
// CUID (with default sector 0 B key) test
// regular cards will NAK the WRITEBLOCK(0) command, while DirectWrite will ACK it
// if we do get an ACK, we immediately abort to ensure nothing is ever actually written
// only perform test if we haven't already identified Gen2. No need test if we have a positive identification already
if (isGen2 == false) {
mf_reset_card();
res = iso14443a_select_card(uid, NULL, &cuid, true, 0, true);
if (res) {
uint64_t tmpkey = bytes_to_num(key, 6);
if (mifare_classic_authex(pcs, cuid, 0, keytype, tmpkey, AUTH_FIRST, NULL, NULL) == 0) {
if ((mifare_sendcmd_short(pcs, 1, ISO14443A_CMD_WRITEBLOCK, 0, buf, PM3_CMD_DATA_SIZE, par, NULL) == 1) && (buf[0] == 0x0A)) {
flag |= MAGIC_FLAG_GEN_2;
// turn off immediately to ensure nothing ever accidentally writes to the block
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
}
if ((mifare_sendcmd_short(pcs, 1, ISO14443A_CMD_WRITEBLOCK, 0, buf, PM3_CMD_DATA_SIZE, par, NULL) == 1) && (buf[0] == 0x0A)) {
flag |= MAGIC_FLAG_GEN_2;
// turn off immediately to ensure nothing ever accidentally writes to the block
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
}
crypto1_deinit(pcs);
}
}
// magic MFC Gen3 test 1
mf_reset_card();
res = iso14443a_select_card(uid, NULL, &cuid, true, 0, true);
if (res) {
ReaderTransmit(rdbl00, sizeof(rdbl00), NULL);
res = ReaderReceive(buf, PM3_CMD_DATA_SIZE, par);
if (res == 18) {
flag |= MAGIC_FLAG_GEN_3;
}
}
// magic MFC Gen4 GDM magic auth test
mf_reset_card();
res = iso14443a_select_card(uid, NULL, &cuid, true, 0, true);
if (res) {
ReaderTransmit(gen4gdmAuth, sizeof(gen4gdmAuth), NULL);
res = ReaderReceive(buf, PM3_CMD_DATA_SIZE, par);
if (res == 4) {
flag |= MAGIC_FLAG_GDM_AUTH;
}
}
// QL88 test
mf_reset_card();
res = iso14443a_select_card(uid, NULL, &cuid, true, 0, true);
if (res) {
if (mifare_classic_authex(pcs, cuid, 68, MF_KEY_B, 0x707B11FC1481, AUTH_FIRST, NULL, NULL) == 0) {
flag |= MAGIC_FLAG_QL88;
}
crypto1_deinit(pcs);
}
}
};
// magic MFC Gen3 test 1
mf_reset_card();
res = iso14443a_select_card(uid, NULL, &cuid, true, 0, true);
if (res) {
ReaderTransmit(rdbl00, sizeof(rdbl00), NULL);
res = ReaderReceive(buf, PM3_CMD_DATA_SIZE, par);
if (res == 18) {
flag |= MAGIC_FLAG_GEN_3;
}
}
// magic MFC Gen4 GDM magic auth test
mf_reset_card();
res = iso14443a_select_card(uid, NULL, &cuid, true, 0, true);
if (res) {
ReaderTransmit(gen4gdmAuth, sizeof(gen4gdmAuth), NULL);
res = ReaderReceive(buf, PM3_CMD_DATA_SIZE, par);
if (res == 4) {
flag |= MAGIC_FLAG_GDM_AUTH;
}
}
// QL88 test
mf_reset_card();
res = iso14443a_select_card(uid, NULL, &cuid, true, 0, true);
if (res) {
if (mifare_classic_authex(pcs, cuid, 68, MF_KEY_B, 0x707B11FC1481, AUTH_FIRST, NULL, NULL) == 0) {
flag |= MAGIC_FLAG_QL88;
}
crypto1_deinit(pcs);
}
}
// GDM alt magic wakeup (20)
ReaderTransmitBitsPar(wupGDM1, 7, NULL, NULL);

View file

@ -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);

View file

@ -48,8 +48,8 @@
#include "parity.h"
static bool IsKeyBReadable(uint8_t blockNo) {
uint8_t sector_trailer[16];
emlGetMem(sector_trailer, SectorTrailer(blockNo), 1);
uint8_t sector_trailer[MIFARE_BLOCK_SIZE] = {0};
emlGetMem_xt(sector_trailer, SectorTrailer(blockNo), 1, MIFARE_BLOCK_SIZE);
uint8_t AC = ((sector_trailer[7] >> 5) & 0x04)
| ((sector_trailer[8] >> 2) & 0x02)
| ((sector_trailer[8] >> 7) & 0x01);
@ -57,55 +57,64 @@ static bool IsKeyBReadable(uint8_t blockNo) {
}
static bool IsTrailerAccessAllowed(uint8_t blockNo, uint8_t keytype, uint8_t action) {
uint8_t sector_trailer[16];
emlGetMem(sector_trailer, blockNo, 1);
uint8_t sector_trailer[MIFARE_BLOCK_SIZE] = {0};
emlGetMem_xt(sector_trailer, blockNo, 1, MIFARE_BLOCK_SIZE);
uint8_t AC = ((sector_trailer[7] >> 5) & 0x04)
| ((sector_trailer[8] >> 2) & 0x02)
| ((sector_trailer[8] >> 7) & 0x01);
switch (action) {
case AC_KEYA_READ: {
if (g_dbglevel >= DBG_EXTENDED)
if (g_dbglevel >= DBG_EXTENDED) {
Dbprintf("IsTrailerAccessAllowed: AC_KEYA_READ");
}
return false;
}
case AC_KEYA_WRITE: {
if (g_dbglevel >= DBG_EXTENDED)
if (g_dbglevel >= DBG_EXTENDED) {
Dbprintf("IsTrailerAccessAllowed: AC_KEYA_WRITE");
}
return ((keytype == AUTHKEYA && (AC == 0x00 || AC == 0x01))
|| (keytype == AUTHKEYB && (AC == 0x04 || AC == 0x03)));
}
case AC_KEYB_READ: {
if (g_dbglevel >= DBG_EXTENDED)
if (g_dbglevel >= DBG_EXTENDED) {
Dbprintf("IsTrailerAccessAllowed: AC_KEYB_READ");
}
return (keytype == AUTHKEYA && (AC == 0x00 || AC == 0x02 || AC == 0x01));
}
case AC_KEYB_WRITE: {
if (g_dbglevel >= DBG_EXTENDED)
if (g_dbglevel >= DBG_EXTENDED) {
Dbprintf("IsTrailerAccessAllowed: AC_KEYB_WRITE");
}
return ((keytype == AUTHKEYA && (AC == 0x00 || AC == 0x01))
|| (keytype == AUTHKEYB && (AC == 0x04 || AC == 0x03)));
}
case AC_AC_READ: {
if (g_dbglevel >= DBG_EXTENDED)
if (g_dbglevel >= DBG_EXTENDED) {
Dbprintf("IsTrailerAccessAllowed: AC_AC_READ");
}
return ((keytype == AUTHKEYA)
|| (keytype == AUTHKEYB && !(AC == 0x00 || AC == 0x02 || AC == 0x01)));
}
case AC_AC_WRITE: {
if (g_dbglevel >= DBG_EXTENDED)
if (g_dbglevel >= DBG_EXTENDED) {
Dbprintf("IsTrailerAccessAllowed: AC_AC_WRITE");
}
return ((keytype == AUTHKEYA && (AC == 0x01))
|| (keytype == AUTHKEYB && (AC == 0x03 || AC == 0x05)));
}
default:
default: {
return false;
}
}
}
static bool IsDataAccessAllowed(uint8_t blockNo, uint8_t keytype, uint8_t action) {
uint8_t sector_trailer[16];
emlGetMem(sector_trailer, SectorTrailer(blockNo), 1);
uint8_t sector_trailer[MIFARE_BLOCK_SIZE] = {0};
emlGetMem_xt(sector_trailer, SectorTrailer(blockNo), 1, MIFARE_BLOCK_SIZE);
uint8_t sector_block;
if (blockNo <= MIFARE_2K_MAXBLOCK) {
@ -120,54 +129,62 @@ static bool IsDataAccessAllowed(uint8_t blockNo, uint8_t keytype, uint8_t action
AC = ((sector_trailer[7] >> 2) & 0x04)
| ((sector_trailer[8] << 1) & 0x02)
| ((sector_trailer[8] >> 4) & 0x01);
if (g_dbglevel >= DBG_EXTENDED)
if (g_dbglevel >= DBG_EXTENDED) {
Dbprintf("IsDataAccessAllowed: case 0x00 - %02x", AC);
}
break;
}
case 0x01: {
AC = ((sector_trailer[7] >> 3) & 0x04)
| ((sector_trailer[8] >> 0) & 0x02)
| ((sector_trailer[8] >> 5) & 0x01);
if (g_dbglevel >= DBG_EXTENDED)
if (g_dbglevel >= DBG_EXTENDED) {
Dbprintf("IsDataAccessAllowed: case 0x01 - %02x", AC);
}
break;
}
case 0x02: {
AC = ((sector_trailer[7] >> 4) & 0x04)
| ((sector_trailer[8] >> 1) & 0x02)
| ((sector_trailer[8] >> 6) & 0x01);
if (g_dbglevel >= DBG_EXTENDED)
if (g_dbglevel >= DBG_EXTENDED) {
Dbprintf("IsDataAccessAllowed: case 0x02 - %02x", AC);
}
break;
}
default:
if (g_dbglevel >= DBG_EXTENDED)
if (g_dbglevel >= DBG_EXTENDED) {
Dbprintf("IsDataAccessAllowed: Error");
}
return false;
}
switch (action) {
case AC_DATA_READ: {
if (g_dbglevel >= DBG_EXTENDED)
if (g_dbglevel >= DBG_EXTENDED) {
Dbprintf("IsDataAccessAllowed - AC_DATA_READ: OK");
}
return ((keytype == AUTHKEYA && !(AC == 0x03 || AC == 0x05 || AC == 0x07))
|| (keytype == AUTHKEYB && !(AC == 0x07)));
}
case AC_DATA_WRITE: {
if (g_dbglevel >= DBG_EXTENDED)
if (g_dbglevel >= DBG_EXTENDED) {
Dbprintf("IsDataAccessAllowed - AC_DATA_WRITE: OK");
}
return ((keytype == AUTHKEYA && (AC == 0x00))
|| (keytype == AUTHKEYB && (AC == 0x00 || AC == 0x04 || AC == 0x06 || AC == 0x03)));
}
case AC_DATA_INC: {
if (g_dbglevel >= DBG_EXTENDED)
if (g_dbglevel >= DBG_EXTENDED) {
Dbprintf("IsDataAccessAllowed - AC_DATA_INC: OK");
}
return ((keytype == AUTHKEYA && (AC == 0x00))
|| (keytype == AUTHKEYB && (AC == 0x00 || AC == 0x06)));
}
case AC_DATA_DEC_TRANS_REST: {
if (g_dbglevel >= DBG_EXTENDED)
if (g_dbglevel >= DBG_EXTENDED) {
Dbprintf("AC_DATA_DEC_TRANS_REST: OK");
}
return ((keytype == AUTHKEYA && (AC == 0x00 || AC == 0x06 || AC == 0x01))
|| (keytype == AUTHKEYB && (AC == 0x00 || AC == 0x06 || AC == 0x01)));
}
@ -252,29 +269,33 @@ bool MifareSimInit(uint16_t flags, uint8_t *uid, uint16_t atqa, uint8_t sak, tag
// Length: 4,7,or 10 bytes
if (IS_FLAG_UID_IN_EMUL(flags)) {
if (uid == NULL) {
uid = uid_tmp;
}
// Get UID, SAK, ATQA from EMUL
uint8_t block0[16];
emlGet(block0, 0, 16);
uint8_t block0[MIFARE_BLOCK_SIZE];
emlGet(block0, 0, MIFARE_BLOCK_SIZE);
// Check for 4 bytes uid: bcc corrected and single size uid bits in ATQA
if ((block0[0] ^ block0[1] ^ block0[2] ^ block0[3]) == block0[4] && (block0[6] & 0xc0) == 0) {
FLAG_SET_UID_IN_DATA(flags, 4);
memcpy(uid, block0, 4);
rSAK[0] = block0[5];
memcpy(rATQA, &block0[6], sizeof(rATQA));
}
// Check for 7 bytes UID: double size uid bits in ATQA
else if ((block0[8] & 0xc0) == 0x40) {
} else if ((block0[8] & 0xc0) == 0x40) {
// Check for 7 bytes UID: double size uid bits in ATQA
FLAG_SET_UID_IN_DATA(flags, 7);
memcpy(uid, block0, 7);
rSAK[0] = block0[7];
memcpy(rATQA, &block0[8], sizeof(rATQA));
} else {
Dbprintf("ERROR: " _RED_("Invalid dump. UID/SAK/ATQA not found"));
return false;
}
} else {
if (uid == NULL) {
Dbprintf("ERROR: " _RED_("Missing UID"));
@ -288,16 +309,19 @@ bool MifareSimInit(uint16_t flags, uint8_t *uid, uint16_t atqa, uint8_t sak, tag
memcpy(rATQA, rATQA_Mini, sizeof(rATQA));
rSAK[0] = rSAK_Mini;
if (g_dbglevel > DBG_NONE) Dbprintf("Enforcing Mifare Mini ATQA/SAK");
} else if (IS_FLAG_MF_SIZE(flags, MIFARE_1K_MAX_BYTES)) {
memcpy(rATQA, rATQA_1k, sizeof(rATQA));
rSAK[0] = rSAK_1k;
if (g_dbglevel > DBG_NONE) Dbprintf("Enforcing Mifare 1K ATQA/SAK");
} else if (IS_FLAG_MF_SIZE(flags, MIFARE_2K_MAX_BYTES)) {
memcpy(rATQA, rATQA_2k, sizeof(rATQA));
rSAK[0] = rSAK_2k;
*rats = rRATS;
*rats_len = sizeof(rRATS);
if (g_dbglevel > DBG_NONE) Dbprintf("Enforcing Mifare 2K ATQA/SAK with RATS support");
} else if (IS_FLAG_MF_SIZE(flags, MIFARE_4K_MAX_BYTES)) {
memcpy(rATQA, rATQA_4k, sizeof(rATQA));
rSAK[0] = rSAK_4k;
@ -825,8 +849,8 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *uid, uint16_t
// if key not known and FLAG_NESTED_AUTH_ATTACK and we have nt/nt_enc/parity, send recorded nt_enc and parity
if ((flags & FLAG_NESTED_AUTH_ATTACK) == FLAG_NESTED_AUTH_ATTACK) {
if (emlGetKey(cardAUTHSC, cardAUTHKEY) == 0) {
uint8_t buf[16] = {0};
emlGetMem(buf, (CARD_MEMORY_RF08S_OFFSET / MIFARE_BLOCK_SIZE) + cardAUTHSC, 1);
uint8_t buf[MIFARE_BLOCK_SIZE] = {0};
emlGetMem_xt(buf, (CARD_MEMORY_RF08S_OFFSET / MIFARE_BLOCK_SIZE) + cardAUTHSC, 1, MIFARE_BLOCK_SIZE);
if (buf[(cardAUTHKEY * 8) + 3] == 0xAA) { // extra check to tell we have nt/nt_enc/par_err
running_nested_auth_attack = true;
// nt
@ -955,7 +979,7 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *uid, uint16_t
// first block
if (blockNo == 4) {
p_em += blockNo * 16;
p_em += (blockNo * MIFARE_BLOCK_SIZE);
// TLV in NDEF, flip length between
// 4 | 03 21 D1 02 1C 53 70 91 01 09 54 02 65 6E 4C 69
// 0xFF means long length
@ -970,7 +994,7 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *uid, uint16_t
}
}
emlGetMem(response, blockNo, 1);
emlGetMem_xt(response, blockNo, 1, MIFARE_BLOCK_SIZE);
if (g_dbglevel >= DBG_EXTENDED) {
Dbprintf("[MFEMUL_WORK - ISO14443A_CMD_READBLOCK] Data Block[%d]: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", blockNo,
@ -1010,11 +1034,11 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *uid, uint16_t
}
} else {
if (IsAccessAllowed(blockNo, cardAUTHKEY, AC_DATA_READ) == false) {
memset(response, 0x00, 16); // datablock cannot be read
memset(response, 0x00, MIFARE_BLOCK_SIZE); // datablock cannot be read
if (g_dbglevel >= DBG_EXTENDED) Dbprintf("[MFEMUL_WORK - IsAccessAllowed] Data block %d (0x%02x) cannot be read", blockNo, blockNo);
}
}
AddCrc14A(response, 16);
AddCrc14A(response, MIFARE_BLOCK_SIZE);
mf_crypto1_encrypt(pcs, response, MAX_MIFARE_FRAME_SIZE, response_par);
EmSendCmdPar(response, MAX_MIFARE_FRAME_SIZE, response_par);
FpgaDisableTracing();
@ -1109,7 +1133,9 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *uid, uint16_t
// case MFEMUL_WORK => CMD RATS
if (receivedCmd_len == 4 && receivedCmd_dec[0] == ISO14443A_CMD_RATS && (receivedCmd_dec[1] & 0xF0) <= 0x80 && (receivedCmd_dec[1] & 0x0F) <= 0x0e) {
if (rats && rats_len) {
if (encrypted_data) {
memcpy(response, rats, rats_len);
mf_crypto1_encrypt(pcs, response, rats_len, response_par);
@ -1117,46 +1143,58 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *uid, uint16_t
} else {
EmSendCmd(rats, rats_len);
}
FpgaDisableTracing();
if (g_dbglevel >= DBG_EXTENDED)
if (g_dbglevel >= DBG_EXTENDED) {
Dbprintf("[MFEMUL_WORK] RCV RATS => ACK");
}
} else {
EmSend4bit(encrypted_data ? mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA) : CARD_NACK_NA);
FpgaDisableTracing();
cardSTATE_TO_IDLE();
if (g_dbglevel >= DBG_EXTENDED)
if (g_dbglevel >= DBG_EXTENDED) {
Dbprintf("[MFEMUL_WORK] RCV RATS => NACK");
}
}
break;
}
// case MFEMUL_WORK => ISO14443A_CMD_NXP_DESELECT
if (receivedCmd_len == 3 && receivedCmd_dec[0] == ISO14443A_CMD_NXP_DESELECT) {
if (rats && rats_len) {
// response back NXP_DESELECT
if (encrypted_data) {
memcpy(response, receivedCmd_dec, receivedCmd_len);
mf_crypto1_encrypt(pcs, response, receivedCmd_len, response_par);
EmSendCmdPar(response, receivedCmd_len, response_par);
} else
} else {
EmSendCmd(receivedCmd_dec, receivedCmd_len);
}
FpgaDisableTracing();
if (g_dbglevel >= DBG_EXTENDED)
if (g_dbglevel >= DBG_EXTENDED) {
Dbprintf("[MFEMUL_WORK] RCV NXP DESELECT => ACK");
}
} else {
EmSend4bit(encrypted_data ? mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA) : CARD_NACK_NA);
FpgaDisableTracing();
cardSTATE_TO_IDLE();
if (g_dbglevel >= DBG_EXTENDED)
if (g_dbglevel >= DBG_EXTENDED) {
Dbprintf("[MFEMUL_WORK] RCV NXP DESELECT => NACK");
}
}
break;
}
// case MFEMUL_WORK => command not allowed
if (g_dbglevel >= DBG_EXTENDED)
if (g_dbglevel >= DBG_EXTENDED) {
Dbprintf("Received command not allowed, nacking");
}
EmSend4bit(encrypted_data ? mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA) : CARD_NACK_NA);
FpgaDisableTracing();
break;
@ -1164,14 +1202,16 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *uid, uint16_t
// AUTH1
case MFEMUL_AUTH1: {
if (g_dbglevel >= DBG_EXTENDED)
if (g_dbglevel >= DBG_EXTENDED) {
Dbprintf("[MFEMUL_AUTH1] Enter case");
}
if (receivedCmd_len != 8) {
cardSTATE_TO_IDLE();
LogTrace(uart->output, uart->len, uart->startTime * 16 - DELAY_AIR2ARM_AS_TAG, uart->endTime * 16 - DELAY_AIR2ARM_AS_TAG, uart->parity, true);
if (g_dbglevel >= DBG_EXTENDED)
if (g_dbglevel >= DBG_EXTENDED) {
Dbprintf("MFEMUL_AUTH1: receivedCmd_len != 8 (%d) => cardSTATE_TO_IDLE())", receivedCmd_len);
}
break;
}
@ -1191,6 +1231,7 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *uid, uint16_t
ar_nr_resp[0].state = NESTED;
finished = true;
}
if ((flags & FLAG_NR_AR_ATTACK) == FLAG_NR_AR_ATTACK) {
for (uint8_t i = 0; i < ATTACK_KEY_COUNT; i++) {
@ -1267,12 +1308,16 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *uid, uint16_t
// WRITE BL2
case MFEMUL_WRITEBL2: {
if (receivedCmd_len == MAX_MIFARE_FRAME_SIZE) {
mf_crypto1_decryptEx(pcs, receivedCmd, receivedCmd_len, receivedCmd_dec);
if (CheckCrc14A(receivedCmd_dec, receivedCmd_len)) {
if (IsSectorTrailer(cardWRBL)) {
emlGetMem(response, cardWRBL, 1);
emlGetMem_xt(response, cardWRBL, 1, MIFARE_BLOCK_SIZE);
if (IsAccessAllowed(cardWRBL, cardAUTHKEY, AC_KEYA_WRITE) == false) {
memcpy(receivedCmd_dec, response, 6); // don't change KeyA

View file

@ -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))) {

View file

@ -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);

View file

@ -437,10 +437,10 @@ uint16_t sam_copy_payload_sam2nfc(uint8_t *nfc_tx_buf, uint8_t *sam_rx_buf) {
// 90 00
// NFC req:
// 0C 05 DE 64
// 0C 05 DE 64
// copy data out of c1->a1>->a1->80 node
uint16_t nfc_tx_len = (uint8_t) * (sam_rx_buf + 10);
memcpy(nfc_tx_buf, sam_rx_buf + 11, nfc_tx_len);
return nfc_tx_len;
}
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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);

View file

@ -10,7 +10,7 @@ local green = ac.green
author = ' Author: jareckib - created 04.02.2025'
version = ' version v1.05'
desc = [[
desc = [[
A simple script for searching the password for T5577. The script creates a
dictionary starting from the entered starting year to the entered ending year.
There are two search methods - DDMMYYYY or YYYYMMDD. Checking the entire year
@ -102,11 +102,11 @@ local function main(args)
for o, a in getopt.getopt(args, 'hs:e:dy') do
if o == 'h' then return help() end
if o == 's' then
if o == 's' then
start_year = tonumber(a)
if not start_year then return oops(' Invalid start year') end
end
if o == 'e' then
if o == 'e' then
end_year = tonumber(a)
if not end_year then return oops(' Invalid end year') end
end
@ -115,13 +115,13 @@ local function main(args)
end
if not start_year then return oops(' Starting year is required') end
if start_year < 1900 or start_year > 2100 then
return oops(' Start year must be between 1900 and 2100')
if start_year < 1900 or start_year > 2100 then
return oops(' Start year must be between 1900 and 2100')
end
if args[#args] == "-e" then return oops(' Ending year cannot be empty') end
if not end_year then end_year = current_year end
if end_year < 1900 or end_year > 2100 then
return oops(' End year must be between 1900 and 2100')
if end_year < 1900 or end_year > 2100 then
return oops(' End year must be between 1900 and 2100')
end
if end_year < start_year then return oops(' End year cannot be earlier than start year') end
@ -130,7 +130,7 @@ local function main(args)
if generate_dictionary(start_year, end_year, mode) then
print(ac.green .. " File created: " .. dictionary_path .. res)
print(cyan .. " Starting password testing on T5577..." .. res)
core.console('lf t55 chk -f ' .. dictionary_path)
core.console('lf t55 chk -f ' .. dictionary_path)
else
return oops('Problem saving the file')
end

View file

@ -6,7 +6,7 @@ local dash = string.rep('--', 32)
author = ' Author: jareckib - created 01.02.2025'
version = ' version v1.01'
desc = [[
desc = [[
A simple script for searching the password for T5577. The script creates a
dictionary starting from the entered starting year to the entered ending year.
There are two search methods - DDMMYYYY or YYYYMMDD. Checking the entire year
@ -84,11 +84,11 @@ local function get_valid_year_input(prompt)
local year
while true do
io.write(prompt)
local input = io.read()
local input = io.read()
if input == "" then
print(ac.yellow .. ' ERROR: ' .. ac.reset .. 'Year cannot be empty')
else
year = tonumber(input)
year = tonumber(input)
if not year then
print(ac.yellow .. ' ERROR: ' .. ac.reset .. 'Invalid input (digits only)')
elseif year < 1900 then
@ -155,7 +155,7 @@ local function main(args)
if generate_dictionary(start_year, end_year, mode) then
print(ac.green .. " File created: " .. dictionary_path .. ac.reset)
print(ac.cyan .. " Starting password testing on T5577..." .. ac.reset)
core.console('lf t55 chk -f ' .. dictionary_path)
core.console('lf t55 chk -f ' .. dictionary_path)
else
print(ac.yellow .. ' ERROR: ' .. ac.reset .. 'Problem saving the file.')
end

View file

@ -9,11 +9,11 @@ local command = core.console
author = ' Author: jareckib - 15.02.2025'
version = ' version v1.00'
desc = [[
This simple script first checks if a password has been set for the T5577.
It uses the dictionary t55xx_default_pwds.dic for this purpose. If a password
is found, it uses the wipe command to erase the T5577. Then the reanimation
procedure is applied. If the password is not found or doesn't exist the script
desc = [[
This simple script first checks if a password has been set for the T5577.
It uses the dictionary t55xx_default_pwds.dic for this purpose. If a password
is found, it uses the wipe command to erase the T5577. Then the reanimation
procedure is applied. If the password is not found or doesn't exist the script
only performs the reanimation procedure. The script revives 99% of blocked tags.
]]
usage = [[
@ -91,7 +91,7 @@ end
local function main(args)
for o, a in getopt.getopt(args, 'h') do
if o == 'h' then return help() end
end
end
command('lf t55 chk')
local log_content = read_log_file(logfile)
local password = log_content and extract_password(log_content) or nil

View file

@ -1,5 +1,5 @@
# paxton_net.py - Convert Paxton Net2 to EM4102
# Author jareckib <jareckib@hotmail.com>
# Author jareckib <jareckib@hotmail.com>
# Based on Equipter's tutorial - Downgrade Paxton Net to EM410x
#
# This code is copyright (c) jareckib, 2025, All rights reserved.

View file

@ -1,5 +1,5 @@
# paxton_convert.py - Convert Paxton Net2 and Switch2 to EM4102
# Author jareckib <jareckib@hotmail.com>
# Author jareckib <jareckib@hotmail.com>
# Based on Equipter's tutorial - Downgrade Paxton Net to EM410x
#
# This code is copyright (c) jareckib, 2025, All rights reserved.

View file

@ -1,5 +1,5 @@
# paxton_switch.py - Convert Paxton Switch2 to EM4102
# Author jareckib <jareckib@hotmail.com>
# Author jareckib <jareckib@hotmail.com>
# Based on Equipter's tutorial - Downgrade Paxton Net to EM410x
#
# This code is copyright (c) jareckib, 2025, All rights reserved.

View file

@ -194,7 +194,7 @@ def Describe_Usage_2_1(Usage, ContractMediumEndDate, Certificate):
EventGeoRoute_Direction = Usage.nom(2)
EventGeoVehicleId = Usage.nom(16)
EventCountPassengers_mb = Usage.nom(4)
EventValidityTimeFirstStamp = Usage.nom(11)
print(' EventDateStamp : {} ({})'.format(EventDateStamp, (datetime(1997, 1, 1) + timedelta(days = ContractMediumEndDate - EventDateStamp)).strftime('%Y-%m-%d')))
@ -446,7 +446,7 @@ def main():
oa = MAR_OrganizationalAuthority_Contract_Provider.get(OrganizationalAuthority)
else:
oa = None
if (oa is not None):
s = oa.get(ContractProvider)
if (s is not None):

View file

@ -3784,22 +3784,22 @@ int CmdHF14AAIDSim(const char *Cmd) {
if (ats_len > sizeof(ats)) {
PrintAndLogEx(ERR, "Provided ATS too long");
return PM3_EINVARG;
return PM3_EINVARG;
}
if (aid_len > sizeof(aid)) {
PrintAndLogEx(ERR, "Provided AID too long");
return PM3_EINVARG;
return PM3_EINVARG;
}
if (selectaid_response_len > sizeof(selectaid_response)) {
PrintAndLogEx(ERR, "Provided SelectAID response too long");
return PM3_EINVARG;
return PM3_EINVARG;
}
if (getdata_response_len > sizeof(getdata_response)) {
PrintAndLogEx(ERR, "Provided GetData response too long");
return PM3_EINVARG;
return PM3_EINVARG;
}
if (ats_len > 0) {
@ -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();
}

View file

@ -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");

View file

@ -3246,14 +3246,14 @@ 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) {
PrintAndLogEx(INFO, "----------------------- " _CYAN_("SIO - ASN1 TLV") " ---------------------------");
asn1_print(sio_start, sio_length, " ");
PrintAndLogEx(NORMAL, "");
}
asn1_print(sio_start, sio_length, " ");
PrintAndLogEx(NORMAL, "");
}
}
void printIclassDumpContents(uint8_t *iclass_dump, uint8_t startblock, uint8_t endblock, size_t filesize, bool dense_output) {
@ -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);

View file

@ -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);
}
@ -306,31 +305,31 @@ static void mf_print_block(uint8_t blockno, uint8_t *d, bool verbose) {
ascii_to_buffer((uint8_t *)ascii, d, MFBLOCK_SIZE, sizeof(ascii) - 1, 1);
if (blockno >= MIFARE_1K_MAXBLOCK) {
PrintAndLogEx(INFO,
_BACK_BLUE_("%s| %3d | " _YELLOW_("%s"))
_BACK_BLUE_(_MAGENTA_("%s"))
_BACK_BLUE_("%02X ")
_BACK_BLUE_(_YELLOW_("%s"))
_BACK_BLUE_("| " _YELLOW_("%s"))
,
secstr,
blockno,
keya,
acl,
d[9],
keyb,
ascii
);
PrintAndLogEx(INFO,
_BACK_BLUE_("%s| %3d | " _YELLOW_("%s"))
_BACK_BLUE_(_MAGENTA_("%s"))
_BACK_BLUE_("%02X ")
_BACK_BLUE_(_YELLOW_("%s"))
_BACK_BLUE_("| " _YELLOW_("%s"))
,
secstr,
blockno,
keya,
acl,
d[9],
keyb,
ascii
);
} else {
PrintAndLogEx(INFO, "%s| %3d | " _YELLOW_("%s") _MAGENTA_("%s") "%02X " _YELLOW_("%s") "| " _YELLOW_("%s"),
secstr,
blockno,
keya,
acl,
d[9],
keyb,
ascii
);
secstr,
blockno,
keya,
acl,
d[9],
keyb,
ascii
);
}
} else {
@ -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
@ -7851,7 +7862,7 @@ static int CmdHF14AMfView(const char *Cmd) {
if (bytes_read == MIFARE_MINI_MAX_BYTES)
block_cnt = MIFARE_MINI_MAXBLOCK;
else if (bytes_read == MIFARE_1K_EV1_MAX_BYTES)
block_cnt = MIFARE_1K_EV1_MAXBLOCK;
block_cnt = MIFARE_1K_EV1_MAXBLOCK;
else if (bytes_read == MIFARE_2K_MAX_BYTES)
block_cnt = MIFARE_2K_MAXBLOCK;
else if (bytes_read == MIFARE_4K_MAX_BYTES)
@ -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;

View file

@ -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);
}

View file

@ -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);
}

View file

@ -453,7 +453,7 @@ static int seos_challenge_get(uint8_t *RNDICC, uint8_t RNDICC_len, uint8_t keysl
char getChallengePre[21];
strcpy(getChallengePre, "008700");
// const char keyslot_str[3] = "01";
//strcat(getChallengePre, keyslot_str);
snprintf(getChallengePre + strlen(getChallengePre), 3, "%02u", keyslot);
@ -547,7 +547,7 @@ static int select_DF_verify(uint8_t *response, uint8_t response_length, uint8_t
// Response is an ASN.1 encoded structure
// Extract everything before the 8E tag
int res = PM3_EWRONGANSWER;
int res = PM3_EWRONGANSWER;
for (int i = 0; i < response_length; i++) {
// extract MAC
if (response[i] == 0x8E) {
@ -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");

View file

@ -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);
}

View file

@ -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;
}

View file

@ -1031,7 +1031,7 @@ int DesfireSelectAndAuthenticateEx(DesfireContext_t *dctx, DesfireSecureChannel
isosw = true;
if (verbose) {
PrintAndLogEx(INFO, "Switch to " _CYAN_("native") " for select");
}
}
}
int res;
@ -1055,7 +1055,7 @@ int DesfireSelectAndAuthenticateEx(DesfireContext_t *dctx, DesfireSecureChannel
if (verbose) {
PrintAndLogEx(INFO, "App %06x " _GREEN_("selected"), aid);
}
}
}
if (isosw) {
@ -1124,7 +1124,7 @@ int DesfireSelectAndAuthenticateW(DesfireContext_t *dctx, DesfireSecureChannel s
if (verbose) {
PrintAndLogEx(INFO, "Application %s file iso id %04x is " _GREEN_("selected"), DesfireWayIDStr(way, id), isofileid);
}
}
}
if (!noauth) {

View file

@ -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;
}

View file

@ -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);

View file

@ -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) {

View file

@ -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);

View file

@ -883,7 +883,7 @@ static bool Pack_H800002(int format_idx, wiegand_card_t *card,
memset(packed, 0, sizeof(wiegand_message_t));
if (!validate_card_limit(format_idx, card)) {
return false;
return false;
}
packed->Length = 46;
@ -896,7 +896,7 @@ static bool Pack_H800002(int format_idx, wiegand_card_t *card,
// Invert parity for setting odd parity
set_bit_by_position(packed, even_parity ^ 1, 45);
if (preamble) {
return add_HID_header(packed);
return add_HID_header(packed);
}
return true;
}
@ -906,7 +906,7 @@ static bool Unpack_H800002(wiegand_message_t *packed, wiegand_card_t *card) {
memset(card, 0, sizeof(wiegand_card_t));
if (packed->Length != 46) {
return false; // Wrong length? Stop here.
return false; // Wrong length? Stop here.
}
card->FacilityCode = get_linear_field(packed, 1, 14);
@ -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));
}
@ -1586,7 +1586,7 @@ bool HIDTryUnpack(wiegand_message_t *packed) {
if (found_cnt) {
PrintAndLogEx(INFO, "found %u matching format%c with bit len %d", found_cnt, (found_cnt > 1) ? 's' : ' ', packed->Length);
}
if (packed->Length && ((found_cnt - found_invalid_par) == 0)) { // if length > 0 and no valid parity matches
PrintAndLogEx(WARNING, "Wiegand unknown bit len %d", packed->Length);
PrintAndLogEx(HINT, "Try 0xFFFF's http://cardinfo.barkweb.com.au/");
@ -1607,7 +1607,7 @@ void HIDUnpack(int idx, wiegand_message_t *packed) {
// return true if at least one valid matching formats found
bool decode_wiegand(uint32_t top, uint32_t mid, uint32_t bot, int n) {
bool decode_result;
if (top == 0 && mid == 0 && bot == 0) {
decode_result = false;
} else if ((n > 0) || ((mid & 0xFFFFFFC0) > 0)) { // if n > 0 or there's more than 38 bits

View file

@ -134,7 +134,7 @@ static uint8_t get_length_from_header(wiegand_message_t *data) {
* Right now we just calculate the highest bit set
* 38 bits format is handled by directly setting n=38 in initialize_message_object()
* since it's hard to distinguish 38 bits with formats with preamble bit (26-36 bits)
*
*
* (from http://www.proxmark.org/forum/viewtopic.php?pid=5368#p5368)
* 0000 0010 0000 0000 01xx xxxx xxxx xxxx xxxx xxxx xxxx 26-bit
* 0000 0010 0000 0000 1xxx xxxx xxxx xxxx xxxx xxxx xxxx 27-bit
@ -156,7 +156,7 @@ static uint8_t get_length_from_header(wiegand_message_t *data) {
if ((data->Top & 0x000FFFFF) > 0) { // > 64 bits
hfmt = data->Top & 0x000FFFFF;
len = 64;
} else if (data->Mid > 0) {
} else if (data->Mid > 0) {
// detect HID format b38 set
if (data->Mid & 0xFFFFFFC0) { // 39-64 bits
hfmt = data->Mid;
@ -165,14 +165,14 @@ static uint8_t get_length_from_header(wiegand_message_t *data) {
PrintAndLogEx(DEBUG, "hid preamble detected");
// if bit 38 is set: => 26-36 bits
if (((data->Mid >> 5) & 1) == 1) {
if (((data->Mid >> 5) & 1) == 1) {
hfmt = (((data->Mid & 31) << 12) | (data->Bot >> 26)); //get bits 27-37 to check for format len bit
len = 19;
} else { // if bit 38 is not set => 37 bits
hfmt = 0;
len = 37;
}
}
}
}
} else {
hfmt = data->Bot;
len = 0;

View file

@ -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++) {

View file

@ -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]);

View file

@ -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;
}

View file

@ -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));

View file

@ -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"
}
}

View file

@ -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`

View file

@ -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

View file

@ -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