This commit is contained in:
Akif Dinc 2021-02-17 13:34:35 +01:00
commit 7744e53968
12 changed files with 304 additions and 203 deletions

View file

@ -11,7 +11,7 @@
#include <ctype.h>
#include "cmdparser.h" // command_t
#include "cliparser.h"
#include "pmflash.h"
#include "pmflash.h" // rdv40validation_t
#include "fileutils.h" // saveFile
#include "comms.h" // getfromdevice
#include "cmdflashmemspiffs.h" // spiffs commands
@ -26,6 +26,123 @@
static int CmdHelp(const char *Cmd);
//-------------------------------------------------------------------------------------
// RRG Public RSA Key
#define RRG_RSA_KEY_LEN 128
// public key Exponent E
#define RRG_RSA_E "010001"
// public key modulus N
#define RRG_RSA_N "E28D809BF323171D11D1ACA4C32A5B7E0A8974FD171E75AD120D60E9B76968FF" \
"4B0A6364AE50583F9555B8EE1A725F279E949246DF0EFCE4C02B9F3ACDCC623F" \
"9337F21C0C066FFB703D8BFCB5067F309E056772096642C2B1A8F50305D5EC33" \
"DB7FB5A3C8AC42EB635AE3C148C910750ABAA280CE82DC2F180F49F30A1393B5"
// Following example RSA-1024 keypair, for test purposes (from common/polarssl/rsa.c)
// private key - Exponent D
#define RSA_D "24BF6185468786FDD303083D25E64EFC" \
"66CA472BC44D253102F8B4A9D3BFA750" \
"91386C0077937FE33FA3252D28855837" \
"AE1B484A8A9A45F7EE8C0C634F99E8CD" \
"DF79C5CE07EE72C7F123142198164234" \
"CABB724CF78B8173B9F880FC86322407" \
"AF1FEDFDDE2BEB674CA15F3E81A1521E" \
"071513A1E85B5DFA031F21ECAE91A34D"
// prime P
#define RSA_P "C36D0EB7FCD285223CFB5AABA5BDA3D8" \
"2C01CAD19EA484A87EA4377637E75500" \
"FCB2005C5C7DD6EC4AC023CDA285D796" \
"C3D9E75E1EFC42488BB4F1D13AC30A57"
// prime Q
#define RSA_Q "C000DF51A7C77AE8D7C7370C1FF55B69" \
"E211C2B9E5DB1ED0BF61D0D9899620F4" \
"910E4168387E3C30AA1E00C339A79508" \
"8452DD96A9A5EA5D9DCA68DA636032AF"
#define RSA_DP "C1ACF567564274FB07A0BBAD5D26E298" \
"3C94D22288ACD763FD8E5600ED4A702D" \
"F84198A5F06C2E72236AE490C93F07F8" \
"3CC559CD27BC2D1CA488811730BB5725"
#define RSA_DQ "4959CBF6F8FEF750AEE6977C155579C7" \
"D8AAEA56749EA28623272E4F7D0592AF" \
"7C1F1313CAC9471B5C523BFE592F517B" \
"407A1BD76C164B93DA2D32A383E58357"
#define RSA_QP "9AE7FBC99546432DF71896FC239EADAE" \
"F38D18D2B2F0E2DD275AA977E2BF4411" \
"F5A3B2A5D33605AEBBCCBA7FEB9F2D2F" \
"A74206CEC169D74BF5A8C50D6F48EA08"
int rdv4_get_signature(rdv40_validation_t *out) {
if (out == NULL) {
return PM3_EINVARG;
}
clearCommandBuffer();
SendCommandNG(CMD_FLASHMEM_INFO, NULL, 0);
PacketResponseNG resp;
if (WaitForResponseTimeout(CMD_ACK, &resp, 2500) == false) {
PrintAndLogEx(WARNING, "timeout while waiting for reply");
return PM3_ETIMEOUT;
}
uint8_t isok = resp.oldarg[0] & 0xFF;
if (isok == false) {
PrintAndLogEx(FAILED, "fail reading from flashmemory");
return PM3_EFLASH;
}
//rdv40_validation_t mem;
memcpy(out, (rdv40_validation_t *)resp.data.asBytes, sizeof(rdv40_validation_t));
return PM3_SUCCESS;
}
// validate signature
int rdv4_validate(rdv40_validation_t *mem) {
// Flash ID hash (sha1)
uint8_t sha_hash[20] = {0};
mbedtls_sha1(mem->flashid, sizeof(mem->flashid), sha_hash);
// set up RSA
mbedtls_rsa_context rsa;
mbedtls_rsa_init(&rsa, MBEDTLS_RSA_PKCS_V15, 0);
rsa.len = RRG_RSA_KEY_LEN;
mbedtls_mpi_read_string(&rsa.N, 16, RRG_RSA_N);
mbedtls_mpi_read_string(&rsa.E, 16, RRG_RSA_E);
// Verify (public key)
int is_verified = mbedtls_rsa_pkcs1_verify(&rsa, NULL, NULL, MBEDTLS_RSA_PUBLIC, MBEDTLS_MD_SHA1, 20, sha_hash, mem->signature);
mbedtls_rsa_free(&rsa);
if (is_verified == 0) {
return PM3_SUCCESS;
}
return PM3_EFAILED;
}
static int rdv4_sign_write(uint8_t *signature, uint8_t slen){
// save to mem
clearCommandBuffer();
PacketResponseNG resp;
SendCommandOLD(CMD_FLASHMEM_WRITE, FLASH_MEM_SIGNATURE_OFFSET, FLASH_MEM_SIGNATURE_LEN, 0, signature, slen);
if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
} else {
if (!resp.oldarg[0]) {
PrintAndLogEx(FAILED, "Writing signature ( "_RED_("fail") ")");
} else {
PrintAndLogEx(SUCCESS, "Writing signature ( "_GREEN_("ok") " ) at offset %u", FLASH_MEM_SIGNATURE_OFFSET);
return PM3_SUCCESS;
}
}
return PM3_EFAILED;
}
static int CmdFlashmemSpiBaudrate(const char *Cmd) {
CLIParserContext *ctx;
@ -344,23 +461,14 @@ static int CmdFlashMemInfo(const char *Cmd) {
// shall_write = arg_get_lit(ctx, 2);
CLIParserFree(ctx);
clearCommandBuffer();
SendCommandNG(CMD_FLASHMEM_INFO, NULL, 0);
PacketResponseNG resp;
if (WaitForResponseTimeout(CMD_ACK, &resp, 2500) == false) {
PrintAndLogEx(WARNING, "timeout while waiting for reply");
return PM3_ETIMEOUT;
}
uint8_t isok = resp.oldarg[0] & 0xFF;
if (isok == false) {
PrintAndLogEx(FAILED, "failed");
return PM3_EFLASH;
}
// validate signature here
// validate signature data
rdv40_validation_t mem;
memcpy(&mem, (rdv40_validation_t *)resp.data.asBytes, sizeof(rdv40_validation_t));
int res = rdv4_get_signature(&mem);
if (res != PM3_SUCCESS) {
return res;
}
res = rdv4_validate(&mem);
// Flash ID hash (sha1)
uint8_t sha_hash[20] = {0};
@ -369,7 +477,6 @@ static int CmdFlashMemInfo(const char *Cmd) {
// print header
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, "--- " _CYAN_("Flash memory Information") " ---------");
// PrintAndLogEx(INFO, "-----------------------------------------------------------------");
PrintAndLogEx(INFO, "ID................... %s", sprint_hex_inrow(mem.flashid, sizeof(mem.flashid)));
PrintAndLogEx(INFO, "SHA1................. %s", sprint_hex_inrow(sha_hash, sizeof(sha_hash)));
PrintAndLogEx(NORMAL, "");
@ -378,69 +485,16 @@ static int CmdFlashMemInfo(const char *Cmd) {
PrintAndLogEx(INFO, " %s", sprint_hex_inrow(mem.signature + (i * 32), 32));
}
//-------------------------------------------------------------------------------
// RRG Public RSA Key
//
// public key Exponent E
#define RSA_E "010001"
// public key modulus N
#define RSA_N "E28D809BF323171D11D1ACA4C32A5B7E0A8974FD171E75AD120D60E9B76968FF" \
"4B0A6364AE50583F9555B8EE1A725F279E949246DF0EFCE4C02B9F3ACDCC623F" \
"9337F21C0C066FFB703D8BFCB5067F309E056772096642C2B1A8F50305D5EC33" \
"DB7FB5A3C8AC42EB635AE3C148C910750ABAA280CE82DC2F180F49F30A1393B5"
//-------------------------------------------------------------------------------
// Example RSA-1024 keypair, for test purposes (from common/polarssl/rsa.c)
//
// private key Exponent D
#define RSA_D "24BF6185468786FDD303083D25E64EFC" \
"66CA472BC44D253102F8B4A9D3BFA750" \
"91386C0077937FE33FA3252D28855837" \
"AE1B484A8A9A45F7EE8C0C634F99E8CD" \
"DF79C5CE07EE72C7F123142198164234" \
"CABB724CF78B8173B9F880FC86322407" \
"AF1FEDFDDE2BEB674CA15F3E81A1521E" \
"071513A1E85B5DFA031F21ECAE91A34D"
// prime P
#define RSA_P "C36D0EB7FCD285223CFB5AABA5BDA3D8" \
"2C01CAD19EA484A87EA4377637E75500" \
"FCB2005C5C7DD6EC4AC023CDA285D796" \
"C3D9E75E1EFC42488BB4F1D13AC30A57"
// prime Q
#define RSA_Q "C000DF51A7C77AE8D7C7370C1FF55B69" \
"E211C2B9E5DB1ED0BF61D0D9899620F4" \
"910E4168387E3C30AA1E00C339A79508" \
"8452DD96A9A5EA5D9DCA68DA636032AF"
#define RSA_DP "C1ACF567564274FB07A0BBAD5D26E298" \
"3C94D22288ACD763FD8E5600ED4A702D" \
"F84198A5F06C2E72236AE490C93F07F8" \
"3CC559CD27BC2D1CA488811730BB5725"
#define RSA_DQ "4959CBF6F8FEF750AEE6977C155579C7" \
"D8AAEA56749EA28623272E4F7D0592AF" \
"7C1F1313CAC9471B5C523BFE592F517B" \
"407A1BD76C164B93DA2D32A383E58357"
#define RSA_QP "9AE7FBC99546432DF71896FC239EADAE" \
"F38D18D2B2F0E2DD275AA977E2BF4411" \
"F5A3B2A5D33605AEBBCCBA7FEB9F2D2F" \
"A74206CEC169D74BF5A8C50D6F48EA08"
#define KEY_LEN 128
mbedtls_rsa_context rsa;
mbedtls_rsa_init(&rsa, MBEDTLS_RSA_PKCS_V15, 0);
rsa.len = KEY_LEN;
rsa.len = RRG_RSA_KEY_LEN;
mbedtls_mpi_read_string(&rsa.N, 16, RSA_N);
mbedtls_mpi_read_string(&rsa.E, 16, RSA_E);
// add public key
mbedtls_mpi_read_string(&rsa.N, 16, RRG_RSA_N);
mbedtls_mpi_read_string(&rsa.E, 16, RRG_RSA_E);
// add private key
mbedtls_mpi_read_string(&rsa.D, 16, RSA_D);
mbedtls_mpi_read_string(&rsa.P, 16, RSA_P);
mbedtls_mpi_read_string(&rsa.Q, 16, RSA_Q);
@ -448,8 +502,6 @@ static int CmdFlashMemInfo(const char *Cmd) {
mbedtls_mpi_read_string(&rsa.DQ, 16, RSA_DQ);
mbedtls_mpi_read_string(&rsa.QP, 16, RSA_QP);
bool is_keyok = (mbedtls_rsa_check_pubkey(&rsa) == 0 || mbedtls_rsa_check_privkey(&rsa) == 0);
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, "--- " _CYAN_("RDV4 RSA Public key") " --------------");
@ -466,48 +518,35 @@ static int CmdFlashMemInfo(const char *Cmd) {
PrintAndLogEx(INFO, " %.64s", str_pk + 64);
PrintAndLogEx(INFO, " %.64s", str_pk + 128);
PrintAndLogEx(INFO, " %.64s", str_pk + 192);
PrintAndLogEx(NORMAL, "");
const char *msgkey = "RSA key validation... ";
if (is_keyok)
PrintAndLogEx(SUCCESS, "%s( " _GREEN_("ok") " )", msgkey);
else
PrintAndLogEx(FAILED, "%s( " _RED_("failed") " )", msgkey);
//
uint8_t from_device[KEY_LEN];
uint8_t sign[KEY_LEN];
bool is_keyok = (mbedtls_rsa_check_pubkey(&rsa) == 0 || mbedtls_rsa_check_privkey(&rsa) == 0);
PrintAndLogEx(
(is_keyok) ? SUCCESS : FAILED,
"RSA key validation... ( %s )",
(is_keyok) ? _GREEN_("ok") : _RED_("fail")
);
// to be verified
memcpy(from_device, mem.signature, KEY_LEN);
uint8_t from_device[RRG_RSA_KEY_LEN];
memcpy(from_device, mem.signature, RRG_RSA_KEY_LEN);
// to be signed (all zeros
memset(sign, 0, KEY_LEN);
// to be signed
uint8_t sign[RRG_RSA_KEY_LEN];
memset(sign, 0, RRG_RSA_KEY_LEN);
// Signing (private key)
if (shall_sign) {
int is_signed = mbedtls_rsa_pkcs1_sign(&rsa, NULL, NULL, MBEDTLS_RSA_PRIVATE, MBEDTLS_MD_SHA1, 20, sha_hash, sign);
const char *msgsign = "RSA signing.......... ";
if (is_signed == 0)
PrintAndLogEx(SUCCESS, "%s( " _GREEN_("ok") " )", msgsign);
else
PrintAndLogEx(FAILED, "%s( " _RED_("failed") " )", msgsign);
PrintAndLogEx(
(is_signed == 0) ? SUCCESS : FAILED,
"RSA signing.......... ( %s )",
(is_signed == 0) ? _GREEN_("ok") : _RED_("fail")
);
if (shall_write) {
// save to mem
clearCommandBuffer();
SendCommandOLD(CMD_FLASHMEM_WRITE, FLASH_MEM_SIGNATURE_OFFSET, FLASH_MEM_SIGNATURE_LEN, 0, sign, sizeof(sign));
if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
} else {
if (!resp.oldarg[0])
PrintAndLogEx(FAILED, "Writing signature failed");
else
PrintAndLogEx(SUCCESS, "Writing signature ok [offset: %u]", FLASH_MEM_SIGNATURE_OFFSET);
}
rdv4_sign_write(sign, RRG_RSA_KEY_LEN);
}
PrintAndLogEx(INFO, "Signed");
for (int i = 0; i < (sizeof(sign) / 32); i++) {
@ -517,14 +556,15 @@ static int CmdFlashMemInfo(const char *Cmd) {
// Verify (public key)
int is_verified = mbedtls_rsa_pkcs1_verify(&rsa, NULL, NULL, MBEDTLS_RSA_PUBLIC, MBEDTLS_MD_SHA1, 20, sha_hash, from_device);
const char *msgverify = "RSA verification..... ";
if (is_verified == 0)
PrintAndLogEx(SUCCESS, "%s( " _GREEN_("ok") " )", msgverify);
else
PrintAndLogEx(FAILED, "%s( " _RED_("failed") " )", msgverify);
mbedtls_rsa_free(&rsa);
PrintAndLogEx(
(is_verified == 0) ? SUCCESS : FAILED,
"RSA verification..... ( %s )",
(is_verified == 0) ? _GREEN_("ok") : _RED_("fail")
);
PrintAndLogEx(NORMAL, "");
mbedtls_rsa_free(&rsa);
return PM3_SUCCESS;
}

View file

@ -12,6 +12,7 @@
#define CMDFLASHMEM_H__
#include "common.h"
#include "pmflash.h" // rdv40validation_t
typedef enum {
DICTIONARY_NONE = 0,
@ -21,5 +22,6 @@ typedef enum {
} Dictionary_t;
int CmdFlashMem(const char *Cmd);
int rdv4_get_signature(rdv40_validation_t *out);
int rdv4_validate(rdv40_validation_t *mem);
#endif

View file

@ -40,7 +40,7 @@ typedef struct {
// sample set for selftest.
jooki_test_t jooks[] = {
{ {0x04, 0xDA, 0xB7, 0x6A, 0xE7, 0x4C, 0x80}, "ruxow8lnn88uyeX+", 0x01, 0x00},
{ {0x04, 0xf0, 0x22, 0xc2, 0x33, 0x5e, 0x80}, "\0", 0x01 , 0x00},
{ {0x04, 0xf0, 0x22, 0xc2, 0x33, 0x5e, 0x80}, "\0", 0x01, 0x00},
{ {0x04, 0x8C, 0xEC, 0xDA, 0xF0, 0x4A, 0x80}, "ONrsVf7jX6IaSNV6", 0x01, 0x01},
{ {0x04, 0x92, 0xA7, 0x6A, 0xE7, 0x4C, 0x81}, "Hjjpcx/mZwuveTF+", 0x01, 0x02},
{ {0x04, 0xD0, 0xB0, 0x3A, 0xD3, 0x63, 0x80}, "\0", 0x01, 0x02},
@ -106,7 +106,7 @@ jooki_figure_t jooks_figures[] = {
};
static int jooki_lookup(uint8_t tid, uint8_t fid) {
for (int i=0; i < ARRAYLEN(jooks_figures); i++) {
for (int i = 0; i < ARRAYLEN(jooks_figures); i++) {
jooki_figure_t tmp = jooks_figures[i];
if (tmp.typeid == tid && tmp.figureid == fid) {
return i;
@ -135,7 +135,7 @@ static int jooki_encode(uint8_t *iv, uint8_t tid, uint8_t fid, uint8_t *uid, uin
return PM3_EINVARG;
}
uint8_t d[JOOKI_PLAIN_LEN] = {iv[0], iv[1],iv[2], tid, fid, uid[0], uid[1], uid[2], uid[3], uid[4], uid[5], uid[6]};
uint8_t d[JOOKI_PLAIN_LEN] = {iv[0], iv[1], iv[2], tid, fid, uid[0], uid[1], uid[2], uid[3], uid[4], uid[5], uid[6]};
uint8_t enc[JOOKI_PLAIN_LEN] = {0};
for (uint8_t i = 0; i < JOOKI_PLAIN_LEN; i++) {
@ -150,7 +150,7 @@ static int jooki_encode(uint8_t *iv, uint8_t tid, uint8_t fid, uint8_t *uid, uin
size_t b64len = 0;
uint8_t b64[20];
memset(b64, 0, 20);
mbedtls_base64_encode(b64, sizeof(b64), &b64len, (const unsigned char*)enc, sizeof(enc));
mbedtls_base64_encode(b64, sizeof(b64), &b64len, (const unsigned char *)enc, sizeof(enc));
memcpy(out, b64, b64len);
return PM3_SUCCESS;
}
@ -158,7 +158,7 @@ static int jooki_encode(uint8_t *iv, uint8_t tid, uint8_t fid, uint8_t *uid, uin
static int jooki_decode(uint8_t *b64, uint8_t *result) {
uint8_t ndef[JOOKI_PLAIN_LEN] = {0};
size_t outputlen = 0;
mbedtls_base64_decode(ndef, sizeof(ndef), &outputlen, (const unsigned char*)b64, 16);
mbedtls_base64_decode(ndef, sizeof(ndef), &outputlen, (const unsigned char *)b64, 16);
PrintAndLogEx(DEBUG, "(decode_jooki) raw encoded... " _GREEN_("%s"), sprint_hex(ndef, sizeof(ndef)));
@ -237,7 +237,7 @@ static int jooki_selftest(void) {
uint8_t iv[JOOKI_IV_LEN] = {0};
uint8_t uid[JOOKI_UID_LEN] = {0};
uint8_t result[JOOKI_PLAIN_LEN] = {0};
jooki_decode((uint8_t*)jooks[i].b64, result);
jooki_decode((uint8_t *)jooks[i].b64, result);
memcpy(iv, result, JOOKI_IV_LEN);
uint8_t tid = result[3];
@ -250,7 +250,7 @@ static int jooki_selftest(void) {
int idx = jooki_lookup(tid, fid);
PrintAndLogEx(INFO, "Encoded URL.. %s ( %s )", sprint_hex((const uint8_t*)jooks[i].b64, 12), jooks[i].b64);
PrintAndLogEx(INFO, "Encoded URL.. %s ( %s )", sprint_hex((const uint8_t *)jooks[i].b64, 12), jooks[i].b64);
PrintAndLogEx(INFO, "Type......... %02x - " _GREEN_("%s") " ( %s )", tid, (idx != -1) ? jooks_figures[idx].typedesc : "n/a", tid_ok ? _GREEN_("ok") : _RED_("fail"));
PrintAndLogEx(INFO, "Figurine..... %02x - " _GREEN_("%s") " ( %s )", fid, (idx != -1) ? jooks_figures[idx].figdesc : "n/a", fid_ok ? _GREEN_("ok") : _RED_("fail"));
PrintAndLogEx(INFO, "iv........... %s", sprint_hex(iv, sizeof(iv)));
@ -265,7 +265,7 @@ static int jooki_selftest(void) {
PrintAndLogEx(INFO, "NDEF raw .... %s", sprint_hex(ndefmsg, sizeof(ndefmsg)));
int status = NDEFRecordsDecodeAndPrint(ndefmsg, sizeof(ndefmsg));
if ( status != PM3_SUCCESS) {
if (status != PM3_SUCCESS) {
status = NDEFDecodeAndPrint(ndefmsg, sizeof(ndefmsg), true);
}
PrintAndLogEx(INFO, "==================================================================");
@ -346,11 +346,11 @@ static int CmdHF14AJookiEncode(const char *Cmd) {
uint8_t tid, fid;
if( ftid || ffid ) {
if (ftid || ffid) {
figure_abbr = false;
}
if ( ftid > 0x04 || ffid > 0x20 ) {
if (ftid > 0x04 || ffid > 0x20) {
PrintAndLogEx(ERR, "Use a valid Figure Type ID and Figure ID");
return PM3_EINVARG;
}
@ -484,7 +484,7 @@ static int CmdHF14AJookiSim(const char *Cmd) {
uint8_t *data = calloc(144, sizeof(uint8_t));
memcpy(data, uid, 3);
memcpy(data + (1*4), uid + 3, 4);
memcpy(data + (1 * 4), uid + 3, 4);
// bbc0
data[3] = 0x88 ^ data[0] ^ data[1] ^ data[2];
@ -493,7 +493,7 @@ static int CmdHF14AJookiSim(const char *Cmd) {
data[8] = data[4] ^ data[5] ^ data[6] ^ data[7];
// copy NDEF magic firs, skip BBC1
memcpy(data + (2*4) + 1, "\x48\x00\x00\xE1\x10\x12\x00", 7);
memcpy(data + (2 * 4) + 1, "\x48\x00\x00\xE1\x10\x12\x00", 7);
// copy raw NDEF
jooki_create_ndef(b64, data + (4 * 4));
@ -573,7 +573,7 @@ static int CmdHF14AJookiSim(const char *Cmd) {
}
free(data);
PrintAndLogEx(INFO, "Done");
PrintAndLogEx(HINT, "Try `" _YELLOW_("hf 14a list") "` to view trace log" );
PrintAndLogEx(HINT, "Try `" _YELLOW_("hf 14a list") "` to view trace log");
return PM3_SUCCESS;
}
@ -581,7 +581,7 @@ static int CmdHF14AJookiClone(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "hf jooki clone",
"Write a Jooki token to a Ultralight or NTAG tag",
"hf jooki clone -d <hex bytes> --> where hex is raw NDEF"
"hf jooki clone -d <hex bytes> --> where hex is raw NDEF\n"
"hf jooki clone --b64 7WzlgEzqLgwTnWNy --> using base64 url parameter"
);
@ -651,7 +651,7 @@ static int CmdHF14AJookiClone(const char *Cmd) {
}
PrintAndLogEx(INFO, "Done");
PrintAndLogEx(HINT, "Try `" _YELLOW_("hf mfu ndef") "` to view" );
PrintAndLogEx(HINT, "Try `" _YELLOW_("hf mfu ndef") "` to view");
return PM3_SUCCESS;
}

View file

@ -3560,14 +3560,14 @@ static int CmdHF14MfuNDEF(const char *Cmd) {
DropField();
status = NDEFRecordsDecodeAndPrint(records, (size_t)maxsize);
if ( status != PM3_SUCCESS) {
if (status != PM3_SUCCESS) {
status = NDEFDecodeAndPrint(records, (size_t)maxsize, true);
}
char *jooki = strstr((char*)records, "s.jooki.rocks/s/?s=");
char *jooki = strstr((char *)records, "s.jooki.rocks/s/?s=");
if (jooki) {
jooki += 17;
while(jooki) {
while (jooki) {
if ((*jooki) != '=')
jooki++;
else {

View file

@ -23,6 +23,8 @@
#include "cmddata.h"
#include "commonutil.h"
#include "pm3_cmd.h"
#include "pmflash.h" // rdv40validation_t
#include "cmdflashmem.h" // get_signature..
static int CmdHelp(const char *Cmd);
@ -959,17 +961,29 @@ void pm3_version(bool verbose, bool oneliner) {
PrintAndLogEx(NORMAL, " compiled with " PM3CLIENTCOMPILER __VERSION__ PM3HOSTOS PM3HOSTARCH);
PrintAndLogEx(NORMAL, "\n [ " _YELLOW_("PROXMARK3") " ]");
if (IfPm3Rdv4Fw() == false) {
PrintAndLogEx(NORMAL, " firmware.................. %s", _YELLOW_("PM3GENERIC"));
if (IfPm3FpcUsartHost()) {
PrintAndLogEx(NORMAL, " FPC USART for BT add-on... %s", _GREEN_("present"));
if (IfPm3Rdv4Fw()) {
bool is_genuine_rdv4 = false;
// validate signature data
rdv40_validation_t mem;
if (rdv4_get_signature(&mem) == PM3_SUCCESS) {
if (rdv4_validate(&mem) == PM3_SUCCESS) {
is_genuine_rdv4 = true;
}
} else {
PrintAndLogEx(NORMAL, " firmware.................. %s", _YELLOW_("PM3RDV4"));
}
PrintAndLogEx(NORMAL, " device.................... %s", (is_genuine_rdv4) ? _GREEN_("RDV4") : _RED_("device / fw mismatch"));
PrintAndLogEx(NORMAL, " firmware.................. %s", _YELLOW_("RDV4"));
PrintAndLogEx(NORMAL, " external flash............ %s", IfPm3Flash() ? _GREEN_("present") : _YELLOW_("absent"));
PrintAndLogEx(NORMAL, " smartcard reader.......... %s", IfPm3Smartcard() ? _GREEN_("present") : _YELLOW_("absent"));
PrintAndLogEx(NORMAL, " FPC USART for BT add-on... %s", IfPm3FpcUsartHost() ? _GREEN_("present") : _YELLOW_("absent"));
} else {
PrintAndLogEx(NORMAL, " firmware.................. %s", _YELLOW_("PM3 GENERIC"));
if (IfPm3FpcUsartHost()) {
PrintAndLogEx(NORMAL, " FPC USART for BT add-on... %s", _GREEN_("present"));
}
}
if (IfPm3FpcUsartDevFromUsb()) {
PrintAndLogEx(NORMAL, " FPC USART for developer... %s", _GREEN_("present"));
}

View file

@ -356,11 +356,9 @@ static int CmdHIDClone(const char *Cmd) {
bool q5 = arg_get_lit(ctx, 7);
bool em = arg_get_lit(ctx, 8);
int bin_len = 63;
uint8_t bin[70] = {0};
CLIGetStrWithReturn(ctx, 9, bin, &bin_len);
CLIParserFree(ctx);
if (q5 && em) {
@ -383,12 +381,21 @@ static int CmdHIDClone(const char *Cmd) {
return PM3_EINVARG;
}
if (raw_len) {
uint32_t top = 0, mid = 0, bot = 0;
if (raw_len) {
hexstring_to_u96(&top, &mid, &bot, raw);
packed.Top = top;
packed.Mid = mid;
packed.Bot = bot;
} else if (bin_len) {
int res = binstring_to_u96(&top, &mid, &bot, (const char*)bin);
if (res != bin_len) {
PrintAndLogEx(ERR, "Binary string contains none <0|1> chars");
return PM3_EINVARG;
}
packed.Top = top;
packed.Mid = mid;
packed.Bot = bot;
} else {
if (HIDPack(format_idx, &card, &packed, true) == false) {
PrintAndLogEx(WARNING, "The card data could not be encoded in the selected format.");

View file

@ -60,7 +60,7 @@ int CmdWiegandEncode(const char *Cmd) {
arg_u64_0(NULL, "issue", "<dec>", "issue level"),
arg_u64_0(NULL, "oem", "<dec>", "OEM code"),
arg_str0("w", "wiegand", "<format>", "see `wiegand list` for available formats"),
arg_lit0(NULL, "pre", "add HID preamble to wiegand"),
arg_lit0(NULL, "pre", "add HID ProxII preamble to wiegand output"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);

View file

@ -951,13 +951,13 @@ char *str_ndup(const char *src, size_t len) {
}
/**
* Converts a hex string to component "hi2", "hi" and "lo" 32-bit integers, one nibble
* at a time.
* Converts a hex string to component "hi2", "hi" and "lo" 32-bit integers
* one nibble at a time.
*
* Returns the number of nibbles (4 bits) entered.
*/
int hexstring_to_u96(uint32_t *hi2, uint32_t *hi, uint32_t *lo, const char *str) {
unsigned int n = 0, i = 0;
uint32_t n = 0, i = 0;
while (sscanf(&str[i++], "%1x", &n) == 1) {
*hi2 = (*hi2 << 4) | (*hi >> 28);
@ -967,6 +967,30 @@ int hexstring_to_u96(uint32_t *hi2, uint32_t *hi, uint32_t *lo, const char *str)
return i - 1;
}
/**
* Converts a binary string to component "hi2", "hi" and "lo" 32-bit integers,
* one bit at a time.
*
* Returns the number of bits entered.
*/
int binstring_to_u96(uint32_t *hi2, uint32_t *hi, uint32_t *lo, const char *str) {
uint32_t n = 0, i = 0;
for(;;) {
int res = sscanf(&str[i], "%1u", &n);
if ((res != 1) || (n > 1))
break;
*hi2 = (*hi2 << 1) | (*hi >> 31);
*hi = (*hi << 1) | (*lo >> 31);
*lo = (*lo << 1) | (n & 0x1);
i++;
}
return i;
}
inline uint32_t bitcount32(uint32_t a) {
#if defined __GNUC__
return __builtin_popcountl(a);

View file

@ -105,6 +105,7 @@ void strcreplace(char *buf, size_t len, char from, char to);
char *str_dup(const char *src);
char *str_ndup(const char *src, size_t len);
int hexstring_to_u96(uint32_t *hi2, uint32_t *hi, uint32_t *lo, const char *str);
int binstring_to_u96(uint32_t *hi2, uint32_t *hi, uint32_t *lo, const char *str);
uint32_t bitcount32(uint32_t a);
uint64_t bitcount64(uint64_t a);

View file

@ -143,7 +143,7 @@ Check column "offline" for their availability.
|`hf 14a raw `|N |`Send raw hex data to tag`
|`hf 14a antifuzz `|N |`Fuzzing the anticollision phase. Warning! Readers may react strange`
|`hf 14a config `|N |`Configure 14a settings (use with caution)`
|`hf 14a apdufind `|N |`Enuerate APDUs - CLA/INS/P1P2`
|`hf 14a apdufind `|N |`Enumerate APDUs - CLA/INS/P1P2`
### hf 14b
@ -255,6 +255,19 @@ Check column "offline" for their availability.
|`hf fido assert `|N |`FIDO2 GetAssertion command.`
### hf jooki
{ Jooki RFIDs... }
|command |offline |description
|------- |------- |-----------
|`hf jooki help `|Y |`This help`
|`hf jooki clone `|N |`Write a Jooki token`
|`hf jooki decode `|Y |`Decode Jooki token`
|`hf jooki encode `|Y |`Encode Jooki token`
|`hf jooki sim `|N |`Simulate Jooki token`
### hf iclass
{ ICLASS RFIDs... }