ADD: UL-EV1 signature printing.

CHG: @marshmellows changes.
This commit is contained in:
iceman1001 2015-05-06 14:19:23 +02:00
parent 69a2953679
commit 2b03dea768

View file

@ -21,23 +21,22 @@
#define MAX_ULEV1b_BLOCKS 0x20 #define MAX_ULEV1b_BLOCKS 0x20
#define MAX_NTAG_213 0x2c #define MAX_NTAG_213 0x2c
#define MAX_NTAG_215 0x86 #define MAX_NTAG_215 0x86
#define MAX_NTAG_216 0xE6 #define MAX_NTAG_216 0xe6
typedef enum TAGTYPE_UL { typedef enum TAGTYPE_UL {
UNKNOWN = 0, UNKNOWN = 0x0000,
UL = 1, UL = 0x0001,
UL_C = 2, UL_C = 0x0002,
UL_EV1_48 = 4, UL_EV1_48 = 0x0004,
UL_EV1_128 = 8, UL_EV1_128 = 0x0008,
NTAG = 16, NTAG = 0x0010,
NTAG_213 = 32, NTAG_213 = 0x0020,
NTAG_215 = 64, NTAG_215 = 0x0040,
NTAG_216 = 128, NTAG_216 = 0x0080,
MAGIC = 256, MAGIC = 0x0100,
UL_MAGIC = UL | MAGIC, UL_MAGIC = UL | MAGIC,
UL_C_MAGIC = UL_C | MAGIC, UL_C_MAGIC = UL_C | MAGIC,
UL_ERROR = 0xFFFF, UL_ERROR = 0xFFFF,
} TagTypeUL_t; } TagTypeUL_t;
uint8_t default_3des_keys[7][16] = { uint8_t default_3des_keys[7][16] = {
@ -86,9 +85,9 @@ char* getUlev1CardSizeStr( uint8_t fsize ){
// is LSB set? // is LSB set?
if ( fsize & 1 ) if ( fsize & 1 )
sprintf(retStr, "0x%02X (%d - %d bytes)",fsize, usize, lsize); sprintf(retStr, "0x%02X (%u - %u bytes)",fsize, usize, lsize);
else else
sprintf(retStr, "0x%02X (%d bytes)", fsize, lsize); sprintf(retStr, "0x%02X (%u bytes)", fsize, lsize);
return buf; return buf;
} }
@ -109,13 +108,14 @@ static int ul_send_cmd_raw( uint8_t *cmd, uint8_t cmdlen, uint8_t *response, uin
UsbCommand resp; UsbCommand resp;
if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) return -1; if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) return -1;
if (resp.arg[0] > 0) {
uint16_t resplen = (resp.arg[0] < responseLength) ? resp.arg[0] : responseLength; uint16_t resplen = (resp.arg[0] < responseLength) ? resp.arg[0] : responseLength;
if (resp.arg[0] > 0)
memcpy(response, resp.d.asBytes, resplen); 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 ) { 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}}; 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; if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) return -1;
uint16_t resplen = (resp.arg[0] < responseLength) ? resp.arg[0] : responseLength; 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 ); memcpy(response, resp.d.asBytes, resplen );
return resplen; return resplen;
} else return -1;
} }
*/
static int ul_select( iso14a_card_select_t *card ){ static int ul_select( iso14a_card_select_t *card ){
ul_switch_on_field(); ul_switch_on_field();
UsbCommand resp; UsbCommand resp;
if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) return -1;
ul_switch_off_field(); if (resp.arg[0] < 0) return -1;
return -1;
}
if (resp.arg[0] > 0) {
memcpy(card, resp.d.asBytes, sizeof(iso14a_card_select_t)); memcpy(card, resp.d.asBytes, sizeof(iso14a_card_select_t));
}
return resp.arg[0]; return resp.arg[0];
} }
@ -292,11 +289,11 @@ static int ul_print_type(uint16_t tagtype){
if ( tagtype & UL ) if ( tagtype & UL )
PrintAndLog(" TYPE : MIFARE Ultralight (MF0ICU1) %s", (tagtype & MAGIC)?"<magic>":""); PrintAndLog(" TYPE : MIFARE Ultralight (MF0ICU1) %s", (tagtype & MAGIC)?"<magic>":"");
else if ( tagtype & UL_C) 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) else if ( tagtype & UL_EV1_48)
PrintAndLog(" TYPE : MIFARE Ultralight EV1 48bytes (MF0UL1101)"); PrintAndLog(" TYPE : MIFARE Ultralight EV1 48bytes (MF0UL1101)");
else if ( tagtype & UL_EV1_128) 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 ) else if ( tagtype & NTAG_213 )
PrintAndLog(" TYPE : MIFARE NTAG 213 144bytes (NT2H1311G0DU)"); PrintAndLog(" TYPE : MIFARE NTAG 213 144bytes (NT2H1311G0DU)");
else if ( tagtype & NTAG_215 ) else if ( tagtype & NTAG_215 )
@ -376,6 +373,17 @@ static int ulev1_print_counters(){
return 0; 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){ uint16_t GetHF14AMfU_Type(void){
TagTypeUL_t tagtype = UNKNOWN; TagTypeUL_t tagtype = UNKNOWN;
@ -389,6 +397,7 @@ uint16_t GetHF14AMfU_Type(void){
status = ul_select(&card); status = ul_select(&card);
if ( status < 1 ){ if ( status < 1 ){
PrintAndLog("Error: couldn't select"); PrintAndLog("Error: couldn't select");
ul_switch_off_field();
return UL_ERROR; return UL_ERROR;
} }
@ -399,6 +408,7 @@ uint16_t GetHF14AMfU_Type(void){
} }
len = ulev1_getVersion(version, sizeof(version)); len = ulev1_getVersion(version, sizeof(version));
ul_switch_off_field();
switch (len) { switch (len) {
case -1: case -1:
@ -449,6 +459,7 @@ uint16_t GetHF14AMfU_Type(void){
} else { } else {
tagtype = UL; tagtype = UL;
} }
ul_switch_off_field();
} }
//PrintAndLog("ICE %d", tagtype); //PrintAndLog("ICE %d", tagtype);
@ -459,7 +470,6 @@ uint16_t GetHF14AMfU_Type(void){
//return UL_MAGIC; //return UL_MAGIC;
} }
ul_switch_off_field();
return tagtype; return tagtype;
} }
@ -488,33 +498,32 @@ int CmdHF14AMfUInfo(const char *Cmd){
// read pages 0,1,2,4 (should read 4pages) // read pages 0,1,2,4 (should read 4pages)
status = ul_read(0, data, sizeof(data)); status = ul_read(0, data, sizeof(data));
if ( status == -1 ){ if ( status == -1 ){
PrintAndLog("Error: tag didn't answer to READ"); PrintAndLog("Error: tag didn't answer to READ A");
ul_switch_off_field(); ul_switch_off_field();
return status; return status;
} }
ul_print_default(data); ul_print_default(data);
if ((tagtype & UL_C)){ if ((tagtype & UL_C)){
// lookup lockbits before?
// read pages 0x28, 0x29, 0x2A, 0x2B // read pages 0x28, 0x29, 0x2A, 0x2B
// tag may be locked
uint8_t ulc_conf[16] = {0x00}; uint8_t ulc_conf[16] = {0x00};
status = ul_read(0x28, ulc_conf, sizeof(ulc_conf)); status = ul_read(0x28, ulc_conf, sizeof(ulc_conf));
if ( status == -1 ){ if ( status == -1 ){
PrintAndLog("Error: tag didn't answer to READ"); PrintAndLog("Error: tag didn't answer to READ - possibly locked");
ul_switch_off_field(); } else {
return status; ulc_print_configuration(ulc_conf);
} }
ulc_print_configuration(ulc_conf); if ((tagtype & MAGIC)){
if ((tagtype & UL_C_MAGIC)){
uint8_t ulc_deskey[16] = {0x00}; uint8_t ulc_deskey[16] = {0x00};
status = ul_read(0x2C, ulc_deskey, sizeof(ulc_deskey)); status = ul_read(0x2C, ulc_deskey, sizeof(ulc_deskey));
if ( status == -1 ){ if ( status == -1 ){
PrintAndLog("Error: tag didn't answer to READ"); PrintAndLog("Error: tag didn't answer to READ B");
ul_switch_off_field(); ul_switch_off_field();
return status; return status;
} }
@ -524,6 +533,7 @@ int CmdHF14AMfUInfo(const char *Cmd){
} }
else { else {
PrintAndLog("Trying some default 3des keys"); PrintAndLog("Trying some default 3des keys");
ul_switch_off_field();
for (uint8_t i = 0; i < 7; ++i ){ for (uint8_t i = 0; i < 7; ++i ){
key = default_3des_keys[i]; key = default_3des_keys[i];
if (try3DesAuthentication(key) == 1){ if (try3DesAuthentication(key) == 1){
@ -542,11 +552,10 @@ int CmdHF14AMfUInfo(const char *Cmd){
uint8_t ulev1_conf[16] = {0x00}; uint8_t ulev1_conf[16] = {0x00};
status = ul_read(startconfigblock, ulev1_conf, sizeof(ulev1_conf)); status = ul_read(startconfigblock, ulev1_conf, sizeof(ulev1_conf));
if ( status == -1 ){ if ( status == -1 ){
PrintAndLog("Error: tag didn't answer to READ"); PrintAndLog("Error: tag didn't answer to READ C");
ul_switch_off_field(); ul_switch_off_field();
return status; return status;
} }
ulev1_print_configuration(ulev1_conf); ulev1_print_configuration(ulev1_conf);
uint8_t ulev1_signature[32] = {0x00}; uint8_t ulev1_signature[32] = {0x00};
@ -556,10 +565,7 @@ int CmdHF14AMfUInfo(const char *Cmd){
ul_switch_off_field(); ul_switch_off_field();
return status; return status;
} }
ulev1_print_signature( ulev1_signature, sizeof(ulev1_signature));
PrintAndLog(" ECC Signature : %s", sprint_hex(ulev1_signature, sizeof(ulev1_signature)));
PrintAndLog(" Verify it with the following 'secp128r1' for Elliptic curve cryptograghy in OpenSSL");
} }
if ((tagtype & (UL_EV1_48 | UL_EV1_128 | NTAG_213 | NTAG_215 | NTAG_216))) { 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}; uint8_t cc[16] = {0x00};
status = ul_read(2, cc, sizeof(cc)); status = ul_read(2, cc, sizeof(cc));
if ( status == -1 ){ if ( status == -1 ){
PrintAndLog("Error: tag didn't answer to READ"); PrintAndLog("Error: tag didn't answer to READ D");
ul_switch_off_field(); ul_switch_off_field();
return status; 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("and saves binary dump into the file `filename.bin` or `cardUID.bin`");
PrintAndLog("It autodetects card type.\n"); PrintAndLog("It autodetects card type.\n");
PrintAndLog("Usage: hf mfu dump k <key> n <filename w/o .bin>"); 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(" sample : hf mfu dump");
PrintAndLog(" : hf mfu dump n myfile"); PrintAndLog(" : hf mfu dump n myfile");
return 0; return 0;
@ -751,10 +762,11 @@ int CmdHF14AMfUDump(const char *Cmd){
bool tmplockbit = false; bool tmplockbit = false;
uint8_t dataLen=0; uint8_t dataLen=0;
uint8_t cmdp =0; uint8_t cmdp =0;
//uint8_t key[16]= {0x00}; uint8_t key[16] = {0x00};
uint8_t *key = NULL; uint8_t *keyPtr = key;
size_t fileNlen = 0; size_t fileNlen = 0;
bool errors = FALSE; bool errors = false;
bool swapEndian = false;
while(param_getchar(Cmd, cmdp) != 0x00) while(param_getchar(Cmd, cmdp) != 0x00)
{ {
@ -769,9 +781,7 @@ int CmdHF14AMfUDump(const char *Cmd){
if (dataLen) { if (dataLen) {
errors = true; errors = true;
} else { } else {
//memcpy(key, data, 16); memcpy(key, data, 16);
key = SwapEndian64(data, 16);
PrintAndLog("3des key: %s",sprint_hex(key, 16));
} }
cmdp += 2; cmdp += 2;
hasPwd = true; hasPwd = true;
@ -783,6 +793,9 @@ int CmdHF14AMfUDump(const char *Cmd){
if (fileNlen > FILE_PATH_SIZE-5) fileNlen = FILE_PATH_SIZE-5; if (fileNlen > FILE_PATH_SIZE-5) fileNlen = FILE_PATH_SIZE-5;
cmdp += 2; cmdp += 2;
break; break;
case 's':
swapEndian = true;
cmdp++;
default: default:
PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp)); PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp));
errors = true; errors = true;
@ -794,6 +807,9 @@ int CmdHF14AMfUDump(const char *Cmd){
//Validations //Validations
if(errors) return usage_hf_mfu_dump(); if(errors) return usage_hf_mfu_dump();
if (swapEndian)
keyPtr = SwapEndian64(data, 16);
TagTypeUL_t tagtype = GetHF14AMfU_Type(); TagTypeUL_t tagtype = GetHF14AMfU_Type();
if (tagtype == UL_ERROR) return -1; if (tagtype == UL_ERROR) return -1;
@ -828,7 +844,7 @@ int CmdHF14AMfUDump(const char *Cmd){
PrintAndLog("Command execute time-out"); PrintAndLog("Command execute time-out");
return 1; return 1;
} }
PrintAndLog ("%u,%u",resp.arg[0],resp.arg[1]);
uint8_t isOK = resp.arg[0] & 0xff; uint8_t isOK = resp.arg[0] & 0xff;
if (isOK) { if (isOK) {
memcpy(data, resp.d.asBytes, resp.arg[1]); memcpy(data, resp.d.asBytes, resp.arg[1]);
@ -1159,11 +1175,11 @@ int CmdHF14AMfUCRdBl(const char *Cmd)
UsbCommand resp; UsbCommand resp;
bool hasPwd = FALSE; bool hasPwd = FALSE;
uint8_t blockNo = -1; uint8_t blockNo = -1;
unsigned char key[16]; uint8_t key[16];
char cmdp = param_getchar(Cmd, 0); char cmdp = param_getchar(Cmd, 0);
if (strlen(Cmd) < 1 || cmdp == 'h' || cmdp == 'H') { 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("");
PrintAndLog("sample: hf mfu crdbl 0"); PrintAndLog("sample: hf mfu crdbl 0");
PrintAndLog(" hf mfu crdbl 0 00112233445566778899AABBCCDDEEFF"); PrintAndLog(" hf mfu crdbl 0 00112233445566778899AABBCCDDEEFF");
@ -1255,6 +1271,7 @@ int CmdHF14AMfUCWrBl(const char *Cmd){
if ( blockNo <= 3 ) { if ( blockNo <= 3 ) {
if (!chinese_card){ if (!chinese_card){
PrintAndLog("Access Denied"); PrintAndLog("Access Denied");
return 1;
} else { } else {
PrintAndLog("--Special block no: 0x%02x", blockNo); PrintAndLog("--Special block no: 0x%02x", blockNo);
PrintAndLog("--Data: %s", sprint_hex(bldata, 4)); PrintAndLog("--Data: %s", sprint_hex(bldata, 4));
@ -1266,6 +1283,7 @@ int CmdHF14AMfUCWrBl(const char *Cmd){
PrintAndLog("isOk:%02x", isOK); PrintAndLog("isOk:%02x", isOK);
} else { } else {
PrintAndLog("Command execute timeout"); PrintAndLog("Command execute timeout");
return 1;
} }
} }
} else { } else {
@ -1279,6 +1297,7 @@ int CmdHF14AMfUCWrBl(const char *Cmd){
PrintAndLog("isOk : %02x", isOK); PrintAndLog("isOk : %02x", isOK);
} else { } else {
PrintAndLog("Command execute timeout"); PrintAndLog("Command execute timeout");
return 1;
} }
} }
return 0; return 0;