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... This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log...
## [unreleased][unreleased] ## [unreleased][unreleased]
- Fix/Add 'hf mf sim' bugs fix, RATS support, etc (@mceloff)
- Fix serial of FPC. (@ryan) - Fix serial of FPC. (@ryan)
- Fix 'data shiftgraphzero' corrupting end of GraphBuffer (@doegox) - Fix 'data shiftgraphzero' corrupting end of GraphBuffer (@doegox)
- Fix 'hf legic info' - unsegmented card now uses card size to calc remaining length (@iceman) - 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. 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) [![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 <a href="http://www.youtube.com/watch?feature=player_embedded&v=uyJ-y0kSWfc

View file

@ -160,6 +160,24 @@ build_script:
Copy-Item C:\ProxSpace\pm3\client\hardnested\*.bin C:\ProxSpace\Release\hardnested Copy-Item C:\ProxSpace\pm3\client\hardnested\*.bin C:\ProxSpace\Release\hardnested
Copy-Item C:\ProxSpace\pm3\client\hardnested\tables\*.bin.z C:\ProxSpace\Release\hardnested\tables 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 Write-Host "[ OK ]" -ForegroundColor Green
@ -256,8 +274,8 @@ test_script:
#--- end Job #--- end Job
[bool]$res=$false [bool]$res=$false
# Wait 120 sec timeout for Job # Wait 180 sec timeout for Job
if(Wait-Job $Job -Timeout 150){ if(Wait-Job $Job -Timeout 180){
$Results = $Job | Receive-Job $Results = $Job | Receive-Job
if($Results -like "true"){ if($Results -like "true"){
$res=$true $res=$true

View file

@ -451,23 +451,23 @@ void FpgaWriteConfWord(uint8_t v) {
void SetAdcMuxFor(uint32_t whichGpio) { void SetAdcMuxFor(uint32_t whichGpio) {
#ifndef WITH_FPC #ifndef WITH_FPC
// When compiled without FPC support // When compiled without FPC support
AT91C_BASE_PIOA->PIO_OER = AT91C_BASE_PIOA->PIO_OER =
GPIO_MUXSEL_HIPKD | GPIO_MUXSEL_HIPKD |
GPIO_MUXSEL_LOPKD | GPIO_MUXSEL_LOPKD |
GPIO_MUXSEL_LORAW | GPIO_MUXSEL_LORAW |
GPIO_MUXSEL_HIRAW; GPIO_MUXSEL_HIRAW;
AT91C_BASE_PIOA->PIO_PER = AT91C_BASE_PIOA->PIO_PER =
GPIO_MUXSEL_HIPKD | GPIO_MUXSEL_HIPKD |
GPIO_MUXSEL_LOPKD | GPIO_MUXSEL_LOPKD |
GPIO_MUXSEL_LORAW | GPIO_MUXSEL_LORAW |
GPIO_MUXSEL_HIRAW; GPIO_MUXSEL_HIRAW;
LOW(GPIO_MUXSEL_HIPKD); LOW(GPIO_MUXSEL_HIPKD);
LOW(GPIO_MUXSEL_LOPKD); LOW(GPIO_MUXSEL_LOPKD);
LOW(GPIO_MUXSEL_HIRAW); LOW(GPIO_MUXSEL_HIRAW);
LOW(GPIO_MUXSEL_LORAW); LOW(GPIO_MUXSEL_LORAW);
#else #else
// FPC serial uses HIRAW/LOWRAW pins, so they are excluded here. // FPC serial uses HIRAW/LOWRAW pins, so they are excluded here.

View file

@ -34,8 +34,6 @@
#include "protocols.h" #include "protocols.h"
#include "apps.h" #include "apps.h"
uint8_t MifareCardType;
static bool IsTrailerAccessAllowed(uint8_t blockNo, uint8_t keytype, uint8_t action) { static bool IsTrailerAccessAllowed(uint8_t blockNo, uint8_t keytype, uint8_t action) {
uint8_t sector_trailer[16]; uint8_t sector_trailer[16];
emlGetMem(sector_trailer, blockNo, 1); emlGetMem(sector_trailer, blockNo, 1);
@ -151,196 +149,188 @@ 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 // SPEC: https://www.nxp.com/docs/en/application-note/AN10833.pdf
// ATQA // 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 // SAK
static uint8_t rATQA_Mini_7B[] = {0x44, 0x00}; // indicate Mifare classic Mini 7Byte UID static uint8_t rSAK_Mini = 0x09; // mifare Mini
static uint8_t rATQA_Mini_10B[] = {0x44, 0x00}; // indicate Mifare classic Mini 10Byte UID static uint8_t rSAK_1k = 0x08; // mifare 1k
static uint8_t rSAK_2k = 0x08; // mifare 2k with RATS support
static uint8_t rATQA_1k_4B[] = {0x04, 0x00}; // indicate Mifare classic 1k 4Byte UID static uint8_t rSAK_4k = 0x18; // mifare 4k
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
static uint8_t rUIDBCC1[] = {0x00, 0x00, 0x00, 0x00, 0x00}; // UID 1st cascade level 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 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 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; *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 // -- Determine the UID
// Can be set from emulator memory or incoming data // Can be set from emulator memory or incoming data
// Length: 4,7,or 10 bytes // Length: 4,7,or 10 bytes
// Get UID, SAK, ATQA from EMUL
if ((flags & FLAG_UID_IN_EMUL) == FLAG_UID_IN_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 if ((flags & FLAG_4B_UID_IN_DATA) == FLAG_4B_UID_IN_DATA) { // get UID from datain
memcpy(rUIDBCC1, datain, 4); memcpy(rUIDBCC1, datain, 4);
*uid_len = 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); 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);
// save CUID
*cuid = bytes_to_num(rUIDBCC1, 4);
// BCC
rUIDBCC1[4] = rUIDBCC1[0] ^ rUIDBCC1[1] ^ rUIDBCC1[2] ^ rUIDBCC1[3];
if (MF_DBGLEVEL >= MF_DBG_NONE) {
Dbprintf("4B UID: %02x%02x%02x%02x", rUIDBCC1[0], rUIDBCC1[1], rUIDBCC1[2], rUIDBCC1[3]);
}
// Correct uid size bits in ATQA
rATQA[0] = (rATQA[0] & 0x3f) | 0x00; // single size uid
} else if ((flags & FLAG_7B_UID_IN_DATA) == FLAG_7B_UID_IN_DATA) { } else if ((flags & FLAG_7B_UID_IN_DATA) == FLAG_7B_UID_IN_DATA) {
memcpy(&rUIDBCC1[1], datain, 3); memcpy(&rUIDBCC1[1], datain, 3);
memcpy(rUIDBCC2, datain + 3, 4); memcpy(rUIDBCC2, datain + 3, 4);
*uid_len = 7; *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); 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);
// CascadeTag, CT
rUIDBCC1[0] = MIFARE_SELECT_CT;
// BCC
rUIDBCC1[4] = rUIDBCC1[0] ^ rUIDBCC1[1] ^ rUIDBCC1[2] ^ rUIDBCC1[3];
rUIDBCC2[4] = rUIDBCC2[0] ^ rUIDBCC2[1] ^ rUIDBCC2[2] ^ rUIDBCC2[3];
if (MF_DBGLEVEL >= MF_DBG_NONE) {
Dbprintf("7B UID: %02x %02x %02x %02x %02x %02x %02x",
rUIDBCC1[1], rUIDBCC1[2], rUIDBCC1[3], rUIDBCC2[0], rUIDBCC2[1], rUIDBCC2[2], rUIDBCC2[3]);
}
// 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) { } else if ((flags & FLAG_10B_UID_IN_DATA) == FLAG_10B_UID_IN_DATA) {
memcpy(&rUIDBCC1[1], datain, 3); memcpy(&rUIDBCC1[1], datain, 3);
memcpy(&rUIDBCC2[1], datain + 3, 3); memcpy(&rUIDBCC2[1], datain + 3, 3);
memcpy(rUIDBCC3, datain + 6, 4); memcpy(rUIDBCC3, datain + 6, 4);
*uid_len = 10; *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); 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);
// CascadeTag, CT
rUIDBCC1[0] = MIFARE_SELECT_CT;
rUIDBCC2[0] = MIFARE_SELECT_CT;
// BCC
rUIDBCC1[4] = rUIDBCC1[0] ^ rUIDBCC1[1] ^ rUIDBCC1[2] ^ rUIDBCC1[3];
rUIDBCC2[4] = rUIDBCC2[0] ^ rUIDBCC2[1] ^ rUIDBCC2[2] ^ rUIDBCC2[3];
rUIDBCC3[4] = rUIDBCC3[0] ^ rUIDBCC3[1] ^ rUIDBCC3[2] ^ rUIDBCC3[3];
if (MF_DBGLEVEL >= MF_DBG_NONE) {
Dbprintf("10B UID: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
rUIDBCC1[1], rUIDBCC1[2], rUIDBCC1[3],
rUIDBCC2[1], rUIDBCC2[2], rUIDBCC2[3],
rUIDBCC3[0], rUIDBCC3[1], rUIDBCC3[2], rUIDBCC3[3]
);
}
// Correct uid size bits in ATQA
rATQA[0] = (rATQA[0] & 0x3f) | 0x80; // triple size uid
} else {
Dbprintf("[-] ERROR: UID size not defined");
return false;
} }
switch (*uid_len) { // Calculate actual CRC
AddCrc14A(rSAK, sizeof(rSAK) - 2);
// UID 4B #define TAG_RESPONSE_COUNT 6
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);
// BCC
rUIDBCC1[4] = rUIDBCC1[0] ^ rUIDBCC1[1] ^ rUIDBCC1[2] ^ rUIDBCC1[3];
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:
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;
}
// save CUID
*cuid = bytes_to_num(rUIDBCC2, 4);
// CascadeTag, CT
rUIDBCC1[0] = MIFARE_SELECT_CT;
// BCC
rUIDBCC1[4] = rUIDBCC1[0] ^ rUIDBCC1[1] ^ rUIDBCC1[2] ^ rUIDBCC1[3];
rUIDBCC2[4] = rUIDBCC2[0] ^ rUIDBCC2[1] ^ rUIDBCC2[2] ^ rUIDBCC2[3];
if (MF_DBGLEVEL >= MF_DBG_NONE) {
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;
}
// save CUID
*cuid = bytes_to_num(rUIDBCC3, 4);
// CascadeTag, CT
rUIDBCC1[0] = MIFARE_SELECT_CT;
rUIDBCC2[0] = MIFARE_SELECT_CT;
// BCC
rUIDBCC1[4] = rUIDBCC1[0] ^ rUIDBCC1[1] ^ rUIDBCC1[2] ^ rUIDBCC1[3];
rUIDBCC2[4] = rUIDBCC2[0] ^ rUIDBCC2[1] ^ rUIDBCC2[2] ^ rUIDBCC2[3];
rUIDBCC3[4] = rUIDBCC3[0] ^ rUIDBCC3[1] ^ rUIDBCC3[2] ^ rUIDBCC3[3];
if (MF_DBGLEVEL >= MF_DBG_NONE) {
Dbprintf("10B UID: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
rUIDBCC1[1], rUIDBCC1[2], rUIDBCC1[3],
rUIDBCC2[1], rUIDBCC2[2], rUIDBCC2[3],
rUIDBCC3[0], rUIDBCC3[1], rUIDBCC3[2], rUIDBCC3[3]
);
}
break;
default:
break;
}
#define TAG_RESPONSE_COUNT 9
static tag_response_info_t responses_init[TAG_RESPONSE_COUNT] = { static tag_response_info_t responses_init[TAG_RESPONSE_COUNT] = {
{ .response = rATQA, .response_n = sizeof(rATQA) }, // Answer to request - respond with card type { .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 = 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 = 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 = 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, .response_n = sizeof(rSAK) }, //
{ .response = rSAK_1, .response_n = sizeof(rSAK_1) }, // SAK Mifare 1K { .response = rSAKuid, .response_n = sizeof(rSAKuid) } //
{ .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
}; };
// Prepare ("precompile") the responses of the anticollision phase. // 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 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) // 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 // 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 512 #define ALLOCATED_TAG_MODULATION_BUFFER_SIZE 225
uint8_t *free_buffer = BigBuf_malloc(ALLOCATED_TAG_MODULATION_BUFFER_SIZE); uint8_t *free_buffer = BigBuf_malloc(ALLOCATED_TAG_MODULATION_BUFFER_SIZE);
// modulation buffer pointer and current buffer free space 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 UIDBCC1 1
#define UIDBCC2 2 #define UIDBCC2 2
#define UIDBCC3 3 #define UIDBCC3 3
#define SAK_MINI 4 #define SAK 4
#define SAK_1 5 #define SAKuid 5
#define SAK_2 6
#define SAK_4 7
#define SAK1 8
return true; 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[MAX_MIFARE_FRAME_SIZE] = {0x00};
uint8_t response_par[MAX_MIFARE_PARITY_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}; uint8_t rAUTH_AT[] = {0x00, 0x00, 0x00, 0x00};
//Here, we collect UID,sector,keytype,NT,AR,NR,NT2,AR2,NR2 //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(); 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 // free eventually allocated BigBuf memory but keep Emulator Memory
BigBuf_free_keep_EM(); 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(); BigBuf_free_keep_EM();
return; return;
} }
@ -579,34 +552,21 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t
// Send SAK according UID len // Send SAK according UID len
switch (uid_len) { switch (uid_len) {
case 4: case 4:
switch (MifareCardType) { // UID completed
case 0: // Mifare Mini EmSendPrecompiledCmd(&responses[SAK]);
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;
}
LED_B_ON(); LED_B_ON();
cardSTATE = MFEMUL_WORK; cardSTATE = MFEMUL_WORK;
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_SELECT1] cardSTATE = MFEMUL_WORK"); if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_SELECT1] cardSTATE = MFEMUL_WORK");
break; break;
case 7: case 7:
// SAK => Need another select round // SAK => Need another select round
EmSendPrecompiledCmd(&responses[SAK1]); EmSendPrecompiledCmd(&responses[SAKuid]);
cardSTATE = MFEMUL_SELECT2; cardSTATE = MFEMUL_SELECT2;
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_SELECT1] cardSTATE = MFEMUL_SELECT2"); if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_SELECT1] cardSTATE = MFEMUL_SELECT2");
break; break;
case 10: case 10:
// SAK => Need another select round // SAK => Need another select round
EmSendPrecompiledCmd(&responses[SAK1]); EmSendPrecompiledCmd(&responses[SAKuid]);
cardSTATE = MFEMUL_SELECT2; cardSTATE = MFEMUL_SELECT2;
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_SELECT1] cardSTATE = MFEMUL_SELECT2"); if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_SELECT1] cardSTATE = MFEMUL_SELECT2");
break; break;
@ -657,27 +617,14 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t
switch (uid_len) { switch (uid_len) {
case 7: 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]); if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_SELECT2] SELECT CL2 %02x%02x%02x%02x received", receivedCmd[2], receivedCmd[3], receivedCmd[4], receivedCmd[5]);
// UID completed
switch (MifareCardType) { EmSendPrecompiledCmd(&responses[SAK]);
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;
}
cardSTATE = MFEMUL_WORK; cardSTATE = MFEMUL_WORK;
LED_B_ON(); LED_B_ON();
break; break;
case 10: case 10:
// SAK => Need another select round // SAK => Need another select round
EmSendPrecompiledCmd(&responses[SAK1]); EmSendPrecompiledCmd(&responses[SAKuid]);
cardSTATE = MFEMUL_SELECT3; cardSTATE = MFEMUL_SELECT3;
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_SELECT2] cardSTATE = MFEMUL_SELECT3"); if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_SELECT2] cardSTATE = MFEMUL_SELECT3");
default: 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[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_3 &&
receivedCmd[1] == 0x70 && receivedCmd[1] == 0x70 &&
memcmp(&receivedCmd[2], responses[UIDBCC3].response, 4) == 0)) { memcmp(&receivedCmd[2], responses[UIDBCC3].response, 4) == 0)) {
// UID completed
switch (MifareCardType) { EmSendPrecompiledCmd(&responses[SAK]);
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;
}
cardSTATE = MFEMUL_WORK; cardSTATE = MFEMUL_WORK;
LED_B_ON(); LED_B_ON();
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) { 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 // 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) {
EmSend4bit(encrypted_data ? mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA) : CARD_NACK_NA); if (rats && rats_len) {
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] RCV RATS => NACK"); 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; break;
} }

