- now are able to verify signature. Thanks @doegox!

This commit is contained in:
iceman1001 2024-04-24 00:23:16 +02:00
parent b84fa69f39
commit 59c07f911a
5 changed files with 128 additions and 6 deletions

View file

@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file.
This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log...
## [unreleased][unreleased]
- Changed `hf st info` - now tries to check signature if available (@iceman1001)
- Added `hf 14b mobib` - try to read out all data from a MOBIB card (@iceman1001)
- Added `hf 14b calyso` - try to read out all data from a Calypso card (@iceman1001)
- Changed the graphbuffer handling implementation (@HACKhalo2)

View file

@ -130,6 +130,15 @@ static const productName_t uidmapping[] = {
{ 0xe002480000000000LL, 24, "ST Microelectronics; ST25TV16K"},
{ 0xe002480000000000LL, 24, "ST Microelectronics; ST25TV64K"},
/*
ST25TV02K 0xe0 02 23
ST25TV512 0xe0 02 23
ST25TV02KC 0xe00208
ST25TV512C 0xe00208
ST25TV04K-P 0xe00235
ST25TV16K 0xe00248
ST25TV64K 0xe00248
*/
{ 0xE003000000000000LL, 16, "Hitachi, Ltd Japan" },
@ -283,7 +292,7 @@ static int nxp_15693_print_signature(uint8_t *uid, uint8_t *signature) {
{"NXP NTAG21x (2013)", "04494E1A386D3D3CFE3DC10E5DE68A499B1C202DB5B132393E89ED19FE5BE8BC61"},
{"MIKRON Public key", "04F971EDA742A4A80D32DCF6A814A707CC3DC396D35902F72929FDCD698B3468F2"},
{"VivoKey Spark1 Public key", "04D64BB732C0D214E7EC580736ACF847284B502C25C0F7F2FA86AACE1DADA4387A"},
{"TruST25 (ST) key 01?", "041d92163650161a2548d33881c235d0fb2315c2c31a442f23c87acf14497c0cba"},
{"TruST25 (ST) key 01?", "041D92163650161A2548D33881C235D0FB2315C2C31A442F23C87ACF14497C0CBA"},
{"TruST25 (ST) key 04?", "04101E188A8B4CDDBC62D5BC3E0E6850F0C2730E744B79765A0E079907FBDB01BC"},
};
/*
@ -364,7 +373,6 @@ static int nxp_15693_print_signature(uint8_t *uid, uint8_t *signature) {
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);

View file

@ -78,7 +78,7 @@ int mfc_ev1_print_signature(uint8_t *uid, uint8_t uidlen, uint8_t *signature, in
{"NXP NTAG21x (2013)", "04494E1A386D3D3CFE3DC10E5DE68A499B1C202DB5B132393E89ED19FE5BE8BC61"},
{"MIKRON Public key", "04F971EDA742A4A80D32DCF6A814A707CC3DC396D35902F72929FDCD698B3468F2"},
{"VivoKey Spark1 Public key", "04D64BB732C0D214E7EC580736ACF847284B502C25C0F7F2FA86AACE1DADA4387A"},
{"TruST25 (ST) key 01?", "041d92163650161a2548d33881c235d0fb2315c2c31a442f23c87acf14497c0cba"},
{"TruST25 (ST) key 01?", "041D92163650161A2548D33881C235D0FB2315C2C31A442F23C87ACF14497C0CBA"},
{"TruST25 (ST) key 04?", "04101E188A8B4CDDBC62D5BC3E0E6850F0C2730E744B79765A0E079907FBDB01BC"},
};

View file

@ -1254,7 +1254,7 @@ static int ulev1_print_signature(uint64_t tagtype, uint8_t *uid, uint8_t *signat
{"NXP NTAG21x (2013)", "04494E1A386D3D3CFE3DC10E5DE68A499B1C202DB5B132393E89ED19FE5BE8BC61"},
{"MIKRON Public key", "04F971EDA742A4A80D32DCF6A814A707CC3DC396D35902F72929FDCD698B3468F2"},
{"VivoKey Spark1 Public key", "04D64BB732C0D214E7EC580736ACF847284B502C25C0F7F2FA86AACE1DADA4387A"},
{"TruST25 (ST) key 01?", "041d92163650161a2548d33881c235d0fb2315c2c31a442f23c87acf14497c0cba"},
{"TruST25 (ST) key 01?", "041D92163650161A2548D33881C235D0FB2315C2C31A442F23C87ACF14497C0CBA"},
{"TruST25 (ST) key 04?", "04101E188A8B4CDDBC62D5BC3E0E6850F0C2730E744B79765A0E079907FBDB01BC"},
};

View file

@ -32,11 +32,37 @@
#include "cmdnfc.h" // print_type4_cc_info
#include "commonutil.h" // get_sw
#include "protocols.h" // ISO7816 APDU return codes
#include "crypto/libpcrypto.h" // ecdsa
#define TIMEOUT 2000
static int CmdHelp(const char *Cmd);
static bool st25ta_select(iso14a_card_select_t *card) {
clearCommandBuffer();
SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT | ISO14A_NO_DISCONNECT | ISO14A_NO_RATS, 0, 0, NULL, 0);
PacketResponseNG resp;
if (WaitForResponseTimeout(CMD_ACK, &resp, 1500) == false) {
PrintAndLogEx(DEBUG, "iso14443a card select timeout");
DropField();
return false;
} else {
uint16_t len = (resp.oldarg[1] & 0xFFFF);
if (len == 0) {
PrintAndLogEx(DEBUG, "iso14443a card select failed");
DropField();
return false;
}
if (card) {
memcpy(card, resp.data.asBytes, sizeof(iso14a_card_select_t));
}
}
return true;
}
static void print_st25ta_system_info(uint8_t *d, uint8_t n) {
if (n < 0x12) {
PrintAndLogEx(WARNING, "Not enough bytes read from system file");
@ -121,6 +147,86 @@ 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"},
};
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, "--- " _CYAN_("Tag Signature"));
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(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;
}
static int st25ta_get_signature(uint8_t *signature) {
/*
hf 14a raw -sck 0200A4040007D276000085010100
hf 14a raw -ck 0300A4000C020001
hf 14a raw -c 02a2b000e020
*/
typedef struct {
const char* apdu;
uint8_t apdulen;
} transport_st25a_apdu_t;
transport_st25a_apdu_t cmds[] = {
{ "\x00\xA4\x04\x00\x07\xD2\x76\x00\x00\x85\x01\x01\x00", 13 },
{ "\x00\xA4\x00\x0C\x02\x00\x01", 7 },
{ "\xa2\xb0\x00\xe0\x20", 5 },
};
uint8_t resp[40] = {0};
int resplen = 0;
bool activate_field = true;
for (uint8_t i = 0; i < ARRAYLEN(cmds); i++) {
int res = ExchangeAPDU14a( (uint8_t*)cmds[i].apdu, cmds[i].apdulen, activate_field, true, resp, sizeof(resp), &resplen);
if (res != PM3_SUCCESS) {
DropField();
return res;
}
activate_field = false;
}
if (signature) {
memcpy(signature, resp, 32);
}
DropField();
return PM3_SUCCESS;
}
// ST25TA
static int infoHFST25TA(void) {
@ -225,13 +331,20 @@ static int infoHFST25TA(void) {
return PM3_ESOFT;
}
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, "--- " _CYAN_("Tag Information") " ---------------------------");
PrintAndLogEx(NORMAL, "");
iso14a_card_select_t card;
if (st25ta_select(&card)) {
uint8_t sig[32] = {0};
if (st25ta_get_signature(sig) == PM3_SUCCESS) {
print_st25ta_signature(card.uid, sig);
}
}
print_type4_cc_info(st_cc_data, sizeof(st_cc_data));
print_st25ta_system_info(response, resplen - 2);
return PM3_SUCCESS;
}