Merge branch 'master' into experimental_varlen

* master: (27 commits)
  textual
  style redundant assignment
  timeout fix
  small fix
  add termcap
  add readline and small fix
  rdp
  textual
  null term?
  fix: https://github.com/RfidResearchGroup/proxmark3/issues/166
  add dlls to release
  style
  style
  test fix
  test fixes
  another fix
  fix memleak
  fix
  textual
  use printandlogex
  ...
This commit is contained in:
Philippe Teuwen 2019-04-17 22:06:39 +02:00
commit 7cbcf8163c
20 changed files with 519 additions and 534 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]
- Fix/Add 'hf mf sim' bugs fix, RATS support, etc (@mceloff)
- Fix serial of FPC. (@ryan)
- Fix 'data shiftgraphzero' corrupting end of GraphBuffer (@doegox)
- Fix 'hf legic info' - unsegmented card now uses card size to calc remaining length (@iceman)

View file

@ -2,6 +2,7 @@ Proxmark3 RDV4.0 Dedicated Github
===============
This repo is based on iceman fork for proxmark3. It is dedicated to bringing the most out of the new features for proxmark3 RDV4.0 new hardware and design.
[![Build status](https://ci.appveyor.com/api/projects/status/ct5blik2wa96bv0x/branch/master?svg=true)](https://ci.appveyor.com/project/iceman1001/proxmark3-ji4wj/branch/master)
[![Latest release](https://img.shields.io/github/release/RfidResearchGroup/proxmark3.svg)](https://github.com/RfidResearchGroup/proxmark3/releases/latest)
<a href="http://www.youtube.com/watch?feature=player_embedded&v=uyJ-y0kSWfc

View file

@ -161,6 +161,24 @@ build_script:
Copy-Item C:\ProxSpace\pm3\client\hardnested\tables\*.bin.z C:\ProxSpace\Release\hardnested\tables
# dll files
Copy-Item C:\ProxSpace\msys2\mingw32\bin\libgcc_s_dw2-1.dll C:\ProxSpace\Release
Copy-Item C:\ProxSpace\msys2\mingw32\bin\libstdc++-6.dll C:\ProxSpace\Release
Copy-Item C:\ProxSpace\msys2\mingw32\bin\libwinpthread-1.dll C:\ProxSpace\Release
Copy-Item C:\ProxSpace\msys2\mingw32\bin\Qt5Core.dll C:\ProxSpace\Release
Copy-Item C:\ProxSpace\msys2\mingw32\bin\Qt5Gui.dll C:\ProxSpace\Release
Copy-Item C:\ProxSpace\msys2\mingw32\bin\Qt5Widgets.dll C:\ProxSpace\Release
Copy-Item C:\ProxSpace\msys2\mingw32\bin\libreadline*.dll C:\ProxSpace\Release
Copy-Item C:\ProxSpace\msys2\mingw32\bin\libtermcap-0.dll C:\ProxSpace\Release
Write-Host "[ OK ]" -ForegroundColor Green
@ -256,8 +274,8 @@ test_script:
#--- end Job
[bool]$res=$false
# Wait 120 sec timeout for Job
if(Wait-Job $Job -Timeout 150){
# Wait 180 sec timeout for Job
if(Wait-Job $Job -Timeout 180){
$Results = $Job | Receive-Job
if($Results -like "true"){
$res=$true

View file

@ -34,8 +34,6 @@
#include "protocols.h"
#include "apps.h"
uint8_t MifareCardType;
static bool IsTrailerAccessAllowed(uint8_t blockNo, uint8_t keytype, uint8_t action) {
uint8_t sector_trailer[16];
emlGetMem(sector_trailer, blockNo, 1);
@ -151,89 +149,104 @@ static bool IsAccessAllowed(uint8_t blockNo, uint8_t keytype, uint8_t action) {
}
}
static bool MifareSimInit(uint16_t flags, uint8_t *datain, tag_response_info_t **responses, uint32_t *cuid, uint8_t *uid_len) {
static bool MifareSimInit(uint16_t flags, uint8_t *datain, tag_response_info_t **responses, uint32_t *cuid, uint8_t *uid_len, uint8_t **rats, uint8_t *rats_len) {
// SPEC: https://www.nxp.com/docs/en/application-note/AN10833.pdf
// ATQA
static uint8_t rATQA_Mini[] = {0x04, 0x00}; // indicate Mifare classic Mini 4Byte UID
static uint8_t rATQA_1k[] = {0x04, 0x00}; // indicate Mifare classic 1k 4Byte UID
static uint8_t rATQA_2k[] = {0x04, 0x00}; // indicate Mifare classic 2k 4Byte UID
static uint8_t rATQA_4k[] = {0x02, 0x00}; // indicate Mifare classic 4k 4Byte UID
static uint8_t rATQA_Mini_4B[] = {0x44, 0x00}; // indicate Mifare classic Mini 4Byte UID
static uint8_t rATQA_Mini_7B[] = {0x44, 0x00}; // indicate Mifare classic Mini 7Byte UID
static uint8_t rATQA_Mini_10B[] = {0x44, 0x00}; // indicate Mifare classic Mini 10Byte UID
static uint8_t rATQA_1k_4B[] = {0x04, 0x00}; // indicate Mifare classic 1k 4Byte UID
static uint8_t rATQA_1k_7B[] = {0x44, 0x00}; // indicate Mifare classic 1k 7Byte UID
static uint8_t rATQA_1k_10B[] = {0x42, 0x00}; // indicate Mifare classic 4k 10Byte UID
static uint8_t rATQA_2k_4B[] = {0x04, 0x00}; // indicate Mifare classic 2k 4Byte UID
static uint8_t rATQA_2k_7B[] = {0x44, 0x00}; // indicate Mifare classic 2k 7Byte UID
static uint8_t rATQA_2k_10B[] = {0x42, 0x00}; // indicate Mifare classic 4k 10Byte UID
static uint8_t rATQA_4k_4B[] = {0x02, 0x00}; // indicate Mifare classic 4k 4Byte UID
static uint8_t rATQA_4k_7B[] = {0x42, 0x00}; // indicate Mifare classic 4k 7Byte UID
static uint8_t rATQA_4k_10B[] = {0x42, 0x00}; // indicate Mifare classic 4k 10Byte UID
static uint8_t rATQA[] = {0x00, 0x00};
// SAK + CRC
static uint8_t rSAK_mini[] = {0x09, 0x3f, 0xcc}; // mifare Mini
static uint8_t rSAK_1[] = {0x08, 0xb6, 0xdd}; // mifare 1k
static uint8_t rSAK_2[] = {0x08, 0xb6, 0xdd}; // mifare 2k
static uint8_t rSAK_4[] = {0x18, 0x37, 0xcd}; // mifare 4k
// SAK
static uint8_t rSAK_Mini = 0x09; // mifare Mini
static uint8_t rSAK_1k = 0x08; // mifare 1k
static uint8_t rSAK_2k = 0x08; // mifare 2k with RATS support
static uint8_t rSAK_4k = 0x18; // mifare 4k
static uint8_t rUIDBCC1[] = {0x00, 0x00, 0x00, 0x00, 0x00}; // UID 1st cascade level
static uint8_t rUIDBCC2[] = {0x00, 0x00, 0x00, 0x00, 0x00}; // UID 2nd cascade level
static uint8_t rUIDBCC3[] = {0x00, 0x00, 0x00, 0x00, 0x00}; // UID 3nd cascade level
static uint8_t rSAK1[] = {0x04, 0xda, 0x17}; // Acknowledge but indicate UID is not finished. Used for any MIFARE Classic CL1 with double UID size
static uint8_t rATQA[] = {0x00, 0x00}; // Current ATQA
static uint8_t rSAK[] = {0x00, 0x00, 0x00}; // Current SAK, CRC
static uint8_t rSAKuid[] = {0x04, 0xda, 0x17}; // UID incomplete cascade bit, CRC
// RATS answer for 2K NXP mifare classic (with CRC)
static uint8_t rRATS[] = {0x0c, 0x75, 0x77, 0x80, 0x02, 0xc1, 0x05, 0x2f, 0x2f, 0x01, 0xbc, 0xd6, 0x60, 0xd3};
*uid_len = 0;
// By default use 1K tag
memcpy(rATQA, rATQA_1k, sizeof(rATQA));
rSAK[0] = rSAK_1k;
//by default RATS not supported
*rats_len = 0;
*rats = NULL;
// -- Determine the UID
// Can be set from emulator memory or incoming data
// Length: 4,7,or 10 bytes
// Get UID, SAK, ATQA from EMUL
if ((flags & FLAG_UID_IN_EMUL) == FLAG_UID_IN_EMUL) {
emlGetMemBt(datain, 0, 10); // load 10bytes from EMUL to the datain pointer. to be used below.
uint8_t block0[16];
emlGetMemBt(block0, 0, 16);
// If uid size defined, copy only uid from EMUL to use, backward compatibility for 'hf_colin.c', 'hf_mattyrun.c'
if ((flags & (FLAG_4B_UID_IN_DATA | FLAG_7B_UID_IN_DATA | FLAG_10B_UID_IN_DATA)) != 0) {
memcpy(datain, block0, 10); // load 10bytes from EMUL to the datain pointer. to be used below.
} else {
// Check for 4 bytes uid: bcc corrected and single size uid bits in ATQA
if ((block0[0] ^ block0[1] ^ block0[2] ^ block0[3]) == block0[4] && (block0[6] & 0xc0) == 0) {
flags |= FLAG_4B_UID_IN_DATA;
memcpy(datain, block0, 4);
rSAK[0] = block0[5];
memcpy(rATQA, &block0[6], sizeof(rATQA));
}
// Check for 7 bytes UID: double size uid bits in ATQA
else if ((block0[8] & 0xc0) == 0x40) {
flags |= FLAG_7B_UID_IN_DATA;
memcpy(datain, block0, 7);
rSAK[0] = block0[7];
memcpy(rATQA, &block0[8], sizeof(rATQA));
} else {
Dbprintf("[-] ERROR: Invalid dump. UID/SAK/ATQA not found");
return false;
}
}
}
// Tune tag type, if defined directly
// Otherwise use defined by default or extracted from EMUL
if ((flags & FLAG_MF_MINI) == FLAG_MF_MINI) {
memcpy(rATQA, rATQA_Mini, sizeof(rATQA));
rSAK[0] = rSAK_Mini;
Dbprintf("Mifare Mini");
} else if ((flags & FLAG_MF_1K) == FLAG_MF_1K) {
memcpy(rATQA, rATQA_1k, sizeof(rATQA));
rSAK[0] = rSAK_1k;
Dbprintf("Mifare 1K");
} else if ((flags & FLAG_MF_2K) == FLAG_MF_2K) {
memcpy(rATQA, rATQA_2k, sizeof(rATQA));
rSAK[0] = rSAK_2k;
*rats = rRATS;
*rats_len = sizeof(rRATS);
Dbprintf("Mifare 2K with RATS support");
} else if ((flags & FLAG_MF_4K) == FLAG_MF_4K) {
memcpy(rATQA, rATQA_4k, sizeof(rATQA));
rSAK[0] = rSAK_4k;
Dbprintf("Mifare 4K");
}
// Prepare UID arrays
if ((flags & FLAG_4B_UID_IN_DATA) == FLAG_4B_UID_IN_DATA) { // get UID from datain
memcpy(rUIDBCC1, datain, 4);
*uid_len = 4;
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("MifareSimInit - FLAG_4B_UID_IN_DATA => Get UID from datain: %02X - Flag: %02X - UIDBCC1: %02X", FLAG_4B_UID_IN_DATA, flags, rUIDBCC1);
} else if ((flags & FLAG_7B_UID_IN_DATA) == FLAG_7B_UID_IN_DATA) {
memcpy(&rUIDBCC1[1], datain, 3);
memcpy(rUIDBCC2, datain + 3, 4);
*uid_len = 7;
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("MifareSimInit - FLAG_7B_UID_IN_DATA => Get UID from datain: %02X - Flag: %02X - UIDBCC1: %02X", FLAG_7B_UID_IN_DATA, flags, rUIDBCC1);
} else if ((flags & FLAG_10B_UID_IN_DATA) == FLAG_10B_UID_IN_DATA) {
memcpy(&rUIDBCC1[1], datain, 3);
memcpy(&rUIDBCC2[1], datain + 3, 3);
memcpy(rUIDBCC3, datain + 6, 4);
*uid_len = 10;
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("MifareSimInit - FLAG_10B_UID_IN_DATA => Get UID from datain: %02X - Flag: %02X - UIDBCC1: %02X", FLAG_10B_UID_IN_DATA, flags, rUIDBCC1);
}
switch (*uid_len) {
// UID 4B
case 4:
switch (MifareCardType) {
case 0: // Mifare Mini
memcpy(rATQA, rATQA_Mini_4B, sizeof rATQA_Mini_4B);
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("=> Using rATQA_Mini_4B");
break;
case 1: // Mifare 1K
memcpy(rATQA, rATQA_1k_4B, sizeof rATQA_1k_4B);
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("=> Using rATQA_1k_4B");
break;
case 2: // Mifare 2K
memcpy(rATQA, rATQA_2k_4B, sizeof rATQA_2k_4B);
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("=> Using rATQA_2k_4B");
break;
case 4: // Mifare 4K
memcpy(rATQA, rATQA_4k_4B, sizeof rATQA_4k_4B);
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("=> Using rATQA_4k_4B");
break;
}
// save CUID
*cuid = bytes_to_num(rUIDBCC1, 4);
@ -242,29 +255,15 @@ static bool MifareSimInit(uint16_t flags, uint8_t *datain, tag_response_info_t *
if (MF_DBGLEVEL >= MF_DBG_NONE) {
Dbprintf("4B UID: %02x%02x%02x%02x", rUIDBCC1[0], rUIDBCC1[1], rUIDBCC1[2], rUIDBCC1[3]);
}
break;
// UID 7B
case 7:
// Correct uid size bits in ATQA
rATQA[0] = (rATQA[0] & 0x3f) | 0x00; // single size uid
switch (MifareCardType) {
case 0: // Mifare Mini
memcpy(rATQA, rATQA_Mini_7B, sizeof rATQA_Mini_7B);
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("=> Using rATQA_Mini_7B");
break;
case 1: // Mifare 1K
memcpy(rATQA, rATQA_1k_7B, sizeof rATQA_1k_7B);
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("=> Using rATQA_1k_7B");
break;
case 2: // Mifare 2K
memcpy(rATQA, rATQA_2k_7B, sizeof rATQA_2k_7B);
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("=> Using rATQA_2k_7B");
break;
case 4: // Mifare 4K
memcpy(rATQA, rATQA_4k_7B, sizeof rATQA_4k_7B);
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("=> Using rATQA_4k_4B");
break;
}
} else if ((flags & FLAG_7B_UID_IN_DATA) == FLAG_7B_UID_IN_DATA) {
memcpy(&rUIDBCC1[1], datain, 3);
memcpy(rUIDBCC2, datain + 3, 4);
*uid_len = 7;
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("MifareSimInit - FLAG_7B_UID_IN_DATA => Get UID from datain: %02X - Flag: %02X - UIDBCC1: %02X", FLAG_7B_UID_IN_DATA, flags, rUIDBCC1);
// save CUID
*cuid = bytes_to_num(rUIDBCC2, 4);
@ -277,28 +276,16 @@ static bool MifareSimInit(uint16_t flags, uint8_t *datain, tag_response_info_t *
Dbprintf("7B UID: %02x %02x %02x %02x %02x %02x %02x",
rUIDBCC1[1], rUIDBCC1[2], rUIDBCC1[3], rUIDBCC2[0], rUIDBCC2[1], rUIDBCC2[2], rUIDBCC2[3]);
}
break;
// UID 10B
case 10:
switch (MifareCardType) {
case 0: // Mifare Mini
memcpy(rATQA, rATQA_Mini_10B, sizeof rATQA_Mini_10B);
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("=> Using rATQA_Mini_10B");
break;
case 1: // Mifare 1K
memcpy(rATQA, rATQA_1k_10B, sizeof rATQA_1k_10B);
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("=> Using rATQA_1k_10B");
break;
case 2: // Mifare 2K
memcpy(rATQA, rATQA_2k_10B, sizeof rATQA_2k_10B);
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("=> Using rATQA_2k_10B");
break;
case 4: // Mifare 4K
memcpy(rATQA, rATQA_4k_10B, sizeof rATQA_4k_10B);
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("=> Using rATQA_4k_10B");
break;
}
// Correct uid size bits in ATQA
rATQA[0] = (rATQA[0] & 0x3f) | 0x40; // double size uid
} else if ((flags & FLAG_10B_UID_IN_DATA) == FLAG_10B_UID_IN_DATA) {
memcpy(&rUIDBCC1[1], datain, 3);
memcpy(&rUIDBCC2[1], datain + 3, 3);
memcpy(rUIDBCC3, datain + 6, 4);
*uid_len = 10;
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("MifareSimInit - FLAG_10B_UID_IN_DATA => Get UID from datain: %02X - Flag: %02X - UIDBCC1: %02X", FLAG_10B_UID_IN_DATA, flags, rUIDBCC1);
// save CUID
*cuid = bytes_to_num(rUIDBCC3, 4);
@ -317,30 +304,33 @@ static bool MifareSimInit(uint16_t flags, uint8_t *datain, tag_response_info_t *
rUIDBCC3[0], rUIDBCC3[1], rUIDBCC3[2], rUIDBCC3[3]
);
}
break;
default:
break;
// Correct uid size bits in ATQA
rATQA[0] = (rATQA[0] & 0x3f) | 0x80; // triple size uid
} else {
Dbprintf("[-] ERROR: UID size not defined");
return false;
}
#define TAG_RESPONSE_COUNT 9
// Calculate actual CRC
AddCrc14A(rSAK, sizeof(rSAK) - 2);
#define TAG_RESPONSE_COUNT 6
static tag_response_info_t responses_init[TAG_RESPONSE_COUNT] = {
{ .response = rATQA, .response_n = sizeof(rATQA) }, // Answer to request - respond with card type
{ .response = rUIDBCC1, .response_n = sizeof(rUIDBCC1) }, // Anticollision cascade1 - respond with first part of uid
{ .response = rUIDBCC2, .response_n = sizeof(rUIDBCC2) }, // Anticollision cascade2 - respond with 2nd part of uid
{ .response = rUIDBCC3, .response_n = sizeof(rUIDBCC3) }, // Anticollision cascade3 - respond with 3th part of uid
{ .response = rSAK_mini, .response_n = sizeof(rSAK_mini) }, // SAK Mifare Mini
{ .response = rSAK_1, .response_n = sizeof(rSAK_1) }, // SAK Mifare 1K
{ .response = rSAK_2, .response_n = sizeof(rSAK_2) }, // SAK Mifare 2K
{ .response = rSAK_4, .response_n = sizeof(rSAK_4) }, // SAK Mifare 4K
{ .response = rSAK1, .response_n = sizeof(rSAK1) } // Acknowledge select - Need another cascades
{ .response = rSAK, .response_n = sizeof(rSAK) }, //
{ .response = rSAKuid, .response_n = sizeof(rSAKuid) } //
};
// Prepare ("precompile") the responses of the anticollision phase.
// There will be not enough time to do this at the moment the reader sends its REQA or SELECT
// There are 9 predefined responses with a total of 32 bytes data to transmit.
// There are 6 predefined responses with a total of 23 bytes data to transmit.
// Coded responses need one byte per bit to transfer (data, parity, start, stop, correction)
// 32 * 8 data bits, 32 * 1 parity bits, 9 start bits, 9 stop bits, 9 correction bits -> need 315 bytes buffer
#define ALLOCATED_TAG_MODULATION_BUFFER_SIZE 512
// 23 * 8 data bits, 23 * 1 parity bits, 6 start bits, 6 stop bits, 6 correction bits -> need 225 bytes buffer
#define ALLOCATED_TAG_MODULATION_BUFFER_SIZE 225
uint8_t *free_buffer = BigBuf_malloc(ALLOCATED_TAG_MODULATION_BUFFER_SIZE);
// modulation buffer pointer and current buffer free space size
@ -361,11 +351,8 @@ static bool MifareSimInit(uint16_t flags, uint8_t *datain, tag_response_info_t *
#define UIDBCC1 1
#define UIDBCC2 2
#define UIDBCC3 3
#define SAK_MINI 4
#define SAK_1 5
#define SAK_2 6
#define SAK_4 7
#define SAK1 8
#define SAK 4
#define SAKuid 5
return true;
}
@ -422,6 +409,9 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t
uint8_t response[MAX_MIFARE_FRAME_SIZE] = {0x00};
uint8_t response_par[MAX_MIFARE_PARITY_SIZE] = {0x00};
uint8_t *rats = NULL;
uint8_t rats_len = 0;
uint8_t rAUTH_AT[] = {0x00, 0x00, 0x00, 0x00};
//Here, we collect UID,sector,keytype,NT,AR,NR,NT2,AR2,NR2
@ -447,27 +437,10 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t
tUart *uart = GetUart();
if ((flags & FLAG_MF_MINI) == FLAG_MF_MINI) {
MifareCardType = 0;
Dbprintf("Mifare Mini");
}
if ((flags & FLAG_MF_1K) == FLAG_MF_1K) {
MifareCardType = 1;
Dbprintf("Mifare 1K");
}
if ((flags & FLAG_MF_2K) == FLAG_MF_2K) {
MifareCardType = 2;
Dbprintf("Mifare 2K");
}
if ((flags & FLAG_MF_4K) == FLAG_MF_4K) {
MifareCardType = 4;
Dbprintf("Mifare 4K");
}
// free eventually allocated BigBuf memory but keep Emulator Memory
BigBuf_free_keep_EM();
if (MifareSimInit(flags, datain, &responses, &cuid, &uid_len) == false) {
if (MifareSimInit(flags, datain, &responses, &cuid, &uid_len, &rats, &rats_len) == false) {
BigBuf_free_keep_EM();
return;
}
@ -579,34 +552,21 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t
// Send SAK according UID len
switch (uid_len) {
case 4:
switch (MifareCardType) {
case 0: // Mifare Mini
EmSendPrecompiledCmd(&responses[SAK_MINI]);
break;
case 1: // Mifare 1K
EmSendPrecompiledCmd(&responses[SAK_1]);
break;
case 2: // Mifare 2K
EmSendPrecompiledCmd(&responses[SAK_2]);
break;
case 4: // Mifare 4K
EmSendPrecompiledCmd(&responses[SAK_4]);
break;
}
// UID completed
EmSendPrecompiledCmd(&responses[SAK]);
LED_B_ON();
cardSTATE = MFEMUL_WORK;
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_SELECT1] cardSTATE = MFEMUL_WORK");
break;
case 7:
// SAK => Need another select round
EmSendPrecompiledCmd(&responses[SAK1]);
EmSendPrecompiledCmd(&responses[SAKuid]);
cardSTATE = MFEMUL_SELECT2;
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_SELECT1] cardSTATE = MFEMUL_SELECT2");
break;
case 10:
// SAK => Need another select round
EmSendPrecompiledCmd(&responses[SAK1]);
EmSendPrecompiledCmd(&responses[SAKuid]);
cardSTATE = MFEMUL_SELECT2;
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_SELECT1] cardSTATE = MFEMUL_SELECT2");
break;
@ -657,27 +617,14 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t
switch (uid_len) {
case 7:
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_SELECT2] SELECT CL2 %02x%02x%02x%02x received", receivedCmd[2], receivedCmd[3], receivedCmd[4], receivedCmd[5]);
switch (MifareCardType) {
case 0: // Mifare Mini
EmSendPrecompiledCmd(&responses[SAK_MINI]);
break;
case 1: // Mifare 1K
EmSendPrecompiledCmd(&responses[SAK_1]);
break;
case 2: // Mifare 2K
EmSendPrecompiledCmd(&responses[SAK_2]);
break;
case 4: // Mifare 4K
EmSendPrecompiledCmd(&responses[SAK_4]);
break;
}
// UID completed
EmSendPrecompiledCmd(&responses[SAK]);
cardSTATE = MFEMUL_WORK;
LED_B_ON();
break;
case 10:
// SAK => Need another select round
EmSendPrecompiledCmd(&responses[SAK1]);
EmSendPrecompiledCmd(&responses[SAKuid]);
cardSTATE = MFEMUL_SELECT3;
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_SELECT2] cardSTATE = MFEMUL_SELECT3");
default:
@ -714,22 +661,8 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t
(receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_3 &&
receivedCmd[1] == 0x70 &&
memcmp(&receivedCmd[2], responses[UIDBCC3].response, 4) == 0)) {
switch (MifareCardType) {
case 0: // Mifare Mini
EmSendPrecompiledCmd(&responses[SAK_MINI]);
break;
case 1: // Mifare 1K
EmSendPrecompiledCmd(&responses[SAK_1]);
break;
case 2: // Mifare 2K
EmSendPrecompiledCmd(&responses[SAK_2]);
break;
case 4: // Mifare 4K
EmSendPrecompiledCmd(&responses[SAK_4]);
break;
}
// UID completed
EmSendPrecompiledCmd(&responses[SAK]);
cardSTATE = MFEMUL_WORK;
LED_B_ON();
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) {
@ -1003,9 +936,37 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t
}
// case MFEMUL_WORK => CMD RATS
if (receivedCmd_dec[0] == ISO14443A_CMD_RATS) {
if (receivedCmd_len == 4 && receivedCmd_dec[0] == ISO14443A_CMD_RATS && receivedCmd_dec[1] == 0x80) {
if (rats && rats_len) {
if (encrypted_data) {
memcpy(response, rats, rats_len);
mf_crypto1_encrypt(pcs, response, rats_len, response_par);
EmSendCmdPar(response, rats_len, response_par);
} else
EmSendCmd(rats, rats_len);
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] RCV RATS => ACK");
} else {
EmSend4bit(encrypted_data ? mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA) : CARD_NACK_NA);
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] RCV RATS => NACK");
}
break;
}
// case MFEMUL_WORK => ISO14443A_CMD_NXP_DESELECT
if (receivedCmd_len == 3 && receivedCmd_dec[0] == ISO14443A_CMD_NXP_DESELECT) {
if (rats && rats_len) {
// response back NXP_DESELECT
if (encrypted_data) {
memcpy(response, receivedCmd_dec, receivedCmd_len);
mf_crypto1_encrypt(pcs, response, receivedCmd_len, response_par);
EmSendCmdPar(response, receivedCmd_len, response_par);
} else
EmSendCmd(receivedCmd_dec, receivedCmd_len);
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] RCV NXP DESELECT => ACK");
} else {
EmSend4bit(encrypted_data ? mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA) : CARD_NACK_NA);
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] RCV NXP DESELECT => NACK");
}
break;
}

View file

@ -396,7 +396,7 @@ static int CmdrevengSearch(const char *Cmd) {
uint8_t width[NMODELS] = {0};
int count = 0;
uint8_t crcChars = 0;
uint8_t crcChars;
char result[30];
char revResult[30];
int ans = GetModels(Models, &count, width);

View file

@ -52,13 +52,13 @@ static int CmdHelp(const char *Cmd);
static int CmdHFFidoInfo(const char *cmd) {
if (cmd && strlen(cmd) > 0)
PrintAndLog("WARNING: command don't have any parameters.\n");
PrintAndLogEx(WARNING, "WARNING: command don't have any parameters.\n");
// info about 14a part
infoHF14A(false, false);
// FIDO info
PrintAndLog("--------------------------------------------");
PrintAndLogEx(NORMAL, "--------------------------------------------");
SetAPDULogging(false);
uint8_t buf[APDU_RES_LEN] = {0};
@ -73,9 +73,9 @@ static int CmdHFFidoInfo(const char *cmd) {
if (sw != 0x9000) {
if (sw)
PrintAndLog("Not a FIDO card! APDU response: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
PrintAndLogEx(INFO, "Not a FIDO card! APDU response: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
else
PrintAndLog("APDU exchange error. Card returns 0x0000.");
PrintAndLogEx(ERR, "APDU exchange error. Card returns 0x0000.");
DropField();
return 0;
@ -83,14 +83,14 @@ static int CmdHFFidoInfo(const char *cmd) {
if (!strncmp((char *)buf, "U2F_V2", 7)) {
if (!strncmp((char *)buf, "FIDO_2_0", 8)) {
PrintAndLog("FIDO2 authenricator detected. Version: %.*s", len, buf);
PrintAndLogEx(INFO, "FIDO2 authenricator detected. Version: %.*s", len, buf);
} else {
PrintAndLog("FIDO authenricator detected (not standard U2F).");
PrintAndLog("Non U2F authenticator version:");
PrintAndLogEx(INFO, "FIDO authenricator detected (not standard U2F).");
PrintAndLogEx(INFO, "Non U2F authenticator version:");
dump_buffer((const unsigned char *)buf, len, NULL, 0);
}
} else {
PrintAndLog("FIDO U2F authenricator detected. Version: %.*s", len, buf);
PrintAndLogEx(INFO, "FIDO U2F authenricator detected. Version: %.*s", len, buf);
}
res = FIDO2GetInfo(buf, sizeof(buf), &len, &sw);
@ -99,28 +99,22 @@ static int CmdHFFidoInfo(const char *cmd) {
return res;
}
if (sw != 0x9000) {
PrintAndLog("FIDO2 version not exists (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
PrintAndLogEx(ERR, "FIDO2 version not exists (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
return 0;
}
if (buf[0]) {
PrintAndLog("FIDO2 ger version error: %d - %s", buf[0], fido2GetCmdErrorDescription(buf[0]));
PrintAndLogEx(ERR, "FIDO2 ger version error: %d - %s", buf[0], fido2GetCmdErrorDescription(buf[0]));
return 0;
}
if (len > 1) {
// if (false) {
// PrintAndLog("FIDO2 version: (len=%d)", len);
// dump_buffer((const unsigned char *)buf, len, NULL, 0);
// }
PrintAndLog("FIDO2 version CBOR decoded:");
PrintAndLogEx(SUCCESS, "FIDO2 version CBOR decoded:");
TinyCborPrintFIDOPackage(fido2CmdGetInfo, true, &buf[1], len - 1);
} else {
PrintAndLog("FIDO2 version length error");
PrintAndLogEx(ERR, "FIDO2 version length error");
}
return 0;
}
@ -149,13 +143,13 @@ static json_t *OpenJson(int paramnum, char *fname, void *argtable[], bool *err)
if (access(fname, F_OK) != -1) {
root = json_load_file(fname, 0, &error);
if (!root) {
PrintAndLog("ERROR: json error on line %d: %s", error.line, error.text);
PrintAndLogEx(ERR, "ERROR: json error on line %d: %s", error.line, error.text);
*err = true;
return NULL;
}
if (!json_is_object(root)) {
PrintAndLog("ERROR: Invalid json format. root must be an object.");
PrintAndLogEx(ERR, "ERROR: Invalid json format. root must be an object.");
json_decref(root);
*err = true;
return NULL;
@ -216,13 +210,13 @@ static int CmdHFFidoRegister(const char *cmd) {
memset(cdata, 0x00, 32);
CLIGetStrWithReturn(6, cdata, &chlen);
if (chlen > 16) {
PrintAndLog("ERROR: challenge parameter length in ASCII mode must be less than 16 chars instead of: %d", chlen);
PrintAndLogEx(ERR, "ERROR: challenge parameter length in ASCII mode must be less than 16 chars instead of: %d", chlen);
return 1;
}
} else {
CLIGetHexWithReturn(6, cdata, &chlen);
if (chlen && chlen != 32) {
PrintAndLog("ERROR: challenge parameter length must be 32 bytes only.");
PrintAndLogEx(ERR, "ERROR: challenge parameter length must be 32 bytes only.");
return 1;
}
}
@ -234,13 +228,13 @@ static int CmdHFFidoRegister(const char *cmd) {
memset(adata, 0x00, 32);
CLIGetStrWithReturn(7, adata, &applen);
if (applen > 16) {
PrintAndLog("ERROR: application parameter length in ASCII mode must be less than 16 chars instead of: %d", applen);
PrintAndLogEx(ERR, "ERROR: application parameter length in ASCII mode must be less than 16 chars instead of: %d", applen);
return 1;
}
} else {
CLIGetHexWithReturn(7, adata, &applen);
if (applen && applen != 32) {
PrintAndLog("ERROR: application parameter length must be 32 bytes only.");
PrintAndLogEx(ERR, "ERROR: application parameter length must be 32 bytes only.");
return 1;
}
}
@ -262,13 +256,13 @@ static int CmdHFFidoRegister(const char *cmd) {
int res = FIDOSelect(true, true, buf, sizeof(buf), &len, &sw);
if (res) {
PrintAndLog("Can't select authenticator. res=%x. Exit...", res);
PrintAndLogEx(ERR, "Can't select authenticator. res=%x. Exit...", res);
DropField();
return res;
}
if (sw != 0x9000) {
PrintAndLog("Can't select FIDO application. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
PrintAndLogEx(ERR, "Can't select FIDO application. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
DropField();
return 2;
}
@ -276,44 +270,44 @@ static int CmdHFFidoRegister(const char *cmd) {
res = FIDORegister(data, buf, sizeof(buf), &len, &sw);
DropField();
if (res) {
PrintAndLog("Can't execute register command. res=%x. Exit...", res);
PrintAndLogEx(ERR, "Can't execute register command. res=%x. Exit...", res);
return res;
}
if (sw != 0x9000) {
PrintAndLog("ERROR execute register command. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
PrintAndLogEx(ERR, "ERROR execute register command. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
return 3;
}
PrintAndLog("");
PrintAndLogEx(NORMAL, "");
if (APDULogging)
PrintAndLog("---------------------------------------------------------------");
PrintAndLog("data len: %d", len);
PrintAndLogEx(NORMAL, "---------------------------------------------------------------");
PrintAndLogEx(NORMAL, "data len: %d", len);
if (verbose2) {
PrintAndLog("--------------data----------------------");
PrintAndLogEx(NORMAL, "--------------data----------------------");
dump_buffer((const unsigned char *)buf, len, NULL, 0);
PrintAndLog("--------------data----------------------");
PrintAndLogEx(NORMAL, "--------------data----------------------");
}
if (buf[0] != 0x05) {
PrintAndLog("ERROR: First byte must be 0x05, but it %2x", buf[0]);
PrintAndLogEx(ERR, "ERROR: First byte must be 0x05, but it %2x", buf[0]);
return 5;
}
PrintAndLog("User public key: %s", sprint_hex(&buf[1], 65));
PrintAndLogEx(SUCCESS, "User public key: %s", sprint_hex(&buf[1], 65));
uint8_t keyHandleLen = buf[66];
PrintAndLog("Key handle[%d]: %s", keyHandleLen, sprint_hex(&buf[67], keyHandleLen));
PrintAndLogEx(SUCCESS, "Key handle[%d]: %s", keyHandleLen, sprint_hex(&buf[67], keyHandleLen));
int derp = 67 + keyHandleLen;
int derLen = (buf[derp + 2] << 8) + buf[derp + 3] + 4;
if (verbose2) {
PrintAndLog("DER certificate[%d]:\n------------------DER-------------------", derLen);
PrintAndLogEx(NORMAL, "DER certificate[%d]:\n------------------DER-------------------", derLen);
dump_buffer_simple((const unsigned char *)&buf[derp], derLen, NULL);
PrintAndLog("\n----------------DER---------------------");
PrintAndLogEx(NORMAL, "\n----------------DER---------------------");
} else {
if (verbose)
PrintAndLog("------------------DER-------------------");
PrintAndLog("DER certificate[%d]: %s...", derLen, sprint_hex(&buf[derp], 20));
PrintAndLogEx(NORMAL, "------------------DER-------------------");
PrintAndLogEx(NORMAL, "DER certificate[%d]: %s...", derLen, sprint_hex(&buf[derp], 20));
}
// check and print DER certificate
@ -321,16 +315,16 @@ static int CmdHFFidoRegister(const char *cmd) {
// print DER certificate in TLV view
if (showDERTLV) {
PrintAndLog("----------------DER TLV-----------------");
PrintAndLogEx(NORMAL, "----------------DER TLV-----------------");
asn1_print(&buf[derp], derLen, " ");
PrintAndLog("----------------DER TLV-----------------");
PrintAndLogEx(NORMAL, "----------------DER TLV-----------------");
}
FIDOCheckDERAndGetKey(&buf[derp], derLen, verbose, public_key, sizeof(public_key));
// get hash
int hashp = 1 + 65 + 1 + keyHandleLen + derLen;
PrintAndLog("Hash[%d]: %s", len - hashp, sprint_hex(&buf[hashp], len - hashp));
PrintAndLogEx(SUCCESS, "Hash[%d]: %s", len - hashp, sprint_hex(&buf[hashp], len - hashp));
// check ANSI X9.62 format ECDSA signature (on P-256)
uint8_t rval[300] = {0};
@ -338,8 +332,8 @@ static int CmdHFFidoRegister(const char *cmd) {
res = ecdsa_asn1_get_signature(&buf[hashp], len - hashp, rval, sval);
if (!res) {
if (verbose) {
PrintAndLog(" r: %s", sprint_hex(rval, 32));
PrintAndLog(" s: %s", sprint_hex(sval, 32));
PrintAndLogEx(NORMAL, " r: %s", sprint_hex(rval, 32));
PrintAndLogEx(NORMAL, " s: %s", sprint_hex(sval, 32));
}
uint8_t xbuf[4096] = {0};
@ -351,23 +345,23 @@ static int CmdHFFidoRegister(const char *cmd) {
&buf[67], keyHandleLen, // keyHandle
&buf[1], 65, // user public key
NULL, 0);
//PrintAndLog("--xbuf(%d)[%d]: %s", res, xbuflen, sprint_hex(xbuf, xbuflen));
//PrintAndLogEx(NORMAL, "--xbuf(%d)[%d]: %s", res, xbuflen, sprint_hex(xbuf, xbuflen));
res = ecdsa_signature_verify(public_key, xbuf, xbuflen, &buf[hashp], len - hashp);
if (res) {
if (res == -0x4e00) {
PrintAndLog("Signature is NOT VALID.");
PrintAndLogEx(WARNING, "Signature is NOT VALID.");
} else {
PrintAndLog("Other signature check error: %x %s", (res < 0) ? -res : res, ecdsa_get_error(res));
PrintAndLogEx(WARNING, "Other signature check error: %x %s", (res < 0) ? -res : res, ecdsa_get_error(res));
}
} else {
PrintAndLog("Signature is OK.");
PrintAndLogEx(SUCCESS, "Signature is OK.");
}
} else {
PrintAndLog("Invalid signature. res=%d.", res);
PrintAndLogEx(WARNING, "Invalid signature. res = %d.", res);
}
PrintAndLog("\nauth command: ");
PrintAndLogEx(INFO, "\nauth command: ");
printf("hf fido auth %s%s", paramsPlain ? "-p " : "", sprint_hex_inrow(&buf[67], keyHandleLen));
if (chlen || applen)
printf(" %s", paramsPlain ? (char *)cdata : sprint_hex_inrow(cdata, 32));
@ -385,10 +379,10 @@ static int CmdHFFidoRegister(const char *cmd) {
res = json_dump_file(root, fname, JSON_INDENT(2));
if (res) {
PrintAndLog("ERROR: can't save the file: %s", fname);
PrintAndLogEx(ERR, "ERROR: can't save the file: %s", fname);
return 200;
}
PrintAndLog("File `%s` saved.", fname);
PrintAndLogEx(SUCCESS, "File " _YELLOW_("`%s`") " saved.", fname);
// free json object
json_decref(root);
@ -457,7 +451,7 @@ static int CmdHFFidoAuthenticate(const char *cmd) {
// public key
CLIGetHexWithReturn(8, hdata, &hdatalen);
if (hdatalen && hdatalen != 65) {
PrintAndLog("ERROR: public key length must be 65 bytes only.");
PrintAndLogEx(ERR, "ERROR: public key length must be 65 bytes only.");
return 1;
}
if (hdatalen) {
@ -467,7 +461,7 @@ static int CmdHFFidoAuthenticate(const char *cmd) {
CLIGetHexWithReturn(9, hdata, &hdatalen);
if (hdatalen > 255) {
PrintAndLog("ERROR: application parameter length must be less than 255.");
PrintAndLogEx(ERR, "ERROR: application parameter length must be less than 255.");
return 1;
}
if (hdatalen) {
@ -480,13 +474,13 @@ static int CmdHFFidoAuthenticate(const char *cmd) {
memset(hdata, 0x00, 32);
CLIGetStrWithReturn(9, hdata, &hdatalen);
if (hdatalen > 16) {
PrintAndLog("ERROR: challenge parameter length in ASCII mode must be less than 16 chars instead of: %d", hdatalen);
PrintAndLogEx(ERR, "ERROR: challenge parameter length in ASCII mode must be less than 16 chars instead of: %d", hdatalen);
return 1;
}
} else {
CLIGetHexWithReturn(10, hdata, &hdatalen);
if (hdatalen && hdatalen != 32) {
PrintAndLog("ERROR: challenge parameter length must be 32 bytes only.");
PrintAndLogEx(ERR, "ERROR: challenge parameter length must be 32 bytes only.");
return 1;
}
}
@ -497,13 +491,13 @@ static int CmdHFFidoAuthenticate(const char *cmd) {
memset(hdata, 0x00, 32);
CLIGetStrWithReturn(11, hdata, &hdatalen);
if (hdatalen > 16) {
PrintAndLog("ERROR: application parameter length in ASCII mode must be less than 16 chars instead of: %d", hdatalen);
PrintAndLogEx(ERR, "ERROR: application parameter length in ASCII mode must be less than 16 chars instead of: %d", hdatalen);
return 1;
}
} else {
CLIGetHexWithReturn(10, hdata, &hdatalen);
if (hdatalen && hdatalen != 32) {
PrintAndLog("ERROR: application parameter length must be 32 bytes only.");
PrintAndLogEx(ERR, "ERROR: application parameter length must be 32 bytes only.");
return 1;
}
}
@ -530,13 +524,13 @@ static int CmdHFFidoAuthenticate(const char *cmd) {
int res = FIDOSelect(true, true, buf, sizeof(buf), &len, &sw);
if (res) {
PrintAndLog("Can't select authenticator. res=%x. Exit...", res);
PrintAndLogEx(ERR, "Can't select authenticator. res=%x. Exit...", res);
DropField();
return res;
}
if (sw != 0x9000) {
PrintAndLog("Can't select FIDO application. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
PrintAndLogEx(ERR, "Can't select FIDO application. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
DropField();
return 2;
}
@ -544,20 +538,20 @@ static int CmdHFFidoAuthenticate(const char *cmd) {
res = FIDOAuthentication(data, datalen, controlByte, buf, sizeof(buf), &len, &sw);
DropField();
if (res) {
PrintAndLog("Can't execute authentication command. res=%x. Exit...", res);
PrintAndLogEx(ERR, "Can't execute authentication command. res=%x. Exit...", res);
return res;
}
if (sw != 0x9000) {
PrintAndLog("ERROR execute authentication command. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
PrintAndLogEx(ERR, "ERROR execute authentication command. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
return 3;
}
PrintAndLog("---------------------------------------------------------------");
PrintAndLog("User presence: %s", (buf[0] ? "verified" : "not verified"));
PrintAndLogEx(NORMAL, "---------------------------------------------------------------");
PrintAndLogEx(SUCCESS, "User presence: %s", (buf[0] ? "verified" : "not verified"));
uint32_t cntr = (uint32_t)bytes_to_num(&buf[1], 4);
PrintAndLog("Counter: %d", cntr);
PrintAndLog("Hash[%d]: %s", len - 5, sprint_hex(&buf[5], len - 5));
PrintAndLogEx(SUCCESS, "Counter: %d", cntr);
PrintAndLogEx(SUCCESS, "Hash[%d]: %s", len - 5, sprint_hex(&buf[5], len - 5));
// check ANSI X9.62 format ECDSA signature (on P-256)
uint8_t rval[300] = {0};
@ -565,8 +559,8 @@ static int CmdHFFidoAuthenticate(const char *cmd) {
res = ecdsa_asn1_get_signature(&buf[5], len - 5, rval, sval);
if (!res) {
if (verbose) {
PrintAndLog(" r: %s", sprint_hex(rval, 32));
PrintAndLog(" s: %s", sprint_hex(sval, 32));
PrintAndLogEx(NORMAL, " r: %s", sprint_hex(rval, 32));
PrintAndLogEx(NORMAL, " s: %s", sprint_hex(sval, 32));
}
if (public_key_loaded) {
uint8_t xbuf[4096] = {0};
@ -577,22 +571,22 @@ static int CmdHFFidoAuthenticate(const char *cmd) {
&buf[1], 4, // counter
data, 32, // challenge parameter
NULL, 0);
//PrintAndLog("--xbuf(%d)[%d]: %s", res, xbuflen, sprint_hex(xbuf, xbuflen));
//PrintAndLogEx(NORMAL, "--xbuf(%d)[%d]: %s", res, xbuflen, sprint_hex(xbuf, xbuflen));
res = ecdsa_signature_verify(public_key, xbuf, xbuflen, &buf[5], len - 5);
if (res) {
if (res == -0x4e00) {
PrintAndLog("Signature is NOT VALID.");
PrintAndLogEx(WARNING, "Signature is NOT VALID.");
} else {
PrintAndLog("Other signature check error: %x %s", (res < 0) ? -res : res, ecdsa_get_error(res));
PrintAndLogEx(WARNING, "Other signature check error: %x %s", (res < 0) ? -res : res, ecdsa_get_error(res));
}
} else {
PrintAndLog("Signature is OK.");
PrintAndLogEx(SUCCESS, "Signature is OK.");
}
} else {
PrintAndLog("No public key provided. can't check signature.");
PrintAndLogEx(WARNING, "No public key provided. can't check signature.");
}
} else {
PrintAndLog("Invalid signature. res=%d.", res);
PrintAndLogEx(ERR, "Invalid signature. res = %d.", res);
}
if (root) {
@ -604,10 +598,10 @@ static int CmdHFFidoAuthenticate(const char *cmd) {
res = json_dump_file(root, fname, JSON_INDENT(2));
if (res) {
PrintAndLog("ERROR: can't save the file: %s", fname);
PrintAndLogEx(ERR, "ERROR: can't save the file: %s", fname);
return 200;
}
PrintAndLog("File `%s` saved.", fname);
PrintAndLogEx(SUCCESS, "File " _YELLOW_("`%s`") " saved.", fname);
// free json object
json_decref(root);
@ -691,13 +685,13 @@ static int CmdHFFido2MakeCredential(const char *cmd) {
int res = GetExistsFileNameJson("fido", cjsonname, fname);
if (res) {
PrintAndLog("ERROR: Can't found the json file.");
PrintAndLogEx(ERR, "ERROR: Can't found the json file.");
return res;
}
PrintAndLog("fname: %s\n", fname);
PrintAndLogEx(NORMAL, "fname: %s\n", fname);
root = json_load_file(fname, 0, &error);
if (!root) {
PrintAndLog("ERROR: json error on line %d: %s", error.line, error.text);
PrintAndLogEx(ERR, "ERROR: json error on line %d: %s", error.line, error.text);
return 1;
}
@ -711,13 +705,13 @@ static int CmdHFFido2MakeCredential(const char *cmd) {
res = FIDOSelect(true, true, buf, sizeof(buf), &len, &sw);
if (res) {
PrintAndLog("Can't select authenticator. res=%x. Exit...", res);
PrintAndLogEx(ERR, "Can't select authenticator. res=%x. Exit...", res);
DropField();
return res;
}
if (sw != 0x9000) {
PrintAndLog("Can't select FIDO application. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
PrintAndLogEx(ERR, "Can't select FIDO application. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
DropField();
return 2;
}
@ -727,35 +721,35 @@ static int CmdHFFido2MakeCredential(const char *cmd) {
return res;
if (showCBOR) {
PrintAndLog("CBOR make credentional request:");
PrintAndLog("---------------- CBOR ------------------");
PrintAndLogEx(INFO, "CBOR make credentional request:");
PrintAndLogEx(NORMAL, "---------------- CBOR ------------------");
TinyCborPrintFIDOPackage(fido2CmdMakeCredential, false, data, datalen);
PrintAndLog("---------------- CBOR ------------------");
PrintAndLogEx(NORMAL, "---------------- CBOR ------------------");
}
res = FIDO2MakeCredential(data, datalen, buf, sizeof(buf), &len, &sw);
DropField();
if (res) {
PrintAndLog("Can't execute make credential command. res=%x. Exit...", res);
PrintAndLogEx(ERR, "Can't execute make credential command. res=%x. Exit...", res);
return res;
}
if (sw != 0x9000) {
PrintAndLog("ERROR execute make credential command. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
PrintAndLogEx(ERR, "ERROR execute make credential command. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
return 3;
}
if (buf[0]) {
PrintAndLog("FIDO2 make credential error: %d - %s", buf[0], fido2GetCmdErrorDescription(buf[0]));
PrintAndLogEx(ERR, "FIDO2 make credential error: %d - %s", buf[0], fido2GetCmdErrorDescription(buf[0]));
return 0;
}
PrintAndLog("MakeCredential result (%d b) OK.", len);
PrintAndLogEx(SUCCESS, "MakeCredential result (%d b) OK.", len);
if (showCBOR) {
PrintAndLog("CBOR make credentional response:");
PrintAndLog("---------------- CBOR ------------------");
PrintAndLogEx(SUCCESS, "CBOR make credentional response:");
PrintAndLogEx(NORMAL, "---------------- CBOR ------------------");
TinyCborPrintFIDOPackage(fido2CmdMakeCredential, true, &buf[1], len - 1);
PrintAndLog("---------------- CBOR ------------------");
PrintAndLogEx(NORMAL, "---------------- CBOR ------------------");
}
// parse returned cbor
@ -764,14 +758,13 @@ static int CmdHFFido2MakeCredential(const char *cmd) {
if (root) {
res = json_dump_file(root, fname, JSON_INDENT(2));
if (res) {
PrintAndLog("ERROR: can't save the file: %s", fname);
PrintAndLogEx(ERR, "ERROR: can't save the file: %s", fname);
return 200;
}
PrintAndLog("File `%s` saved.", fname);
PrintAndLogEx(SUCCESS, "File " _YELLOW_("`%s`") " saved.", fname);
}
json_decref(root);
return 0;
};
@ -818,13 +811,13 @@ static int CmdHFFido2GetAssertion(const char *cmd) {
int res = GetExistsFileNameJson("fido", "fido2", fname);
if (res) {
PrintAndLog("ERROR: Can't found the json file.");
PrintAndLogEx(ERR, "ERROR: Can't found the json file.");
return res;
}
PrintAndLog("fname: %s\n", fname);
PrintAndLogEx(NORMAL, "fname: %s\n", fname);
root = json_load_file(fname, 0, &error);
if (!root) {
PrintAndLog("ERROR: json error on line %d: %s", error.line, error.text);
PrintAndLogEx(ERR, "ERROR: json error on line %d: %s", error.line, error.text);
return 1;
}
@ -838,13 +831,13 @@ static int CmdHFFido2GetAssertion(const char *cmd) {
res = FIDOSelect(true, true, buf, sizeof(buf), &len, &sw);
if (res) {
PrintAndLog("Can't select authenticator. res=%x. Exit...", res);
PrintAndLogEx(ERR, "Can't select authenticator. res=%x. Exit...", res);
DropField();
return res;
}
if (sw != 0x9000) {
PrintAndLog("Can't select FIDO application. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
PrintAndLogEx(ERR, "Can't select FIDO application. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
DropField();
return 2;
}
@ -854,35 +847,35 @@ static int CmdHFFido2GetAssertion(const char *cmd) {
return res;
if (showCBOR) {
PrintAndLog("CBOR get assertion request:");
PrintAndLog("---------------- CBOR ------------------");
PrintAndLogEx(SUCCESS, "CBOR get assertion request:");
PrintAndLogEx(NORMAL, "---------------- CBOR ------------------");
TinyCborPrintFIDOPackage(fido2CmdGetAssertion, false, data, datalen);
PrintAndLog("---------------- CBOR ------------------");
PrintAndLogEx(NORMAL, "---------------- CBOR ------------------");
}
res = FIDO2GetAssertion(data, datalen, buf, sizeof(buf), &len, &sw);
DropField();
if (res) {
PrintAndLog("Can't execute get assertion command. res=%x. Exit...", res);
PrintAndLogEx(ERR, "Can't execute get assertion command. res=%x. Exit...", res);
return res;
}
if (sw != 0x9000) {
PrintAndLog("ERROR execute get assertion command. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
PrintAndLogEx(ERR, "ERROR execute get assertion command. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
return 3;
}
if (buf[0]) {
PrintAndLog("FIDO2 get assertion error: %d - %s", buf[0], fido2GetCmdErrorDescription(buf[0]));
PrintAndLogEx(ERR, "FIDO2 get assertion error: %d - %s", buf[0], fido2GetCmdErrorDescription(buf[0]));
return 0;
}
PrintAndLog("GetAssertion result (%d b) OK.", len);
PrintAndLogEx(SUCCESS, "GetAssertion result (%d b) OK.", len);
if (showCBOR) {
PrintAndLog("CBOR get assertion response:");
PrintAndLog("---------------- CBOR ------------------");
PrintAndLogEx(SUCCESS, "CBOR get assertion response:");
PrintAndLogEx(NORMAL, "---------------- CBOR ------------------");
TinyCborPrintFIDOPackage(fido2CmdGetAssertion, true, &buf[1], len - 1);
PrintAndLog("---------------- CBOR ------------------");
PrintAndLogEx(NORMAL, "---------------- CBOR ------------------");
}
// parse returned cbor
@ -891,14 +884,13 @@ static int CmdHFFido2GetAssertion(const char *cmd) {
if (root) {
res = json_dump_file(root, fname, JSON_INDENT(2));
if (res) {
PrintAndLog("ERROR: can't save the file: %s", fname);
PrintAndLogEx(ERR, "ERROR: can't save the file: %s", fname);
return 200;
}
PrintAndLog("File `%s` saved.", fname);
PrintAndLogEx(SUCCESS, "File " _YELLOW_("`%s`") " saved.", fname);
}
json_decref(root);
return 0;
};

View file

@ -64,14 +64,14 @@ static int usage_hf14_mifare(void) {
PrintAndLogEx(NORMAL, " hf mf darkside 16 B");
return 0;
}
static int usage_hf14_mf1ksim(void) {
static int usage_hf14_mfsim(void) {
PrintAndLogEx(NORMAL, "Usage: hf mf sim [h] u <uid> n <numreads> [i] [x] [e] [v]");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h this help");
PrintAndLogEx(NORMAL, " u (Optional) UID 4,7 or 10bytes. If not specified, the UID 4b from emulator memory will be used");
PrintAndLogEx(NORMAL, " t (Optional) 0 = MIFARE Mini");
PrintAndLogEx(NORMAL, " 1 = MIFARE Classic 1k (Default)");
PrintAndLogEx(NORMAL, " 1 = MIFARE Classic 2k");
PrintAndLogEx(NORMAL, " 1 = MIFARE Classic 2k plus in SL0 mode");
PrintAndLogEx(NORMAL, " 4 = MIFARE Classic 4k");
PrintAndLogEx(NORMAL, " n (Optional) Automatically exit simulation after <numreads> blocks have been read by reader. 0 = infinite");
PrintAndLogEx(NORMAL, " i (Optional) Interactive, means that console will not be returned until simulation finishes or is aborted");
@ -2136,11 +2136,11 @@ void readerAttack(nonces_t data, bool setEmulatorMem, bool verbose) {
}
}
static int CmdHF14AMf1kSim(const char *Cmd) {
static int CmdHF14AMfSim(const char *Cmd) {
uint8_t uid[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
uint8_t exitAfterNReads = 0;
uint16_t flags = (FLAG_UID_IN_EMUL | FLAG_4B_UID_IN_DATA);
uint16_t flags = 0;
int uidlen = 0;
uint8_t cmdp = 0;
bool errors = false, verbose = false, setEmulatorMem = false;
@ -2153,7 +2153,7 @@ static int CmdHF14AMf1kSim(const char *Cmd) {
cmdp++;
break;
case 'h':
return usage_hf14_mf1ksim();
return usage_hf14_mfsim();
case 'i':
flags |= FLAG_INTERACTIVE;
cmdp++;
@ -2191,16 +2191,16 @@ static int CmdHF14AMf1kSim(const char *Cmd) {
param_gethex_ex(Cmd, cmdp + 1, uid, &uidlen);
switch (uidlen) {
case 20:
flags = FLAG_10B_UID_IN_DATA;
flags |= FLAG_10B_UID_IN_DATA;
break;
case 14:
flags = FLAG_7B_UID_IN_DATA;
flags |= FLAG_7B_UID_IN_DATA;
break;
case 8:
flags = FLAG_4B_UID_IN_DATA;
flags |= FLAG_4B_UID_IN_DATA;
break;
default:
return usage_hf14_mf1ksim();
return usage_hf14_mfsim();
}
cmdp += 2;
break;
@ -2219,7 +2219,11 @@ static int CmdHF14AMf1kSim(const char *Cmd) {
}
}
//Validations
if (errors) return usage_hf14_mf1ksim();
if (errors) return usage_hf14_mfsim();
// Use UID, SAK, ATQA from EMUL, if uid not defined
if ((flags & (FLAG_4B_UID_IN_DATA | FLAG_7B_UID_IN_DATA | FLAG_10B_UID_IN_DATA)) == 0)
flags |= FLAG_UID_IN_EMUL;
PrintAndLogEx(NORMAL, " uid:%s, numreads:%d, flags:%d (0x%02x) "
, (uidlen == 0) ? "N/A" : sprint_hex(uid, uidlen >> 1)
@ -3550,7 +3554,7 @@ static command_t CommandTable[] = {
{"auth4", CmdHF14AMfAuth4, 0, "ISO14443-4 AES authentication"},
// {"sniff", CmdHF14AMfSniff, 0, "Sniff card-reader communication"},
{"-----------", CmdHelp, 0, ""},
{"sim", CmdHF14AMf1kSim, 0, "Simulate MIFARE card"},
{"sim", CmdHF14AMfSim, 0, "Simulate MIFARE card"},
{"eclr", CmdHF14AMfEClear, 0, "Clear simulator memory block"},
{"eget", CmdHF14AMfEGet, 0, "Get simulator memory block"},
{"eset", CmdHF14AMfESet, 0, "Set simulator memory block"},

View file

@ -856,9 +856,7 @@ int EM4x50Read(const char *Cmd, bool verbose) {
phaseoff = 0;
// now do it again to find the end
end = skip;
for (i += 3; i < j - 4 ; ++i) {
end += tmpbuff[i];
if (tmpbuff[i] >= clk * 3 - tol && tmpbuff[i] <= clk * 3 + tol) //3 clocks
if (tmpbuff[i + 1] >= clk * 2 - tol && tmpbuff[i + 1] <= clk * 2 + tol) //2 clocks
if (tmpbuff[i + 2] >= clk * 3 - tol && tmpbuff[i + 2] <= clk * 3 + tol) //3 clocks

View file

@ -200,23 +200,23 @@ static int PrintATR(uint8_t *atr, size_t atrlen) {
bool protocol_T15_present = false;
if (T0 & 0x10) {
PrintAndLog("\t- TA1 (Maximum clock frequency, proposed bit duration) [ 0x%02x ]", atr[2 + T1len]);
PrintAndLogEx(NORMAL, "\t- TA1 (Maximum clock frequency, proposed bit duration) [ 0x%02x ]", atr[2 + T1len]);
T1len++;
}
if (T0 & 0x20) {
PrintAndLog("\t- TB1 (Deprecated: VPP requirements) [ 0x%02x ]", atr[2 + T1len]);
PrintAndLogEx(NORMAL, "\t- TB1 (Deprecated: VPP requirements) [ 0x%02x ]", atr[2 + T1len]);
T1len++;
}
if (T0 & 0x40) {
PrintAndLog("\t- TC1 (Extra delay between bytes required by card) [ 0x%02x ]", atr[2 + T1len]);
PrintAndLogEx(NORMAL, "\t- TC1 (Extra delay between bytes required by card) [ 0x%02x ]", atr[2 + T1len]);
T1len++;
}
if (T0 & 0x80) {
uint8_t TD1 = atr[2 + T1len];
PrintAndLog("\t- TD1 (First offered transmission protocol, presence of TA2..TD2) [ 0x%02x ] Protocol T%d", TD1, TD1 & 0x0f);
PrintAndLogEx(NORMAL, "\t- TD1 (First offered transmission protocol, presence of TA2..TD2) [ 0x%02x ] Protocol T%d", TD1, TD1 & 0x0f);
protocol_T0_present = false;
if ((TD1 & 0x0f) == 0) {
protocol_T0_present = true;
@ -228,20 +228,20 @@ static int PrintATR(uint8_t *atr, size_t atrlen) {
T1len++;
if (TD1 & 0x10) {
PrintAndLog("\t- TA2 (Specific protocol and parameters to be used after the ATR) [ 0x%02x ]", atr[2 + T1len + TD1len]);
PrintAndLogEx(NORMAL, "\t- TA2 (Specific protocol and parameters to be used after the ATR) [ 0x%02x ]", atr[2 + T1len + TD1len]);
TD1len++;
}
if (TD1 & 0x20) {
PrintAndLog("\t- TB2 (Deprecated: VPP precise voltage requirement) [ 0x%02x ]", atr[2 + T1len + TD1len]);
PrintAndLogEx(NORMAL, "\t- TB2 (Deprecated: VPP precise voltage requirement) [ 0x%02x ]", atr[2 + T1len + TD1len]);
TD1len++;
}
if (TD1 & 0x40) {
PrintAndLog("\t- TC2 (Maximum waiting time for protocol T=0) [ 0x%02x ]", atr[2 + T1len + TD1len]);
PrintAndLogEx(NORMAL, "\t- TC2 (Maximum waiting time for protocol T=0) [ 0x%02x ]", atr[2 + T1len + TD1len]);
TD1len++;
}
if (TD1 & 0x80) {
uint8_t TDi = atr[2 + T1len + TD1len];
PrintAndLog("\t- TD2 (A supported protocol or more global parameters, presence of TA3..TD3) [ 0x%02x ] Protocol T%d", TDi, TDi & 0x0f);
PrintAndLogEx(NORMAL, "\t- TD2 (A supported protocol or more global parameters, presence of TA3..TD3) [ 0x%02x ] Protocol T%d", TDi, TDi & 0x0f);
if ((TDi & 0x0f) == 0) {
protocol_T0_present = true;
}
@ -255,20 +255,20 @@ static int PrintATR(uint8_t *atr, size_t atrlen) {
while (nextCycle) {
nextCycle = false;
if (TDi & 0x10) {
PrintAndLog("\t- TA%d: 0x%02x", vi, atr[2 + T1len + TD1len + TDilen]);
PrintAndLogEx(NORMAL, "\t- TA%d: 0x%02x", vi, atr[2 + T1len + TD1len + TDilen]);
TDilen++;
}
if (TDi & 0x20) {
PrintAndLog("\t- TB%d: 0x%02x", vi, atr[2 + T1len + TD1len + TDilen]);
PrintAndLogEx(NORMAL, "\t- TB%d: 0x%02x", vi, atr[2 + T1len + TD1len + TDilen]);
TDilen++;
}
if (TDi & 0x40) {
PrintAndLog("\t- TC%d: 0x%02x", vi, atr[2 + T1len + TD1len + TDilen]);
PrintAndLogEx(NORMAL, "\t- TC%d: 0x%02x", vi, atr[2 + T1len + TD1len + TDilen]);
TDilen++;
}
if (TDi & 0x80) {
TDi = atr[2 + T1len + TD1len + TDilen];
PrintAndLog("\t- TD%d [ 0x%02x ] Protocol T%d", vi, TDi, TDi & 0x0f);
PrintAndLogEx(NORMAL, "\t- TD%d [ 0x%02x ] Protocol T%d", vi, TDi, TDi & 0x0f);
TDilen++;
nextCycle = true;

View file

@ -64,7 +64,7 @@ void SendCommand(UsbCommand *c) {
#endif
if (offline) {
PrintAndLogEx(WARNING, "Sending bytes to Proxmark3 failed." _YELLOW_("offline") );
PrintAndLogEx(WARNING, "Sending bytes to Proxmark3 failed." _YELLOW_("offline"));
return;
}
@ -384,13 +384,13 @@ __attribute__((force_align_arg_pointer))
if (txBufferNGLen) { // NG packet
if (!uart_send(sp, (uint8_t *) &txBufferNG, txBufferNGLen)) {
//counter_to_offline++;
PrintAndLogEx(WARNING, "sending bytes to Proxmark3 device" _RED_("failed") );
PrintAndLogEx(WARNING, "sending bytes to Proxmark3 device" _RED_("failed"));
}
txBufferNGLen = 0;
} else {
if (!uart_send(sp, (uint8_t *) &txBuffer, sizeof(UsbCommand))) {
//counter_to_offline++;
PrintAndLogEx(WARNING, "sending bytes to Proxmark3 device" _RED_("failed") );
PrintAndLogEx(WARNING, "sending bytes to Proxmark3 device" _RED_("failed"));
}
}
txBuffer_pending = false;

View file

@ -46,7 +46,7 @@ static void ParamLoadDefaults(struct tlvdb *tlvRoot) {
static void PrintChannel(EMVCommandChannel channel) {
switch (channel) {
case ECC_CONTACTLESS:
PrintAndLogEx(INFO, "Channel: CONTACTLESS");
PrintAndLogEx(INFO, "Channel: CONTACTLESS (T=CL)");
break;
case ECC_CONTACT:
PrintAndLogEx(INFO, "Channel: CONTACT");
@ -203,7 +203,6 @@ static int CmdEMVPPSE(const char *Cmd) {
if (res)
return res;
if (decodeTLV)
TLVPrintFromBuffer(buf, len);
@ -288,6 +287,7 @@ static int CmdEMVGPO(const char *Cmd) {
PrintAndLogEx(ERR, "Can't create PDOL data.");
tlvdb_free(tmp_ext);
tlvdb_free(tlvRoot);
if (pdol_data_tlv != &data_tlv);
free(pdol_data_tlv);
return 4;
}
@ -410,7 +410,7 @@ static int CmdEMVAC(const char *Cmd) {
termDecision = EMVAC_ARQC;
if (termDecision == 0xff) {
PrintAndLog("ERROR: can't find terminal decision '%s'", arg_get_str(3)->sval[0]);
PrintAndLogEx(ERR, "ERROR: can't find terminal decision '%s'", arg_get_str(3)->sval[0]);
return 1;
}
} else {
@ -647,7 +647,7 @@ static void InitTransactionParameters(struct tlvdb *tlvRoot, bool paramLoadJSON,
ParamLoadDefaults(tlvRoot);
if (paramLoadJSON) {
PrintAndLog("* * Transaction parameters loading from JSON...");
PrintAndLogEx(INFO, "* * Transaction parameters loading from JSON...");
ParamLoadFromJson(tlvRoot);
}
@ -678,12 +678,12 @@ static void InitTransactionParameters(struct tlvdb *tlvRoot, bool paramLoadJSON,
static void ProcessGPOResponseFormat1(struct tlvdb *tlvRoot, uint8_t *buf, size_t len, bool decodeTLV) {
if (buf[0] == 0x80) {
if (decodeTLV) {
PrintAndLog("GPO response format1:");
PrintAndLogEx(SUCCESS, "GPO response format1:");
TLVPrintFromBuffer(buf, len);
}
if (len < 4 || (len - 4) % 4) {
PrintAndLogEx(ERR, "GPO response format1 parsing error. length=%d", len);
PrintAndLogEx(ERR, "GPO response format 1 parsing error. length = %d", len);
} else {
// AIP
struct tlvdb *f1AIP = tlvdb_fixed(0x82, 2, buf + 2);
@ -708,7 +708,7 @@ static void ProcessGPOResponseFormat1(struct tlvdb *tlvRoot, uint8_t *buf, size_
static void ProcessACResponseFormat1(struct tlvdb *tlvRoot, uint8_t *buf, size_t len, bool decodeTLV) {
if (buf[0] == 0x80) {
if (decodeTLV) {
PrintAndLog("GPO response format1:");
PrintAndLogEx(SUCCESS, "GPO response format 1:");
TLVPrintFromBuffer(buf, len);
}
@ -719,7 +719,7 @@ static void ProcessACResponseFormat1(struct tlvdb *tlvRoot, uint8_t *buf, size_t
} else {
struct tlvdb *tlvElm = NULL;
if (decodeTLV)
PrintAndLog("\n------------ Format1 decoded ------------");
PrintAndLogEx(NORMAL, "\n------------ Format1 decoded ------------");
// CID (Cryptogram Information Data)
tlvdb_change_or_add_node_ex(tlvRoot, 0x9f27, 1, &buf[2], &tlvElm);
@ -873,23 +873,23 @@ static int CmdEMVExec(const char *Cmd) {
if (decodeTLV)
TLVPrintFromBuffer(buf, len);
PrintAndLog("* Selected.");
PrintAndLogEx(NORMAL, "* Selected.");
PrintAndLog("\n* Init transaction parameters.");
PrintAndLogEx(NORMAL, "\n* Init transaction parameters.");
InitTransactionParameters(tlvRoot, paramLoadJSON, TrType, GenACGPO);
TLVPrintFromTLV(tlvRoot); // TODO delete!!!
PrintAndLogEx(NORMAL, "\n* Calc PDOL.");
pdol_data_tlv = dol_process(tlvdb_get(tlvRoot, 0x9f38, NULL), tlvRoot, 0x83);
if (!pdol_data_tlv) {
PrintAndLogEx(WARNING, "Error: can't create PDOL TLV.");
PrintAndLogEx(ERR, "Error: can't create PDOL TLV.");
dreturn(4);
}
size_t pdol_data_tlv_data_len;
unsigned char *pdol_data_tlv_data = tlv_encode(pdol_data_tlv, &pdol_data_tlv_data_len);
if (!pdol_data_tlv_data) {
PrintAndLogEx(WARNING, "Error: can't create PDOL data.");
PrintAndLogEx(ERR, "Error: can't create PDOL data.");
dreturn(4);
}
PrintAndLogEx(NORMAL, "PDOL data[%d]: %s", pdol_data_tlv_data_len, sprint_hex(pdol_data_tlv_data, pdol_data_tlv_data_len));
@ -901,7 +901,7 @@ static int CmdEMVExec(const char *Cmd) {
//free(pdol_data_tlv); --- free on exit.
if (res) {
PrintAndLogEx(NORMAL, "GPO error(%d): %4x. Exit...", res, sw);
PrintAndLogEx(ERR, "GPO error(%d): %4x. Exit...", res, sw);
dreturn(5);
}
@ -919,7 +919,7 @@ static int CmdEMVExec(const char *Cmd) {
const struct tlv *pantlv = tlvdb_get(tlvRoot, 0x5a, NULL);
PrintAndLogEx(NORMAL, "\n* * Extracted PAN from track2: %s", sprint_hex(pantlv->value, pantlv->len));
} else {
PrintAndLogEx(NORMAL, "\n* * WARNING: Can't extract PAN from track2.");
PrintAndLogEx(WARNING, "\n* * WARNING: Can't extract PAN from track2.");
}
}
}
@ -928,7 +928,7 @@ static int CmdEMVExec(const char *Cmd) {
const struct tlv *AFL = tlvdb_get(tlvRoot, 0x94, NULL);
if (!AFL || !AFL->len)
PrintAndLogEx(NORMAL, "WARNING: AFL not found.");
PrintAndLogEx(WARNING, "WARNING: AFL not found.");
while (AFL && AFL->len) {
if (AFL->len % 4) {
@ -1066,11 +1066,11 @@ static int CmdEMVExec(const char *Cmd) {
PrintAndLogEx(NORMAL, "* * Generate challenge");
res = EMVGenerateChallenge(channel, true, buf, sizeof(buf), &len, &sw, tlvRoot);
if (res) {
PrintAndLogEx(WARNING, "Error GetChallenge. APDU error %4x", sw);
PrintAndLogEx(ERR, "Error GetChallenge. APDU error %4x", sw);
dreturn(6);
}
if (len < 4) {
PrintAndLogEx(WARNING, "Error GetChallenge. Wrong challenge length %d", len);
PrintAndLogEx(ERR, "Error GetChallenge. Wrong challenge length %d", len);
dreturn(6);
}
@ -1085,7 +1085,7 @@ static int CmdEMVExec(const char *Cmd) {
PrintAndLogEx(NORMAL, "* * Calc CDOL1");
struct tlv *cdol_data_tlv = dol_process(tlvdb_get(tlvRoot, 0x8c, NULL), tlvRoot, 0x01); // 0x01 - dummy tag
if (!cdol_data_tlv) {
PrintAndLogEx(WARNING, "Error: can't create CDOL1 TLV.");
PrintAndLogEx(ERR, "Error: can't create CDOL1 TLV.");
dreturn(6);
}
@ -1096,7 +1096,7 @@ static int CmdEMVExec(const char *Cmd) {
res = EMVAC(channel, true, (TrType == TT_CDA) ? EMVAC_TC + EMVAC_CDAREQ : EMVAC_TC, (uint8_t *)cdol_data_tlv->value, cdol_data_tlv->len, buf, sizeof(buf), &len, &sw, tlvRoot);
if (res) {
PrintAndLogEx(NORMAL, "AC1 error(%d): %4x. Exit...", res, sw);
PrintAndLogEx(ERR, "AC1 error(%d): %4x. Exit...", res, sw);
dreturn(7);
}
@ -1175,7 +1175,7 @@ static int CmdEMVExec(const char *Cmd) {
struct tlv *udol_data_tlv = dol_process(UDOL ? UDOL : &defUDOL, tlvRoot, 0x01); // 0x01 - dummy tag
if (!udol_data_tlv) {
PrintAndLogEx(WARNING, "Error: can't create UDOL TLV.");
PrintAndLogEx(ERR, "Error: can't create UDOL TLV.");
dreturn(8);
}
@ -1185,7 +1185,7 @@ static int CmdEMVExec(const char *Cmd) {
res = MSCComputeCryptoChecksum(channel, true, (uint8_t *)udol_data_tlv->value, udol_data_tlv->len, buf, sizeof(buf), &len, &sw, tlvRoot);
if (res) {
PrintAndLogEx(WARNING, "Error Compute Crypto Checksum. APDU error %4x", sw);
PrintAndLogEx(ERR, "Error Compute Crypto Checksum. APDU error %4x", sw);
free(udol_data_tlv);
dreturn(9);
}
@ -1198,7 +1198,7 @@ static int CmdEMVExec(const char *Cmd) {
}
} else {
PrintAndLogEx(WARNING, "Error MSD: Track2 data not found.");
PrintAndLogEx(ERR, "Error MSD: Track2 data not found.");
}
}
@ -1209,7 +1209,7 @@ static int CmdEMVExec(const char *Cmd) {
PrintAndLogEx(NORMAL, "* * Calc CDOL1");
struct tlv *cdol1_data_tlv = dol_process(tlvdb_get(tlvRoot, 0x8c, NULL), tlvRoot, 0x01); // 0x01 - dummy tag
if (!cdol1_data_tlv) {
PrintAndLogEx(WARNING, "Error: can't create CDOL1 TLV.");
PrintAndLogEx(ERR, "Error: can't create CDOL1 TLV.");
dreturn(6);
}
@ -1220,7 +1220,7 @@ static int CmdEMVExec(const char *Cmd) {
res = EMVAC(channel, true, (TrType == TT_CDA) ? EMVAC_TC + EMVAC_CDAREQ : EMVAC_TC, (uint8_t *)cdol1_data_tlv->value, cdol1_data_tlv->len, buf, sizeof(buf), &len, &sw, tlvRoot);
if (res) {
PrintAndLogEx(NORMAL, "AC1 error(%d): %4x. Exit...", res, sw);
PrintAndLogEx(ERR, "AC1 error(%d): %4x. Exit...", res, sw);
free(cdol1_data_tlv);
dreturn(7);
}
@ -1232,7 +1232,7 @@ static int CmdEMVExec(const char *Cmd) {
tlvdb_get_uint8(tlvRoot, 0x9f27, &CID);
// AC1 print result
PrintAndLog("");
PrintAndLogEx(NORMAL, "");
if ((CID & EMVAC_AC_MASK) == EMVAC_AAC) PrintAndLogEx(INFO, "AC1 result: AAC (Transaction declined)");
if ((CID & EMVAC_AC_MASK) == EMVAC_TC) PrintAndLogEx(INFO, "AC1 result: TC (Transaction approved)");
if ((CID & EMVAC_AC_MASK) == EMVAC_ARQC) PrintAndLogEx(INFO, "AC1 result: ARQC (Online authorisation requested)");
@ -1264,13 +1264,13 @@ static int CmdEMVExec(const char *Cmd) {
PrintAndLogEx(NORMAL, "CVR length: %d", CVRlen);
PrintAndLogEx(NORMAL, "CVR: %s", sprint_hex(&IAD->value[4], CVRlen));
} else {
PrintAndLogEx(NORMAL, "Wrong CVR length! CVR: %s", sprint_hex(&IAD->value[3], VDDlen - 2));
PrintAndLogEx(WARNING, "Wrong CVR length! CVR: %s", sprint_hex(&IAD->value[3], VDDlen - 2));
}
}
if (IDDlen)
PrintAndLogEx(NORMAL, "IDD: %s", sprint_hex(&IAD->value[VDDlen + 1], IDDlen));
} else {
PrintAndLogEx(NORMAL, "Issuer Application Data (IAD) not found.");
PrintAndLogEx(WARNING, "Issuer Application Data (IAD) not found.");
}
PrintAndLogEx(NORMAL, "\n* * Processing online request");
@ -1278,7 +1278,9 @@ static int CmdEMVExec(const char *Cmd) {
// authorization response code from acquirer
const char HostResponse[] = "00"; // 0x3030
size_t HostResponseLen = sizeof(HostResponse) - 1;
PrintAndLogEx(NORMAL, "Host Response: `%s`", HostResponse);
tlvdb_change_or_add_node(tlvRoot, 0x8a, HostResponseLen, (const unsigned char *)HostResponse);
if (CryptoVersion == 10) {
@ -1300,30 +1302,23 @@ static int CmdEMVExec(const char *Cmd) {
PrintAndLogEx(NORMAL, "ARPC: n/a");
} else {
PrintAndLogEx(NORMAL, "Application Cryptogram (AC) not found.");
PrintAndLogEx(WARNING, "Application Cryptogram (AC) not found.");
}
// here must be external authenticate, but we dont know ARPC
}
// needs to send AC2 command (res == ARQC)
if ((CID & EMVAC_AC_MASK) == EMVAC_ARQC) {
PrintAndLogEx(NORMAL, "\n* * Calc CDOL2");
struct tlv *cdol2_data_tlv = dol_process(tlvdb_get(tlvRoot, 0x8d, NULL), tlvRoot, 0x01); // 0x01 - dummy tag
if (!cdol2_data_tlv) {
PrintAndLogEx(WARNING, "Error: can't create CDOL2 TLV.");
PrintAndLogEx(ERR, "Error: can't create CDOL2 TLV.");
dreturn(6);
}
PrintAndLogEx(NORMAL, "CDOL2 data[%d]: %s", cdol2_data_tlv->len, sprint_hex(cdol2_data_tlv->value, cdol2_data_tlv->len));
//PrintAndLogEx(NORMAL, "* * AC2");
// here must be AC2, but we dont make external authenticate (
/* // AC2
PRINT_INDENT(level);
if ((CID & EMVAC_AC2_MASK) == EMVAC_AAC2) fprintf(f, "\tAC2: AAC (Transaction declined)\n");
@ -1332,7 +1327,6 @@ static int CmdEMVExec(const char *Cmd) {
if ((CID & EMVAC_AC2_MASK) == EMVAC_AC2_MASK) fprintf(f, "\tAC2: RFU\n");
*/
}
}
DropFieldEx(channel);
@ -1409,7 +1403,7 @@ static int CmdEMVScan(const char *Cmd) {
#ifndef WITH_SMARTCARD
// not compiled with smartcard functionality, we need to exit
if (channel == ECC_CONTACT) {
PrintAndLogEx(WARNING, "PM3 Client is not compiled with support for SMARTCARD. Exiting.");
PrintAndLogEx(ERR, "PM3 Client is not compiled with support for SMARTCARD. Exiting.");
return 0;
}
#endif
@ -1652,7 +1646,7 @@ static int CmdEMVScan(const char *Cmd) {
if (decodeTLV) {
TLVPrintFromBuffer(buf, len);
PrintAndLog("");
PrintAndLogEx(NORMAL, "");
}
json_t *jsonelm = json_object();
@ -1692,7 +1686,7 @@ static int CmdEMVScan(const char *Cmd) {
PrintAndLogEx(ERR, "Can't save the file: %s", fname);
return 200;
}
PrintAndLogEx(SUCCESS, "File `%s` saved.", fname);
PrintAndLogEx(SUCCESS, "File " _YELLOW_("`%s`") " saved.", fname);
// free json object
json_decref(root);
@ -1807,7 +1801,7 @@ static int CmdEMVRoca(const char *Cmd) {
return 5;
}
PrintAndLog("\n* Init transaction parameters.");
PrintAndLogEx(NORMAL, "\n* Init transaction parameters.");
InitTransactionParameters(tlvRoot, true, TT_QVSDCMCHIP, false);
PrintAndLogEx(NORMAL, "-->Calc PDOL.");

View file

@ -253,20 +253,29 @@ static size_t crypto_pk_polarssl_get_nbits(const struct crypto_pk *_cp) {
static unsigned char *crypto_pk_polarssl_get_parameter(const struct crypto_pk *_cp, unsigned param, size_t *plen) {
struct crypto_pk_polarssl *cp = (struct crypto_pk_polarssl *)_cp;
unsigned char *result = NULL;
int res;
switch (param) {
// mod
case 0:
*plen = mbedtls_mpi_size(&cp->ctx.N);
result = malloc(*plen);
memset(result, 0x00, *plen);
mbedtls_mpi_write_binary(&cp->ctx.N, result, *plen);
res = mbedtls_mpi_write_binary(&cp->ctx.N, result, *plen);
if (res < 0) {
printf("Error write_binary.");
result = 0;
}
break;
// exp
case 1:
*plen = mbedtls_mpi_size(&cp->ctx.E);
result = malloc(*plen);
memset(result, 0x00, *plen);
mbedtls_mpi_write_binary(&cp->ctx.E, result, *plen);
res = mbedtls_mpi_write_binary(&cp->ctx.E, result, *plen);
if (res < 0) {
printf("Error write_binary.");
result = 0;
}
break;
default:
printf("Error get parameter. Param = %u", param);

View file

@ -75,7 +75,7 @@ int JsonSaveJsonObject(json_t *root, const char *path, json_t *value) {
if (path[0] == '$') {
if (json_path_set(root, path, value, 0, &error)) {
PrintAndLog("ERROR: can't set json path: ", error.text);
PrintAndLogEx(ERR, "ERROR: can't set json path: ", error.text);
return 2;
} else {
return 0;
@ -151,12 +151,12 @@ int JsonSaveTLVElm(json_t *elm, const char *path, struct tlv *tlvelm, bool saveN
if (json_is_array(elm)) {
if (json_array_append_new(elm, obj)) {
PrintAndLog("ERROR: can't append array: %s", path);
PrintAndLogEx(ERR, "ERROR: can't append array: %s", path);
return 2;
}
} else {
if (json_path_set(elm, path, obj, 0, &error)) {
PrintAndLog("ERROR: can't set json path: ", error.text);
PrintAndLogEx(ERR, "ERROR: can't set json path: ", error.text);
return 2;
}
}
@ -225,7 +225,7 @@ int JsonSaveTLVTree(json_t *root, json_t *elm, const char *path, struct tlvdb *t
// check
if (!json_is_array(chjson)) {
PrintAndLog("E->Internal logic error. `$.Childs` is not an array.");
PrintAndLogEx(ERR, "E->Internal logic error. `$.Childs` is not an array.");
break;
}
@ -243,18 +243,18 @@ static bool HexToBuffer(const char *errormsg, const char *hexvalue, uint8_t *buf
switch (param_gethex_to_eol(hexvalue, 0, buffer, maxbufferlen, &buflen)) {
case 1:
PrintAndLog("%s Invalid HEX value.", errormsg);
PrintAndLogEx(ERR, "%s Invalid HEX value.", errormsg);
return false;
case 2:
PrintAndLog("%s Hex value too large.", errormsg);
PrintAndLogEx(ERR, "%s Hex value too large.", errormsg);
return false;
case 3:
PrintAndLog("%s Hex value must have even number of digits.", errormsg);
PrintAndLogEx(ERR, "%s Hex value must have even number of digits.", errormsg);
return false;
}
if (buflen > maxbufferlen) {
PrintAndLog("%s HEX length (%d) more than %d", errormsg, (bufferlen) ? *bufferlen : -1, maxbufferlen);
PrintAndLogEx(ERR, "%s HEX length (%d) more than %d", errormsg, (bufferlen) ? *bufferlen : -1, maxbufferlen);
return false;
}
@ -300,7 +300,7 @@ bool ParamLoadFromJson(struct tlvdb *tlv) {
json_error_t error;
if (!tlv) {
PrintAndLog("ERROR load params: tlv tree is NULL.");
PrintAndLogEx(ERR, "ERROR load params: tlv tree is NULL.");
return false;
}
@ -312,30 +312,30 @@ bool ParamLoadFromJson(struct tlvdb *tlv) {
root = json_load_file(fname, 0, &error);
if (!root) {
PrintAndLog("Load params: json error on line %d: %s", error.line, error.text);
PrintAndLogEx(ERR, "Load params: json error on line " _YELLOW_("%d") ": %s", error.line, error.text);
return false;
}
if (!json_is_array(root)) {
PrintAndLog("Load params: Invalid json format. root must be array.");
PrintAndLogEx(ERR, "Load params: Invalid json format. root must be array.");
return false;
}
PrintAndLog("Load params: json(%d) OK", json_array_size(root));
PrintAndLogEx(SUCCESS, "Load params: json(%d) " _GREEN_("OK"), json_array_size(root));
for (int i = 0; i < json_array_size(root); i++) {
json_t *data, *jtag, *jlength, *jvalue;
data = json_array_get(root, i);
if (!json_is_object(data)) {
PrintAndLog("Load params: data [%d] is not an object", i + 1);
PrintAndLogEx(ERR, "Load params: data [%d] is not an object", i + 1);
json_decref(root);
return false;
}
jtag = json_object_get(data, "tag");
if (!json_is_string(jtag)) {
PrintAndLog("Load params: data [%d] tag is not a string", i + 1);
PrintAndLogEx(ERR, "Load params: data [%d] tag is not a string", i + 1);
json_decref(root);
return false;
}
@ -343,7 +343,7 @@ bool ParamLoadFromJson(struct tlvdb *tlv) {
jvalue = json_object_get(data, "value");
if (!json_is_string(jvalue)) {
PrintAndLog("Load params: data [%d] value is not a string", i + 1);
PrintAndLogEx(ERR, "Load params: data [%d] value is not a string", i + 1);
json_decref(root);
return false;
}
@ -351,19 +351,19 @@ bool ParamLoadFromJson(struct tlvdb *tlv) {
jlength = json_object_get(data, "length");
if (!json_is_number(jlength)) {
PrintAndLog("Load params: data [%d] length is not a number", i + 1);
PrintAndLogEx(ERR, "Load params: data [%d] length is not a number", i + 1);
json_decref(root);
return false;
}
int tlvLength = json_integer_value(jlength);
if (tlvLength > 250) {
PrintAndLog("Load params: data [%d] length more than 250", i + 1);
PrintAndLogEx(ERR, "Load params: data [%d] length more than 250", i + 1);
json_decref(root);
return false;
}
PrintAndLog("TLV param: %s[%d]=%s", tlvTag, tlvLength, tlvValue);
PrintAndLogEx(SUCCESS, "TLV param: %s[%d]=%s", tlvTag, tlvLength, tlvValue);
uint8_t buf[251] = {0};
size_t buflen = 0;
@ -382,7 +382,7 @@ bool ParamLoadFromJson(struct tlvdb *tlv) {
}
if (buflen != tlvLength) {
PrintAndLog("Load params: data [%d] length of HEX must(%d) be identical to length in TLV param(%d)", i + 1, buflen, tlvLength);
PrintAndLogEx(ERR, "Load params: data [%d] length of HEX must(%d) be identical to length in TLV param(%d)", i + 1, buflen, tlvLength);
json_decref(root);
return false;
}

View file

@ -162,16 +162,16 @@ int COSEGetECDSAKey(uint8_t *data, size_t datalen, bool verbose, uint8_t *public
size_t len;
if (verbose)
PrintAndLog("----------- CBOR decode ----------------");
PrintAndLogEx(NORMAL, "----------- CBOR decode ----------------");
// kty
int res = CborMapGetKeyById(&parser, &map, data, datalen, 1);
if (!res) {
cbor_value_get_int64(&map, &i64);
if (verbose)
PrintAndLog("kty [%lld] %s", (long long)i64, GetCOSEktyDescription(i64));
PrintAndLogEx(SUCCESS, "kty [%lld] %s", (long long)i64, GetCOSEktyDescription(i64));
if (i64 != 2)
PrintAndLog("ERROR: kty must be 2.");
PrintAndLogEx(ERR, "ERROR: kty must be 2.");
}
// algorithm
@ -179,9 +179,9 @@ int COSEGetECDSAKey(uint8_t *data, size_t datalen, bool verbose, uint8_t *public
if (!res) {
cbor_value_get_int64(&map, &i64);
if (verbose)
PrintAndLog("algorithm [%lld] %s", (long long)i64, GetCOSEAlgDescription(i64));
PrintAndLogEx(SUCCESS, "algorithm [%lld] %s", (long long)i64, GetCOSEAlgDescription(i64));
if (i64 != -7)
PrintAndLog("ERROR: algorithm must be -7.");
PrintAndLogEx(ERR, "ERROR: algorithm must be -7.");
}
// curve
@ -189,9 +189,9 @@ int COSEGetECDSAKey(uint8_t *data, size_t datalen, bool verbose, uint8_t *public
if (!res) {
cbor_value_get_int64(&map, &i64);
if (verbose)
PrintAndLog("curve [%lld] %s", (long long)i64, GetCOSECurveDescription(i64));
PrintAndLogEx(SUCCESS, "curve [%lld] %s", (long long)i64, GetCOSECurveDescription(i64));
if (i64 != 1)
PrintAndLog("ERROR: curve must be 1.");
PrintAndLogEx(ERR, "ERROR: curve must be 1.");
}
// plain key
@ -203,9 +203,9 @@ int COSEGetECDSAKey(uint8_t *data, size_t datalen, bool verbose, uint8_t *public
res = CborGetBinStringValue(&map, &public_key[1], 32, &len);
cbor_check(res);
if (verbose)
PrintAndLog("x - coordinate [%d]: %s", len, sprint_hex(&public_key[1], 32));
PrintAndLogEx(SUCCESS, "x - coordinate [%d]: %s", len, sprint_hex(&public_key[1], 32));
if (len != 32)
PrintAndLog("ERROR: x - coordinate length must be 32.");
PrintAndLogEx(ERR, "ERROR: x - coordinate length must be 32.");
}
// y - coordinate
@ -214,9 +214,9 @@ int COSEGetECDSAKey(uint8_t *data, size_t datalen, bool verbose, uint8_t *public
res = CborGetBinStringValue(&map, &public_key[33], 32, &len);
cbor_check(res);
if (verbose)
PrintAndLog("y - coordinate [%d]: %s", len, sprint_hex(&public_key[33], 32));
PrintAndLogEx(SUCCESS, "y - coordinate [%d]: %s", len, sprint_hex(&public_key[33], 32));
if (len != 32)
PrintAndLog("ERROR: y - coordinate length must be 32.");
PrintAndLogEx(ERR, "ERROR: y - coordinate length must be 32.");
}
// d - private key
@ -226,11 +226,11 @@ int COSEGetECDSAKey(uint8_t *data, size_t datalen, bool verbose, uint8_t *public
res = CborGetBinStringValue(&map, private_key, sizeof(private_key), &len);
cbor_check(res);
if (verbose)
PrintAndLog("d - private key [%d]: %s", len, sprint_hex(private_key, len));
PrintAndLogEx(SUCCESS, "d - private key [%d]: %s", len, sprint_hex(private_key, len));
}
if (verbose)
PrintAndLog("----------- CBOR decode ----------------");
PrintAndLogEx(NORMAL, "----------- CBOR decode ----------------");
return 0;
}

View file

@ -226,52 +226,52 @@ int FIDOCheckDERAndGetKey(uint8_t *der, size_t derLen, bool verbose, uint8_t *pu
mbedtls_x509_crt_init(&cacert);
res = mbedtls_x509_crt_parse(&cacert, (const unsigned char *) additional_ca_pem, additional_ca_pem_len);
if (res < 0) {
PrintAndLog("ERROR: CA parse certificate returned -0x%x - %s", -res, ecdsa_get_error(res));
PrintAndLogEx(ERR, "ERROR: CA parse certificate returned -0x%x - %s", -res, ecdsa_get_error(res));
}
if (verbose)
PrintAndLog("CA load OK. %d skipped", res);
PrintAndLogEx(SUCCESS, "CA load OK. %d skipped", res);
// load DER certificate from authenticator's data
mbedtls_x509_crt cert;
mbedtls_x509_crt_init(&cert);
res = mbedtls_x509_crt_parse_der(&cert, der, derLen);
if (res) {
PrintAndLog("ERROR: DER parse returned 0x%x - %s", (res < 0) ? -res : res, ecdsa_get_error(res));
PrintAndLogEx(ERR, "ERROR: DER parse returned 0x%x - %s", (res < 0) ? -res : res, ecdsa_get_error(res));
}
// get certificate info
char linfo[300] = {0};
if (verbose) {
mbedtls_x509_crt_info(linfo, sizeof(linfo), " ", &cert);
PrintAndLog("DER certificate info:\n%s", linfo);
PrintAndLogEx(SUCCESS, "DER certificate info:\n%s", linfo);
}
// verify certificate
uint32_t verifyflags = 0;
res = mbedtls_x509_crt_verify(&cert, &cacert, NULL, NULL, &verifyflags, NULL, NULL);
if (res) {
PrintAndLog("ERROR: DER verify returned 0x%x - %s\n", (res < 0) ? -res : res, ecdsa_get_error(res));
PrintAndLogEx(ERR, "ERROR: DER verify returned 0x%x - %s\n", (res < 0) ? -res : res, ecdsa_get_error(res));
} else {
PrintAndLog("Certificate OK.\n");
PrintAndLogEx(SUCCESS, "Certificate OK.\n");
}
if (verbose) {
memset(linfo, 0x00, sizeof(linfo));
mbedtls_x509_crt_verify_info(linfo, sizeof(linfo), " ", verifyflags);
PrintAndLog("Verification info:\n%s", linfo);
PrintAndLogEx(SUCCESS, "Verification info:\n%s", linfo);
}
// get public key
res = ecdsa_public_key_from_pk(&cert.pk, publicKey, publicKeyMaxLen);
if (res) {
PrintAndLog("ERROR: getting public key from certificate 0x%x - %s", (res < 0) ? -res : res, ecdsa_get_error(res));
PrintAndLogEx(ERR, "ERROR: getting public key from certificate 0x%x - %s", (res < 0) ? -res : res, ecdsa_get_error(res));
} else {
if (verbose)
PrintAndLog("Got a public key from certificate:\n%s", sprint_hex_inrow(publicKey, 65));
PrintAndLogEx(SUCCESS, "Got a public key from certificate:\n%s", sprint_hex_inrow(publicKey, 65));
}
if (verbose)
PrintAndLog("------------------DER-------------------");
PrintAndLogEx(NORMAL, "------------------DER-------------------");
mbedtls_x509_crt_free(&cert);
mbedtls_x509_crt_free(&cacert);
@ -362,15 +362,15 @@ static int FIDO2CheckSignature(json_t *root, uint8_t *publickey, uint8_t *sign,
res = ecdsa_asn1_get_signature(sign, signLen, rval, sval);
if (!res) {
if (verbose) {
PrintAndLog(" r: %s", sprint_hex(rval, 32));
PrintAndLog(" s: %s", sprint_hex(sval, 32));
PrintAndLogEx(NORMAL, " r: %s", sprint_hex(rval, 32));
PrintAndLogEx(NORMAL, " s: %s", sprint_hex(sval, 32));
}
uint8_t clientDataHash[32] = {0};
size_t clientDataHashLen = 0;
res = JsonLoadBufAsHex(root, "$.ClientDataHash", clientDataHash, sizeof(clientDataHash), &clientDataHashLen);
if (res || clientDataHashLen != 32) {
PrintAndLog("ERROR: Can't get clientDataHash from json!");
PrintAndLogEx(ERR, "ERROR: Can't get clientDataHash from json!");
return 2;
}
@ -380,20 +380,20 @@ static int FIDO2CheckSignature(json_t *root, uint8_t *publickey, uint8_t *sign,
authData, authDataLen, // rpIdHash[32] + flags[1] + signCount[4]
clientDataHash, 32, // Hash of the serialized client data. "$.ClientDataHash" from json
NULL, 0);
//PrintAndLog("--xbuf(%d)[%d]: %s", res, xbuflen, sprint_hex(xbuf, xbuflen));
//PrintAndLogEx(NORMAL, "--xbuf(%d)[%d]: %s", res, xbuflen, sprint_hex(xbuf, xbuflen));
res = ecdsa_signature_verify(publickey, xbuf, xbuflen, sign, signLen);
if (res) {
if (res == -0x4e00) {
PrintAndLog("Signature is NOT VALID.");
PrintAndLogEx(WARNING, "Signature is NOT VALID.");
} else {
PrintAndLog("Other signature check error: %x %s", (res < 0) ? -res : res, ecdsa_get_error(res));
PrintAndLogEx(WARNING, "Other signature check error: %x %s", (res < 0) ? -res : res, ecdsa_get_error(res));
}
return res;
} else {
PrintAndLog("Signature is OK.");
PrintAndLogEx(SUCCESS, "Signature is OK.");
}
} else {
PrintAndLog("Invalid signature. res=%d.", res);
PrintAndLogEx(ERR, "Invalid signature. res = %d.", res);
return res;
}
@ -415,7 +415,7 @@ int FIDO2MakeCredentionalParseRes(json_t *root, uint8_t *data, size_t dataLen, b
res = cbor_value_dup_text_string(&map, &buf, &n, &map);
cbor_check(res);
PrintAndLog("format: %s", buf);
PrintAndLogEx(INFO, "format: %s", buf);
free(buf);
// authData
@ -431,43 +431,43 @@ int FIDO2MakeCredentionalParseRes(json_t *root, uint8_t *data, size_t dataLen, b
memcpy(authData, ubuf, authDataLen);
if (verbose2) {
PrintAndLog("authData[%d]: %s", n, sprint_hex_inrow(authData, authDataLen));
PrintAndLogEx(INFO, "authData[%d]: %s", n, sprint_hex_inrow(authData, authDataLen));
} else {
PrintAndLog("authData[%d]: %s...", n, sprint_hex(authData, MIN(authDataLen, 16)));
PrintAndLogEx(INFO, "authData[%d]: %s...", n, sprint_hex(authData, MIN(authDataLen, 16)));
}
PrintAndLog("RP ID Hash: %s", sprint_hex(ubuf, 32));
PrintAndLogEx(INFO, "RP ID Hash: %s", sprint_hex(ubuf, 32));
// check RP ID Hash
if (CheckrpIdHash(root, ubuf)) {
PrintAndLog("rpIdHash OK.");
PrintAndLogEx(SUCCESS, "rpIdHash OK.");
} else {
PrintAndLog("rpIdHash ERROR!");
PrintAndLogEx(ERR, "rpIdHash ERROR!");
}
PrintAndLog("Flags 0x%02x:", ubuf[32]);
PrintAndLogEx(INFO, "Flags 0x%02x:", ubuf[32]);
if (!ubuf[32])
PrintAndLog("none");
PrintAndLogEx(SUCCESS, "none");
if (ubuf[32] & 0x01)
PrintAndLog("up - user presence result");
PrintAndLogEx(SUCCESS, "up - user presence result");
if (ubuf[32] & 0x04)
PrintAndLog("uv - user verification (fingerprint scan or a PIN or ...) result");
PrintAndLogEx(SUCCESS, "uv - user verification (fingerprint scan or a PIN or ...) result");
if (ubuf[32] & 0x40)
PrintAndLog("at - attested credential data included");
PrintAndLogEx(SUCCESS, "at - attested credential data included");
if (ubuf[32] & 0x80)
PrintAndLog("ed - extension data included");
PrintAndLogEx(SUCCESS, "ed - extension data included");
uint32_t cntr = (uint32_t)bytes_to_num(&ubuf[33], 4);
PrintAndLog("Counter: %d", cntr);
PrintAndLogEx(SUCCESS, "Counter: %d", cntr);
JsonSaveInt(root, "$.AppData.Counter", cntr);
// attestation data
PrintAndLog("AAGUID: %s", sprint_hex(&ubuf[37], 16));
PrintAndLogEx(SUCCESS, "AAGUID: %s", sprint_hex(&ubuf[37], 16));
JsonSaveBufAsHexCompact(root, "$.AppData.AAGUID", &ubuf[37], 16);
// Credential ID
uint8_t cridlen = (uint16_t)bytes_to_num(&ubuf[53], 2);
PrintAndLog("Credential id[%d]: %s", cridlen, sprint_hex_inrow(&ubuf[55], cridlen));
PrintAndLogEx(SUCCESS, "Credential id[%d]: %s", cridlen, sprint_hex_inrow(&ubuf[55], cridlen));
JsonSaveInt(root, "$.AppData.CredentialIdLen", cridlen);
JsonSaveBufAsHexCompact(root, "$.AppData.CredentialId", &ubuf[55], cridlen);
@ -475,24 +475,24 @@ int FIDO2MakeCredentionalParseRes(json_t *root, uint8_t *data, size_t dataLen, b
uint8_t coseKey[65] = {0};
uint16_t cplen = n - 55 - cridlen;
if (verbose2) {
PrintAndLog("Credentional public key (COSE_KEY)[%d]: %s", cplen, sprint_hex_inrow(&ubuf[55 + cridlen], cplen));
PrintAndLogEx(SUCCESS, "Credentional public key (COSE_KEY)[%d]: %s", cplen, sprint_hex_inrow(&ubuf[55 + cridlen], cplen));
} else {
PrintAndLog("Credentional public key (COSE_KEY)[%d]: %s...", cplen, sprint_hex(&ubuf[55 + cridlen], MIN(cplen, 16)));
PrintAndLogEx(SUCCESS, "Credentional public key (COSE_KEY)[%d]: %s...", cplen, sprint_hex(&ubuf[55 + cridlen], MIN(cplen, 16)));
}
JsonSaveBufAsHexCompact(root, "$.AppData.COSE_KEY", &ubuf[55 + cridlen], cplen);
if (showCBOR) {
PrintAndLog("COSE structure:");
PrintAndLog("---------------- CBOR ------------------");
PrintAndLogEx(INFO, "COSE structure:");
PrintAndLogEx(NORMAL, "---------------- CBOR ------------------");
TinyCborPrintFIDOPackage(fido2COSEKey, true, &ubuf[55 + cridlen], cplen);
PrintAndLog("---------------- CBOR ------------------");
PrintAndLogEx(NORMAL, "---------------- CBOR ------------------");
}
res = COSEGetECDSAKey(&ubuf[55 + cridlen], cplen, verbose, coseKey);
if (res) {
PrintAndLog("ERROR: Can't get COSE_KEY.");
PrintAndLogEx(ERR, "ERROR: Can't get COSE_KEY.");
} else {
PrintAndLog("COSE public key: %s", sprint_hex_inrow(coseKey, sizeof(coseKey)));
PrintAndLogEx(SUCCESS, "COSE public key: %s", sprint_hex_inrow(coseKey, sizeof(coseKey)));
JsonSaveBufAsHexCompact(root, "$.AppData.COSEPublicKey", coseKey, sizeof(coseKey));
}
@ -518,7 +518,7 @@ int FIDO2MakeCredentionalParseRes(json_t *root, uint8_t *data, size_t dataLen, b
cbor_check(res);
if (!strcmp(key, "alg")) {
cbor_value_get_int64(&mapsmt, &alg);
PrintAndLog("Alg [%lld] %s", (long long)alg, GetCOSEAlgDescription(alg));
PrintAndLogEx(INFO, "Alg [%lld] %s", (long long)alg, GetCOSEAlgDescription(alg));
res = cbor_value_advance_fixed(&mapsmt);
cbor_check(res);
}
@ -527,9 +527,9 @@ int FIDO2MakeCredentionalParseRes(json_t *root, uint8_t *data, size_t dataLen, b
res = CborGetBinStringValue(&mapsmt, sign, sizeof(sign), &signLen);
cbor_check(res);
if (verbose2) {
PrintAndLog("signature [%d]: %s", signLen, sprint_hex_inrow(sign, signLen));
PrintAndLogEx(INFO, "signature [%d]: %s", signLen, sprint_hex_inrow(sign, signLen));
} else {
PrintAndLog("signature [%d]: %s...", signLen, sprint_hex(sign, MIN(signLen, 16)));
PrintAndLogEx(INFO, "signature [%d]: %s...", signLen, sprint_hex(sign, MIN(signLen, 16)));
}
}
@ -537,11 +537,11 @@ int FIDO2MakeCredentionalParseRes(json_t *root, uint8_t *data, size_t dataLen, b
res = CborGetArrayBinStringValue(&mapsmt, der, sizeof(der), &derLen);
cbor_check(res);
if (verbose2) {
PrintAndLog("DER certificate[%d]:\n------------------DER-------------------", derLen);
PrintAndLogEx(NORMAL, "DER certificate[%d]:\n------------------DER-------------------", derLen);
dump_buffer_simple((const unsigned char *)der, derLen, NULL);
PrintAndLog("\n----------------DER---------------------");
PrintAndLogEx(NORMAL, "\n----------------DER---------------------");
} else {
PrintAndLog("DER [%d]: %s...", derLen, sprint_hex(der, MIN(derLen, 16)));
PrintAndLogEx(NORMAL, "DER [%d]: %s...", derLen, sprint_hex(der, MIN(derLen, 16)));
}
JsonSaveBufAsHexCompact(root, "$.AppData.DER", der, derLen);
}
@ -553,9 +553,9 @@ int FIDO2MakeCredentionalParseRes(json_t *root, uint8_t *data, size_t dataLen, b
// print DER certificate in TLV view
if (showDERTLV) {
PrintAndLog("----------------DER TLV-----------------");
PrintAndLogEx(NORMAL, "----------------DER TLV-----------------");
asn1_print(der, derLen, " ");
PrintAndLog("----------------DER TLV-----------------");
PrintAndLogEx(NORMAL, "----------------DER TLV-----------------");
}
FIDOCheckDERAndGetKey(der, derLen, verbose, public_key, sizeof(public_key));
JsonSaveBufAsHexCompact(root, "$.AppData.DERPublicKey", public_key, sizeof(public_key));
@ -664,14 +664,14 @@ int FIDO2GetAssertionParseRes(json_t *root, uint8_t *data, size_t dataLen, bool
char ctype[200] = {0};
res = CborGetStringValue(&mapint, ctype, sizeof(ctype), &n);
cbor_check(res);
PrintAndLog("credential type: %s", ctype);
PrintAndLogEx(SUCCESS, "credential type: %s", ctype);
}
if (!strcmp(key, "id")) {
uint8_t cid[200] = {0};
res = CborGetBinStringValue(&mapint, cid, sizeof(cid), &n);
cbor_check(res);
PrintAndLog("credential id [%d]: %s", n, sprint_hex(cid, n));
PrintAndLogEx(SUCCESS, "credential id [%d]: %s", n, sprint_hex(cid, n));
}
}
res = cbor_value_leave_container(&map, &mapint);
@ -690,34 +690,34 @@ int FIDO2GetAssertionParseRes(json_t *root, uint8_t *data, size_t dataLen, bool
memcpy(authData, ubuf, authDataLen);
if (verbose2) {
PrintAndLog("authData[%d]: %s", n, sprint_hex_inrow(authData, authDataLen));
PrintAndLogEx(INFO, "authData[%d]: %s", n, sprint_hex_inrow(authData, authDataLen));
} else {
PrintAndLog("authData[%d]: %s...", n, sprint_hex(authData, MIN(authDataLen, 16)));
PrintAndLogEx(INFO, "authData[%d]: %s...", n, sprint_hex(authData, MIN(authDataLen, 16)));
}
PrintAndLog("RP ID Hash: %s", sprint_hex(ubuf, 32));
PrintAndLogEx(INFO, "RP ID Hash: %s", sprint_hex(ubuf, 32));
// check RP ID Hash
if (CheckrpIdHash(root, ubuf)) {
PrintAndLog("rpIdHash OK.");
PrintAndLogEx(SUCCESS, "rpIdHash OK.");
} else {
PrintAndLog("rpIdHash ERROR!");
PrintAndLogEx(ERR, "rpIdHash ERROR!");
}
PrintAndLog("Flags 0x%02x:", ubuf[32]);
PrintAndLogEx(INFO, "Flags 0x%02x:", ubuf[32]);
if (!ubuf[32])
PrintAndLog("none");
PrintAndLogEx(SUCCESS, "none");
if (ubuf[32] & 0x01)
PrintAndLog("up - user presence result");
PrintAndLogEx(SUCCESS, "up - user presence result");
if (ubuf[32] & 0x04)
PrintAndLog("uv - user verification (fingerprint scan or a PIN or ...) result");
PrintAndLogEx(SUCCESS, "uv - user verification (fingerprint scan or a PIN or ...) result");
if (ubuf[32] & 0x40)
PrintAndLog("at - attested credential data included");
PrintAndLogEx(SUCCESS, "at - attested credential data included");
if (ubuf[32] & 0x80)
PrintAndLog("ed - extension data included");
PrintAndLogEx(SUCCESS, "ed - extension data included");
uint32_t cntr = (uint32_t)bytes_to_num(&ubuf[33], 4);
PrintAndLog("Counter: %d", cntr);
PrintAndLogEx(SUCCESS, "Counter: %d", cntr);
JsonSaveInt(root, "$.AppData.Counter", cntr);
free(ubuf);
@ -725,7 +725,7 @@ int FIDO2GetAssertionParseRes(json_t *root, uint8_t *data, size_t dataLen, bool
// publicKeyCredentialUserEntity
res = CborMapGetKeyById(&parser, &map, data, dataLen, 4);
if (res) {
PrintAndLog("UserEntity n/a");
PrintAndLogEx(SUCCESS, "UserEntity n/a");
} else {
res = cbor_value_enter_container(&map, &mapint);
cbor_check(res);
@ -739,14 +739,14 @@ int FIDO2GetAssertionParseRes(json_t *root, uint8_t *data, size_t dataLen, bool
char cname[200] = {0};
res = CborGetStringValue(&mapint, cname, sizeof(cname), &n);
cbor_check(res);
PrintAndLog("UserEntity %s: %s", key, cname);
PrintAndLogEx(SUCCESS, "UserEntity %s: %s", key, cname);
}
if (!strcmp(key, "id")) {
uint8_t cid[200] = {0};
res = CborGetBinStringValue(&mapint, cid, sizeof(cid), &n);
cbor_check(res);
PrintAndLog("UserEntity id [%d]: %s", n, sprint_hex(cid, n));
PrintAndLogEx(SUCCESS, "UserEntity id [%d]: %s", n, sprint_hex(cid, n));
// check
uint8_t idbuf[100] = {0};
@ -755,9 +755,9 @@ int FIDO2GetAssertionParseRes(json_t *root, uint8_t *data, size_t dataLen, bool
JsonLoadBufAsHex(root, "$.UserEntity.id", idbuf, sizeof(idbuf), &idbuflen);
if (idbuflen == n && !memcmp(idbuf, cid, idbuflen)) {
PrintAndLog("UserEntity id OK.");
PrintAndLogEx(SUCCESS, "UserEntity id OK.");
} else {
PrintAndLog("ERROR: Wrong UserEntity id (from json: %s)", sprint_hex(idbuf, idbuflen));
PrintAndLogEx(ERR, "ERROR: Wrong UserEntity id (from json: %s)", sprint_hex(idbuf, idbuflen));
}
}
}
@ -778,9 +778,9 @@ int FIDO2GetAssertionParseRes(json_t *root, uint8_t *data, size_t dataLen, bool
cbor_check(res);
if (verbose2) {
PrintAndLog("signature [%d]: %s", signLen, sprint_hex_inrow(sign, signLen));
PrintAndLogEx(SUCCESS, "signature [%d]: %s", signLen, sprint_hex_inrow(sign, signLen));
} else {
PrintAndLog("signature [%d]: %s...", signLen, sprint_hex(sign, MIN(signLen, 16)));
PrintAndLogEx(SUCCESS, "signature [%d]: %s...", signLen, sprint_hex(sign, MIN(signLen, 16)));
}
// get public key from json
@ -796,11 +796,11 @@ int FIDO2GetAssertionParseRes(json_t *root, uint8_t *data, size_t dataLen, bool
// numberOfCredentials
res = CborMapGetKeyById(&parser, &map, data, dataLen, 5);
if (res) {
PrintAndLog("numberOfCredentials: 1 by default");
PrintAndLogEx(SUCCESS, "numberOfCredentials: 1 by default");
} else {
int64_t numberOfCredentials = 0;
cbor_value_get_int64(&map, &numberOfCredentials);
PrintAndLog("numberOfCredentials: %lld", (long long)numberOfCredentials);
PrintAndLogEx(SUCCESS, "numberOfCredentials: %lld", (long long)numberOfCredentials);
}
return 0;

View file

@ -22,7 +22,7 @@ void jsonp_error_set_source(json_error_t *error, const char *source) {
length = strlen(source);
if (length < JSON_ERROR_SOURCE_LENGTH) {
strncpy(error->source, source, JSON_ERROR_SOURCE_LENGTH);
strncpy(error->source, source, JSON_ERROR_SOURCE_LENGTH - 1);
} else {
size_t extra = length - JSON_ERROR_SOURCE_LENGTH + 4;
memcpy(error->source, "...", 3);

View file

@ -65,9 +65,15 @@ static RetType write_to_buffer(void *cookie, const char *data, LenType len) {
if (newsize >= b->alloc) { // NB! one extra byte is needed to avoid buffer overflow at close_buffer
// make room
size_t newalloc = newsize + newsize / 2 + 1; // give 50% more room
ptr = realloc(ptr, newalloc);
if (ptr == NULL)
char *tmp = realloc(ptr, newalloc);
if (tmp == NULL) {
free(ptr);
return -1;
} else {
ptr = tmp;
}
b->alloc = newalloc;
*b->ptr = ptr;
}

View file

@ -151,6 +151,7 @@ ISO 7816-4 Basic interindustry commands. For command APDU's.
#define ISO14443A_CMD_WRITEBLOCK 0xA0
#define ISO14443A_CMD_HALT 0x50
#define ISO14443A_CMD_RATS 0xE0
#define ISO14443A_CMD_NXP_DESELECT 0xC2
#define MIFARE_SELECT_CT 0x88
#define MIFARE_AUTH_KEYA 0x60