View file

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

View file

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

View file

@ -64,14 +64,14 @@ static int usage_hf14_mifare(void) {
PrintAndLogEx(NORMAL, " hf mf darkside 16 B"); PrintAndLogEx(NORMAL, " hf mf darkside 16 B");
return 0; 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, "Usage: hf mf sim [h] u <uid> n <numreads> [i] [x] [e] [v]");
PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h this help"); 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, " 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, " t (Optional) 0 = MIFARE Mini");
PrintAndLogEx(NORMAL, " 1 = MIFARE Classic 1k (Default)"); 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, " 4 = MIFARE Classic 4k");
PrintAndLogEx(NORMAL, " n (Optional) Automatically exit simulation after <numreads> blocks have been read by reader. 0 = infinite"); 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"); 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 uid[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
uint8_t exitAfterNReads = 0; uint8_t exitAfterNReads = 0;
uint16_t flags = (FLAG_UID_IN_EMUL | FLAG_4B_UID_IN_DATA); uint16_t flags = 0;
int uidlen = 0; int uidlen = 0;
uint8_t cmdp = 0; uint8_t cmdp = 0;
bool errors = false, verbose = false, setEmulatorMem = false; bool errors = false, verbose = false, setEmulatorMem = false;
@ -2153,7 +2153,7 @@ static int CmdHF14AMf1kSim(const char *Cmd) {
cmdp++; cmdp++;
break; break;
case 'h': case 'h':
return usage_hf14_mf1ksim(); return usage_hf14_mfsim();
case 'i': case 'i':
flags |= FLAG_INTERACTIVE; flags |= FLAG_INTERACTIVE;
cmdp++; cmdp++;
@ -2191,16 +2191,16 @@ static int CmdHF14AMf1kSim(const char *Cmd) {
param_gethex_ex(Cmd, cmdp + 1, uid, &uidlen); param_gethex_ex(Cmd, cmdp + 1, uid, &uidlen);
switch (uidlen) { switch (uidlen) {
case 20: case 20:
flags = FLAG_10B_UID_IN_DATA; flags |= FLAG_10B_UID_IN_DATA;
break; break;
case 14: case 14:
flags = FLAG_7B_UID_IN_DATA; flags |= FLAG_7B_UID_IN_DATA;
break; break;
case 8: case 8:
flags = FLAG_4B_UID_IN_DATA; flags |= FLAG_4B_UID_IN_DATA;
break; break;
default: default:
return usage_hf14_mf1ksim(); return usage_hf14_mfsim();
} }
cmdp += 2; cmdp += 2;
break; break;
@ -2219,7 +2219,11 @@ static int CmdHF14AMf1kSim(const char *Cmd) {
} }
} }
//Validations //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) " PrintAndLogEx(NORMAL, " uid:%s, numreads:%d, flags:%d (0x%02x) "
, (uidlen == 0) ? "N/A" : sprint_hex(uid, uidlen >> 1) , (uidlen == 0) ? "N/A" : sprint_hex(uid, uidlen >> 1)
@ -3550,7 +3554,7 @@ static command_t CommandTable[] = {
{"auth4", CmdHF14AMfAuth4, 0, "ISO14443-4 AES authentication"}, {"auth4", CmdHF14AMfAuth4, 0, "ISO14443-4 AES authentication"},
// {"sniff", CmdHF14AMfSniff, 0, "Sniff card-reader communication"}, // {"sniff", CmdHF14AMfSniff, 0, "Sniff card-reader communication"},
{"-----------", CmdHelp, 0, ""}, {"-----------", CmdHelp, 0, ""},
{"sim", CmdHF14AMf1kSim, 0, "Simulate MIFARE card"}, {"sim", CmdHF14AMfSim, 0, "Simulate MIFARE card"},
{"eclr", CmdHF14AMfEClear, 0, "Clear simulator memory block"}, {"eclr", CmdHF14AMfEClear, 0, "Clear simulator memory block"},
{"eget", CmdHF14AMfEGet, 0, "Get simulator memory block"}, {"eget", CmdHF14AMfEGet, 0, "Get simulator memory block"},
{"eset", CmdHF14AMfESet, 0, "Set 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; phaseoff = 0;
// now do it again to find the end // now do it again to find the end
end = skip;
for (i += 3; i < j - 4 ; ++i) { 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] >= 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 + 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 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; bool protocol_T15_present = false;
if (T0 & 0x10) { 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++; T1len++;
} }
if (T0 & 0x20) { 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++; T1len++;
} }
if (T0 & 0x40) { 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++; T1len++;
} }
if (T0 & 0x80) { if (T0 & 0x80) {
uint8_t TD1 = atr[2 + T1len]; 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; protocol_T0_present = false;
if ((TD1 & 0x0f) == 0) { if ((TD1 & 0x0f) == 0) {
protocol_T0_present = true; protocol_T0_present = true;
@ -228,20 +228,20 @@ static int PrintATR(uint8_t *atr, size_t atrlen) {
T1len++; T1len++;
if (TD1 & 0x10) { 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++; TD1len++;
} }
if (TD1 & 0x20) { 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++; TD1len++;
} }
if (TD1 & 0x40) { 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++; TD1len++;
} }
if (TD1 & 0x80) { if (TD1 & 0x80) {
uint8_t TDi = atr[2 + T1len + TD1len]; 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) { if ((TDi & 0x0f) == 0) {
protocol_T0_present = true; protocol_T0_present = true;
} }
@ -255,20 +255,20 @@ static int PrintATR(uint8_t *atr, size_t atrlen) {
while (nextCycle) { while (nextCycle) {
nextCycle = false; nextCycle = false;
if (TDi & 0x10) { 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++; TDilen++;
} }
if (TDi & 0x20) { 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++; TDilen++;
} }
if (TDi & 0x40) { 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++; TDilen++;
} }
if (TDi & 0x80) { if (TDi & 0x80) {
TDi = atr[2 + T1len + TD1len + TDilen]; 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++; TDilen++;
nextCycle = true; nextCycle = true;

View file

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

View file

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

View file

@ -152,10 +152,10 @@ int roca_self_test(void) {
if (emv_rocacheck(keyp, 64, false)) { if (emv_rocacheck(keyp, 64, false)) {
PrintAndLogEx(SUCCESS, "Weak modulus [ %s]", _GREEN_("PASS")); PrintAndLogEx(SUCCESS, "Weak modulus [ %s]", _GREEN_("PASS"));
} else { } else {
ret++; ret++;
PrintAndLogEx(FAILED, "Weak modulus [ %s]", _RED_("Fail")); PrintAndLogEx(FAILED, "Weak modulus [ %s]", _RED_("Fail"));
} }
// negative // negative

View file

@ -75,7 +75,7 @@ int JsonSaveJsonObject(json_t *root, const char *path, json_t *value) {
if (path[0] == '$') { if (path[0] == '$') {
if (json_path_set(root, path, value, 0, &error)) { 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; return 2;
} else { } else {
return 0; 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_is_array(elm)) {
if (json_array_append_new(elm, obj)) { 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; return 2;
} }
} else { } else {
if (json_path_set(elm, path, obj, 0, &error)) { 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; return 2;
} }
} }
@ -225,7 +225,7 @@ int JsonSaveTLVTree(json_t *root, json_t *elm, const char *path, struct tlvdb *t
// check // check
if (!json_is_array(chjson)) { 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; 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)) { switch (param_gethex_to_eol(hexvalue, 0, buffer, maxbufferlen, &buflen)) {
case 1: case 1:
PrintAndLog("%s Invalid HEX value.", errormsg); PrintAndLogEx(ERR, "%s Invalid HEX value.", errormsg);
return false; return false;
case 2: case 2:
PrintAndLog("%s Hex value too large.", errormsg); PrintAndLogEx(ERR, "%s Hex value too large.", errormsg);
return false; return false;
case 3: 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; return false;
} }
if (buflen > maxbufferlen) { 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; return false;
} }
@ -300,7 +300,7 @@ bool ParamLoadFromJson(struct tlvdb *tlv) {
json_error_t error; json_error_t error;
if (!tlv) { if (!tlv) {
PrintAndLog("ERROR load params: tlv tree is NULL."); PrintAndLogEx(ERR, "ERROR load params: tlv tree is NULL.");
return false; return false;
} }
@ -312,30 +312,30 @@ bool ParamLoadFromJson(struct tlvdb *tlv) {
root = json_load_file(fname, 0, &error); root = json_load_file(fname, 0, &error);
if (!root) { 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; return false;
} }
if (!json_is_array(root)) { 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; 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++) { for (int i = 0; i < json_array_size(root); i++) {
json_t *data, *jtag, *jlength, *jvalue; json_t *data, *jtag, *jlength, *jvalue;
data = json_array_get(root, i); data = json_array_get(root, i);
if (!json_is_object(data)) { 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); json_decref(root);
return false; return false;
} }
jtag = json_object_get(data, "tag"); jtag = json_object_get(data, "tag");
if (!json_is_string(jtag)) { 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); json_decref(root);
return false; return false;
} }
@ -343,7 +343,7 @@ bool ParamLoadFromJson(struct tlvdb *tlv) {
jvalue = json_object_get(data, "value"); jvalue = json_object_get(data, "value");
if (!json_is_string(jvalue)) { 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); json_decref(root);
return false; return false;
} }
@ -351,19 +351,19 @@ bool ParamLoadFromJson(struct tlvdb *tlv) {
jlength = json_object_get(data, "length"); jlength = json_object_get(data, "length");
if (!json_is_number(jlength)) { 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); json_decref(root);
return false; return false;
} }
int tlvLength = json_integer_value(jlength); int tlvLength = json_integer_value(jlength);
if (tlvLength > 250) { 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); json_decref(root);
return false; 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}; uint8_t buf[251] = {0};
size_t buflen = 0; size_t buflen = 0;
@ -382,7 +382,7 @@ bool ParamLoadFromJson(struct tlvdb *tlv) {
} }
if (buflen != tlvLength) { 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); json_decref(root);
return false; return false;
} }

