mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-14 02:27:26 -07:00
code style, code clean up of redundant functions, comments, its many minor fixes across the platform. Sorry for not making 20 commits
This commit is contained in:
parent
6bb7199a7b
commit
cef07dedf6
57 changed files with 672 additions and 521 deletions
7
.github/workflows/codeql-analysis.yml
vendored
7
.github/workflows/codeql-analysis.yml
vendored
|
@ -45,6 +45,13 @@ jobs:
|
||||||
- name: Install dependencies
|
- 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
|
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
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
|
|
@ -321,9 +321,10 @@ bool RAMFUNC LogTraceBits(const uint8_t *btBytes, uint16_t bitLen, uint32_t time
|
||||||
// Emulator memory
|
// Emulator memory
|
||||||
int emlSet(const uint8_t *data, uint32_t offset, uint32_t length) {
|
int emlSet(const uint8_t *data, uint32_t offset, uint32_t length) {
|
||||||
uint8_t *mem = BigBuf_get_EM_addr();
|
uint8_t *mem = BigBuf_get_EM_addr();
|
||||||
if (!mem) {
|
if (mem == NULL) {
|
||||||
return PM3_EMALLOC;
|
return PM3_EMALLOC;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (offset + length <= CARD_MEMORY_SIZE) {
|
if (offset + length <= CARD_MEMORY_SIZE) {
|
||||||
memcpy(mem + offset, data, length);
|
memcpy(mem + offset, data, length);
|
||||||
return PM3_SUCCESS;
|
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) {
|
int emlGet(uint8_t *out, uint32_t offset, uint32_t length) {
|
||||||
uint8_t *mem = BigBuf_get_EM_addr();
|
uint8_t *mem = BigBuf_get_EM_addr();
|
||||||
if (!mem) {
|
if (mem == NULL) {
|
||||||
return PM3_EMALLOC;
|
return PM3_EMALLOC;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (offset + length <= CARD_MEMORY_SIZE) {
|
if (offset + length <= CARD_MEMORY_SIZE) {
|
||||||
memcpy(out, mem + offset, length);
|
memcpy(out, mem + offset, length);
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
|
|
|
@ -311,7 +311,7 @@ void WriteTagToFlash(uint32_t uid, size_t size) {
|
||||||
uint32_t len = size;
|
uint32_t len = size;
|
||||||
uint8_t data[(size * (16 * 64)) / 1024];
|
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];
|
char dest[SPIFFS_OBJ_NAME_LEN];
|
||||||
uint8_t buid[4];
|
uint8_t buid[4];
|
||||||
|
@ -646,7 +646,7 @@ failtag:
|
||||||
emlClearMem();
|
emlClearMem();
|
||||||
uint8_t mblock[16];
|
uint8_t mblock[16];
|
||||||
for (uint8_t sectorNo = 0; sectorNo < sectorsCnt; sectorNo++) {
|
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++) {
|
for (uint8_t t = 0; t < 2; t++) {
|
||||||
memcpy(mblock + t * 10, foundKey[t][sectorNo], 6);
|
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);
|
emlSetMem_xt(dataoutbuf, FirstBlockOfSector(s) + blockNo, 1, 16);
|
||||||
} else {
|
} else {
|
||||||
// sector trailer, keep the keys, set only the AC
|
// 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);
|
memcpy(&dataoutbuf2[6], &dataoutbuf[6], 4);
|
||||||
emlSetMem_xt(dataoutbuf2, FirstBlockOfSector(s) + blockNo, 1, 16);
|
emlSetMem_xt(dataoutbuf2, FirstBlockOfSector(s) + blockNo, 1, 16);
|
||||||
}
|
}
|
||||||
|
@ -878,7 +878,7 @@ void saMifareMakeTag(void) {
|
||||||
int flags = 0;
|
int flags = 0;
|
||||||
for (int blockNum = 0; blockNum < 16 * 4; blockNum++) {
|
for (int blockNum = 0; blockNum < 16 * 4; blockNum++) {
|
||||||
uint8_t mblock[16];
|
uint8_t mblock[16];
|
||||||
emlGetMem(mblock, blockNum, 1);
|
emlGetMem_xt(mblock, blockNum, 1, MIFARE_BLOCK_SIZE);
|
||||||
// switch on field and send magic sequence
|
// switch on field and send magic sequence
|
||||||
if (blockNum == 0)
|
if (blockNum == 0)
|
||||||
flags = 0x08 + 0x02;
|
flags = 0x08 + 0x02;
|
||||||
|
|
|
@ -500,7 +500,7 @@ void RunMod(void) {
|
||||||
uint8_t mblock[MIFARE_BLOCK_SIZE];
|
uint8_t mblock[MIFARE_BLOCK_SIZE];
|
||||||
for (uint8_t sectorNo = 0; sectorNo < sectorsCnt; ++sectorNo) {
|
for (uint8_t sectorNo = 0; sectorNo < sectorsCnt; ++sectorNo) {
|
||||||
if (validKey[0][sectorNo] || validKey[1][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) {
|
for (uint8_t keyType = 0; keyType < 2; ++keyType) {
|
||||||
if (validKey[keyType][sectorNo]) {
|
if (validKey[keyType][sectorNo]) {
|
||||||
memcpy(mblock + keyType * 10, foundKey[keyType][sectorNo], 6);
|
memcpy(mblock + keyType * 10, foundKey[keyType][sectorNo], 6);
|
||||||
|
|
|
@ -150,7 +150,7 @@ void RunMod(void) {
|
||||||
} else if (playing && selected == 2) {
|
} else if (playing && selected == 2) {
|
||||||
// Now it work only with HID Corporate 1000 (35bit), but is easily extensible to others RFID.
|
// 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.
|
// It is necessary only to calculate the correct parity.
|
||||||
|
|
||||||
// Brute force code
|
// Brute force code
|
||||||
// Check if the badge is an HID Corporate 1000
|
// Check if the badge is an HID Corporate 1000
|
||||||
if ((high[selected] & 0xFFFFFFF8) != 0x28) {
|
if ((high[selected] & 0xFFFFFFF8) != 0x28) {
|
||||||
|
|
|
@ -46,7 +46,7 @@ void RunMod(void) {
|
||||||
StandAloneMode();
|
StandAloneMode();
|
||||||
Dbprintf(">> LF HID proxII bruteforce v2 a.k.a Prox2Brute Started <<");
|
Dbprintf(">> LF HID proxII bruteforce v2 a.k.a Prox2Brute Started <<");
|
||||||
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
|
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
|
||||||
uint32_t high = 0, low = 0;
|
uint32_t high = 0;
|
||||||
|
|
||||||
uint32_t fac = FACILITY_CODE, cardnum = 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
|
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
|
// 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 |= oddparity32((low >> 1) & 0xFFF);
|
||||||
low |= evenparity32((low >> 13) & 0xFFF) << 25;
|
low |= evenparity32((low >> 13) & 0xFFF) << 25;
|
||||||
add_HID_preamble(NULL, &high, &low, 26);
|
add_HID_preamble(NULL, &high, &low, 26);
|
||||||
|
|
|
@ -1370,7 +1370,11 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||||
// involved in dealing with emulator memory. But if it is called later, it might
|
// involved in dealing with emulator memory. But if it is called later, it might
|
||||||
// destroy the Emulator Memory.
|
// 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;
|
break;
|
||||||
}
|
}
|
||||||
case CMD_HF_ISO15693_EML_SETMEM: {
|
case CMD_HF_ISO15693_EML_SETMEM: {
|
||||||
|
@ -1402,7 +1406,7 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t *buf = BigBuf_malloc(payload->length);
|
uint8_t *buf = BigBuf_calloc(payload->length);
|
||||||
emlGet(buf, payload->offset, payload->length);
|
emlGet(buf, payload->offset, payload->length);
|
||||||
LED_B_ON();
|
LED_B_ON();
|
||||||
reply_ng(CMD_HF_ISO15693_EML_GETMEM, PM3_SUCCESS, buf, payload->length);
|
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);
|
EMVsim(payload->flags, payload->exitAfter, payload->uid, payload->atqa, payload->sak);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
case CMD_HF_ISO14443A_SIMULATE: {
|
case CMD_HF_ISO14443A_SIMULATE: {
|
||||||
struct p {
|
struct p {
|
||||||
uint8_t tagtype;
|
uint8_t tagtype;
|
||||||
|
@ -1890,36 +1894,65 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CMD_HF_MIFARE_EML_MEMCLR: {
|
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);
|
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;
|
break;
|
||||||
}
|
}
|
||||||
case CMD_HF_MIFARE_EML_MEMSET: {
|
case CMD_HF_MIFARE_EML_MEMSET: {
|
||||||
|
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||||
struct p {
|
struct p {
|
||||||
uint8_t blockno;
|
uint16_t blockno;
|
||||||
uint8_t blockcnt;
|
uint8_t blockcnt;
|
||||||
uint8_t blockwidth;
|
uint8_t blockwidth;
|
||||||
uint8_t data[];
|
uint8_t data[];
|
||||||
} PACKED;
|
} PACKED;
|
||||||
struct p *payload = (struct p *) packet->data.asBytes;
|
struct p *payload = (struct p *) packet->data.asBytes;
|
||||||
|
|
||||||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
|
||||||
|
|
||||||
// backwards compat... default bytewidth
|
// backwards compat... default bytewidth
|
||||||
if (payload->blockwidth == 0)
|
if (payload->blockwidth == 0) {
|
||||||
payload->blockwidth = 16;
|
payload->blockwidth = MIFARE_BLOCK_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
emlSetMem_xt(payload->data, payload->blockno, payload->blockcnt, payload->blockwidth);
|
emlSetMem_xt(payload->data, payload->blockno, payload->blockcnt, payload->blockwidth);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CMD_HF_MIFARE_EML_MEMGET: {
|
case CMD_HF_MIFARE_EML_MEMGET: {
|
||||||
|
|
||||||
|
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||||
struct p {
|
struct p {
|
||||||
uint8_t blockno;
|
uint16_t blockno;
|
||||||
uint8_t blockcnt;
|
uint8_t blockcnt;
|
||||||
|
uint8_t blockwidth;
|
||||||
} PACKED;
|
} PACKED;
|
||||||
struct p *payload = (struct p *) packet->data.asBytes;
|
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;
|
break;
|
||||||
}
|
}
|
||||||
case CMD_HF_MIFARE_EML_LOAD: {
|
case CMD_HF_MIFARE_EML_LOAD: {
|
||||||
|
|
|
@ -133,7 +133,9 @@ void tdes_nxp_send(const void *in, void *out, size_t length, const void *key, ui
|
||||||
}
|
}
|
||||||
|
|
||||||
void aes128_nxp_receive(const void *in, void *out, size_t length, const void *key, unsigned char iv[16]) {
|
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 *tin = (uint8_t *) in;
|
||||||
uint8_t *tout = (uint8_t *) out;
|
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]) {
|
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 *tin = (uint8_t *) in;
|
||||||
uint8_t *tout = (uint8_t *) out;
|
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);
|
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) {
|
void Desfire_des_key_new(const uint8_t *value, desfirekey_t key) {
|
||||||
uint8_t data[8];
|
|
||||||
memcpy(data, value, 8);
|
uint8_t data[8] = {0};
|
||||||
for (int n = 0; n < 8; n++) {
|
memcpy(data, value, sizeof(data));
|
||||||
|
|
||||||
|
for (size_t n = 0; n < sizeof(data); n++) {
|
||||||
data[n] &= 0xFE;
|
data[n] &= 0xFE;
|
||||||
}
|
}
|
||||||
|
|
||||||
Desfire_des_key_new_with_version(data, key);
|
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) {
|
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) {
|
switch (authkey->type) {
|
||||||
case T_DES:
|
case T_DES: {
|
||||||
memcpy(buffer, rnda, 4);
|
memcpy(buffer, rnda, 4);
|
||||||
memcpy(buffer + 4, rndb, 4);
|
memcpy(buffer + 4, rndb, 4);
|
||||||
Desfire_des_key_new_with_version(buffer, key);
|
Desfire_des_key_new_with_version(buffer, key);
|
||||||
break;
|
break;
|
||||||
case T_3DES:
|
}
|
||||||
|
case T_3DES: {
|
||||||
memcpy(buffer, rnda, 4);
|
memcpy(buffer, rnda, 4);
|
||||||
memcpy(buffer + 4, rndb, 4);
|
memcpy(buffer + 4, rndb, 4);
|
||||||
memcpy(buffer + 8, rnda + 4, 4);
|
memcpy(buffer + 8, rnda + 4, 4);
|
||||||
memcpy(buffer + 12, rndb + 4, 4);
|
memcpy(buffer + 12, rndb + 4, 4);
|
||||||
Desfire_3des_key_new_with_version(buffer, key);
|
Desfire_3des_key_new_with_version(buffer, key);
|
||||||
break;
|
break;
|
||||||
case T_3K3DES:
|
}
|
||||||
|
case T_3K3DES: {
|
||||||
memcpy(buffer, rnda, 4);
|
memcpy(buffer, rnda, 4);
|
||||||
memcpy(buffer + 4, rndb, 4);
|
memcpy(buffer + 4, rndb, 4);
|
||||||
memcpy(buffer + 8, rnda + 6, 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);
|
memcpy(buffer + 20, rndb + 12, 4);
|
||||||
Desfire_3k3des_key_new(buffer, key);
|
Desfire_3k3des_key_new(buffer, key);
|
||||||
break;
|
break;
|
||||||
case T_AES:
|
}
|
||||||
|
case T_AES: {
|
||||||
memcpy(buffer, rnda, 4);
|
memcpy(buffer, rnda, 4);
|
||||||
memcpy(buffer + 4, rndb, 4);
|
memcpy(buffer + 4, rndb, 4);
|
||||||
memcpy(buffer + 8, rnda + 12, 4);
|
memcpy(buffer + 8, rnda + 12, 4);
|
||||||
memcpy(buffer + 12, rndb + 12, 4);
|
memcpy(buffer + 12, rndb + 12, 4);
|
||||||
Desfire_aes_key_new(buffer, key);
|
Desfire_aes_key_new(buffer, key);
|
||||||
break;
|
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
|
// Used to compute CMAC on complete blocks
|
||||||
memcpy(key->cmac_sk1, l, kbs);
|
memcpy(key->cmac_sk1, l, kbs);
|
||||||
|
|
||||||
txor = l[0] & 0x80;
|
txor = (l[0] & 0x80);
|
||||||
|
|
||||||
lsl(key->cmac_sk1, kbs);
|
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
|
// Used to compute CMAC on the last block if non-complete
|
||||||
memcpy(key->cmac_sk2, key->cmac_sk1, kbs);
|
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);
|
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) {
|
while (len % kbs) {
|
||||||
buffer[len++] = 0x00;
|
buffer[len++] = 0x00;
|
||||||
}
|
}
|
||||||
xor(key->cmac_sk2, buffer + len - kbs, kbs);
|
xor(buffer + len - kbs, key->cmac_sk2, kbs);
|
||||||
} else {
|
} 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);
|
mifare_cypher_blocks_chained(NULL, key, ivect, buffer, len, MCD_SEND, MCO_ENCYPHER);
|
||||||
|
|
||||||
memcpy(cmac, ivect, kbs);
|
memcpy(cmac, ivect, kbs);
|
||||||
//free(buffer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t key_block_size(const desfirekey_t key) {
|
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.
|
* 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;
|
size_t mac_length = DESFIRE_MAC_LENGTH;
|
||||||
switch (key->type) {
|
switch (key->type) {
|
||||||
case T_DES:
|
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 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) {
|
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;
|
return ((nbytes / block_size) + 1) * block_size;
|
||||||
else
|
} else {
|
||||||
return nbytes;
|
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;
|
size_t crc_length = 0;
|
||||||
if (!(communication_settings & NO_CRC)) {
|
if (!(communication_settings & NO_CRC)) {
|
||||||
switch (DESFIRE(tag)->authentication_scheme) {
|
switch (DESFIRE(tag)->authentication_scheme) {
|
||||||
case AS_LEGACY:
|
case AS_LEGACY: {
|
||||||
crc_length = 2;
|
crc_length = 2;
|
||||||
break;
|
break;
|
||||||
case AS_NEW:
|
}
|
||||||
|
case AS_NEW: {
|
||||||
crc_length = 4;
|
crc_length = 4;
|
||||||
break;
|
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) {
|
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 *res = data;
|
||||||
uint8_t mac[4];
|
uint8_t mac[4] = {0};
|
||||||
size_t edl;
|
size_t edl;
|
||||||
bool append_mac = true;
|
bool append_mac = true;
|
||||||
desfirekey_t key = DESFIRE(tag)->session_key;
|
|
||||||
|
|
||||||
if (!key)
|
desfirekey_t key = DESFIRE(tag)->session_key;
|
||||||
|
if (!key) {
|
||||||
return data;
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
switch (communication_settings & MDCM_MASK) {
|
switch (communication_settings & MDCM_MASK) {
|
||||||
case MDCM_PLAIN:
|
case MDCM_PLAIN: {
|
||||||
if (AS_LEGACY == DESFIRE(tag)->authentication_scheme)
|
if (AS_LEGACY == DESFIRE(tag)->authentication_scheme) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* When using new authentication methods, PLAIN data transmission from
|
* 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;
|
append_mac = false;
|
||||||
|
}
|
||||||
/* pass through */
|
/* pass through */
|
||||||
case MDCM_MACED:
|
case MDCM_MACED: {
|
||||||
switch (DESFIRE(tag)->authentication_scheme) {
|
switch (DESFIRE(tag)->authentication_scheme) {
|
||||||
case AS_LEGACY:
|
case AS_LEGACY: {
|
||||||
if (!(communication_settings & MAC_COMMAND))
|
|
||||||
|
if (!(communication_settings & MAC_COMMAND)) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* pass through */
|
/* pass through */
|
||||||
edl = padded_data_length(*nbytes - offset, key_block_size(DESFIRE(tag)->session_key)) + offset;
|
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)
|
// Copy again provided data (was overwritten by mifare_cypher_blocks_chained)
|
||||||
memcpy(res, data, *nbytes);
|
memcpy(res, data, *nbytes);
|
||||||
|
|
||||||
if (!(communication_settings & MAC_COMMAND))
|
if (!(communication_settings & MAC_COMMAND)) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
// Append MAC
|
// Append MAC
|
||||||
size_t bla = maced_data_length(DESFIRE(tag)->session_key, *nbytes - offset) + offset;
|
size_t bla = maced_data_length(DESFIRE(tag)->session_key, *nbytes - offset) + offset;
|
||||||
(void)bla++;
|
(void)bla++;
|
||||||
|
@ -485,9 +495,12 @@ void *mifare_cryto_preprocess_data(desfiretag_t tag, void *data, size_t *nbytes,
|
||||||
|
|
||||||
*nbytes += 4;
|
*nbytes += 4;
|
||||||
break;
|
break;
|
||||||
case AS_NEW:
|
}
|
||||||
if (!(communication_settings & CMAC_COMMAND))
|
case AS_NEW: {
|
||||||
|
if (!(communication_settings & CMAC_COMMAND)) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
cmac(key, DESFIRE(tag)->ivect, res, *nbytes, DESFIRE(tag)->cmac);
|
cmac(key, DESFIRE(tag)->ivect, res, *nbytes, DESFIRE(tag)->cmac);
|
||||||
|
|
||||||
if (append_mac) {
|
if (append_mac) {
|
||||||
|
@ -498,10 +511,11 @@ void *mifare_cryto_preprocess_data(desfiretag_t tag, void *data, size_t *nbytes,
|
||||||
*nbytes += DESFIRE_CMAC_LENGTH;
|
*nbytes += DESFIRE_CMAC_LENGTH;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case MDCM_ENCIPHERED:
|
}
|
||||||
|
case MDCM_ENCIPHERED: {
|
||||||
/* |<-------------- data -------------->|
|
/* |<-------------- data -------------->|
|
||||||
* |<--- offset -->| |
|
* |<--- offset -->| |
|
||||||
* +---------------+--------------------+-----+---------+
|
* +---------------+--------------------+-----+---------+
|
||||||
|
@ -517,8 +531,10 @@ void *mifare_cryto_preprocess_data(desfiretag_t tag, void *data, size_t *nbytes,
|
||||||
* encypher()/decypher()
|
* encypher()/decypher()
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (!(communication_settings & ENC_COMMAND))
|
if (!(communication_settings & ENC_COMMAND)) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
edl = enciphered_data_length(tag, *nbytes - offset, communication_settings) + offset;
|
edl = enciphered_data_length(tag, *nbytes - offset, communication_settings) + offset;
|
||||||
|
|
||||||
// Fill in the crypto buffer with data ...
|
// 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)) {
|
if (!(communication_settings & NO_CRC)) {
|
||||||
// ... CRC ...
|
// ... CRC ...
|
||||||
switch (DESFIRE(tag)->authentication_scheme) {
|
switch (DESFIRE(tag)->authentication_scheme) {
|
||||||
case AS_LEGACY:
|
case AS_LEGACY: {
|
||||||
AddCrc14A(res + offset, *nbytes - offset);
|
AddCrc14A(res + offset, *nbytes - offset);
|
||||||
*nbytes += 2;
|
*nbytes += 2;
|
||||||
break;
|
break;
|
||||||
case AS_NEW:
|
}
|
||||||
|
case AS_NEW: {
|
||||||
crc32_append(res, *nbytes);
|
crc32_append(res, *nbytes);
|
||||||
*nbytes += 4;
|
*nbytes += 4;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ... and padding
|
// ... 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);
|
mifare_cypher_blocks_chained(tag, NULL, NULL, res + offset, *nbytes - offset, MCD_SEND, (AS_NEW == DESFIRE(tag)->authentication_scheme) ? MCO_ENCYPHER : MCO_DECYPHER);
|
||||||
break;
|
break;
|
||||||
default:
|
}
|
||||||
|
default: {
|
||||||
*nbytes = -1;
|
*nbytes = -1;
|
||||||
res = NULL;
|
res = NULL;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void *mifare_cryto_postprocess_data(desfiretag_t tag, void *data, size_t *nbytes, int communication_settings) {
|
void *mifare_cryto_postprocess_data(desfiretag_t tag, void *data, size_t *nbytes, int communication_settings) {
|
||||||
|
|
||||||
void *res = data;
|
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.
|
// Return directly if we just have a status code.
|
||||||
if (1 == *nbytes) {
|
if (1 == *nbytes) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
desfirekey_t key = DESFIRE(tag)->session_key;
|
||||||
|
if (!key) {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t first_cmac_byte = 0x00;
|
||||||
|
|
||||||
switch (communication_settings & MDCM_MASK) {
|
switch (communication_settings & MDCM_MASK) {
|
||||||
case MDCM_PLAIN: {
|
case MDCM_PLAIN: {
|
||||||
|
|
||||||
|
@ -659,11 +679,12 @@ void *mifare_cryto_postprocess_data(desfiretag_t tag, void *data, size_t *nbytes
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MDCM_ENCIPHERED: {
|
case MDCM_ENCIPHERED: {
|
||||||
|
|
||||||
(*nbytes)--;
|
(*nbytes)--;
|
||||||
|
|
||||||
bool verified = false;
|
bool verified = false;
|
||||||
int crc_pos = 0x00;
|
int crc_pos = 0x00;
|
||||||
int end_crc_pos = 0x00;
|
int end_crc_pos = 0x00;
|
||||||
uint8_t x;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* AS_LEGACY:
|
* AS_LEGACY:
|
||||||
|
@ -742,8 +763,9 @@ void *mifare_cryto_postprocess_data(desfiretag_t tag, void *data, size_t *nbytes
|
||||||
verified = true;
|
verified = true;
|
||||||
for (int n = end_crc_pos; n < *nbytes - 1; n++) {
|
for (int n = end_crc_pos; n < *nbytes - 1; n++) {
|
||||||
uint8_t byte = ((uint8_t *)res)[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;
|
verified = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -768,7 +790,7 @@ void *mifare_cryto_postprocess_data(desfiretag_t tag, void *data, size_t *nbytes
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case AS_NEW: {
|
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 - 1] = ((uint8_t *)res)[crc_pos];
|
||||||
((uint8_t *)res)[crc_pos] = x;
|
((uint8_t *)res)[crc_pos] = x;
|
||||||
break;
|
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) {
|
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];
|
uint8_t ovect[DESFIRE_MAX_CRYPTO_BLOCK_SIZE];
|
||||||
if (direction == MCD_SEND) {
|
if (direction == MCD_SEND) {
|
||||||
xor(ivect, data, block_size);
|
xor(data, ivect, block_size);
|
||||||
} else {
|
} else {
|
||||||
memcpy(ovect, data, block_size);
|
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};
|
uint8_t edata[DESFIRE_MAX_CRYPTO_BLOCK_SIZE] = {0};
|
||||||
|
|
||||||
switch (key->type) {
|
switch (key->type) {
|
||||||
case T_DES:
|
case T_DES: {
|
||||||
switch (operation) {
|
switch (operation) {
|
||||||
case MCO_ENCYPHER:
|
case MCO_ENCYPHER: {
|
||||||
//DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_ENCRYPT);
|
//DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_ENCRYPT);
|
||||||
des_encrypt(edata, data, key->data);
|
des_encrypt(edata, data, key->data);
|
||||||
break;
|
break;
|
||||||
case MCO_DECYPHER:
|
}
|
||||||
|
case MCO_DECYPHER: {
|
||||||
//DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_DECRYPT);
|
//DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_DECRYPT);
|
||||||
des_decrypt(edata, data, key->data);
|
des_decrypt(edata, data, key->data);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case T_3DES:
|
}
|
||||||
|
case T_3DES: {
|
||||||
switch (operation) {
|
switch (operation) {
|
||||||
case MCO_ENCYPHER:
|
case MCO_ENCYPHER: {
|
||||||
mbedtls_des3_set2key_enc(&ctx3, key->data);
|
mbedtls_des3_set2key_enc(&ctx3, key->data);
|
||||||
mbedtls_des3_crypt_ecb(&ctx3, data, edata);
|
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 *) 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 *) edata, (DES_cblock *) data, &(key->ks2), DES_DECRYPT);
|
||||||
// DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_ENCRYPT);
|
// DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_ENCRYPT);
|
||||||
break;
|
break;
|
||||||
case MCO_DECYPHER:
|
}
|
||||||
|
case MCO_DECYPHER: {
|
||||||
mbedtls_des3_set2key_dec(&ctx3, key->data);
|
mbedtls_des3_set2key_dec(&ctx3, key->data);
|
||||||
mbedtls_des3_crypt_ecb(&ctx3, data, edata);
|
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 *) 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 *) edata, (DES_cblock *) data, &(key->ks2), DES_ENCRYPT);
|
||||||
// DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_DECRYPT);
|
// DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_DECRYPT);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case T_3K3DES:
|
}
|
||||||
|
case T_3K3DES: {
|
||||||
switch (operation) {
|
switch (operation) {
|
||||||
case MCO_ENCYPHER:
|
case MCO_ENCYPHER: {
|
||||||
mbedtls_des3_set3key_enc(&ctx3, key->data);
|
mbedtls_des3_set3key_enc(&ctx3, key->data);
|
||||||
mbedtls_des3_crypt_ecb(&ctx3, data, edata);
|
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 *) 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 *) edata, (DES_cblock *) data, &(key->ks2), DES_DECRYPT);
|
||||||
// DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks3), DES_ENCRYPT);
|
// DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks3), DES_ENCRYPT);
|
||||||
break;
|
break;
|
||||||
case MCO_DECYPHER:
|
}
|
||||||
|
case MCO_DECYPHER: {
|
||||||
mbedtls_des3_set3key_dec(&ctx3, key->data);
|
mbedtls_des3_set3key_dec(&ctx3, key->data);
|
||||||
mbedtls_des3_crypt_ecb(&ctx3, data, edata);
|
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 *) 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 *) edata, (DES_cblock *) data, &(key->ks2), DES_ENCRYPT);
|
||||||
// DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_DECRYPT);
|
// DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_DECRYPT);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case T_AES:
|
}
|
||||||
|
case T_AES: {
|
||||||
switch (operation) {
|
switch (operation) {
|
||||||
case MCO_ENCYPHER: {
|
case MCO_ENCYPHER: {
|
||||||
mbedtls_aes_init(&actx);
|
mbedtls_aes_init(&actx);
|
||||||
mbedtls_aes_setkey_enc(&actx, key->data, 128);
|
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;
|
break;
|
||||||
}
|
}
|
||||||
case MCO_DECYPHER: {
|
case MCO_DECYPHER: {
|
||||||
mbedtls_aes_init(&actx);
|
mbedtls_aes_init(&actx);
|
||||||
mbedtls_aes_setkey_dec(&actx, key->data, 128);
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(data, edata, block_size);
|
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) {
|
if (direction == MCD_SEND) {
|
||||||
memcpy(ivect, data, block_size);
|
memcpy(ivect, data, block_size);
|
||||||
} else {
|
} else {
|
||||||
xor(ivect, data, block_size);
|
xor(data, ivect, block_size);
|
||||||
memcpy(ivect, ovect, block_size);
|
memcpy(ivect, ovect, block_size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -183,7 +183,7 @@ void tdes_nxp_send(const void *in, void *out, size_t length, const void *key, ui
|
||||||
void aes128_nxp_receive(const void *in, void *out, size_t length, const void *key, unsigned char iv[16]);
|
void aes128_nxp_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 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_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_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);
|
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_generate_subkeys(desfirekey_t key);
|
||||||
void cmac(const desfirekey_t key, uint8_t *ivect, const uint8_t *data, size_t len, uint8_t *cmac);
|
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
|
#endif
|
||||||
|
|
|
@ -125,7 +125,7 @@ void ExecuteEMVSim(uint8_t *receivedCmd, uint16_t receivedCmd_len, uint8_t *rece
|
||||||
Dbprintf("");
|
Dbprintf("");
|
||||||
|
|
||||||
// use annotate to give some hints about the command
|
// 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
|
// This is a common request from the reader which we can just immediately respond to since we know we can't
|
||||||
// handle it.
|
// handle it.
|
||||||
|
@ -141,7 +141,7 @@ void ExecuteEMVSim(uint8_t *receivedCmd, uint16_t receivedCmd_len, uint8_t *rece
|
||||||
|
|
||||||
currentState = GENERATE_AC;
|
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++) {
|
for (int i = 0; i < 29; i++) {
|
||||||
receivedCmd[6 + i] = receivedCmd[12 + 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,
|
0x20, 0x00, 0x9f, 0x26, 0x08, 0x56, 0xcb, 0x4e, 0xe1, 0xa4,
|
||||||
0xef, 0xac, 0x74, 0x9f, 0x27, 0x01, 0x80, 0x9f, 0x36, 0x02,
|
0xef, 0xac, 0x74, 0x9f, 0x27, 0x01, 0x80, 0x9f, 0x36, 0x02,
|
||||||
0x00, 0x07, 0x9f, 0x6c, 0x02, 0x3e, 0x00, 0x9f, 0x6e, 0x04,
|
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
|
// do the replacement
|
||||||
template[0] = responseToReader[0]; // class bit 0
|
template[0] = responseToReader[0]; // class bit 0
|
||||||
|
|
|
@ -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);
|
Dbhexdump(*rxlen, response_bit, false);
|
||||||
Dbprintf("htS: skipping %d bit SOF", sof_bits);
|
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");
|
DBG DbpString("htS: Warning, not all bits of SOF are 1");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1455,7 +1455,7 @@ bool SimulateIso14443aInit(uint8_t tagType, uint16_t flags, uint8_t *data,
|
||||||
// response to send, and send it.
|
// response to send, and send it.
|
||||||
// 'hf 14a sim'
|
// '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) {
|
uint8_t *ats, size_t ats_len) {
|
||||||
|
|
||||||
#define ATTACK_KEY_COUNT 16
|
#define ATTACK_KEY_COUNT 16
|
||||||
|
@ -1508,7 +1508,7 @@ void SimulateIso14443aTag(uint8_t tagType, uint16_t flags, uint8_t *data, uint8_
|
||||||
.modulation_n = 0
|
.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();
|
BigBuf_free_keep_EM();
|
||||||
reply_ng(CMD_HF_MIFARE_SIMULATE, PM3_EINIT, NULL, 0);
|
reply_ng(CMD_HF_MIFARE_SIMULATE, PM3_EINIT, NULL, 0);
|
||||||
return;
|
return;
|
||||||
|
@ -1684,8 +1684,8 @@ void SimulateIso14443aTag(uint8_t tagType, uint16_t flags, uint8_t *data, uint8_
|
||||||
// first blocks of emu are header
|
// first blocks of emu are header
|
||||||
uint16_t start = block * 4 + MFU_DUMP_PREFIX_LENGTH;
|
uint16_t start = block * 4 + MFU_DUMP_PREFIX_LENGTH;
|
||||||
uint8_t emdata[MAX_MIFARE_FRAME_SIZE];
|
uint8_t emdata[MAX_MIFARE_FRAME_SIZE];
|
||||||
emlGet(emdata, start, 16);
|
emlGet(emdata, start, MIFARE_BLOCK_SIZE);
|
||||||
AddCrc14A(emdata, 16);
|
AddCrc14A(emdata, MIFARE_BLOCK_SIZE);
|
||||||
EmSendCmd(emdata, sizeof(emdata));
|
EmSendCmd(emdata, sizeof(emdata));
|
||||||
numReads++; // Increment number of times reader requested a block
|
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];
|
p_response = &responses[RESP_INDEX_UIDC1];
|
||||||
} else { // all other tags (16 byte block tags)
|
} else { // all other tags (16 byte block tags)
|
||||||
uint8_t emdata[MAX_MIFARE_FRAME_SIZE] = {0};
|
uint8_t emdata[MAX_MIFARE_FRAME_SIZE] = {0};
|
||||||
emlGet(emdata, block, 16);
|
emlGet(emdata, block, MIFARE_BLOCK_SIZE);
|
||||||
AddCrc14A(emdata, 16);
|
AddCrc14A(emdata, MIFARE_BLOCK_SIZE);
|
||||||
EmSendCmd(emdata, sizeof(emdata));
|
EmSendCmd(emdata, sizeof(emdata));
|
||||||
// We already responded, do not send anything with the EmSendCmd14443aRaw() that is called below
|
// We already responded, do not send anything with the EmSendCmd14443aRaw() that is called below
|
||||||
p_response = NULL;
|
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) {
|
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]);
|
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[0] = receivedCmd[0];
|
||||||
dynamic_response_info.response[1] = 0x00;
|
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
|
// receivedCmd in this case is expecting to structured with possibly a CID, then the APDU command for SelectFile
|
||||||
// | IBlock (CID) | CID | APDU Command | CRC |
|
// | IBlock (CID) | CID | APDU Command | CRC |
|
||||||
// or | IBlock (noCID) | 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
|
// 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)
|
// aid len is found as a hex value in receivedCmd[6] (Index Starts at 0)
|
||||||
int received_aid_len = receivedCmd[5+offset];
|
int received_aid_len = receivedCmd[5 + offset];
|
||||||
uint8_t *received_aid = &receivedCmd[6+offset];
|
uint8_t *received_aid = &receivedCmd[6 + offset];
|
||||||
|
|
||||||
// aid enumeration flag
|
// aid enumeration flag
|
||||||
if ((flags & FLAG_ENUMERATE_AID) == FLAG_ENUMERATE_AID) {
|
if ((flags & FLAG_ENUMERATE_AID) == FLAG_ENUMERATE_AID) {
|
||||||
|
|
|
@ -142,7 +142,7 @@ RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time);
|
||||||
RAMFUNC int ManchesterDecoding(uint8_t bit, uint16_t offset, uint32_t non_real_time);
|
RAMFUNC int ManchesterDecoding(uint8_t bit, uint16_t offset, uint32_t non_real_time);
|
||||||
|
|
||||||
void RAMFUNC SniffIso14443a(uint8_t param);
|
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);
|
uint8_t *iRATs, size_t irats_len);
|
||||||
|
|
||||||
void SimulateIso14443aTagAID(uint8_t tagType, uint16_t flags, uint8_t *uid,
|
void SimulateIso14443aTagAID(uint8_t tagType, uint16_t flags, uint8_t *uid,
|
||||||
|
|
|
@ -2117,14 +2117,6 @@ void Iso15693InitTag(void) {
|
||||||
StartCountSspClk();
|
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
|
// Simulate an ISO15693 TAG, perform anti-collision and then print any reader commands
|
||||||
// all demodulation performed in arm rather than host. - greg
|
// all demodulation performed in arm rather than host. - greg
|
||||||
void SimTagIso15693(const uint8_t *uid, uint8_t block_size) {
|
void SimTagIso15693(const uint8_t *uid, uint8_t block_size) {
|
||||||
|
|
|
@ -46,7 +46,6 @@ int GetIso15693AnswerFromTag(uint8_t *response, uint16_t max_len, uint16_t timeo
|
||||||
//void RecordRawAdcSamplesIso15693(void);
|
//void RecordRawAdcSamplesIso15693(void);
|
||||||
void AcquireRawAdcSamplesIso15693(void);
|
void AcquireRawAdcSamplesIso15693(void);
|
||||||
void ReaderIso15693(iso15_card_select_t *p_card); // ISO15693 reader
|
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 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 BruteforceIso15693Afi(uint32_t flags); // find an AFI of a tag
|
||||||
void SendRawCommand15693(iso15_raw_cmd_t *packet); // send arbitrary commands from CLI
|
void SendRawCommand15693(iso15_raw_cmd_t *packet); // send arbitrary commands from CLI
|
||||||
|
|
|
@ -944,7 +944,7 @@ static void fcAll(uint8_t fc, int *n, uint8_t clock, int16_t *remainder) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool add_HID_preamble(uint32_t *hi2, uint32_t *hi, uint32_t *lo, uint8_t length){
|
bool add_HID_preamble(uint32_t *hi2, uint32_t *hi, uint32_t *lo, uint8_t length) {
|
||||||
// Invalid value
|
// Invalid value
|
||||||
if (length > 84 || length == 0)
|
if (length > 84 || length == 0)
|
||||||
return false;
|
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
|
// No header bits added to 37-bit cards
|
||||||
} else if (length >= 32) {
|
} else if (length >= 32) {
|
||||||
*hi |= 0x20; // Bit 37; standard header
|
*hi |= 0x20; // Bit 37; standard header
|
||||||
*hi |= 1U << (length - 32); // leading 1: start bit
|
*hi |= 1U << (length - 32); // leading 1: start bit
|
||||||
} else {
|
} else {
|
||||||
*hi |= 0x20; // Bit 37; standard header
|
*hi |= 0x20; // Bit 37; standard header
|
||||||
*lo |= 1U << length; // leading 1: start bit
|
*lo |= 1U << length; // leading 1: start bit
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
void ModThenAcquireRawAdcSamples125k(uint32_t delay_off, uint16_t period_0, uint16_t period_1,
|
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,
|
const uint8_t *symbol_extra, uint16_t *period_extra, uint8_t *command, bool verbose,
|
||||||
bool keep_field_on, uint32_t samples, bool ledcontrol);
|
bool keep_field_on, uint32_t samples, bool ledcontrol);
|
||||||
|
|
||||||
void ReadTItag(bool ledcontrol);
|
void ReadTItag(bool ledcontrol);
|
||||||
void WriteTItag(uint32_t idhi, uint32_t idlo, uint16_t crc, bool ledcontrol);
|
void WriteTItag(uint32_t idhi, uint32_t idlo, uint16_t crc, bool ledcontrol);
|
||||||
|
|
||||||
|
|
|
@ -2223,7 +2223,7 @@ OUT:
|
||||||
blockno = (32 * 4 + (i - 32) * 16) ^ 0xF;
|
blockno = (32 * 4 + (i - 32) * 16) ^ 0xF;
|
||||||
}
|
}
|
||||||
// get ST
|
// get ST
|
||||||
emlGetMem(block, blockno, 1);
|
emlGetMem_xt(block, blockno, 1, MIFARE_BLOCK_SIZE);
|
||||||
|
|
||||||
memcpy(block, k_sector[i].keyA, 6);
|
memcpy(block, k_sector[i].keyA, 6);
|
||||||
memcpy(block + 10, k_sector[i].keyB, 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
|
// 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) {
|
int MifareECardLoad(uint8_t sectorcnt, uint8_t keytype, uint8_t *key) {
|
||||||
|
|
||||||
if ((keytype > MF_KEY_B) && (key == NULL)) {
|
if ((keytype > MF_KEY_B) && (key == NULL)) {
|
||||||
|
|
||||||
if (g_dbglevel >= DBG_ERROR) {
|
if (g_dbglevel >= DBG_ERROR) {
|
||||||
Dbprintf("Error, missing key");
|
Dbprintf("Error, missing key");
|
||||||
}
|
}
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
LED_A_ON();
|
LED_A_ON();
|
||||||
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
|
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
|
// MFC 1K EV1, skip sector 16 since its lockdown
|
||||||
if (s == 16) {
|
if (s == 16) {
|
||||||
// unknown sector trailer, keep the keys, set only the AC
|
// unknown sector trailer, keep the keys, set only the AC
|
||||||
uint8_t st[16] = {0x00};
|
uint8_t st[MIFARE_BLOCK_SIZE] = {0x00};
|
||||||
emlGetMem(st, FirstBlockOfSector(s) + 3, 1);
|
emlGetMem_xt(st, FirstBlockOfSector(s) + 3, 1, MIFARE_BLOCK_SIZE);
|
||||||
memcpy(st + 6, "\x70\xF0\xF8\x69", 4);
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2556,7 +2526,8 @@ int MifareECardLoad(uint8_t sectorcnt, uint8_t keytype, uint8_t *key) {
|
||||||
}
|
}
|
||||||
have_uid = true;
|
have_uid = true;
|
||||||
} else { // no need for anticollision. We can directly select the card
|
} 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) {
|
if (iso14443a_fast_select_card(uid, cascade_levels) == 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -2565,7 +2536,7 @@ int MifareECardLoad(uint8_t sectorcnt, uint8_t keytype, uint8_t *key) {
|
||||||
|
|
||||||
// Auth
|
// Auth
|
||||||
if (keytype > MF_KEY_B) {
|
if (keytype > MF_KEY_B) {
|
||||||
if (! bd_authenticated) {
|
if (bd_authenticated == false) {
|
||||||
ui64Key = bytes_to_num(key, 6);
|
ui64Key = bytes_to_num(key, 6);
|
||||||
if (mifare_classic_auth(pcs, cuid, 0, keytype, ui64Key, AUTH_FIRST)) {
|
if (mifare_classic_auth(pcs, cuid, 0, keytype, ui64Key, AUTH_FIRST)) {
|
||||||
retval = PM3_EFAILED;
|
retval = PM3_EFAILED;
|
||||||
|
@ -2592,7 +2563,7 @@ int MifareECardLoad(uint8_t sectorcnt, uint8_t keytype, uint8_t *key) {
|
||||||
|
|
||||||
#define MAX_RETRIES 2
|
#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++) {
|
for (uint8_t b = 0; b < NumBlocksPerSector(s); b++) {
|
||||||
|
|
||||||
memset(data, 0x00, sizeof(data));
|
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
|
// 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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsSectorTrailer(b)) {
|
if (IsSectorTrailer(b)) {
|
||||||
// sector trailer, keep the keys, set only the AC
|
// sector trailer, keep the keys, set only the AC
|
||||||
uint8_t st[16] = {0x00};
|
uint8_t st[MIFARE_BLOCK_SIZE] = {0x00};
|
||||||
emlGetMem(st, tb, 1);
|
emlGetMem_xt(st, tb, 1, MIFARE_BLOCK_SIZE);
|
||||||
memcpy(st + 6, data + 6, 4);
|
memcpy(st + 6, data + 6, 4);
|
||||||
emlSetMem_xt(st, tb, 1, 16);
|
emlSetMem_xt(st, tb, 1, MIFARE_BLOCK_SIZE);
|
||||||
} else {
|
} else {
|
||||||
emlSetMem_xt(data, tb, 1, 16);
|
emlSetMem_xt(data, tb, 1, MIFARE_BLOCK_SIZE);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -2927,7 +2898,6 @@ void MifareCIdent(bool is_mfc, uint8_t keytype, uint8_t *key) {
|
||||||
// variables
|
// variables
|
||||||
uint8_t rec[1] = {0x00};
|
uint8_t rec[1] = {0x00};
|
||||||
uint8_t recpar[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 rdblf0[4] = {ISO14443A_CMD_READBLOCK, 0xF0, 0x8D, 0x5f};
|
||||||
uint8_t rdbl00[4] = {ISO14443A_CMD_READBLOCK, 0x00, 0x02, 0xa8};
|
uint8_t rdbl00[4] = {ISO14443A_CMD_READBLOCK, 0x00, 0x02, 0xa8};
|
||||||
uint8_t gen4gdmAuth[4] = {MIFARE_MAGIC_GDM_AUTH_KEY, 0x00, 0x6C, 0x92};
|
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 *par = BigBuf_calloc(MAX_PARITY_SIZE);
|
||||||
uint8_t *buf = BigBuf_calloc(PM3_CMD_DATA_SIZE);
|
uint8_t *buf = BigBuf_calloc(PM3_CMD_DATA_SIZE);
|
||||||
uint8_t *uid = BigBuf_calloc(10);
|
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;
|
uint16_t flag = MAGIC_FLAG_NONE;
|
||||||
uint32_t cuid = 0;
|
uint32_t cuid = 0;
|
||||||
int res = 0;
|
int res = 0;
|
||||||
|
@ -2991,144 +2963,141 @@ void MifareCIdent(bool is_mfc, uint8_t keytype, uint8_t *key) {
|
||||||
// reset card
|
// reset card
|
||||||
mf_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 (res) {
|
||||||
if (cuid == 0xAA55C396) {
|
if (cuid == 0xAA55C396) {
|
||||||
flag |= MAGIC_FLAG_GEN_UNFUSED;
|
flag |= MAGIC_FLAG_GEN_UNFUSED;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReaderTransmit(rats, sizeof(rats), NULL);
|
if (memcmp(card->ats, "\x09\x78\x00\x91\x02\xDA\xBC\x19\x10", 9) == 0) {
|
||||||
res = ReaderReceive(buf, PM3_CMD_DATA_SIZE, par);
|
// 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) {
|
// test for super card
|
||||||
if (memcmp(buf, "\x09\x78\x00\x91\x02\xDA\xBC\x19\x10", 9) == 0) {
|
ReaderTransmit(superGen1, sizeof(superGen1), NULL);
|
||||||
// test for some MFC gen2
|
res = ReaderReceive(buf, PM3_CMD_DATA_SIZE, par);
|
||||||
isGen2 = true;
|
if (res == 22) {
|
||||||
flag |= MAGIC_FLAG_GEN_2;
|
uint8_t isGen = MAGIC_FLAG_SUPER_GEN1;
|
||||||
} 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
|
// check for super card gen2
|
||||||
isGen2 = true;
|
// not available after RATS, reset card before executing
|
||||||
flag |= MAGIC_FLAG_GEN_2;
|
mf_reset_card();
|
||||||
} else if (memcmp(buf, "\x0A\x78\x00\x81\x02\xDB\xA0\xC1\x19\x40\x2A\xB5", 12) == 0) {
|
|
||||||
// test for Ultralight magic gen2
|
iso14443a_select_card(uid, NULL, &cuid, true, 0, true);
|
||||||
isGen2 = true;
|
ReaderTransmit(rdbl00, sizeof(rdbl00), NULL);
|
||||||
flag |= MAGIC_FLAG_GEN_2;
|
res = ReaderReceive(buf, PM3_CMD_DATA_SIZE, par);
|
||||||
} else if (memcmp(buf, "\x85\x00\x00\xA0\x00\x00\x0A\xC3\x00\x04\x03\x01\x01\x00\x0B\x03\x41\xDF", 18) == 0) {
|
if (res == 18) {
|
||||||
// test for Ultralight EV1 magic gen2
|
isGen = MAGIC_FLAG_SUPER_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
|
flag |= isGen;
|
||||||
ReaderTransmit(superGen1, sizeof(superGen1), NULL);
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
res = ReaderReceive(buf, PM3_CMD_DATA_SIZE, par);
|
||||||
if (res == 22) {
|
if (res == 18) {
|
||||||
uint8_t isGen = MAGIC_FLAG_SUPER_GEN1;
|
flag |= MAGIC_FLAG_NTAG21X;
|
||||||
|
|
||||||
// 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 (is_mfc == false) {
|
} else {
|
||||||
// magic ntag test
|
|
||||||
|
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();
|
mf_reset_card();
|
||||||
|
|
||||||
res = iso14443a_select_card(uid, NULL, &cuid, true, 0, true);
|
res = iso14443a_select_card(uid, NULL, &cuid, true, 0, true);
|
||||||
if (res == 2) {
|
if (res) {
|
||||||
ReaderTransmit(rdblf0, sizeof(rdblf0), NULL);
|
|
||||||
res = ReaderReceive(buf, PM3_CMD_DATA_SIZE, par);
|
|
||||||
if (res == 18) {
|
|
||||||
flag |= MAGIC_FLAG_NTAG21X;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
|
|
||||||
struct Crypto1State mpcs = {0, 0};
|
uint64_t tmpkey = bytes_to_num(key, 6);
|
||||||
struct Crypto1State *pcs;
|
if (mifare_classic_authex(pcs, cuid, 0, keytype, tmpkey, AUTH_FIRST, NULL, NULL) == 0) {
|
||||||
pcs = &mpcs;
|
|
||||||
|
|
||||||
// CUID (with default sector 0 B key) test
|
if ((mifare_sendcmd_short(pcs, 1, ISO14443A_CMD_WRITEBLOCK, 0, buf, PM3_CMD_DATA_SIZE, par, NULL) == 1) && (buf[0] == 0x0A)) {
|
||||||
// regular cards will NAK the WRITEBLOCK(0) command, while DirectWrite will ACK it
|
flag |= MAGIC_FLAG_GEN_2;
|
||||||
// if we do get an ACK, we immediately abort to ensure nothing is ever actually written
|
// turn off immediately to ensure nothing ever accidentally writes to the block
|
||||||
// only perform test if we haven't already identified Gen2. No need test if we have a positive identification already
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
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);
|
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)
|
// GDM alt magic wakeup (20)
|
||||||
ReaderTransmitBitsPar(wupGDM1, 7, NULL, NULL);
|
ReaderTransmitBitsPar(wupGDM1, 7, NULL, NULL);
|
||||||
|
|
|
@ -43,8 +43,6 @@ void MifareChkKeys(uint8_t *datain, uint8_t reserved_mem);
|
||||||
void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
|
void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
|
||||||
void MifareChkKeys_file(uint8_t *fn);
|
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 MifareECardLoad(uint8_t sectorcnt, uint8_t keytype, uint8_t *key);
|
||||||
int MifareECardLoadExt(uint8_t sectorcnt, uint8_t keytype, uint8_t *key);
|
int MifareECardLoadExt(uint8_t sectorcnt, uint8_t keytype, uint8_t *key);
|
||||||
|
|
||||||
|
|
|
@ -48,8 +48,8 @@
|
||||||
#include "parity.h"
|
#include "parity.h"
|
||||||
|
|
||||||
static bool IsKeyBReadable(uint8_t blockNo) {
|
static bool IsKeyBReadable(uint8_t blockNo) {
|
||||||
uint8_t sector_trailer[16];
|
uint8_t sector_trailer[MIFARE_BLOCK_SIZE] = {0};
|
||||||
emlGetMem(sector_trailer, SectorTrailer(blockNo), 1);
|
emlGetMem_xt(sector_trailer, SectorTrailer(blockNo), 1, MIFARE_BLOCK_SIZE);
|
||||||
uint8_t AC = ((sector_trailer[7] >> 5) & 0x04)
|
uint8_t AC = ((sector_trailer[7] >> 5) & 0x04)
|
||||||
| ((sector_trailer[8] >> 2) & 0x02)
|
| ((sector_trailer[8] >> 2) & 0x02)
|
||||||
| ((sector_trailer[8] >> 7) & 0x01);
|
| ((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) {
|
static bool IsTrailerAccessAllowed(uint8_t blockNo, uint8_t keytype, uint8_t action) {
|
||||||
uint8_t sector_trailer[16];
|
uint8_t sector_trailer[MIFARE_BLOCK_SIZE] = {0};
|
||||||
emlGetMem(sector_trailer, blockNo, 1);
|
emlGetMem_xt(sector_trailer, blockNo, 1, MIFARE_BLOCK_SIZE);
|
||||||
|
|
||||||
uint8_t AC = ((sector_trailer[7] >> 5) & 0x04)
|
uint8_t AC = ((sector_trailer[7] >> 5) & 0x04)
|
||||||
| ((sector_trailer[8] >> 2) & 0x02)
|
| ((sector_trailer[8] >> 2) & 0x02)
|
||||||
| ((sector_trailer[8] >> 7) & 0x01);
|
| ((sector_trailer[8] >> 7) & 0x01);
|
||||||
|
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case AC_KEYA_READ: {
|
case AC_KEYA_READ: {
|
||||||
if (g_dbglevel >= DBG_EXTENDED)
|
if (g_dbglevel >= DBG_EXTENDED) {
|
||||||
Dbprintf("IsTrailerAccessAllowed: AC_KEYA_READ");
|
Dbprintf("IsTrailerAccessAllowed: AC_KEYA_READ");
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
case AC_KEYA_WRITE: {
|
case AC_KEYA_WRITE: {
|
||||||
if (g_dbglevel >= DBG_EXTENDED)
|
if (g_dbglevel >= DBG_EXTENDED) {
|
||||||
Dbprintf("IsTrailerAccessAllowed: AC_KEYA_WRITE");
|
Dbprintf("IsTrailerAccessAllowed: AC_KEYA_WRITE");
|
||||||
|
}
|
||||||
return ((keytype == AUTHKEYA && (AC == 0x00 || AC == 0x01))
|
return ((keytype == AUTHKEYA && (AC == 0x00 || AC == 0x01))
|
||||||
|| (keytype == AUTHKEYB && (AC == 0x04 || AC == 0x03)));
|
|| (keytype == AUTHKEYB && (AC == 0x04 || AC == 0x03)));
|
||||||
}
|
}
|
||||||
case AC_KEYB_READ: {
|
case AC_KEYB_READ: {
|
||||||
if (g_dbglevel >= DBG_EXTENDED)
|
if (g_dbglevel >= DBG_EXTENDED) {
|
||||||
Dbprintf("IsTrailerAccessAllowed: AC_KEYB_READ");
|
Dbprintf("IsTrailerAccessAllowed: AC_KEYB_READ");
|
||||||
|
}
|
||||||
return (keytype == AUTHKEYA && (AC == 0x00 || AC == 0x02 || AC == 0x01));
|
return (keytype == AUTHKEYA && (AC == 0x00 || AC == 0x02 || AC == 0x01));
|
||||||
}
|
}
|
||||||
case AC_KEYB_WRITE: {
|
case AC_KEYB_WRITE: {
|
||||||
if (g_dbglevel >= DBG_EXTENDED)
|
if (g_dbglevel >= DBG_EXTENDED) {
|
||||||
Dbprintf("IsTrailerAccessAllowed: AC_KEYB_WRITE");
|
Dbprintf("IsTrailerAccessAllowed: AC_KEYB_WRITE");
|
||||||
|
}
|
||||||
return ((keytype == AUTHKEYA && (AC == 0x00 || AC == 0x01))
|
return ((keytype == AUTHKEYA && (AC == 0x00 || AC == 0x01))
|
||||||
|| (keytype == AUTHKEYB && (AC == 0x04 || AC == 0x03)));
|
|| (keytype == AUTHKEYB && (AC == 0x04 || AC == 0x03)));
|
||||||
}
|
}
|
||||||
case AC_AC_READ: {
|
case AC_AC_READ: {
|
||||||
if (g_dbglevel >= DBG_EXTENDED)
|
if (g_dbglevel >= DBG_EXTENDED) {
|
||||||
Dbprintf("IsTrailerAccessAllowed: AC_AC_READ");
|
Dbprintf("IsTrailerAccessAllowed: AC_AC_READ");
|
||||||
|
}
|
||||||
return ((keytype == AUTHKEYA)
|
return ((keytype == AUTHKEYA)
|
||||||
|| (keytype == AUTHKEYB && !(AC == 0x00 || AC == 0x02 || AC == 0x01)));
|
|| (keytype == AUTHKEYB && !(AC == 0x00 || AC == 0x02 || AC == 0x01)));
|
||||||
}
|
}
|
||||||
case AC_AC_WRITE: {
|
case AC_AC_WRITE: {
|
||||||
if (g_dbglevel >= DBG_EXTENDED)
|
if (g_dbglevel >= DBG_EXTENDED) {
|
||||||
Dbprintf("IsTrailerAccessAllowed: AC_AC_WRITE");
|
Dbprintf("IsTrailerAccessAllowed: AC_AC_WRITE");
|
||||||
|
}
|
||||||
return ((keytype == AUTHKEYA && (AC == 0x01))
|
return ((keytype == AUTHKEYA && (AC == 0x01))
|
||||||
|| (keytype == AUTHKEYB && (AC == 0x03 || AC == 0x05)));
|
|| (keytype == AUTHKEYB && (AC == 0x03 || AC == 0x05)));
|
||||||
}
|
}
|
||||||
default:
|
default: {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool IsDataAccessAllowed(uint8_t blockNo, uint8_t keytype, uint8_t action) {
|
static bool IsDataAccessAllowed(uint8_t blockNo, uint8_t keytype, uint8_t action) {
|
||||||
|
|
||||||
uint8_t sector_trailer[16];
|
uint8_t sector_trailer[MIFARE_BLOCK_SIZE] = {0};
|
||||||
emlGetMem(sector_trailer, SectorTrailer(blockNo), 1);
|
emlGetMem_xt(sector_trailer, SectorTrailer(blockNo), 1, MIFARE_BLOCK_SIZE);
|
||||||
|
|
||||||
uint8_t sector_block;
|
uint8_t sector_block;
|
||||||
if (blockNo <= MIFARE_2K_MAXBLOCK) {
|
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)
|
AC = ((sector_trailer[7] >> 2) & 0x04)
|
||||||
| ((sector_trailer[8] << 1) & 0x02)
|
| ((sector_trailer[8] << 1) & 0x02)
|
||||||
| ((sector_trailer[8] >> 4) & 0x01);
|
| ((sector_trailer[8] >> 4) & 0x01);
|
||||||
if (g_dbglevel >= DBG_EXTENDED)
|
if (g_dbglevel >= DBG_EXTENDED) {
|
||||||
Dbprintf("IsDataAccessAllowed: case 0x00 - %02x", AC);
|
Dbprintf("IsDataAccessAllowed: case 0x00 - %02x", AC);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 0x01: {
|
case 0x01: {
|
||||||
AC = ((sector_trailer[7] >> 3) & 0x04)
|
AC = ((sector_trailer[7] >> 3) & 0x04)
|
||||||
| ((sector_trailer[8] >> 0) & 0x02)
|
| ((sector_trailer[8] >> 0) & 0x02)
|
||||||
| ((sector_trailer[8] >> 5) & 0x01);
|
| ((sector_trailer[8] >> 5) & 0x01);
|
||||||
if (g_dbglevel >= DBG_EXTENDED)
|
if (g_dbglevel >= DBG_EXTENDED) {
|
||||||
Dbprintf("IsDataAccessAllowed: case 0x01 - %02x", AC);
|
Dbprintf("IsDataAccessAllowed: case 0x01 - %02x", AC);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 0x02: {
|
case 0x02: {
|
||||||
AC = ((sector_trailer[7] >> 4) & 0x04)
|
AC = ((sector_trailer[7] >> 4) & 0x04)
|
||||||
| ((sector_trailer[8] >> 1) & 0x02)
|
| ((sector_trailer[8] >> 1) & 0x02)
|
||||||
| ((sector_trailer[8] >> 6) & 0x01);
|
| ((sector_trailer[8] >> 6) & 0x01);
|
||||||
if (g_dbglevel >= DBG_EXTENDED)
|
if (g_dbglevel >= DBG_EXTENDED) {
|
||||||
Dbprintf("IsDataAccessAllowed: case 0x02 - %02x", AC);
|
Dbprintf("IsDataAccessAllowed: case 0x02 - %02x", AC);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
if (g_dbglevel >= DBG_EXTENDED)
|
if (g_dbglevel >= DBG_EXTENDED) {
|
||||||
Dbprintf("IsDataAccessAllowed: Error");
|
Dbprintf("IsDataAccessAllowed: Error");
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case AC_DATA_READ: {
|
case AC_DATA_READ: {
|
||||||
if (g_dbglevel >= DBG_EXTENDED)
|
if (g_dbglevel >= DBG_EXTENDED) {
|
||||||
Dbprintf("IsDataAccessAllowed - AC_DATA_READ: OK");
|
Dbprintf("IsDataAccessAllowed - AC_DATA_READ: OK");
|
||||||
|
}
|
||||||
return ((keytype == AUTHKEYA && !(AC == 0x03 || AC == 0x05 || AC == 0x07))
|
return ((keytype == AUTHKEYA && !(AC == 0x03 || AC == 0x05 || AC == 0x07))
|
||||||
|| (keytype == AUTHKEYB && !(AC == 0x07)));
|
|| (keytype == AUTHKEYB && !(AC == 0x07)));
|
||||||
}
|
}
|
||||||
case AC_DATA_WRITE: {
|
case AC_DATA_WRITE: {
|
||||||
if (g_dbglevel >= DBG_EXTENDED)
|
if (g_dbglevel >= DBG_EXTENDED) {
|
||||||
Dbprintf("IsDataAccessAllowed - AC_DATA_WRITE: OK");
|
Dbprintf("IsDataAccessAllowed - AC_DATA_WRITE: OK");
|
||||||
|
}
|
||||||
return ((keytype == AUTHKEYA && (AC == 0x00))
|
return ((keytype == AUTHKEYA && (AC == 0x00))
|
||||||
|| (keytype == AUTHKEYB && (AC == 0x00 || AC == 0x04 || AC == 0x06 || AC == 0x03)));
|
|| (keytype == AUTHKEYB && (AC == 0x00 || AC == 0x04 || AC == 0x06 || AC == 0x03)));
|
||||||
}
|
}
|
||||||
case AC_DATA_INC: {
|
case AC_DATA_INC: {
|
||||||
if (g_dbglevel >= DBG_EXTENDED)
|
if (g_dbglevel >= DBG_EXTENDED) {
|
||||||
Dbprintf("IsDataAccessAllowed - AC_DATA_INC: OK");
|
Dbprintf("IsDataAccessAllowed - AC_DATA_INC: OK");
|
||||||
|
}
|
||||||
return ((keytype == AUTHKEYA && (AC == 0x00))
|
return ((keytype == AUTHKEYA && (AC == 0x00))
|
||||||
|| (keytype == AUTHKEYB && (AC == 0x00 || AC == 0x06)));
|
|| (keytype == AUTHKEYB && (AC == 0x00 || AC == 0x06)));
|
||||||
}
|
}
|
||||||
case AC_DATA_DEC_TRANS_REST: {
|
case AC_DATA_DEC_TRANS_REST: {
|
||||||
if (g_dbglevel >= DBG_EXTENDED)
|
if (g_dbglevel >= DBG_EXTENDED) {
|
||||||
Dbprintf("AC_DATA_DEC_TRANS_REST: OK");
|
Dbprintf("AC_DATA_DEC_TRANS_REST: OK");
|
||||||
|
}
|
||||||
return ((keytype == AUTHKEYA && (AC == 0x00 || AC == 0x06 || AC == 0x01))
|
return ((keytype == AUTHKEYA && (AC == 0x00 || AC == 0x06 || AC == 0x01))
|
||||||
|| (keytype == AUTHKEYB && (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
|
// Length: 4,7,or 10 bytes
|
||||||
|
|
||||||
if (IS_FLAG_UID_IN_EMUL(flags)) {
|
if (IS_FLAG_UID_IN_EMUL(flags)) {
|
||||||
|
|
||||||
if (uid == NULL) {
|
if (uid == NULL) {
|
||||||
uid = uid_tmp;
|
uid = uid_tmp;
|
||||||
}
|
}
|
||||||
// Get UID, SAK, ATQA from EMUL
|
// Get UID, SAK, ATQA from EMUL
|
||||||
uint8_t block0[16];
|
uint8_t block0[MIFARE_BLOCK_SIZE];
|
||||||
emlGet(block0, 0, 16);
|
emlGet(block0, 0, MIFARE_BLOCK_SIZE);
|
||||||
|
|
||||||
// Check for 4 bytes uid: bcc corrected and single size uid bits in ATQA
|
// 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) {
|
if ((block0[0] ^ block0[1] ^ block0[2] ^ block0[3]) == block0[4] && (block0[6] & 0xc0) == 0) {
|
||||||
FLAG_SET_UID_IN_DATA(flags, 4);
|
FLAG_SET_UID_IN_DATA(flags, 4);
|
||||||
memcpy(uid, block0, 4);
|
memcpy(uid, block0, 4);
|
||||||
rSAK[0] = block0[5];
|
rSAK[0] = block0[5];
|
||||||
memcpy(rATQA, &block0[6], sizeof(rATQA));
|
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);
|
FLAG_SET_UID_IN_DATA(flags, 7);
|
||||||
memcpy(uid, block0, 7);
|
memcpy(uid, block0, 7);
|
||||||
rSAK[0] = block0[7];
|
rSAK[0] = block0[7];
|
||||||
memcpy(rATQA, &block0[8], sizeof(rATQA));
|
memcpy(rATQA, &block0[8], sizeof(rATQA));
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
Dbprintf("ERROR: " _RED_("Invalid dump. UID/SAK/ATQA not found"));
|
Dbprintf("ERROR: " _RED_("Invalid dump. UID/SAK/ATQA not found"));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (uid == NULL) {
|
if (uid == NULL) {
|
||||||
Dbprintf("ERROR: " _RED_("Missing UID"));
|
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));
|
memcpy(rATQA, rATQA_Mini, sizeof(rATQA));
|
||||||
rSAK[0] = rSAK_Mini;
|
rSAK[0] = rSAK_Mini;
|
||||||
if (g_dbglevel > DBG_NONE) Dbprintf("Enforcing Mifare Mini ATQA/SAK");
|
if (g_dbglevel > DBG_NONE) Dbprintf("Enforcing Mifare Mini ATQA/SAK");
|
||||||
|
|
||||||
} else if (IS_FLAG_MF_SIZE(flags, MIFARE_1K_MAX_BYTES)) {
|
} else if (IS_FLAG_MF_SIZE(flags, MIFARE_1K_MAX_BYTES)) {
|
||||||
memcpy(rATQA, rATQA_1k, sizeof(rATQA));
|
memcpy(rATQA, rATQA_1k, sizeof(rATQA));
|
||||||
rSAK[0] = rSAK_1k;
|
rSAK[0] = rSAK_1k;
|
||||||
if (g_dbglevel > DBG_NONE) Dbprintf("Enforcing Mifare 1K ATQA/SAK");
|
if (g_dbglevel > DBG_NONE) Dbprintf("Enforcing Mifare 1K ATQA/SAK");
|
||||||
|
|
||||||
} else if (IS_FLAG_MF_SIZE(flags, MIFARE_2K_MAX_BYTES)) {
|
} else if (IS_FLAG_MF_SIZE(flags, MIFARE_2K_MAX_BYTES)) {
|
||||||
memcpy(rATQA, rATQA_2k, sizeof(rATQA));
|
memcpy(rATQA, rATQA_2k, sizeof(rATQA));
|
||||||
rSAK[0] = rSAK_2k;
|
rSAK[0] = rSAK_2k;
|
||||||
*rats = rRATS;
|
*rats = rRATS;
|
||||||
*rats_len = sizeof(rRATS);
|
*rats_len = sizeof(rRATS);
|
||||||
if (g_dbglevel > DBG_NONE) Dbprintf("Enforcing Mifare 2K ATQA/SAK with RATS support");
|
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)) {
|
} else if (IS_FLAG_MF_SIZE(flags, MIFARE_4K_MAX_BYTES)) {
|
||||||
memcpy(rATQA, rATQA_4k, sizeof(rATQA));
|
memcpy(rATQA, rATQA_4k, sizeof(rATQA));
|
||||||
rSAK[0] = rSAK_4k;
|
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 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 ((flags & FLAG_NESTED_AUTH_ATTACK) == FLAG_NESTED_AUTH_ATTACK) {
|
||||||
if (emlGetKey(cardAUTHSC, cardAUTHKEY) == 0) {
|
if (emlGetKey(cardAUTHSC, cardAUTHKEY) == 0) {
|
||||||
uint8_t buf[16] = {0};
|
uint8_t buf[MIFARE_BLOCK_SIZE] = {0};
|
||||||
emlGetMem(buf, (CARD_MEMORY_RF08S_OFFSET / MIFARE_BLOCK_SIZE) + cardAUTHSC, 1);
|
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
|
if (buf[(cardAUTHKEY * 8) + 3] == 0xAA) { // extra check to tell we have nt/nt_enc/par_err
|
||||||
running_nested_auth_attack = true;
|
running_nested_auth_attack = true;
|
||||||
// nt
|
// nt
|
||||||
|
@ -955,7 +979,7 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *uid, uint16_t
|
||||||
// first block
|
// first block
|
||||||
if (blockNo == 4) {
|
if (blockNo == 4) {
|
||||||
|
|
||||||
p_em += blockNo * 16;
|
p_em += (blockNo * MIFARE_BLOCK_SIZE);
|
||||||
// TLV in NDEF, flip length between
|
// TLV in NDEF, flip length between
|
||||||
// 4 | 03 21 D1 02 1C 53 70 91 01 09 54 02 65 6E 4C 69
|
// 4 | 03 21 D1 02 1C 53 70 91 01 09 54 02 65 6E 4C 69
|
||||||
// 0xFF means long length
|
// 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) {
|
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,
|
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 {
|
} else {
|
||||||
if (IsAccessAllowed(blockNo, cardAUTHKEY, AC_DATA_READ) == false) {
|
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);
|
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);
|
mf_crypto1_encrypt(pcs, response, MAX_MIFARE_FRAME_SIZE, response_par);
|
||||||
EmSendCmdPar(response, MAX_MIFARE_FRAME_SIZE, response_par);
|
EmSendCmdPar(response, MAX_MIFARE_FRAME_SIZE, response_par);
|
||||||
FpgaDisableTracing();
|
FpgaDisableTracing();
|
||||||
|
@ -1109,7 +1133,9 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *uid, uint16_t
|
||||||
|
|
||||||
// case MFEMUL_WORK => CMD RATS
|
// 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 (receivedCmd_len == 4 && receivedCmd_dec[0] == ISO14443A_CMD_RATS && (receivedCmd_dec[1] & 0xF0) <= 0x80 && (receivedCmd_dec[1] & 0x0F) <= 0x0e) {
|
||||||
|
|
||||||
if (rats && rats_len) {
|
if (rats && rats_len) {
|
||||||
|
|
||||||
if (encrypted_data) {
|
if (encrypted_data) {
|
||||||
memcpy(response, rats, rats_len);
|
memcpy(response, rats, rats_len);
|
||||||
mf_crypto1_encrypt(pcs, response, rats_len, response_par);
|
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 {
|
} else {
|
||||||
EmSendCmd(rats, rats_len);
|
EmSendCmd(rats, rats_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
FpgaDisableTracing();
|
FpgaDisableTracing();
|
||||||
if (g_dbglevel >= DBG_EXTENDED)
|
|
||||||
|
if (g_dbglevel >= DBG_EXTENDED) {
|
||||||
Dbprintf("[MFEMUL_WORK] RCV RATS => ACK");
|
Dbprintf("[MFEMUL_WORK] RCV RATS => ACK");
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
EmSend4bit(encrypted_data ? mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA) : CARD_NACK_NA);
|
EmSend4bit(encrypted_data ? mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA) : CARD_NACK_NA);
|
||||||
FpgaDisableTracing();
|
FpgaDisableTracing();
|
||||||
cardSTATE_TO_IDLE();
|
cardSTATE_TO_IDLE();
|
||||||
if (g_dbglevel >= DBG_EXTENDED)
|
if (g_dbglevel >= DBG_EXTENDED) {
|
||||||
Dbprintf("[MFEMUL_WORK] RCV RATS => NACK");
|
Dbprintf("[MFEMUL_WORK] RCV RATS => NACK");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// case MFEMUL_WORK => ISO14443A_CMD_NXP_DESELECT
|
// case MFEMUL_WORK => ISO14443A_CMD_NXP_DESELECT
|
||||||
if (receivedCmd_len == 3 && receivedCmd_dec[0] == ISO14443A_CMD_NXP_DESELECT) {
|
if (receivedCmd_len == 3 && receivedCmd_dec[0] == ISO14443A_CMD_NXP_DESELECT) {
|
||||||
|
|
||||||
if (rats && rats_len) {
|
if (rats && rats_len) {
|
||||||
|
|
||||||
// response back NXP_DESELECT
|
// response back NXP_DESELECT
|
||||||
if (encrypted_data) {
|
if (encrypted_data) {
|
||||||
memcpy(response, receivedCmd_dec, receivedCmd_len);
|
memcpy(response, receivedCmd_dec, receivedCmd_len);
|
||||||
mf_crypto1_encrypt(pcs, response, receivedCmd_len, response_par);
|
mf_crypto1_encrypt(pcs, response, receivedCmd_len, response_par);
|
||||||
EmSendCmdPar(response, receivedCmd_len, response_par);
|
EmSendCmdPar(response, receivedCmd_len, response_par);
|
||||||
} else
|
} else {
|
||||||
EmSendCmd(receivedCmd_dec, receivedCmd_len);
|
EmSendCmd(receivedCmd_dec, receivedCmd_len);
|
||||||
|
}
|
||||||
|
|
||||||
FpgaDisableTracing();
|
FpgaDisableTracing();
|
||||||
if (g_dbglevel >= DBG_EXTENDED)
|
if (g_dbglevel >= DBG_EXTENDED) {
|
||||||
Dbprintf("[MFEMUL_WORK] RCV NXP DESELECT => ACK");
|
Dbprintf("[MFEMUL_WORK] RCV NXP DESELECT => ACK");
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
EmSend4bit(encrypted_data ? mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA) : CARD_NACK_NA);
|
EmSend4bit(encrypted_data ? mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA) : CARD_NACK_NA);
|
||||||
FpgaDisableTracing();
|
FpgaDisableTracing();
|
||||||
cardSTATE_TO_IDLE();
|
cardSTATE_TO_IDLE();
|
||||||
if (g_dbglevel >= DBG_EXTENDED)
|
if (g_dbglevel >= DBG_EXTENDED) {
|
||||||
Dbprintf("[MFEMUL_WORK] RCV NXP DESELECT => NACK");
|
Dbprintf("[MFEMUL_WORK] RCV NXP DESELECT => NACK");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// case MFEMUL_WORK => command not allowed
|
// case MFEMUL_WORK => command not allowed
|
||||||
if (g_dbglevel >= DBG_EXTENDED)
|
if (g_dbglevel >= DBG_EXTENDED) {
|
||||||
Dbprintf("Received command not allowed, nacking");
|
Dbprintf("Received command not allowed, nacking");
|
||||||
|
}
|
||||||
EmSend4bit(encrypted_data ? mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA) : CARD_NACK_NA);
|
EmSend4bit(encrypted_data ? mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA) : CARD_NACK_NA);
|
||||||
FpgaDisableTracing();
|
FpgaDisableTracing();
|
||||||
break;
|
break;
|
||||||
|
@ -1164,14 +1202,16 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *uid, uint16_t
|
||||||
|
|
||||||
// AUTH1
|
// AUTH1
|
||||||
case MFEMUL_AUTH1: {
|
case MFEMUL_AUTH1: {
|
||||||
if (g_dbglevel >= DBG_EXTENDED)
|
if (g_dbglevel >= DBG_EXTENDED) {
|
||||||
Dbprintf("[MFEMUL_AUTH1] Enter case");
|
Dbprintf("[MFEMUL_AUTH1] Enter case");
|
||||||
|
}
|
||||||
|
|
||||||
if (receivedCmd_len != 8) {
|
if (receivedCmd_len != 8) {
|
||||||
cardSTATE_TO_IDLE();
|
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);
|
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);
|
Dbprintf("MFEMUL_AUTH1: receivedCmd_len != 8 (%d) => cardSTATE_TO_IDLE())", receivedCmd_len);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1191,6 +1231,7 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *uid, uint16_t
|
||||||
ar_nr_resp[0].state = NESTED;
|
ar_nr_resp[0].state = NESTED;
|
||||||
finished = true;
|
finished = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((flags & FLAG_NR_AR_ATTACK) == FLAG_NR_AR_ATTACK) {
|
if ((flags & FLAG_NR_AR_ATTACK) == FLAG_NR_AR_ATTACK) {
|
||||||
|
|
||||||
for (uint8_t i = 0; i < ATTACK_KEY_COUNT; i++) {
|
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
|
// WRITE BL2
|
||||||
case MFEMUL_WRITEBL2: {
|
case MFEMUL_WRITEBL2: {
|
||||||
|
|
||||||
if (receivedCmd_len == MAX_MIFARE_FRAME_SIZE) {
|
if (receivedCmd_len == MAX_MIFARE_FRAME_SIZE) {
|
||||||
|
|
||||||
mf_crypto1_decryptEx(pcs, receivedCmd, receivedCmd_len, receivedCmd_dec);
|
mf_crypto1_decryptEx(pcs, receivedCmd, receivedCmd_len, receivedCmd_dec);
|
||||||
|
|
||||||
if (CheckCrc14A(receivedCmd_dec, receivedCmd_len)) {
|
if (CheckCrc14A(receivedCmd_dec, receivedCmd_len)) {
|
||||||
|
|
||||||
if (IsSectorTrailer(cardWRBL)) {
|
if (IsSectorTrailer(cardWRBL)) {
|
||||||
|
|
||||||
emlGetMem(response, cardWRBL, 1);
|
emlGetMem_xt(response, cardWRBL, 1, MIFARE_BLOCK_SIZE);
|
||||||
|
|
||||||
if (IsAccessAllowed(cardWRBL, cardAUTHKEY, AC_KEYA_WRITE) == false) {
|
if (IsAccessAllowed(cardWRBL, cardAUTHKEY, AC_KEYA_WRITE) == false) {
|
||||||
memcpy(receivedCmd_dec, response, 6); // don't change KeyA
|
memcpy(receivedCmd_dec, response, 6); // don't change KeyA
|
||||||
|
|
|
@ -756,14 +756,16 @@ uint8_t FirstBlockOfSector(uint8_t sectorNo) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// work with emulator memory
|
// 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 offset = blockNum * block_width;
|
||||||
uint32_t len = blocksCount * block_width;
|
uint32_t len = blocksCount * block_width;
|
||||||
emlSet(data, offset, len);
|
emlSet(data, offset, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
void emlGetMem(uint8_t *data, int blockNum, int blocksCount) {
|
void emlGetMem_xt(uint8_t *data, uint16_t blockNum, uint8_t blocksCount, uint8_t block_width) {
|
||||||
emlGet(data, (blockNum * 16), (blocksCount * 16));
|
uint32_t offset = blockNum * block_width;
|
||||||
|
uint32_t len = blocksCount * block_width;
|
||||||
|
emlGet(data, offset, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool emlCheckValBl(int blockNum) {
|
bool emlCheckValBl(int blockNum) {
|
||||||
|
@ -817,10 +819,11 @@ uint64_t emlGetKey(int sectorNum, int keyType) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void emlClearMem(void) {
|
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 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};
|
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
|
// fill sectors trailer data
|
||||||
for (uint16_t b = 3; b < MIFARE_4K_MAXBLOCK; ((b < MIFARE_2K_MAXBLOCK - 4) ? (b += 4) : (b += 16))) {
|
for (uint16_t b = 3; b < MIFARE_4K_MAXBLOCK; ((b < MIFARE_2K_MAXBLOCK - 4) ? (b += 4) : (b += 16))) {
|
||||||
|
|
|
@ -131,8 +131,9 @@ uint8_t SectorTrailer(uint8_t blockNo);
|
||||||
|
|
||||||
// emulator functions
|
// emulator functions
|
||||||
void emlClearMem(void);
|
void emlClearMem(void);
|
||||||
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);
|
||||||
void emlGetMem(uint8_t *data, int blockNum, int blocksCount);
|
void emlGetMem_xt(uint8_t *data, uint16_t blockNum, uint8_t blocksCount, uint8_t block_width);
|
||||||
|
|
||||||
uint64_t emlGetKey(int sectorNum, int keyType);
|
uint64_t emlGetKey(int sectorNum, int keyType);
|
||||||
int emlGetValBl(uint32_t *blReg, uint8_t *blBlock, int blockNum);
|
int emlGetValBl(uint32_t *blReg, uint8_t *blBlock, int blockNum);
|
||||||
void emlSetValBl(uint32_t blReg, uint8_t blBlock, int blockNum);
|
void emlSetValBl(uint32_t blReg, uint8_t blBlock, int blockNum);
|
||||||
|
|
|
@ -437,10 +437,10 @@ uint16_t sam_copy_payload_sam2nfc(uint8_t *nfc_tx_buf, uint8_t *sam_rx_buf) {
|
||||||
// 90 00
|
// 90 00
|
||||||
|
|
||||||
// NFC req:
|
// NFC req:
|
||||||
// 0C 05 DE 64
|
// 0C 05 DE 64
|
||||||
|
|
||||||
// copy data out of c1->a1>->a1->80 node
|
// copy data out of c1->a1>->a1->80 node
|
||||||
uint16_t nfc_tx_len = (uint8_t) * (sam_rx_buf + 10);
|
uint16_t nfc_tx_len = (uint8_t) * (sam_rx_buf + 10);
|
||||||
memcpy(nfc_tx_buf, sam_rx_buf + 11, nfc_tx_len);
|
memcpy(nfc_tx_buf, sam_rx_buf + 11, nfc_tx_len);
|
||||||
return nfc_tx_len;
|
return nfc_tx_len;
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,9 +49,9 @@ static int sam_send_request_iso15(const uint8_t *const request, const uint8_t re
|
||||||
if (g_dbglevel >= DBG_DEBUG)
|
if (g_dbglevel >= DBG_DEBUG)
|
||||||
DbpString("start sam_send_request_iso14a");
|
DbpString("start sam_send_request_iso14a");
|
||||||
|
|
||||||
uint8_t * buf1 = BigBuf_malloc(ISO7816_MAX_FRAME);
|
uint8_t *buf1 = BigBuf_malloc(ISO7816_MAX_FRAME);
|
||||||
uint8_t * buf2 = BigBuf_malloc(ISO7816_MAX_FRAME);
|
uint8_t *buf2 = BigBuf_malloc(ISO7816_MAX_FRAME);
|
||||||
if(buf1 == NULL || buf2 == NULL){
|
if (buf1 == NULL || buf2 == NULL) {
|
||||||
res = PM3_EMALLOC;
|
res = PM3_EMALLOC;
|
||||||
goto out;
|
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);
|
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;
|
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);
|
memcpy(response, nfc_tx_buf, nfc_tx_len);
|
||||||
*response_len = nfc_tx_len;
|
*response_len = nfc_tx_len;
|
||||||
if (g_dbglevel >= DBG_INFO) {
|
if (g_dbglevel >= DBG_INFO) {
|
||||||
DbpString("NR-MAC: ");
|
DbpString("NR-MAC: ");
|
||||||
Dbhexdump((*response_len)-1, response+1, false);
|
Dbhexdump((*response_len) - 1, response + 1, false);
|
||||||
}
|
}
|
||||||
res = PM3_SUCCESS;
|
res = PM3_SUCCESS;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_cmd_update = (nfc_tx_buf[0] & 0x0F) == ICLASS_CMD_UPDATE;
|
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
|
// block update(2) command and fake the response to prevent update of epurse
|
||||||
|
|
||||||
// NFC TX BUFFERS PREPARED BY SAM LOOKS LIKE:
|
// 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:
|
// NFC RX BUFFERS EXPECTED BY SAM WOULD LOOK LIKE:
|
||||||
// #2(FF FF FF FF) #1(C9 FD FF FF) 3A 47
|
// #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 + 0, nfc_tx_buf + 6, 4);
|
||||||
memcpy(nfc_rx_buf+4, nfc_tx_buf+0, 4);
|
memcpy(nfc_rx_buf + 4, nfc_tx_buf + 0, 4);
|
||||||
AddCrc(nfc_rx_buf, 8);
|
AddCrc(nfc_rx_buf, 8);
|
||||||
nfc_rx_len = 10;
|
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;
|
res = PM3_ECARDEXCHANGE;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -358,7 +358,7 @@ int sam_picopass_get_pacs(PacketCommandNG *c) {
|
||||||
|
|
||||||
// implicit StartSspClk() happens here
|
// implicit StartSspClk() happens here
|
||||||
Iso15693InitReader();
|
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;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -129,9 +129,9 @@ static int sam_send_request_iso14a(const uint8_t *const request, const uint8_t r
|
||||||
if (g_dbglevel >= DBG_DEBUG)
|
if (g_dbglevel >= DBG_DEBUG)
|
||||||
DbpString("start sam_send_request_iso14a");
|
DbpString("start sam_send_request_iso14a");
|
||||||
|
|
||||||
uint8_t * buf1 = BigBuf_malloc(ISO7816_MAX_FRAME);
|
uint8_t *buf1 = BigBuf_malloc(ISO7816_MAX_FRAME);
|
||||||
uint8_t * buf2 = BigBuf_malloc(ISO7816_MAX_FRAME);
|
uint8_t *buf2 = BigBuf_malloc(ISO7816_MAX_FRAME);
|
||||||
if(buf1 == NULL || buf2 == NULL){
|
if (buf1 == NULL || buf2 == NULL) {
|
||||||
res = PM3_EMALLOC;
|
res = PM3_EMALLOC;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
|
@ -548,7 +548,7 @@ static s32_t spiffs_page_consistency_check_i(spiffs *fs) {
|
||||||
SPIFFS_API_CHECK_RES(fs, SPIFFS_ERR_INTERNAL);
|
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)
|
// 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...
|
// checking with +1 block count to avoid overflow also in inner loop, which adds one page...
|
||||||
// would exceed value storable in uint32_t
|
// 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);
|
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,
|
// because loop indices are using spiffs_page_ix type,
|
||||||
// that type can hold a large enough value
|
// 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_DBG("Avoiding infinite loop, total_blocks "_SPIPRIpg" too large for spiffs_page_ix type\n", total_blocks);
|
||||||
SPIFFS_CHECK_RES(SPIFFS_ERR_INTERNAL);
|
SPIFFS_CHECK_RES(SPIFFS_ERR_INTERNAL);
|
||||||
}
|
}
|
||||||
// because loop indices are using spiffs_page_ix type,
|
// because loop indices are using spiffs_page_ix type,
|
||||||
// that type can hold a large enough value
|
// 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_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);
|
SPIFFS_CHECK_RES(SPIFFS_ERR_INTERNAL);
|
||||||
}
|
}
|
||||||
|
@ -586,7 +586,7 @@ static s32_t spiffs_page_consistency_check_i(spiffs *fs) {
|
||||||
0);
|
0);
|
||||||
// traverse each page except for lookup pages
|
// traverse each page except for lookup pages
|
||||||
spiffs_page_ix cur_pix = SPIFFS_OBJ_LOOKUP_PAGES(fs) + SPIFFS_PAGES_PER_BLOCK(fs) * cur_block;
|
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)
|
//if ((cur_pix & 0xff) == 0)
|
||||||
// SPIFFS_CHECK_DBG("PA: processing pix "_SPIPRIpg", block "_SPIPRIbl" of pix "_SPIPRIpg", block "_SPIPRIbl"\n",
|
// SPIFFS_CHECK_DBG("PA: processing pix "_SPIPRIpg", block "_SPIPRIbl" of pix "_SPIPRIpg", block "_SPIPRIbl"\n",
|
||||||
// cur_pix, cur_block, total_blocks, block_count);
|
// cur_pix, cur_block, total_blocks, block_count);
|
||||||
|
|
|
@ -10,7 +10,7 @@ local green = ac.green
|
||||||
|
|
||||||
author = ' Author: jareckib - created 04.02.2025'
|
author = ' Author: jareckib - created 04.02.2025'
|
||||||
version = ' version v1.05'
|
version = ' version v1.05'
|
||||||
desc = [[
|
desc = [[
|
||||||
A simple script for searching the password for T5577. The script creates a
|
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.
|
dictionary starting from the entered starting year to the entered ending year.
|
||||||
There are two search methods - DDMMYYYY or YYYYMMDD. Checking the entire 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
|
for o, a in getopt.getopt(args, 'hs:e:dy') do
|
||||||
if o == 'h' then return help() end
|
if o == 'h' then return help() end
|
||||||
if o == 's' then
|
if o == 's' then
|
||||||
start_year = tonumber(a)
|
start_year = tonumber(a)
|
||||||
if not start_year then return oops(' Invalid start year') end
|
if not start_year then return oops(' Invalid start year') end
|
||||||
end
|
end
|
||||||
if o == 'e' then
|
if o == 'e' then
|
||||||
end_year = tonumber(a)
|
end_year = tonumber(a)
|
||||||
if not end_year then return oops(' Invalid end year') end
|
if not end_year then return oops(' Invalid end year') end
|
||||||
end
|
end
|
||||||
|
@ -115,13 +115,13 @@ local function main(args)
|
||||||
end
|
end
|
||||||
|
|
||||||
if not start_year then return oops(' Starting year is required') end
|
if not start_year then return oops(' Starting year is required') end
|
||||||
if start_year < 1900 or start_year > 2100 then
|
if start_year < 1900 or start_year > 2100 then
|
||||||
return oops(' Start year must be between 1900 and 2100')
|
return oops(' Start year must be between 1900 and 2100')
|
||||||
end
|
end
|
||||||
if args[#args] == "-e" then return oops(' Ending year cannot be empty') 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 not end_year then end_year = current_year end
|
||||||
if end_year < 1900 or end_year > 2100 then
|
if end_year < 1900 or end_year > 2100 then
|
||||||
return oops(' End year must be between 1900 and 2100')
|
return oops(' End year must be between 1900 and 2100')
|
||||||
end
|
end
|
||||||
|
|
||||||
if end_year < start_year then return oops(' End year cannot be earlier than start year') 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
|
if generate_dictionary(start_year, end_year, mode) then
|
||||||
print(ac.green .. " File created: " .. dictionary_path .. res)
|
print(ac.green .. " File created: " .. dictionary_path .. res)
|
||||||
print(cyan .. " Starting password testing on T5577..." .. 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
|
else
|
||||||
return oops('Problem saving the file')
|
return oops('Problem saving the file')
|
||||||
end
|
end
|
||||||
|
|
|
@ -6,7 +6,7 @@ local dash = string.rep('--', 32)
|
||||||
|
|
||||||
author = ' Author: jareckib - created 01.02.2025'
|
author = ' Author: jareckib - created 01.02.2025'
|
||||||
version = ' version v1.01'
|
version = ' version v1.01'
|
||||||
desc = [[
|
desc = [[
|
||||||
A simple script for searching the password for T5577. The script creates a
|
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.
|
dictionary starting from the entered starting year to the entered ending year.
|
||||||
There are two search methods - DDMMYYYY or YYYYMMDD. Checking the entire 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
|
local year
|
||||||
while true do
|
while true do
|
||||||
io.write(prompt)
|
io.write(prompt)
|
||||||
local input = io.read()
|
local input = io.read()
|
||||||
if input == "" then
|
if input == "" then
|
||||||
print(ac.yellow .. ' ERROR: ' .. ac.reset .. 'Year cannot be empty')
|
print(ac.yellow .. ' ERROR: ' .. ac.reset .. 'Year cannot be empty')
|
||||||
else
|
else
|
||||||
year = tonumber(input)
|
year = tonumber(input)
|
||||||
if not year then
|
if not year then
|
||||||
print(ac.yellow .. ' ERROR: ' .. ac.reset .. 'Invalid input (digits only)')
|
print(ac.yellow .. ' ERROR: ' .. ac.reset .. 'Invalid input (digits only)')
|
||||||
elseif year < 1900 then
|
elseif year < 1900 then
|
||||||
|
@ -155,7 +155,7 @@ local function main(args)
|
||||||
if generate_dictionary(start_year, end_year, mode) then
|
if generate_dictionary(start_year, end_year, mode) then
|
||||||
print(ac.green .. " File created: " .. dictionary_path .. ac.reset)
|
print(ac.green .. " File created: " .. dictionary_path .. ac.reset)
|
||||||
print(ac.cyan .. " Starting password testing on T5577..." .. 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
|
else
|
||||||
print(ac.yellow .. ' ERROR: ' .. ac.reset .. 'Problem saving the file.')
|
print(ac.yellow .. ' ERROR: ' .. ac.reset .. 'Problem saving the file.')
|
||||||
end
|
end
|
||||||
|
|
|
@ -9,11 +9,11 @@ local command = core.console
|
||||||
|
|
||||||
author = ' Author: jareckib - 15.02.2025'
|
author = ' Author: jareckib - 15.02.2025'
|
||||||
version = ' version v1.00'
|
version = ' version v1.00'
|
||||||
desc = [[
|
desc = [[
|
||||||
This simple script first checks if a password has been set for the T5577.
|
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
|
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
|
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
|
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.
|
only performs the reanimation procedure. The script revives 99% of blocked tags.
|
||||||
]]
|
]]
|
||||||
usage = [[
|
usage = [[
|
||||||
|
@ -91,7 +91,7 @@ end
|
||||||
local function main(args)
|
local function main(args)
|
||||||
for o, a in getopt.getopt(args, 'h') do
|
for o, a in getopt.getopt(args, 'h') do
|
||||||
if o == 'h' then return help() end
|
if o == 'h' then return help() end
|
||||||
end
|
end
|
||||||
command('lf t55 chk')
|
command('lf t55 chk')
|
||||||
local log_content = read_log_file(logfile)
|
local log_content = read_log_file(logfile)
|
||||||
local password = log_content and extract_password(log_content) or nil
|
local password = log_content and extract_password(log_content) or nil
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# paxton_net.py - Convert Paxton Net2 to EM4102
|
# paxton_net.py - Convert Paxton Net2 to EM4102
|
||||||
# Author jareckib <jareckib@hotmail.com>
|
# Author jareckib <jareckib@hotmail.com>
|
||||||
# Based on Equipter's tutorial - Downgrade Paxton Net to EM410x
|
# Based on Equipter's tutorial - Downgrade Paxton Net to EM410x
|
||||||
#
|
#
|
||||||
# This code is copyright (c) jareckib, 2025, All rights reserved.
|
# This code is copyright (c) jareckib, 2025, All rights reserved.
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# paxton_convert.py - Convert Paxton Net2 and Switch2 to EM4102
|
# paxton_convert.py - Convert Paxton Net2 and Switch2 to EM4102
|
||||||
# Author jareckib <jareckib@hotmail.com>
|
# Author jareckib <jareckib@hotmail.com>
|
||||||
# Based on Equipter's tutorial - Downgrade Paxton Net to EM410x
|
# Based on Equipter's tutorial - Downgrade Paxton Net to EM410x
|
||||||
#
|
#
|
||||||
# This code is copyright (c) jareckib, 2025, All rights reserved.
|
# This code is copyright (c) jareckib, 2025, All rights reserved.
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# paxton_switch.py - Convert Paxton Switch2 to EM4102
|
# paxton_switch.py - Convert Paxton Switch2 to EM4102
|
||||||
# Author jareckib <jareckib@hotmail.com>
|
# Author jareckib <jareckib@hotmail.com>
|
||||||
# Based on Equipter's tutorial - Downgrade Paxton Net to EM410x
|
# Based on Equipter's tutorial - Downgrade Paxton Net to EM410x
|
||||||
#
|
#
|
||||||
# This code is copyright (c) jareckib, 2025, All rights reserved.
|
# This code is copyright (c) jareckib, 2025, All rights reserved.
|
||||||
|
|
|
@ -194,7 +194,7 @@ def Describe_Usage_2_1(Usage, ContractMediumEndDate, Certificate):
|
||||||
EventGeoRoute_Direction = Usage.nom(2)
|
EventGeoRoute_Direction = Usage.nom(2)
|
||||||
EventGeoVehicleId = Usage.nom(16)
|
EventGeoVehicleId = Usage.nom(16)
|
||||||
EventCountPassengers_mb = Usage.nom(4)
|
EventCountPassengers_mb = Usage.nom(4)
|
||||||
|
|
||||||
EventValidityTimeFirstStamp = Usage.nom(11)
|
EventValidityTimeFirstStamp = Usage.nom(11)
|
||||||
|
|
||||||
print(' EventDateStamp : {} ({})'.format(EventDateStamp, (datetime(1997, 1, 1) + timedelta(days = ContractMediumEndDate - EventDateStamp)).strftime('%Y-%m-%d')))
|
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)
|
oa = MAR_OrganizationalAuthority_Contract_Provider.get(OrganizationalAuthority)
|
||||||
else:
|
else:
|
||||||
oa = None
|
oa = None
|
||||||
|
|
||||||
if (oa is not None):
|
if (oa is not None):
|
||||||
s = oa.get(ContractProvider)
|
s = oa.get(ContractProvider)
|
||||||
if (s is not None):
|
if (s is not None):
|
||||||
|
|
|
@ -3784,22 +3784,22 @@ int CmdHF14AAIDSim(const char *Cmd) {
|
||||||
|
|
||||||
if (ats_len > sizeof(ats)) {
|
if (ats_len > sizeof(ats)) {
|
||||||
PrintAndLogEx(ERR, "Provided ATS too long");
|
PrintAndLogEx(ERR, "Provided ATS too long");
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (aid_len > sizeof(aid)) {
|
if (aid_len > sizeof(aid)) {
|
||||||
PrintAndLogEx(ERR, "Provided AID too long");
|
PrintAndLogEx(ERR, "Provided AID too long");
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (selectaid_response_len > sizeof(selectaid_response)) {
|
if (selectaid_response_len > sizeof(selectaid_response)) {
|
||||||
PrintAndLogEx(ERR, "Provided SelectAID response too long");
|
PrintAndLogEx(ERR, "Provided SelectAID response too long");
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getdata_response_len > sizeof(getdata_response)) {
|
if (getdata_response_len > sizeof(getdata_response)) {
|
||||||
PrintAndLogEx(ERR, "Provided GetData response too long");
|
PrintAndLogEx(ERR, "Provided GetData response too long");
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ats_len > 0) {
|
if (ats_len > 0) {
|
||||||
|
@ -3857,14 +3857,17 @@ int CmdHF14AAIDSim(const char *Cmd) {
|
||||||
bool keypress = kbd_enter_pressed();
|
bool keypress = kbd_enter_pressed();
|
||||||
while (keypress == false) {
|
while (keypress == false) {
|
||||||
|
|
||||||
if (WaitForResponseTimeout(CMD_HF_MIFARE_SIMULATE, &resp, 1500) == 0)
|
if (WaitForResponseTimeout(CMD_HF_MIFARE_SIMULATE, &resp, 1500) == 0) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (resp.status != PM3_SUCCESS)
|
if (resp.status != PM3_SUCCESS) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if ((flags & FLAG_NR_AR_ATTACK) != FLAG_NR_AR_ATTACK)
|
if ((flags & FLAG_NR_AR_ATTACK) != FLAG_NR_AR_ATTACK) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
keypress = kbd_enter_pressed();
|
keypress = kbd_enter_pressed();
|
||||||
}
|
}
|
||||||
|
|
|
@ -282,9 +282,9 @@ static const productName_t uidmapping[] = {
|
||||||
static int CmdHF15Help(const char *Cmd);
|
static int CmdHF15Help(const char *Cmd);
|
||||||
|
|
||||||
static int nxp_15693_print_signature(uint8_t *uid, uint8_t *signature) {
|
static int nxp_15693_print_signature(uint8_t *uid, uint8_t *signature) {
|
||||||
|
|
||||||
int reason = 0;
|
int reason = 0;
|
||||||
int index = -1;
|
int index = originality_check_verify(uid, 8, signature, 32, PK_MFC);
|
||||||
index = originality_check_verify(uid, 8, signature, 32, PK_MFC);
|
|
||||||
if (index >= 0) {
|
if (index >= 0) {
|
||||||
reason = 1;
|
reason = 1;
|
||||||
} else {
|
} 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);
|
int ret = originality_check_print(signature, 32, index);
|
||||||
if (ret != PM3_SUCCESS) {
|
if (ret != PM3_SUCCESS) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (reason) {
|
switch (reason) {
|
||||||
case 1:
|
case 1:
|
||||||
PrintAndLogEx(INFO, " Params used: UID and signature, plain");
|
PrintAndLogEx(INFO, " Params used: UID and signature, plain");
|
||||||
|
|
|
@ -3246,14 +3246,14 @@ void print_iclass_sio(uint8_t *iclass_dump, size_t dump_len, bool verbose) {
|
||||||
}
|
}
|
||||||
|
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(INFO, "---------------------------- " _CYAN_("SIO - RAW") " ----------------------------");
|
PrintAndLogEx(INFO, "--------------------------- " _CYAN_("SIO - RAW") " -----------------------------");
|
||||||
print_hex_noascii_break(sio_start, sio_length, 32);
|
print_hex_noascii_break(sio_start, sio_length, 32);
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
PrintAndLogEx(INFO, "----------------------- " _CYAN_("SIO - ASN1 TLV") " ---------------------------");
|
PrintAndLogEx(INFO, "----------------------- " _CYAN_("SIO - ASN1 TLV") " ---------------------------");
|
||||||
asn1_print(sio_start, sio_length, " ");
|
asn1_print(sio_start, sio_length, " ");
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void printIclassDumpContents(uint8_t *iclass_dump, uint8_t startblock, uint8_t endblock, size_t filesize, bool dense_output) {
|
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_lit0(NULL, "vb6kdf", "use the VB6 elite KDF instead of a file"),
|
||||||
arg_param_end
|
arg_param_end
|
||||||
};
|
};
|
||||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||||
|
|
||||||
int fnlen = 0;
|
int fnlen = 0;
|
||||||
char filename[FILE_PATH_SIZE] = {0};
|
char filename[FILE_PATH_SIZE] = {0};
|
||||||
|
@ -5425,7 +5425,7 @@ static int CmdHFiClassSAM(const char *Cmd) {
|
||||||
data[0] = flags;
|
data[0] = flags;
|
||||||
|
|
||||||
int cmdlen = 0;
|
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);
|
CLIParserFree(ctx);
|
||||||
return PM3_ESOFT;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
|
@ -5437,7 +5437,7 @@ static int CmdHFiClassSAM(const char *Cmd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
SendCommandNG(CMD_HF_SAM_PICOPASS, data, cmdlen+1);
|
SendCommandNG(CMD_HF_SAM_PICOPASS, data, cmdlen + 1);
|
||||||
PacketResponseNG resp;
|
PacketResponseNG resp;
|
||||||
if (WaitForResponseTimeout(CMD_HF_SAM_PICOPASS, &resp, 4000) == false) {
|
if (WaitForResponseTimeout(CMD_HF_SAM_PICOPASS, &resp, 4000) == false) {
|
||||||
PrintAndLogEx(WARNING, "SAM timeout");
|
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 = oid + 2 + oid_length;
|
||||||
const uint8_t mediaType_data = mediaType[2];
|
const uint8_t mediaType_data = mediaType[2];
|
||||||
PrintAndLogEx(SUCCESS, "SIO Media Type: " _GREEN_("%s"), getSioMediaTypeInfo(mediaType_data));
|
PrintAndLogEx(SUCCESS, "SIO Media Type: " _GREEN_("%s"), getSioMediaTypeInfo(mediaType_data));
|
||||||
} else if(breakOnNrMac && d[0] == 0x05) {
|
} else if (breakOnNrMac && d[0] == 0x05) {
|
||||||
PrintAndLogEx(SUCCESS, "Nr-MAC: " _GREEN_("%s"), sprint_hex_inrow(d+1, 8));
|
PrintAndLogEx(SUCCESS, "Nr-MAC: " _GREEN_("%s"), sprint_hex_inrow(d + 1, 8));
|
||||||
if(verbose){
|
if (verbose) {
|
||||||
PrintAndLogEx(INFO, "Replay Nr-MAC to dump SIO:");
|
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 {
|
} else {
|
||||||
print_hex(d, resp.length);
|
print_hex(d, resp.length);
|
||||||
|
|
|
@ -70,7 +70,6 @@ static int usage_hf14_keybrute(void) {
|
||||||
|
|
||||||
int mfc_ev1_print_signature(uint8_t *uid, uint8_t uidlen, uint8_t *signature, int signature_len) {
|
int 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);
|
int index = originality_check_verify(uid, uidlen, signature, signature_len, PK_MFC);
|
||||||
PrintAndLogEx(NORMAL, "");
|
|
||||||
return originality_check_print(signature, signature_len, index);
|
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);
|
ascii_to_buffer((uint8_t *)ascii, d, MFBLOCK_SIZE, sizeof(ascii) - 1, 1);
|
||||||
|
|
||||||
if (blockno >= MIFARE_1K_MAXBLOCK) {
|
if (blockno >= MIFARE_1K_MAXBLOCK) {
|
||||||
PrintAndLogEx(INFO,
|
PrintAndLogEx(INFO,
|
||||||
_BACK_BLUE_("%s| %3d | " _YELLOW_("%s"))
|
_BACK_BLUE_("%s| %3d | " _YELLOW_("%s"))
|
||||||
_BACK_BLUE_(_MAGENTA_("%s"))
|
_BACK_BLUE_(_MAGENTA_("%s"))
|
||||||
_BACK_BLUE_("%02X ")
|
_BACK_BLUE_("%02X ")
|
||||||
_BACK_BLUE_(_YELLOW_("%s"))
|
_BACK_BLUE_(_YELLOW_("%s"))
|
||||||
_BACK_BLUE_("| " _YELLOW_("%s"))
|
_BACK_BLUE_("| " _YELLOW_("%s"))
|
||||||
,
|
,
|
||||||
secstr,
|
secstr,
|
||||||
blockno,
|
blockno,
|
||||||
keya,
|
keya,
|
||||||
acl,
|
acl,
|
||||||
d[9],
|
d[9],
|
||||||
keyb,
|
keyb,
|
||||||
ascii
|
ascii
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
PrintAndLogEx(INFO, "%s| %3d | " _YELLOW_("%s") _MAGENTA_("%s") "%02X " _YELLOW_("%s") "| " _YELLOW_("%s"),
|
PrintAndLogEx(INFO, "%s| %3d | " _YELLOW_("%s") _MAGENTA_("%s") "%02X " _YELLOW_("%s") "| " _YELLOW_("%s"),
|
||||||
secstr,
|
secstr,
|
||||||
blockno,
|
blockno,
|
||||||
keya,
|
keya,
|
||||||
acl,
|
acl,
|
||||||
d[9],
|
d[9],
|
||||||
keyb,
|
keyb,
|
||||||
ascii
|
ascii
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
@ -746,6 +745,7 @@ static int mfc_read_tag(iso14a_card_select_t *card, uint8_t *carddata, uint8_t n
|
||||||
free(fptr);
|
free(fptr);
|
||||||
free(keyA);
|
free(keyA);
|
||||||
free(keyB);
|
free(keyB);
|
||||||
|
|
||||||
PrintAndLogEx(SUCCESS, "\nSucceeded in dumping all blocks");
|
PrintAndLogEx(SUCCESS, "\nSucceeded in dumping all blocks");
|
||||||
return PM3_SUCCESS ;
|
return PM3_SUCCESS ;
|
||||||
}
|
}
|
||||||
|
@ -2138,7 +2138,7 @@ static int CmdHF14AMfNestedStatic(const char *Cmd) {
|
||||||
e_sector[sectorNo].foundKey[trgKeyType] = 1;
|
e_sector[sectorNo].foundKey[trgKeyType] = 1;
|
||||||
e_sector[sectorNo].Key[trgKeyType] = bytes_to_num(keyBlock, 6);
|
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;
|
continue;
|
||||||
default :
|
default :
|
||||||
PrintAndLogEx(ERR, "unknown error.\n");
|
PrintAndLogEx(ERR, "unknown error.\n");
|
||||||
|
@ -2955,7 +2955,7 @@ noValidKeyFound:
|
||||||
|
|
||||||
// Try the found keys are reused
|
// Try the found keys are reused
|
||||||
if (bytes_to_num(tmp_key, MIFARE_KEY_SIZE) != 0) {
|
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.
|
// <!> Returns false keys, so we just stick to the slower mfchk.
|
||||||
for (int i = 0; i < sector_cnt; i++) {
|
for (int i = 0; i < sector_cnt; i++) {
|
||||||
for (int j = MF_KEY_A; j <= MF_KEY_B; j++) {
|
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");
|
PrintAndLogEx(INFO, "Note: option -e implies -i");
|
||||||
flags |= FLAG_INTERACTIVE;
|
flags |= FLAG_INTERACTIVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((flags & FLAG_NR_AR_ATTACK) != FLAG_NR_AR_ATTACK) {
|
if ((flags & FLAG_NR_AR_ATTACK) != FLAG_NR_AR_ATTACK) {
|
||||||
PrintAndLogEx(WARNING, "Option -e requires -x or -y");
|
PrintAndLogEx(WARNING, "Option -e requires -x or -y");
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
|
@ -4278,22 +4279,27 @@ static int CmdHF14AMfSim(const char *Cmd) {
|
||||||
|
|
||||||
payload.flags = flags;
|
payload.flags = flags;
|
||||||
payload.exitAfter = exitAfterNReads;
|
payload.exitAfter = exitAfterNReads;
|
||||||
|
|
||||||
memcpy(payload.uid, uid, uidlen);
|
memcpy(payload.uid, uid, uidlen);
|
||||||
|
|
||||||
payload.atqa = (atqa[1] << 8) | atqa[0];
|
payload.atqa = (atqa[1] << 8) | atqa[0];
|
||||||
payload.sak = sak[0];
|
payload.sak = sak[0];
|
||||||
|
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
|
|
||||||
if (flags & FLAG_INTERACTIVE) {
|
if ((flags & FLAG_INTERACTIVE) == FLAG_INTERACTIVE) {
|
||||||
PrintAndLogEx(INFO, "Press " _GREEN_("pm3 button") " or a key to abort simulation");
|
PrintAndLogEx(INFO, "Press " _GREEN_("pm3 button") " or a key to abort simulation");
|
||||||
} else {
|
} else {
|
||||||
PrintAndLogEx(INFO, "Press " _GREEN_("pm3 button") " or send another cmd to abort simulation");
|
PrintAndLogEx(INFO, "Press " _GREEN_("pm3 button") " or send another cmd to abort simulation");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cont;
|
bool cont;
|
||||||
do {
|
do {
|
||||||
|
|
||||||
cont = false;
|
cont = false;
|
||||||
SendCommandNG(CMD_HF_MIFARE_SIMULATE, (uint8_t *)&payload, sizeof(payload));
|
SendCommandNG(CMD_HF_MIFARE_SIMULATE, (uint8_t *)&payload, sizeof(payload));
|
||||||
if (flags & FLAG_INTERACTIVE) {
|
|
||||||
|
if ((flags & FLAG_INTERACTIVE) == FLAG_INTERACTIVE) {
|
||||||
PacketResponseNG resp;
|
PacketResponseNG resp;
|
||||||
sector_t *k_sector = NULL;
|
sector_t *k_sector = NULL;
|
||||||
|
|
||||||
|
@ -4305,19 +4311,24 @@ static int CmdHF14AMfSim(const char *Cmd) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (resp.status != PM3_SUCCESS)
|
if (resp.status != PM3_SUCCESS) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if ((flags & FLAG_NR_AR_ATTACK) != FLAG_NR_AR_ATTACK)
|
if ((flags & FLAG_NR_AR_ATTACK) != FLAG_NR_AR_ATTACK) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
const nonces_t *data = (nonces_t *)resp.data.asBytes;
|
const nonces_t *data = (nonces_t *)resp.data.asBytes;
|
||||||
readerAttack(k_sector, k_sectors_cnt, data[0], setEmulatorMem, verbose);
|
readerAttack(k_sector, k_sectors_cnt, data[0], setEmulatorMem, verbose);
|
||||||
|
|
||||||
if (setEmulatorMem) {
|
if (setEmulatorMem) {
|
||||||
cont = true;
|
cont = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (keypress) {
|
if (keypress) {
|
||||||
if ((flags & FLAG_NR_AR_ATTACK) == FLAG_NR_AR_ATTACK) {
|
if ((flags & FLAG_NR_AR_ATTACK) == FLAG_NR_AR_ATTACK) {
|
||||||
// inform device to break the sim loop since client has exited
|
// 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)
|
if (bytes_read == MIFARE_MINI_MAX_BYTES)
|
||||||
block_cnt = MIFARE_MINI_MAXBLOCK;
|
block_cnt = MIFARE_MINI_MAXBLOCK;
|
||||||
else if (bytes_read == MIFARE_1K_EV1_MAX_BYTES)
|
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)
|
else if (bytes_read == MIFARE_2K_MAX_BYTES)
|
||||||
block_cnt = MIFARE_2K_MAXBLOCK;
|
block_cnt = MIFARE_2K_MAXBLOCK;
|
||||||
else if (bytes_read == MIFARE_4K_MAX_BYTES)
|
else if (bytes_read == MIFARE_4K_MAX_BYTES)
|
||||||
|
@ -9623,7 +9634,7 @@ static int CmdHF14AMfInfo(const char *Cmd) {
|
||||||
PacketResponseNG resp;
|
PacketResponseNG resp;
|
||||||
if (WaitForResponseTimeout(CMD_ACK, &resp, 2500) == false) {
|
if (WaitForResponseTimeout(CMD_ACK, &resp, 2500) == false) {
|
||||||
PrintAndLogEx(DEBUG, "iso14443a card select timeout");
|
PrintAndLogEx(DEBUG, "iso14443a card select timeout");
|
||||||
return 0;
|
return PM3_ETIMEOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
iso14a_card_select_t card;
|
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 k08s[MIFARE_KEY_SIZE] = {0xA3, 0x96, 0xEF, 0xA4, 0xE2, 0x4F};
|
||||||
uint8_t k08[6] = {0xA3, 0x16, 0x67, 0xA8, 0xCE, 0xC1};
|
uint8_t k08[MIFARE_KEY_SIZE] = {0xA3, 0x16, 0x67, 0xA8, 0xCE, 0xC1};
|
||||||
uint8_t k32[6] = {0x51, 0x8B, 0x33, 0x54, 0xE7, 0x60};
|
uint8_t k32[MIFARE_KEY_SIZE] = {0x51, 0x8B, 0x33, 0x54, 0xE7, 0x60};
|
||||||
if (mf_read_block(0, 4, k08s, blockdata) == PM3_SUCCESS) {
|
if (mf_read_block(0, 4, k08s, blockdata) == PM3_SUCCESS) {
|
||||||
PrintAndLogEx(SUCCESS, "Backdoor key..... " _YELLOW_("%s"), sprint_hex_inrow(k08s, sizeof(k08s)));
|
PrintAndLogEx(SUCCESS, "Backdoor key..... " _YELLOW_("%s"), sprint_hex_inrow(k08s, sizeof(k08s)));
|
||||||
fKeyType = MF_KEY_BD;
|
fKeyType = MF_KEY_BD;
|
||||||
|
|
|
@ -192,7 +192,6 @@ static nxp_cardtype_t getCardType(uint8_t type, uint8_t major, uint8_t minor) {
|
||||||
// --- GET SIGNATURE
|
// --- GET SIGNATURE
|
||||||
static int plus_print_signature(uint8_t *uid, uint8_t uidlen, uint8_t *signature, int signature_len) {
|
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);
|
int index = originality_check_verify(uid, uidlen, signature, signature_len, PK_MFP);
|
||||||
PrintAndLogEx(NORMAL, "");
|
|
||||||
return originality_check_print(signature, signature_len, index);
|
return originality_check_print(signature, signature_len, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1417,7 +1417,6 @@ static int ulev1_print_signature(uint64_t tagtype, uint8_t *uid, uint8_t *signat
|
||||||
} else if (signature_len == 48) {
|
} else if (signature_len == 48) {
|
||||||
index = originality_check_verify(uid, 7, signature, signature_len, PK_MFULAES);
|
index = originality_check_verify(uid, 7, signature, signature_len, PK_MFULAES);
|
||||||
}
|
}
|
||||||
PrintAndLogEx(NORMAL, "");
|
|
||||||
return originality_check_print(signature, signature_len, index);
|
return originality_check_print(signature, signature_len, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2451,7 +2450,6 @@ static int CmdHF14AMfUInfo(const char *Cmd) {
|
||||||
}
|
}
|
||||||
// check signature
|
// check signature
|
||||||
int index = originality_check_verify_ex(card.uid, 7, signature, sizeof(signature), PK_ST25TN, false, true);
|
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);
|
originality_check_print(signature, sizeof(signature), index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -453,7 +453,7 @@ static int seos_challenge_get(uint8_t *RNDICC, uint8_t RNDICC_len, uint8_t keysl
|
||||||
|
|
||||||
char getChallengePre[21];
|
char getChallengePre[21];
|
||||||
strcpy(getChallengePre, "008700");
|
strcpy(getChallengePre, "008700");
|
||||||
|
|
||||||
// const char keyslot_str[3] = "01";
|
// const char keyslot_str[3] = "01";
|
||||||
//strcat(getChallengePre, keyslot_str);
|
//strcat(getChallengePre, keyslot_str);
|
||||||
snprintf(getChallengePre + strlen(getChallengePre), 3, "%02u", keyslot);
|
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
|
// Response is an ASN.1 encoded structure
|
||||||
// Extract everything before the 8E tag
|
// Extract everything before the 8E tag
|
||||||
|
|
||||||
int res = PM3_EWRONGANSWER;
|
int res = PM3_EWRONGANSWER;
|
||||||
for (int i = 0; i < response_length; i++) {
|
for (int i = 0; i < response_length; i++) {
|
||||||
// extract MAC
|
// extract MAC
|
||||||
if (response[i] == 0x8E) {
|
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) {
|
if (res != PM3_SUCCESS) {
|
||||||
goto out;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------- MAC Key Generation -----------------
|
// ----------------- 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, "Supp MAC......................... " _YELLOW_("%s"), sprint_hex_inrow(MAC_value, MAC_value_len));
|
||||||
// PrintAndLogEx(INFO, "Calc MAC......................... " _YELLOW_("%s"), sprint_hex_inrow(cmac, sizeof(cmac)));
|
// PrintAndLogEx(INFO, "Calc MAC......................... " _YELLOW_("%s"), sprint_hex_inrow(cmac, sizeof(cmac)));
|
||||||
|
|
||||||
out:
|
|
||||||
PrintAndLogEx(INFO, "--- " _CYAN_("MAC") " ---------------------------");
|
PrintAndLogEx(INFO, "--- " _CYAN_("MAC") " ---------------------------");
|
||||||
PrintAndLogEx(ERR, _RED_("MAC Verification Failed"));
|
PrintAndLogEx(ERR, _RED_("MAC Verification Failed"));
|
||||||
return PM3_ESOFT;
|
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];
|
uint8_t response[PM3_CMD_DATA_SIZE];
|
||||||
|
|
||||||
// ---------------- Diversify Keys ----------------
|
// ---------------- Diversify Keys ----------------
|
||||||
uint8_t undiversified_key[16] = { 0x00 };
|
uint8_t mk[16] = { 0x00 };
|
||||||
memcpy(undiversified_key, keys[key_index].readKey, 16);
|
memcpy(mk, keys[key_index].readKey, 16);
|
||||||
|
|
||||||
uint8_t keyslot = 0x01; // up to 0x0F
|
uint8_t keyslot = 0x01; // up to 0x0F
|
||||||
uint8_t AES_key[24] = {0x00};
|
uint8_t AES_key[24] = {0x00};
|
||||||
uint8_t MAC_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;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
seos_kdf(true, undiversified_key, keyslot, adfOID, sizeof(adfOID), CRYPTOGRAM_Diversifier, diversifier_len, AES_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, undiversified_key, keyslot, adfOID, sizeof(adfOID), CRYPTOGRAM_Diversifier, diversifier_len, MAC_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(&MAC_key[16], &MAC_key[0], 8);
|
||||||
memcpy(&AES_key[16], &AES_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 :)
|
// if we made it here, its a success and we break :)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (i == ARRAYLEN(known_AID_map)) {
|
||||||
|
return PM3_ESOFT;
|
||||||
|
}
|
||||||
return res;
|
return res;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1668,7 +1668,7 @@ static int CmdHfSeosSAM(const char *Cmd) {
|
||||||
data[0] = flags;
|
data[0] = flags;
|
||||||
|
|
||||||
int cmdlen = 0;
|
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);
|
CLIParserFree(ctx);
|
||||||
return PM3_ESOFT;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
|
@ -1680,7 +1680,7 @@ static int CmdHfSeosSAM(const char *Cmd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
SendCommandNG(CMD_HF_SAM_SEOS, data, cmdlen+1);
|
SendCommandNG(CMD_HF_SAM_SEOS, data, cmdlen + 1);
|
||||||
PacketResponseNG resp;
|
PacketResponseNG resp;
|
||||||
if (WaitForResponseTimeout(CMD_HF_SAM_SEOS, &resp, 4000) == false) {
|
if (WaitForResponseTimeout(CMD_HF_SAM_SEOS, &resp, 4000) == false) {
|
||||||
PrintAndLogEx(WARNING, "SAM timeout");
|
PrintAndLogEx(WARNING, "SAM timeout");
|
||||||
|
|
|
@ -150,7 +150,6 @@ static void print_st25ta_system_info(uint8_t *d, uint8_t n) {
|
||||||
|
|
||||||
static int print_st25ta_signature(uint8_t *uid, uint8_t *signature) {
|
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);
|
int index = originality_check_verify_ex(uid, 7, signature, 32, PK_ST25TA, false, true);
|
||||||
PrintAndLogEx(NORMAL, "");
|
|
||||||
return originality_check_print(signature, 32, index);
|
return originality_check_print(signature, 32, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -136,25 +136,28 @@ const ecdsa_publickey_ng_t manufacturer_public_keys[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// return pk if match index else -1
|
// returns index of pk if match else -1
|
||||||
int originality_check_verify(uint8_t *data, uint8_t data_len, uint8_t *signature, uint8_t signature_len, pk_type_t type) {
|
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);
|
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) {
|
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;
|
bool is_zero = true;
|
||||||
for (uint8_t i = 0; i < signature_len; i++) {
|
for (uint8_t i = 0; i < signature_len; i++) {
|
||||||
if (signature[i] != 0) {
|
if (signature[i] != 0) {
|
||||||
is_zero = false;
|
is_zero = false;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_zero) {
|
if (is_zero) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t tmp_data[data_len];
|
uint8_t tmp_data[data_len];
|
||||||
uint8_t tmp_signature[signature_len];
|
uint8_t tmp_signature[signature_len];
|
||||||
|
|
||||||
if (reverse) {
|
if (reverse) {
|
||||||
reverse_array_copy(data, data_len, tmp_data);
|
reverse_array_copy(data, data_len, tmp_data);
|
||||||
reverse_array_copy(signature, signature_len, tmp_signature);
|
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) {
|
int originality_check_print(uint8_t *signature, int signature_len, int index) {
|
||||||
|
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
|
||||||
if ((index < 0) || (index >= ARRAYLEN(manufacturer_public_keys))) {
|
if ((index < 0) || (index >= ARRAYLEN(manufacturer_public_keys))) {
|
||||||
|
|
||||||
PrintAndLogEx(INFO, " TAG IC Signature: %s", sprint_hex_inrow(signature, 16));
|
PrintAndLogEx(INFO, " TAG IC Signature: %s", sprint_hex_inrow(signature, 16));
|
||||||
if (signature_len > 16) {
|
if (signature_len > 16) {
|
||||||
PrintAndLogEx(INFO, " : %s", sprint_hex_inrow(signature + 16, 16));
|
PrintAndLogEx(INFO, " : %s", sprint_hex_inrow(signature + 16, 16));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (signature_len > 32) {
|
if (signature_len > 32) {
|
||||||
PrintAndLogEx(INFO, " : %s", sprint_hex_inrow(signature + 32, 16));
|
PrintAndLogEx(INFO, " : %s", sprint_hex_inrow(signature + 32, 16));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (signature_len > 48) {
|
if (signature_len > 48) {
|
||||||
PrintAndLogEx(INFO, " : %s", sprint_hex_inrow(signature + 48, signature_len - 48));
|
PrintAndLogEx(INFO, " : %s", sprint_hex_inrow(signature + 48, signature_len - 48));
|
||||||
}
|
}
|
||||||
|
|
||||||
PrintAndLogEx(SUCCESS, " Signature verification: " _RED_("failed"));
|
PrintAndLogEx(SUCCESS, " Signature verification: " _RED_("failed"));
|
||||||
return PM3_ESOFT;
|
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) {
|
if (manufacturer_public_keys[index].keylen > 16) {
|
||||||
PrintAndLogEx(INFO, " : %.32s", manufacturer_public_keys[index].value + 32);
|
PrintAndLogEx(INFO, " : %.32s", manufacturer_public_keys[index].value + 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (manufacturer_public_keys[index].keylen > 32) {
|
if (manufacturer_public_keys[index].keylen > 32) {
|
||||||
PrintAndLogEx(INFO, " : %.32s", manufacturer_public_keys[index].value + 64);
|
PrintAndLogEx(INFO, " : %.32s", manufacturer_public_keys[index].value + 64);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (manufacturer_public_keys[index].keylen > 48) {
|
if (manufacturer_public_keys[index].keylen > 48) {
|
||||||
PrintAndLogEx(INFO, " : %.32s", manufacturer_public_keys[index].value + 96);
|
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, " 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));
|
PrintAndLogEx(INFO, " TAG IC Signature: %s", sprint_hex_inrow(signature, 16));
|
||||||
|
|
||||||
if (signature_len > 16) {
|
if (signature_len > 16) {
|
||||||
PrintAndLogEx(INFO, " : %s", sprint_hex_inrow(signature + 16, 16));
|
PrintAndLogEx(INFO, " : %s", sprint_hex_inrow(signature + 16, 16));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (signature_len > 32) {
|
if (signature_len > 32) {
|
||||||
PrintAndLogEx(INFO, " : %s", sprint_hex_inrow(signature + 32, 16));
|
PrintAndLogEx(INFO, " : %s", sprint_hex_inrow(signature + 32, 16));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (signature_len > 48) {
|
if (signature_len > 48) {
|
||||||
PrintAndLogEx(INFO, " : %s", sprint_hex_inrow(signature + 48, signature_len - 48));
|
PrintAndLogEx(INFO, " : %s", sprint_hex_inrow(signature + 48, signature_len - 48));
|
||||||
}
|
}
|
||||||
|
|
||||||
PrintAndLogEx(SUCCESS, " Signature verification: " _GREEN_("successful"));
|
PrintAndLogEx(SUCCESS, " Signature verification: " _GREEN_("successful"));
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1031,7 +1031,7 @@ int DesfireSelectAndAuthenticateEx(DesfireContext_t *dctx, DesfireSecureChannel
|
||||||
isosw = true;
|
isosw = true;
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
PrintAndLogEx(INFO, "Switch to " _CYAN_("native") " for select");
|
PrintAndLogEx(INFO, "Switch to " _CYAN_("native") " for select");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int res;
|
int res;
|
||||||
|
@ -1055,7 +1055,7 @@ int DesfireSelectAndAuthenticateEx(DesfireContext_t *dctx, DesfireSecureChannel
|
||||||
|
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
PrintAndLogEx(INFO, "App %06x " _GREEN_("selected"), aid);
|
PrintAndLogEx(INFO, "App %06x " _GREEN_("selected"), aid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isosw) {
|
if (isosw) {
|
||||||
|
@ -1124,7 +1124,7 @@ int DesfireSelectAndAuthenticateW(DesfireContext_t *dctx, DesfireSecureChannel s
|
||||||
|
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
PrintAndLogEx(INFO, "Application %s file iso id %04x is " _GREEN_("selected"), DesfireWayIDStr(way, id), isofileid);
|
PrintAndLogEx(INFO, "Application %s file iso id %04x is " _GREEN_("selected"), DesfireWayIDStr(way, id), isofileid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!noauth) {
|
if (!noauth) {
|
||||||
|
|
|
@ -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)
|
if (sector0 == NULL)
|
||||||
return PM3_EINVARG;
|
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"));
|
PrintAndLogEx(SUCCESS, "CRC8...... 0x%02X ( %s )", sector0[16], _GREEN_("ok"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mad_ver == 2 && sector10) {
|
if (mad_ver == 2 && sector16) {
|
||||||
int res2 = madCRCCheck(sector10, true, 2);
|
int res2 = madCRCCheck(sector16, true, 2);
|
||||||
if (res == PM3_SUCCESS)
|
if (res == PM3_SUCCESS)
|
||||||
res = res2;
|
res = res2;
|
||||||
|
|
||||||
if (verbose && !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)
|
// MA (multi-application card)
|
||||||
|
@ -241,27 +241,30 @@ int MADCheck(uint8_t *sector0, uint8_t *sector10, bool verbose, bool *haveMAD2)
|
||||||
return res;
|
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;
|
*madlen = 0;
|
||||||
bool haveMAD2 = false;
|
bool haveMAD2 = false;
|
||||||
int res = MADCheck(sector0, sector10, false, &haveMAD2);
|
int res = MADCheck(sector0, sector16, false, &haveMAD2);
|
||||||
if (res != PM3_SUCCESS) {
|
if (res != PM3_SUCCESS) {
|
||||||
PrintAndLogEx(WARNING, "Not a valid MAD");
|
PrintAndLogEx(WARNING, "Not a valid MAD");
|
||||||
return res;
|
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);
|
mad[*madlen] = madGetAID(sector0, swapmad, 1, i);
|
||||||
(*madlen)++;
|
(*madlen)++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (haveMAD2) {
|
if (haveMAD2) {
|
||||||
// mad2 sector (0x10 == 16dec) here
|
// mad2 sector (0x10 == 16) here
|
||||||
mad[*madlen] = 0x0005;
|
mad[*madlen] = 0x0005;
|
||||||
(*madlen)++;
|
(*madlen)++;
|
||||||
|
|
||||||
|
// 7 + 8 + 8 == 23
|
||||||
for (int i = 1; i < 24; i++) {
|
for (int i = 1; i < 24; i++) {
|
||||||
mad[*madlen] = madGetAID(sector10, swapmad, 2, i);
|
mad[*madlen] = madGetAID(sector16, swapmad, 2, i);
|
||||||
|
|
||||||
(*madlen)++;
|
(*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 sector0[MFBLOCK_SIZE * 4] = {0};
|
||||||
uint8_t sector10[MFBLOCK_SIZE * 4] = {0};
|
uint8_t sector16[MFBLOCK_SIZE * 4] = {0};
|
||||||
|
|
||||||
memcpy(sector0, in, sizeof(sector0));
|
memcpy(sector0, in, sizeof(sector0));
|
||||||
if (ilen == MIFARE_4K_MAX_BYTES) {
|
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};
|
uint16_t mad[7 + 8 + 8 + 8 + 8] = {0};
|
||||||
size_t madlen = 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");
|
PrintAndLogEx(ERR, "can't decode MAD");
|
||||||
return PM3_ESOFT;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,8 +21,8 @@
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
int MADCheck(uint8_t *sector0, uint8_t *sector10, bool verbose, bool *haveMAD2);
|
int MADCheck(uint8_t *sector0, uint8_t *sector16, bool verbose, bool *haveMAD2);
|
||||||
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);
|
||||||
int MAD1DecodeAndPrint(uint8_t *sector, bool swapmad, bool verbose, bool *haveMAD2);
|
int MAD1DecodeAndPrint(uint8_t *sector, bool swapmad, bool verbose, bool *haveMAD2);
|
||||||
int MAD2DecodeAndPrint(uint8_t *sector, bool swapmad, bool verbose);
|
int MAD2DecodeAndPrint(uint8_t *sector, bool swapmad, bool verbose);
|
||||||
int MADDFDecodeAndPrint(uint32_t short_aid, bool verbose);
|
int MADDFDecodeAndPrint(uint32_t short_aid, bool verbose);
|
||||||
|
|
|
@ -1036,19 +1036,25 @@ int mf_write_sector(uint8_t sectorNo, uint8_t keyType, const uint8_t *key, uint8
|
||||||
|
|
||||||
// EMULATOR
|
// EMULATOR
|
||||||
int mf_eml_get_mem(uint8_t *data, int blockNum, int blocksCount) {
|
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) {
|
if (size > PM3_CMD_DATA_SIZE) {
|
||||||
return PM3_ESOFT;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
uint8_t blockno;
|
uint16_t blockno;
|
||||||
uint8_t blockcnt;
|
uint8_t blockcnt;
|
||||||
|
uint8_t blockwidth;
|
||||||
} PACKED payload;
|
} PACKED payload;
|
||||||
|
|
||||||
payload.blockno = blockNum;
|
payload.blockno = blockNum;
|
||||||
payload.blockcnt = blocksCount;
|
payload.blockcnt = blocksCount;
|
||||||
|
payload.blockwidth = blockBtWidth;
|
||||||
|
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
SendCommandNG(CMD_HF_MIFARE_EML_MEMGET, (uint8_t *)&payload, sizeof(payload));
|
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;
|
return PM3_ETIMEOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (resp.status == PM3_SUCCESS)
|
if (resp.status == PM3_SUCCESS) {
|
||||||
memcpy(data, resp.data.asBytes, size);
|
memcpy(data, resp.data.asBytes, size);
|
||||||
|
}
|
||||||
|
|
||||||
return resp.status;
|
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) {
|
int mf_eml_set_mem_xt(uint8_t *data, int blockNum, int blocksCount, int blockBtWidth) {
|
||||||
|
|
||||||
struct p {
|
struct p {
|
||||||
uint8_t blockno;
|
uint16_t blockno;
|
||||||
uint8_t blockcnt;
|
uint8_t blockcnt;
|
||||||
uint8_t blockwidth;
|
uint8_t blockwidth;
|
||||||
uint8_t data[];
|
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) {
|
if (!isOK) {
|
||||||
|
|
||||||
uint8_t reason = (resp.oldarg[1] & 0xFF);
|
uint8_t reason = (resp.oldarg[1] & 0xFF);
|
||||||
if ( reason == 4) {
|
if (reason == 4) {
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(WARNING, "GDM magic write signature block failed");
|
PrintAndLogEx(WARNING, "GDM magic write signature block failed");
|
||||||
} else if (reason == 5) {
|
} else if (reason == 5) {
|
||||||
|
|
|
@ -92,6 +92,7 @@ int mf_write_block(uint8_t blockno, uint8_t keyType, const uint8_t *key, uint8_t
|
||||||
int mf_write_sector(uint8_t sectorNo, uint8_t keyType, const uint8_t *key, uint8_t *sector);
|
int mf_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(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_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);
|
int mf_eml_set_mem_xt(uint8_t *data, int blockNum, int blocksCount, int blockBtWidth);
|
||||||
|
|
||||||
|
|
|
@ -883,7 +883,7 @@ static bool Pack_H800002(int format_idx, wiegand_card_t *card,
|
||||||
memset(packed, 0, sizeof(wiegand_message_t));
|
memset(packed, 0, sizeof(wiegand_message_t));
|
||||||
|
|
||||||
if (!validate_card_limit(format_idx, card)) {
|
if (!validate_card_limit(format_idx, card)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
packed->Length = 46;
|
packed->Length = 46;
|
||||||
|
@ -896,7 +896,7 @@ static bool Pack_H800002(int format_idx, wiegand_card_t *card,
|
||||||
// Invert parity for setting odd parity
|
// Invert parity for setting odd parity
|
||||||
set_bit_by_position(packed, even_parity ^ 1, 45);
|
set_bit_by_position(packed, even_parity ^ 1, 45);
|
||||||
if (preamble) {
|
if (preamble) {
|
||||||
return add_HID_header(packed);
|
return add_HID_header(packed);
|
||||||
}
|
}
|
||||||
return true;
|
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));
|
memset(card, 0, sizeof(wiegand_card_t));
|
||||||
|
|
||||||
if (packed->Length != 46) {
|
if (packed->Length != 46) {
|
||||||
return false; // Wrong length? Stop here.
|
return false; // Wrong length? Stop here.
|
||||||
}
|
}
|
||||||
|
|
||||||
card->FacilityCode = get_linear_field(packed, 1, 14);
|
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) {
|
static bool validate_card_limit(int format_idx, wiegand_card_t *card) {
|
||||||
cardformatdescriptor_t card_descriptor = FormatTable[format_idx].Fields;
|
cardformatdescriptor_t card_descriptor = FormatTable[format_idx].Fields;
|
||||||
return !((card->FacilityCode > card_descriptor.MaxFC) ||
|
return !((card->FacilityCode > card_descriptor.MaxFC) ||
|
||||||
(card->CardNumber > card_descriptor.MaxCN)||
|
(card->CardNumber > card_descriptor.MaxCN) ||
|
||||||
(card->IssueLevel > card_descriptor.MaxIL) ||
|
(card->IssueLevel > card_descriptor.MaxIL) ||
|
||||||
(card->OEM > card_descriptor.MaxOEM));
|
(card->OEM > card_descriptor.MaxOEM));
|
||||||
}
|
}
|
||||||
|
@ -1586,7 +1586,7 @@ bool HIDTryUnpack(wiegand_message_t *packed) {
|
||||||
if (found_cnt) {
|
if (found_cnt) {
|
||||||
PrintAndLogEx(INFO, "found %u matching format%c with bit len %d", found_cnt, (found_cnt > 1) ? 's' : ' ', packed->Length);
|
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
|
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(WARNING, "Wiegand unknown bit len %d", packed->Length);
|
||||||
PrintAndLogEx(HINT, "Try 0xFFFF's http://cardinfo.barkweb.com.au/");
|
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
|
// 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_wiegand(uint32_t top, uint32_t mid, uint32_t bot, int n) {
|
||||||
bool decode_result;
|
bool decode_result;
|
||||||
|
|
||||||
if (top == 0 && mid == 0 && bot == 0) {
|
if (top == 0 && mid == 0 && bot == 0) {
|
||||||
decode_result = false;
|
decode_result = false;
|
||||||
} else if ((n > 0) || ((mid & 0xFFFFFFC0) > 0)) { // if n > 0 or there's more than 38 bits
|
} else if ((n > 0) || ((mid & 0xFFFFFFC0) > 0)) { // if n > 0 or there's more than 38 bits
|
||||||
|
|
|
@ -134,7 +134,7 @@ static uint8_t get_length_from_header(wiegand_message_t *data) {
|
||||||
* Right now we just calculate the highest bit set
|
* Right now we just calculate the highest bit set
|
||||||
* 38 bits format is handled by directly setting n=38 in initialize_message_object()
|
* 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)
|
* 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)
|
* (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 01xx xxxx xxxx xxxx xxxx xxxx xxxx 26-bit
|
||||||
* 0000 0010 0000 0000 1xxx xxxx xxxx xxxx xxxx xxxx xxxx 27-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
|
if ((data->Top & 0x000FFFFF) > 0) { // > 64 bits
|
||||||
hfmt = data->Top & 0x000FFFFF;
|
hfmt = data->Top & 0x000FFFFF;
|
||||||
len = 64;
|
len = 64;
|
||||||
} else if (data->Mid > 0) {
|
} else if (data->Mid > 0) {
|
||||||
// detect HID format b38 set
|
// detect HID format b38 set
|
||||||
if (data->Mid & 0xFFFFFFC0) { // 39-64 bits
|
if (data->Mid & 0xFFFFFFC0) { // 39-64 bits
|
||||||
hfmt = data->Mid;
|
hfmt = data->Mid;
|
||||||
|
@ -165,14 +165,14 @@ static uint8_t get_length_from_header(wiegand_message_t *data) {
|
||||||
PrintAndLogEx(DEBUG, "hid preamble detected");
|
PrintAndLogEx(DEBUG, "hid preamble detected");
|
||||||
|
|
||||||
// if bit 38 is set: => 26-36 bits
|
// 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
|
hfmt = (((data->Mid & 31) << 12) | (data->Bot >> 26)); //get bits 27-37 to check for format len bit
|
||||||
len = 19;
|
len = 19;
|
||||||
} else { // if bit 38 is not set => 37 bits
|
} else { // if bit 38 is not set => 37 bits
|
||||||
hfmt = 0;
|
hfmt = 0;
|
||||||
len = 37;
|
len = 37;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
hfmt = data->Bot;
|
hfmt = data->Bot;
|
||||||
len = 0;
|
len = 0;
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
#include "commonutil.h"
|
#include "commonutil.h"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include "stdbool.h"
|
||||||
|
|
||||||
/* Similar to FpgaGatherVersion this formats stored version information
|
/* Similar to FpgaGatherVersion this formats stored version information
|
||||||
* into a string representation. It takes a pointer to the struct version_information_t,
|
* 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
|
// 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];
|
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[i] = data[i + 1];
|
||||||
}
|
}
|
||||||
data[len - 1] = first;
|
data[n - 1] = first;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rotate Right - Ultralight, Desfire
|
// Rotate Right - Ultralight, Desfire
|
||||||
void ror(uint8_t *data, const size_t len) {
|
void ror(uint8_t *data, const size_t n) {
|
||||||
uint8_t last = data[len - 1];
|
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[i] = data[i - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
data[0] = last;
|
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) {
|
void lsl(uint8_t *data, size_t len) {
|
||||||
for (size_t n = 0; n < len - 1; n++) {
|
for (size_t n = 0; n < len - 1; n++) {
|
||||||
|
|
|
@ -128,8 +128,9 @@ void Uint7byteToMemBe(uint8_t *data, uint64_t value);
|
||||||
void Uint8byteToMemBe(uint8_t *data, uint64_t value);
|
void Uint8byteToMemBe(uint8_t *data, uint64_t value);
|
||||||
|
|
||||||
// rotate left byte array
|
// rotate left byte array
|
||||||
void rol(uint8_t *data, const size_t len);
|
void rol(uint8_t *data, const size_t n);
|
||||||
void ror(uint8_t *data, const size_t len);
|
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);
|
void lsl(uint8_t *data, size_t len);
|
||||||
uint32_t le24toh(const uint8_t data[3]);
|
uint32_t le24toh(const uint8_t data[3]);
|
||||||
|
|
|
@ -321,11 +321,11 @@ static int asn1_get_sequence_of_cb(void *ctx,
|
||||||
cb_ctx->cur;
|
cb_ctx->cur;
|
||||||
|
|
||||||
if (cur->buf.p != NULL) {
|
if (cur->buf.p != NULL) {
|
||||||
cur->next =
|
cur->next = mbedtls_calloc(1, sizeof(mbedtls_asn1_sequence));
|
||||||
mbedtls_calloc(1, sizeof(mbedtls_asn1_sequence));
|
|
||||||
|
|
||||||
if (cur->next == NULL)
|
if (cur->next == NULL) {
|
||||||
return (MBEDTLS_ERR_ASN1_ALLOC_FAILED);
|
return (MBEDTLS_ERR_ASN1_ALLOC_FAILED);
|
||||||
|
}
|
||||||
|
|
||||||
cur = cur->next;
|
cur = cur->next;
|
||||||
}
|
}
|
||||||
|
|
|
@ -180,8 +180,7 @@ int mbedtls_cipher_cmac_starts(mbedtls_cipher_context_t *ctx,
|
||||||
if (ctx == NULL || ctx->cipher_info == NULL || key == NULL)
|
if (ctx == NULL || ctx->cipher_info == NULL || key == NULL)
|
||||||
return (MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA);
|
return (MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA);
|
||||||
|
|
||||||
if ((retval = mbedtls_cipher_setkey(ctx, key, (int)keybits,
|
if ((retval = mbedtls_cipher_setkey(ctx, key, (int)keybits, MBEDTLS_ENCRYPT)) != 0)
|
||||||
MBEDTLS_ENCRYPT)) != 0)
|
|
||||||
return (retval);
|
return (retval);
|
||||||
|
|
||||||
type = ctx->cipher_info->type;
|
type = ctx->cipher_info->type;
|
||||||
|
@ -405,14 +404,12 @@ int mbedtls_aes_cmac_prf_128(const unsigned char *key, size_t key_length,
|
||||||
} else {
|
} else {
|
||||||
memset(zero_key, 0, MBEDTLS_AES_BLOCK_SIZE);
|
memset(zero_key, 0, MBEDTLS_AES_BLOCK_SIZE);
|
||||||
|
|
||||||
ret = mbedtls_cipher_cmac(cipher_info, zero_key, 128, key,
|
ret = mbedtls_cipher_cmac(cipher_info, zero_key, 128, key, key_length, int_key);
|
||||||
key_length, int_key);
|
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = mbedtls_cipher_cmac(cipher_info, int_key, 128, input, in_len,
|
ret = mbedtls_cipher_cmac(cipher_info, int_key, 128, input, in_len, output);
|
||||||
output);
|
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
mbedtls_platform_zeroize(int_key, sizeof(int_key));
|
mbedtls_platform_zeroize(int_key, sizeof(int_key));
|
||||||
|
|
|
@ -920,7 +920,7 @@
|
||||||
},
|
},
|
||||||
"emv help": {
|
"emv help": {
|
||||||
"command": "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": [
|
"notes": [
|
||||||
"emv list --frame -> show frame delay times",
|
"emv list --frame -> show frame delay times",
|
||||||
"emv list -1 -> use trace buffer"
|
"emv list -1 -> use trace buffer"
|
||||||
|
@ -1025,11 +1025,11 @@
|
||||||
"offline": false,
|
"offline": false,
|
||||||
"options": [
|
"options": [
|
||||||
"-h, --help This help",
|
"-h, --help This help",
|
||||||
"-t, --selftest Self test",
|
"--test Perform self tests",
|
||||||
"-a, --apdu Show APDU requests and responses",
|
"-a, --apdu Show APDU requests and responses",
|
||||||
"-w, --wired Send data via contact (iso7816) interface. (def: Contactless interface)"
|
"-w, --wired Send data via contact (iso7816) interface. (def: Contactless interface)"
|
||||||
],
|
],
|
||||||
"usage": "emv roca [-htaw]"
|
"usage": "emv roca [-haw] [--test]"
|
||||||
},
|
},
|
||||||
"emv scan": {
|
"emv scan": {
|
||||||
"command": "emv scan",
|
"command": "emv scan",
|
||||||
|
@ -1410,19 +1410,19 @@
|
||||||
"hf 14a simaid -t 3 -> MIFARE Desfire",
|
"hf 14a simaid -t 3 -> MIFARE Desfire",
|
||||||
"hf 14a simaid -t 4 -> ISO/IEC 14443-4",
|
"hf 14a simaid -t 4 -> ISO/IEC 14443-4",
|
||||||
"hf 14a simaid -t 11 -> Javacard (JCOP)",
|
"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 --aid a000000000000000000000 --selectaid_response 9000 --getdata_response 9000 -> Custom AID and responses",
|
||||||
"hf 14a simaid -t 3 --rats 05788172220101 --response 01009000 --apdu 86009000 -> Custom RATS Added",
|
"hf 14a simaid -t 3 --ats 0578817222 --selectaid_response 01009000 --getdata_response 86009000 -> Custom ATS and responses",
|
||||||
"hf 14a simaid -t 3 --rats 05788172220101 -x -> Enumerate AID Values"
|
"hf 14a simaid -t 3 --ats 0578817222 -x -> Enumerate AID Values"
|
||||||
],
|
],
|
||||||
"offline": false,
|
"offline": false,
|
||||||
"options": [
|
"options": [
|
||||||
"-h, --help This help",
|
"-h, --help This help",
|
||||||
"-t, --type <1-12> Simulation type to use",
|
"-t, --type <1-12> Simulation type to use",
|
||||||
"-u, --uid <hex> <4|7|10> hex bytes UID",
|
"-u, --uid <hex> <4|7|10> hex bytes UID",
|
||||||
"-r, --rats <hex> <0-20> hex bytes RATS",
|
"-r, --ats <hex> <0-20> hex bytes ATS",
|
||||||
"-a, --aid <hex> <0-100> hex bytes for AID to respond to (Default: A000000000000000000000)",
|
"-a, --aid <hex> <0-30> hex bytes for AID to respond to (Default: A000000000000000000000)",
|
||||||
"-e, --response <hex> <0-100> hex bytes for APDU Response to AID Select (Default: 9000)",
|
"-e, --selectaid_response <hex> <0-100> hex bytes for APDU Response to AID Select (Default: 9000)",
|
||||||
"-p, --apdu <hex> <0-100> hex bytes for APDU Response to Get Data request after AID (Default: 9000)",
|
"-p, --getdata_response <hex> <0-100> hex bytes for APDU Response to Get Data request after AID (Default: 9000)",
|
||||||
"-x, --enumerate Enumerate all AID values via returning Not Found and print them to console"
|
"-x, --enumerate Enumerate all AID values via returning Not Found and print them to console"
|
||||||
],
|
],
|
||||||
"usage": "hf 14a simaid [-hx] -t <1-12> [-u <hex>] [-r <hex>] [-a <hex>] [-e <hex>] [-p <hex>]"
|
"usage": "hf 14a simaid [-hx] -t <1-12> [-u <hex>] [-r <hex>] [-a <hex>] [-e <hex>] [-p <hex>]"
|
||||||
|
@ -3657,14 +3657,23 @@
|
||||||
"command": "hf iclass sam",
|
"command": "hf iclass sam",
|
||||||
"description": "Extract PACS via a HID SAM",
|
"description": "Extract PACS via a HID SAM",
|
||||||
"notes": [
|
"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,
|
"offline": false,
|
||||||
"options": [
|
"options": [
|
||||||
"-h, --help This help",
|
"-h, --help This help",
|
||||||
"-v, --verbose verbose output"
|
"-v, --verbose verbose output",
|
||||||
|
"-k, --keep keep the field active after command executed",
|
||||||
|
"-n, --nodetect skip selecting the card and sending card details to SAM",
|
||||||
|
"-t, --tlv decode TLV",
|
||||||
|
"--break-on-nr-mac stop tag interaction on nr-mac",
|
||||||
|
"-p, --prevent-epurse-update fake epurse update",
|
||||||
|
"--shallow shallow mod",
|
||||||
|
"-d, --data <hex> DER encoded command to send to SAM"
|
||||||
],
|
],
|
||||||
"usage": "hf iclass sam [-hv]"
|
"usage": "hf iclass sam [-hvkntp] [--break-on-nr-mac] [--shallow] [-d <hex>]..."
|
||||||
},
|
},
|
||||||
"hf iclass sim": {
|
"hf iclass sim": {
|
||||||
"command": "hf iclass sim",
|
"command": "hf iclass sim",
|
||||||
|
@ -4486,12 +4495,13 @@
|
||||||
"-f, --file <fn> Specify a filename for dump file",
|
"-f, --file <fn> Specify a filename for dump file",
|
||||||
"--mini MIFARE Classic Mini / S20",
|
"--mini MIFARE Classic Mini / S20",
|
||||||
"--1k MIFARE Classic 1k / S50 (def)",
|
"--1k MIFARE Classic 1k / S50 (def)",
|
||||||
|
"--1k+ MIFARE Classic Ev1 1k / S50",
|
||||||
"--2k MIFARE Classic/Plus 2k",
|
"--2k MIFARE Classic/Plus 2k",
|
||||||
"--4k MIFARE Classic 4k / S70",
|
"--4k MIFARE Classic 4k / S70",
|
||||||
"--emu from emulator memory",
|
"--emu from emulator memory",
|
||||||
"--gdm use gdm alt (20/23) magic wakeup"
|
"--gdm use gdm alt (20/23) magic wakeup"
|
||||||
],
|
],
|
||||||
"usage": "hf mf cload [-h] [-f <fn>] [--mini] [--1k] [--2k] [--4k] [--emu] [--gdm]"
|
"usage": "hf mf cload [-h] [-f <fn>] [--mini] [--1k] [--1k+] [--2k] [--4k] [--emu] [--gdm]"
|
||||||
},
|
},
|
||||||
"hf mf csave": {
|
"hf mf csave": {
|
||||||
"command": "hf mf csave",
|
"command": "hf mf csave",
|
||||||
|
@ -7693,7 +7703,7 @@
|
||||||
"description": "Extract PACS via a HID SAM",
|
"description": "Extract PACS via a HID SAM",
|
||||||
"notes": [
|
"notes": [
|
||||||
"hf seos sam",
|
"hf seos sam",
|
||||||
"hd seos sam -d a005a103800104 -> get PACS data"
|
"hf seos sam -d a005a103800104 -> get PACS data"
|
||||||
],
|
],
|
||||||
"offline": false,
|
"offline": false,
|
||||||
"options": [
|
"options": [
|
||||||
|
@ -9851,8 +9861,8 @@
|
||||||
"command": "lf hitag chk",
|
"command": "lf hitag chk",
|
||||||
"description": "Run dictionary key or password recovery against Hitag card.",
|
"description": "Run dictionary key or password recovery against Hitag card.",
|
||||||
"notes": [
|
"notes": [
|
||||||
"lf hitag chk",
|
"lf hitag chk -> checks for both pwd / crypto keys",
|
||||||
"-> checks for both pwd / crypto keyslf hitag chk --crypto -> use def dictionary",
|
"lf hitag chk --crypto -> use def dictionary",
|
||||||
"lf hitag chk --pwd -f my.dic -> pwd mode, custom dictionary"
|
"lf hitag chk --pwd -f my.dic -> pwd mode, custom dictionary"
|
||||||
],
|
],
|
||||||
"offline": false,
|
"offline": false,
|
||||||
|
@ -13202,6 +13212,6 @@
|
||||||
"metadata": {
|
"metadata": {
|
||||||
"commands_extracted": 759,
|
"commands_extracted": 759,
|
||||||
"extracted_by": "PM3Help2JSON v1.00",
|
"extracted_by": "PM3Help2JSON v1.00",
|
||||||
"extracted_on": "2025-01-14T15:42:02"
|
"extracted_on": "2025-02-21T14:36:13"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -150,7 +150,7 @@ Check column "offline" for their availability.
|
||||||
|------- |------- |-----------
|
|------- |------- |-----------
|
||||||
|`emv help `|Y |`This help`
|
|`emv help `|Y |`This help`
|
||||||
|`emv list `|Y |`List ISO7816 history`
|
|`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 challenge `|N |`Generate challenge`
|
||||||
|`emv exec `|N |`Executes EMV contactless transaction`
|
|`emv exec `|N |`Executes EMV contactless transaction`
|
||||||
|`emv genac `|N |`Generate ApplicationCryptogram`
|
|`emv genac `|N |`Generate ApplicationCryptogram`
|
||||||
|
|
|
@ -924,6 +924,9 @@ typedef struct {
|
||||||
// No key available client/pm3: no cryptographic key available.
|
// No key available client/pm3: no cryptographic key available.
|
||||||
#define PM3_ENOKEY -28
|
#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)
|
// No data client/pm3: no data available, no host frame available (not really an error)
|
||||||
#define PM3_ENODATA -98
|
#define PM3_ENODATA -98
|
||||||
// Quit program client: reserved, order to quit the program
|
// Quit program client: reserved, order to quit the program
|
||||||
|
|
|
@ -205,6 +205,12 @@ ISO 7816-4 Basic interindustry commands. For command APDU's.
|
||||||
#define MIFARE_EV1_UIDF1 0x40
|
#define MIFARE_EV1_UIDF1 0x40
|
||||||
#define MIFARE_EV1_UIDF2 0x20
|
#define MIFARE_EV1_UIDF2 0x20
|
||||||
#define MIFARE_EV1_UIDF3 0x60
|
#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_WRITE 0xA2
|
||||||
#define MIFARE_ULC_COMP_WRITE 0xA0
|
#define MIFARE_ULC_COMP_WRITE 0xA0
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue