Merge branch 'master' into master

Signed-off-by: Iceman <iceman@iuse.se>
This commit is contained in:
Iceman
2024-12-26 21:15:14 +01:00
committed by GitHub
88 changed files with 1131 additions and 672 deletions
+5 -1
View File
@@ -4,9 +4,13 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
## [unreleased][unreleased]
- Added `hf iclass trbl` to perform tear-off attacks on iClass (@antiklesys)
- Added support for connection to host device in all Docker envs (@doegox)
- Changed `hf 15 info` to show all type matches and check ST25TVxC signature (@doegox)
- Added initial support for ST25TN and its signature verification (@doegox)
- Changed originality checks handling to refactor code and pk data (@doegox)
- Changed `uniq.yaml` workflow to be case-insensitive (@iceman1001)
- Fixed `mem load --mfc` not erasing all SPI flash blocks after extending to 4095 keys (@piotrva)
- Extended area for Mifare keys in SPI flash to hold 4095 keys (@piotrva)
- Changed extended area for Mifare keys in SPI flash to hold 4095 keys (@piotrva)
- Fixed DESFire D40 secure channel crypto (@nvx)
- Fixed `hf mfp info` fix signature check on 4b UID cards (@doegox)
- Automatically set maximum read/write block when using predefined types in `hf_mf_ultimatecard` script (@piotrva)
+1
View File
@@ -270,6 +270,7 @@ set (TARGET_SOURCES
${PM3_ROOT}/client/src/crypto/asn1dump.c
${PM3_ROOT}/client/src/crypto/asn1utils.c
${PM3_ROOT}/client/src/crypto/libpcrypto.c
${PM3_ROOT}/client/src/crypto/originality.c
${PM3_ROOT}/client/src/emv/test/cda_test.c
${PM3_ROOT}/client/src/emv/test/crypto_test.c
${PM3_ROOT}/client/src/emv/test/cryptotest.c
+1
View File
@@ -693,6 +693,7 @@ SRCS = mifare/aiddesfire.c \
crypto/asn1dump.c \
crypto/asn1utils.c\
crypto/libpcrypto.c\
crypto/originality.c\
emv/cmdemv.c \
emv/crypto.c\
emv/crypto_polarssl.c\
+1
View File
@@ -271,6 +271,7 @@ set (TARGET_SOURCES
${PM3_ROOT}/client/src/crypto/asn1dump.c
${PM3_ROOT}/client/src/crypto/asn1utils.c
${PM3_ROOT}/client/src/crypto/libpcrypto.c
${PM3_ROOT}/client/src/crypto/originality.c
${PM3_ROOT}/client/src/emv/test/cda_test.c
${PM3_ROOT}/client/src/emv/test/crypto_test.c
${PM3_ROOT}/client/src/emv/test/cryptotest.c
+136
View File
@@ -879,6 +879,14 @@
"Description": "DEL Delhi Metro App 2",
"Type": "transport"
},
{
"AID": "025342",
"Vendor": "Bangkok Expressway and Metro Public Limited Company (BEM)",
"Country": "TH",
"Name": "MRT Stored Value Card (BKK)",
"Description": "Might also be used by BKK MRT Plus and/or BKK Park & Ride Plus Cards",
"Type": "transport"
},
{
"AID": "034D44",
"Vendor": "Delhi Metro Rail Corporation Limited",
@@ -887,6 +895,14 @@
"Description": "DEL Delhi Metro App 3",
"Type": "transport"
},
{
"AID": "035342",
"Vendor": "Bangkok Expressway and Metro Public Limited Company (BEM)",
"Country": "TH",
"Name": "MRT Stored Value Card (BKK)",
"Description": "Might also be used by BKK MRT Plus and/or BKK Park & Ride Plus Cards",
"Type": "transport"
},
{
"AID": "044D44",
"Vendor": "Delhi Metro Rail Corporation Limited",
@@ -895,6 +911,14 @@
"Description": "DEL Delhi Metro App 4",
"Type": "transport"
},
{
"AID": "045342",
"Vendor": "Bangkok Expressway and Metro Public Limited Company (BEM)",
"Country": "TH",
"Name": "MRT Stored Value Card (BKK)",
"Description": "Might also be used by BKK MRT Plus and/or BKK Park & Ride Plus Cards",
"Type": "transport"
},
{
"AID": "052242",
"Vendor": "Belbim",
@@ -911,6 +935,14 @@
"Description": "DEL Delhi Metro App 5",
"Type": "transport"
},
{
"AID": "055342",
"Vendor": "Bangkok Expressway and Metro Public Limited Company (BEM)",
"Country": "TH",
"Name": "MRT Stored Value Card (BKK)",
"Description": "Might also be used by BKK MRT Plus and/or BKK Park & Ride Plus Cards",
"Type": "transport"
},
{
"AID": "062242",
"Vendor": "Belbim",
@@ -927,6 +959,14 @@
"Description": "DEL Delhi Metro App 6",
"Type": "transport"
},
{
"AID": "065342",
"Vendor": "Bangkok Expressway and Metro Public Limited Company (BEM)",
"Country": "TH",
"Name": "MRT Stored Value Card (BKK)",
"Description": "Might also be used by BKK MRT Plus and/or BKK Park & Ride Plus Cards",
"Type": "transport"
},
{
"AID": "074D44",
"Vendor": "Delhi Metro Rail Corporation Limited",
@@ -935,6 +975,22 @@
"Description": "DEL Delhi Metro App 7",
"Type": "transport"
},
{
"AID": "075342",
"Vendor": "Bangkok Expressway and Metro Public Limited Company (BEM)",
"Country": "TH",
"Name": "MRT Stored Value Card (BKK)",
"Description": "Might also be used by BKK MRT Plus and/or BKK Park & Ride Plus Cards",
"Type": "transport"
},
{
"AID": "085342",
"Vendor": "Bangkok Expressway and Metro Public Limited Company (BEM)",
"Country": "TH",
"Name": "MRT Stored Value Card (BKK)",
"Description": "Might also be used by BKK MRT Plus and/or BKK Park & Ride Plus Cards",
"Type": "transport"
},
{
"AID": "087522",
"Vendor": "Umo Mobility via Cubic Transportation Systems",
@@ -943,6 +999,78 @@
"Description": "Umo Mobility Card",
"Type": "transport"
},
{
"AID": "095342",
"Vendor": "Bangkok Expressway and Metro Public Limited Company (BEM)",
"Country": "TH",
"Name": "MRT Stored Value Card (BKK)",
"Description": "Might also be used by BKK MRT Plus and/or BKK Park & Ride Plus Cards",
"Type": "transport"
},
{
"AID": "0A5342",
"Vendor": "Bangkok Expressway and Metro Public Limited Company (BEM)",
"Country": "TH",
"Name": "MRT Stored Value Card (BKK)",
"Description": "Might also be used by BKK MRT Plus and/or BKK Park & Ride Plus Cards",
"Type": "transport"
},
{
"AID": "0B5342",
"Vendor": "Bangkok Expressway and Metro Public Limited Company (BEM)",
"Country": "TH",
"Name": "MRT Stored Value Card (BKK)",
"Description": "Might also be used by BKK MRT Plus and/or BKK Park & Ride Plus Cards",
"Type": "transport"
},
{
"AID": "0C5342",
"Vendor": "Bangkok Expressway and Metro Public Limited Company (BEM)",
"Country": "TH",
"Name": "MRT Stored Value Card (BKK)",
"Description": "Might also be used by BKK MRT Plus and/or BKK Park & Ride Plus Cards",
"Type": "transport"
},
{
"AID": "0D5342",
"Vendor": "Bangkok Expressway and Metro Public Limited Company (BEM)",
"Country": "TH",
"Name": "MRT Stored Value Card (BKK)",
"Description": "Might also be used by BKK MRT Plus and/or BKK Park & Ride Plus Cards",
"Type": "transport"
},
{
"AID": "0E5342",
"Vendor": "Bangkok Expressway and Metro Public Limited Company (BEM)",
"Country": "TH",
"Name": "MRT Stored Value Card (BKK)",
"Description": "Might also be used by BKK MRT Plus and/or BKK Park & Ride Plus Cards",
"Type": "transport"
},
{
"AID": "0F5342",
"Vendor": "Bangkok Expressway and Metro Public Limited Company (BEM)",
"Country": "TH",
"Name": "MRT Stored Value Card (BKK)",
"Description": "Might also be used by BKK MRT Plus and/or BKK Park & Ride Plus Cards",
"Type": "transport"
},
{
"AID": "105342",
"Vendor": "Bangkok Expressway and Metro Public Limited Company (BEM)",
"Country": "TH",
"Name": "MRT Stored Value Card (BKK)",
"Description": "Might also be used by BKK MRT Plus and/or BKK Park & Ride Plus Cards",
"Type": "transport"
},
{
"AID": "115342",
"Vendor": "Bangkok Expressway and Metro Public Limited Company (BEM)",
"Country": "TH",
"Name": "MRT Stored Value Card (BKK)",
"Description": "Might also be used by BKK MRT Plus and/or BKK Park & Ride Plus Cards",
"Type": "transport"
},
{
"AID": "2211AF",
"Vendor": "National Transport Authority",
@@ -1071,6 +1199,14 @@
"Description": "CMH COTA Smartcard; Masabi Justride Tap and Ride DESFire Smartcard",
"Type": "transport"
},
{
"AID": "D000D0",
"Vendor": "Greater Dayton Regional Transit Authority (RTA) via Masabi Ltd",
"Country": "US",
"Name": "RTA Tapp Pay Card (DAY)",
"Description": "DAY RTA Tapp Pay Card; Masabi Justride Tap and Ride DESFire Smartcard",
"Type": "transport"
},
{
"AID": "DD00DD",
"Vendor": "Regional Transporation District (RTD) via Masabi Ltd",
+5 -1
View File
@@ -2681,7 +2681,11 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) {
}
if (isST) {
PrintAndLogEx(HINT, "Hint: try `" _YELLOW_("hf st info") "`");
if (card.ats_len > 0) {
PrintAndLogEx(HINT, "Hint: try `" _YELLOW_("hf st25ta info") "`");
} else {
PrintAndLogEx(HINT, "Hint: try `" _YELLOW_("hf mfu info") "`");
}
}
if (isEMV) {
+130 -131
View File
@@ -43,6 +43,7 @@
#include "cliparser.h"
#include "util_posix.h" // msleep
#include "iso15.h" // typedef structs / enum
#include "crypto/originality.h"
#define FrameSOF Iso15693FrameSOF
#define Logic0 Iso15693Logic0
@@ -281,121 +282,35 @@ static const productName_t uidmapping[] = {
static int CmdHF15Help(const char *Cmd);
static int nxp_15693_print_signature(uint8_t *uid, uint8_t *signature) {
#define PUBLIC_ECDA_KEYLEN 33
const ecdsa_publickey_t nxp_15693_public_keys[] = {
{"NXP MIFARE Classic MFC1C14_x", "044F6D3F294DEA5737F0F46FFEE88A356EED95695DD7E0C27A591E6F6F65962BAF"},
{"MIFARE Classic / QL88", "046F70AC557F5461CE5052C8E4A7838C11C7A236797E8A0730A101837C004039C2"},
{"NXP ICODE DNA, ICODE SLIX2", "048878A2A2D3EEC336B4F261A082BD71F9BE11C4E2E896648B32EFA59CEA6E59F0"},
{"NXP Public key", "04A748B6A632FBEE2C0897702B33BEA1C074998E17B84ACA04FF267E5D2C91F6DC"},
{"NXP Ultralight Ev1", "0490933BDCD6E99B4E255E3DA55389A827564E11718E017292FAF23226A96614B8"},
{"NXP NTAG21x (2013)", "04494E1A386D3D3CFE3DC10E5DE68A499B1C202DB5B132393E89ED19FE5BE8BC61"},
{"MIKRON Public key", "04F971EDA742A4A80D32DCF6A814A707CC3DC396D35902F72929FDCD698B3468F2"},
{"VivoKey Spark1 Public key", "04D64BB732C0D214E7EC580736ACF847284B502C25C0F7F2FA86AACE1DADA4387A"},
{"TruST25 (ST) key 01?", "041D92163650161A2548D33881C235D0FB2315C2C31A442F23C87ACF14497C0CBA"},
{"TruST25 (ST) key 04?", "04101E188A8B4CDDBC62D5BC3E0E6850F0C2730E744B79765A0E079907FBDB01BC"},
};
/*
uint8_t nxp_15693_public_keys[][PUBLIC_ECDA_KEYLEN] = {
// ICODE SLIX2 / DNA
{
0x04, 0x88, 0x78, 0xA2, 0xA2, 0xD3, 0xEE, 0xC3,
0x36, 0xB4, 0xF2, 0x61, 0xA0, 0x82, 0xBD, 0x71,
0xF9, 0xBE, 0x11, 0xC4, 0xE2, 0xE8, 0x96, 0x64,
0x8B, 0x32, 0xEF, 0xA5, 0x9C, 0xEA, 0x6E, 0x59, 0xF0
},
// unknown. Needs identification
{
0x04, 0x4F, 0x6D, 0x3F, 0x29, 0x4D, 0xEA, 0x57,
0x37, 0xF0, 0xF4, 0x6F, 0xFE, 0xE8, 0x8A, 0x35,
0x6E, 0xED, 0x95, 0x69, 0x5D, 0xD7, 0xE0, 0xC2,
0x7A, 0x59, 0x1E, 0x6F, 0x6F, 0x65, 0x96, 0x2B, 0xAF
},
// unknown. Needs identification
{
0x04, 0xA7, 0x48, 0xB6, 0xA6, 0x32, 0xFB, 0xEE,
0x2C, 0x08, 0x97, 0x70, 0x2B, 0x33, 0xBE, 0xA1,
0xC0, 0x74, 0x99, 0x8E, 0x17, 0xB8, 0x4A, 0xCA,
0x04, 0xFF, 0x26, 0x7E, 0x5D, 0x2C, 0x91, 0xF6, 0xDC
},
// manufacturer public key
{
0x04, 0x6F, 0x70, 0xAC, 0x55, 0x7F, 0x54, 0x61,
0xCE, 0x50, 0x52, 0xC8, 0xE4, 0xA7, 0x83, 0x8C,
0x11, 0xC7, 0xA2, 0x36, 0x79, 0x7E, 0x8A, 0x07,
0x30, 0xA1, 0x01, 0x83, 0x7C, 0x00, 0x40, 0x39, 0xC2
},
// MIKRON public key.
{
0x04, 0xf9, 0x71, 0xed, 0xa7, 0x42, 0xa4, 0xa8,
0x0d, 0x32, 0xdc, 0xf6, 0xa8, 0x14, 0xa7, 0x07,
0xcc, 0x3d, 0xc3, 0x96, 0xd3, 0x59, 0x02, 0xf7,
0x29, 0x29, 0xfd, 0xcd, 0x69, 0x8b, 0x34, 0x68, 0xf2
}
};
*/
uint8_t revuid[HF15_UID_LENGTH] = {0};
reverse_array_copy(uid, sizeof(revuid), revuid);
uint8_t revsign[32] = {0};
reverse_array_copy(signature, sizeof(revsign), revsign);
uint8_t i;
int reason = 0;
bool is_valid = false;
for (i = 0; i < ARRAYLEN(nxp_15693_public_keys); i++) {
int dl = 0;
uint8_t key[PUBLIC_ECDA_KEYLEN];
param_gethex_to_eol(nxp_15693_public_keys[i].value, 0, key, PUBLIC_ECDA_KEYLEN, &dl);
int res = ecdsa_signature_r_s_verify(MBEDTLS_ECP_DP_SECP128R1, key, uid, 8, signature, 32, false);
is_valid = (res == 0);
if (is_valid) {
reason = 1;
break;
}
int index = -1;
index = originality_check_verify(uid, 8, signature, 32, PK_MFC);
if (index >= 0) {
reason = 1;
} else {
// try with sha256
res = ecdsa_signature_r_s_verify(MBEDTLS_ECP_DP_SECP128R1, key, uid, 8, signature, 32, true);
is_valid = (res == 0);
if (is_valid) {
index = originality_check_verify_ex(uid, 8, signature, 32, PK_MFC, false, true);
if (index >= 0) {
reason = 2;
break;
}
// try with reversed uid / signature
res = ecdsa_signature_r_s_verify(MBEDTLS_ECP_DP_SECP128R1, key, revuid, sizeof(revuid), revsign, sizeof(revsign), false);
is_valid = (res == 0);
if (is_valid) {
reason = 3;
break;
}
// try with sha256
res = ecdsa_signature_r_s_verify(MBEDTLS_ECP_DP_SECP128R1, key, revuid, sizeof(revuid), revsign, sizeof(revsign), true);
is_valid = (res == 0);
if (is_valid) {
reason = 4;
break;
} else {
// try with reversed uid / signature
index = originality_check_verify_ex(uid, 8, signature, 32, PK_MFC, true, false);
if (index >= 0) {
reason = 3;
} else {
// try with sha256 and reversed uid / signature
index = originality_check_verify_ex(uid, 8, signature, 32, PK_MFC, true, true);
if (index >= 0) {
reason = 3;
}
}
}
}
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, "--- " _CYAN_("Tag Signature"));
if (is_valid == false || i == ARRAYLEN(nxp_15693_public_keys)) {
PrintAndLogEx(INFO, " Elliptic curve parameters: NID_secp128r1");
PrintAndLogEx(INFO, " TAG IC Signature: %s", sprint_hex_inrow(signature, 32));
PrintAndLogEx(SUCCESS, " Signature verification: " _RED_("failed"));
return PM3_ESOFT;
int ret = originality_check_print(signature, 32, index);
if (ret != PM3_SUCCESS) {
return ret;
}
PrintAndLogEx(INFO, " IC signature public key name: " _GREEN_("%s"), nxp_15693_public_keys[i].desc);
PrintAndLogEx(INFO, "IC signature public key value: %s", nxp_15693_public_keys[i].value);
PrintAndLogEx(INFO, " Elliptic curve parameters: NID_secp128r1");
PrintAndLogEx(INFO, " TAG IC Signature: %s", sprint_hex_inrow(signature, 32));
PrintAndLogEx(SUCCESS, " Signature verification: " _GREEN_("successful"));
switch (reason) {
case 1:
PrintAndLogEx(INFO, " Params used: UID and signature, plain");
@@ -416,14 +331,15 @@ static int nxp_15693_print_signature(uint8_t *uid, uint8_t *signature) {
// get a product description based on the UID
// uid[8] tag uid
// returns description of the best match
static const char *getTagInfo_15(const uint8_t *uid) {
static void printTagInfo_15(const uint8_t *uid) {
if (uid == NULL) {
return "";
return;
}
uint64_t myuid, mask;
int i = 0, best = -1;
memcpy(&myuid, uid, sizeof(uint64_t));
// find first best match
while (uidmapping[i].mask > 0) {
if (uidmapping[i].mask > 64) {
mask = uidmapping[i].mask;
@@ -441,10 +357,23 @@ static const char *getTagInfo_15(const uint8_t *uid) {
}
i++;
}
if (best >= 0) {
i = 0;
while (uidmapping[i].mask > 0) {
if (uidmapping[i].mask > 64) {
mask = uidmapping[i].mask;
} else {
mask = (~0ULL) << (64 - uidmapping[i].mask);
}
if (((myuid & mask) == uidmapping[i].uid) && (uidmapping[i].mask == uidmapping[best].mask)) {
PrintAndLogEx(SUCCESS, "TYPE MATCH " _YELLOW_("%s"), uidmapping[i].desc);
}
i++;
}
} else {
PrintAndLogEx(SUCCESS, "TYPE...... " _YELLOW_("%s"), uidmapping[i].desc);
}
if (best >= 0)
return uidmapping[best].desc;
return uidmapping[i].desc;
}
// return a clear-text message to an errorcode
@@ -531,7 +460,7 @@ static int getUID(bool verbose, bool loop, uint8_t *buf) {
if (verbose) {
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(SUCCESS, "UID.... " _GREEN_("%s"), iso15693_sprintUID(NULL, buf));
PrintAndLogEx(SUCCESS, "TYPE... " _YELLOW_("%s"), getTagInfo_15(buf));
printTagInfo_15(buf);
PrintAndLogEx(NORMAL, "");
}
res = PM3_SUCCESS;
@@ -963,6 +892,66 @@ static int NxpSysInfo(uint8_t *uid) {
return PM3_SUCCESS;
}
static int StCheckSig(uint8_t *uid) {
// request to be sent to device/card
uint8_t approxlen = 2 + 8 + 1 + 2;
iso15_raw_cmd_t *packet = (iso15_raw_cmd_t *)calloc(1, sizeof(iso15_raw_cmd_t) + approxlen);
if (packet == NULL) {
PrintAndLogEx(FAILED, "failed to allocate memory");
return PM3_EMALLOC;
}
// ISO15693 Protocol params
packet->raw[packet->rawlen++] = arg_get_raw_flag(HF15_UID_LENGTH, false, false, false);
packet->raw[packet->rawlen++] = ISO15693_READBLOCK;
// add UID (scan, uid)
memcpy(packet->raw + packet->rawlen, uid, HF15_UID_LENGTH);
packet->rawlen += HF15_UID_LENGTH;
packet->flags = (ISO15_CONNECT| ISO15_READ_RESPONSE | ISO15_NO_DISCONNECT);
uint16_t blkoff = packet->rawlen;
char signature_hex[65] = {0};
for (int j=0; j<17; j++) {
packet->rawlen = blkoff;
// block no
packet->raw[packet->rawlen++] = 0x3F + j;
// crc
AddCrc15(packet->raw, packet->rawlen);
packet->rawlen += 2;
clearCommandBuffer();
SendCommandNG(CMD_HF_ISO15693_COMMAND, (uint8_t *)packet, ISO15_RAW_LEN(packet->rawlen));
PacketResponseNG resp;
if (WaitForResponseTimeout(CMD_HF_ISO15693_COMMAND, &resp, 2000) == false) {
PrintAndLogEx(DEBUG, "iso15693 timeout");
free(packet);
DropField();
return PM3_ETIMEOUT;
}
ISO15_ERROR_HANDLING_RESPONSE
uint8_t *d = resp.data.asBytes;
ISO15_ERROR_HANDLING_CARD_RESPONSE(d, resp.length)
if (j==0) {
if (memcmp(d + 1, "K04S", 4) != 0) {
// No signature
free(packet);
return PM3_ESOFT;
}
} else {
memcpy(signature_hex + ((j - 1) * 4), d + 1, 4);
}
packet->flags = (ISO15_READ_RESPONSE | ISO15_NO_DISCONNECT);
}
free(packet);
DropField();
uint8_t signature[16];
size_t signature_len;
hexstr_to_byte_array(signature_hex, signature, &signature_len);
uint8_t uid_swap[HF15_UID_LENGTH];
reverse_array_copy(uid, HF15_UID_LENGTH, uid_swap);
int index = originality_check_verify_ex(uid_swap, HF15_UID_LENGTH, signature, signature_len, PK_ST25TV, false, true);
PrintAndLogEx(NORMAL, "");
return originality_check_print(signature, signature_len, index);
}
/**
* Commandline handling: HF15 CMD SYSINFO
* get system information from tag/VICC
@@ -1071,7 +1060,7 @@ static int CmdHF15Info(const char *Cmd) {
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, "--- " _CYAN_("Tag Information") " ---------------------------");
PrintAndLogEx(SUCCESS, "UID....... " _GREEN_("%s"), iso15693_sprintUID(NULL, uid));
PrintAndLogEx(SUCCESS, "TYPE...... " _YELLOW_("%s"), getTagInfo_15(d + 2));
printTagInfo_15(d + 2);
PrintAndLogEx(SUCCESS, "SYSINFO... %s", sprint_hex(d, resp.length - 2));
// DSFID
@@ -1109,19 +1098,29 @@ static int CmdHF15Info(const char *Cmd) {
uint8_t nxp_version = d[6] & 0x18;
PrintAndLogEx(DEBUG, "NXP Version: %02x", nxp_version);
if (d[8] == 0x04 && d[7] == 0x01 && nxp_version == 0x08) {
PrintAndLogEx(DEBUG, "SLIX2 Detected, getting NXP System Info");
return NxpSysInfo(uid);
} else if (d[8] == 0x04 && d[7] == 0x01 && nxp_version == 0x18) { // If it is an NTAG 5
PrintAndLogEx(DEBUG, "NTAG 5 Detected, getting NXP System Info");
return NxpSysInfo(uid);
} else if (d[8] == 0x04 && (d[7] == 0x01 || d[7] == 0x02 || d[7] == 0x03)) { // If SLI, SLIX, SLIX-l, or SLIX-S check EAS status
PrintAndLogEx(DEBUG, "SLI, SLIX, SLIX-L, or SLIX-S Detected checking EAS status");
return NxpTestEAS(uid);
if (d[8] == 0x04) {
// NXP
if (d[7] == 0x01 && nxp_version == 0x08) {
PrintAndLogEx(DEBUG, "SLIX2 Detected, getting NXP System Info");
return NxpSysInfo(uid);
} else if (d[7] == 0x01 && nxp_version == 0x18) { // If it is an NTAG 5
PrintAndLogEx(DEBUG, "NTAG 5 Detected, getting NXP System Info");
return NxpSysInfo(uid);
} else if ((d[7] == 0x01 || d[7] == 0x02 || d[7] == 0x03)) { // If SLI, SLIX, SLIX-l, or SLIX-S check EAS status
PrintAndLogEx(DEBUG, "SLI, SLIX, SLIX-L, or SLIX-S Detected checking EAS status");
return NxpTestEAS(uid);
}
} else if (d[8] == 0x02) {
// ST, check d[7]:
// ST25TV512C/ST25TV02KC 0x08
// ST25TV512/ST25TV02K 0x23
// ST25TV04K-P 0x35
// ST25TV16K/ST25TV64K 0x48
if (d[7] == 0x08) {
PrintAndLogEx(DEBUG, "ST25TVxC Detected, getting ST Signature");
return StCheckSig(uid);
}
}
PrintAndLogEx(NORMAL, "");
return PM3_SUCCESS;
}
@@ -1405,7 +1404,7 @@ static void print_tag_15693(iso15_tag_t *tag, bool dense_output, bool verbose) {
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, "--- " _CYAN_("Tag Information") " --%.*s", (tag->bytesPerPage * 3), dashes);
PrintAndLogEx(SUCCESS, "UID....... " _GREEN_("%s"), iso15693_sprintUID(NULL, tag->uid));
PrintAndLogEx(SUCCESS, "TYPE...... " _YELLOW_("%s"), getTagInfo_15(tag->uid));
printTagInfo_15(tag->uid);
PrintAndLogEx(SUCCESS, "DSFID..... 0x%02X", tag->dsfid);
PrintAndLogEx(SUCCESS, "AFI....... 0x%02X", tag->afi);
PrintAndLogEx(SUCCESS, "IC ref.... 0x%02X", tag->ic);
@@ -1934,7 +1933,7 @@ static int CmdHF15Dump(const char *Cmd) {
tag->pagesCount = d[dCpt++] + 1;
tag->bytesPerPage = d[dCpt++] + 1;
} else {
// Set tag memory layout values (if can't be readed in SYSINFO)
// Set tag memory layout values (if can't be read in SYSINFO)
tag->bytesPerPage = blocksize;
tag->pagesCount = 128;
}
@@ -1943,7 +1942,7 @@ static int CmdHF15Dump(const char *Cmd) {
tag->ic = d[dCpt++];
}
// add lenght for blockno (1)
// add length for blockno (1)
packet->rawlen++;
packet->raw[0] |= ISO15_REQ_OPTION; // Add option to dump lock status
packet->raw[1] = ISO15693_READBLOCK;
@@ -3338,7 +3337,7 @@ static int CmdHF15View(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "hf 15 view",
"Print a ISO-15693 tag dump file (bin/eml/json)",
"hf 15 view -f hf-iclass-AA162D30F8FF12F1-dump.bin\n"
"hf 15 view -f hf-15-1122334455667788-dump.bin\n"
);
void *argtable[] = {
arg_param_begin,
+164
View File
@@ -2373,3 +2373,167 @@ uint64_t GetCrypto1ProbableKey(AuthData_t *ad) {
crypto1_destroy(revstate);
return key;
}
// FMCOS 2.0
void annotateFMCOS20(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) {
if (cmdsize < 2)
return;
int pos = 0;
switch (cmd[0]) {
case 2:
case 3:
pos = 2;
break;
case 0:
pos = 1;
break;
default:
pos = 3;
break;
}
switch (cmd[pos]) {
case FMCOS20_CMD_EXTERNAL_AUTHENTICATION:
snprintf(exp, size, "EXT. AUTH");
break;
case FMCOS20_CMD_GET_CHALLENGE:
snprintf(exp, size, "GET CHALLENGE");
break;
case FMCOS20_CMD_INTERNAL_AUTHENTICATION:
snprintf(exp, size, "INT. AUTH");
break;
case FMCOS20_CMD_SELECT:
snprintf(exp, size, "SELECT");
break;
case FMCOS20_CMD_VERIFY_PIN:
snprintf(exp, size, "VERIFY PIN");
break;
case FMCOS20_CMD_READ_BINARY:
snprintf(exp, size, "READ BINARY");
break;
case FMCOS20_CMD_READ_RECORD:
snprintf(exp, size, "READ RECORD");
break;
case FMCOS20_CMD_UPDATE_BINARY:
snprintf(exp, size, "UPDATE BINARY");
break;
case FMCOS20_CMD_UPDATE_RECORD:
snprintf(exp, size, "UPDATE RECORD");
break;
case FMCOS20_CMD_APPEND_RECORD:
snprintf(exp, size, "APPEND RECORD");
break;
case FMCOS20_CMD_ERASE_DF:
snprintf(exp, size, "ERASE DF");
break;
case FMCOS20_CMD_WRITE_KEY:
snprintf(exp, size, "WRITE KEY");
break;
case FMCOS20_CMD_CREATE_FILE:
snprintf(exp, size, "CREATE FILE");
break;
case FMCOS20_CMD_CARD_BLOCK:
snprintf(exp, size, "CARD BLOCK");
break;
case FMCOS20_CMD_APP_UNBLOCK:
snprintf(exp, size, "APP UNBLOCK");
break;
case FMCOS20_CMD_APP_BLOCK:
if (cmd[pos+1] == 0)
snprintf(exp, size, "APP BLOCK (TEMP)");
else if(cmd[pos+1] == 1)
snprintf(exp, size, "APP BLOCK (PERM)");
else
snprintf(exp, size, "APP BLOCK");
break;
case FMCOS20_CMD_PIN_UNBLOCK:
snprintf(exp, size, "PIN UNBLOCK");
break;
case FMCOS20_CMD_CHANGE_PIN:
if (cmd[pos+1] == 0)
snprintf(exp, size, "RESET PIN");
else if (cmd[pos+1] == 1)
snprintf(exp, size, "CHANGE PIN");
break;
case FMCOS20_CMD_INITIALIZE_TRANSACTION:
if (cmd[pos+1] == 0)
snprintf(exp, size, "INIT. TRANSACTION (CREDIT)");
else if (cmd[pos+1] == 1)
snprintf(exp, size, "INIT. TRANSACTION (PURCHASE)");
else if (cmd[pos+1] == 2)
snprintf(exp, size, "INIT. TRANSACTION (CASH WITHDRAW)");
else if (cmd[pos+1] == 3)
snprintf(exp, size, "INIT. TRANSACTION (CAPP PURCHASE)");
else if (cmd[pos+1] == 4)
snprintf(exp, size, "INIT. TRANSACTION (OVERDRAFT)");
else if (cmd[pos+1] == 5)
snprintf(exp, size, "INIT. TRANSACTION (WITHDRAW)");
break;
case FMCOS20_CMD_CREDIT_LOAD:
snprintf(exp, size, "CREDIT LOAD");
break;
case FMCOS20_CMD_PURCHASE:
if(cmd[pos+1] == 0)
snprintf(exp, size, "PURCHASE");
else if (cmd[pos+1] == 1)
snprintf(exp, size, "CAPP PURCHASE / CASH WITHDRAW");
else if (cmd[pos+1] == 3)
snprintf(exp, size, "WITHDRAW");
break;
case FMCOS20_CMD_UPDATE_OVERDRAW_LIMIT:
snprintf(exp, size, "UPDATE OVERDRAFT");
break;
case FMCOS20_CMD_GET_TRANSACTION_PROOF:
snprintf(exp, size, "TRANSACTION RECORD");
break;
case FMCOS20_CMD_GET_BALANCE:
snprintf(exp, size, "GET BALANCE");
break;
case FMCOS20_CMD_INITIALIZE_GREY_LOCK_UNLOCK:
if (cmd[pos+1] == 8)
snprintf(exp, size, "INIT. GRAY LOCK");
else if (cmd[pos+1] == 9)
snprintf(exp, size, "INIT. GRAY UNLOCK");
break;
case FMCOS20_CMD_GREY_LOCK_UNLOCK:
if (cmd[pos+1] == 8)
snprintf(exp, size, "GRAY LOCK");
else if (cmd[pos+1] == 9)
snprintf(exp, size, "GRAY UNLOCK");
break;
case FMCOS20_CMD_DEBIT_UNLOCK:
snprintf(exp, size, "DEBIT UNLOCK");
break;
case FMCOS20_CMD_CALCULATE_ROM_CRC:
snprintf(exp, size, "CALC. ROM CRC");
break;
case FMCOS20_CMD_GET_RESPONSE:
snprintf(exp, size, "GET RESPONSE");
break;
case FMCOS20_CMD_UNBLOCK:
snprintf(exp, size, "UNBLOCK");
break;
case FMCOS20_CMD_PULL:
snprintf(exp, size, "PULL");
break;
case FMCOS20_CMD_CHARGE:
snprintf(exp, size, "CHARGE");
break;
case FMCOS20_CMD_WRITE_EEPROM:
snprintf(exp, size, "WRITE EEPROM");
break;
case FMCOS20_CMD_READ_EEPROM:
snprintf(exp, size, "READ EEPROM");
break;
case FMCOS20_CMD_INITIALIZE_EEPROM:
snprintf(exp, size, "INIT. EEPROM");
break;
case FMCOS20_CMD_READ_ROM:
snprintf(exp, size, "READ ROM");
break;
default:
//snprintf(exp, size, "?");
break;
}
}
+2
View File
@@ -76,4 +76,6 @@ bool NestedCheckKey(uint64_t key, AuthData_t *ad, uint8_t *cmd, uint8_t cmdsize,
bool CheckCrypto1Parity(const uint8_t *cmd_enc, uint8_t cmdsize, uint8_t *cmd, const uint8_t *parity_enc);
uint64_t GetCrypto1ProbableKey(AuthData_t *ad);
void annotateFMCOS20(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize);
#endif // CMDHFLIST
+8 -47
View File
@@ -46,6 +46,7 @@
#include "generator.h" // keygens.
#include "fpga.h"
#include "mifare/mifarehost.h"
#include "crypto/originality.h"
static int CmdHelp(const char *Cmd);
@@ -68,52 +69,9 @@ static int usage_hf14_keybrute(void) {
*/
int mfc_ev1_print_signature(uint8_t *uid, uint8_t uidlen, uint8_t *signature, int signature_len) {
// ref: MIFARE Classic EV1 Originality Signature Validation
#define PUBLIC_MFCEV1_ECDA_KEYLEN 33
const ecdsa_publickey_t nxp_mfc_public_keys[] = {
{"NXP MIFARE Classic MFC1C14_x", "044F6D3F294DEA5737F0F46FFEE88A356EED95695DD7E0C27A591E6F6F65962BAF"},
{"MIFARE Classic / QL88", "046F70AC557F5461CE5052C8E4A7838C11C7A236797E8A0730A101837C004039C2"},
{"NXP ICODE DNA, ICODE SLIX2", "048878A2A2D3EEC336B4F261A082BD71F9BE11C4E2E896648B32EFA59CEA6E59F0"},
{"NXP Public key", "04A748B6A632FBEE2C0897702B33BEA1C074998E17B84ACA04FF267E5D2C91F6DC"},
{"NXP Ultralight Ev1", "0490933BDCD6E99B4E255E3DA55389A827564E11718E017292FAF23226A96614B8"},
{"NXP NTAG21x (2013)", "04494E1A386D3D3CFE3DC10E5DE68A499B1C202DB5B132393E89ED19FE5BE8BC61"},
{"MIKRON Public key", "04F971EDA742A4A80D32DCF6A814A707CC3DC396D35902F72929FDCD698B3468F2"},
{"VivoKey Spark1 Public key", "04D64BB732C0D214E7EC580736ACF847284B502C25C0F7F2FA86AACE1DADA4387A"},
{"TruST25 (ST) key 01?", "041D92163650161A2548D33881C235D0FB2315C2C31A442F23C87ACF14497C0CBA"},
{"TruST25 (ST) key 04?", "04101E188A8B4CDDBC62D5BC3E0E6850F0C2730E744B79765A0E079907FBDB01BC"},
};
uint8_t i;
bool is_valid = false;
for (i = 0; i < ARRAYLEN(nxp_mfc_public_keys); i++) {
int dl = 0;
uint8_t key[PUBLIC_MFCEV1_ECDA_KEYLEN];
param_gethex_to_eol(nxp_mfc_public_keys[i].value, 0, key, PUBLIC_MFCEV1_ECDA_KEYLEN, &dl);
int res = ecdsa_signature_r_s_verify(MBEDTLS_ECP_DP_SECP128R1, key, uid, uidlen, signature, signature_len, false);
is_valid = (res == 0);
if (is_valid)
break;
}
PrintAndLogEx(INFO, "");
PrintAndLogEx(INFO, "--- " _CYAN_("Tag Signature"));
if (is_valid == false || i == ARRAYLEN(nxp_mfc_public_keys)) {
PrintAndLogEx(INFO, " Elliptic curve parameters: NID_secp128r1");
PrintAndLogEx(INFO, " TAG IC Signature: %s", sprint_hex_inrow(signature, 32));
PrintAndLogEx(SUCCESS, " Signature verification: " _RED_("failed"));
return PM3_ESOFT;
}
PrintAndLogEx(INFO, " IC signature public key name: " _GREEN_("%s"), nxp_mfc_public_keys[i].desc);
PrintAndLogEx(INFO, "IC signature public key value: %s", nxp_mfc_public_keys[i].value);
PrintAndLogEx(INFO, " Elliptic curve parameters: NID_secp128r1");
PrintAndLogEx(INFO, " TAG IC Signature: %s", sprint_hex_inrow(signature, 32));
PrintAndLogEx(SUCCESS, " Signature verification: " _GREEN_("successful"));
return PM3_SUCCESS;
int index = originality_check_verify(uid, uidlen, signature, signature_len, PK_MFC);
PrintAndLogEx(NORMAL, "");
return originality_check_print(signature, signature_len, index);
}
static int mf_read_uid(uint8_t *uid, int *uidlen, int *nxptype) {
@@ -10018,10 +9976,13 @@ static int CmdHF14AMfISEN(const char *Cmd) {
uint64_t t1 = msclock();
uint32_t flags = collect_fm11rf08s_with_data | (collect_fm11rf08s_without_backdoor << 1);
SendCommandMIX(CMD_HF_MIFARE_ACQ_STATIC_ENCRYPTED_NONCES, flags, blockn, keytype, key, sizeof(key));
if (WaitForResponseTimeout(CMD_ACK, &resp, 1000)) {
if (WaitForResponseTimeout(CMD_ACK, &resp, 2500)) {
if (resp.oldarg[0] != PM3_SUCCESS) {
return NONCE_FAIL;
}
} else {
PrintAndLogEx(WARNING, "Fail, transfer from device time-out");
return PM3_ETIMEOUT;
}
uint8_t num_sectors = MIFARE_1K_MAXSECTOR + 1;
iso14a_fm11rf08s_nonces_with_data_t nonces_dump = {0};
+4 -54
View File
@@ -45,6 +45,7 @@
#include "generator.h"
#include "mifare/aiddesfire.h"
#include "util.h"
#include "crypto/originality.h"
#define MAX_KEY_LEN 24
#define MAX_KEYS_LIST_LEN 1024
@@ -442,61 +443,10 @@ int desfire_print_signature(uint8_t *uid, uint8_t uidlen, uint8_t *signature, si
PrintAndLogEx(DEBUG, "SIGNATURE=NULL");
return PM3_EINVARG;
}
// ref: MIFARE Desfire Originality Signature Validation
// See tools/recover_pk.py to recover Pk from UIDs and signatures
#define PUBLIC_DESFIRE_ECDA_KEYLEN 57
const ecdsa_publickey_t nxp_desfire_public_keys[] = {
{"NTAG424DNA, DESFire Ev2", "048A9B380AF2EE1B98DC417FECC263F8449C7625CECE82D9B916C992DA209D68422B81EC20B65A66B5102A61596AF3379200599316A00A1410"},
{"NTAG413DNA, DESFire Ev1", "04BB5D514F7050025C7D0F397310360EEC91EAF792E96FC7E0F496CB4E669D414F877B7B27901FE67C2E3B33CD39D1C797715189AC951C2ADD"},
{"DESFire Ev2", "04B304DC4C615F5326FE9383DDEC9AA892DF3A57FA7FFB3276192BC0EAA252ED45A865E3B093A3D0DCE5BE29E92F1392CE7DE321E3E5C52B3A"},
{"DESFire Ev3", "041DB46C145D0A36539C6544BD6D9B0AA62FF91EC48CBC6ABAE36E0089A46F0D08C8A715EA40A63313B92E90DDC1730230E0458A33276FB743"},
{"NTAG424DNA, NTAG424DNATT, DESFire Light Ev2", "04B304DC4C615F5326FE9383DDEC9AA892DF3A57FA7FFB3276192BC0EAA252ED45A865E3B093A3D0DCE5BE29E92F1392CE7DE321E3E5C52B3B"},
{"DESFire Light", "040E98E117AAA36457F43173DC920A8757267F44CE4EC5ADD3C54075571AEBBF7B942A9774A1D94AD02572427E5AE0A2DD36591B1FB34FCF3D"},
{"MIFARE Plus Ev1", "044409ADC42F91A8394066BA83D872FB1D16803734E911170412DDF8BAD1A4DADFD0416291AFE1C748253925DA39A5F39A1C557FFACD34C62E"},
{"MIFARE Plus Ev2", "04BB49AE4447E6B1B6D21C098C1538B594A11A4A1DBF3D5E673DEACDEB3CC512D1C08AFA1A2768CE20A200BACD2DC7804CD7523A0131ABF607"},
{"DESFire Ev2 XL", "04CD5D45E50B1502F0BA4656FF37669597E7E183251150F9574CC8DA56BF01C7ABE019E29FEA48F9CE22C3EA4029A765E1BC95A89543BAD1BC"},
{"MIFARE Plus Troika", "040F732E0EA7DF2B38F791BF89425BF7DCDF3EE4D976669E3831F324FF15751BD52AFF1782F72FF2731EEAD5F63ABE7D126E03C856FFB942AF"},
};
uint32_t i;
bool is_valid = false;
for (i = 0; i < ARRAYLEN(nxp_desfire_public_keys); i++) {
int dl = 0;
uint8_t key[PUBLIC_DESFIRE_ECDA_KEYLEN];
param_gethex_to_eol(nxp_desfire_public_keys[i].value, 0, key, PUBLIC_DESFIRE_ECDA_KEYLEN, &dl);
int res = ecdsa_signature_r_s_verify(MBEDTLS_ECP_DP_SECP224R1, key, uid, uidlen, signature, signature_len, false);
is_valid = (res == 0);
if (is_valid)
break;
}
// PrintAndLogEx(NORMAL, "");
// PrintAndLogEx(INFO, "--- " _CYAN_("Tag Signature"));
if (is_valid == false || i == ARRAYLEN(nxp_desfire_public_keys)) {
PrintAndLogEx(INFO, " Elliptic curve parameters: NID_secp224r1");
PrintAndLogEx(INFO, " TAG IC Signature: %s", sprint_hex_inrow(signature, 16));
PrintAndLogEx(INFO, " : %s", sprint_hex_inrow(signature + 16, 16));
PrintAndLogEx(INFO, " : %s", sprint_hex_inrow(signature + 32, 16));
PrintAndLogEx(INFO, " : %s", sprint_hex_inrow(signature + 48, signature_len - 48));
PrintAndLogEx(SUCCESS, " Signature verification: " _RED_("failed"));
return PM3_ESOFT;
}
PrintAndLogEx(INFO, " IC signature public key name: " _GREEN_("%s"), nxp_desfire_public_keys[i].desc);
PrintAndLogEx(INFO, "IC signature public key value: %.32s", nxp_desfire_public_keys[i].value);
PrintAndLogEx(INFO, " : %.32s", nxp_desfire_public_keys[i].value + 32);
PrintAndLogEx(INFO, " : %.32s", nxp_desfire_public_keys[i].value + 64);
PrintAndLogEx(INFO, " : %.32s", nxp_desfire_public_keys[i].value + 96);
PrintAndLogEx(INFO, " Elliptic curve parameters: NID_secp224r1");
PrintAndLogEx(INFO, " TAG IC Signature: %s", sprint_hex_inrow(signature, 16));
PrintAndLogEx(INFO, " : %s", sprint_hex_inrow(signature + 16, 16));
PrintAndLogEx(INFO, " : %s", sprint_hex_inrow(signature + 32, 16));
PrintAndLogEx(INFO, " : %s", sprint_hex_inrow(signature + 48, signature_len - 48));
PrintAndLogEx(SUCCESS, " Signature verification: " _GREEN_("successful"));
return PM3_SUCCESS;
int index = originality_check_verify(uid, uidlen, signature, signature_len, PK_MFDES);
PrintAndLogEx(NORMAL, "");
return originality_check_print(signature, signature_len, index);
}
static void swap24(uint8_t *data) {
+3 -48
View File
@@ -35,6 +35,7 @@
#include "crypto/libpcrypto.h"
#include "cmdhfmf.h" // printblock, header
#include "cmdtrace.h"
#include "crypto/originality.h"
static const uint8_t mfp_default_key[16] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
static uint16_t mfp_card_adresses[] = {0x9000, 0x9001, 0x9002, 0x9003, 0x9004, 0x9006, 0x9007, 0xA000, 0xA001, 0xA080, 0xA081, 0xC000, 0xC001};
@@ -190,55 +191,9 @@ static nxp_cardtype_t getCardType(uint8_t type, uint8_t major, uint8_t minor) {
// --- GET SIGNATURE
static int plus_print_signature(uint8_t *uid, uint8_t uidlen, uint8_t *signature, int signature_len) {
// ref: MIFARE Plus EV1 Originality Signature Validation
#define PUBLIC_PLUS_ECDA_KEYLEN 57
const ecdsa_publickey_t nxp_plus_public_keys[] = {
{"MIFARE Plus EV1", "044409ADC42F91A8394066BA83D872FB1D16803734E911170412DDF8BAD1A4DADFD0416291AFE1C748253925DA39A5F39A1C557FFACD34C62E"},
{"MIFARE Plus Ev2", "04BB49AE4447E6B1B6D21C098C1538B594A11A4A1DBF3D5E673DEACDEB3CC512D1C08AFA1A2768CE20A200BACD2DC7804CD7523A0131ABF607"},
{"MIFARE Plus Troika", "040F732E0EA7DF2B38F791BF89425BF7DCDF3EE4D976669E3831F324FF15751BD52AFF1782F72FF2731EEAD5F63ABE7D126E03C856FFB942AF"}
};
uint8_t i;
bool is_valid = false;
for (i = 0; i < ARRAYLEN(nxp_plus_public_keys); i++) {
int dl = 0;
uint8_t key[PUBLIC_PLUS_ECDA_KEYLEN];
param_gethex_to_eol(nxp_plus_public_keys[i].value, 0, key, PUBLIC_PLUS_ECDA_KEYLEN, &dl);
int res = ecdsa_signature_r_s_verify(MBEDTLS_ECP_DP_SECP224R1, key, uid, uidlen, signature, signature_len, false);
is_valid = (res == 0);
if (is_valid)
break;
}
int index = originality_check_verify(uid, uidlen, signature, signature_len, PK_MFP);
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, "--- " _CYAN_("Tag Signature"));
if (is_valid == false || i == ARRAYLEN(nxp_plus_public_keys)) {
PrintAndLogEx(INFO, " Elliptic curve parameters: NID_secp224r1");
PrintAndLogEx(INFO, " TAG IC Signature: %s", sprint_hex_inrow(signature, 16));
PrintAndLogEx(INFO, " : %s", sprint_hex_inrow(signature + 16, 16));
PrintAndLogEx(INFO, " : %s", sprint_hex_inrow(signature + 32, 16));
PrintAndLogEx(INFO, " : %s", sprint_hex_inrow(signature + 48, signature_len - 48));
PrintAndLogEx(SUCCESS, " Signature verification: " _RED_("failed"));
return PM3_ESOFT;
}
PrintAndLogEx(INFO, " IC signature public key name: " _GREEN_("%s"), nxp_plus_public_keys[i].desc);
PrintAndLogEx(INFO, "IC signature public key value: %.32s", nxp_plus_public_keys[i].value);
PrintAndLogEx(INFO, " : %.32s", nxp_plus_public_keys[i].value + 32);
PrintAndLogEx(INFO, " : %.32s", nxp_plus_public_keys[i].value + 64);
PrintAndLogEx(INFO, " : %.32s", nxp_plus_public_keys[i].value + 96);
PrintAndLogEx(INFO, " Elliptic curve parameters: NID_secp224r1");
PrintAndLogEx(INFO, " TAG IC Signature: %s", sprint_hex_inrow(signature, 16));
PrintAndLogEx(INFO, " : %s", sprint_hex_inrow(signature + 16, 16));
PrintAndLogEx(INFO, " : %s", sprint_hex_inrow(signature + 32, 16));
PrintAndLogEx(INFO, " : %s", sprint_hex_inrow(signature + 48, signature_len - 48));
PrintAndLogEx(SUCCESS, " Signature verification: " _GREEN_("successful"));
return PM3_SUCCESS;
return originality_check_print(signature, signature_len, index);
}
static int get_plus_signature(uint8_t *signature, int *signature_len) {
+100 -150
View File
@@ -35,6 +35,7 @@
#include "fileutils.h" // saveFile
#include "cmdtrace.h" // trace list
#include "preferences.h" // setDeviceDebugLevel
#include "crypto/originality.h"
#define MAX_UL_BLOCKS 0x0F
#define MAX_ULC_BLOCKS 0x2F
@@ -53,6 +54,8 @@
#define MAX_MY_D_MOVE_LEAN 0x0F
#define MAX_UL_NANO_40 0x0A
#define MAX_UL_AES 0x37
#define MAX_ST25TN512 0x3F
#define MAX_ST25TN01K 0x3F
static int CmdHelp(const char *Cmd);
@@ -103,7 +106,9 @@ static uint64_t UL_TYPES_ARRAY[] = {
MFU_TT_MAGIC_1A, MFU_TT_MAGIC_1B,
MFU_TT_MAGIC_NTAG, MFU_TT_NTAG_210u,
MFU_TT_UL_MAGIC, MFU_TT_UL_C_MAGIC,
MFU_TT_UL_AES
MFU_TT_UL_AES,
MFU_TT_ST25TN512, MFU_TT_ST25TN01K,
};
static uint8_t UL_MEMORY_ARRAY[ARRAYLEN(UL_TYPES_ARRAY)] = {
@@ -124,7 +129,9 @@ static uint8_t UL_MEMORY_ARRAY[ARRAYLEN(UL_TYPES_ARRAY)] = {
// MAGIC_1A, MAGIC_1B, MAGIC_NTAG,
MAX_UL_BLOCKS, MAX_UL_BLOCKS, MAX_NTAG_216,
// NTAG_210u, UL_MAGIC, UL_C_MAGIC
MAX_NTAG_210, MAX_UL_BLOCKS, MAX_ULC_BLOCKS, MAX_UL_AES
MAX_NTAG_210, MAX_UL_BLOCKS, MAX_ULC_BLOCKS, MAX_UL_AES,
// ST25TN512, ST25TN01K,
MAX_ST25TN512, MAX_ST25TN01K,
};
static const ul_family_t ul_family[] = {
@@ -789,7 +796,13 @@ static int ul_print_default(uint8_t *data, uint8_t *real_uid) {
PrintAndLogEx(SUCCESS, " BCC1: %02X ( " _GREEN_("ok") " )", data[8]);
else
PrintAndLogEx(NORMAL, " BCC1: %02X, crc should be %02X", data[8], crc1);
PrintAndLogEx(SUCCESS, " Internal: %02X ( %s )", data[9], (data[9] == 0x48) ? _GREEN_("default") : _RED_("not default"));
if (uid[0] == 0x04) {
PrintAndLogEx(SUCCESS, " Internal: %02X ( %s )", data[9], (data[9] == 0x48) ? _GREEN_("default") : _RED_("not default"));
} else if (uid[0] == 0x02) {
PrintAndLogEx(SUCCESS, " Sysblock: %02X ( %s )", data[9], (data[9] == 0x2C) ? _GREEN_("default") : _RED_("not default"));
} else {
PrintAndLogEx(SUCCESS, " Internal: %02X", data[9]);
}
} else {
PrintAndLogEx(SUCCESS, "Blocks 0-2: %s", sprint_hex(data + 0, 12));
}
@@ -1011,6 +1024,10 @@ int ul_print_type(uint64_t tagtype, uint8_t spaces) {
snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("INFINEON my-d\x99 move lean (SLE 66R01L)"), spaces, "");
else if (tagtype & MFU_TT_FUDAN_UL)
snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("FUDAN Ultralight Compatible (or other compatible)"), spaces, "");
else if (tagtype & MFU_TT_ST25TN512)
snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("ST ST25TN512 64bytes"), spaces, "");
else if (tagtype & MFU_TT_ST25TN01K)
snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("ST ST25TN01K 160bytes"), spaces, "");
else
snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("Unknown %06" PRIx64), spaces, "", tagtype);
@@ -1397,132 +1414,14 @@ static int ulev1_print_counters(void) {
}
static int ulev1_print_signature(uint64_t tagtype, uint8_t *uid, uint8_t *signature, size_t signature_len) {
#define PUBLIC_ECDA_KEYLEN 33
#define PUBLIC_ECDA_192_KEYLEN 49
// known public keys for the originality check (source: https://github.com/alexbatalov/node-nxp-originality-verifier)
// ref: AN11350 NTAG 21x Originality Signature Validation
// ref: AN11341 MIFARE Ultralight EV1 Originality Signature Validation
const ecdsa_publickey_t nxp_mfu_public_keys[] = {
{"NXP MIFARE Classic MFC1C14_x", "044F6D3F294DEA5737F0F46FFEE88A356EED95695DD7E0C27A591E6F6F65962BAF"},
{"MIFARE Classic / QL88", "046F70AC557F5461CE5052C8E4A7838C11C7A236797E8A0730A101837C004039C2"},
{"NXP ICODE DNA, ICODE SLIX2", "048878A2A2D3EEC336B4F261A082BD71F9BE11C4E2E896648B32EFA59CEA6E59F0"},
{"NXP Public key", "04A748B6A632FBEE2C0897702B33BEA1C074998E17B84ACA04FF267E5D2C91F6DC"},
{"NXP Ultralight Ev1", "0490933BDCD6E99B4E255E3DA55389A827564E11718E017292FAF23226A96614B8"},
{"NXP NTAG21x (2013)", "04494E1A386D3D3CFE3DC10E5DE68A499B1C202DB5B132393E89ED19FE5BE8BC61"},
{"MIKRON Public key", "04F971EDA742A4A80D32DCF6A814A707CC3DC396D35902F72929FDCD698B3468F2"},
{"VivoKey Spark1 Public key", "04D64BB732C0D214E7EC580736ACF847284B502C25C0F7F2FA86AACE1DADA4387A"},
{"TruST25 (ST) key 01?", "041D92163650161A2548D33881C235D0FB2315C2C31A442F23C87ACF14497C0CBA"},
{"TruST25 (ST) key 04?", "04101E188A8B4CDDBC62D5BC3E0E6850F0C2730E744B79765A0E079907FBDB01BC"},
};
// https://www.nxp.com/docs/en/application-note/AN13452.pdf
const ecdsa_publickey_t nxp_mfu_192_public_keys[] = {
{"NXP Ultralight AES", "0453BF8C49B7BD9FE3207A91513B9C1D238ECAB07186B772104AB535F7D3AE63CF7C7F3DD0D169DA3E99E43C6399621A86"},
};
/*
uint8_t nxp_mfu_public_keys[6][PUBLIC_ECDA_KEYLEN] = {
// UL, NTAG21x and NDEF
{
0x04, 0x49, 0x4e, 0x1a, 0x38, 0x6d, 0x3d, 0x3c,
0xfe, 0x3d, 0xc1, 0x0e, 0x5d, 0xe6, 0x8a, 0x49,
0x9b, 0x1c, 0x20, 0x2d, 0xb5, 0xb1, 0x32, 0x39,
0x3e, 0x89, 0xed, 0x19, 0xfe, 0x5b, 0xe8, 0xbc, 0x61
},
// UL EV1
{
0x04, 0x90, 0x93, 0x3b, 0xdc, 0xd6, 0xe9, 0x9b,
0x4e, 0x25, 0x5e, 0x3d, 0xa5, 0x53, 0x89, 0xa8,
0x27, 0x56, 0x4e, 0x11, 0x71, 0x8e, 0x01, 0x72,
0x92, 0xfa, 0xf2, 0x32, 0x26, 0xa9, 0x66, 0x14, 0xb8
},
// unknown. Needs identification
{
0x04, 0x4F, 0x6D, 0x3F, 0x29, 0x4D, 0xEA, 0x57,
0x37, 0xF0, 0xF4, 0x6F, 0xFE, 0xE8, 0x8A, 0x35,
0x6E, 0xED, 0x95, 0x69, 0x5D, 0xD7, 0xE0, 0xC2,
0x7A, 0x59, 0x1E, 0x6F, 0x6F, 0x65, 0x96, 0x2B, 0xAF
},
// unknown. Needs identification
{
0x04, 0xA7, 0x48, 0xB6, 0xA6, 0x32, 0xFB, 0xEE,
0x2C, 0x08, 0x97, 0x70, 0x2B, 0x33, 0xBE, 0xA1,
0xC0, 0x74, 0x99, 0x8E, 0x17, 0xB8, 0x4A, 0xCA,
0x04, 0xFF, 0x26, 0x7E, 0x5D, 0x2C, 0x91, 0xF6, 0xDC
},
// manufacturer public key
{
0x04, 0x6F, 0x70, 0xAC, 0x55, 0x7F, 0x54, 0x61,
0xCE, 0x50, 0x52, 0xC8, 0xE4, 0xA7, 0x83, 0x8C,
0x11, 0xC7, 0xA2, 0x36, 0x79, 0x7E, 0x8A, 0x07,
0x30, 0xA1, 0x01, 0x83, 0x7C, 0x00, 0x40, 0x39, 0xC2
},
// MIKRON public key.
{
0x04, 0xf9, 0x71, 0xed, 0xa7, 0x42, 0xa4, 0xa8,
0x0d, 0x32, 0xdc, 0xf6, 0xa8, 0x14, 0xa7, 0x07,
0xcc, 0x3d, 0xc3, 0x96, 0xd3, 0x59, 0x02, 0xf7,
0x29, 0x29, 0xfd, 0xcd, 0x69, 0x8b, 0x34, 0x68, 0xf2
}
};
*/
uint8_t i;
bool is_valid = false;
int index = -1;
if (signature_len == 32) {
for (i = 0; i < ARRAYLEN(nxp_mfu_public_keys); i++) {
int dl = 0;
uint8_t key[PUBLIC_ECDA_KEYLEN] = {0};
param_gethex_to_eol(nxp_mfu_public_keys[i].value, 0, key, PUBLIC_ECDA_KEYLEN, &dl);
int res = ecdsa_signature_r_s_verify(MBEDTLS_ECP_DP_SECP128R1, key, uid, 7, signature, signature_len, false);
is_valid = (res == 0);
if (is_valid)
break;
}
index = originality_check_verify(uid, 7, signature, signature_len, PK_MFUL);
} else if (signature_len == 48) {
index = originality_check_verify(uid, 7, signature, signature_len, PK_MFULAES);
}
bool is_192_valid = false;
if (signature_len == 48) {
for (i = 0; i < ARRAYLEN(nxp_mfu_192_public_keys); i++) {
int dl = 0;
uint8_t key[PUBLIC_ECDA_192_KEYLEN] = {0};
param_gethex_to_eol(nxp_mfu_192_public_keys[i].value, 0, key, PUBLIC_ECDA_192_KEYLEN, &dl);
int res = ecdsa_signature_r_s_verify(MBEDTLS_ECP_DP_SECP192R1, key, uid, 7, signature, signature_len, false);
is_192_valid = (res == 0);
if (is_192_valid)
break;
}
}
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, "--- " _CYAN_("Tag Signature"));
if (is_192_valid) {
PrintAndLogEx(INFO, " IC signature public key name: " _GREEN_("%s"), nxp_mfu_192_public_keys[i].desc);
PrintAndLogEx(INFO, "IC signature public key value: %s", nxp_mfu_192_public_keys[i].value);
PrintAndLogEx(INFO, " Elliptic curve parameters: NID_secp192r1");
PrintAndLogEx(INFO, " TAG IC Signature: %s", sprint_hex_inrow(signature, signature_len));
PrintAndLogEx(SUCCESS, " Signature verification ( " _GREEN_("successful") " )");
return PM3_SUCCESS;
}
if (is_valid) {
PrintAndLogEx(INFO, " IC signature public key name: " _GREEN_("%s"), nxp_mfu_public_keys[i].desc);
PrintAndLogEx(INFO, "IC signature public key value: %s", nxp_mfu_public_keys[i].value);
PrintAndLogEx(INFO, " Elliptic curve parameters: NID_secp128r1");
PrintAndLogEx(INFO, " TAG IC Signature: %s", sprint_hex_inrow(signature, signature_len));
PrintAndLogEx(SUCCESS, " Signature verification ( " _GREEN_("successful") " )");
return PM3_SUCCESS;
}
PrintAndLogEx(INFO, " Elliptic curve parameters: %s", (signature_len == 48) ? "NID_secp192r1" : "NID_secp128r1");
PrintAndLogEx(INFO, " TAG IC Signature: %s", sprint_hex_inrow(signature, signature_len));
PrintAndLogEx(SUCCESS, " Signature verification ( " _RED_("fail") " )");
return PM3_ESOFT;
return originality_check_print(signature, signature_len, index);
}
static int ulev1_print_version(uint8_t *data) {
@@ -2115,17 +2014,55 @@ uint64_t GetHF14AMfU_Type(void) {
// Ultralight - ATQA / SAK
if (card.atqa[1] != 0x00 || card.atqa[0] != 0x44 || card.sak != 0x00) {
//PrintAndLogEx(NORMAL, "Tag is not Ultralight | NTAG | MY-D [ATQA: %02X %02X SAK: %02X]\n", card.atqa[1], card.atqa[0], card.sak);
//PrintAndLogEx(NORMAL, "Tag is not Ultralight | NTAG | MY-D |ST25TN [ATQA: %02X %02X SAK: %02X]\n", card.atqa[1], card.atqa[0], card.sak);
DropField();
return MFU_TT_UL_ERROR;
}
if (card.uid[0] != 0x05) {
if (card.uid[0] == 0x02) {
// ST25TN
// read SYSBLOCK
uint8_t data[4] = {0x00};
int status = ul_read(0x02, data, sizeof(data));
if (status <= 1) {
tagtype = MFU_TT_UL;
} else {
status = ul_read(data[1] + 1, data, sizeof(data));
if (status <= 1) {
tagtype = MFU_TT_UL;
} else {
// data[3] == KID == 0x05 Key ID
// data[2] == REV == 0x13 Product version
if ((data[1]==0x90) && (data[0]==0x90)) {
tagtype = MFU_TT_ST25TN01K;
} else if ((data[1]==0x90) && (data[0]==0x91)) {
tagtype = MFU_TT_ST25TN512;
}
}
}
} else if (card.uid[0] == 0x05) {
// Infineon MY-D tests Exam high nibble
DropField();
uint8_t nib = (card.uid[1] & 0xf0) >> 4;
switch (nib) {
// case 0: tagtype = SLE66R35E7; break; //or SLE 66R35E7 - mifare compat... should have different sak/atqa for mf 1k
case 1:
tagtype = MFU_TT_MY_D;
break; // or SLE 66RxxS ... up to 512 pages of 8 user bytes...
case 2:
tagtype = MFU_TT_MY_D_NFC;
break; // or SLE 66RxxP ... up to 512 pages of 8 user bytes... (or in nfc mode FF pages of 4 bytes)
case 3:
tagtype = (MFU_TT_MY_D_MOVE | MFU_TT_MY_D_MOVE_NFC);
break; // or SLE 66R01P // 38 pages of 4 bytes //notice: we can not currently distinguish between these two
case 7:
tagtype = MFU_TT_MY_D_MOVE_LEAN;
break; // or SLE 66R01L // 16 pages of 4 bytes
}
} else {
uint8_t version[10] = {0x00};
int len = ulev1_getVersion(version, sizeof(version));
DropField();
switch (len) {
case 0x0A: {
/*
@@ -2213,7 +2150,6 @@ uint64_t GetHF14AMfU_Type(void) {
tagtype = MFU_TT_UNKNOWN;
break;
}
// This is a test from cards that doesn't answer to GET_VERSION command
// UL vs UL-C vs NTAG203 vs FUDAN FM11NT021 (which is NTAG213 compatiable)
if (tagtype & (MFU_TT_UL | MFU_TT_UL_C | MFU_TT_NTAG_203)) {
@@ -2267,25 +2203,6 @@ uint64_t GetHF14AMfU_Type(void) {
tagtype = ul_fudan_check();
DropField();
}
} else {
DropField();
// Infinition MY-D tests Exam high nibble
uint8_t nib = (card.uid[1] & 0xf0) >> 4;
switch (nib) {
// case 0: tagtype = SLE66R35E7; break; //or SLE 66R35E7 - mifare compat... should have different sak/atqa for mf 1k
case 1:
tagtype = MFU_TT_MY_D;
break; // or SLE 66RxxS ... up to 512 pages of 8 user bytes...
case 2:
tagtype = MFU_TT_MY_D_NFC;
break; // or SLE 66RxxP ... up to 512 pages of 8 user bytes... (or in nfc mode FF pages of 4 bytes)
case 3:
tagtype = (MFU_TT_MY_D_MOVE | MFU_TT_MY_D_MOVE_NFC);
break; // or SLE 66R01P // 38 pages of 4 bytes //notice: we can not currently distinguish between these two
case 7:
tagtype = MFU_TT_MY_D_MOVE_LEAN;
break; // or SLE 66R01L // 16 pages of 4 bytes
}
}
tagtype |= ul_magic_test();
@@ -2495,6 +2412,39 @@ static int CmdHF14AMfUInfo(const char *Cmd) {
}
}
// ST25TN info & signature
if (tagtype & (MFU_TT_ST25TN512 | MFU_TT_ST25TN01K)) {
status = ul_read(0x02, data, sizeof(data));
if (status <= 1) {
PrintAndLogEx(ERR, "Error: tag didn't answer to READ SYSBLOCK");
DropField();
return PM3_ESOFT;
}
status = ul_read(data[1] + 1, data, sizeof(data));
if (status <= 1) {
PrintAndLogEx(ERR, "Error: tag didn't answer to READ SYSBLOCK");
DropField();
return PM3_ESOFT;
}
PrintAndLogEx(INFO, "--- " _CYAN_("Tag System Information"));
PrintAndLogEx(INFO, " Key ID: %02x", data[3]);
PrintAndLogEx(INFO, " Product Version: %02x", data[2]);
PrintAndLogEx(INFO, " Product Code: %02x%02x", data[1], data[0]);
uint8_t signature[32] = {0};
for (int blkoff=0; blkoff<8; blkoff++) {
status = ul_read(0x34 + blkoff, signature + (blkoff * 4), 4);
if (status <= 1) {
PrintAndLogEx(ERR, "Error: tag didn't answer to READ SYSBLOCK");
DropField();
return PM3_ESOFT;
}
}
// check signature
int index = originality_check_verify_ex(card.uid, 7, signature, sizeof(signature), PK_ST25TN, false, true);
PrintAndLogEx(NORMAL, "");
originality_check_print(signature, sizeof(signature), index);
}
// Read signature
if ((tagtype & (MFU_TT_UL_EV1_48 | MFU_TT_UL_EV1_128 | MFU_TT_UL_EV1 | MFU_TT_UL_NANO_40 |
MFU_TT_NTAG_210u | MFU_TT_NTAG_213 | MFU_TT_NTAG_213_F | MFU_TT_NTAG_213_C |
+2
View File
@@ -96,6 +96,8 @@ int CmdHF14MfUTamper(const char *Cmd);
#define MFU_TT_MAGIC_4 0x400000000ULL
#define MFU_TT_MAGIC_4_GDM 0x800000000ULL
#define MFU_TT_MAGIC_NTAG21X 0x1000000000ULL
#define MFU_TT_ST25TN512 0x2000000000ULL
#define MFU_TT_ST25TN01K 0x4000000000ULL
#define MFU_TT_UL_MAGIC (MFU_TT_UL | MFU_TT_MAGIC)
#define MFU_TT_UL_C_MAGIC (MFU_TT_UL_C | MFU_TT_MAGIC)
// Don't forget to fill UL_TYPES_ARRAY and UL_MEMORY_ARRAY if new types are added
+11 -43
View File
@@ -33,6 +33,7 @@
#include "commonutil.h" // get_sw
#include "protocols.h" // ISO7816 APDU return codes
#include "crypto/libpcrypto.h" // ecdsa
#include "crypto/originality.h"
#define TIMEOUT 2000
@@ -148,48 +149,9 @@ static void print_st25ta_system_info(uint8_t *d, uint8_t n) {
}
static int print_st25ta_signature(uint8_t *uid, uint8_t *signature) {
#define PUBLIC_ECDA_KEYLEN 33
// known public keys for the originality check (source: https://github.com/alexbatalov/node-nxp-originality-verifier)
// ref: AN11350 NTAG 21x Originality Signature Validation
// ref: AN11341 MIFARE Ultralight EV1 Originality Signature Validation
const ecdsa_publickey_t nxp_mfu_public_keys[] = {
{"NXP MIFARE Classic MFC1C14_x", "044F6D3F294DEA5737F0F46FFEE88A356EED95695DD7E0C27A591E6F6F65962BAF"},
{"MIFARE Classic / QL88", "046F70AC557F5461CE5052C8E4A7838C11C7A236797E8A0730A101837C004039C2"},
{"NXP ICODE DNA, ICODE SLIX2", "048878A2A2D3EEC336B4F261A082BD71F9BE11C4E2E896648B32EFA59CEA6E59F0"},
{"NXP Public key", "04A748B6A632FBEE2C0897702B33BEA1C074998E17B84ACA04FF267E5D2C91F6DC"},
{"NXP Ultralight Ev1", "0490933BDCD6E99B4E255E3DA55389A827564E11718E017292FAF23226A96614B8"},
{"NXP NTAG21x (2013)", "04494E1A386D3D3CFE3DC10E5DE68A499B1C202DB5B132393E89ED19FE5BE8BC61"},
{"MIKRON Public key", "04F971EDA742A4A80D32DCF6A814A707CC3DC396D35902F72929FDCD698B3468F2"},
{"VivoKey Spark1 Public key", "04D64BB732C0D214E7EC580736ACF847284B502C25C0F7F2FA86AACE1DADA4387A"},
{"TruST25 (ST) key 01?", "041D92163650161A2548D33881C235D0FB2315C2C31A442F23C87ACF14497C0CBA"},
{"TruST25 (ST) key 04?", "04101E188A8B4CDDBC62D5BC3E0E6850F0C2730E744B79765A0E079907FBDB01BC"},
};
for (uint8_t i = 0; i < ARRAYLEN(nxp_mfu_public_keys); i++) {
int dl = 0;
uint8_t key[PUBLIC_ECDA_KEYLEN] = {0};
param_gethex_to_eol(nxp_mfu_public_keys[i].value, 0, key, PUBLIC_ECDA_KEYLEN, &dl);
int res = ecdsa_signature_r_s_verify(MBEDTLS_ECP_DP_SECP128R1, key, uid, 7, signature, 32, true);
if (res == 0) {
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, "--- " _CYAN_("Tag Signature"));
PrintAndLogEx(INFO, " IC signature public key name: " _GREEN_("%s"), nxp_mfu_public_keys[i].desc);
PrintAndLogEx(INFO, "IC signature public key value: %s", nxp_mfu_public_keys[i].value);
PrintAndLogEx(INFO, " Elliptic curve parameters: NID_secp128r1");
PrintAndLogEx(INFO, " TAG IC Signature: %s", sprint_hex_inrow(signature, 32));
PrintAndLogEx(SUCCESS, " Signature verification ( " _GREEN_("successful") " )");
return PM3_SUCCESS;
}
}
return PM3_ESOFT;
int index = originality_check_verify_ex(uid, 7, signature, 32, PK_ST25TA, false, true);
PrintAndLogEx(NORMAL, "");
return originality_check_print(signature, 32, index);
}
static int st25ta_get_signature(uint8_t *signature) {
@@ -221,7 +183,13 @@ static int st25ta_get_signature(uint8_t *signature) {
}
activate_field = false;
}
if (resplen != 32) {
if ((resplen == 2) && (resp[0] == 0x69) && (resp[1] == 0x82)) {
PrintAndLogEx(WARNING, "GetSignature: Security status not satisfied");
}
DropField();
return PM3_ESOFT;
}
if (signature) {
memcpy(signature, resp, 32);
}
+10
View File
@@ -779,6 +779,7 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr
switch (protocol) {
case ISO_14443A:
case ISO_7816_4:
case PROTO_FMCOS20:
annotateIso14443a(explanation, sizeof(explanation), frame, data_len, hdr->isResponse);
break;
case PROTO_MIFARE:
@@ -836,6 +837,9 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr
case SEOS:
annotateSeos(explanation, sizeof(explanation), frame, data_len);
break;
case PROTO_FMCOS20:
annotateFMCOS20(explanation, sizeof(explanation), frame, data_len);
break;
default:
break;
}
@@ -1310,6 +1314,7 @@ int CmdTraceList(const char *Cmd) {
"trace list -t thinfilm -> interpret as " _YELLOW_("Thinfilm") "\n"
"trace list -t topaz -> interpret as " _YELLOW_("Topaz") "\n"
"trace list -t mfp -> interpret as " _YELLOW_("MIFARE Plus") "\n"
"trace list -t fmcos20 -> interpret as " _YELLOW_("FMCOS 2.0") "\n"
"\n"
"trace list -t mf -f mfc_default_keys.dic -> use default dictionary file\n"
"trace list -t 14a --frame -> show frame delay times\n"
@@ -1377,6 +1382,7 @@ int CmdTraceList(const char *Cmd) {
else if (strcmp(type, "thinfilm") == 0) protocol = THINFILM;
else if (strcmp(type, "topaz") == 0) protocol = TOPAZ;
else if (strcmp(type, "mfp") == 0) protocol = PROTO_MFPLUS;
else if (strcmp(type, "fmcos20") == 0) protocol = PROTO_FMCOS20;
else if (strcmp(type, "") == 0) protocol = -1;
else {
PrintAndLogEx(FAILED, "Unknown protocol \"%s\"", type);
@@ -1460,6 +1466,10 @@ int CmdTraceList(const char *Cmd) {
PrintAndLogEx(INFO, _YELLOW_("Hitag 1 / Hitag 2 / Hitag S") " - Timings in ETU (8us)");
}
if (protocol == PROTO_FMCOS20) {
PrintAndLogEx(INFO, _YELLOW_("FMCOS 2.0 / CPU Card") " - Timings n/a");
}
if (protocol == FELICA) {
if (use_us)
PrintAndLogEx(INFO, _YELLOW_("ISO18092 / FeliCa") " - all times are in microseconds");
+174
View File
@@ -0,0 +1,174 @@
//-----------------------------------------------------------------------------
// Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// See LICENSE.txt for the text of the license.
//-----------------------------------------------------------------------------
// originality checks with known pk
//-----------------------------------------------------------------------------
#include "originality.h"
#include <string.h> // memcpy
#include "ui.h"
// See tools/recover_pk.py to recover Pk from UIDs and signatures
const ecdsa_publickey_ng_t manufacturer_public_keys[] = {
{PK_MFC, MBEDTLS_ECP_DP_SECP128R1, 33, "NXP MIFARE Classic MFC1C14_x",
"044F6D3F294DEA5737F0F46FFEE88A356EED95695DD7E0C27A591E6F6F65962BAF"},
{PK_MFC, MBEDTLS_ECP_DP_SECP128R1, 33, "MIFARE Classic / QL88",
"046F70AC557F5461CE5052C8E4A7838C11C7A236797E8A0730A101837C004039C2"},
// ref: TagInfo
// NTAG 210/212 ? not present in recover_pk
{PK_MFUL, MBEDTLS_ECP_DP_SECP128R1, 33, "NXP Public key",
"04A748B6A632FBEE2C0897702B33BEA1C074998E17B84ACA04FF267E5D2C91F6DC"},
// ref: AN11341 MIFARE Ultralight EV1 Originality Signature Validation
{PK_MFUL, MBEDTLS_ECP_DP_SECP128R1, 33, "NXP Ultralight EV1",
"0490933BDCD6E99B4E255E3DA55389A827564E11718E017292FAF23226A96614B8"},
// ref: AN11350 NTAG 21x Originality Signature Validation
{PK_MFUL, MBEDTLS_ECP_DP_SECP128R1, 33, "NXP NTAG21x (2013)",
"04494E1A386D3D3CFE3DC10E5DE68A499B1C202DB5B132393E89ED19FE5BE8BC61"},
// ref: AN13452 MIFARE Ultralight AES features and hints
{PK_MFULAES, MBEDTLS_ECP_DP_SECP192R1, 49, "NXP Ultralight AES",
"0453BF8C49B7BD9FE3207A91513B9C1D238ECAB07186B772104AB535F7D3AE63CF7C7F3DD0D169DA3E99E43C6399621A86"},
// ref: TagInfo
{PK_MFULAES, MBEDTLS_ECP_DP_SECP192R1, 49, "NXP Ultralight AES (alt key)",
"04DC34DAA903F2726A6225B11C692AF6AB4396575CA12810CBBCE3F781A097B3833B50AB364A70D9C2B641A728A599AE74"},
{PK_MFP, MBEDTLS_ECP_DP_SECP224R1, 57, "MIFARE Plus EV1",
"044409ADC42F91A8394066BA83D872FB1D16803734E911170412DDF8BAD1A4DADFD0416291AFE1C748253925DA39A5F39A1C557FFACD34C62E"},
// not present in recover_pk
{PK_MFP, MBEDTLS_ECP_DP_SECP224R1, 57, "MIFARE Plus EV2",
"04BB49AE4447E6B1B6D21C098C1538B594A11A4A1DBF3D5E673DEACDEB3CC512D1C08AFA1A2768CE20A200BACD2DC7804CD7523A0131ABF607"},
{PK_MFP, MBEDTLS_ECP_DP_SECP224R1, 57, "MIFARE Plus Troika",
"040F732E0EA7DF2B38F791BF89425BF7DCDF3EE4D976669E3831F324FF15751BD52AFF1782F72FF2731EEAD5F63ABE7D126E03C856FFB942AF"},
// ref: AN12343 MIFARE DESFire Light Features and Hints
// not present in recover_pk
{PK_MFDES, MBEDTLS_ECP_DP_SECP224R1, 57, "DESFire Light",
"040E98E117AAA36457F43173DC920A8757267F44CE4EC5ADD3C54075571AEBBF7B942A9774A1D94AD02572427E5AE0A2DD36591B1FB34FCF3D"},
{PK_MFDES, MBEDTLS_ECP_DP_SECP224R1, 57, "NTAG413DNA, DESFire EV1",
"04BB5D514F7050025C7D0F397310360EEC91EAF792E96FC7E0F496CB4E669D414F877B7B27901FE67C2E3B33CD39D1C797715189AC951C2ADD"},
{PK_MFDES, MBEDTLS_ECP_DP_SECP224R1, 57, "NTAG424DNA, NTAG424DNATT, DESFire EV2, DESFire Light EV2",
"04B304DC4C615F5326FE9383DDEC9AA892DF3A57FA7FFB3276192BC0EAA252ED45A865E3B093A3D0DCE5BE29E92F1392CE7DE321E3E5C52B3A"},
// ref: AN12196 NTAG 424 DNA and NTAG 424 DNA TagTamper features and hints
{PK_MFDES, MBEDTLS_ECP_DP_SECP224R1, 57, "NTAG424DNA, DESFire EV2, DESFire Light",
"048A9B380AF2EE1B98DC417FECC263F8449C7625CECE82D9B916C992DA209D68422B81EC20B65A66B5102A61596AF3379200599316A00A1410"},
{PK_MFDES, MBEDTLS_ECP_DP_SECP224R1, 57, "DESFire EV2 XL",
"04CD5D45E50B1502F0BA4656FF37669597E7E183251150F9574CC8DA56BF01C7ABE019E29FEA48F9CE22C3EA4029A765E1BC95A89543BAD1BC"},
{PK_MFDES, MBEDTLS_ECP_DP_SECP224R1, 57, "DESFire EV3",
"041DB46C145D0A36539C6544BD6D9B0AA62FF91EC48CBC6ABAE36E0089A46F0D08C8A715EA40A63313B92E90DDC1730230E0458A33276FB743"},
// ref: AN5101 TruST25 digital signature for ST25TA512B, ST25TA02KB, ST25TA02KB-D and ST25TA02KB-P devices
{PK_ST25TA, MBEDTLS_ECP_DP_SECP128R1, 33, "ST25TA TruST25 (ST) key 01?",
"041D92163650161A2548D33881C235D0FB2315C2C31A442F23C87ACF14497C0CBA"},
// ref: AN5660 TruST25 digital signature for ST25TN512 and ST25TN01K devices
{PK_ST25TN, MBEDTLS_ECP_DP_SECP128R1, 33, "ST25TN TruST25 (ST) KeyID 05",
"0440004F974F7C76BC8718E523D85FA7B354A9A992BFA966CB8219242F9D274FD6"},
// ref: AN5104 TruST25 digital signature for ST25TV512 and ST25TV02K devices ?
// ref: AN5149 TruST25 digital signature for ST25DV02K-W1, ST25DV02K-W2 devices ?
// ref: AN5580 TruST25 digital signature for ST25TV512C and ST25TV02KC devices
{PK_ST25TV, MBEDTLS_ECP_DP_SECP128R1, 33, "ST25TV TruST25 (ST) KeyID 04",
"04101E188A8B4CDDBC62D5BC3E0E6850F0C2730E744B79765A0E079907FBDB01BC"},
{PK_15, MBEDTLS_ECP_DP_SECP128R1, 33, "NXP ICODE DNA, ICODE SLIX2",
"048878A2A2D3EEC336B4F261A082BD71F9BE11C4E2E896648B32EFA59CEA6E59F0"},
{PK_15, MBEDTLS_ECP_DP_SECP128R1, 33, "VivoKey Spark1 Public key",
"04D64BB732C0D214E7EC580736ACF847284B502C25C0F7F2FA86AACE1DADA4387A"},
// FIXME: what type(s) of card exactly? MFC? MFUL? not present in recover_pk
{PK_MIK, MBEDTLS_ECP_DP_SECP128R1, 33, "MIKRON Public key",
"04F971EDA742A4A80D32DCF6A814A707CC3DC396D35902F72929FDCD698B3468F2"},
};
// return pk if match index else -1
int originality_check_verify(uint8_t *data, uint8_t data_len, uint8_t *signature, uint8_t signature_len, pk_type_t type) {
return originality_check_verify_ex(data, data_len, signature, signature_len, type, false, false);
}
int originality_check_verify_ex(uint8_t *data, uint8_t data_len, uint8_t *signature, uint8_t signature_len, pk_type_t type, bool reverse, bool hash) {
// test if signature is null
bool is_zero = true;
for (uint8_t i = 0; i < signature_len; i++) {
if (signature[i] != 0) {
is_zero = false;
}
}
if (is_zero) {
return -1;
}
uint8_t tmp_data[data_len];
uint8_t tmp_signature[signature_len];
if (reverse) {
reverse_array_copy(data, data_len, tmp_data);
reverse_array_copy(signature, signature_len, tmp_signature);
} else {
memcpy(tmp_data, data, data_len);
memcpy(tmp_signature, signature, signature_len);
}
for (uint8_t i = 0; i < ARRAYLEN(manufacturer_public_keys); i++) {
if ((type != PK_ALL) && (type != manufacturer_public_keys[i].type))
continue;
int dl = 0;
uint8_t key[manufacturer_public_keys[i].keylen];
param_gethex_to_eol(manufacturer_public_keys[i].value, 0, key, manufacturer_public_keys[i].keylen, &dl);
if (ecdsa_signature_r_s_verify(manufacturer_public_keys[i].grp_id, key, tmp_data, data_len, tmp_signature, signature_len, hash) == 0)
return i;
}
return -1;
}
int originality_check_print(uint8_t *signature, int signature_len, int index) {
if ((index < 0) || (index >= ARRAYLEN(manufacturer_public_keys))) {
PrintAndLogEx(INFO, " TAG IC Signature: %s", sprint_hex_inrow(signature, 16));
if (signature_len > 16) {
PrintAndLogEx(INFO, " : %s", sprint_hex_inrow(signature + 16, 16));
}
if (signature_len > 32) {
PrintAndLogEx(INFO, " : %s", sprint_hex_inrow(signature + 32, 16));
}
if (signature_len > 48) {
PrintAndLogEx(INFO, " : %s", sprint_hex_inrow(signature + 48, signature_len - 48));
}
PrintAndLogEx(SUCCESS, " Signature verification: " _RED_("failed"));
return PM3_ESOFT;
}
PrintAndLogEx(INFO, " IC signature public key name: " _GREEN_("%s"), manufacturer_public_keys[index].desc);
PrintAndLogEx(INFO, "IC signature public key value: %.32s", manufacturer_public_keys[index].value);
if (manufacturer_public_keys[index].keylen > 16) {
PrintAndLogEx(INFO, " : %.32s", manufacturer_public_keys[index].value + 32);
}
if (manufacturer_public_keys[index].keylen > 32) {
PrintAndLogEx(INFO, " : %.32s", manufacturer_public_keys[index].value + 64);
}
if (manufacturer_public_keys[index].keylen > 48) {
PrintAndLogEx(INFO, " : %.32s", manufacturer_public_keys[index].value + 96);
}
PrintAndLogEx(INFO, " Elliptic curve parameters: %s", mbedtls_ecp_curve_info_from_grp_id(manufacturer_public_keys[index].grp_id)->name);
PrintAndLogEx(INFO, " TAG IC Signature: %s", sprint_hex_inrow(signature, 16));
if (signature_len > 16) {
PrintAndLogEx(INFO, " : %s", sprint_hex_inrow(signature + 16, 16));
}
if (signature_len > 32) {
PrintAndLogEx(INFO, " : %s", sprint_hex_inrow(signature + 32, 16));
}
if (signature_len > 48) {
PrintAndLogEx(INFO, " : %s", sprint_hex_inrow(signature + 48, signature_len - 48));
}
PrintAndLogEx(SUCCESS, " Signature verification: " _GREEN_("successful"));
return PM3_SUCCESS;
}
+42
View File
@@ -0,0 +1,42 @@
//-----------------------------------------------------------------------------
// Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// See LICENSE.txt for the text of the license.
//-----------------------------------------------------------------------------
// originality checks with known pk
//-----------------------------------------------------------------------------
#ifndef ORIGINALITY_H
#define ORIGINALITY_H
#include "common.h"
#include "commonutil.h"
#include "libpcrypto.h"
#include <mbedtls/pk.h>
#include <mbedtls/ecp.h>
typedef enum {PK_MFC, PK_MFUL, PK_MFULAES, PK_MFP, PK_MFDES, PK_ST25TA, PK_ST25TN, PK_ST25TV, PK_15, PK_MIK, PK_ALL} pk_type_t;
typedef struct {
const pk_type_t type;
const mbedtls_ecp_group_id grp_id;
const uint8_t keylen;
const char *desc;
const char *value;
} ecdsa_publickey_ng_t;
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_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_print(uint8_t *signature, int signature_len, int index);
#endif /* originality.h */
+2 -1
View File
@@ -2081,7 +2081,7 @@
"command": "hf 15 view",
"description": "Print a ISO-15693 tag dump file (bin/eml/json)",
"notes": [
"hf 15 view -f hf-iclass-AA162D30F8FF12F1-dump.bin"
"hf 15 view -f hf-15-1122334455667788-dump.bin"
],
"offline": true,
"options": [
@@ -12837,6 +12837,7 @@
"trace list -t thinfilm -> interpret as Thinfilm",
"trace list -t topaz -> interpret as Topaz",
"trace list -t mfp -> interpret as MIFARE Plus",
"trace list -t fmcos20 -> interpret as FMCOS 2.0",
"",
"trace list -t mf -f mfc_default_keys.dic -> use default dictionary file",
"trace list -t 14a --frame -> show frame delay times",
@@ -41,7 +41,7 @@ Alternatively, and only if the issue still persists after following the steps ab
## Apple Silicon (M1) Notes
^[Top](#top)
Ensure Rosetta 2 is installed as it's currently needed to run `arm-none-eabi-gcc` as it's delivered as a precombiled x86_64 binary.
Ensure Rosetta 2 is installed as it's currently needed to run `arm-none-eabi-gcc` as it's delivered as a precombiled x86_64 binary. **Note: Starting from v4.19552, it is no longer necessary to install Rosetta 2, Apple Silicons are already supported**
If you see an error like:

Some files were not shown because too many files have changed in this diff Show More