View file

@ -162,16 +162,16 @@ int COSEGetECDSAKey(uint8_t *data, size_t datalen, bool verbose, uint8_t *public
size_t len; size_t len;
if (verbose) if (verbose)
PrintAndLog("----------- CBOR decode ----------------"); PrintAndLogEx(NORMAL, "----------- CBOR decode ----------------");
// kty // kty
int res = CborMapGetKeyById(&parser, &map, data, datalen, 1); int res = CborMapGetKeyById(&parser, &map, data, datalen, 1);
if (!res) { if (!res) {
cbor_value_get_int64(&map, &i64); cbor_value_get_int64(&map, &i64);
if (verbose) if (verbose)
PrintAndLog("kty [%lld] %s", (long long)i64, GetCOSEktyDescription(i64)); PrintAndLogEx(SUCCESS, "kty [%lld] %s", (long long)i64, GetCOSEktyDescription(i64));
if (i64 != 2) if (i64 != 2)
PrintAndLog("ERROR: kty must be 2."); PrintAndLogEx(ERR, "ERROR: kty must be 2.");
} }
// algorithm // algorithm
@ -179,9 +179,9 @@ int COSEGetECDSAKey(uint8_t *data, size_t datalen, bool verbose, uint8_t *public
if (!res) { if (!res) {
cbor_value_get_int64(&map, &i64); cbor_value_get_int64(&map, &i64);
if (verbose) if (verbose)
PrintAndLog("algorithm [%lld] %s", (long long)i64, GetCOSEAlgDescription(i64)); PrintAndLogEx(SUCCESS, "algorithm [%lld] %s", (long long)i64, GetCOSEAlgDescription(i64));
if (i64 != -7) if (i64 != -7)
PrintAndLog("ERROR: algorithm must be -7."); PrintAndLogEx(ERR, "ERROR: algorithm must be -7.");
} }
// curve // curve
@ -189,9 +189,9 @@ int COSEGetECDSAKey(uint8_t *data, size_t datalen, bool verbose, uint8_t *public
if (!res) { if (!res) {
cbor_value_get_int64(&map, &i64); cbor_value_get_int64(&map, &i64);
if (verbose) if (verbose)
PrintAndLog("curve [%lld] %s", (long long)i64, GetCOSECurveDescription(i64)); PrintAndLogEx(SUCCESS, "curve [%lld] %s", (long long)i64, GetCOSECurveDescription(i64));
if (i64 != 1) if (i64 != 1)
PrintAndLog("ERROR: curve must be 1."); PrintAndLogEx(ERR, "ERROR: curve must be 1.");
} }
// plain key // 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); res = CborGetBinStringValue(&map, &public_key[1], 32, &len);
cbor_check(res); cbor_check(res);
if (verbose) 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) if (len != 32)
PrintAndLog("ERROR: x - coordinate length must be 32."); PrintAndLogEx(ERR, "ERROR: x - coordinate length must be 32.");
} }
// y - coordinate // 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); res = CborGetBinStringValue(&map, &public_key[33], 32, &len);
cbor_check(res); cbor_check(res);
if (verbose) 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) if (len != 32)
PrintAndLog("ERROR: y - coordinate length must be 32."); PrintAndLogEx(ERR, "ERROR: y - coordinate length must be 32.");
} }
// d - private key // 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); res = CborGetBinStringValue(&map, private_key, sizeof(private_key), &len);
cbor_check(res); cbor_check(res);
if (verbose) 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) if (verbose)
PrintAndLog("----------- CBOR decode ----------------"); PrintAndLogEx(NORMAL, "----------- CBOR decode ----------------");
return 0; 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); mbedtls_x509_crt_init(&cacert);
res = mbedtls_x509_crt_parse(&cacert, (const unsigned char *) additional_ca_pem, additional_ca_pem_len); res = mbedtls_x509_crt_parse(&cacert, (const unsigned char *) additional_ca_pem, additional_ca_pem_len);
if (res < 0) { 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) if (verbose)
PrintAndLog("CA load OK. %d skipped", res); PrintAndLogEx(SUCCESS, "CA load OK. %d skipped", res);
// load DER certificate from authenticator's data // load DER certificate from authenticator's data
mbedtls_x509_crt cert; mbedtls_x509_crt cert;
mbedtls_x509_crt_init(&cert); mbedtls_x509_crt_init(&cert);
res = mbedtls_x509_crt_parse_der(&cert, der, derLen); res = mbedtls_x509_crt_parse_der(&cert, der, derLen);
if (res) { 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 // get certificate info
char linfo[300] = {0}; char linfo[300] = {0};
if (verbose) { if (verbose) {
mbedtls_x509_crt_info(linfo, sizeof(linfo), " ", &cert); 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 // verify certificate
uint32_t verifyflags = 0; uint32_t verifyflags = 0;
res = mbedtls_x509_crt_verify(&cert, &cacert, NULL, NULL, &verifyflags, NULL, NULL); res = mbedtls_x509_crt_verify(&cert, &cacert, NULL, NULL, &verifyflags, NULL, NULL);
if (res) { 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 { } else {
PrintAndLog("Certificate OK.\n"); PrintAndLogEx(SUCCESS, "Certificate OK.\n");
} }
if (verbose) { if (verbose) {
memset(linfo, 0x00, sizeof(linfo)); memset(linfo, 0x00, sizeof(linfo));
mbedtls_x509_crt_verify_info(linfo, sizeof(linfo), " ", verifyflags); 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 // get public key
res = ecdsa_public_key_from_pk(&cert.pk, publicKey, publicKeyMaxLen); res = ecdsa_public_key_from_pk(&cert.pk, publicKey, publicKeyMaxLen);
if (res) { 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 { } else {
if (verbose) 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) if (verbose)
PrintAndLog("------------------DER-------------------"); PrintAndLogEx(NORMAL, "------------------DER-------------------");
mbedtls_x509_crt_free(&cert); mbedtls_x509_crt_free(&cert);
mbedtls_x509_crt_free(&cacert); 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); res = ecdsa_asn1_get_signature(sign, signLen, rval, sval);
if (!res) { if (!res) {
if (verbose) { if (verbose) {
PrintAndLog(" r: %s", sprint_hex(rval, 32)); PrintAndLogEx(NORMAL, " r: %s", sprint_hex(rval, 32));
PrintAndLog(" s: %s", sprint_hex(sval, 32)); PrintAndLogEx(NORMAL, " s: %s", sprint_hex(sval, 32));
} }
uint8_t clientDataHash[32] = {0}; uint8_t clientDataHash[32] = {0};
size_t clientDataHashLen = 0; size_t clientDataHashLen = 0;
res = JsonLoadBufAsHex(root, "$.ClientDataHash", clientDataHash, sizeof(clientDataHash), &clientDataHashLen); res = JsonLoadBufAsHex(root, "$.ClientDataHash", clientDataHash, sizeof(clientDataHash), &clientDataHashLen);
if (res || clientDataHashLen != 32) { if (res || clientDataHashLen != 32) {
PrintAndLog("ERROR: Can't get clientDataHash from json!"); PrintAndLogEx(ERR, "ERROR: Can't get clientDataHash from json!");
return 2; 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] authData, authDataLen, // rpIdHash[32] + flags[1] + signCount[4]
clientDataHash, 32, // Hash of the serialized client data. "$.ClientDataHash" from json clientDataHash, 32, // Hash of the serialized client data. "$.ClientDataHash" from json
NULL, 0); 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); res = ecdsa_signature_verify(publickey, xbuf, xbuflen, sign, signLen);
if (res) { if (res) {
if (res == -0x4e00) { if (res == -0x4e00) {
PrintAndLog("Signature is NOT VALID."); PrintAndLogEx(WARNING, "Signature is NOT VALID.");
} else { } 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; return res;
} else { } else {
PrintAndLog("Signature is OK."); PrintAndLogEx(SUCCESS, "Signature is OK.");
} }
} else { } else {
PrintAndLog("Invalid signature. res=%d.", res); PrintAndLogEx(ERR, "Invalid signature. res = %d.", res);
return 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); res = cbor_value_dup_text_string(&map, &buf, &n, &map);
cbor_check(res); cbor_check(res);
PrintAndLog("format: %s", buf); PrintAndLogEx(INFO, "format: %s", buf);
free(buf); free(buf);
// authData // authData
@ -431,43 +431,43 @@ int FIDO2MakeCredentionalParseRes(json_t *root, uint8_t *data, size_t dataLen, b
memcpy(authData, ubuf, authDataLen); memcpy(authData, ubuf, authDataLen);
if (verbose2) { if (verbose2) {
PrintAndLog("authData[%d]: %s", n, sprint_hex_inrow(authData, authDataLen)); PrintAndLogEx(INFO, "authData[%d]: %s", n, sprint_hex_inrow(authData, authDataLen));
} else { } 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 // check RP ID Hash
if (CheckrpIdHash(root, ubuf)) { if (CheckrpIdHash(root, ubuf)) {
PrintAndLog("rpIdHash OK."); PrintAndLogEx(SUCCESS, "rpIdHash OK.");
} else { } else {
PrintAndLog("rpIdHash ERROR!"); PrintAndLogEx(ERR, "rpIdHash ERROR!");
} }
PrintAndLog("Flags 0x%02x:", ubuf[32]); PrintAndLogEx(INFO, "Flags 0x%02x:", ubuf[32]);
if (!ubuf[32]) if (!ubuf[32])
PrintAndLog("none"); PrintAndLogEx(SUCCESS, "none");
if (ubuf[32] & 0x01) if (ubuf[32] & 0x01)
PrintAndLog("up - user presence result"); PrintAndLogEx(SUCCESS, "up - user presence result");
if (ubuf[32] & 0x04) 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) if (ubuf[32] & 0x40)
PrintAndLog("at - attested credential data included"); PrintAndLogEx(SUCCESS, "at - attested credential data included");
if (ubuf[32] & 0x80) 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); 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); JsonSaveInt(root, "$.AppData.Counter", cntr);
// attestation data // 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); JsonSaveBufAsHexCompact(root, "$.AppData.AAGUID", &ubuf[37], 16);
// Credential ID // Credential ID
uint8_t cridlen = (uint16_t)bytes_to_num(&ubuf[53], 2); 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); JsonSaveInt(root, "$.AppData.CredentialIdLen", cridlen);
JsonSaveBufAsHexCompact(root, "$.AppData.CredentialId", &ubuf[55], 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}; uint8_t coseKey[65] = {0};
uint16_t cplen = n - 55 - cridlen; uint16_t cplen = n - 55 - cridlen;
if (verbose2) { 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 { } 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); JsonSaveBufAsHexCompact(root, "$.AppData.COSE_KEY", &ubuf[55 + cridlen], cplen);
if (showCBOR) { if (showCBOR) {
PrintAndLog("COSE structure:"); PrintAndLogEx(INFO, "COSE structure:");
PrintAndLog("---------------- CBOR ------------------"); PrintAndLogEx(NORMAL, "---------------- CBOR ------------------");
TinyCborPrintFIDOPackage(fido2COSEKey, true, &ubuf[55 + cridlen], cplen); TinyCborPrintFIDOPackage(fido2COSEKey, true, &ubuf[55 + cridlen], cplen);
PrintAndLog("---------------- CBOR ------------------"); PrintAndLogEx(NORMAL, "---------------- CBOR ------------------");
} }
res = COSEGetECDSAKey(&ubuf[55 + cridlen], cplen, verbose, coseKey); res = COSEGetECDSAKey(&ubuf[55 + cridlen], cplen, verbose, coseKey);
if (res) { if (res) {
PrintAndLog("ERROR: Can't get COSE_KEY."); PrintAndLogEx(ERR, "ERROR: Can't get COSE_KEY.");
} else { } 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)); 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); cbor_check(res);
if (!strcmp(key, "alg")) { if (!strcmp(key, "alg")) {
cbor_value_get_int64(&mapsmt, &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); res = cbor_value_advance_fixed(&mapsmt);
cbor_check(res); 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); res = CborGetBinStringValue(&mapsmt, sign, sizeof(sign), &signLen);
cbor_check(res); cbor_check(res);
if (verbose2) { if (verbose2) {
PrintAndLog("signature [%d]: %s", signLen, sprint_hex_inrow(sign, signLen)); PrintAndLogEx(INFO, "signature [%d]: %s", signLen, sprint_hex_inrow(sign, signLen));
} else { } 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); res = CborGetArrayBinStringValue(&mapsmt, der, sizeof(der), &derLen);
cbor_check(res); cbor_check(res);
if (verbose2) { 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); dump_buffer_simple((const unsigned char *)der, derLen, NULL);
PrintAndLog("\n----------------DER---------------------"); PrintAndLogEx(NORMAL, "\n----------------DER---------------------");
} else { } 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); 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 // print DER certificate in TLV view
if (showDERTLV) { if (showDERTLV) {
PrintAndLog("----------------DER TLV-----------------"); PrintAndLogEx(NORMAL, "----------------DER TLV-----------------");
asn1_print(der, derLen, " "); asn1_print(der, derLen, " ");
PrintAndLog("----------------DER TLV-----------------"); PrintAndLogEx(NORMAL, "----------------DER TLV-----------------");
} }
FIDOCheckDERAndGetKey(der, derLen, verbose, public_key, sizeof(public_key)); FIDOCheckDERAndGetKey(der, derLen, verbose, public_key, sizeof(public_key));
JsonSaveBufAsHexCompact(root, "$.AppData.DERPublicKey", 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}; char ctype[200] = {0};
res = CborGetStringValue(&mapint, ctype, sizeof(ctype), &n); res = CborGetStringValue(&mapint, ctype, sizeof(ctype), &n);
cbor_check(res); cbor_check(res);
PrintAndLog("credential type: %s", ctype); PrintAndLogEx(SUCCESS, "credential type: %s", ctype);
} }
if (!strcmp(key, "id")) { if (!strcmp(key, "id")) {
uint8_t cid[200] = {0}; uint8_t cid[200] = {0};
res = CborGetBinStringValue(&mapint, cid, sizeof(cid), &n); res = CborGetBinStringValue(&mapint, cid, sizeof(cid), &n);
cbor_check(res); 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); 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); memcpy(authData, ubuf, authDataLen);
if (verbose2) { if (verbose2) {
PrintAndLog("authData[%d]: %s", n, sprint_hex_inrow(authData, authDataLen)); PrintAndLogEx(INFO, "authData[%d]: %s", n, sprint_hex_inrow(authData, authDataLen));
} else { } 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 // check RP ID Hash
if (CheckrpIdHash(root, ubuf)) { if (CheckrpIdHash(root, ubuf)) {
PrintAndLog("rpIdHash OK."); PrintAndLogEx(SUCCESS, "rpIdHash OK.");
} else { } else {
PrintAndLog("rpIdHash ERROR!"); PrintAndLogEx(ERR, "rpIdHash ERROR!");
} }
PrintAndLog("Flags 0x%02x:", ubuf[32]); PrintAndLogEx(INFO, "Flags 0x%02x:", ubuf[32]);
if (!ubuf[32]) if (!ubuf[32])
PrintAndLog("none"); PrintAndLogEx(SUCCESS, "none");
if (ubuf[32] & 0x01) if (ubuf[32] & 0x01)
PrintAndLog("up - user presence result"); PrintAndLogEx(SUCCESS, "up - user presence result");
if (ubuf[32] & 0x04) 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) if (ubuf[32] & 0x40)
PrintAndLog("at - attested credential data included"); PrintAndLogEx(SUCCESS, "at - attested credential data included");
if (ubuf[32] & 0x80) 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); 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); JsonSaveInt(root, "$.AppData.Counter", cntr);
free(ubuf); free(ubuf);
@ -725,7 +725,7 @@ int FIDO2GetAssertionParseRes(json_t *root, uint8_t *data, size_t dataLen, bool
// publicKeyCredentialUserEntity // publicKeyCredentialUserEntity
res = CborMapGetKeyById(&parser, &map, data, dataLen, 4); res = CborMapGetKeyById(&parser, &map, data, dataLen, 4);
if (res) { if (res) {
PrintAndLog("UserEntity n/a"); PrintAndLogEx(SUCCESS, "UserEntity n/a");
} else { } else {
res = cbor_value_enter_container(&map, &mapint); res = cbor_value_enter_container(&map, &mapint);
cbor_check(res); cbor_check(res);
@ -739,14 +739,14 @@ int FIDO2GetAssertionParseRes(json_t *root, uint8_t *data, size_t dataLen, bool
char cname[200] = {0}; char cname[200] = {0};
res = CborGetStringValue(&mapint, cname, sizeof(cname), &n); res = CborGetStringValue(&mapint, cname, sizeof(cname), &n);
cbor_check(res); cbor_check(res);
PrintAndLog("UserEntity %s: %s", key, cname); PrintAndLogEx(SUCCESS, "UserEntity %s: %s", key, cname);
} }
if (!strcmp(key, "id")) { if (!strcmp(key, "id")) {
uint8_t cid[200] = {0}; uint8_t cid[200] = {0};
res = CborGetBinStringValue(&mapint, cid, sizeof(cid), &n); res = CborGetBinStringValue(&mapint, cid, sizeof(cid), &n);
cbor_check(res); 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 // check
uint8_t idbuf[100] = {0}; 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); JsonLoadBufAsHex(root, "$.UserEntity.id", idbuf, sizeof(idbuf), &idbuflen);
if (idbuflen == n && !memcmp(idbuf, cid, idbuflen)) { if (idbuflen == n && !memcmp(idbuf, cid, idbuflen)) {
PrintAndLog("UserEntity id OK."); PrintAndLogEx(SUCCESS, "UserEntity id OK.");
} else { } 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); cbor_check(res);
if (verbose2) { if (verbose2) {
PrintAndLog("signature [%d]: %s", signLen, sprint_hex_inrow(sign, signLen)); PrintAndLogEx(SUCCESS, "signature [%d]: %s", signLen, sprint_hex_inrow(sign, signLen));
} else { } 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 // get public key from json
@ -796,11 +796,11 @@ int FIDO2GetAssertionParseRes(json_t *root, uint8_t *data, size_t dataLen, bool
// numberOfCredentials // numberOfCredentials
res = CborMapGetKeyById(&parser, &map, data, dataLen, 5); res = CborMapGetKeyById(&parser, &map, data, dataLen, 5);
if (res) { if (res) {
PrintAndLog("numberOfCredentials: 1 by default"); PrintAndLogEx(SUCCESS, "numberOfCredentials: 1 by default");
} else { } else {
int64_t numberOfCredentials = 0; int64_t numberOfCredentials = 0;
cbor_value_get_int64(&map, &numberOfCredentials); cbor_value_get_int64(&map, &numberOfCredentials);
PrintAndLog("numberOfCredentials: %lld", (long long)numberOfCredentials); PrintAndLogEx(SUCCESS, "numberOfCredentials: %lld", (long long)numberOfCredentials);
} }
return 0; return 0;

View file

@ -22,7 +22,7 @@ void jsonp_error_set_source(json_error_t *error, const char *source) {
length = strlen(source); length = strlen(source);
if (length < JSON_ERROR_SOURCE_LENGTH) { if (length < JSON_ERROR_SOURCE_LENGTH) {
strncpy(error->source, source, JSON_ERROR_SOURCE_LENGTH); strncpy(error->source, source, JSON_ERROR_SOURCE_LENGTH - 1);
} else { } else {
size_t extra = length - JSON_ERROR_SOURCE_LENGTH + 4; size_t extra = length - JSON_ERROR_SOURCE_LENGTH + 4;
memcpy(error->source, "...", 3); 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 if (newsize >= b->alloc) { // NB! one extra byte is needed to avoid buffer overflow at close_buffer
// make room // make room
size_t newalloc = newsize + newsize / 2 + 1; // give 50% more 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; return -1;
} else {
ptr = tmp;
}
b->alloc = newalloc; b->alloc = newalloc;
*b->ptr = ptr; *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_WRITEBLOCK 0xA0
#define ISO14443A_CMD_HALT 0x50 #define ISO14443A_CMD_HALT 0x50
#define ISO14443A_CMD_RATS 0xE0 #define ISO14443A_CMD_RATS 0xE0
#define ISO14443A_CMD_NXP_DESELECT 0xC2
#define MIFARE_SELECT_CT 0x88 #define MIFARE_SELECT_CT 0x88
#define MIFARE_AUTH_KEYA 0x60 #define MIFARE_AUTH_KEYA 0x60
@ -167,7 +168,7 @@ ISO 7816-4 Basic interindustry commands. For command APDU's.
#define MIFARE_EV1_SETMODE 0x43 #define MIFARE_EV1_SETMODE 0x43
#define MIFARE_ULC_WRITE 0xA2 #define MIFARE_ULC_WRITE 0xA2
#define MIFARE_ULC_COMP_WRITE 0xA0 #define MIFARE_ULC_COMP_WRITE 0xA0
#define MIFARE_ULC_AUTH_1 0x1A #define MIFARE_ULC_AUTH_1 0x1A
#define MIFARE_ULC_AUTH_2 0xAF #define MIFARE_ULC_AUTH_2 0xAF