mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2024-09-20 07:16:14 +08:00
ndef parser - now handles more ndef types
This commit is contained in:
parent
3380ffb2e1
commit
57f9a00906
11
CHANGELOG.md
11
CHANGELOG.md
|
@ -3,11 +3,12 @@ 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]
|
||||
- FIXED 'hf desfire' changekey, GetUID, 3DES sesson key tweak. (@mwalker33)
|
||||
- Fixed `hf fido` commands now works correctly (@merlokk)
|
||||
- Changed `hf nfc ndefread` - ndef parser now handles more types (@iceman1001)
|
||||
- Fix `hf desfire` changekey, GetUID, 3DES sesson key tweak. (@mwalker33)
|
||||
- Fix `hf fido` commands now works correctly (@merlokk)
|
||||
- Moved / renamed `client/resource/fido2_defparams.json` -> `client/resource/hf_fido2_defparams.json` (@merlokk)
|
||||
- Added `hf cipurse` commands to work with cipurse transport cards (@merlokk)
|
||||
- Added '--gap' option to lf em 410x sim for more control over sim data (@mwalker)
|
||||
- Added `--gap` option to lf em 410x sim for more control over sim data (@mwalker)
|
||||
- Changed `hf fido` - refactored load/save json objects (@iceman1001)
|
||||
- Moved / renamed `fido2.json` -> `client/resource/fido2_defparams.json` (@iceman1001)
|
||||
- Added openocd shikra support based on @ninjastyle82 patch to deprecated iceman fork (@iceman1001)
|
||||
|
@ -17,8 +18,8 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
|
|||
- Added `data asn1` - a command to decode ASN1 byte arrays (@iceman1001)
|
||||
- Added `hf 15 disableprivacy` - from @g3gg0 fork *WIP* (@iceman1001)
|
||||
- Added `lf_ident_json.lua` - script to identify t55xx json dump files (@iceman1001)
|
||||
- Fixed `hf iclass chk` - multithread concurrency issues solved (@iceman1001)
|
||||
- Fixed hf_iceclass standalone - correct null terminator filename (@metalauricle)
|
||||
- Fix `hf iclass chk` - multithread concurrency issues solved (@iceman1001)
|
||||
- Fix hf_iceclass standalone - correct null terminator filename (@metalauricle)
|
||||
- Changed `trace list -t mfdes - added annotations for EV2, EV3 (@iceman1001)`
|
||||
- Changed `hf iclass lookup` - fixed swapped args (@iceman1001)
|
||||
- Changed `hf iclass decrypt` - added the possibility to decode the data as block6 if you have a cardhelper (@iceman1001)
|
||||
|
|
|
@ -15,9 +15,16 @@
|
|||
#include "ui.h"
|
||||
#include "util.h" // sprint_hex...
|
||||
#include "crypto/asn1utils.h"
|
||||
#include "crypto/libpcrypto.h"
|
||||
#include "ecp.h"
|
||||
#include "commonutil.h" // ARRAYLEN
|
||||
#include "pm3_cmd.h"
|
||||
|
||||
#define STRBOOL(p) ((p) ? "+" : "-")
|
||||
#define STRBOOL(p) ((p) ? "1" : "0")
|
||||
|
||||
#define NDEF_WIFIAPPL "application/vnd.wfa"
|
||||
#define NDEF_BLUEAPPL "application/vnd.bluetooth"
|
||||
#define NDEF_VCARDTEXT "text/vcard"
|
||||
|
||||
static const char *TypeNameFormat_s[] = {
|
||||
"Empty Record",
|
||||
|
@ -91,6 +98,9 @@ static const char *URI_s[] = {
|
|||
"urn:nfc:" // 0x23
|
||||
};
|
||||
|
||||
static int ndefRecordDecodeAndPrint(uint8_t *ndefRecord, size_t ndefRecordLen);
|
||||
static int ndefDecodePayload(NDEFHeader_t *ndef);
|
||||
|
||||
static uint16_t ndefTLVGetLength(uint8_t *data, size_t *indx) {
|
||||
uint16_t len = 0;
|
||||
if (data[0] == 0xff) {
|
||||
|
@ -142,20 +152,123 @@ static int ndefDecodeHeader(uint8_t *data, size_t datalen, NDEFHeader_t *header)
|
|||
}
|
||||
|
||||
static int ndefPrintHeader(NDEFHeader_t *header) {
|
||||
PrintAndLogEx(INFO, "Header:");
|
||||
PrintAndLogEx(INFO, _CYAN_("Header info"));
|
||||
|
||||
PrintAndLogEx(SUCCESS, "\tMessage Begin: %s", STRBOOL(header->MessageBegin));
|
||||
PrintAndLogEx(SUCCESS, "\tMessage End: %s", STRBOOL(header->MessageEnd));
|
||||
PrintAndLogEx(SUCCESS, "\tChunk Flag: %s", STRBOOL(header->ChunkFlag));
|
||||
PrintAndLogEx(SUCCESS, "\tShort Record Bit: %s", STRBOOL(header->ShortRecordBit));
|
||||
PrintAndLogEx(SUCCESS, "\tID Len Present: %s", STRBOOL(header->IDLenPresent));
|
||||
PrintAndLogEx(SUCCESS, "\tType Name Format: [0x%02x] %s", header->TypeNameFormat, TypeNameFormat_s[header->TypeNameFormat]);
|
||||
PrintAndLogEx(SUCCESS, " %s ....... Message begin", STRBOOL(header->MessageBegin));
|
||||
PrintAndLogEx(SUCCESS, " %s ...... Message end", STRBOOL(header->MessageEnd));
|
||||
PrintAndLogEx(SUCCESS, " %s ..... Chunk flag", STRBOOL(header->ChunkFlag));
|
||||
PrintAndLogEx(SUCCESS, " %s .... Short record bit", STRBOOL(header->ShortRecordBit));
|
||||
PrintAndLogEx(SUCCESS, " %s ... ID Len present", STRBOOL(header->IDLenPresent));
|
||||
PrintAndLogEx(SUCCESS, "");
|
||||
|
||||
PrintAndLogEx(SUCCESS, "\tHeader length : %zu", header->len);
|
||||
PrintAndLogEx(SUCCESS, "\tType length : %zu", header->TypeLen);
|
||||
PrintAndLogEx(SUCCESS, "\tPayload length : %zu", header->PayloadLen);
|
||||
PrintAndLogEx(SUCCESS, "\tID length : %zu", header->IDLen);
|
||||
PrintAndLogEx(SUCCESS, "\tRecord length : %zu", header->RecLen);
|
||||
PrintAndLogEx(SUCCESS, " Header length...... %zu", header->len);
|
||||
PrintAndLogEx(SUCCESS, " Type length........ %zu", header->TypeLen);
|
||||
PrintAndLogEx(SUCCESS, " Payload length..... %zu", header->PayloadLen);
|
||||
PrintAndLogEx(SUCCESS, " ID length.......... %zu", header->IDLen);
|
||||
PrintAndLogEx(SUCCESS, " Record length...... %zu", header->RecLen);
|
||||
|
||||
PrintAndLogEx(SUCCESS, " Type name format... [ 0x%02x ] " _YELLOW_("%s"), header->TypeNameFormat, TypeNameFormat_s[header->TypeNameFormat]);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static const char *get_curve_name(mbedtls_ecp_group_id grp_id) {
|
||||
switch (grp_id) {
|
||||
case MBEDTLS_ECP_DP_NONE:
|
||||
return "";
|
||||
case MBEDTLS_ECP_DP_SECP192R1:
|
||||
return "SECP192R1"; // Domain parameters for the 192-bit curve defined by FIPS 186-4 and SEC1
|
||||
case MBEDTLS_ECP_DP_SECP224R1:
|
||||
return "SECP224R1"; // Domain parameters for the 224-bit curve defined by FIPS 186-4 and SEC1
|
||||
case MBEDTLS_ECP_DP_SECP256R1:
|
||||
return "SECP256R1"; // Domain parameters for the 256-bit curve defined by FIPS 186-4 and SEC1
|
||||
case MBEDTLS_ECP_DP_SECP384R1:
|
||||
return "SECP384R1"; // Domain parameters for the 384-bit curve defined by FIPS 186-4 and SEC1
|
||||
case MBEDTLS_ECP_DP_SECP521R1:
|
||||
return "SECP521R1"; // Domain parameters for the 521-bit curve defined by FIPS 186-4 and SEC1
|
||||
case MBEDTLS_ECP_DP_BP256R1:
|
||||
return "BP256R1"; // Domain parameters for 256-bit Brainpool curve
|
||||
case MBEDTLS_ECP_DP_BP384R1:
|
||||
return "BP384R1"; // Domain parameters for 384-bit Brainpool curve
|
||||
case MBEDTLS_ECP_DP_BP512R1:
|
||||
return "BP512R1"; // Domain parameters for 512-bit Brainpool curve
|
||||
case MBEDTLS_ECP_DP_CURVE25519:
|
||||
return "CURVE25519"; // Domain parameters for Curve25519
|
||||
case MBEDTLS_ECP_DP_SECP192K1:
|
||||
return "SECP192K1"; // Domain parameters for 192-bit "Koblitz" curve
|
||||
case MBEDTLS_ECP_DP_SECP224K1:
|
||||
return "SECP224K1"; // Domain parameters for 224-bit "Koblitz" curve
|
||||
case MBEDTLS_ECP_DP_SECP256K1:
|
||||
return "SECP256K1"; // Domain parameters for 256-bit "Koblitz" curve
|
||||
case MBEDTLS_ECP_DP_CURVE448:
|
||||
return "CURVE448"; // Domain parameters for Curve448
|
||||
case MBEDTLS_ECP_DP_SECP128R1:
|
||||
return "SECP128R1"; // Domain parameters for the 128-bit curve used for NXP originality check
|
||||
default :
|
||||
return "";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
mbedtls_ecp_group_id grp_id;
|
||||
uint8_t keylen;
|
||||
const char *desc;
|
||||
const char *value;
|
||||
} PACKED ndef_publickey_t;
|
||||
|
||||
static int ndef_print_signature(uint8_t *data, uint8_t data_len, uint8_t *signature, uint8_t sign_len) {
|
||||
|
||||
const ndef_publickey_t ndef_public_keys[] = {
|
||||
{ MBEDTLS_ECP_DP_SECP256R1, 65, "Minecraft Earth", "04760200b60315f31ff7951d0892b87930c34967dfbf57763afc775fc56a22b601f7b8fd9e47519524505322435b07d0782463f39400a39a9dbc06bab2225c082a"},
|
||||
};
|
||||
|
||||
uint8_t i;
|
||||
int reason = 0;
|
||||
bool is_valid = false;
|
||||
for (i = 0; i < ARRAYLEN(ndef_public_keys); i++) {
|
||||
|
||||
int dl = 0;
|
||||
uint8_t key[ndef_public_keys[i].keylen];
|
||||
param_gethex_to_eol(ndef_public_keys[i].value, 0, key, ndef_public_keys[i].keylen, &dl);
|
||||
|
||||
int res = ecdsa_signature_r_s_verify(ndef_public_keys[i].grp_id, key, data, data_len, signature, sign_len, false);
|
||||
is_valid = (res == 0);
|
||||
if (is_valid) {
|
||||
reason = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
// try with sha256
|
||||
res = ecdsa_signature_r_s_verify(ndef_public_keys[i].grp_id, key, data, data_len, signature, sign_len, true);
|
||||
is_valid = (res == 0);
|
||||
if (is_valid) {
|
||||
reason = 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(INFO, "--- " _CYAN_("NDEF Signature"));
|
||||
if (is_valid == false || i == ARRAYLEN(ndef_public_keys)) {
|
||||
PrintAndLogEx(INFO, " Elliptic curve parameters: %s", get_curve_name(ndef_public_keys[i].grp_id));
|
||||
PrintAndLogEx(INFO, " NDEF Signature: %s", sprint_hex_inrow(signature, 32));
|
||||
PrintAndLogEx(SUCCESS, " Signature verification: " _RED_("failed"));
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
PrintAndLogEx(INFO, " IC signature public key name: %s", ndef_public_keys[i].desc);
|
||||
PrintAndLogEx(INFO, "IC signature public key value: %s", ndef_public_keys[i].value);
|
||||
PrintAndLogEx(INFO, " Elliptic curve parameters: %s", get_curve_name(ndef_public_keys[i].grp_id));
|
||||
PrintAndLogEx(INFO, " NDEF Signature: %s", sprint_hex_inrow(signature, 32));
|
||||
PrintAndLogEx(SUCCESS, " Signature verification: " _GREEN_("successful"));
|
||||
switch (reason) {
|
||||
case 1:
|
||||
PrintAndLogEx(INFO, " Params used: signature, plain");
|
||||
break;
|
||||
case 2:
|
||||
PrintAndLogEx(INFO, " Params used: signature, SHA256");
|
||||
break;
|
||||
}
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -251,6 +364,8 @@ static int ndefDecodeSig2(uint8_t *sig, size_t siglen) {
|
|||
PrintAndLogEx(SUCCESS, "\tsignature : " _GREEN_("ECDSA-%d"), slen * 8);
|
||||
PrintAndLogEx(SUCCESS, "\t\tr: %s", sprint_hex(&sig[indx], slen));
|
||||
PrintAndLogEx(SUCCESS, "\t\ts: %s", sprint_hex(&sig[indx + slen], slen));
|
||||
|
||||
ndef_print_signature(NULL, 0, NULL, 0);
|
||||
}
|
||||
} else {
|
||||
PrintAndLogEx(INFO, "\tsignature: unknown type");
|
||||
|
@ -301,18 +416,169 @@ static int ndefDecodeSig(uint8_t *sig, size_t siglen) {
|
|||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
static int ndefDecodePayloadDeviceInfo(uint8_t *payload, size_t len) {
|
||||
if (payload == NULL)
|
||||
return PM3_EINVARG;
|
||||
if (len < 1)
|
||||
return PM3_EINVARG;
|
||||
|
||||
PrintAndLogEx(INFO, _CYAN_("Device information"));
|
||||
uint8_t *p = payload;
|
||||
p++;
|
||||
uint8_t n = *(p++);
|
||||
PrintAndLogEx(INFO, "Vendor........ " _YELLOW_("%.*s"), n, p);
|
||||
p += n + 1;
|
||||
n = *(p++);
|
||||
PrintAndLogEx(INFO, "Model......... " _YELLOW_("%.*s"), n, p);
|
||||
p += n + 1;
|
||||
n = *(p++);
|
||||
PrintAndLogEx(INFO, "Unique name... " _YELLOW_("%.*s"), n, p);
|
||||
p += n + 1;
|
||||
n = *(p++);
|
||||
//uuid string
|
||||
// record.uuid_string = '123e4567-e89b-12d3-a456-426655440000'
|
||||
// 8-4-4-4-12
|
||||
char uuid[37] = {0};
|
||||
sprintf(uuid, "%s-", sprint_hex_inrow(p, 4));
|
||||
p += 4;
|
||||
sprintf(uuid + strlen(uuid), "%s-", sprint_hex_inrow(p, 2));
|
||||
p += 2;
|
||||
sprintf(uuid + strlen(uuid), "%s-", sprint_hex_inrow(p, 2));
|
||||
p += 2;
|
||||
sprintf(uuid + strlen(uuid), "%s-", sprint_hex_inrow(p, 2));
|
||||
p += 2;
|
||||
sprintf(uuid + strlen(uuid), "%s", sprint_hex_inrow(p, 6));
|
||||
p += 6;
|
||||
PrintAndLogEx(INFO, "UUID.......... " _YELLOW_("%s"), uuid);
|
||||
p++;
|
||||
n = *(p++);
|
||||
PrintAndLogEx(INFO, "Version....... " _YELLOW_("%.*s"), n, p);
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int ndefDecodePayloadSmartPoster(uint8_t *ndef, size_t ndeflen, bool print, bool verbose) {
|
||||
if (print) {
|
||||
PrintAndLogEx(INFO, _YELLOW_("Well Known Record - Smartposter {"));
|
||||
}
|
||||
|
||||
NDEFHeader_t NDEFHeader = {0};
|
||||
int res = ndefDecodeHeader(ndef, ndeflen, &NDEFHeader);
|
||||
if (res != PM3_SUCCESS) {
|
||||
PrintAndLogEx(FAILED, "decode header failed..");
|
||||
return res;
|
||||
}
|
||||
|
||||
if (verbose) {
|
||||
ndefPrintHeader(&NDEFHeader);
|
||||
}
|
||||
|
||||
if (NDEFHeader.TypeLen && NDEFHeader.PayloadLen) {
|
||||
ndefDecodePayload(&NDEFHeader);
|
||||
}
|
||||
|
||||
if (NDEFHeader.TypeLen) {
|
||||
PrintAndLogEx(INFO, "Type data");
|
||||
print_buffer(NDEFHeader.Type, NDEFHeader.TypeLen, 1);
|
||||
}
|
||||
if (NDEFHeader.IDLen) {
|
||||
PrintAndLogEx(INFO, "ID data");
|
||||
print_buffer(NDEFHeader.ID, NDEFHeader.IDLen, 1);
|
||||
}
|
||||
if (NDEFHeader.PayloadLen) {
|
||||
PrintAndLogEx(INFO, "Payload data");
|
||||
print_buffer(NDEFHeader.Payload, NDEFHeader.PayloadLen, 1);
|
||||
}
|
||||
// recursive
|
||||
if (NDEFHeader.MessageEnd == false) {
|
||||
ndefDecodePayloadSmartPoster(ndef + NDEFHeader.RecLen, ndeflen - NDEFHeader.RecLen, false, false);
|
||||
}
|
||||
|
||||
if (print) {
|
||||
PrintAndLogEx(INFO, _YELLOW_("}"));
|
||||
}
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int ndefDecodeMime_wifi(NDEFHeader_t *ndef) {
|
||||
PrintAndLogEx(INFO, _CYAN_("WiFi details"));
|
||||
if (ndef->PayloadLen > 1) {
|
||||
PrintAndLogEx(INFO, ">>> decorder, to be implemented <<<");
|
||||
}
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int ndefDecodeMime_vcard(NDEFHeader_t *ndef) {
|
||||
PrintAndLogEx(INFO, _CYAN_("VCARD details"));
|
||||
if (ndef->PayloadLen > 1) {
|
||||
PrintAndLogEx(INFO, "Data... " _YELLOW_("%.*s"), (int)ndef->PayloadLen, ndef->Payload);
|
||||
PrintAndLogEx(INFO, ">>> decorder, to be implemented <<<");
|
||||
}
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int ndefDecodeMime_bt(NDEFHeader_t *ndef) {
|
||||
PrintAndLogEx(INFO, "Type............ " _YELLOW_("%.*s"), (int)ndef->TypeLen, ndef->Type );
|
||||
if (ndef->PayloadLen > 1) {
|
||||
uint16_t ooblen = (ndef->Payload[1] << 8 | ndef->Payload[0]);
|
||||
PrintAndLogEx(INFO, "OOB data len.... %u", ooblen);
|
||||
PrintAndLogEx(INFO, "BT MAC.......... " _YELLOW_("%s"), sprint_hex(ndef->Payload + 2, 6));
|
||||
// Let's check payload[8]. Tells us a bit about the UUID's. If 0x07 then it tells us a service UUID is 128bit
|
||||
switch (ndef->Payload[8]) {
|
||||
case 0x02:
|
||||
PrintAndLogEx(INFO, "Optional Data... incomplete list 16-bit UUID's");
|
||||
break;
|
||||
case 0x03:
|
||||
PrintAndLogEx(INFO, "Optional Data... complete list 16-bit UUID's");
|
||||
break;
|
||||
case 0x04:
|
||||
PrintAndLogEx(INFO, "Optional Data... incomplete list 32-bit UUID's");
|
||||
break;
|
||||
case 0x05:
|
||||
PrintAndLogEx(INFO, "Optional Data... complete list 32-bit UUID's");
|
||||
break;
|
||||
case 0x06:
|
||||
PrintAndLogEx(INFO, "Optional Data... incomplete list 128-bit UUID's");
|
||||
break;
|
||||
case 0x07:
|
||||
PrintAndLogEx(INFO, "Optional Data... complete list 128-bit UUID's");
|
||||
break;
|
||||
default:
|
||||
PrintAndLogEx(INFO, "Optional Data... [ %02x ]", ndef->Payload[8]);
|
||||
break;
|
||||
}
|
||||
// Let's check payload[9]. If 0x08 then SHORT_NAME or if 0x09 then COMPLETE_NAME
|
||||
if (ndef->Payload[9] == 0x08 ) {
|
||||
PrintAndLogEx(INFO, "Short name...... " _YELLOW_("%s"), ndef->Payload + 10, ndef->PayloadLen - 10);
|
||||
} else if (ndef->Payload[9] == 0x09 ) {
|
||||
PrintAndLogEx(INFO, "Complete name... " _YELLOW_("%s"), ndef->Payload + 10, ndef->PayloadLen - 10);
|
||||
} else {
|
||||
PrintAndLogEx(INFO, "[ %02x ]", ndef->Payload[9]);
|
||||
}
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
}
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int ndefDecodePayload(NDEFHeader_t *ndef) {
|
||||
|
||||
PrintAndLogEx(INFO, "");
|
||||
switch (ndef->TypeNameFormat) {
|
||||
case tnfEmptyRecord:
|
||||
PrintAndLogEx(INFO, "Empty Record");
|
||||
if (ndef->TypeLen != 0 || ndef->IDLen != 0 || ndef->PayloadLen != 0) {
|
||||
PrintAndLogEx(FAILED, "unexpected data in TNF_EMPTY record");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case tnfWellKnownRecord:
|
||||
PrintAndLogEx(INFO, "Well Known Record");
|
||||
PrintAndLogEx(INFO, "\ttype\t: %.*s", (int)ndef->TypeLen, ndef->Type);
|
||||
|
||||
if (!strncmp((char *)ndef->Type, "T", ndef->TypeLen)) {
|
||||
PrintAndLogEx(INFO, _CYAN_("Text"));
|
||||
uint8_t utf8 = (ndef->Payload[0] >> 7);
|
||||
uint8_t lc_len = ndef->Payload[0] & 0x3F;
|
||||
PrintAndLogEx(INFO,
|
||||
"\tUTF %d\t: " _GREEN_("%.*s") ", " _GREEN_("%.*s"),
|
||||
" UTF %d... " _GREEN_("%.*s") ", " _GREEN_("%.*s"),
|
||||
(utf8 == 0) ? 8 : 16,
|
||||
lc_len,
|
||||
ndef->Payload + 1,
|
||||
|
@ -322,8 +588,9 @@ static int ndefDecodePayload(NDEFHeader_t *ndef) {
|
|||
}
|
||||
|
||||
if (!strncmp((char *)ndef->Type, "U", ndef->TypeLen)) {
|
||||
PrintAndLogEx(INFO, _CYAN_("URL"));
|
||||
PrintAndLogEx(INFO
|
||||
, "\turi\t: " _GREEN_("%s%.*s")
|
||||
, " uri... " _GREEN_("%s%.*s")
|
||||
, (ndef->Payload[0] <= 0x23 ? URI_s[ndef->Payload[0]] : "[err]")
|
||||
, (int)(ndef->PayloadLen - 1)
|
||||
, &ndef->Payload[1]
|
||||
|
@ -331,34 +598,67 @@ static int ndefDecodePayload(NDEFHeader_t *ndef) {
|
|||
}
|
||||
|
||||
if (!strncmp((char *)ndef->Type, "Sig", ndef->TypeLen)) {
|
||||
PrintAndLogEx(INFO, _CYAN_("Signature"));
|
||||
ndefDecodeSig(ndef->Payload, ndef->PayloadLen);
|
||||
}
|
||||
|
||||
if (!strncmp((char *)ndef->Type, "Sp", ndef->TypeLen)) {
|
||||
ndefDecodePayloadSmartPoster(ndef->Payload, ndef->PayloadLen, true, false);
|
||||
}
|
||||
|
||||
if (!strncmp((char *)ndef->Type, "Di", ndef->TypeLen)) {
|
||||
ndefDecodePayloadDeviceInfo(ndef->Payload, ndef->PayloadLen);
|
||||
}
|
||||
|
||||
if (!strncmp((char *)ndef->Type, "Hc", ndef->TypeLen)) {
|
||||
PrintAndLogEx(INFO, _CYAN_("Handover carrier"));
|
||||
PrintAndLogEx(INFO, "- decoder to be impl -");
|
||||
}
|
||||
|
||||
if (!strncmp((char *)ndef->Type, "Hr", ndef->TypeLen)) {
|
||||
PrintAndLogEx(INFO, _CYAN_("Handover request"));
|
||||
PrintAndLogEx(INFO, "- decoder to be impl -");
|
||||
}
|
||||
|
||||
if (!strncmp((char *)ndef->Type, "Hs", ndef->TypeLen)) {
|
||||
PrintAndLogEx(INFO, _CYAN_("Handover select"));
|
||||
PrintAndLogEx(INFO, "- decoder to be impl -");
|
||||
}
|
||||
|
||||
if (!strncmp((char *)ndef->Type, "ac", ndef->TypeLen)) {
|
||||
PrintAndLogEx(INFO, _CYAN_("Alternative carrier"));
|
||||
PrintAndLogEx(INFO, "- decoder to be impl -");
|
||||
}
|
||||
break;
|
||||
case tnfMIMEMediaRecord:
|
||||
PrintAndLogEx(INFO, "MIME Media Record");
|
||||
|
||||
if (str_startswith((const char *)ndef->Type, NDEF_WIFIAPPL)) {
|
||||
ndefDecodeMime_wifi(ndef);
|
||||
}
|
||||
if (str_startswith((const char *)ndef->Type, NDEF_VCARDTEXT)) {
|
||||
ndefDecodeMime_vcard(ndef);
|
||||
}
|
||||
if (str_startswith((const char *)ndef->Type, NDEF_BLUEAPPL)) {
|
||||
ndefDecodeMime_bt(ndef);
|
||||
}
|
||||
|
||||
break;
|
||||
case tnfAbsoluteURIRecord:
|
||||
PrintAndLogEx(INFO, "Absolute URI Record");
|
||||
PrintAndLogEx(INFO, "\ttype : %.*s", (int)ndef->TypeLen, ndef->Type);
|
||||
PrintAndLogEx(INFO, "\tpayload : %.*s", (int)ndef->PayloadLen, ndef->Payload);
|
||||
break;
|
||||
case tnfEmptyRecord:
|
||||
PrintAndLogEx(INFO, "Empty Record");
|
||||
PrintAndLogEx(INFO, "\t -to be impl-");
|
||||
break;
|
||||
case tnfMIMEMediaRecord:
|
||||
PrintAndLogEx(INFO, "MIME Media Record");
|
||||
PrintAndLogEx(INFO, "\t -to be impl-");
|
||||
PrintAndLogEx(INFO, " payload : %.*s", (int)ndef->PayloadLen, ndef->Payload);
|
||||
break;
|
||||
case tnfExternalRecord:
|
||||
PrintAndLogEx(INFO, "External Record");
|
||||
PrintAndLogEx(INFO, "\t -to be impl-");
|
||||
break;
|
||||
case tnfUnchangedRecord:
|
||||
PrintAndLogEx(INFO, "Unchanged Record");
|
||||
PrintAndLogEx(INFO, "\t -to be impl-");
|
||||
PrintAndLogEx(INFO, "- decoder to be impl -");
|
||||
break;
|
||||
case tnfUnknownRecord:
|
||||
PrintAndLogEx(INFO, "Unknown Record");
|
||||
PrintAndLogEx(INFO, "\t -to be impl-");
|
||||
PrintAndLogEx(INFO, "- decoder to be impl -");
|
||||
break;
|
||||
case tnfUnchangedRecord:
|
||||
PrintAndLogEx(INFO, "Unchanged Record");
|
||||
PrintAndLogEx(INFO, "- decoder to be impl -");
|
||||
break;
|
||||
}
|
||||
return PM3_SUCCESS;
|
||||
|
@ -371,19 +671,22 @@ static int ndefRecordDecodeAndPrint(uint8_t *ndefRecord, size_t ndefRecordLen) {
|
|||
return res;
|
||||
|
||||
ndefPrintHeader(&NDEFHeader);
|
||||
PrintAndLogEx(INFO, "");
|
||||
PrintAndLogEx(INFO, _CYAN_("Payload info"));
|
||||
|
||||
if (NDEFHeader.TypeLen) {
|
||||
PrintAndLogEx(INFO, "Type data:");
|
||||
PrintAndLogEx(INFO, "Type data");
|
||||
print_buffer(NDEFHeader.Type, NDEFHeader.TypeLen, 1);
|
||||
}
|
||||
if (NDEFHeader.IDLen) {
|
||||
PrintAndLogEx(INFO, "ID data:");
|
||||
PrintAndLogEx(INFO, "ID data");
|
||||
print_buffer(NDEFHeader.ID, NDEFHeader.IDLen, 1);
|
||||
}
|
||||
if (NDEFHeader.PayloadLen) {
|
||||
PrintAndLogEx(INFO, "Payload data:");
|
||||
PrintAndLogEx(INFO, "Payload data");
|
||||
print_buffer(NDEFHeader.Payload, NDEFHeader.PayloadLen, 1);
|
||||
if (NDEFHeader.TypeLen)
|
||||
}
|
||||
if (NDEFHeader.TypeLen && NDEFHeader.PayloadLen) {
|
||||
ndefDecodePayload(&NDEFHeader);
|
||||
}
|
||||
|
||||
|
@ -438,8 +741,6 @@ int NDEFDecodeAndPrint(uint8_t *ndef, size_t ndefLen, bool verbose) {
|
|||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(INFO, "--- " _CYAN_("NDEF parsing") " ----------------");
|
||||
while (indx < ndefLen) {
|
||||
|
||||
PrintAndLogEx(INFO, "-----------------------------------------------------");
|
||||
switch (ndef[indx]) {
|
||||
case 0x00: {
|
||||
indx++;
|
||||
|
@ -462,11 +763,11 @@ int NDEFDecodeAndPrint(uint8_t *ndef, size_t ndefLen, bool verbose) {
|
|||
uint8_t Size = ndef[indx + 1];
|
||||
uint8_t BytesLockedPerLockBit = (ndef[indx + 2] >> 4) & 0x0f;
|
||||
uint8_t bytes_per_page = ndef[indx + 2] & 0x0f;
|
||||
PrintAndLogEx(SUCCESS, " Pages addr (number of pages) : %d", pages_addr);
|
||||
PrintAndLogEx(SUCCESS, "Byte offset (number of bytes) : %d", byte_offset);
|
||||
PrintAndLogEx(SUCCESS, "Size in bits of the lock area : %d. bytes approx: %d", Size, Size / 8);
|
||||
PrintAndLogEx(SUCCESS, " Number of bytes / page : %d", bytes_per_page);
|
||||
PrintAndLogEx(SUCCESS, "Bytes Locked Per LockBit.");
|
||||
PrintAndLogEx(SUCCESS, " Pages addr (number of pages)... %d", pages_addr);
|
||||
PrintAndLogEx(SUCCESS, "Byte offset (number of bytes)... %d", byte_offset);
|
||||
PrintAndLogEx(SUCCESS, "Size in bits of the lock area %d. bytes approx %d", Size, Size / 8);
|
||||
PrintAndLogEx(SUCCESS, " Number of bytes / page... %d", bytes_per_page);
|
||||
PrintAndLogEx(SUCCESS, "Bytes Locked Per LockBit");
|
||||
PrintAndLogEx(SUCCESS, " number of bytes that each dynamic lock bit is able to lock: %d", BytesLockedPerLockBit);
|
||||
}
|
||||
indx += len;
|
||||
|
|
Loading…
Reference in a new issue