mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-07-30 19:40:37 -07:00
mem info , now supports loading PEM with private key
This commit is contained in:
parent
1d6b4b2722
commit
e35ebf6b69
2 changed files with 140 additions and 80 deletions
|
@ -17,6 +17,7 @@
|
||||||
#include "cmdflashmemspiffs.h" // spiffs commands
|
#include "cmdflashmemspiffs.h" // spiffs commands
|
||||||
#include "rsa.h"
|
#include "rsa.h"
|
||||||
#include "sha1.h"
|
#include "sha1.h"
|
||||||
|
#include "pk.h" // PEM key load functions
|
||||||
|
|
||||||
#define MCK 48000000
|
#define MCK 48000000
|
||||||
#define FLASH_MINFAST 24000000 //33000000
|
#define FLASH_MINFAST 24000000 //33000000
|
||||||
|
@ -128,6 +129,7 @@ int rdv4_validate(rdv40_validation_t *mem) {
|
||||||
return PM3_EFAILED;
|
return PM3_EFAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int rdv4_sign_write(uint8_t *signature, uint8_t slen){
|
static int rdv4_sign_write(uint8_t *signature, uint8_t slen){
|
||||||
// save to mem
|
// save to mem
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
|
@ -401,9 +403,9 @@ static int CmdFlashMemWipe(const char *Cmd) {
|
||||||
CLIParserContext *ctx;
|
CLIParserContext *ctx;
|
||||||
CLIParserInit(&ctx, "mem wipe",
|
CLIParserInit(&ctx, "mem wipe",
|
||||||
"Wipe flash memory on device, which fills it with 0xFF\n"
|
"Wipe flash memory on device, which fills it with 0xFF\n"
|
||||||
_WHITE_("[ ") _RED_("!!! OBS") " ] use with caution",
|
_WHITE_("[ ") _RED_("!!! OBS") _WHITE_(" ] use with caution"),
|
||||||
"mem wipe -p 0 -> wipes first page"
|
"mem wipe -p 0 -> wipes first page"
|
||||||
// "mem wipe -i -> inital total wipe"
|
// "mem wipe -i -> inital total wipe"
|
||||||
);
|
);
|
||||||
|
|
||||||
void *argtable[] = {
|
void *argtable[] = {
|
||||||
|
@ -450,33 +452,84 @@ static int CmdFlashMemInfo(const char *Cmd) {
|
||||||
CLIParserInit(&ctx, "mem info",
|
CLIParserInit(&ctx, "mem info",
|
||||||
"Collect signature and verify it from flash memory",
|
"Collect signature and verify it from flash memory",
|
||||||
"mem info"
|
"mem info"
|
||||||
// "mem info -s -d 0102030405060708"
|
|
||||||
);
|
);
|
||||||
|
|
||||||
void *argtable[] = {
|
void *argtable[] = {
|
||||||
arg_param_begin,
|
arg_param_begin,
|
||||||
arg_lit0("s", "sign", "create a signature"),
|
arg_lit0("s", "sign", "create a signature"),
|
||||||
arg_str0("d", NULL, "<hex>", "flash memory id, 8 hex bytes"),
|
arg_str0("d", NULL, "<hex>", "flash memory id, 8 hex bytes"),
|
||||||
|
arg_str0("p", "pem", "<fn>", "key in PEM format"),
|
||||||
|
arg_lit0("v", "verbose", "verbose output"),
|
||||||
// arg_lit0("w", "write", "write signature to flash memory"),
|
// arg_lit0("w", "write", "write signature to flash memory"),
|
||||||
arg_param_end
|
arg_param_end
|
||||||
};
|
};
|
||||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||||
|
|
||||||
bool shall_sign = false, shall_write = false;
|
bool shall_sign = arg_get_lit(ctx, 1);
|
||||||
shall_sign = arg_get_lit(ctx, 1);
|
|
||||||
|
|
||||||
int dlen = 0;
|
int dlen = 0;
|
||||||
uint8_t id[8] = {0};
|
uint8_t id[8] = {0};
|
||||||
int res = CLIParamHexToBuf(arg_get_str(ctx, 2), id, sizeof(id), &dlen);
|
int res = CLIParamHexToBuf(arg_get_str(ctx, 2), id, sizeof(id), &dlen);
|
||||||
|
|
||||||
// shall_write = arg_get_lit(ctx, 3);
|
int pemlen = 0;
|
||||||
|
char pem_fn[FILE_PATH_SIZE] = {0};
|
||||||
|
CLIParamStrToBuf(arg_get_str(ctx, 3), (uint8_t *)pem_fn, FILE_PATH_SIZE, &pemlen);
|
||||||
|
|
||||||
|
bool verbose = arg_get_lit(ctx, 4);
|
||||||
|
bool shall_write = false;
|
||||||
|
// shall_write = arg_get_lit(ctx, 5);
|
||||||
CLIParserFree(ctx);
|
CLIParserFree(ctx);
|
||||||
|
|
||||||
if (dlen > 0 && dlen < sizeof(id) ) {
|
if (res || (dlen > 0 && dlen < sizeof(id)) ) {
|
||||||
PrintAndLogEx(FAILED, "Error parsing flash memory id, expect 8, got %d", dlen);
|
PrintAndLogEx(FAILED, "Error parsing flash memory id, expect 8, got %d", dlen);
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// set up PK key context now.
|
||||||
|
mbedtls_pk_context pkctx;
|
||||||
|
mbedtls_pk_init( &pkctx );
|
||||||
|
bool got_private = false;
|
||||||
|
// PEM
|
||||||
|
if (pemlen) {
|
||||||
|
// PEM file
|
||||||
|
char *path = NULL;
|
||||||
|
if (searchFile(&path, RESOURCES_SUBDIR, pem_fn, ".pem", true) != PM3_SUCCESS) {
|
||||||
|
if (searchFile(&path, RESOURCES_SUBDIR, pem_fn, "", false) != PM3_SUCCESS) {
|
||||||
|
return PM3_EFILE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PrintAndLogEx(INFO, "loading file `" _YELLOW_("%s") "`" NOLF, path);
|
||||||
|
|
||||||
|
// load private
|
||||||
|
res = mbedtls_pk_parse_keyfile(&pkctx, path, NULL);
|
||||||
|
//res = mbedtls_pk_parse_public_keyfile(&pkctx, path);
|
||||||
|
if (res == 0) {
|
||||||
|
PrintAndLogEx(NORMAL, " ( " _GREEN_("ok") " )");
|
||||||
|
} else {
|
||||||
|
PrintAndLogEx(NORMAL, " ( " _RED_("fail") " )");
|
||||||
|
mbedtls_pk_free(&pkctx);
|
||||||
|
free(path);
|
||||||
|
return PM3_EFILE;
|
||||||
|
}
|
||||||
|
|
||||||
|
mbedtls_rsa_context *rsa = (mbedtls_rsa_context*)pkctx.pk_ctx;
|
||||||
|
if (rsa == NULL) {
|
||||||
|
PrintAndLogEx(FAILED, "failed to allocate rsa context memory");
|
||||||
|
return PM3_EMALLOC;
|
||||||
|
}
|
||||||
|
free(path);
|
||||||
|
got_private = true;
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// it not loaded, we need to setup the context manually
|
||||||
|
if (mbedtls_pk_setup( &pkctx, mbedtls_pk_info_from_type( (mbedtls_pk_type_t) MBEDTLS_PK_RSA ) ) != 0 ) {
|
||||||
|
PrintAndLogEx(FAILED, "failed, mbedtls_pk_setup returned ");
|
||||||
|
return PM3_ESOFT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// validate devicesignature data
|
// validate devicesignature data
|
||||||
rdv40_validation_t mem;
|
rdv40_validation_t mem;
|
||||||
res = rdv4_get_signature(&mem);
|
res = rdv4_get_signature(&mem);
|
||||||
|
@ -494,66 +547,69 @@ static int CmdFlashMemInfo(const char *Cmd) {
|
||||||
PrintAndLogEx(INFO, "--- " _CYAN_("Flash memory Information") " ---------");
|
PrintAndLogEx(INFO, "--- " _CYAN_("Flash memory Information") " ---------");
|
||||||
PrintAndLogEx(INFO, "ID................... %s", sprint_hex_inrow(mem.flashid, sizeof(mem.flashid)));
|
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(INFO, "SHA1................. %s", sprint_hex_inrow(sha_hash, sizeof(sha_hash)));
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
PrintAndLogEx(INFO, "--- " _CYAN_("RDV4 RSA signature") " ---------------");
|
||||||
|
for (int i = 0; i < (sizeof(mem.signature) / 32); i++) {
|
||||||
|
PrintAndLogEx(INFO, " %s", sprint_hex_inrow(mem.signature + (i * 32), 32));
|
||||||
|
}
|
||||||
PrintAndLogEx(
|
PrintAndLogEx(
|
||||||
(res == PM3_SUCCESS) ? SUCCESS : FAILED,
|
(res == PM3_SUCCESS) ? SUCCESS : FAILED,
|
||||||
"Signature............ ( %s )",
|
"Signature............ ( %s )",
|
||||||
(res == PM3_SUCCESS) ? _GREEN_("ok") : _RED_("fail")
|
(res == PM3_SUCCESS) ? _GREEN_("ok") : _RED_("fail")
|
||||||
);
|
);
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(INFO, "--- " _CYAN_("RDV4 RSA signature") " ---------------");
|
|
||||||
for (int i = 0; i < (sizeof(mem.signature) / 32); i++) {
|
mbedtls_rsa_context *rsa = NULL;
|
||||||
PrintAndLogEx(INFO, " %s", sprint_hex_inrow(mem.signature + (i * 32), 32));
|
|
||||||
|
if (got_private) {
|
||||||
|
rsa = mbedtls_pk_rsa( pkctx );
|
||||||
|
rsa->padding = MBEDTLS_RSA_PKCS_V15;
|
||||||
|
rsa->hash_id = 0;
|
||||||
|
rsa->len = RRG_RSA_KEY_LEN;
|
||||||
|
} else {
|
||||||
|
|
||||||
|
rsa = (mbedtls_rsa_context *)calloc(1, sizeof(mbedtls_rsa_context));
|
||||||
|
mbedtls_rsa_init(rsa, MBEDTLS_RSA_PKCS_V15, 0);
|
||||||
|
rsa->len = RRG_RSA_KEY_LEN;
|
||||||
|
|
||||||
|
// add public key
|
||||||
|
mbedtls_mpi_read_string(&rsa->N, 16, RRG_RSA_N);
|
||||||
|
mbedtls_mpi_read_string(&rsa->E, 16, RRG_RSA_E);
|
||||||
}
|
}
|
||||||
|
|
||||||
mbedtls_rsa_context rsa;
|
|
||||||
mbedtls_rsa_init(&rsa, MBEDTLS_RSA_PKCS_V15, 0);
|
|
||||||
|
|
||||||
rsa.len = RRG_RSA_KEY_LEN;
|
|
||||||
|
|
||||||
// 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);
|
|
||||||
mbedtls_mpi_read_string(&rsa.DP, 16, RSA_DP);
|
|
||||||
mbedtls_mpi_read_string(&rsa.DQ, 16, RSA_DQ);
|
|
||||||
mbedtls_mpi_read_string(&rsa.QP, 16, RSA_QP);
|
|
||||||
|
|
||||||
PrintAndLogEx(NORMAL, "");
|
|
||||||
PrintAndLogEx(INFO, "--- " _CYAN_("RDV4 RSA Public key") " --------------");
|
PrintAndLogEx(INFO, "--- " _CYAN_("RDV4 RSA Public key") " --------------");
|
||||||
|
if (verbose) {
|
||||||
|
char str_exp[10];
|
||||||
|
char str_pk[261];
|
||||||
|
size_t exlen = 0, pklen = 0;
|
||||||
|
mbedtls_mpi_write_string(&rsa->E, 16, str_exp, sizeof(str_exp), &exlen);
|
||||||
|
mbedtls_mpi_write_string(&rsa->N, 16, str_pk, sizeof(str_pk), &pklen);
|
||||||
|
|
||||||
char str_exp[10];
|
PrintAndLogEx(INFO, "Len.................. %"PRIu64, rsa->len);
|
||||||
char str_pk[261];
|
PrintAndLogEx(INFO, "Exponent............. %s", str_exp);
|
||||||
size_t exlen = 0, pklen = 0;
|
PrintAndLogEx(INFO, "Public key modulus N");
|
||||||
mbedtls_mpi_write_string(&rsa.E, 16, str_exp, sizeof(str_exp), &exlen);
|
PrintAndLogEx(INFO, " %.64s", str_pk);
|
||||||
mbedtls_mpi_write_string(&rsa.N, 16, str_pk, sizeof(str_pk), &pklen);
|
PrintAndLogEx(INFO, " %.64s", str_pk + 64);
|
||||||
|
PrintAndLogEx(INFO, " %.64s", str_pk + 128);
|
||||||
|
PrintAndLogEx(INFO, " %.64s", str_pk + 192);
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
}
|
||||||
|
|
||||||
PrintAndLogEx(INFO, "Len.................. %"PRIu64, rsa.len);
|
bool is_keyok = (mbedtls_rsa_check_pubkey(rsa) == 0);
|
||||||
PrintAndLogEx(INFO, "Exponent............. %s", str_exp);
|
|
||||||
PrintAndLogEx(INFO, "Public key modulus N");
|
|
||||||
PrintAndLogEx(INFO, " %.64s", str_pk);
|
|
||||||
PrintAndLogEx(INFO, " %.64s", str_pk + 64);
|
|
||||||
PrintAndLogEx(INFO, " %.64s", str_pk + 128);
|
|
||||||
PrintAndLogEx(INFO, " %.64s", str_pk + 192);
|
|
||||||
PrintAndLogEx(NORMAL, "");
|
|
||||||
|
|
||||||
bool is_keyok = (mbedtls_rsa_check_pubkey(&rsa) == 0);
|
|
||||||
PrintAndLogEx(
|
PrintAndLogEx(
|
||||||
(is_keyok) ? SUCCESS : FAILED,
|
(is_keyok) ? SUCCESS : FAILED,
|
||||||
"RSA public key validation.... ( %s )",
|
"RRG/Iceman RSA public key check.... ( %s )",
|
||||||
(is_keyok) ? _GREEN_("ok") : _RED_("fail")
|
|
||||||
);
|
|
||||||
|
|
||||||
is_keyok = (mbedtls_rsa_check_privkey(&rsa) == 0);
|
|
||||||
PrintAndLogEx(
|
|
||||||
(is_keyok) ? SUCCESS : FAILED,
|
|
||||||
"RSA private key validation... ( %s )",
|
|
||||||
(is_keyok) ? _GREEN_("ok") : _RED_("fail")
|
(is_keyok) ? _GREEN_("ok") : _RED_("fail")
|
||||||
);
|
);
|
||||||
|
|
||||||
|
is_keyok = (mbedtls_rsa_check_privkey(rsa) == 0);
|
||||||
|
if (verbose) {
|
||||||
|
PrintAndLogEx(
|
||||||
|
(is_keyok) ? SUCCESS : FAILED,
|
||||||
|
"RRG/Iceman RSA private key check... ( %s )",
|
||||||
|
(is_keyok) ? _GREEN_("ok") : _YELLOW_("N/A")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// to be verified
|
// to be verified
|
||||||
uint8_t from_device[RRG_RSA_KEY_LEN];
|
uint8_t from_device[RRG_RSA_KEY_LEN];
|
||||||
|
@ -565,43 +621,47 @@ static int CmdFlashMemInfo(const char *Cmd) {
|
||||||
|
|
||||||
// Signing (private key)
|
// Signing (private key)
|
||||||
if (shall_sign) {
|
if (shall_sign) {
|
||||||
PrintAndLogEx(NORMAL, "");
|
|
||||||
PrintAndLogEx(INFO, "--- " _CYAN_("Enter signing") " --------------------");
|
|
||||||
|
|
||||||
if (dlen == 8) {
|
if (is_keyok) {
|
||||||
mbedtls_sha1(id, sizeof(id), sha_hash);
|
|
||||||
}
|
|
||||||
PrintAndLogEx(INFO, "Signing %s", sprint_hex_inrow(sha_hash, sizeof(sha_hash)));
|
|
||||||
|
|
||||||
int is_signed = mbedtls_rsa_pkcs1_sign(&rsa, NULL, NULL, MBEDTLS_RSA_PRIVATE, MBEDTLS_MD_SHA1, 20, sha_hash, sign);
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(
|
PrintAndLogEx(INFO, "--- " _CYAN_("Enter signing") " --------------------");
|
||||||
(is_signed == 0) ? SUCCESS : FAILED,
|
|
||||||
"RSA signing.......... ( %s )",
|
if (dlen == 8) {
|
||||||
(is_signed == 0) ? _GREEN_("ok") : _RED_("fail")
|
mbedtls_sha1(id, sizeof(id), sha_hash);
|
||||||
);
|
}
|
||||||
|
PrintAndLogEx(INFO, "Signing....... %s", sprint_hex_inrow(sha_hash, sizeof(sha_hash)));
|
||||||
if (shall_write) {
|
|
||||||
rdv4_sign_write(sign, RRG_RSA_KEY_LEN);
|
int is_signed = mbedtls_rsa_pkcs1_sign(rsa, NULL, NULL, MBEDTLS_RSA_PRIVATE, MBEDTLS_MD_SHA1, 20, sha_hash, sign);
|
||||||
}
|
PrintAndLogEx(
|
||||||
PrintAndLogEx(INFO, "Signed");
|
(is_signed == 0) ? SUCCESS : FAILED,
|
||||||
for (int i = 0; i < (sizeof(sign) / 32); i++) {
|
"RSA signing... ( %s )",
|
||||||
PrintAndLogEx(INFO, " %s", sprint_hex_inrow(sign + (i * 32), 32));
|
(is_signed == 0) ? _GREEN_("ok") : _RED_("fail")
|
||||||
|
);
|
||||||
|
|
||||||
|
if (shall_write) {
|
||||||
|
rdv4_sign_write(sign, RRG_RSA_KEY_LEN);
|
||||||
|
}
|
||||||
|
PrintAndLogEx(INFO, "New signature");
|
||||||
|
for (int i = 0; i < (sizeof(sign) / 32); i++) {
|
||||||
|
PrintAndLogEx(INFO, " %s", sprint_hex_inrow(sign + (i * 32), 32));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
PrintAndLogEx(FAILED, "no private key available to sign");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify (public key)
|
// Verify (public key)
|
||||||
bool is_verified = (mbedtls_rsa_pkcs1_verify(&rsa, NULL, NULL, MBEDTLS_RSA_PUBLIC, MBEDTLS_MD_SHA1, 20, sha_hash, from_device) == 0);
|
bool is_verified = (mbedtls_rsa_pkcs1_verify(rsa, NULL, NULL, MBEDTLS_RSA_PUBLIC, MBEDTLS_MD_SHA1, 20, sha_hash, from_device) == 0);
|
||||||
mbedtls_rsa_free(&rsa);
|
|
||||||
|
|
||||||
|
mbedtls_pk_free(&pkctx);
|
||||||
|
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(
|
PrintAndLogEx(
|
||||||
(is_verified) ? SUCCESS : FAILED,
|
(is_verified) ? SUCCESS : FAILED,
|
||||||
"RSA verification..... ( %s )",
|
"Genuine Proxmark3 RDV4 signature detected... %s",
|
||||||
(is_verified) ? _GREEN_("ok") : _RED_("fail")
|
(is_verified) ? ":heavy_check_mark:" : ":x:"
|
||||||
);
|
);
|
||||||
if (is_verified) {
|
|
||||||
PrintAndLogEx(SUCCESS, "Genuine Proxmark3 RDV4 signature detected");
|
|
||||||
}
|
|
||||||
|
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1805,7 +1805,7 @@ int searchFile(char **foundpath, const char *pm3dir, const char *searchname, con
|
||||||
int res = searchFinalFile(foundpath, pm3dir, filename, silent);
|
int res = searchFinalFile(foundpath, pm3dir, filename, silent);
|
||||||
if (res != PM3_SUCCESS) {
|
if (res != PM3_SUCCESS) {
|
||||||
if ((res == PM3_EFILE) && (!silent))
|
if ((res == PM3_EFILE) && (!silent))
|
||||||
PrintAndLogEx(FAILED, "Error - can't find %s", filename);
|
PrintAndLogEx(FAILED, "Error - can't find `" _YELLOW_("%s") "`", filename);
|
||||||
free(filename);
|
free(filename);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue