Merge branch 'master' of https://github.com/RfidResearchGroup/proxmark3
This commit is contained in:
@@ -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...
|
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]
|
## [unreleased][unreleased]
|
||||||
|
- Added `hf mfu ndef` - read and decode NDEF Type2 messages (@iceman1001)
|
||||||
- Added `data ndef` - decode NDEF messages (@iceman1001)
|
- Added `data ndef` - decode NDEF messages (@iceman1001)
|
||||||
- Change - usb write's now waits for shiftregisters (@pwpiwi)
|
- Change - usb write's now waits for shiftregisters (@pwpiwi)
|
||||||
- Change - NDEF supports more signatures now (@iceman1001)
|
- Change - NDEF supports more signatures now (@iceman1001)
|
||||||
|
|||||||
@@ -2309,8 +2309,9 @@ static int CmdDataNDEF(const char *Cmd) {
|
|||||||
int datalen = 0;
|
int datalen = 0;
|
||||||
uint8_t data[MAX_NDEF_LEN] = {0};
|
uint8_t data[MAX_NDEF_LEN] = {0};
|
||||||
CLIGetHexWithReturn(1, data, &datalen);
|
CLIGetHexWithReturn(1, data, &datalen);
|
||||||
|
|
||||||
CLIParserFree();
|
CLIParserFree();
|
||||||
|
if (datalen == 0)
|
||||||
|
return PM3_EINVARG;
|
||||||
|
|
||||||
PrintAndLogEx(INFO, "Parsed NDEF Records");
|
PrintAndLogEx(INFO, "Parsed NDEF Records");
|
||||||
return NDEFRecordsDecodeAndPrint(data, datalen);
|
return NDEFRecordsDecodeAndPrint(data, datalen);
|
||||||
|
|||||||
@@ -208,7 +208,8 @@ const productName uidmapping[] = {
|
|||||||
{ 0, 0, "no tag-info available" } // must be the last entry
|
{ 0, 0, "no tag-info available" } // must be the last entry
|
||||||
};
|
};
|
||||||
|
|
||||||
uint8_t nxp_public_keys[][33] = {
|
#define PUBLIC_ECDA_KEYLEN 33
|
||||||
|
uint8_t nxp_15693_public_keys[][PUBLIC_ECDA_KEYLEN] = {
|
||||||
// ICODE SLIX2 / DNA
|
// ICODE SLIX2 / DNA
|
||||||
{
|
{
|
||||||
0x04, 0x88, 0x78, 0xA2, 0xA2, 0xD3, 0xEE, 0xC3,
|
0x04, 0x88, 0x78, 0xA2, 0xA2, 0xD3, 0xEE, 0xC3,
|
||||||
@@ -216,10 +217,67 @@ uint8_t nxp_public_keys[][33] = {
|
|||||||
0xF9, 0xBE, 0x11, 0xC4, 0xE2, 0xE8, 0x96, 0x64,
|
0xF9, 0xBE, 0x11, 0xC4, 0xE2, 0xE8, 0x96, 0x64,
|
||||||
0x8B, 0x32, 0xEF, 0xA5, 0x9C, 0xEA, 0x6E, 0x59, 0xF0
|
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
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static int CmdHF15Help(const char *Cmd);
|
static int CmdHF15Help(const char *Cmd);
|
||||||
|
|
||||||
|
static int nxp_15693_print_signature(uint8_t *uid, uint8_t *signature) {
|
||||||
|
|
||||||
|
uint8_t i;
|
||||||
|
int res;
|
||||||
|
bool is_valid = false;
|
||||||
|
for (i = 0; i< ARRAYLEN(nxp_15693_public_keys); i++) {
|
||||||
|
|
||||||
|
res = ecdsa_signature_r_s_verify(MBEDTLS_ECP_DP_SECP128R1, nxp_15693_public_keys[i], uid, 8, signature, 32, false);
|
||||||
|
|
||||||
|
is_valid = (res == 0);
|
||||||
|
if (is_valid)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
if (is_valid == false) {
|
||||||
|
PrintAndLogEx(SUCCESS, "Signature verification " _RED_("failed"));
|
||||||
|
return PM3_ESOFT;
|
||||||
|
}
|
||||||
|
|
||||||
|
PrintAndLogEx(INFO, "\n--- Tag Signature");
|
||||||
|
PrintAndLogEx(INFO, " IC signature public key name : %s", (i == 0)? "NXP ICODE SLIX2 / DNA" : "unknown, post on forum");
|
||||||
|
PrintAndLogEx(INFO, " IC signature public key value : %s", sprint_hex(nxp_15693_public_keys[i], 33));
|
||||||
|
PrintAndLogEx(INFO, " Elliptic curve parameters : NID_secp128r1");
|
||||||
|
PrintAndLogEx(INFO, " TAG IC Signature : %s", sprint_hex(signature, 32));
|
||||||
|
PrintAndLogEx(INFO, " Signature verification " _GREEN_("successful"));
|
||||||
|
return PM3_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
// fast method to just read the UID of a tag (collision detection not supported)
|
// fast method to just read the UID of a tag (collision detection not supported)
|
||||||
// *buf should be large enough to fit the 64bit uid
|
// *buf should be large enough to fit the 64bit uid
|
||||||
// returns 1 if succeeded
|
// returns 1 if succeeded
|
||||||
@@ -796,16 +854,8 @@ static int NxpSysInfo(uint8_t *uid) {
|
|||||||
uint8_t signature[32] = {0x00};
|
uint8_t signature[32] = {0x00};
|
||||||
memcpy(signature, recv + 1, 32);
|
memcpy(signature, recv + 1, 32);
|
||||||
|
|
||||||
int res = ecdsa_signature_r_s_verify(MBEDTLS_ECP_DP_SECP128R1, nxp_public_keys[0], uid, 8, signature, 32, false);
|
nxp_15693_print_signature(uid, signature);
|
||||||
bool is_valid = (res == 0);
|
|
||||||
|
|
||||||
PrintAndLogEx(NORMAL, "");
|
|
||||||
PrintAndLogEx(NORMAL, " Tag Signature");
|
|
||||||
PrintAndLogEx(NORMAL, " IC signature public key name : NXP ICODE SLIX2 / DNA");
|
|
||||||
PrintAndLogEx(NORMAL, " IC signature public key value : %s", sprint_hex(nxp_public_keys[0], 33));
|
|
||||||
PrintAndLogEx(NORMAL, " Elliptic curve parameters : NID_secp128r1");
|
|
||||||
PrintAndLogEx(NORMAL, " TAG IC Signature : %s", sprint_hex(signature, 32));
|
|
||||||
PrintAndLogEx(NORMAL, " Signature verification %s", (is_valid) ? _GREEN_("successful") : _RED_("failed"));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -901,10 +951,16 @@ static int CmdHF15Info(const char *Cmd) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check if SLIX2 and attempt to get NXP System Information
|
// Check if SLIX2 and attempt to get NXP System Information
|
||||||
|
PrintAndLogEx(INFO, "4 & 08 :: %02x 7 == 1 :: %u 8 == 4 :: %u", recv[4], recv[7], recv[8]);
|
||||||
if (recv[8] == 0x04 && recv[7] == 0x01 && recv[4] & 0x80) {
|
if (recv[8] == 0x04 && recv[7] == 0x01 && recv[4] & 0x80) {
|
||||||
return NxpSysInfo(uid);
|
return NxpSysInfo(uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if (recv[8] == 0x04 && recv[7] == 0x02 && recv[4] & 0x80) {
|
||||||
|
return NxpSysInfo(uid);
|
||||||
|
//}
|
||||||
|
|
||||||
|
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "commonutil.h" // ARRAYLEN
|
||||||
#include "cmdparser.h" // command_t
|
#include "cmdparser.h" // command_t
|
||||||
#include "comms.h"
|
#include "comms.h"
|
||||||
#include "ui.h"
|
#include "ui.h"
|
||||||
@@ -121,18 +122,10 @@ static int get_desfire_freemem(uint32_t *free_mem) {
|
|||||||
// --- GET SIGNATURE
|
// --- GET SIGNATURE
|
||||||
static int desfire_print_signature(uint8_t *uid, uint8_t *signature, size_t signature_len, desfire_cardtype_t card_type) {
|
static int desfire_print_signature(uint8_t *uid, uint8_t *signature, size_t signature_len, desfire_cardtype_t card_type) {
|
||||||
|
|
||||||
uint8_t public_key;
|
|
||||||
if (card_type == LIGHT)
|
|
||||||
public_key = 0;
|
|
||||||
else if (card_type == EV2)
|
|
||||||
public_key = 1;
|
|
||||||
else
|
|
||||||
return PM3_EINVARG;
|
|
||||||
|
|
||||||
#define PUBLIC_DESFIRE_ECDA_KEYLEN 57
|
#define PUBLIC_DESFIRE_ECDA_KEYLEN 57
|
||||||
|
|
||||||
// ref: MIFARE Desfire Originality Signature Validation
|
// ref: MIFARE Desfire Originality Signature Validation
|
||||||
uint8_t nxp_desfire_keys[2][PUBLIC_DESFIRE_ECDA_KEYLEN] = {
|
uint8_t nxp_desfire_keys[][PUBLIC_DESFIRE_ECDA_KEYLEN] = {
|
||||||
// DESFire Light
|
// DESFire Light
|
||||||
{
|
{
|
||||||
0x04, 0x0E, 0x98, 0xE1, 0x17, 0xAA, 0xA3, 0x64,
|
0x04, 0x0E, 0x98, 0xE1, 0x17, 0xAA, 0xA3, 0x64,
|
||||||
@@ -143,7 +136,11 @@ static int desfire_print_signature(uint8_t *uid, uint8_t *signature, size_t sign
|
|||||||
0xD0, 0x25, 0x72, 0x42, 0x7E, 0x5A, 0xE0, 0xA2,
|
0xD0, 0x25, 0x72, 0x42, 0x7E, 0x5A, 0xE0, 0xA2,
|
||||||
0xDD, 0x36, 0x59, 0x1B, 0x1F, 0xB3, 0x4F, 0xCF, 0x3D
|
0xDD, 0x36, 0x59, 0x1B, 0x1F, 0xB3, 0x4F, 0xCF, 0x3D
|
||||||
},
|
},
|
||||||
// DESFire Ev2
|
|
||||||
|
// DESFire Ev2 - wanted
|
||||||
|
// DESFire Ev3 - wanted
|
||||||
|
|
||||||
|
// Unknown - needs identification
|
||||||
{
|
{
|
||||||
0x04, 0x8A, 0x9B, 0x38, 0x0A, 0xF2, 0xEE, 0x1B,
|
0x04, 0x8A, 0x9B, 0x38, 0x0A, 0xF2, 0xEE, 0x1B,
|
||||||
0x98, 0xDC, 0x41, 0x7F, 0xEC, 0xC2, 0x63, 0xF8,
|
0x98, 0xDC, 0x41, 0x7F, 0xEC, 0xC2, 0x63, 0xF8,
|
||||||
@@ -152,26 +149,59 @@ static int desfire_print_signature(uint8_t *uid, uint8_t *signature, size_t sign
|
|||||||
0x42, 0x2B, 0x81, 0xEC, 0x20, 0xB6, 0x5A, 0x66,
|
0x42, 0x2B, 0x81, 0xEC, 0x20, 0xB6, 0x5A, 0x66,
|
||||||
0xB5, 0x10, 0x2A, 0x61, 0x59, 0x6A, 0xF3, 0x37,
|
0xB5, 0x10, 0x2A, 0x61, 0x59, 0x6A, 0xF3, 0x37,
|
||||||
0x92, 0x00, 0x59, 0x93, 0x16, 0xA0, 0x0A, 0x14, 0x10
|
0x92, 0x00, 0x59, 0x93, 0x16, 0xA0, 0x0A, 0x14, 0x10
|
||||||
}
|
},
|
||||||
|
|
||||||
|
// Unknown - needs identification
|
||||||
|
{
|
||||||
|
0x04, 0x44, 0x09, 0xAD, 0xC4, 0x2F, 0x91, 0xA8,
|
||||||
|
0x39, 0x40, 0x66, 0xBA, 0x83, 0xD8, 0x72, 0xFB,
|
||||||
|
0x1D, 0x16, 0x80, 0x37, 0x34, 0xE9, 0x11, 0x17,
|
||||||
|
0x04, 0x12, 0xDD, 0xF8, 0xBA, 0xD1, 0xA4, 0xDA,
|
||||||
|
0xDF, 0xD0, 0x41, 0x62, 0x91, 0xAF, 0xE1, 0xC7,
|
||||||
|
0x48, 0x25, 0x39, 0x25, 0xDA, 0x39, 0xA5, 0xF3,
|
||||||
|
0x9A, 0x1C, 0x55, 0x7F, 0xFA, 0xCD, 0x34, 0xC6, 0x2E
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
uint8_t i;
|
||||||
|
int res;
|
||||||
|
bool is_valid = false;
|
||||||
|
|
||||||
|
for (i = 0; i< ARRAYLEN(nxp_desfire_keys); i++) {
|
||||||
|
|
||||||
|
res = ecdsa_signature_r_s_verify(MBEDTLS_ECP_DP_SECP224R1, nxp_desfire_keys[i], uid, 7, signature, signature_len, false);
|
||||||
|
|
||||||
|
is_valid = (res == 0);
|
||||||
|
if (is_valid)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (is_valid == false) {
|
||||||
|
PrintAndLogEx(SUCCESS, "Signature verification " _RED_("failed"));
|
||||||
|
return PM3_ESOFT;
|
||||||
|
}
|
||||||
|
|
||||||
int res = ecdsa_signature_r_s_verify(MBEDTLS_ECP_DP_SECP224R1, nxp_desfire_keys[public_key], uid, 7, signature, signature_len, false);
|
char *publickeyname;
|
||||||
bool is_valid = (res == 0);
|
switch(i) {
|
||||||
|
case 0:
|
||||||
|
publickeyname = "NXP DESFire Light";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
publickeyname = "Unknown DESFire, post on forum";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
PrintAndLogEx(INFO, " Tag Signature");
|
PrintAndLogEx(INFO, " Tag Signature");
|
||||||
PrintAndLogEx(INFO, " IC signature public key name : %s", (card_type == LIGHT) ? "NXP DESFire Light" : "NXP DESFire Ev2");
|
PrintAndLogEx(INFO, " IC signature public key name : %s", publickeyname);
|
||||||
PrintAndLogEx(INFO, " IC signature public key value : %s", sprint_hex(nxp_desfire_keys[public_key], 16));
|
PrintAndLogEx(INFO, " IC signature public key value : %s", sprint_hex(nxp_desfire_keys[i], 16));
|
||||||
PrintAndLogEx(INFO, " : %s", sprint_hex(nxp_desfire_keys[public_key] + 16, 16));
|
PrintAndLogEx(INFO, " : %s", sprint_hex(nxp_desfire_keys[i] + 16, 16));
|
||||||
PrintAndLogEx(INFO, " : %s", sprint_hex(nxp_desfire_keys[public_key] + 32, 16));
|
PrintAndLogEx(INFO, " : %s", sprint_hex(nxp_desfire_keys[i] + 32, 16));
|
||||||
PrintAndLogEx(INFO, " : %s", sprint_hex(nxp_desfire_keys[public_key] + 48, PUBLIC_DESFIRE_ECDA_KEYLEN - 48));
|
PrintAndLogEx(INFO, " : %s", sprint_hex(nxp_desfire_keys[i] + 48, PUBLIC_DESFIRE_ECDA_KEYLEN - 48));
|
||||||
PrintAndLogEx(INFO, " Elliptic curve parameters : NID_secp224r1");
|
PrintAndLogEx(INFO, " Elliptic curve parameters : NID_secp224r1");
|
||||||
PrintAndLogEx(INFO, " TAG IC Signature : %s", sprint_hex(signature, 16));
|
PrintAndLogEx(INFO, " TAG IC Signature : %s", sprint_hex(signature, 16));
|
||||||
PrintAndLogEx(INFO, " : %s", sprint_hex(signature + 16, 16));
|
PrintAndLogEx(INFO, " : %s", sprint_hex(signature + 16, 16));
|
||||||
PrintAndLogEx(INFO, " : %s", sprint_hex(signature + 32, 16));
|
PrintAndLogEx(INFO, " : %s", sprint_hex(signature + 32, 16));
|
||||||
PrintAndLogEx(INFO, " : %s", sprint_hex(signature + 48, signature_len - 48));
|
PrintAndLogEx(INFO, " : %s", sprint_hex(signature + 48, signature_len - 48));
|
||||||
PrintAndLogEx( (is_valid) ? SUCCESS : WARNING, " Signature verified %s", (is_valid) ? _GREEN_("successful") : _RED_("failed"));
|
PrintAndLogEx( (is_valid) ? SUCCESS : WARNING, " Signature verified " _GREEN_("successful"));
|
||||||
PrintAndLogEx(INFO, "-------------------------------------------------------------");
|
PrintAndLogEx(INFO, "-------------------------------------------------------------");
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,9 @@
|
|||||||
#include "fileutils.h"
|
#include "fileutils.h"
|
||||||
#include "protocols.h"
|
#include "protocols.h"
|
||||||
#include "generator.h"
|
#include "generator.h"
|
||||||
|
#include "mifare/ndef.h"
|
||||||
|
#include "cliparser/cliparser.h"
|
||||||
|
|
||||||
|
|
||||||
#define MAX_UL_BLOCKS 0x0F
|
#define MAX_UL_BLOCKS 0x0F
|
||||||
#define MAX_ULC_BLOCKS 0x2B
|
#define MAX_ULC_BLOCKS 0x2B
|
||||||
@@ -259,29 +262,6 @@ uint8_t default_pwd_pack[][4] = {
|
|||||||
{0xFF, 0xFF, 0xFF, 0xFF}, // PACK 0x00,0x00 -- factory default
|
{0xFF, 0xFF, 0xFF, 0xFF}, // PACK 0x00,0x00 -- factory default
|
||||||
};
|
};
|
||||||
|
|
||||||
#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
|
|
||||||
uint8_t public_keys[2][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
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
uint32_t UL_TYPES_ARRAY[] = {
|
uint32_t UL_TYPES_ARRAY[] = {
|
||||||
UNKNOWN, UL, UL_C, UL_EV1_48, UL_EV1_128, NTAG,
|
UNKNOWN, UL, UL_C, UL_EV1_48, UL_EV1_128, NTAG,
|
||||||
NTAG_203, NTAG_210, NTAG_212, NTAG_213, NTAG_215, NTAG_216,
|
NTAG_203, NTAG_210, NTAG_212, NTAG_213, NTAG_215, NTAG_216,
|
||||||
@@ -563,6 +543,22 @@ static int ul_print_default(uint8_t *data) {
|
|||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int ndef_get_maxsize(uint8_t *data) {
|
||||||
|
// no NDEF message
|
||||||
|
if (data[0] != 0xE1)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (data[2] == 0x06)
|
||||||
|
return 48;
|
||||||
|
else if (data[2] == 0x12)
|
||||||
|
return 144;
|
||||||
|
else if (data[2] == 0x3E)
|
||||||
|
return 496;
|
||||||
|
else if (data[2] == 0x6D)
|
||||||
|
return 872;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int ndef_print_CC(uint8_t *data) {
|
static int ndef_print_CC(uint8_t *data) {
|
||||||
// no NDEF message
|
// no NDEF message
|
||||||
if (data[0] != 0xE1)
|
if (data[0] != 0xE1)
|
||||||
@@ -868,19 +864,98 @@ static int ulev1_print_counters() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int ulev1_print_signature(TagTypeUL_t tagtype, uint8_t *uid, uint8_t *signature, size_t signature_len) {
|
static int ulev1_print_signature(TagTypeUL_t tagtype, uint8_t *uid, uint8_t *signature, size_t signature_len) {
|
||||||
uint8_t public_key = 0;
|
|
||||||
if (tagtype == UL_EV1_48 || tagtype == UL_EV1_128) {
|
#define PUBLIC_ECDA_KEYLEN 33
|
||||||
public_key = 1;
|
|
||||||
|
// 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
|
||||||
|
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;
|
||||||
|
int res;
|
||||||
|
bool is_valid = false;
|
||||||
|
for (i = 0; i< ARRAYLEN(nxp_mfu_public_keys); i++) {
|
||||||
|
|
||||||
|
res = ecdsa_signature_r_s_verify(MBEDTLS_ECP_DP_SECP128R1, nxp_mfu_public_keys[i], uid, 7, signature, signature_len, false);
|
||||||
|
|
||||||
|
is_valid = (res == 0);
|
||||||
|
if (is_valid)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (is_valid == false) {
|
||||||
|
PrintAndLogEx(SUCCESS, "Signature verification " _RED_("failed"));
|
||||||
|
return PM3_ESOFT;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *publickeyname;
|
||||||
|
switch(i) {
|
||||||
|
case 0:
|
||||||
|
publickeyname = "NXP NTAG21x (2013)";
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
publickeyname = "NXP Ev1";
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
publickeyname = "Manufacturer, post on forum";
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
publickeyname = "MIKRON";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
publickeyname = "Unknown, post on forum";
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
int res = ecdsa_signature_r_s_verify(MBEDTLS_ECP_DP_SECP128R1, public_keys[public_key], uid, 7, signature, signature_len, false);
|
|
||||||
bool is_valid = (res == 0);
|
|
||||||
|
|
||||||
PrintAndLogEx(INFO, "\n--- Tag Signature");
|
PrintAndLogEx(INFO, "\n--- Tag Signature");
|
||||||
PrintAndLogEx(INFO, "IC signature public key name : NXP NTAG21x (2013)");
|
PrintAndLogEx(INFO, "IC signature public key name : %s", publickeyname);
|
||||||
PrintAndLogEx(INFO, "IC signature public key value : %s", sprint_hex(public_keys[public_key], PUBLIC_ECDA_KEYLEN));
|
PrintAndLogEx(INFO, "IC signature public key value : %s", sprint_hex(nxp_mfu_public_keys[i], PUBLIC_ECDA_KEYLEN));
|
||||||
PrintAndLogEx(INFO, " Elliptic curve parameters : NID_secp128r1");
|
PrintAndLogEx(INFO, " Elliptic curve parameters : NID_secp128r1");
|
||||||
PrintAndLogEx(INFO, " TAG IC Signature : %s", sprint_hex(signature, signature_len));
|
PrintAndLogEx(INFO, " TAG IC Signature : %s", sprint_hex(signature, signature_len));
|
||||||
PrintAndLogEx(SUCCESS, "Signature verified %s", (is_valid) ? _GREEN_("successful") : _RED_("failed"));
|
PrintAndLogEx(SUCCESS, "Signature verified " _GREEN_("successful"));
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2633,6 +2708,100 @@ static int CmdHF14AMfuOtpTearoff(const char *Cmd) {
|
|||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int CmdHF14MfuNDEF(const char *Cmd) {
|
||||||
|
|
||||||
|
int keylen;
|
||||||
|
int maxsize = 16, status;
|
||||||
|
bool hasAuthKey = false;
|
||||||
|
bool swapEndian = false;
|
||||||
|
|
||||||
|
iso14a_card_select_t card;
|
||||||
|
uint8_t data[16] = {0x00};
|
||||||
|
uint8_t key[16] = {0x00};
|
||||||
|
uint8_t *p_key = key;
|
||||||
|
uint8_t pack[4] = {0, 0, 0, 0};
|
||||||
|
|
||||||
|
CLIParserInit("hf mfu ndef",
|
||||||
|
"Prints NFC Data Exchange Format (NDEF)",
|
||||||
|
"Usage:\n\thf mfu ndef -> shows NDEF data\n"
|
||||||
|
"\thf mfu ndef -k ffffffff -> shows NDEF data with key\n");
|
||||||
|
|
||||||
|
void *argtable[] = {
|
||||||
|
arg_param_begin,
|
||||||
|
arg_str0("kK", "key", "replace default key for NDEF", NULL),
|
||||||
|
arg_lit0("lL", "key", "(optional) swap entered key's endianness"),
|
||||||
|
arg_param_end
|
||||||
|
};
|
||||||
|
CLIExecWithReturn(Cmd, argtable, true);
|
||||||
|
|
||||||
|
CLIGetHexWithReturn(1, key, &keylen);
|
||||||
|
swapEndian = arg_get_lit(2);
|
||||||
|
CLIParserFree();
|
||||||
|
|
||||||
|
switch(keylen) {
|
||||||
|
case 0:
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
case 16:
|
||||||
|
hasAuthKey = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
PrintAndLogEx(WARNING, "ERROR: Key is incorrect length\n");
|
||||||
|
return PM3_EINVARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get tag type
|
||||||
|
TagTypeUL_t tagtype = GetHF14AMfU_Type();
|
||||||
|
if (tagtype == UL_ERROR) return PM3_ESOFT;
|
||||||
|
|
||||||
|
// Is tag UL/NTAG?
|
||||||
|
|
||||||
|
// Swap endianness
|
||||||
|
if (swapEndian && hasAuthKey) p_key = SwapEndian64(key, keylen, (keylen == 16) ? 8 : 4);
|
||||||
|
|
||||||
|
// Select and Auth
|
||||||
|
if (ul_auth_select(&card, tagtype, hasAuthKey, p_key, pack, sizeof(pack)) == PM3_ESOFT) return PM3_ESOFT;
|
||||||
|
|
||||||
|
// read pages 0,1,2,3 (should read 4pages)
|
||||||
|
status = ul_read(0, data, sizeof(data));
|
||||||
|
if (status == -1) {
|
||||||
|
DropField();
|
||||||
|
PrintAndLogEx(ERR, "Error: tag didn't answer to READ");
|
||||||
|
return PM3_ESOFT;
|
||||||
|
} else if (status == 16) {
|
||||||
|
|
||||||
|
status = ndef_print_CC(data + 12);
|
||||||
|
if (status == PM3_ESOFT) {
|
||||||
|
DropField();
|
||||||
|
PrintAndLogEx(ERR, "Error: tag didn't contain a NDEF Container");
|
||||||
|
return PM3_ESOFT;
|
||||||
|
}
|
||||||
|
|
||||||
|
// max datasize;
|
||||||
|
maxsize = ndef_get_maxsize(data + 12);
|
||||||
|
}
|
||||||
|
|
||||||
|
// allocate mem
|
||||||
|
uint8_t *records = calloc(maxsize, sizeof(uint8_t));
|
||||||
|
if (records == NULL) {
|
||||||
|
DropField();
|
||||||
|
return PM3_EMALLOC;
|
||||||
|
}
|
||||||
|
|
||||||
|
// read NDEF records.
|
||||||
|
for(uint16_t i = 0, j = 0; i < maxsize; i += 16, j += 4) {
|
||||||
|
status = ul_read(4 + j, records + i, 16);
|
||||||
|
if (status == -1) {
|
||||||
|
DropField();
|
||||||
|
PrintAndLogEx(ERR, "Error: tag didn't answer to READ");
|
||||||
|
return PM3_ESOFT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DropField();
|
||||||
|
status = NDEFDecodeAndPrint(records, (size_t)maxsize, true);
|
||||||
|
free(records);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
//------------------------------------
|
//------------------------------------
|
||||||
// Menu Stuff
|
// Menu Stuff
|
||||||
//------------------------------------
|
//------------------------------------
|
||||||
@@ -2651,6 +2820,7 @@ static command_t CommandTable[] = {
|
|||||||
{"gen", CmdHF14AMfUGenDiverseKeys, AlwaysAvailable, "Generate 3des mifare diversified keys"},
|
{"gen", CmdHF14AMfUGenDiverseKeys, AlwaysAvailable, "Generate 3des mifare diversified keys"},
|
||||||
{"pwdgen", CmdHF14AMfUPwdGen, AlwaysAvailable, "Generate pwd from known algos"},
|
{"pwdgen", CmdHF14AMfUPwdGen, AlwaysAvailable, "Generate pwd from known algos"},
|
||||||
{"otptear", CmdHF14AMfuOtpTearoff, IfPm3Iso14443a, "Tear-off test on OTP bits"},
|
{"otptear", CmdHF14AMfuOtpTearoff, IfPm3Iso14443a, "Tear-off test on OTP bits"},
|
||||||
|
{"ndef", CmdHF14MfuNDEF, IfPm3Iso14443a, "Prints NDEF records from card"},
|
||||||
{NULL, NULL, NULL, NULL}
|
{NULL, NULL, NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -308,15 +308,15 @@ static int ndefDecodePayload(NDEFHeader_t *ndef) {
|
|||||||
switch (ndef->TypeNameFormat) {
|
switch (ndef->TypeNameFormat) {
|
||||||
case tnfWellKnownRecord:
|
case tnfWellKnownRecord:
|
||||||
PrintAndLogEx(INFO, "Well Known Record");
|
PrintAndLogEx(INFO, "Well Known Record");
|
||||||
PrintAndLogEx(NORMAL, "\ttype: %.*s", (int)ndef->TypeLen, ndef->Type);
|
PrintAndLogEx(INFO, "\ttype : %.*s", (int)ndef->TypeLen, ndef->Type);
|
||||||
|
|
||||||
if (!strncmp((char *)ndef->Type, "T", ndef->TypeLen)) {
|
if (!strncmp((char *)ndef->Type, "T", ndef->TypeLen)) {
|
||||||
PrintAndLogEx(NORMAL, "\ttext : %.*s", (int)ndef->PayloadLen, ndef->Payload);
|
PrintAndLogEx(INFO, "\ttext : " _GREEN_("%.*s"), (int)ndef->PayloadLen, ndef->Payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strncmp((char *)ndef->Type, "U", ndef->TypeLen)) {
|
if (!strncmp((char *)ndef->Type, "U", ndef->TypeLen)) {
|
||||||
PrintAndLogEx(NORMAL
|
PrintAndLogEx(INFO
|
||||||
, "\turi : %s%.*s"
|
, "\turi : " _GREEN_("%s%.*s")
|
||||||
, (ndef->Payload[0] <= 0x23 ? URI_s[ndef->Payload[0]] : "[err]")
|
, (ndef->Payload[0] <= 0x23 ? URI_s[ndef->Payload[0]] : "[err]")
|
||||||
, (int)(ndef->PayloadLen - 1)
|
, (int)(ndef->PayloadLen - 1)
|
||||||
, &ndef->Payload[1]
|
, &ndef->Payload[1]
|
||||||
@@ -330,14 +330,28 @@ static int ndefDecodePayload(NDEFHeader_t *ndef) {
|
|||||||
break;
|
break;
|
||||||
case tnfAbsoluteURIRecord:
|
case tnfAbsoluteURIRecord:
|
||||||
PrintAndLogEx(INFO, "Absolute URI Record");
|
PrintAndLogEx(INFO, "Absolute URI Record");
|
||||||
PrintAndLogEx(NORMAL, "\ttype: %.*s", (int)ndef->TypeLen, ndef->Type);
|
PrintAndLogEx(INFO, "\ttype : %.*s", (int)ndef->TypeLen, ndef->Type);
|
||||||
PrintAndLogEx(NORMAL, "\tpayload: %.*s", (int)ndef->PayloadLen, ndef->Payload);
|
PrintAndLogEx(INFO, "\tpayload : %.*s", (int)ndef->PayloadLen, ndef->Payload);
|
||||||
break;
|
break;
|
||||||
case tnfEmptyRecord:
|
case tnfEmptyRecord:
|
||||||
|
PrintAndLogEx(INFO, "Empty Record");
|
||||||
|
PrintAndLogEx(INFO, "\t -to be impl-");
|
||||||
|
break;
|
||||||
case tnfMIMEMediaRecord:
|
case tnfMIMEMediaRecord:
|
||||||
|
PrintAndLogEx(INFO, "MIME Media Record");
|
||||||
|
PrintAndLogEx(INFO, "\t -to be impl-");
|
||||||
|
break;
|
||||||
case tnfExternalRecord:
|
case tnfExternalRecord:
|
||||||
|
PrintAndLogEx(INFO, "External Record");
|
||||||
|
PrintAndLogEx(INFO, "\t -to be impl-");
|
||||||
|
break;
|
||||||
case tnfUnchangedRecord:
|
case tnfUnchangedRecord:
|
||||||
|
PrintAndLogEx(INFO, "Unchanged Record");
|
||||||
|
PrintAndLogEx(INFO, "\t -to be impl-");
|
||||||
|
break;
|
||||||
case tnfUnknownRecord:
|
case tnfUnknownRecord:
|
||||||
|
PrintAndLogEx(INFO, "Unknown Record");
|
||||||
|
PrintAndLogEx(INFO, "\t -to be impl-");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
@@ -372,8 +386,11 @@ static int ndefRecordDecodeAndPrint(uint8_t *ndefRecord, size_t ndefRecordLen) {
|
|||||||
int NDEFRecordsDecodeAndPrint(uint8_t *ndefRecord, size_t ndefRecordLen) {
|
int NDEFRecordsDecodeAndPrint(uint8_t *ndefRecord, size_t ndefRecordLen) {
|
||||||
bool firstRec = true;
|
bool firstRec = true;
|
||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
|
size_t counter = 0;
|
||||||
|
|
||||||
while (len < ndefRecordLen) {
|
while (len < ndefRecordLen) {
|
||||||
|
counter++;
|
||||||
|
|
||||||
NDEFHeader_t NDEFHeader = {0};
|
NDEFHeader_t NDEFHeader = {0};
|
||||||
int res = ndefDecodeHeader(&ndefRecord[len], ndefRecordLen - len, &NDEFHeader);
|
int res = ndefDecodeHeader(&ndefRecord[len], ndefRecordLen - len, &NDEFHeader);
|
||||||
if (res != PM3_SUCCESS)
|
if (res != PM3_SUCCESS)
|
||||||
@@ -381,7 +398,7 @@ int NDEFRecordsDecodeAndPrint(uint8_t *ndefRecord, size_t ndefRecordLen) {
|
|||||||
|
|
||||||
if (firstRec) {
|
if (firstRec) {
|
||||||
if (!NDEFHeader.MessageBegin) {
|
if (!NDEFHeader.MessageBegin) {
|
||||||
PrintAndLogEx(ERR, "NDEF first record have MessageBegin=false!");
|
PrintAndLogEx(ERR, "NDEF first record have MessageBegin = false!");
|
||||||
return PM3_ESOFT;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
firstRec = false;
|
firstRec = false;
|
||||||
@@ -392,6 +409,9 @@ int NDEFRecordsDecodeAndPrint(uint8_t *ndefRecord, size_t ndefRecordLen) {
|
|||||||
return PM3_ESOFT;
|
return PM3_ESOFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
PrintAndLogEx(SUCCESS, "Record " _YELLOW_("%zu"), counter);
|
||||||
|
PrintAndLogEx(INFO, "-----------------------------------------------------");
|
||||||
ndefRecordDecodeAndPrint(&ndefRecord[len], NDEFHeader.RecLen);
|
ndefRecordDecodeAndPrint(&ndefRecord[len], NDEFHeader.RecLen);
|
||||||
|
|
||||||
len += NDEFHeader.RecLen;
|
len += NDEFHeader.RecLen;
|
||||||
@@ -407,22 +427,26 @@ int NDEFDecodeAndPrint(uint8_t *ndef, size_t ndefLen, bool verbose) {
|
|||||||
|
|
||||||
size_t indx = 0;
|
size_t indx = 0;
|
||||||
|
|
||||||
PrintAndLogEx(INFO, "NDEF decoding:");
|
PrintAndLogEx(INFO, "");
|
||||||
|
PrintAndLogEx(INFO, "NDEF parsing");
|
||||||
while (indx < ndefLen) {
|
while (indx < ndefLen) {
|
||||||
|
|
||||||
|
PrintAndLogEx(INFO, "-----------------------------------------------------");
|
||||||
switch (ndef[indx]) {
|
switch (ndef[indx]) {
|
||||||
case 0x00: {
|
case 0x00: {
|
||||||
indx++;
|
indx++;
|
||||||
uint16_t len = ndefTLVGetLength(&ndef[indx], &indx);
|
uint16_t len = ndefTLVGetLength(&ndef[indx], &indx);
|
||||||
PrintAndLogEx(INFO, "-- NDEF NULL block.");
|
|
||||||
|
PrintAndLogEx(SUCCESS, "-- NDEF NULL block.");
|
||||||
if (len)
|
if (len)
|
||||||
PrintAndLogEx(WARNING, "NDEF NULL block size must be 0 instead of %d.", len);
|
PrintAndLogEx(WARNING, "NDEF NULL block size must be 0, got %d bytes", len);
|
||||||
indx += len;
|
indx += len;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 0x03: {
|
case 0x03: {
|
||||||
indx++;
|
indx++;
|
||||||
uint16_t len = ndefTLVGetLength(&ndef[indx], &indx);
|
uint16_t len = ndefTLVGetLength(&ndef[indx], &indx);
|
||||||
PrintAndLogEx(INFO, "-- NDEF message. len: %d", len);
|
PrintAndLogEx(SUCCESS, "Found NDEF message (%d bytes)", len);
|
||||||
|
|
||||||
int res = NDEFRecordsDecodeAndPrint(&ndef[indx], len);
|
int res = NDEFRecordsDecodeAndPrint(&ndef[indx], len);
|
||||||
if (res != PM3_SUCCESS)
|
if (res != PM3_SUCCESS)
|
||||||
@@ -434,12 +458,12 @@ int NDEFDecodeAndPrint(uint8_t *ndef, size_t ndefLen, bool verbose) {
|
|||||||
case 0xfd: {
|
case 0xfd: {
|
||||||
indx++;
|
indx++;
|
||||||
uint16_t len = ndefTLVGetLength(&ndef[indx], &indx);
|
uint16_t len = ndefTLVGetLength(&ndef[indx], &indx);
|
||||||
PrintAndLogEx(INFO, "-- NDEF proprietary info. Skipped %d bytes.", len);
|
PrintAndLogEx(SUCCESS, "-- NDEF proprietary info. Skipped %d bytes.", len);
|
||||||
indx += len;
|
indx += len;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 0xfe: {
|
case 0xfe: {
|
||||||
PrintAndLogEx(INFO, "-- NDEF Terminator. Done.");
|
PrintAndLogEx(SUCCESS, "-- NDEF Terminator. Done.");
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
|
|||||||
Reference in New Issue
Block a user