mem * - now uses cliparser

This commit is contained in:
iceman1001 2020-10-03 17:12:58 +02:00
commit cc245016ea
3 changed files with 212 additions and 273 deletions

View file

@ -1,6 +1,6 @@
#!/usr/bin/env -S pm3 -s #!/usr/bin/env -S pm3 -s
mem load f mfc_default_keys m mem load -f mfc_default_keys --mfc
mem load f t55xx_default_pwds t mem load -f t55xx_default_pwds --t55xx
mem load f iclass_default_keys i mem load -f iclass_default_keys --iclass
lf t55xx deviceconfig z p lf t55xx deviceconfig z p

View file

@ -74,9 +74,9 @@ function main(args)
-- Upload dictionaries -- Upload dictionaries
print('Uploading dictionaries to RDV4 flashmemory') print('Uploading dictionaries to RDV4 flashmemory')
print(dash) print(dash)
core.console('mem load f mfc_default_keys m') core.console('mem load -f mfc_default_keys --mfc')
core.console('mem load f t55xx_default_pwds t') core.console('mem load -f t55xx_default_pwds --t55xx')
core.console('mem load f iclass_default_keys i') core.console('mem load -f iclass_default_keys --iclass')
print(dash) print(dash)
-- T55x7 Device configuration -- T55x7 Device configuration

View file

