diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 340b53555..26bac8435 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -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 diff --git a/armsrc/BigBuf.c b/armsrc/BigBuf.c index f3f84af13..26af3af0d 100644 --- a/armsrc/BigBuf.c +++ b/armsrc/BigBuf.c @@ -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; diff --git a/armsrc/Standalone/hf_colin.c b/armsrc/Standalone/hf_colin.c index ad45cda1a..61c93514b 100644 --- a/armsrc/Standalone/hf_colin.c +++ b/armsrc/Standalone/hf_colin.c @@ -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; diff --git a/armsrc/Standalone/hf_mattyrun.c b/armsrc/Standalone/hf_mattyrun.c index ad1e6b863..615d79718 100644 --- a/armsrc/Standalone/hf_mattyrun.c +++ b/armsrc/Standalone/hf_mattyrun.c @@ -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); diff --git a/armsrc/Standalone/lf_hidbrute.c b/armsrc/Standalone/lf_hidbrute.c index 6bdf27384..822df3bfb 100644 --- a/armsrc/Standalone/lf_hidbrute.c +++ b/armsrc/Standalone/lf_hidbrute.c @@ -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) { diff --git a/armsrc/Standalone/lf_prox2brute.c b/armsrc/Standalone/lf_prox2brute.c index ab736a9d1..86c06a91a 100644 --- a/armsrc/Standalone/lf_prox2brute.c +++ b/armsrc/Standalone/lf_prox2brute.c @@ -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); diff --git a/armsrc/appmain.c b/armsrc/appmain.c index aeff70df2..9140c03c3 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -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: { diff --git a/armsrc/desfire_crypto.c b/armsrc/desfire_crypto.c index 24da62747..0e9dc9466 100644 --- a/armsrc/desfire_crypto.c +++ b/armsrc/desfire_crypto.c @@ -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); } } diff --git a/armsrc/desfire_crypto.h b/armsrc/desfire_crypto.h index 3413125d4..10a15fbf9 100644 --- a/armsrc/desfire_crypto.h +++ b/armsrc/desfire_crypto.h @@ -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 diff --git a/armsrc/emvsim.c b/armsrc/emvsim.c index fd50b040d..5b2c2b58e 100644 --- a/armsrc/emvsim.c +++ b/armsrc/emvsim.c @@ -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 diff --git a/armsrc/hitagS.c b/armsrc/hitagS.c index 932f4bcc1..b80210f66 100644 --- a/armsrc/hitagS.c +++ b/armsrc/hitagS.c @@ -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"); } } diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index ba66eb063..f469061d7 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -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) { diff --git a/armsrc/iso14443a.h b/armsrc/iso14443a.h index 34a94dbb5..7c9eed81b 100644 --- a/armsrc/iso14443a.h +++ b/armsrc/iso14443a.h @@ -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, diff --git a/armsrc/iso15693.c b/armsrc/iso15693.c index cbf9e8f88..390766099 100644 --- a/armsrc/iso15693.c +++ b/armsrc/iso15693.c @@ -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) { diff --git a/armsrc/iso15693.h b/armsrc/iso15693.h index 0f04fddf9..81bc2d1a0 100644 --- a/armsrc/iso15693.h +++ b/armsrc/iso15693.h @@ -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 diff --git a/armsrc/lfops.c b/armsrc/lfops.c index 8215a07ea..46c1e0d3f 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -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 diff --git a/armsrc/lfops.h b/armsrc/lfops.h index 9d9a029d4..5a25a74d8 100644 --- a/armsrc/lfops.h +++ b/armsrc/lfops.h @@ -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); diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c index 8e9d93bc7..a027dcecc 100644 --- a/armsrc/mifarecmd.c +++ b/armsrc/mifarecmd.c @@ -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); diff --git a/armsrc/mifarecmd.h b/armsrc/mifarecmd.h index 2dcfa4e4b..f6d190d82 100644 --- a/armsrc/mifarecmd.h +++ b/armsrc/mifarecmd.h @@ -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); diff --git a/armsrc/mifaresim.c b/armsrc/mifaresim.c index 4ee88ec34..c58025473 100644 --- a/armsrc/mifaresim.c +++ b/armsrc/mifaresim.c @@ -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 diff --git a/armsrc/mifareutil.c b/armsrc/mifareutil.c index b8cb4838d..d19233f0a 100644 --- a/armsrc/mifareutil.c +++ b/armsrc/mifareutil.c @@ -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))) { diff --git a/armsrc/mifareutil.h b/armsrc/mifareutil.h index d2d259c73..28987c363 100644 --- a/armsrc/mifareutil.h +++ b/armsrc/mifareutil.h @@ -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); diff --git a/armsrc/sam_common.c b/armsrc/sam_common.c index ebedfc3b4..567520ee3 100644 --- a/armsrc/sam_common.c +++ b/armsrc/sam_common.c @@ -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; -} \ No newline at end of file +} diff --git a/armsrc/sam_picopass.c b/armsrc/sam_picopass.c index 450e46253..270468f66 100644 --- a/armsrc/sam_picopass.c +++ b/armsrc/sam_picopass.c @@ -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; } diff --git a/armsrc/sam_seos.c b/armsrc/sam_seos.c index facdb2545..7d4a018be 100644 --- a/armsrc/sam_seos.c +++ b/armsrc/sam_seos.c @@ -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; } diff --git a/armsrc/spiffs_check.c b/armsrc/spiffs_check.c index 636feb769..e082fefbb 100644 --- a/armsrc/spiffs_check.c +++ b/armsrc/spiffs_check.c @@ -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); diff --git a/client/luascripts/lf_t55xx_chk.lua b/client/luascripts/lf_t55xx_chk.lua index 9343b0cde..6c1da33ce 100644 --- a/client/luascripts/lf_t55xx_chk.lua +++ b/client/luascripts/lf_t55xx_chk.lua @@ -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 diff --git a/client/luascripts/lf_t55xx_chk_date.lua b/client/luascripts/lf_t55xx_chk_date.lua index dcd5124d2..29b26d506 100644 --- a/client/luascripts/lf_t55xx_chk_date.lua +++ b/client/luascripts/lf_t55xx_chk_date.lua @@ -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 diff --git a/client/luascripts/lf_t55xx_fix.lua b/client/luascripts/lf_t55xx_fix.lua index bed267eac..a77cb2b9b 100644 --- a/client/luascripts/lf_t55xx_fix.lua +++ b/client/luascripts/lf_t55xx_fix.lua @@ -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 diff --git a/client/pyscripts/PAXTON_NET.py b/client/pyscripts/PAXTON_NET.py index 532ca276e..921cc9459 100644 --- a/client/pyscripts/PAXTON_NET.py +++ b/client/pyscripts/PAXTON_NET.py @@ -1,5 +1,5 @@ # paxton_net.py - Convert Paxton Net2 to EM4102 -# Author jareckib +# Author jareckib # Based on Equipter's tutorial - Downgrade Paxton Net to EM410x # # This code is copyright (c) jareckib, 2025, All rights reserved. diff --git a/client/pyscripts/Paxton_convert.py b/client/pyscripts/Paxton_convert.py index 9c00d5326..0a0415bff 100644 --- a/client/pyscripts/Paxton_convert.py +++ b/client/pyscripts/Paxton_convert.py @@ -1,5 +1,5 @@ # paxton_convert.py - Convert Paxton Net2 and Switch2 to EM4102 -# Author jareckib +# Author jareckib # Based on Equipter's tutorial - Downgrade Paxton Net to EM410x # # This code is copyright (c) jareckib, 2025, All rights reserved. diff --git a/client/pyscripts/Paxton_switch.py b/client/pyscripts/Paxton_switch.py index b65b1d39b..e51def0f7 100644 --- a/client/pyscripts/Paxton_switch.py +++ b/client/pyscripts/Paxton_switch.py @@ -1,5 +1,5 @@ # paxton_switch.py - Convert Paxton Switch2 to EM4102 -# Author jareckib +# Author jareckib # Based on Equipter's tutorial - Downgrade Paxton Net to EM410x # # This code is copyright (c) jareckib, 2025, All rights reserved. diff --git a/client/pyscripts/intertic.py b/client/pyscripts/intertic.py index f262040c2..2793aee43 100644 --- a/client/pyscripts/intertic.py +++ b/client/pyscripts/intertic.py @@ -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): diff --git a/client/src/cmdhf14a.c b/client/src/cmdhf14a.c index 33ce1a28d..bb551687e 100644 --- a/client/src/cmdhf14a.c +++ b/client/src/cmdhf14a.c @@ -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(); } diff --git a/client/src/cmdhf15.c b/client/src/cmdhf15.c index e2295c697..c50f6b5e0 100644 --- a/client/src/cmdhf15.c +++ b/client/src/cmdhf15.c @@ -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"); diff --git a/client/src/cmdhficlass.c b/client/src/cmdhficlass.c index d99cbe986..136d5abea 100644 --- a/client/src/cmdhficlass.c +++ b/client/src/cmdhficlass.c @@ -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); diff --git a/client/src/cmdhfmf.c b/client/src/cmdhfmf.c index 70e0bbf40..7034ab6f3 100644 --- a/client/src/cmdhfmf.c +++ b/client/src/cmdhfmf.c @@ -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; diff --git a/client/src/cmdhfmfp.c b/client/src/cmdhfmfp.c index 70bc28e09..bb3bbe58d 100644 --- a/client/src/cmdhfmfp.c +++ b/client/src/cmdhfmfp.c @@ -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); } diff --git a/client/src/cmdhfmfu.c b/client/src/cmdhfmfu.c index ed8ddaf01..dc6a982b4 100644 --- a/client/src/cmdhfmfu.c +++ b/client/src/cmdhfmfu.c @@ -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); } diff --git a/client/src/cmdhfseos.c b/client/src/cmdhfseos.c index 3160c1c84..efbb37657 100644 --- a/client/src/cmdhfseos.c +++ b/client/src/cmdhfseos.c @@ -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"); diff --git a/client/src/cmdhfst25ta.c b/client/src/cmdhfst25ta.c index 7dff65067..b2846b689 100644 --- a/client/src/cmdhfst25ta.c +++ b/client/src/cmdhfst25ta.c @@ -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); } diff --git a/client/src/crypto/originality.c b/client/src/crypto/originality.c index 5d667420f..6b6e687a0 100644 --- a/client/src/crypto/originality.c +++ b/client/src/crypto/originality.c @@ -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; } diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index 07297d05a..f390c3ca2 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -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) { diff --git a/client/src/mifare/mad.c b/client/src/mifare/mad.c index e254fd187..10335994f 100644 --- a/client/src/mifare/mad.c +++ b/client/src/mifare/mad.c @@ -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; } diff --git a/client/src/mifare/mad.h b/client/src/mifare/mad.h index d1f5240f4..1da097527 100644 --- a/client/src/mifare/mad.h +++ b/client/src/mifare/mad.h @@ -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); diff --git a/client/src/mifare/mifarehost.c b/client/src/mifare/mifarehost.c index 0a9d7aba9..a2a8de47a 100644 --- a/client/src/mifare/mifarehost.c +++ b/client/src/mifare/mifarehost.c @@ -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) { diff --git a/client/src/mifare/mifarehost.h b/client/src/mifare/mifarehost.h index 6dc12da52..e043db324 100644 --- a/client/src/mifare/mifarehost.h +++ b/client/src/mifare/mifarehost.h @@ -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); diff --git a/client/src/wiegand_formats.c b/client/src/wiegand_formats.c index 69d869785..df1127ec1 100644 --- a/client/src/wiegand_formats.c +++ b/client/src/wiegand_formats.c @@ -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 diff --git a/client/src/wiegand_formatutils.c b/client/src/wiegand_formatutils.c index fed31d9fb..0a17f654d 100644 --- a/client/src/wiegand_formatutils.c +++ b/client/src/wiegand_formatutils.c @@ -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; diff --git a/common/commonutil.c b/common/commonutil.c index 7ed34067f..d4eed608e 100644 --- a/common/commonutil.c +++ b/common/commonutil.c @@ -17,6 +17,7 @@ //----------------------------------------------------------------------------- #include "commonutil.h" #include +#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++) { diff --git a/common/commonutil.h b/common/commonutil.h index 0b187ef10..2ab4fbd79 100644 --- a/common/commonutil.h +++ b/common/commonutil.h @@ -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]); diff --git a/common/mbedtls/asn1parse.c b/common/mbedtls/asn1parse.c index 98460e055..84a558bdc 100644 --- a/common/mbedtls/asn1parse.c +++ b/common/mbedtls/asn1parse.c @@ -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; } diff --git a/common/mbedtls/cmac.c b/common/mbedtls/cmac.c index 32a5937b0..b179ad483 100644 --- a/common/mbedtls/cmac.c +++ b/common/mbedtls/cmac.c @@ -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)); diff --git a/doc/commands.json b/doc/commands.json index d3b4e711e..d540c2bc8 100644 --- a/doc/commands.json +++ b/doc/commands.json @@ -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 <4|7|10> hex bytes UID", - "-r, --rats <0-20> hex bytes RATS", - "-a, --aid <0-100> hex bytes for AID to respond to (Default: A000000000000000000000)", - "-e, --response <0-100> hex bytes for APDU Response to AID Select (Default: 9000)", - "-p, --apdu <0-100> hex bytes for APDU Response to Get Data request after AID (Default: 9000)", + "-r, --ats <0-20> hex bytes ATS", + "-a, --aid <0-30> hex bytes for AID to respond to (Default: A000000000000000000000)", + "-e, --selectaid_response <0-100> hex bytes for APDU Response to AID Select (Default: 9000)", + "-p, --getdata_response <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 ] [-r ] [-a ] [-e ] [-p ]" @@ -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 DER encoded command to send to SAM" ], - "usage": "hf iclass sam [-hv]" + "usage": "hf iclass sam [-hvkntp] [--break-on-nr-mac] [--shallow] [-d ]..." }, "hf iclass sim": { "command": "hf iclass sim", @@ -4486,12 +4495,13 @@ "-f, --file 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 ] [--mini] [--1k] [--2k] [--4k] [--emu] [--gdm]" + "usage": "hf mf cload [-h] [-f ] [--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" } } diff --git a/doc/commands.md b/doc/commands.md index 8650508ff..032f7dd6d 100644 --- a/doc/commands.md +++ b/doc/commands.md @@ -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` diff --git a/include/pm3_cmd.h b/include/pm3_cmd.h index 9128dbb90..a592fb5c0 100644 --- a/include/pm3_cmd.h +++ b/include/pm3_cmd.h @@ -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 diff --git a/include/protocols.h b/include/protocols.h index eb22a89a7..7048263d5 100644 --- a/include/protocols.h +++ b/include/protocols.h @@ -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