mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-22 06:13:51 -07:00
next steps
This commit is contained in:
parent
c03e15b553
commit
6d82079c0b
1 changed files with 317 additions and 2 deletions
|
@ -29,9 +29,290 @@
|
||||||
#include "iso7816/apduinfo.h" // GetAPDUCodeDescription
|
#include "iso7816/apduinfo.h" // GetAPDUCodeDescription
|
||||||
#include "commonutil.h" // get_sw
|
#include "commonutil.h" // get_sw
|
||||||
#include "protocols.h" // ISO7816 APDU return codes
|
#include "protocols.h" // ISO7816 APDU return codes
|
||||||
|
#include "mifare/mifaredefault.h" // AES_KEY_LEN
|
||||||
|
#include <mbedtls/aes.h>
|
||||||
|
#include <mbedtls/cmac.h>
|
||||||
|
//#include <mbedtls/entropy.h>
|
||||||
|
#include <mbedtls/error.h>
|
||||||
|
|
||||||
static int CmdHelp(const char *Cmd);
|
static int CmdHelp(const char *Cmd);
|
||||||
|
|
||||||
|
|
||||||
|
// missing
|
||||||
|
#define ICT_DESFIRE_FILEKEY "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
|
||||||
|
#define ICT_DESFIRE_MASTER_APPKEY "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
|
||||||
|
#define ICT_BLE_DEFAULT_BASE_KEY "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
|
||||||
|
|
||||||
|
#define ICT_MIFARE_A_KEY "\x9c\x28\xa6\x0f\x72\x49"
|
||||||
|
#define ICT_MIFARE_B_KEY "\xc9\x82\x6a\xf0\x27\x94"
|
||||||
|
#define ICT_MIFARE_SECTOR 14
|
||||||
|
#define ICT_APP_ID 0x1023f5
|
||||||
|
#define ICT_REV_APP_ID 0xf52310
|
||||||
|
#define ICT_FILE_ID 0
|
||||||
|
#define ICT_FILE_SIZE 128
|
||||||
|
|
||||||
|
#define ICT_CT_DESFIRE 0
|
||||||
|
#define ICT_CT_CLASSIC 1
|
||||||
|
#define ICT_CT_NFC 2
|
||||||
|
|
||||||
|
static int derive_ble_key(uint8_t *unique_data, uint8_t len, uint8_t *app_key) {
|
||||||
|
|
||||||
|
if (unique_data == NULL || app_key == NULL) {
|
||||||
|
return PM3_EINVARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t input[1 + len];
|
||||||
|
input[0] = 0x01;
|
||||||
|
memcpy(input + 1, unique_data, len);
|
||||||
|
|
||||||
|
uint8_t mac[16];
|
||||||
|
memset(mac, 0x00, 16);
|
||||||
|
|
||||||
|
uint8_t key[AES_KEY_LEN];
|
||||||
|
memcpy(key, ICT_BLE_DEFAULT_BASE_KEY, sizeof(key));
|
||||||
|
|
||||||
|
// NIST 800-38B
|
||||||
|
mbedtls_aes_cmac_prf_128(key, MBEDTLS_AES_BLOCK_SIZE, input, sizeof(input), mac);
|
||||||
|
|
||||||
|
memcpy(app_key, mac, sizeof(mac));
|
||||||
|
return PM3_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int derive_app_key(uint8_t *uid, uint8_t *app_key) {
|
||||||
|
if (uid == NULL || app_key == NULL) {
|
||||||
|
return PM3_EINVARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
c = b'\x88' + uid
|
||||||
|
ch, cl = c[0:4], c[4:8]
|
||||||
|
payload = (ch + cl + cl + ch) * 2
|
||||||
|
AES.new(ICT_DESFIRE_MASTER_APPKEY, AES.MODE_CBC, iv=b'\0'*16).decrypt(payload)[16:]
|
||||||
|
*/
|
||||||
|
uint8_t input[] = {0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||||
|
memcpy(input + 1, uid, 7);
|
||||||
|
|
||||||
|
// uint32_t ch = bytes_to_num(input, 4);
|
||||||
|
// uint32_t cl = bytes_to_num(input + 4, 4);
|
||||||
|
// uint64_t payload = ((2 * ch) + (2 * cl) * 2);
|
||||||
|
|
||||||
|
uint8_t key[AES_KEY_LEN];
|
||||||
|
memcpy(key, ICT_DESFIRE_MASTER_APPKEY, AES_KEY_LEN);
|
||||||
|
|
||||||
|
uint8_t iv[16] = {0};
|
||||||
|
mbedtls_aes_context aes;
|
||||||
|
mbedtls_aes_init(&aes);
|
||||||
|
if (mbedtls_aes_setkey_enc(&aes, key, 128)) {
|
||||||
|
return PM3_ESOFT;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t output[8];
|
||||||
|
if (mbedtls_aes_crypt_cbc(&aes, MBEDTLS_AES_DECRYPT, sizeof(input), iv, input, output)) {
|
||||||
|
return PM3_ESOFT;
|
||||||
|
}
|
||||||
|
mbedtls_aes_free(&aes);
|
||||||
|
memcpy(app_key, output, sizeof(output));
|
||||||
|
return PM3_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Might miss payload..
|
||||||
|
static int diversify_mifare_key(uint8_t *uid, uint8_t *app_key) {
|
||||||
|
if (uid == NULL || app_key == NULL) {
|
||||||
|
return PM3_EINVARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t input[8];
|
||||||
|
memcpy(input, uid, 4);
|
||||||
|
|
||||||
|
uint32_t big = bytes_to_num(uid, 4);
|
||||||
|
big ^= 0xFFFFFFFF;
|
||||||
|
num_to_bytes(big, 4, input + 4);
|
||||||
|
|
||||||
|
uint8_t key[AES_KEY_LEN];
|
||||||
|
// memcpy(key, ICT_DESFIRE_FILEKEY, AES_KEY_LEN);
|
||||||
|
|
||||||
|
uint8_t iv[16] = {0};
|
||||||
|
mbedtls_aes_context aes;
|
||||||
|
mbedtls_aes_init(&aes);
|
||||||
|
if (mbedtls_aes_setkey_enc(&aes, key, 128)) {
|
||||||
|
return PM3_ESOFT;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t output[8];
|
||||||
|
if (mbedtls_aes_crypt_cbc(&aes, MBEDTLS_AES_DECRYPT, sizeof(input), iv, input, output)) {
|
||||||
|
return PM3_ESOFT;
|
||||||
|
}
|
||||||
|
mbedtls_aes_free(&aes);
|
||||||
|
memcpy(app_key, output, sizeof(output));
|
||||||
|
return PM3_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int decrypt_card_sector(uint8_t *uid, uint8_t *sector_data, uint8_t len, uint8_t *plain) {
|
||||||
|
if (uid == NULL || sector_data == NULL || plain == NULL) {
|
||||||
|
return PM3_EINVARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t input[len];
|
||||||
|
memcpy(input, sector_data, len);
|
||||||
|
|
||||||
|
uint8_t key[AES_KEY_LEN];
|
||||||
|
diversify_mifare_key(uid, key);
|
||||||
|
|
||||||
|
uint8_t iv[16] = {0};
|
||||||
|
mbedtls_aes_context aes;
|
||||||
|
mbedtls_aes_init(&aes);
|
||||||
|
if (mbedtls_aes_setkey_enc(&aes, key, 128)) {
|
||||||
|
return PM3_ESOFT;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t output[len];
|
||||||
|
if (mbedtls_aes_crypt_cbc(&aes, MBEDTLS_AES_DECRYPT, sizeof(input), iv, input, output)) {
|
||||||
|
return PM3_ESOFT;
|
||||||
|
}
|
||||||
|
mbedtls_aes_free(&aes);
|
||||||
|
|
||||||
|
memcpy(plain, output, sizeof(output));
|
||||||
|
return PM3_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int derive_mifare_key(uint8_t *uid, const uint8_t *base_key, uint8_t *app_key) {
|
||||||
|
if (uid == NULL || base_key == NULL || app_key == NULL) {
|
||||||
|
return PM3_EINVARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t diverse[MIFARE_KEY_SIZE];
|
||||||
|
diversify_mifare_key(uid, diverse);
|
||||||
|
|
||||||
|
for (uint8_t i=0; i < MIFARE_KEY_SIZE; i++) {
|
||||||
|
app_key[i] = base_key[i] ^ diverse[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return PM3_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int derive_mifare_key_a(uint8_t *uid, uint8_t *app_key) {
|
||||||
|
return derive_mifare_key(uid, (const uint8_t*)ICT_MIFARE_A_KEY, app_key);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int derive_mifare_key_b(uint8_t *uid, uint8_t *app_key) {
|
||||||
|
return derive_mifare_key(uid, (const uint8_t*)ICT_MIFARE_B_KEY, app_key);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int decrypt_card_file(uint8_t *card_file, uint8_t len, uint8_t *plain) {
|
||||||
|
if (card_file == NULL || plain == NULL) {
|
||||||
|
return PM3_EINVARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t input[ICT_FILE_SIZE];
|
||||||
|
memcpy(input, card_file, len);
|
||||||
|
|
||||||
|
uint8_t key[AES_KEY_LEN];
|
||||||
|
// memcpy(key, ICT_DESFIRE_FILEKEY, AES_KEY_LEN);
|
||||||
|
|
||||||
|
uint8_t iv[16] = {0};
|
||||||
|
mbedtls_aes_context aes;
|
||||||
|
mbedtls_aes_init(&aes);
|
||||||
|
if (mbedtls_aes_setkey_enc(&aes, key, 128)) {
|
||||||
|
return PM3_ESOFT;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t output[ICT_FILE_SIZE];
|
||||||
|
if (mbedtls_aes_crypt_cbc(&aes, MBEDTLS_AES_DECRYPT, ICT_FILE_SIZE, iv, input, output)) {
|
||||||
|
return PM3_ESOFT;
|
||||||
|
}
|
||||||
|
mbedtls_aes_free(&aes);
|
||||||
|
memcpy(plain, output, sizeof(output));
|
||||||
|
return PM3_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int encrypt_card_file(uint8_t *card_file, uint8_t len, bool padding, uint8_t *enc) {
|
||||||
|
|
||||||
|
if (len > ICT_FILE_SIZE) {
|
||||||
|
return PM3_EINVARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t input[ICT_FILE_SIZE];
|
||||||
|
memcpy(input, card_file, len);
|
||||||
|
|
||||||
|
if (padding) {
|
||||||
|
memset(input + len, 0x4C, 128 - len);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t key[AES_KEY_LEN];
|
||||||
|
// memcpy(key, ICT_DESFIRE_FILEKEY, AES_KEY_LEN);
|
||||||
|
|
||||||
|
uint8_t iv[16] = {0};
|
||||||
|
mbedtls_aes_context aes;
|
||||||
|
mbedtls_aes_init(&aes);
|
||||||
|
if (mbedtls_aes_setkey_enc(&aes, key, 128)) {
|
||||||
|
return PM3_ESOFT;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t output[ICT_FILE_SIZE];
|
||||||
|
if (mbedtls_aes_crypt_cbc(&aes, MBEDTLS_AES_ENCRYPT, ICT_FILE_SIZE, iv, input, output)) {
|
||||||
|
return PM3_ESOFT;
|
||||||
|
}
|
||||||
|
mbedtls_aes_free(&aes);
|
||||||
|
memcpy(enc, output, sizeof(output));
|
||||||
|
return PM3_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void itc_decode_card_blob(uint8_t *data, uint8_t card_type) {
|
||||||
|
if (data == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
uint8_t block[16];
|
||||||
|
if (card_type == ICT_CT_NFC)
|
||||||
|
memcpy(block, data+16, sizeof(block));
|
||||||
|
else
|
||||||
|
memcpy(block, data, sizeof(block));
|
||||||
|
|
||||||
|
uint8_t bit_count = data[8];
|
||||||
|
|
||||||
|
uint8_t wiegand[32];
|
||||||
|
|
||||||
|
if (card_type == ICT_CT_DESFIRE || card_type == ICT_CT_NFC) {
|
||||||
|
memcpy(wiegand, data + 11, 32-11);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (card_type == ICT_CT_CLASSIC) {
|
||||||
|
memcpy(wiegand, data + 9, 32-9);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bit_count == 26) {
|
||||||
|
fc, cn = decode_wiegand_26(wiegand_payload)
|
||||||
|
ct = "Wiegand 26-bit"
|
||||||
|
}
|
||||||
|
if (bit_count == 34) {
|
||||||
|
fc, cn = decode_wiegand_34(wiegand_payload)
|
||||||
|
ct = "Wiegand 34-bit"
|
||||||
|
}else {
|
||||||
|
return f"Unknown format (bitlength={bit_count})", None, None
|
||||||
|
}
|
||||||
|
|
||||||
|
return ct, fc, cn
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
static void itc_encode_card_blob(uint8_t facility_code, uint16_t card_number, uint8_t bit_count) {
|
||||||
|
/*
|
||||||
|
// encode wiegand ..
|
||||||
|
uint8_t wiegand[] = {0,0,0,0,0};
|
||||||
|
if (bit_count == 26) {
|
||||||
|
// wiegand_data = encode_wiegand_26(facility_code, card_number)
|
||||||
|
}
|
||||||
|
if (bit_count == 34) {
|
||||||
|
// wiegand_data = encode_wiegand_34(facility_code, card_number)
|
||||||
|
}
|
||||||
|
|
||||||
|
// card binary blog
|
||||||
|
uint8_t blob[] = {
|
||||||
|
'@', 'I', 'C', 'T', 0x00, 0x80, 0x00, 0x00, bit_count, 0x00, bit_count
|
||||||
|
};
|
||||||
|
// return b'@ICT' + bytes([0,128,0,0,bit_count, 0, bit_count]) + wiegand_data
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
static int ict_select(void) {
|
static int ict_select(void) {
|
||||||
bool activate_field = true;
|
bool activate_field = true;
|
||||||
bool keep_field_on = true;
|
bool keep_field_on = true;
|
||||||
|
@ -107,6 +388,39 @@ static int CmdHfIctInfo(const char *Cmd) {
|
||||||
return infoICT(true);
|
return infoICT(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int CmdHfIctRead(const char *Cmd) {
|
||||||
|
|
||||||
|
// MFC actions
|
||||||
|
uint8_t uid[4] = {0x04, 0x01, 0x02, 0x03};
|
||||||
|
uint8_t key[MIFARE_KEY_SIZE] = {0};
|
||||||
|
derive_mifare_key_a(uid, key);
|
||||||
|
derive_mifare_key_b(uid, key);
|
||||||
|
|
||||||
|
uint8_t encsector[48] = {0};
|
||||||
|
uint8_t plainsector[48] = {0};
|
||||||
|
decrypt_card_sector(uid, encsector, sizeof(encsector), plainsector);
|
||||||
|
|
||||||
|
// DESFIRE Actions
|
||||||
|
uint8_t aeskey[AES_KEY_LEN] = {0};
|
||||||
|
uint8_t desfireuid[7] = {0x04, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06};
|
||||||
|
derive_app_key(desfireuid, aeskey);
|
||||||
|
|
||||||
|
uint8_t uniquedata[16] = {0};
|
||||||
|
derive_ble_key(uniquedata, sizeof(uniquedata), aeskey);
|
||||||
|
|
||||||
|
uint8_t encdata[ICT_FILE_SIZE] = {0};
|
||||||
|
uint8_t plaindata[ICT_FILE_SIZE] = {0};
|
||||||
|
decrypt_card_file(encdata, sizeof(encdata), plaindata);
|
||||||
|
encrypt_card_file(plaindata, sizeof(plaindata), true, encdata);
|
||||||
|
|
||||||
|
// blob actions
|
||||||
|
uint8_t mfcblob[48] = {0};
|
||||||
|
itc_decode_card_blob(mfcblob, ICT_CT_CLASSIC);
|
||||||
|
itc_encode_card_blob(101, 1337, 26);
|
||||||
|
|
||||||
|
return PM3_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
static int CmdHfIctList(const char *Cmd) {
|
static int CmdHfIctList(const char *Cmd) {
|
||||||
return CmdTraceListAlias(Cmd, "hf ict", "14a -c");
|
return CmdTraceListAlias(Cmd, "hf ict", "14a -c");
|
||||||
}
|
}
|
||||||
|
@ -115,6 +429,7 @@ static command_t CommandTable[] = {
|
||||||
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
||||||
{"info", CmdHfIctInfo, IfPm3NfcBarcode, "Tag information"},
|
{"info", CmdHfIctInfo, IfPm3NfcBarcode, "Tag information"},
|
||||||
{"list", CmdHfIctList, AlwaysAvailable, "List ICT history"},
|
{"list", CmdHfIctList, AlwaysAvailable, "List ICT history"},
|
||||||
|
{"reader", CmdHfIctRead, AlwaysAvailable, "Act like an IS14443-a reader"},
|
||||||
{NULL, NULL, NULL, NULL}
|
{NULL, NULL, NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue