From e35ebf6b6938802d630c3d45a82c1af328ed33cf Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 31 Mar 2021 15:52:57 +0200 Subject: [PATCH] mem info , now supports loading PEM with private key --- client/src/cmdflashmem.c | 218 +++++++++++++++++++++++++-------------- client/src/fileutils.c | 2 +- 2 files changed, 140 insertions(+), 80 deletions(-) diff --git a/client/src/cmdflashmem.c b/client/src/cmdflashmem.c index 34f60bd51..c0a12cc39 100644 --- a/client/src/cmdflashmem.c +++ b/client/src/cmdflashmem.c @@ -17,6 +17,7 @@ #include "cmdflashmemspiffs.h" // spiffs commands #include "rsa.h" #include "sha1.h" +#include "pk.h" // PEM key load functions #define MCK 48000000 #define FLASH_MINFAST 24000000 //33000000 @@ -128,6 +129,7 @@ int rdv4_validate(rdv40_validation_t *mem) { return PM3_EFAILED; } + static int rdv4_sign_write(uint8_t *signature, uint8_t slen){ // save to mem clearCommandBuffer(); @@ -401,9 +403,9 @@ static int CmdFlashMemWipe(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "mem wipe", "Wipe flash memory on device, which fills it with 0xFF\n" - _WHITE_("[ ") _RED_("!!! OBS") " ] use with caution", - "mem wipe -p 0 -> wipes first page" -// "mem wipe -i -> inital total wipe" + _WHITE_("[ ") _RED_("!!! OBS") _WHITE_(" ] use with caution"), + "mem wipe -p 0 -> wipes first page" +// "mem wipe -i -> inital total wipe" ); void *argtable[] = { @@ -450,33 +452,84 @@ static int CmdFlashMemInfo(const char *Cmd) { CLIParserInit(&ctx, "mem info", "Collect signature and verify it from flash memory", "mem info" -// "mem info -s -d 0102030405060708" ); void *argtable[] = { arg_param_begin, arg_lit0("s", "sign", "create a signature"), arg_str0("d", NULL, "", "flash memory id, 8 hex bytes"), + arg_str0("p", "pem", "", "key in PEM format"), + arg_lit0("v", "verbose", "verbose output"), // arg_lit0("w", "write", "write signature to flash memory"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); - bool shall_sign = false, shall_write = false; - shall_sign = arg_get_lit(ctx, 1); + bool shall_sign = arg_get_lit(ctx, 1); int dlen = 0; uint8_t id[8] = {0}; 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); - 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); 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 rdv40_validation_t mem; res = rdv4_get_signature(&mem); @@ -494,66 +547,69 @@ static int CmdFlashMemInfo(const char *Cmd) { PrintAndLogEx(INFO, "--- " _CYAN_("Flash memory Information") " ---------"); 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, ""); + 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( (res == PM3_SUCCESS) ? SUCCESS : FAILED, "Signature............ ( %s )", (res == PM3_SUCCESS) ? _GREEN_("ok") : _RED_("fail") ); 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)); + + mbedtls_rsa_context *rsa = NULL; + + 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") " --------------"); + 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]; - 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); + PrintAndLogEx(INFO, "Len.................. %"PRIu64, rsa->len); + 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, ""); + } - PrintAndLogEx(INFO, "Len.................. %"PRIu64, rsa.len); - 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); + bool is_keyok = (mbedtls_rsa_check_pubkey(rsa) == 0); PrintAndLogEx( (is_keyok) ? SUCCESS : FAILED, - "RSA public key validation.... ( %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 )", + "RRG/Iceman RSA public key check.... ( %s )", (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 uint8_t from_device[RRG_RSA_KEY_LEN]; @@ -565,43 +621,47 @@ static int CmdFlashMemInfo(const char *Cmd) { // Signing (private key) if (shall_sign) { - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(INFO, "--- " _CYAN_("Enter signing") " --------------------"); - if (dlen == 8) { - mbedtls_sha1(id, sizeof(id), sha_hash); - } - PrintAndLogEx(INFO, "Signing %s", sprint_hex_inrow(sha_hash, sizeof(sha_hash))); + if (is_keyok) { - int is_signed = mbedtls_rsa_pkcs1_sign(&rsa, NULL, NULL, MBEDTLS_RSA_PRIVATE, MBEDTLS_MD_SHA1, 20, sha_hash, sign); - PrintAndLogEx( - (is_signed == 0) ? SUCCESS : FAILED, - "RSA signing.......... ( %s )", - (is_signed == 0) ? _GREEN_("ok") : _RED_("fail") - ); - - if (shall_write) { - rdv4_sign_write(sign, RRG_RSA_KEY_LEN); - } - PrintAndLogEx(INFO, "Signed"); - for (int i = 0; i < (sizeof(sign) / 32); i++) { - PrintAndLogEx(INFO, " %s", sprint_hex_inrow(sign + (i * 32), 32)); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(INFO, "--- " _CYAN_("Enter signing") " --------------------"); + + if (dlen == 8) { + 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( + (is_signed == 0) ? SUCCESS : FAILED, + "RSA signing... ( %s )", + (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) - 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); + bool is_verified = (mbedtls_rsa_pkcs1_verify(rsa, NULL, NULL, MBEDTLS_RSA_PUBLIC, MBEDTLS_MD_SHA1, 20, sha_hash, from_device) == 0); + mbedtls_pk_free(&pkctx); + + PrintAndLogEx(NORMAL, ""); PrintAndLogEx( (is_verified) ? SUCCESS : FAILED, - "RSA verification..... ( %s )", - (is_verified) ? _GREEN_("ok") : _RED_("fail") + "Genuine Proxmark3 RDV4 signature detected... %s", + (is_verified) ? ":heavy_check_mark:" : ":x:" ); - if (is_verified) { - PrintAndLogEx(SUCCESS, "Genuine Proxmark3 RDV4 signature detected"); - } - PrintAndLogEx(NORMAL, ""); return PM3_SUCCESS; } diff --git a/client/src/fileutils.c b/client/src/fileutils.c index dc7ac530a..6cc29d867 100644 --- a/client/src/fileutils.c +++ b/client/src/fileutils.c @@ -1805,7 +1805,7 @@ int searchFile(char **foundpath, const char *pm3dir, const char *searchname, con int res = searchFinalFile(foundpath, pm3dir, filename, silent); if (res != PM3_SUCCESS) { if ((res == PM3_EFILE) && (!silent)) - PrintAndLogEx(FAILED, "Error - can't find %s", filename); + PrintAndLogEx(FAILED, "Error - can't find `" _YELLOW_("%s") "`", filename); free(filename); return res; }