@ -8,16 +8,13 @@
// Proxmark3 RDV40 Flash memory commands // Proxmark3 RDV40 Flash memory commands
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#include "cmdflashmem.h" #include "cmdflashmem.h"
#include <ctype.h> #include <ctype.h>
#include "cmdparser.h" // command_t
#include "cmdparser.h" // command_t #include "cliparser.h"
#include "pmflash.h" #include "pmflash.h"
#include "fileutils.h" //saveFile #include "fileutils.h" // saveFile
#include "comms.h" //getfromdevice #include "comms.h" // getfromdevice
#include "cmdflashmemspiffs.h" // spiffs commands #include "cmdflashmemspiffs.h" // spiffs commands
#include "rsa.h" #include "rsa.h"
#include "sha1.h" #include "sha1.h"
@ -29,90 +26,34 @@
static int CmdHelp(const char *Cmd); static int CmdHelp(const char *Cmd);
static int usage_flashmem_spibaud(void) {
PrintAndLogEx(NORMAL, "Usage: mem spibaud [h] <baudrate>");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h this help");
PrintAndLogEx(NORMAL, " <baudrate> SPI baudrate in MHz [24|48]");
PrintAndLogEx(NORMAL, " ");
PrintAndLogEx(NORMAL, " If >= 24MHz, FASTREADS instead of READS instruction will be used.");
PrintAndLogEx(NORMAL, " Reading Flash ID will virtually always fail under 48MHz setting");
PrintAndLogEx(NORMAL, " Unless you know what you are doing, please stay at 24MHz");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, " mem spibaud 48");
return PM3_SUCCESS;
}
static int usage_flashmem_load(void) {
PrintAndLogEx(NORMAL, "Loads binary file into flash memory on device");
PrintAndLogEx(NORMAL, "Usage: mem load [o <offset>] f <file name> [m|t|i]");
PrintAndLogEx(NORMAL, "Warning: mem area to be written must have been wiped first");
PrintAndLogEx(NORMAL, "(this is already taken care when loading dictionaries)");
PrintAndLogEx(NORMAL, " o <offset> : offset in memory");
PrintAndLogEx(NORMAL, " f <filename> : file name");
PrintAndLogEx(NORMAL, " m : upload 6 bytes keys (mifare key dictionary)");
PrintAndLogEx(NORMAL, " i : upload 8 bytes keys (iClass key dictionary)");
PrintAndLogEx(NORMAL, " t : upload 4 bytes keys (pwd dictionary)");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, " mem load f myfile"); // upload file myfile at default offset 0
PrintAndLogEx(NORMAL, " mem load f myfile o 1024"); // upload file myfile at offset 1024
PrintAndLogEx(NORMAL, " mem load f mfc_default_keys m");
PrintAndLogEx(NORMAL, " mem load f t55xx_default_pwds t");
PrintAndLogEx(NORMAL, " mem load f iclass_default_keys i");
return PM3_SUCCESS;
}
static int usage_flashmem_dump(void) {
PrintAndLogEx(NORMAL, "Dumps flash memory on device into a file or in console");
PrintAndLogEx(NORMAL, " Usage: mem dump [o <offset>] [l <length>] [f <file name>] [p]");
PrintAndLogEx(NORMAL, " o <offset> : offset in memory");
PrintAndLogEx(NORMAL, " l <length> : length");
PrintAndLogEx(NORMAL, " f <filename> : file name");
PrintAndLogEx(NORMAL, " p : print dump in console");
PrintAndLogEx(NORMAL, " You must specify at lease option f or option p, both if you wish");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, " mem dump f myfile"); // download whole flashmem to file myfile
PrintAndLogEx(NORMAL, " mem dump p o 262015 l 128"); // display 128 bytes from offset 262015 (RSA sig)
PrintAndLogEx(NORMAL, " mem dump p f myfile o 241664 l 58"); // download and display 58 bytes from offset 241664 to file myfile
return PM3_SUCCESS;
}
static int usage_flashmem_wipe(void) {
PrintAndLogEx(WARNING, "[OBS] use with caution.");
PrintAndLogEx(NORMAL, "Wipe flash memory on device, which fills memory with 0xFF\n");
PrintAndLogEx(NORMAL, " Usage: mem wipe p <page>");
PrintAndLogEx(NORMAL, " p <page> : 0,1,2 page memory");
// PrintAndLogEx(NORMAL, " i : inital total wipe");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, " mem wipe p 0"); // wipes first page.
return PM3_SUCCESS;
}
static int usage_flashmem_info(void) {
PrintAndLogEx(NORMAL, "Collect signature and verify it from flash memory\n");
PrintAndLogEx(NORMAL, " Usage: mem info");
// PrintAndLogEx(NORMAL, " s : create a signature");
// PrintAndLogEx(NORMAL, " w : write signature to flash memory");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, " mem info");
// PrintAndLogEx(NORMAL, " mem info s");
return PM3_SUCCESS;
}
static int CmdFlashmemSpiBaudrate(const char *Cmd) { static int CmdFlashmemSpiBaudrate(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, " mem baudrate 48",
"Set the baudrate for the SPI flash memory communications.\n"
"Reading Flash ID will virtually always fail under 48MHz setting.\n"
"Unless you know what you are doing, please stay at 24MHz.\n"
"If >= 24MHz, FASTREADS instead of READS instruction will be used.",
"mem baudrate --mhz 48"
);
void *argtable[] = {
arg_param_begin,
arg_int1(NULL, "mhz", "<24|48>", "SPI baudrate in MHz"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
int br = arg_get_int_def(ctx, 1, -1);
CLIParserFree(ctx);
char ctmp = tolower(param_getchar(Cmd, 0)); if (br == -1) {
if (strlen(Cmd) < 1 || ctmp == 'h') { PrintAndLogEx(ERR, "failed to get baudrate");
return usage_flashmem_spibaud(); return PM3_EINVARG;
} }
uint32_t baudrate = param_get32ex(Cmd, 0, 0, 10); uint32_t baudrate = br * 1000000;
baudrate = baudrate * 1000000;
if (baudrate != FLASH_BAUD && baudrate != FLASH_MINBAUD) { if (baudrate != FLASH_BAUD && baudrate != FLASH_MINBAUD) {
usage_flashmem_spibaud(); PrintAndLogEx(ERR, "wrong baudrate. Only 24 or 48 is allowed");
return PM3_EINVARG; return PM3_EINVARG;
} }
SendCommandNG(CMD_FLASHMEM_SET_SPIBAUDRATE, (uint8_t *)&baudrate, sizeof(uint32_t)); SendCommandNG(CMD_FLASHMEM_SET_SPIBAUDRATE, (uint8_t *)&baudrate, sizeof(uint32_t));
@ -121,52 +62,50 @@ static int CmdFlashmemSpiBaudrate(const char *Cmd) {
static int CmdFlashMemLoad(const char *Cmd) { static int CmdFlashMemLoad(const char *Cmd) {
uint32_t start_index = 0; CLIParserContext *ctx;
CLIParserInit(&ctx, "mem load",
"Loads binary file into flash memory on device\n"
"Warning: mem area to be written must have been wiped first\n"
"( this is already taken care when loading dictionaries )",
"mem load -f myfile -> upload file myfile values at default offset 0\n"
"mem load -f myfile -o 1024 -> upload file myfile values at offset 1024\n"
"mem load -f mfc_default_keys -m -> upload MFC keys\n"
"mem load -f t55xx_default_pwds -t -> upload T55XX passwords\n"
"mem load -f iclass_default_keys -i -> upload iCLASS keys\n"
);
void *argtable[] = {
arg_param_begin,
arg_int0("o", "offset", "<dec>", "offset in memory"),
arg_lit0("m", "mifare,mfc", "upload 6 bytes keys (mifare key dictionary)"),
arg_lit0("i", "iclass", "upload 8 bytes keys (iClass key dictionary)"),
arg_lit0("t", "t55xx", "upload 4 bytes keys (password dictionary)"),
arg_strx0("f", "file", "<filename>", "file name"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
int offset = arg_get_int_def(ctx, 1, 0);
bool is_mfc = arg_get_lit(ctx, 2);
bool is_iclass = arg_get_lit(ctx, 3);
bool is_t55xx = arg_get_lit(ctx, 4);
int fnlen = 0;
char filename[FILE_PATH_SIZE] = {0}; char filename[FILE_PATH_SIZE] = {0};
bool errors = false; CLIParamStrToBuf(arg_get_str(ctx, 5), (uint8_t*)filename, FILE_PATH_SIZE, &fnlen);
uint8_t cmdp = 0; CLIParserFree(ctx);
Dictionary_t d = DICTIONARY_NONE; Dictionary_t d = DICTIONARY_NONE;
if (is_mfc) {
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { d = DICTIONARY_MIFARE;
switch (tolower(param_getchar(Cmd, cmdp))) { PrintAndLogEx(INFO, "treating file as MIFARE Classic keys");
case 'h': } else if (is_iclass) {
return usage_flashmem_load(); d = DICTIONARY_ICLASS;
case 'f': PrintAndLogEx(INFO, "treating file as iCLASS keys");
if (param_getstr(Cmd, cmdp + 1, filename, FILE_PATH_SIZE) >= FILE_PATH_SIZE) { } else if (is_t55xx) {
PrintAndLogEx(FAILED, "Filename too long"); d = DICTIONARY_T55XX;
errors = true; PrintAndLogEx(INFO, "treating file as T55xx passwords");
break;
}
cmdp += 2;
break;
case 'o':
start_index = param_get32ex(Cmd, cmdp + 1, 0, 10);
cmdp += 2;
break;
case 'm':
d = DICTIONARY_MIFARE;
cmdp++;
break;
case 't':
d = DICTIONARY_T55XX;
cmdp++;
break;
case 'i':
d = DICTIONARY_ICLASS;
cmdp++;
break;
default:
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
errors = true;
break;
}
} }
//Validations
if (errors || cmdp == 0) {
usage_flashmem_load();
return PM3_EINVARG;
}
size_t datalen = 0; size_t datalen = 0;
uint32_t keycount = 0; uint32_t keycount = 0;
int res = 0; int res = 0;
@ -174,7 +113,7 @@ static int CmdFlashMemLoad(const char *Cmd) {
switch (d) { switch (d) {
case DICTIONARY_MIFARE: case DICTIONARY_MIFARE:
start_index = DEFAULT_MF_KEYS_OFFSET; offset = DEFAULT_MF_KEYS_OFFSET;
res = loadFileDICTIONARY(filename, data + 2, &datalen, 6, &keycount); res = loadFileDICTIONARY(filename, data + 2, &datalen, 6, &keycount);
if (res || !keycount) { if (res || !keycount) {
free(data); free(data);
@ -189,7 +128,7 @@ static int CmdFlashMemLoad(const char *Cmd) {
datalen += 2; datalen += 2;
break; break;
case DICTIONARY_T55XX: case DICTIONARY_T55XX:
start_index = DEFAULT_T55XX_KEYS_OFFSET; offset = DEFAULT_T55XX_KEYS_OFFSET;
res = loadFileDICTIONARY(filename, data + 2, &datalen, 4, &keycount); res = loadFileDICTIONARY(filename, data + 2, &datalen, 4, &keycount);
if (res || !keycount) { if (res || !keycount) {
free(data); free(data);
@ -204,7 +143,7 @@ static int CmdFlashMemLoad(const char *Cmd) {
datalen += 2; datalen += 2;
break; break;
case DICTIONARY_ICLASS: case DICTIONARY_ICLASS:
start_index = DEFAULT_ICLASS_KEYS_OFFSET; offset = DEFAULT_ICLASS_KEYS_OFFSET;
res = loadFileDICTIONARY(filename, data + 2, &datalen, 8, &keycount); res = loadFileDICTIONARY(filename, data + 2, &datalen, 8, &keycount);
if (res || !keycount) { if (res || !keycount) {
free(data); free(data);
@ -253,13 +192,13 @@ static int CmdFlashMemLoad(const char *Cmd) {
clearCommandBuffer(); clearCommandBuffer();
SendCommandOLD(CMD_FLASHMEM_WRITE, start_index + bytes_sent, bytes_in_packet, 0, data + bytes_sent, bytes_in_packet); SendCommandOLD(CMD_FLASHMEM_WRITE, offset + bytes_sent, bytes_in_packet, 0, data + bytes_sent, bytes_in_packet);
bytes_remaining -= bytes_in_packet; bytes_remaining -= bytes_in_packet;
bytes_sent += bytes_in_packet; bytes_sent += bytes_in_packet;
PacketResponseNG resp; PacketResponseNG resp;
if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { if (WaitForResponseTimeout(CMD_ACK, &resp, 2000) == false) {
PrintAndLogEx(WARNING, "timeout while waiting for reply."); PrintAndLogEx(WARNING, "timeout while waiting for reply.");
conn.block_after_ACK = false; conn.block_after_ACK = false;
free(data); free(data);
@ -276,54 +215,37 @@ static int CmdFlashMemLoad(const char *Cmd) {
conn.block_after_ACK = false; conn.block_after_ACK = false;
free(data); free(data);
PrintAndLogEx(SUCCESS, "Wrote "_GREEN_("%zu")" bytes to offset "_GREEN_("%u"), datalen, start_index); PrintAndLogEx(SUCCESS, "Wrote "_GREEN_("%zu")" bytes to offset "_GREEN_("%u"), datalen, offset);
return PM3_SUCCESS; return PM3_SUCCESS;
} }
static int CmdFlashMemDump(const char *Cmd) { static int CmdFlashMemDump(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "mem dump",
"Dumps flash memory on device into a file or view in console",
"mem dump -f myfile -> download all flashmem to file\n"
"mem dump --view -o 262015 --len 128 -> display 128 bytes from offset 262015 (RSA sig)\n"
"mem dump --view -f myfile -o 241664 --len 58 -> display 58 bytes from offset 241664 and save to file"
);
void *argtable[] = {
arg_param_begin,
arg_int0("o", "offset", "<dec>", "offset in memory"),
arg_int0("l", "len", "<dec>", "length"),
arg_lit0("v", "view", "view dump"),
arg_strx0("f", "file", "<filename>", "file name"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
int offset = arg_get_int_def(ctx, 1, 0);
int len = arg_get_int_def(ctx, 2, FLASH_MEM_MAX_SIZE);
bool view = arg_get_lit(ctx, 3);
int fnlen = 0;
char filename[FILE_PATH_SIZE] = {0}; char filename[FILE_PATH_SIZE] = {0};
uint8_t cmdp = 0; CLIParamStrToBuf(arg_get_str(ctx, 4), (uint8_t*)filename, FILE_PATH_SIZE, &fnlen);
bool errors = false; CLIParserFree(ctx);
bool print = false;
uint32_t start_index = 0, len = FLASH_MEM_MAX_SIZE;
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
switch (tolower(param_getchar(Cmd, cmdp))) {
case 'h':
return usage_flashmem_dump();
case 'l':
len = param_get32ex(Cmd, cmdp + 1, FLASH_MEM_MAX_SIZE, 10);
cmdp += 2;
break;
case 'o':
start_index = param_get32ex(Cmd, cmdp + 1, 0, 10);
cmdp += 2;
break;
case 'p':
print = true;
cmdp += 1;
break;
case 'f':
//File handling
if (param_getstr(Cmd, cmdp + 1, filename, FILE_PATH_SIZE) >= FILE_PATH_SIZE) {
PrintAndLogEx(FAILED, "Filename too long");
errors = true;
break;
}
cmdp += 2;
break;
default:
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
errors = true;
break;
}
}
//Validations
if (errors || cmdp == 0) {
usage_flashmem_dump();
return PM3_EINVARG;
}
uint8_t *dump = calloc(len, sizeof(uint8_t)); uint8_t *dump = calloc(len, sizeof(uint8_t));
if (!dump) { if (!dump) {
@ -331,14 +253,15 @@ static int CmdFlashMemDump(const char *Cmd) {
return PM3_EMALLOC; return PM3_EMALLOC;
} }
PrintAndLogEx(INFO, "downloading "_YELLOW_("%u")" bytes from flashmem", len); PrintAndLogEx(INFO, "downloading "_YELLOW_("%u")" bytes from flash memory", len);
if (!GetFromDevice(FLASH_MEM, dump, len, start_index, NULL, 0, NULL, -1, true)) { if (!GetFromDevice(FLASH_MEM, dump, len, offset, NULL, 0, NULL, -1, true)) {
PrintAndLogEx(FAILED, "ERROR; downloading from flashmemory"); PrintAndLogEx(FAILED, "ERROR; downloading from flash memory");
free(dump); free(dump);
return PM3_EFLASH; return PM3_EFLASH;
} }
if (print) { if (view) {
PrintAndLogEx(INFO, "---- " _CYAN_("data") " ---------------");
print_hex_break(dump, len, 32); print_hex_break(dump, len, 32);
} }
@ -350,39 +273,32 @@ static int CmdFlashMemDump(const char *Cmd) {
free(dump); free(dump);
return PM3_SUCCESS; return PM3_SUCCESS;
} }
static int CmdFlashMemWipe(const char *Cmd) { static int CmdFlashMemWipe(const char *Cmd) {
uint8_t cmdp = 0; CLIParserContext *ctx;
bool errors = false; CLIParserInit(&ctx, "mem wipe",
bool initalwipe = false; "Wipe flash memory on device, which fills it with 0xFF\n"
uint8_t page = 0; _WHITE_("[ ") _RED_("!!! OBS") " ] use with caution",
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { "mem wipe -p 0 -> wipes first page"
switch (tolower(param_getchar(Cmd, cmdp))) { // "mem wipe -i -> inital total wipe"
case 'h': );
return usage_flashmem_wipe();
case 'p':
page = param_get8ex(Cmd, cmdp + 1, 0, 10);
if (page > 2) {
PrintAndLogEx(WARNING, "page must be 0, 1 or 2");
errors = true;
break;
}
cmdp += 2;
break;
case 'i':
initalwipe = true;
cmdp++;
break;
default:
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
errors = true;
break;
}
}
//Validations void *argtable[] = {
if (errors || cmdp == 0) { arg_param_begin,
usage_flashmem_wipe(); arg_int0("p", NULL, "<dec>", "0,1,2 page memory"),
// arg_lit0("i", NULL, "inital total wipe"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
bool initalwipe = false;
int page = arg_get_int_def(ctx, 1, -1);
// initalwipe = arg_get_lit(ctx, 2);
CLIParserFree(ctx);
if (page < 0 || page > 2 ) {
PrintAndLogEx(WARNING, "page must be 0, 1 or 2");
return PM3_EINVARG; return PM3_EINVARG;
} }
@ -393,59 +309,51 @@ static int CmdFlashMemWipe(const char *Cmd) {
PrintAndLogEx(WARNING, "timeout while waiting for reply."); PrintAndLogEx(WARNING, "timeout while waiting for reply.");
return PM3_ETIMEOUT; return PM3_ETIMEOUT;
} }
const char* msg = "Flash WIPE ";
uint8_t isok = resp.oldarg[0] & 0xFF; uint8_t isok = resp.oldarg[0] & 0xFF;
if (isok) if (isok)
PrintAndLogEx(SUCCESS, "Flash WIPE ok"); PrintAndLogEx(SUCCESS, "%s ( " _GREEN_("ok")" )", msg);
else { else {
PrintAndLogEx(FAILED, "Flash WIPE failed"); PrintAndLogEx(FAILED, "%s ( " _RED_("failed") " )", msg);
return PM3_EFLASH; return PM3_EFLASH;
} }
return PM3_SUCCESS; return PM3_SUCCESS;
} }
static int CmdFlashMemInfo(const char *Cmd) { static int CmdFlashMemInfo(const char *Cmd) {
uint8_t sha_hash[20] = {0}; CLIParserContext *ctx;
mbedtls_rsa_context rsa; CLIParserInit(&ctx, "mem info",
"Collect signature and verify it from flash memory",
"mem info"
// "mem info -s"
);
uint8_t cmdp = 0; void *argtable[] = {
bool errors = false, shall_write = false, shall_sign = false; arg_param_begin,
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { // arg_lit0("s", NULL, "create a signature"),
switch (tolower(param_getchar(Cmd, cmdp))) { // arg_lit0("w", NULL, "write signature to flash memory"),
case 'h': arg_param_end
return usage_flashmem_info(); };
case 's': { CLIExecWithReturn(ctx, Cmd, argtable, true);
shall_sign = true;
cmdp++;
break;
}
case 'w':
shall_write = true;
cmdp++;
break;
default:
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
errors = true;
break;
}
}
//Validations bool shall_sign = false, shall_write = false;
if (errors) { // shall_sign = arg_get_lit(ctx, 1);
usage_flashmem_info(); // shall_write = arg_get_lit(ctx, 2);
return PM3_EINVARG; CLIParserFree(ctx);
}
clearCommandBuffer(); clearCommandBuffer();
SendCommandNG(CMD_FLASHMEM_INFO, NULL, 0); SendCommandNG(CMD_FLASHMEM_INFO, NULL, 0);
PacketResponseNG resp; PacketResponseNG resp;
if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) { if (WaitForResponseTimeout(CMD_ACK, &resp, 2500) == false) {
PrintAndLogEx(WARNING, "timeout while waiting for reply."); PrintAndLogEx(WARNING, "timeout while waiting for reply");
return PM3_ETIMEOUT; return PM3_ETIMEOUT;
} }
uint8_t isok = resp.oldarg[0] & 0xFF; uint8_t isok = resp.oldarg[0] & 0xFF;
if (!isok) { if (isok == false) {
PrintAndLogEx(FAILED, "failed"); PrintAndLogEx(FAILED, "failed");
return PM3_EFLASH; return PM3_EFLASH;
} }
@ -455,15 +363,20 @@ static int CmdFlashMemInfo(const char *Cmd) {
memcpy(&mem, (rdv40_validation_t *)resp.data.asBytes, sizeof(rdv40_validation_t)); memcpy(&mem, (rdv40_validation_t *)resp.data.asBytes, sizeof(rdv40_validation_t));
// Flash ID hash (sha1) // Flash ID hash (sha1)
uint8_t sha_hash[20] = {0};
mbedtls_sha1(mem.flashid, sizeof(mem.flashid), sha_hash); mbedtls_sha1(mem.flashid, sizeof(mem.flashid), sha_hash);
// print header // print header
PrintAndLogEx(INFO, "\n--- Flash memory Information ---------"); PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, "-------------------------------------------------------------"); PrintAndLogEx(INFO, "--- " _CYAN_("Flash memory Information") " ---------");
PrintAndLogEx(INFO, "ID | %s", sprint_hex(mem.flashid, sizeof(mem.flashid))); // PrintAndLogEx(INFO, "-----------------------------------------------------------------");
PrintAndLogEx(INFO, "SHA1 | %s", sprint_hex(sha_hash, sizeof(sha_hash))); PrintAndLogEx(INFO, "ID................... %s", sprint_hex_inrow(mem.flashid, sizeof(mem.flashid)));
PrintAndLogEx(INFO, "RSA SIGNATURE |"); PrintAndLogEx(INFO, "SHA1................. %s", sprint_hex_inrow(sha_hash, sizeof(sha_hash)));
print_hex_break(mem.signature, sizeof(mem.signature), 32); 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));
}
//------------------------------------------------------------------------------- //-------------------------------------------------------------------------------
// RRG Public RSA Key // RRG Public RSA Key
@ -473,7 +386,10 @@ static int CmdFlashMemInfo(const char *Cmd) {
#define RSA_E "010001" #define RSA_E "010001"
// public key modulus N // public key modulus N
#define RSA_N "E28D809BF323171D11D1ACA4C32A5B7E0A8974FD171E75AD120D60E9B76968FF4B0A6364AE50583F9555B8EE1A725F279E949246DF0EFCE4C02B9F3ACDCC623F9337F21C0C066FFB703D8BFCB5067F309E056772096642C2B1A8F50305D5EC33DB7FB5A3C8AC42EB635AE3C148C910750ABAA280CE82DC2F180F49F30A1393B5" #define RSA_N "E28D809BF323171D11D1ACA4C32A5B7E0A8974FD171E75AD120D60E9B76968FF" \
"4B0A6364AE50583F9555B8EE1A725F279E949246DF0EFCE4C02B9F3ACDCC623F" \
"9337F21C0C066FFB703D8BFCB5067F309E056772096642C2B1A8F50305D5EC33" \
"DB7FB5A3C8AC42EB635AE3C148C910750ABAA280CE82DC2F180F49F30A1393B5"
//------------------------------------------------------------------------------- //-------------------------------------------------------------------------------
// Example RSA-1024 keypair, for test purposes (from common/polarssl/rsa.c) // Example RSA-1024 keypair, for test purposes (from common/polarssl/rsa.c)
@ -516,9 +432,9 @@ static int CmdFlashMemInfo(const char *Cmd) {
"F5A3B2A5D33605AEBBCCBA7FEB9F2D2F" \ "F5A3B2A5D33605AEBBCCBA7FEB9F2D2F" \
"A74206CEC169D74BF5A8C50D6F48EA08" "A74206CEC169D74BF5A8C50D6F48EA08"
#define KEY_LEN 128 #define KEY_LEN 128
mbedtls_rsa_context rsa;
mbedtls_rsa_init(&rsa, MBEDTLS_RSA_PKCS_V15, 0); mbedtls_rsa_init(&rsa, MBEDTLS_RSA_PKCS_V15, 0);
rsa.len = KEY_LEN; rsa.len = KEY_LEN;
@ -532,13 +448,31 @@ static int CmdFlashMemInfo(const char *Cmd) {
mbedtls_mpi_read_string(&rsa.DQ, 16, RSA_DQ); mbedtls_mpi_read_string(&rsa.DQ, 16, RSA_DQ);
mbedtls_mpi_read_string(&rsa.QP, 16, RSA_QP); mbedtls_mpi_read_string(&rsa.QP, 16, RSA_QP);
PrintAndLogEx(INFO, "KEY length | %d", KEY_LEN);
bool is_keyok = (mbedtls_rsa_check_pubkey(&rsa) == 0 || mbedtls_rsa_check_privkey(&rsa) == 0); bool is_keyok = (mbedtls_rsa_check_pubkey(&rsa) == 0 || mbedtls_rsa_check_privkey(&rsa) == 0);
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, "--- " _CYAN_("RDV4 RSA Public key") " --------------");
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.................. %u", 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, "");
const char *msgkey = "RSA key validation... ";
if (is_keyok) if (is_keyok)
PrintAndLogEx(SUCCESS, "RSA key validation ok"); PrintAndLogEx(SUCCESS, "%s( " _GREEN_("ok") " )", msgkey);
else else
PrintAndLogEx(FAILED, "RSA key validation failed"); PrintAndLogEx(FAILED, "%s( " _RED_("failed") " )", msgkey);
// //
uint8_t from_device[KEY_LEN]; uint8_t from_device[KEY_LEN];
@ -554,10 +488,11 @@ static int CmdFlashMemInfo(const char *Cmd) {
if (shall_sign) { if (shall_sign) {
int is_signed = mbedtls_rsa_pkcs1_sign(&rsa, NULL, NULL, MBEDTLS_RSA_PRIVATE, MBEDTLS_MD_SHA1, 20, sha_hash, 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) if (is_signed == 0)
PrintAndLogEx(SUCCESS, "RSA Signing ok"); PrintAndLogEx(SUCCESS, "%s( " _GREEN_("ok") " )", msgsign);
else else
PrintAndLogEx(FAILED, "RSA Signing failed"); PrintAndLogEx(FAILED, "%s( " _RED_("failed") " )", msgsign);
if (shall_write) { if (shall_write) {
// save to mem // save to mem
@ -574,29 +509,33 @@ static int CmdFlashMemInfo(const char *Cmd) {
} }
} }
PrintAndLogEx(INFO, "Signed | "); PrintAndLogEx(INFO, "Signed");
print_hex_break(sign, sizeof(sign), 32); for (int i = 0; i < (sizeof(sign) / 32); i++) {
PrintAndLogEx(INFO, " %s", sprint_hex_inrow(sign + (i * 32), 32));
}
} }
// Verify (public key) // Verify (public key)
int is_verified = mbedtls_rsa_pkcs1_verify(&rsa, NULL, NULL, MBEDTLS_RSA_PUBLIC, MBEDTLS_MD_SHA1, 20, sha_hash, from_device); 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) if (is_verified == 0)
PrintAndLogEx(SUCCESS, "RSA Verification ok"); PrintAndLogEx(SUCCESS, "%s( " _GREEN_("ok") " )", msgverify);
else else
PrintAndLogEx(FAILED, "RSA Verification failed"); PrintAndLogEx(FAILED, "%s( " _RED_("failed") " )", msgverify);
PrintAndLogEx(NORMAL, "");
mbedtls_rsa_free(&rsa); mbedtls_rsa_free(&rsa);
return PM3_SUCCESS; return PM3_SUCCESS;
} }
static command_t CommandTable[] = { static command_t CommandTable[] = {
{"help", CmdHelp, AlwaysAvailable, "This help"}, {"help", CmdHelp, AlwaysAvailable, "This help"},
{"spiffs", CmdFlashMemSpiFFS, IfPm3Flash, "High level SPI FileSystem Flash manipulation [rdv40]"}, {"baudrate", CmdFlashmemSpiBaudrate, IfPm3Flash, "Set Flash memory Spi baudrate"},
{"spibaud", CmdFlashmemSpiBaudrate, IfPm3Flash, "Set Flash memory Spi baudrate [rdv40]"}, {"spiffs", CmdFlashMemSpiFFS, IfPm3Flash, "High level SPI FileSystem Flash manipulation"},
{"info", CmdFlashMemInfo, IfPm3Flash, "Flash memory information [rdv40]"}, {"info", CmdFlashMemInfo, IfPm3Flash, "Flash memory information"},
{"load", CmdFlashMemLoad, IfPm3Flash, "Load data into flash memory [rdv40]"}, {"load", CmdFlashMemLoad, IfPm3Flash, "Load data into flash memory"},
{"dump", CmdFlashMemDump, IfPm3Flash, "Dump data from flash memory [rdv40]"}, {"dump", CmdFlashMemDump, IfPm3Flash, "Dump data from flash memory"},
{"wipe", CmdFlashMemWipe, IfPm3Flash, "Wipe data from flash memory [rdv40]"}, {"wipe", CmdFlashMemWipe, IfPm3Flash, "Wipe data from flash memory"},
{NULL, NULL, NULL, NULL} {NULL, NULL, NULL, NULL}
}; };