mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-03-19 19:38:52 +08:00
ADD: UL-EV1 signature printing.
CHG: @marshmellows changes.
This commit is contained in:
parent
69a2953679
commit
2b03dea768
1 changed files with 80 additions and 61 deletions
|
@ -21,23 +21,22 @@
|
|||
#define MAX_ULEV1b_BLOCKS 0x20
|
||||
#define MAX_NTAG_213 0x2c
|
||||
#define MAX_NTAG_215 0x86
|
||||
#define MAX_NTAG_216 0xE6
|
||||
#define MAX_NTAG_216 0xe6
|
||||
|
||||
typedef enum TAGTYPE_UL {
|
||||
UNKNOWN = 0,
|
||||
UL = 1,
|
||||
UL_C = 2,
|
||||
UL_EV1_48 = 4,
|
||||
UL_EV1_128 = 8,
|
||||
NTAG = 16,
|
||||
NTAG_213 = 32,
|
||||
NTAG_215 = 64,
|
||||
NTAG_216 = 128,
|
||||
MAGIC = 256,
|
||||
UNKNOWN = 0x0000,
|
||||
UL = 0x0001,
|
||||
UL_C = 0x0002,
|
||||
UL_EV1_48 = 0x0004,
|
||||
UL_EV1_128 = 0x0008,
|
||||
NTAG = 0x0010,
|
||||
NTAG_213 = 0x0020,
|
||||
NTAG_215 = 0x0040,
|
||||
NTAG_216 = 0x0080,
|
||||
MAGIC = 0x0100,
|
||||
UL_MAGIC = UL | MAGIC,
|
||||
UL_C_MAGIC = UL_C | MAGIC,
|
||||
UL_ERROR = 0xFFFF,
|
||||
|
||||
} TagTypeUL_t;
|
||||
|
||||
uint8_t default_3des_keys[7][16] = {
|
||||
|
@ -86,9 +85,9 @@ char* getUlev1CardSizeStr( uint8_t fsize ){
|
|||
|
||||
// is LSB set?
|
||||
if ( fsize & 1 )
|
||||
sprintf(retStr, "0x%02X (%d - %d bytes)",fsize, usize, lsize);
|
||||
sprintf(retStr, "0x%02X (%u - %u bytes)",fsize, usize, lsize);
|
||||
else
|
||||
sprintf(retStr, "0x%02X (%d bytes)", fsize, lsize);
|
||||
sprintf(retStr, "0x%02X (%u bytes)", fsize, lsize);
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
@ -108,14 +107,15 @@ static int ul_send_cmd_raw( uint8_t *cmd, uint8_t cmdlen, uint8_t *response, uin
|
|||
SendCommand(&c);
|
||||
UsbCommand resp;
|
||||
if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) return -1;
|
||||
|
||||
uint16_t resplen = (resp.arg[0] < responseLength) ? resp.arg[0] : responseLength;
|
||||
if (resp.arg[0] > 0)
|
||||
|
||||
if (resp.arg[0] > 0) {
|
||||
uint16_t resplen = (resp.arg[0] < responseLength) ? resp.arg[0] : responseLength;
|
||||
memcpy(response, resp.d.asBytes, resplen);
|
||||
|
||||
return resplen;
|
||||
return resplen;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
static int ul_send_cmd_raw_crc( uint8_t *cmd, uint8_t cmdlen, uint8_t *response, uint16_t responseLength, bool append_crc ) {
|
||||
|
||||
UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_RAW | ISO14A_NO_DISCONNECT , cmdlen, 0}};
|
||||
|
@ -128,25 +128,22 @@ static int ul_send_cmd_raw_crc( uint8_t *cmd, uint8_t cmdlen, uint8_t *response,
|
|||
if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) return -1;
|
||||
|
||||
uint16_t resplen = (resp.arg[0] < responseLength) ? resp.arg[0] : responseLength;
|
||||
if (resp.arg[0] > 0)
|
||||
if (resp.arg[0] > 0) {
|
||||
memcpy(response, resp.d.asBytes, resplen );
|
||||
|
||||
return resplen;
|
||||
} else return -1;
|
||||
}
|
||||
|
||||
*/
|
||||
static int ul_select( iso14a_card_select_t *card ){
|
||||
|
||||
ul_switch_on_field();
|
||||
|
||||
UsbCommand resp;
|
||||
if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
|
||||
ul_switch_off_field();
|
||||
return -1;
|
||||
}
|
||||
if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) return -1;
|
||||
if (resp.arg[0] < 0) return -1;
|
||||
|
||||
memcpy(card, resp.d.asBytes, sizeof(iso14a_card_select_t));
|
||||
|
||||
if (resp.arg[0] > 0) {
|
||||
memcpy(card, resp.d.asBytes, sizeof(iso14a_card_select_t));
|
||||
}
|
||||
return resp.arg[0];
|
||||
}
|
||||
|
||||
|
@ -292,11 +289,11 @@ static int ul_print_type(uint16_t tagtype){
|
|||
if ( tagtype & UL )
|
||||
PrintAndLog(" TYPE : MIFARE Ultralight (MF0ICU1) %s", (tagtype & MAGIC)?"<magic>":"");
|
||||
else if ( tagtype & UL_C)
|
||||
PrintAndLog(" TYPE : MIFARE Ultralight C (MF0ULC) %s", (tagtype & MAGIC)?"<magic>":"" );
|
||||
PrintAndLog(" TYPE : MIFARE Ultralight C (MF0ULC) %s [%x]", (tagtype & MAGIC)?"<magic>":"", tagtype );
|
||||
else if ( tagtype & UL_EV1_48)
|
||||
PrintAndLog(" TYPE : MIFARE Ultralight EV1 48bytes (MF0UL1101)");
|
||||
else if ( tagtype & UL_EV1_128)
|
||||
PrintAndLog(" TYPE : MIFARE Ultralight EV1 128bytes (MF0UL2101");
|
||||
PrintAndLog(" TYPE : MIFARE Ultralight EV1 128bytes (MF0UL2101)");
|
||||
else if ( tagtype & NTAG_213 )
|
||||
PrintAndLog(" TYPE : MIFARE NTAG 213 144bytes (NT2H1311G0DU)");
|
||||
else if ( tagtype & NTAG_215 )
|
||||
|
@ -376,6 +373,17 @@ static int ulev1_print_counters(){
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int ulev1_print_signature( uint8_t *data, uint8_t len){
|
||||
|
||||
PrintAndLog("IC signature public key name : NXP NTAG21x 2013");
|
||||
PrintAndLog("IC signature public key value : 04494e1a386d3d3cfe3dc10e5de68a499b1c202db5b132393e89ed19fe5be8bc61");
|
||||
PrintAndLog(" Elliptic curve parameters : secp128r1");
|
||||
PrintAndLog(" Tag ECC Signature : %s", sprint_hex(data, len));
|
||||
//to do: verify if signature is valid
|
||||
//PrintAndLog("IC signature status: %s valid", (iseccvalid() )?"":"not");
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t GetHF14AMfU_Type(void){
|
||||
|
||||
TagTypeUL_t tagtype = UNKNOWN;
|
||||
|
@ -389,6 +397,7 @@ uint16_t GetHF14AMfU_Type(void){
|
|||
status = ul_select(&card);
|
||||
if ( status < 1 ){
|
||||
PrintAndLog("Error: couldn't select");
|
||||
ul_switch_off_field();
|
||||
return UL_ERROR;
|
||||
}
|
||||
|
||||
|
@ -399,6 +408,7 @@ uint16_t GetHF14AMfU_Type(void){
|
|||
}
|
||||
|
||||
len = ulev1_getVersion(version, sizeof(version));
|
||||
ul_switch_off_field();
|
||||
|
||||
switch (len) {
|
||||
case -1:
|
||||
|
@ -449,6 +459,7 @@ uint16_t GetHF14AMfU_Type(void){
|
|||
} else {
|
||||
tagtype = UL;
|
||||
}
|
||||
ul_switch_off_field();
|
||||
}
|
||||
|
||||
//PrintAndLog("ICE %d", tagtype);
|
||||
|
@ -459,12 +470,11 @@ uint16_t GetHF14AMfU_Type(void){
|
|||
//return UL_MAGIC;
|
||||
}
|
||||
|
||||
ul_switch_off_field();
|
||||
return tagtype;
|
||||
}
|
||||
|
||||
int CmdHF14AMfUInfo(const char *Cmd){
|
||||
|
||||
|
||||
uint8_t data[16] = {0x00};
|
||||
iso14a_card_select_t card;
|
||||
uint8_t *key;
|
||||
|
@ -488,33 +498,32 @@ int CmdHF14AMfUInfo(const char *Cmd){
|
|||
// read pages 0,1,2,4 (should read 4pages)
|
||||
status = ul_read(0, data, sizeof(data));
|
||||
if ( status == -1 ){
|
||||
PrintAndLog("Error: tag didn't answer to READ");
|
||||
PrintAndLog("Error: tag didn't answer to READ A");
|
||||
ul_switch_off_field();
|
||||
return status;
|
||||
}
|
||||
|
||||
ul_print_default(data);
|
||||
|
||||
|
||||
if ((tagtype & UL_C)){
|
||||
|
||||
// lookup lockbits before?
|
||||
// read pages 0x28, 0x29, 0x2A, 0x2B
|
||||
// tag may be locked
|
||||
uint8_t ulc_conf[16] = {0x00};
|
||||
status = ul_read(0x28, ulc_conf, sizeof(ulc_conf));
|
||||
if ( status == -1 ){
|
||||
PrintAndLog("Error: tag didn't answer to READ");
|
||||
ul_switch_off_field();
|
||||
return status;
|
||||
PrintAndLog("Error: tag didn't answer to READ - possibly locked");
|
||||
} else {
|
||||
ulc_print_configuration(ulc_conf);
|
||||
}
|
||||
|
||||
ulc_print_configuration(ulc_conf);
|
||||
|
||||
if ((tagtype & UL_C_MAGIC)){
|
||||
if ((tagtype & MAGIC)){
|
||||
|
||||
uint8_t ulc_deskey[16] = {0x00};
|
||||
status = ul_read(0x2C, ulc_deskey, sizeof(ulc_deskey));
|
||||
if ( status == -1 ){
|
||||
PrintAndLog("Error: tag didn't answer to READ");
|
||||
PrintAndLog("Error: tag didn't answer to READ B");
|
||||
ul_switch_off_field();
|
||||
return status;
|
||||
}
|
||||
|
@ -524,6 +533,7 @@ int CmdHF14AMfUInfo(const char *Cmd){
|
|||
}
|
||||
else {
|
||||
PrintAndLog("Trying some default 3des keys");
|
||||
ul_switch_off_field();
|
||||
for (uint8_t i = 0; i < 7; ++i ){
|
||||
key = default_3des_keys[i];
|
||||
if (try3DesAuthentication(key) == 1){
|
||||
|
@ -542,11 +552,10 @@ int CmdHF14AMfUInfo(const char *Cmd){
|
|||
uint8_t ulev1_conf[16] = {0x00};
|
||||
status = ul_read(startconfigblock, ulev1_conf, sizeof(ulev1_conf));
|
||||
if ( status == -1 ){
|
||||
PrintAndLog("Error: tag didn't answer to READ");
|
||||
PrintAndLog("Error: tag didn't answer to READ C");
|
||||
ul_switch_off_field();
|
||||
return status;
|
||||
}
|
||||
|
||||
}
|
||||
ulev1_print_configuration(ulev1_conf);
|
||||
|
||||
uint8_t ulev1_signature[32] = {0x00};
|
||||
|
@ -556,10 +565,7 @@ int CmdHF14AMfUInfo(const char *Cmd){
|
|||
ul_switch_off_field();
|
||||
return status;
|
||||
}
|
||||
|
||||
PrintAndLog(" ECC Signature : %s", sprint_hex(ulev1_signature, sizeof(ulev1_signature)));
|
||||
PrintAndLog(" Verify it with the following 'secp128r1' for Elliptic curve cryptograghy in OpenSSL");
|
||||
|
||||
ulev1_print_signature( ulev1_signature, sizeof(ulev1_signature));
|
||||
}
|
||||
|
||||
if ((tagtype & (UL_EV1_48 | UL_EV1_128 | NTAG_213 | NTAG_215 | NTAG_216))) {
|
||||
|
@ -595,7 +601,7 @@ int CmdHF14AMfUInfo(const char *Cmd){
|
|||
uint8_t cc[16] = {0x00};
|
||||
status = ul_read(2, cc, sizeof(cc));
|
||||
if ( status == -1 ){
|
||||
PrintAndLog("Error: tag didn't answer to READ");
|
||||
PrintAndLog("Error: tag didn't answer to READ D");
|
||||
ul_switch_off_field();
|
||||
return status;
|
||||
}
|
||||
|
@ -723,6 +729,11 @@ int usage_hf_mfu_dump(void)
|
|||
PrintAndLog("and saves binary dump into the file `filename.bin` or `cardUID.bin`");
|
||||
PrintAndLog("It autodetects card type.\n");
|
||||
PrintAndLog("Usage: hf mfu dump k <key> n <filename w/o .bin>");
|
||||
PrintAndLog(" Options : ");
|
||||
PrintAndLog(" k <key> : Enter key for authentication");
|
||||
PrintAndLog(" n <FN > : Enter filename w/o .bin to save the dump as");
|
||||
PrintAndLog(" s : Swap entered key's endianness for auth");
|
||||
PrintAndLog("");
|
||||
PrintAndLog(" sample : hf mfu dump");
|
||||
PrintAndLog(" : hf mfu dump n myfile");
|
||||
return 0;
|
||||
|
@ -751,10 +762,11 @@ int CmdHF14AMfUDump(const char *Cmd){
|
|||
bool tmplockbit = false;
|
||||
uint8_t dataLen=0;
|
||||
uint8_t cmdp =0;
|
||||
//uint8_t key[16]= {0x00};
|
||||
uint8_t *key = NULL;
|
||||
uint8_t key[16] = {0x00};
|
||||
uint8_t *keyPtr = key;
|
||||
size_t fileNlen = 0;
|
||||
bool errors = FALSE;
|
||||
bool errors = false;
|
||||
bool swapEndian = false;
|
||||
|
||||
while(param_getchar(Cmd, cmdp) != 0x00)
|
||||
{
|
||||
|
@ -769,9 +781,7 @@ int CmdHF14AMfUDump(const char *Cmd){
|
|||
if (dataLen) {
|
||||
errors = true;
|
||||
} else {
|
||||
//memcpy(key, data, 16);
|
||||
key = SwapEndian64(data, 16);
|
||||
PrintAndLog("3des key: %s",sprint_hex(key, 16));
|
||||
memcpy(key, data, 16);
|
||||
}
|
||||
cmdp += 2;
|
||||
hasPwd = true;
|
||||
|
@ -783,6 +793,9 @@ int CmdHF14AMfUDump(const char *Cmd){
|
|||
if (fileNlen > FILE_PATH_SIZE-5) fileNlen = FILE_PATH_SIZE-5;
|
||||
cmdp += 2;
|
||||
break;
|
||||
case 's':
|
||||
swapEndian = true;
|
||||
cmdp++;
|
||||
default:
|
||||
PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp));
|
||||
errors = true;
|
||||
|
@ -794,6 +807,9 @@ int CmdHF14AMfUDump(const char *Cmd){
|
|||
//Validations
|
||||
if(errors) return usage_hf_mfu_dump();
|
||||
|
||||
if (swapEndian)
|
||||
keyPtr = SwapEndian64(data, 16);
|
||||
|
||||
TagTypeUL_t tagtype = GetHF14AMfU_Type();
|
||||
if (tagtype == UL_ERROR) return -1;
|
||||
|
||||
|
@ -828,7 +844,7 @@ int CmdHF14AMfUDump(const char *Cmd){
|
|||
PrintAndLog("Command execute time-out");
|
||||
return 1;
|
||||
}
|
||||
|
||||
PrintAndLog ("%u,%u",resp.arg[0],resp.arg[1]);
|
||||
uint8_t isOK = resp.arg[0] & 0xff;
|
||||
if (isOK) {
|
||||
memcpy(data, resp.d.asBytes, resp.arg[1]);
|
||||
|
@ -1159,11 +1175,11 @@ int CmdHF14AMfUCRdBl(const char *Cmd)
|
|||
UsbCommand resp;
|
||||
bool hasPwd = FALSE;
|
||||
uint8_t blockNo = -1;
|
||||
unsigned char key[16];
|
||||
uint8_t key[16];
|
||||
char cmdp = param_getchar(Cmd, 0);
|
||||
|
||||
if (strlen(Cmd) < 1 || cmdp == 'h' || cmdp == 'H') {
|
||||
PrintAndLog("Usage: hf mfu crdbl <block number> <password>");
|
||||
PrintAndLog("Usage: hf mfu crdbl <block number> <key>");
|
||||
PrintAndLog("");
|
||||
PrintAndLog("sample: hf mfu crdbl 0");
|
||||
PrintAndLog(" hf mfu crdbl 0 00112233445566778899AABBCCDDEEFF");
|
||||
|
@ -1255,6 +1271,7 @@ int CmdHF14AMfUCWrBl(const char *Cmd){
|
|||
if ( blockNo <= 3 ) {
|
||||
if (!chinese_card){
|
||||
PrintAndLog("Access Denied");
|
||||
return 1;
|
||||
} else {
|
||||
PrintAndLog("--Special block no: 0x%02x", blockNo);
|
||||
PrintAndLog("--Data: %s", sprint_hex(bldata, 4));
|
||||
|
@ -1266,6 +1283,7 @@ int CmdHF14AMfUCWrBl(const char *Cmd){
|
|||
PrintAndLog("isOk:%02x", isOK);
|
||||
} else {
|
||||
PrintAndLog("Command execute timeout");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -1279,6 +1297,7 @@ int CmdHF14AMfUCWrBl(const char *Cmd){
|
|||
PrintAndLog("isOk : %02x", isOK);
|
||||
} else {
|
||||
PrintAndLog("Command execute timeout");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
@ -1532,4 +1551,4 @@ int CmdHFMFUltra(const char *Cmd){
|
|||
int CmdHelp(const char *Cmd){
|
||||
CmdsHelp(CommandTable);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue