diff --git a/CHANGELOG.md b/CHANGELOG.md index fa298c52c..ebbd7529f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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) diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index 544fe5395..2a74b1500 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -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 diff --git a/client/Makefile b/client/Makefile index f7a59ed3f..d01e08af0 100644 --- a/client/Makefile +++ b/client/Makefile @@ -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\ diff --git a/client/experimental_lib/CMakeLists.txt b/client/experimental_lib/CMakeLists.txt index e9ac8bb33..87e653c11 100644 --- a/client/experimental_lib/CMakeLists.txt +++ b/client/experimental_lib/CMakeLists.txt @@ -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 diff --git a/client/resources/aid_desfire.json b/client/resources/aid_desfire.json index 489496127..89f8db62f 100644 --- a/client/resources/aid_desfire.json +++ b/client/resources/aid_desfire.json @@ -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", diff --git a/client/src/cmdhf14a.c b/client/src/cmdhf14a.c index d5fbf2633..cd1db3e08 100644 --- a/client/src/cmdhf14a.c +++ b/client/src/cmdhf14a.c @@ -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) { diff --git a/client/src/cmdhf15.c b/client/src/cmdhf15.c index b5d886382..b9014fe35 100644 --- a/client/src/cmdhf15.c +++ b/client/src/cmdhf15.c @@ -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, diff --git a/client/src/cmdhflist.c b/client/src/cmdhflist.c index f9016a29a..1db7fd95a 100644 --- a/client/src/cmdhflist.c +++ b/client/src/cmdhflist.c @@ -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; + } +} \ No newline at end of file diff --git a/client/src/cmdhflist.h b/client/src/cmdhflist.h index cbe18e92c..92f54e4af 100644 --- a/client/src/cmdhflist.h +++ b/client/src/cmdhflist.h @@ -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 diff --git a/client/src/cmdhfmf.c b/client/src/cmdhfmf.c index e61a6a7e9..6c72bccbf 100644 --- a/client/src/cmdhfmf.c +++ b/client/src/cmdhfmf.c @@ -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}; diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 245fae293..ee8b537c9 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -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) { diff --git a/client/src/cmdhfmfp.c b/client/src/cmdhfmfp.c index d0d230e1f..218b87504 100644 --- a/client/src/cmdhfmfp.c +++ b/client/src/cmdhfmfp.c @@ -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) { diff --git a/client/src/cmdhfmfu.c b/client/src/cmdhfmfu.c index 8e0259e2f..5094d40a3 100644 --- a/client/src/cmdhfmfu.c +++ b/client/src/cmdhfmfu.c @@ -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 | diff --git a/client/src/cmdhfmfu.h b/client/src/cmdhfmfu.h index 37dbff558..a365e76d3 100644 --- a/client/src/cmdhfmfu.h +++ b/client/src/cmdhfmfu.h @@ -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 diff --git a/client/src/cmdhfst25ta.c b/client/src/cmdhfst25ta.c index 668d3d00d..7dff65067 100644 --- a/client/src/cmdhfst25ta.c +++ b/client/src/cmdhfst25ta.c @@ -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); } diff --git a/client/src/cmdtrace.c b/client/src/cmdtrace.c index 8e19c3bb5..569e13e23 100644 --- a/client/src/cmdtrace.c +++ b/client/src/cmdtrace.c @@ -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"); diff --git a/client/src/crypto/originality.c b/client/src/crypto/originality.c new file mode 100644 index 000000000..0f2f43e35 --- /dev/null +++ b/client/src/crypto/originality.c @@ -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 // 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; +} diff --git a/client/src/crypto/originality.h b/client/src/crypto/originality.h new file mode 100644 index 000000000..c6aab57fb --- /dev/null +++ b/client/src/crypto/originality.h @@ -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 +#include + +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 */ diff --git a/doc/commands.json b/doc/commands.json index d5f9ca438..0bfc7059d 100644 --- a/doc/commands.json +++ b/doc/commands.json @@ -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", diff --git a/doc/md/Installation_Instructions/macOS-Homebrew-Installation-Instructions.md b/doc/md/Installation_Instructions/macOS-Homebrew-Installation-Instructions.md index 6c1ac3eca..68fe1e899 100644 --- a/doc/md/Installation_Instructions/macOS-Homebrew-Installation-Instructions.md +++ b/doc/md/Installation_Instructions/macOS-Homebrew-Installation-Instructions.md @@ -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: diff --git a/docker/archlinux/Dockerfile b/docker/archlinux/Dockerfile index d020b7052..900b9d04c 100644 --- a/docker/archlinux/Dockerfile +++ b/docker/archlinux/Dockerfile @@ -15,6 +15,12 @@ RUN pacman -S --noconfirm ocl-icd # Create rrg user RUN useradd -ms /bin/bash rrg RUN passwd -d rrg +ARG UART_GID +# dialout group may already exist on another numeric ID than on host +RUN if [ -n "${UART_GID}" ]; then \ + groupadd -g ${UART_GID} mydialout || true; \ + usermod -aG ${UART_GID} rrg; \ + fi RUN printf 'rrg ALL=(ALL) ALL\n' | tee -a /etc/sudoers USER rrg diff --git a/docker/archlinux/docker_build.sh b/docker/archlinux/docker_build.sh deleted file mode 100755 index be92402d6..000000000 --- a/docker/archlinux/docker_build.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -docker build -t "pm3-arch:1.0" . diff --git a/docker/archlinux/docker_rm.sh b/docker/archlinux/docker_rm.sh deleted file mode 100644 index 0c2d24f4e..000000000 --- a/docker/archlinux/docker_rm.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash - -docker rm $(docker ps -aq --filter ancestor=pm3-arch:1.0) -docker image rm pm3-arch:1.0 diff --git a/docker/archlinux/docker_run.sh b/docker/archlinux/docker_run.sh deleted file mode 100755 index f379c5307..000000000 --- a/docker/archlinux/docker_run.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -docker run --volume=$(pwd)/../..:/home/rrg/proxmark3 -w /home/rrg/proxmark3 -it pm3-arch:1.0 diff --git a/docker/build-all.sh b/docker/build-all.sh index ed56a0972..a71727ee6 100755 --- a/docker/build-all.sh +++ b/docker/build-all.sh @@ -1,5 +1,5 @@ #!/bin/bash -for os in archlinux debian-12-bookworm fedora-36 fedora-37 homebrew kali opensuse-leap opensuse-tumbleweed parrot-core-latest ubuntu-20.04 ubuntu-22.04; do - ( cd $os && ./docker_build.sh ) +for os in archlinux debian-12-bookworm debian-12-bookworm-arm64 debian-12-bookworm-armhf debian-13-trixie fedora-36 fedora-37 homebrew kali opensuse-leap opensuse-tumbleweed parrot-core-latest ubuntu-20.04 ubuntu-22.04; do + ( cd $os && ../build.sh ) done diff --git a/docker/build.sh b/docker/build.sh new file mode 100755 index 000000000..499100942 --- /dev/null +++ b/docker/build.sh @@ -0,0 +1,26 @@ +#!/bin/bash + +if [ ! -e docker_conf.inc ]; then + echo "This script must be run from within one of the subfolders" + exit 1 +fi +. docker_conf.inc +# Make sure to connect a Proxmark3 when building if you want to be able to access it from within the Docker instance +UART_PORT="$(../../pm3 --list|grep /dev|head -n1|cut -d' ' -f2)" +if [ -n "$UART_PORT" ]; then + UART_GID="$(stat -c '%g' $UART_PORT)" + BUILDARG="--build-arg UART_GID=$UART_GID" +else + BUILDARG="" +fi + +# For cross-platform support: +# cf https://github.com/multiarch/qemu-user-static +#sudo apt install qemu-user-static +# credential=yes needed to get proper sudo support in cross-platform Docker instances +#docker run --rm --privileged multiarch/qemu-user-static --reset -p yes --credential yes +#docker buildx create --use +#docker buildx inspect --bootstrap +#docker buildx build $DOCKER_PLATFORM $BUILDARG -t "$DOCKER_IMAGE" --load . +# Seems to work without buildx: +docker build $DOCKER_PLATFORM $BUILDARG -t "$DOCKER_IMAGE" . diff --git a/docker/debian-11-bullseye/Dockerfile b/docker/debian-11-bullseye/Dockerfile index 41c8b448e..c32710dda 100644 --- a/docker/debian-11-bullseye/Dockerfile +++ b/docker/debian-11-bullseye/Dockerfile @@ -20,6 +20,12 @@ RUN apt-get install -y opencl-dev && \ # Create rrg user RUN useradd -ms /bin/bash rrg RUN passwd -d rrg +ARG UART_GID +# dialout group may already exist on another numeric ID than on host +RUN if [ -n "${UART_GID}" ]; then \ + groupadd -g ${UART_GID} mydialout || true; \ + usermod -aG ${UART_GID} rrg; \ + fi RUN printf 'rrg ALL=(ALL) ALL\n' | tee -a /etc/sudoers USER rrg diff --git a/docker/debian-11-bullseye/docker_build.sh b/docker/debian-11-bullseye/docker_build.sh deleted file mode 100755 index 3b44dd72c..000000000 --- a/docker/debian-11-bullseye/docker_build.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -docker build -t "pm3-debian-bullseye:1.0" . diff --git a/docker/debian-11-bullseye/docker_rm.sh b/docker/debian-11-bullseye/docker_rm.sh deleted file mode 100644 index b8ce5b834..000000000 --- a/docker/debian-11-bullseye/docker_rm.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash - -docker rm $(docker ps -aq --filter ancestor=pm3-debian-bullseye:1.0) -docker image rm pm3-debian-bullseye:1.0 diff --git a/docker/debian-11-bullseye/docker_run.sh b/docker/debian-11-bullseye/docker_run.sh deleted file mode 100755 index 1216f54cd..000000000 --- a/docker/debian-11-bullseye/docker_run.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -docker run --volume=$(pwd)/../..:/home/rrg/proxmark3 -w /home/rrg/proxmark3 -it pm3-debian-bullseye:1.0 diff --git a/docker/debian-12-bookworm-arm64/Dockerfile b/docker/debian-12-bookworm-arm64/Dockerfile new file mode 100644 index 000000000..792014812 --- /dev/null +++ b/docker/debian-12-bookworm-arm64/Dockerfile @@ -0,0 +1,25 @@ +FROM arm64v8/debian:bookworm-slim + +ENV LANG=C +ENV DEBIAN_FRONTEND=noninteractive +# qtbase5-dev skipped +RUN apt-get update && \ + apt-get dist-upgrade -y && \ + apt-get install -y --no-install-recommends git ca-certificates build-essential cmake pkg-config libreadline-dev gcc-arm-none-eabi libnewlib-dev libbz2-dev liblz4-dev libbluetooth-dev libpython3-dev libssl-dev libgd-dev sudo && \ + apt-get clean + +# Create rrg user +RUN useradd -ms /bin/bash rrg +RUN passwd -d rrg +ARG UART_GID +# dialout group may already exist on another numeric ID than on host +RUN if [ -n "${UART_GID}" ]; then \ + groupadd -g ${UART_GID} mydialout || true; \ + usermod -aG ${UART_GID} rrg; \ + fi +RUN printf 'rrg ALL=(ALL) ALL\n' | tee -a /etc/sudoers + +USER rrg +WORKDIR "/home/rrg" + +CMD ["/bin/bash"] diff --git a/docker/debian-12-bookworm-arm64/README.md b/docker/debian-12-bookworm-arm64/README.md new file mode 100644 index 000000000..2ffa42d1a --- /dev/null +++ b/docker/debian-12-bookworm-arm64/README.md @@ -0,0 +1,17 @@ +# Notes to run tests + +``` +sudo apt update +sudo apt install -y python3-minimal +sudo apt install -y python3-pip +sudo apt install python3.11-venv +python3 -m venv /tmp/venv +source /tmp/venv/bin/activate +python3 -m pip install --use-pep517 pyaes +python3 -m pip install ansicolors sslcrypto +git config --global --add safe.directory /home/rrg/proxmark3 +cd proxmark3 +make clean +make -j +tools/pm3_tests.sh --long +``` diff --git a/docker/debian-12-bookworm-armhf/Dockerfile b/docker/debian-12-bookworm-armhf/Dockerfile new file mode 100644 index 000000000..e5d5acf2b --- /dev/null +++ b/docker/debian-12-bookworm-armhf/Dockerfile @@ -0,0 +1,25 @@ +FROM arm32v7/debian:bookworm-slim + +ENV LANG=C +ENV DEBIAN_FRONTEND=noninteractive +# qtbase5-dev skipped +RUN apt-get update && \ + apt-get dist-upgrade -y && \ + apt-get install -y --no-install-recommends git ca-certificates build-essential cmake pkg-config libreadline-dev gcc-arm-none-eabi libnewlib-dev libbz2-dev liblz4-dev libbluetooth-dev libpython3-dev libssl-dev libgd-dev sudo && \ + apt-get clean + +# Create rrg user +RUN useradd -ms /bin/bash rrg +RUN passwd -d rrg +ARG UART_GID +# dialout group may already exist on another numeric ID than on host +RUN if [ -n "${UART_GID}" ]; then \ + groupadd -g ${UART_GID} mydialout || true; \ + usermod -aG ${UART_GID} rrg; \ + fi +RUN printf 'rrg ALL=(ALL) ALL\n' | tee -a /etc/sudoers + +USER rrg +WORKDIR "/home/rrg" + +CMD ["/bin/bash"] diff --git a/docker/debian-12-bookworm-armhf/README.md b/docker/debian-12-bookworm-armhf/README.md new file mode 100644 index 000000000..2ffa42d1a --- /dev/null +++ b/docker/debian-12-bookworm-armhf/README.md @@ -0,0 +1,17 @@ +# Notes to run tests + +``` +sudo apt update +sudo apt install -y python3-minimal +sudo apt install -y python3-pip +sudo apt install python3.11-venv +python3 -m venv /tmp/venv +source /tmp/venv/bin/activate +python3 -m pip install --use-pep517 pyaes +python3 -m pip install ansicolors sslcrypto +git config --global --add safe.directory /home/rrg/proxmark3 +cd proxmark3 +make clean +make -j +tools/pm3_tests.sh --long +``` diff --git a/docker/debian-12-bookworm/Dockerfile b/docker/debian-12-bookworm/Dockerfile index f2878701e..6c883746d 100644 --- a/docker/debian-12-bookworm/Dockerfile +++ b/docker/debian-12-bookworm/Dockerfile @@ -18,6 +18,12 @@ RUN apt-get install -y opencl-dev && \ # Create rrg user RUN useradd -ms /bin/bash rrg RUN passwd -d rrg +ARG UART_GID +# dialout group may already exist on another numeric ID than on host +RUN if [ -n "${UART_GID}" ]; then \ + groupadd -g ${UART_GID} mydialout || true; \ + usermod -aG ${UART_GID} rrg; \ + fi RUN printf 'rrg ALL=(ALL) ALL\n' | tee -a /etc/sudoers USER rrg diff --git a/docker/debian-12-bookworm/docker_build.sh b/docker/debian-12-bookworm/docker_build.sh deleted file mode 100755 index 0059348cf..000000000 --- a/docker/debian-12-bookworm/docker_build.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -docker build -t "pm3-debian-bookworm:1.0" . diff --git a/docker/debian-12-bookworm/docker_rm.sh b/docker/debian-12-bookworm/docker_rm.sh deleted file mode 100644 index 5818564e0..000000000 --- a/docker/debian-12-bookworm/docker_rm.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash - -docker rm $(docker ps -aq --filter ancestor=pm3-debian-bookworm:1.0) -docker image rm pm3-debian-bookworm:1.0 diff --git a/docker/debian-12-bookworm/docker_run.sh b/docker/debian-12-bookworm/docker_run.sh deleted file mode 100755 index ae264581a..000000000 --- a/docker/debian-12-bookworm/docker_run.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -docker run --volume=$(pwd)/../..:/home/rrg/proxmark3 -w /home/rrg/proxmark3 -it pm3-debian-bookworm:1.0 diff --git a/docker/debian-13-trixie/Dockerfile b/docker/debian-13-trixie/Dockerfile index 120c0c706..607c5bba5 100644 --- a/docker/debian-13-trixie/Dockerfile +++ b/docker/debian-13-trixie/Dockerfile @@ -18,6 +18,12 @@ RUN apt-get install -y opencl-dev && \ # Create rrg user RUN useradd -ms /bin/bash rrg RUN passwd -d rrg +ARG UART_GID +# dialout group may already exist on another numeric ID than on host +RUN if [ -n "${UART_GID}" ]; then \ + groupadd -g ${UART_GID} mydialout || true; \ + usermod -aG ${UART_GID} rrg; \ + fi RUN printf 'rrg ALL=(ALL) ALL\n' | tee -a /etc/sudoers USER rrg diff --git a/docker/debian-13-trixie/docker_build.sh b/docker/debian-13-trixie/docker_build.sh deleted file mode 100755 index 22a5bdbc3..000000000 --- a/docker/debian-13-trixie/docker_build.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -docker build -t "pm3-debian-trixie:1.0" . diff --git a/docker/debian-13-trixie/docker_rm.sh b/docker/debian-13-trixie/docker_rm.sh deleted file mode 100644 index 0afb68014..000000000 --- a/docker/debian-13-trixie/docker_rm.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash - -docker rm $(docker ps -aq --filter ancestor=pm3-debian-trixie:1.0) -docker image rm pm3-debian-trixie:1.0 diff --git a/docker/debian-13-trixie/docker_run.sh b/docker/debian-13-trixie/docker_run.sh deleted file mode 100755 index bc81286fc..000000000 --- a/docker/debian-13-trixie/docker_run.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -docker run --volume=$(pwd)/../..:/home/rrg/proxmark3 -w /home/rrg/proxmark3 -it pm3-debian-trixie:1.0 diff --git a/docker/fedora-36/Dockerfile b/docker/fedora-36/Dockerfile index 610738207..1041b799a 100644 --- a/docker/fedora-36/Dockerfile +++ b/docker/fedora-36/Dockerfile @@ -13,6 +13,12 @@ RUN yum -y install mesa-libOpenCL ocl-icd-devel # Create rrg user RUN useradd -ms /bin/bash rrg RUN passwd -d rrg +ARG UART_GID +# dialout group may already exist on another numeric ID than on host +RUN if [ -n "${UART_GID}" ]; then \ + groupadd -g ${UART_GID} mydialout || true; \ + usermod -aG ${UART_GID} rrg; \ + fi RUN printf 'rrg ALL=(ALL) ALL\n' | tee -a /etc/sudoers USER rrg diff --git a/docker/fedora-36/docker_build.sh b/docker/fedora-36/docker_build.sh deleted file mode 100755 index 1a2e2d392..000000000 --- a/docker/fedora-36/docker_build.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -docker build -t "pm3-fedora-36:1.0" . diff --git a/docker/fedora-36/docker_rm.sh b/docker/fedora-36/docker_rm.sh deleted file mode 100644 index a14c31e80..000000000 --- a/docker/fedora-36/docker_rm.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash - -docker rm $(docker ps -aq --filter ancestor=pm3-fedora-36:1.0) -docker image rm pm3-fedora-36:1.0 diff --git a/docker/fedora-36/docker_run.sh b/docker/fedora-36/docker_run.sh deleted file mode 100755 index 0e6e69925..000000000 --- a/docker/fedora-36/docker_run.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -docker run --volume=$(pwd)/../..:/home/rrg/proxmark3 -w /home/rrg/proxmark3 -it pm3-fedora-36:1.0 diff --git a/docker/fedora-37/Dockerfile b/docker/fedora-37/Dockerfile index 06462c721..bb3118fd2 100644 --- a/docker/fedora-37/Dockerfile +++ b/docker/fedora-37/Dockerfile @@ -13,6 +13,12 @@ RUN yum -y install mesa-libOpenCL ocl-icd-devel # Create rrg user RUN useradd -ms /bin/bash rrg RUN passwd -d rrg +ARG UART_GID +# dialout group may already exist on another numeric ID than on host +RUN if [ -n "${UART_GID}" ]; then \ + groupadd -g ${UART_GID} mydialout || true; \ + usermod -aG ${UART_GID} rrg; \ + fi RUN printf 'rrg ALL=(ALL) ALL\n' | tee -a /etc/sudoers USER rrg diff --git a/docker/fedora-37/docker_build.sh b/docker/fedora-37/docker_build.sh deleted file mode 100755 index 5e3049b68..000000000 --- a/docker/fedora-37/docker_build.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -docker build -t "pm3-fedora-37:1.0" . diff --git a/docker/fedora-37/docker_rm.sh b/docker/fedora-37/docker_rm.sh deleted file mode 100644 index 6f0bd7e56..000000000 --- a/docker/fedora-37/docker_rm.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash - -docker rm $(docker ps -aq --filter ancestor=pm3-fedora-37:1.0) -docker image rm pm3-fedora-37:1.0 diff --git a/docker/fedora-37/docker_run.sh b/docker/fedora-37/docker_run.sh deleted file mode 100755 index eb51525b7..000000000 --- a/docker/fedora-37/docker_run.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -docker run --volume=$(pwd)/../..:/home/rrg/proxmark3 -w /home/rrg/proxmark3 -it pm3-fedora-37:1.0 diff --git a/docker/homebrew/Dockerfile b/docker/homebrew/Dockerfile index 0a432fc18..d4893d154 100644 --- a/docker/homebrew/Dockerfile +++ b/docker/homebrew/Dockerfile @@ -2,6 +2,13 @@ FROM homebrew/brew ENV LANG=C +ARG UART_GID +# dialout group may already exist on another numeric ID than on host +RUN if [ -n "${UART_GID}" ]; then \ + sudo groupadd -g ${UART_GID} mydialout || true; \ + sudo usermod -aG ${UART_GID} linuxbrew; \ + fi + USER linuxbrew WORKDIR "/home/linuxbrew" RUN brew install cmake pkg-config bzip2 lz4 && rm -rf ~/.cache/Homebrew diff --git a/docker/homebrew/README.md b/docker/homebrew/README.md index 549896b33..664db5de3 100644 --- a/docker/homebrew/README.md +++ b/docker/homebrew/README.md @@ -1,5 +1,7 @@ # Notes on linux homebrew +If needed to install sth, run brew as user linuxbrew + Do not `brew install arm-none-eabi-gcc`, it's a Mach-O executable. So only host bins can be built (except tools/hitag2crack/crack5opencl which needs OpenCL) @@ -8,9 +10,10 @@ So only host bins can be built (except tools/hitag2crack/crack5opencl which need ```sh make -j client USE_BREW=1 SKIPREADLINE=1 -make -j mfkey -make -j nonce2key -make -j mf_nonce_brute +make -j cryptorf +make -j mfc_card_only +make -j mfc_card_reader +make -j mfd_aes_brute make -j hitag2crack SKIPOPENCL=1 make -j fpga_compress ``` diff --git a/docker/homebrew/docker_build.sh b/docker/homebrew/docker_build.sh deleted file mode 100755 index 466106d36..000000000 --- a/docker/homebrew/docker_build.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -docker build -t "pm3-brew:1.0" . diff --git a/docker/homebrew/docker_rm.sh b/docker/homebrew/docker_rm.sh deleted file mode 100644 index aa782d4a3..000000000 --- a/docker/homebrew/docker_rm.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash - -docker rm $(docker ps -aq --filter ancestor=pm3-brew:1.0) -docker image rm pm3-brew:1.0 diff --git a/docker/homebrew/docker_run.sh b/docker/homebrew/docker_run.sh deleted file mode 100755 index efde1649b..000000000 --- a/docker/homebrew/docker_run.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash - -docker run --volume=$(pwd)/../..:/home/linuxbrew/proxmark3 -w /home/linuxbrew/proxmark3 -it pm3-brew:1.0 -# if needed, run brew as user linuxbrew diff --git a/docker/kali/Dockerfile b/docker/kali/Dockerfile index 3f1946e29..90349c69d 100644 --- a/docker/kali/Dockerfile +++ b/docker/kali/Dockerfile @@ -9,10 +9,8 @@ RUN apt-get update && \ apt-get install -y --no-install-recommends git ca-certificates build-essential cmake pkg-config libreadline-dev gcc-arm-none-eabi libnewlib-dev libbz2-dev liblz4-dev libbluetooth-dev libpython3-dev libssl-dev libgd-dev sudo && \ apt-get clean -RUN apt-get install -y python3-minimal && \ - apt-get install -y python3-pip && \ - apt-get clean && \ - python3 -m pip install ansicolors sslcrypto +RUN apt-get install -y --no-install-recommends python3-minimal python3-pip python3-venv && \ + apt-get clean RUN apt-get install -y opencl-dev && \ apt-get clean @@ -20,6 +18,12 @@ RUN apt-get install -y opencl-dev && \ # Create rrg user RUN useradd -ms /bin/bash rrg RUN passwd -d rrg +ARG UART_GID +# dialout group may already exist on another numeric ID than on host +RUN if [ -n "${UART_GID}" ]; then \ + groupadd -g ${UART_GID} mydialout || true; \ + usermod -aG ${UART_GID} rrg; \ + fi RUN printf 'rrg ALL=(ALL) ALL\n' | tee -a /etc/sudoers USER rrg diff --git a/docker/kali/docker_build.sh b/docker/kali/docker_build.sh deleted file mode 100755 index 59a8a207b..000000000 --- a/docker/kali/docker_build.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -docker build -t "pm3-kali:1.0" . diff --git a/docker/kali/docker_rm.sh b/docker/kali/docker_rm.sh deleted file mode 100644 index fee4f07cf..000000000 --- a/docker/kali/docker_rm.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash - -docker rm $(docker ps -aq --filter ancestor=pm3-kali:1.0) -docker image rm pm3-kali:1.0 diff --git a/docker/kali/docker_run.sh b/docker/kali/docker_run.sh deleted file mode 100755 index 7124fe5b5..000000000 --- a/docker/kali/docker_run.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -docker run --volume=$(pwd)/../..:/home/rrg/proxmark3 -w /home/rrg/proxmark3 -it pm3-kali:1.0 diff --git a/docker/kali/run_tests.sh b/docker/kali/run_tests.sh index dec20763b..3fc747191 100755 --- a/docker/kali/run_tests.sh +++ b/docker/kali/run_tests.sh @@ -5,4 +5,9 @@ # docker/kali/run_tests.sh; sudo apt update && sudo apt upgrade -y +python3 -m venv /tmp/venv +source /tmp/venv/bin/activate +python3 -m pip install --use-pep517 pyaes +python3 -m pip install ansicolors sslcrypto tools/release_tests.sh +deactivate diff --git a/docker/opensuse-leap/Dockerfile b/docker/opensuse-leap/Dockerfile index 99d608b76..f381bfd9e 100644 --- a/docker/opensuse-leap/Dockerfile +++ b/docker/opensuse-leap/Dockerfile @@ -16,6 +16,12 @@ RUN zypper --non-interactive install ocl-icd-devel # Create rrg user RUN useradd -ms /bin/bash rrg RUN passwd -d rrg +ARG UART_GID +# dialout group may already exist on another numeric ID than on host +RUN if [ -n "${UART_GID}" ]; then \ + groupadd -g ${UART_GID} mydialout || true; \ + usermod -aG ${UART_GID} rrg; \ + fi RUN printf 'rrg ALL=(ALL) NOPASSWD: ALL\n' | tee -a /etc/sudoers USER rrg diff --git a/docker/opensuse-leap/docker_build.sh b/docker/opensuse-leap/docker_build.sh deleted file mode 100755 index d7e8a8873..000000000 --- a/docker/opensuse-leap/docker_build.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -docker build -t "pm3-suse-leap:1.0" . diff --git a/docker/opensuse-leap/docker_rm.sh b/docker/opensuse-leap/docker_rm.sh deleted file mode 100644 index 12302b6f7..000000000 --- a/docker/opensuse-leap/docker_rm.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash - -docker rm $(docker ps -aq --filter ancestor=pm3-suse-leap:1.0) -docker image rm pm3-suse-leap:1.0 diff --git a/docker/opensuse-leap/docker_run.sh b/docker/opensuse-leap/docker_run.sh deleted file mode 100755 index f3c830626..000000000 --- a/docker/opensuse-leap/docker_run.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -docker run --volume=$(pwd)/../..:/home/rrg/proxmark3 -w /home/rrg/proxmark3 -it pm3-suse-leap:1.0 diff --git a/docker/opensuse-tumbleweed/Dockerfile b/docker/opensuse-tumbleweed/Dockerfile index 81dcf331c..a0faf50c2 100644 --- a/docker/opensuse-tumbleweed/Dockerfile +++ b/docker/opensuse-tumbleweed/Dockerfile @@ -15,6 +15,12 @@ RUN zypper --non-interactive install ocl-icd-devel # Create rrg user RUN useradd -ms /bin/bash rrg RUN passwd -d rrg +ARG UART_GID +# dialout group may already exist on another numeric ID than on host +RUN if [ -n "${UART_GID}" ]; then \ + groupadd -g ${UART_GID} mydialout || true; \ + usermod -aG ${UART_GID} rrg; \ + fi RUN printf 'rrg ALL=(ALL) NOPASSWD: ALL\n' | tee -a /etc/sudoers USER rrg diff --git a/docker/opensuse-tumbleweed/docker_build.sh b/docker/opensuse-tumbleweed/docker_build.sh deleted file mode 100755 index b93549831..000000000 --- a/docker/opensuse-tumbleweed/docker_build.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -docker build -t "pm3-suse-tumbleweed:1.0" . diff --git a/docker/opensuse-tumbleweed/docker_rm.sh b/docker/opensuse-tumbleweed/docker_rm.sh deleted file mode 100644 index c4b1b1d53..000000000 --- a/docker/opensuse-tumbleweed/docker_rm.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash - -docker rm $(docker ps -aq --filter ancestor=pm3-suse-tumbleweed:1.0) -docker image rm pm3-suse-tumbleweed:1.0 diff --git a/docker/opensuse-tumbleweed/docker_run.sh b/docker/opensuse-tumbleweed/docker_run.sh deleted file mode 100755 index 79ef74d5c..000000000 --- a/docker/opensuse-tumbleweed/docker_run.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -docker run --volume=$(pwd)/../..:/home/rrg/proxmark3 -w /home/rrg/proxmark3 -it pm3-suse-tumbleweed:1.0 diff --git a/docker/parrot-core-latest/Dockerfile b/docker/parrot-core-latest/Dockerfile index df3952d9d..044acdff4 100644 --- a/docker/parrot-core-latest/Dockerfile +++ b/docker/parrot-core-latest/Dockerfile @@ -18,6 +18,12 @@ RUN apt-get install -y opencl-dev && \ # Create rrg user RUN useradd -ms /bin/bash rrg RUN passwd -d rrg +ARG UART_GID +# dialout group may already exist on another numeric ID than on host +RUN if [ -n "${UART_GID}" ]; then \ + groupadd -g ${UART_GID} mydialout || true; \ + usermod -aG ${UART_GID} rrg; \ + fi RUN printf 'rrg ALL=(ALL) ALL\n' | tee -a /etc/sudoers USER rrg diff --git a/docker/parrot-core-latest/docker_build.sh b/docker/parrot-core-latest/docker_build.sh deleted file mode 100755 index 3e052143d..000000000 --- a/docker/parrot-core-latest/docker_build.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -docker build -t "pm3-parrotsec-core-latest:1.0" . diff --git a/docker/parrot-core-latest/docker_rm.sh b/docker/parrot-core-latest/docker_rm.sh deleted file mode 100644 index 9bf1605e5..000000000 --- a/docker/parrot-core-latest/docker_rm.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash - -docker rm $(docker ps -aq --filter ancestor=pm3-parrotsec-core-latest:1.0) -docker image rm pm3-parrotsec-core-latest:1.0 diff --git a/docker/parrot-core-latest/docker_run.sh b/docker/parrot-core-latest/docker_run.sh deleted file mode 100755 index 509df4461..000000000 --- a/docker/parrot-core-latest/docker_run.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -docker run --volume=$(pwd)/../..:/home/rrg/proxmark3 -w /home/rrg/proxmark3 -it pm3-parrotsec-core-latest:1.0 diff --git a/docker/rm.sh b/docker/rm.sh new file mode 100755 index 000000000..72aab077b --- /dev/null +++ b/docker/rm.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +if [ ! -e docker_conf.inc ]; then + echo "This script must be run from within one of the subfolders" + exit 1 +fi +. docker_conf.inc +CONTAINER=$(docker ps -aq --filter ancestor="$DOCKER_IMAGE") +if [ -n "$CONTAINER" ]; then + docker rm $CONTAINER +fi +docker image rm "$DOCKER_IMAGE" diff --git a/docker/run.sh b/docker/run.sh new file mode 100755 index 000000000..df178fb6c --- /dev/null +++ b/docker/run.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +if [ ! -e docker_conf.inc ]; then + echo "This script must be run from within one of the subfolders" + exit 1 +fi +. docker_conf.inc +UART_PORT="$(../../pm3 --list|grep dev|head -n1|cut -d' ' -f2)" +if [ -n "$UART_PORT" ]; then + DEV="--device=/dev/tty0 --device=$UART_PORT" +else + DEV="" +fi +docker run $DEV $DOCKER_PLATFORM --volume="$(pwd)/../..:/home/rrg/proxmark3" -w /home/rrg/proxmark3 --net=host --rm -it "$DOCKER_IMAGE" diff --git a/docker/ubuntu-18.04/Dockerfile b/docker/ubuntu-18.04/Dockerfile index ecf8c60a3..f287c344e 100644 --- a/docker/ubuntu-18.04/Dockerfile +++ b/docker/ubuntu-18.04/Dockerfile @@ -21,6 +21,12 @@ RUN apt-get install -y opencl-dev && \ # Create rrg user RUN useradd -ms /bin/bash rrg RUN passwd -d rrg +ARG UART_GID +# dialout group may already exist on another numeric ID than on host +RUN if [ -n "${UART_GID}" ]; then \ + groupadd -g ${UART_GID} mydialout || true; \ + usermod -aG ${UART_GID} rrg; \ + fi RUN printf 'rrg ALL=(ALL) ALL\n' | tee -a /etc/sudoers USER rrg diff --git a/docker/ubuntu-18.04/docker_build.sh b/docker/ubuntu-18.04/docker_build.sh deleted file mode 100755 index 252b8792f..000000000 --- a/docker/ubuntu-18.04/docker_build.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -docker build -t "pm3-ubuntu-18.04:1.0" . diff --git a/docker/ubuntu-18.04/docker_rm.sh b/docker/ubuntu-18.04/docker_rm.sh deleted file mode 100644 index 20dcb80b2..000000000 --- a/docker/ubuntu-18.04/docker_rm.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash - -docker rm $(docker ps -aq --filter ancestor=pm3-ubuntu-18.04:1.0) -docker image rm pm3-ubuntu-18.04:1.0 diff --git a/docker/ubuntu-18.04/docker_run.sh b/docker/ubuntu-18.04/docker_run.sh deleted file mode 100755 index 01d133712..000000000 --- a/docker/ubuntu-18.04/docker_run.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -docker run --volume=$(pwd)/../..:/home/rrg/proxmark3 -w /home/rrg/proxmark3 -it pm3-ubuntu-18.04:1.0 diff --git a/docker/ubuntu-20.04/Dockerfile b/docker/ubuntu-20.04/Dockerfile index 4b9bed06f..c02544234 100644 --- a/docker/ubuntu-20.04/Dockerfile +++ b/docker/ubuntu-20.04/Dockerfile @@ -20,6 +20,12 @@ RUN apt-get install -y opencl-dev && \ # Create rrg user RUN useradd -ms /bin/bash rrg RUN passwd -d rrg +ARG UART_GID +# dialout group may already exist on another numeric ID than on host +RUN if [ -n "${UART_GID}" ]; then \ + groupadd -g ${UART_GID} mydialout || true; \ + usermod -aG ${UART_GID} rrg; \ + fi RUN printf 'rrg ALL=(ALL) ALL\n' | tee -a /etc/sudoers USER rrg diff --git a/docker/ubuntu-20.04/docker_build.sh b/docker/ubuntu-20.04/docker_build.sh deleted file mode 100755 index 58dfa2906..000000000 --- a/docker/ubuntu-20.04/docker_build.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -docker build -t "pm3-ubuntu-20.04:1.0" . diff --git a/docker/ubuntu-20.04/docker_rm.sh b/docker/ubuntu-20.04/docker_rm.sh deleted file mode 100644 index d71954339..000000000 --- a/docker/ubuntu-20.04/docker_rm.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash - -docker rm $(docker ps -aq --filter ancestor=pm3-ubuntu-20.04:1.0) -docker image rm pm3-ubuntu-20.04:1.0 diff --git a/docker/ubuntu-20.04/docker_run.sh b/docker/ubuntu-20.04/docker_run.sh deleted file mode 100755 index dd05c9f79..000000000 --- a/docker/ubuntu-20.04/docker_run.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -docker run --volume=$(pwd)/../..:/home/rrg/proxmark3 -w /home/rrg/proxmark3 -it pm3-ubuntu-20.04:1.0 diff --git a/docker/ubuntu-22.04/Dockerfile b/docker/ubuntu-22.04/Dockerfile index 44dd0919e..d182d893e 100644 --- a/docker/ubuntu-22.04/Dockerfile +++ b/docker/ubuntu-22.04/Dockerfile @@ -20,6 +20,12 @@ RUN apt-get install -y opencl-dev && \ # Create rrg user RUN useradd -ms /bin/bash rrg RUN passwd -d rrg +ARG UART_GID +# dialout group may already exist on another numeric ID than on host +RUN if [ -n "${UART_GID}" ]; then \ + groupadd -g ${UART_GID} mydialout || true; \ + usermod -aG ${UART_GID} rrg; \ + fi RUN printf 'rrg ALL=(ALL) ALL\n' | tee -a /etc/sudoers USER rrg diff --git a/docker/ubuntu-22.04/docker_build.sh b/docker/ubuntu-22.04/docker_build.sh deleted file mode 100755 index 1cfd6c10a..000000000 --- a/docker/ubuntu-22.04/docker_build.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -docker build -t "pm3-ubuntu-22.04:1.0" . diff --git a/docker/ubuntu-22.04/docker_rm.sh b/docker/ubuntu-22.04/docker_rm.sh deleted file mode 100644 index d1b82948b..000000000 --- a/docker/ubuntu-22.04/docker_rm.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash - -docker rm $(docker ps -aq --filter ancestor=pm3-ubuntu-22.04:1.0) -docker image rm pm3-ubuntu-22.04:1.0 diff --git a/docker/ubuntu-22.04/docker_run.sh b/docker/ubuntu-22.04/docker_run.sh deleted file mode 100755 index 04f8d99a0..000000000 --- a/docker/ubuntu-22.04/docker_run.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -docker run --volume=$(pwd)/../..:/home/rrg/proxmark3 -w /home/rrg/proxmark3 -it pm3-ubuntu-22.04:1.0 diff --git a/include/protocols.h b/include/protocols.h index 3aa40ea79..3591a8dc2 100644 --- a/include/protocols.h +++ b/include/protocols.h @@ -453,6 +453,7 @@ ISO 7816-4 Basic interindustry commands. For command APDU's. #define PROTO_MFPLUS 17 #define PROTO_TEXKOM 18 #define PROTO_XEROX 19 +#define PROTO_FMCOS20 20 // Picopass fuses #define FUSE_FPERS 0x80 @@ -950,5 +951,43 @@ ISO 7816-4 Basic interindustry commands. For command APDU's. // 0x0A = ACK // 0x05 = NACK +//FMCOS2.0 +#define FMCOS20_CMD_VERIFY_PIN 0x20 +#define FMCOS20_CMD_EXTERNAL_AUTHENTICATION 0x82 +#define FMCOS20_CMD_GET_CHALLENGE 0x84 +#define FMCOS20_CMD_INTERNAL_AUTHENTICATION 0x88 +#define FMCOS20_CMD_SELECT 0xA4 +#define FMCOS20_CMD_READ_BINARY 0xB0 +#define FMCOS20_CMD_READ_RECORD 0xB2 +#define FMCOS20_CMD_GET_RESPONSE 0xC0 +#define FMCOS20_CMD_UPDATE_BINARY 0xD6 +#define FMCOS20_CMD_UPDATE_RECORD 0xDC +#define FMCOS20_CMD_APPEND_RECORD 0xE2 +#define FMCOS20_CMD_CARD_BLOCK 0x16 +#define FMCOS20_CMD_APP_UNBLOCK 0x18 +#define FMCOS20_CMD_APP_BLOCK 0x1E +#define FMCOS20_CMD_PIN_UNBLOCK 0x24 +#define FMCOS20_CMD_UNBLOCK 0x2C +#define FMCOS20_CMD_INITIALIZE_TRANSACTION 0x50 +#define FMCOS20_CMD_CREDIT_LOAD 0x52 +#define FMCOS20_CMD_PURCHASE 0x54 +#define FMCOS20_CMD_UPDATE_OVERDRAW_LIMIT 0x58 +#define FMCOS20_CMD_GET_TRANSACTION_PROOF 0x5A +#define FMCOS20_CMD_GET_BALANCE 0x5C +#define FMCOS20_CMD_CHANGE_PIN 0x5E +#define FMCOS20_CMD_ERASE_DF 0x0E +#define FMCOS20_CMD_PULL 0x30 +#define FMCOS20_CMD_CHARGE 0x32 +#define FMCOS20_CMD_WRITE_KEY 0xD4 +#define FMCOS20_CMD_CREATE_FILE 0xE0 +#define FMCOS20_CMD_WRITE_EEPROM 0x00 +#define FMCOS20_CMD_READ_EEPROM 0x04 +#define FMCOS20_CMD_INITIALIZE_EEPROM 0x02 +#define FMCOS20_CMD_READ_ROM 0x0C +#define FMCOS20_CMD_INITIALIZE_GREY_LOCK_UNLOCK 0x7A +#define FMCOS20_CMD_GREY_LOCK_UNLOCK 0x7C +#define FMCOS20_CMD_DEBIT_UNLOCK 0x7E +#define FMCOS20_CMD_CALCULATE_ROM_CRC 0x0A + #endif // PROTOCOLS_H diff --git a/tools/recover_pk.py b/tools/recover_pk.py index a1dffc9eb..32fd01587 100755 --- a/tools/recover_pk.py +++ b/tools/recover_pk.py @@ -106,42 +106,42 @@ def selftests(): 'pk': "044F6D3F294DEA5737F0F46FFEE88A356EED95695DD7E0C27A591E6F6F65962BAF"}, {'name': "DESFire Light", - 'samples': ["0439556ACB6480", "D5BD0978106E1E38B513642335966AB21E9F950DCFCFAB45FF13D0DC3CA4C2AE7E0D671DF1240937D040DAC4601C5F66ED62C546EE03ED08", - "043B156ACB6480", "76B46932BF2FCF4931A24C755F5CB1686B914F1856177686B864BDAD58EFA6A7493E5C2232F3ADDAA434EA4647BFD1D385BDA6115E77D74C"], - 'pk': "040E98E117AAA36457F43173DC920A8757267F44CE4EC5ADD3C54075571AEBBF7B942A9774A1D94AD02572427E5AE0A2DD36591B1FB34FCF3D"}, + 'samples': ["0439556ACB6480", "D5BD0978106E1E38B513642335966AB21E9F950DCFCFAB45FF13D0DC3CA4C2AE7E0D671DF1240937D040DAC4601C5F66ED62C546EE03ED08", # noqa: E501 + "043B156ACB6480", "76B46932BF2FCF4931A24C755F5CB1686B914F1856177686B864BDAD58EFA6A7493E5C2232F3ADDAA434EA4647BFD1D385BDA6115E77D74C"], # noqa: E501 + 'pk': "040E98E117AAA36457F43173DC920A8757267F44CE4EC5ADD3C54075571AEBBF7B942A9774A1D94AD02572427E5AE0A2DD36591B1FB34FCF3D"}, # noqa: E501 {'name': "DESFire EV2", - 'samples': ["042A41CAE45380", "B2769F8DDB575AEA2A680ADCA8FFED4FAB81A1E9908E2B82FE0FABB697BBD9B23835C416970E75768F12902ACA491349E94E6589EAF4F508", - "045640CAE45380", "D34B53A8C2C100D700DEA1C4C0D0DE4409F3A418CD8D57C4F41F146E42AD9A55F014199ABBF5CA259C7799DB0AE20D5E77D4950AC7E95D33", - "040D259A965B80","B158073A7100C88C3726F4299FA58311FC3CB18744686DE3F234928AD74578F5CAD7FCEC1DCB962ECC7CC000B8557B37F45B76DC6573A58F"], - 'pk': "04B304DC4C615F5326FE9383DDEC9AA892DF3A57FA7FFB3276192BC0EAA252ED45A865E3B093A3D0DCE5BE29E92F1392CE7DE321E3E5C52B3A"}, + 'samples': ["042A41CAE45380", "B2769F8DDB575AEA2A680ADCA8FFED4FAB81A1E9908E2B82FE0FABB697BBD9B23835C416970E75768F12902ACA491349E94E6589EAF4F508", # noqa: E501 + "045640CAE45380", "D34B53A8C2C100D700DEA1C4C0D0DE4409F3A418CD8D57C4F41F146E42AD9A55F014199ABBF5CA259C7799DB0AE20D5E77D4950AC7E95D33", # noqa: E501 + "040D259A965B80", "B158073A7100C88C3726F4299FA58311FC3CB18744686DE3F234928AD74578F5CAD7FCEC1DCB962ECC7CC000B8557B37F45B76DC6573A58F"], # noqa: E501 + 'pk': "04B304DC4C615F5326FE9383DDEC9AA892DF3A57FA7FFB3276192BC0EAA252ED45A865E3B093A3D0DCE5BE29E92F1392CE7DE321E3E5C52B3A"}, # noqa: E501 {'name': "DESFire EV2 XL", - 'samples': ["044ca092806480","9d86dacd3866058b1cf122ff5fc80e997251d99179bc1f996acf6ed7d495da5c39dde699e2760c08d747ef08487b9897d48957e5afd755e2", - "045793d28a6380","e509576a484b4f93b5b97ffa04cb297cae97cff1071bdefd23d5054513e3036203fdd1cdd2cdead0aead88df24ffe7cdaafee1e58a55a745", - "044ba492806480","517b2931355bd9b9f35d72ed90bdab6212d05853abcf9dd45a79d5ceb91d8939c2c90d3a630a4d18a33903a3e23950a7580cf4ca34d03a90"], - 'pk': "04CD5D45E50B1502F0BA4656FF37669597E7E183251150F9574CC8DA56BF01C7ABE019E29FEA48F9CE22C3EA4029A765E1BC95A89543BAD1BC"}, + 'samples': ["044ca092806480", "9d86dacd3866058b1cf122ff5fc80e997251d99179bc1f996acf6ed7d495da5c39dde699e2760c08d747ef08487b9897d48957e5afd755e2", # noqa: E501 + "045793d28a6380", "e509576a484b4f93b5b97ffa04cb297cae97cff1071bdefd23d5054513e3036203fdd1cdd2cdead0aead88df24ffe7cdaafee1e58a55a745", # noqa: E501 + "044ba492806480", "517b2931355bd9b9f35d72ed90bdab6212d05853abcf9dd45a79d5ceb91d8939c2c90d3a630a4d18a33903a3e23950a7580cf4ca34d03a90"], # noqa: E501 + 'pk': "04CD5D45E50B1502F0BA4656FF37669597E7E183251150F9574CC8DA56BF01C7ABE019E29FEA48F9CE22C3EA4029A765E1BC95A89543BAD1BC"}, # noqa: E501 {'name': "DESFire EV3", - 'samples': ["04448BD2DB6B80", "5CBB5632795C8F15263FEFB095B51C7B541AFD914A1AE44EF6FB8AF605EDF13DBFEE6C3A2DB372245E671DFE0D42CB1F0D0B8FE67A89D2F6", - "04445DD2DB6B80", "166BFD9F9BFAA451172566101580DF9894F582C4A4E258C15037AD2F35A475CF1D7FB817618623A6569F991931AFB2766984E21A18512A6D"], - 'pk': "041DB46C145D0A36539C6544BD6D9B0AA62FF91EC48CBC6ABAE36E0089A46F0D08C8A715EA40A63313B92E90DDC1730230E0458A33276FB743"}, + 'samples': ["04448BD2DB6B80", "5CBB5632795C8F15263FEFB095B51C7B541AFD914A1AE44EF6FB8AF605EDF13DBFEE6C3A2DB372245E671DFE0D42CB1F0D0B8FE67A89D2F6", # noqa: E501 + "04445DD2DB6B80", "166BFD9F9BFAA451172566101580DF9894F582C4A4E258C15037AD2F35A475CF1D7FB817618623A6569F991931AFB2766984E21A18512A6D"], # noqa: E501 + 'pk': "041DB46C145D0A36539C6544BD6D9B0AA62FF91EC48CBC6ABAE36E0089A46F0D08C8A715EA40A63313B92E90DDC1730230E0458A33276FB743"}, # noqa: E501 {'name': "Mifare Plus EV1", - 'samples': ["042A2B221C5080", "BAC40CD88E9193C58ADA5055350C4F648EB5A7AEC4FCF9BD4CDD7B1C558DE5F59C6636F26286ED48622AAA2331D4DF1CEE23B57B94BDA631", - "04505082346B80", "78B2FCF6769F60B165F5BDEB3A6D0C26967BB165E65A3B400A01C711356FF0A0807AB1A2706FCA419702AC67211287E31D71927BA25AB235", - "12817C48", "3351979A3449CACD9EE113A75B862917F03EFAE68DA399C06342BF8583C88DFE769DF49754A96F7C28B57189FB05B9C10E2305D41423A6EB"], - 'pk': "044409ADC42F91A8394066BA83D872FB1D16803734E911170412DDF8BAD1A4DADFD0416291AFE1C748253925DA39A5F39A1C557FFACD34C62E"}, + 'samples': ["042A2B221C5080", "BAC40CD88E9193C58ADA5055350C4F648EB5A7AEC4FCF9BD4CDD7B1C558DE5F59C6636F26286ED48622AAA2331D4DF1CEE23B57B94BDA631", # noqa: E501 + "04505082346B80", "78B2FCF6769F60B165F5BDEB3A6D0C26967BB165E65A3B400A01C711356FF0A0807AB1A2706FCA419702AC67211287E31D71927BA25AB235", # noqa: E501 + "12817C48", "3351979A3449CACD9EE113A75B862917F03EFAE68DA399C06342BF8583C88DFE769DF49754A96F7C28B57189FB05B9C10E2305D41423A6EB"], # noqa: E501 + 'pk': "044409ADC42F91A8394066BA83D872FB1D16803734E911170412DDF8BAD1A4DADFD0416291AFE1C748253925DA39A5F39A1C557FFACD34C62E"}, # noqa: E501 - {'name': "NTAG413DNA", - 'samples': ["042468222F5C80", "B9211E320F321BD1D0E158E10FF15109B389638BAE15D9909D7725BF1250ED236D66F1AF75C94D60330E4E92535F5E6997675281A5687173", - "042938222F5C80", "18B642797D1FD71806146A7A6EC778D3FDD04F39C4A3B36A592BD1A114DC44E5528380FA766C0B7EA32B284AFBE84300B620369F0686D8CC"], - 'pk': "04bb5d514f7050025c7d0f397310360eec91eaf792e96fc7e0f496cb4e669d414f877b7b27901fe67c2e3b33cd39d1c797715189ac951c2add"}, + {'name': "NTAG413DNA, DESFire EV1", + 'samples': ["042468222F5C80", "B9211E320F321BD1D0E158E10FF15109B389638BAE15D9909D7725BF1250ED236D66F1AF75C94D60330E4E92535F5E6997675281A5687173", # noqa: E501 + "042938222F5C80", "18B642797D1FD71806146A7A6EC778D3FDD04F39C4A3B36A592BD1A114DC44E5528380FA766C0B7EA32B284AFBE84300B620369F0686D8CC"], # noqa: E501 + 'pk': "04BB5D514F7050025C7D0F397310360EEC91EAF792E96FC7E0F496CB4E669D414F877B7B27901FE67C2E3B33CD39D1C797715189AC951C2ADD"}, # noqa: E501 {'name': "NTAG424DNA", - 'samples': ["0463474AA26A80", "27E9A50E6CA4BA9037C02F7D20A80D0284D0C1D83C67F5A5AC1D8A4EF86C9508417E4E9C6F85AA7920F0ABDED984CAF20467D66EA54BBF08", - "04C46C222A6380", "344A806EBF704C05C19215D2F840529CE365AAD2D08A469A95896D75D477D9FAB02A0C827E9F215BD8EB0E56A3A9A008FB75D706AABBD4DA"], - 'pk': "048A9B380AF2EE1B98DC417FECC263F8449C7625CECE82D9B916C992DA209D68422B81EC20B65A66B5102A61596AF3379200599316A00A1410"}, + 'samples': ["0463474AA26A80", "27E9A50E6CA4BA9037C02F7D20A80D0284D0C1D83C67F5A5AC1D8A4EF86C9508417E4E9C6F85AA7920F0ABDED984CAF20467D66EA54BBF08", # noqa: E501 + "04C46C222A6380", "344A806EBF704C05C19215D2F840529CE365AAD2D08A469A95896D75D477D9FAB02A0C827E9F215BD8EB0E56A3A9A008FB75D706AABBD4DA"], # noqa: E501 + 'pk': "048A9B380AF2EE1B98DC417FECC263F8449C7625CECE82D9B916C992DA209D68422B81EC20B65A66B5102A61596AF3379200599316A00A1410"}, # noqa: E501 {'name': "Vivokey Spark1", # ! tag signature bytes output by pm3 must be read right to left: @@ -159,20 +159,24 @@ def selftests(): 'pk': "048878A2A2D3EEC336B4F261A082BD71F9BE11C4E2E896648B32EFA59CEA6E59F0"}, # {'name': "Minecraft Earth", # # uses secp256r1?, SHA-256, - # 'samples': ["aa", "DF0E506DFF8FCFC4B7B979D917644445F1230D2C7CDC342AFA842CA240C210BE7275F62073A9670F2DCEFC602CBEE771C2B4CD4A04F3D1EA11F49ABDF7E8B721"], + # 'samples': ["aa", "DF0E506DFF8FCFC4B7B979D917644445F1230D2C7CDC342AFA842CA240C210BE7275F62073A9670F2DCEFC602CBEE771C2B4CD4A04F3D1EA11F49ABDF7E8B721"], # noqa: E501 # 'pk': ""}, {'name': "MIFARE Plus Trojka", # uses secp224r1, None, - 'samples': ["04B59F6A226F82", "6F577EB7F570D74DB6250477427F68A0088762BD318767537122919A7916597149F9D16D8B135E9BF826FB28AE293F3168661CD4A049FAED", - "04B44A82D80F92", "A0868ECF26733D3C3C838D055968B4559F77693CC3E346E3A4741BC826801F8360FD88857BEC440AAD3A21153D64302DEB6F5ED40B15C3F7"], - 'pk': "040F732E0EA7DF2B38F791BF89425BF7DCDF3EE4D976669E3831F324FF15751BD52AFF1782F72FF2731EEAD5F63ABE7D126E03C856FFB942AF"}, + 'samples': ["04B59F6A226F82", "6F577EB7F570D74DB6250477427F68A0088762BD318767537122919A7916597149F9D16D8B135E9BF826FB28AE293F3168661CD4A049FAED", # noqa: E501 + "04B44A82D80F92", "A0868ECF26733D3C3C838D055968B4559F77693CC3E346E3A4741BC826801F8360FD88857BEC440AAD3A21153D64302DEB6F5ED40B15C3F7"], # noqa: E501 + 'pk': "040F732E0EA7DF2B38F791BF89425BF7DCDF3EE4D976669E3831F324FF15751BD52AFF1782F72FF2731EEAD5F63ABE7D126E03C856FFB942AF"}, # noqa: E501 {'name': "MIFARE Ultralight AES", # uses prime192v1, None, - 'samples': ["045E4CC2451390", "C9BBDA1B99EB6634CDFD8E3251AC5C4742EA5FA507B8A8A8B39B19AB7340D173331589C54C56C49F0CCA6DDBAC1E492A", - "043F88C2451390", "5C2055A7373F119C3FDD9843020B06AA0E6DE18C16496C425C4AD971A50F05FA1A67B9E39CA60C355EEEEBF8214A84A5"], - 'pk': "0453BF8C49B7BD9FE3207A91513B9C1D238ECAB07186B772104AB535F7D3AE63CF7C7F3DD0D169DA3E99E43C6399621A86"}, - + 'samples': ["045E4CC2451390", "C9BBDA1B99EB6634CDFD8E3251AC5C4742EA5FA507B8A8A8B39B19AB7340D173331589C54C56C49F0CCA6DDBAC1E492A", # noqa: E501 + "043F88C2451390", "5C2055A7373F119C3FDD9843020B06AA0E6DE18C16496C425C4AD971A50F05FA1A67B9E39CA60C355EEEEBF8214A84A5"], # noqa: E501 + 'pk': "0453BF8C49B7BD9FE3207A91513B9C1D238ECAB07186B772104AB535F7D3AE63CF7C7F3DD0D169DA3E99E43C6399621A86"}, # noqa: E501 + {'name': "MIFARE Ultralight AES (alt key)", + # uses prime192v1, None, + # TODO more samples + 'samples': ["04A31232241C90", "057595DCC601CA7E21341F1F978FA134F0204D87A33749C56DDB4ABD6F1F26194341DB10093B34C42F524A30DCC5CE54"], # noqa: E501 + 'pk': "04DC34DAA903F2726A6225B11C692AF6AB4396575CA12810CBBCE3F781A097B3833B50AB364A70D9C2B641A728A599AE74"}, # noqa: E501 {'name': "MIFARE Classic / QL88", 'samples': ["30933C61", "AEA4DD0B800FAC63D4DE08EE91F4650ED825FD6B4D7DEEE98DBC9BAE10BE003E", "20593261", "F762CDD59EEDC075F4DDBA7ECD529FEEE5135C65A84D12EF0A250A321B2012F5"], @@ -204,38 +208,43 @@ def selftests(): succeeded = True for t in tests: - print("Testing %-38s" % (t['name']+":"), end="") + print("Testing %-40s" % (t['name']+":"), end="") curvenames = guess_curvename(t['samples'][1]) recovered = set() for c in curvenames: for h in [None, "md5", "sha1", "sha256", "sha512"]: - recovered |= recover_multiple(t['samples'][::2], t['samples'][1::2], c, alghash=h) + recovered |= set([(c, h, pk) for pk in + recover_multiple(t['samples'][::2], t['samples'][1::2], c, alghash=h)]) if (len(recovered) == 1): - pk = recovered.pop() + c, h, pk = recovered.pop() pk = binascii.hexlify(pk).decode('utf8') if pk.lower() == t['pk'].lower(): - print("( %s )" % color('ok', fg='green')) + print("%15s/%-8s ( %s )" % (c, h, color('ok', fg='green'))) else: succeeded = False - print("( FAIL ) got %s" % pk.lower()) + print("%15s/%-8s ( %s ) got %s" % (c, h, color('fail', fg='red'), pk.lower())) elif len(t['samples'])//2 == 1: - pks = [binascii.hexlify(pk).decode('utf8').lower() for pk in list(recovered)] - if t['pk'].lower() in pks: - print("( %s ) partial" % color('ok', fg='green')) + recovereds = [(c, h) for c, h, pk in list(recovered) + if t['pk'].lower() == binascii.hexlify(pk).decode('utf8').lower()] + if len(recovereds) == 1: + c, h = recovereds[0] + print("%15s/%-8s ( %s ) partial" % (c, h, color('ok', fg='green'))) else: succeeded = False - print("( %s ), got %s" % color('fail', fg='red'), pks) + print(" ( %s ), got" % color('fail', fg='red')) + for c, h, pk in list(recovered): + print(c, h, binascii.hexlify(pk).decode('utf8').lower()) else: - print("( %s )" % color('fail', fg='red')) + print(" ( %s )" % color('fail', fg='red')) succeeded = False - print("=====================================================") + print("===============================================================================") fail = color('fail', fg='red') ok = color('ok', fg='green') - print("Tests: ( %s )" % [fail, ok][succeeded]) + print("Tests: ( %s )" % [fail, ok][succeeded]) print("")