mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-14 10:37:23 -07:00
mem * - now uses cliparser
This commit is contained in:
parent
357921f561
commit
cc245016ea
3 changed files with 212 additions and 273 deletions
|
@ -1,6 +1,6 @@
|
|||
#!/usr/bin/env -S pm3 -s
|
||||
|
||||
mem load f mfc_default_keys m
|
||||
mem load f t55xx_default_pwds t
|
||||
mem load f iclass_default_keys i
|
||||
mem load -f mfc_default_keys --mfc
|
||||
mem load -f t55xx_default_pwds --t55xx
|
||||
mem load -f iclass_default_keys --iclass
|
||||
lf t55xx deviceconfig z p
|
||||
|
|
|
@ -74,9 +74,9 @@ function main(args)
|
|||
-- Upload dictionaries
|
||||
print('Uploading dictionaries to RDV4 flashmemory')
|
||||
print(dash)
|
||||
core.console('mem load f mfc_default_keys m')
|
||||
core.console('mem load f t55xx_default_pwds t')
|
||||
core.console('mem load f iclass_default_keys i')
|
||||
core.console('mem load -f mfc_default_keys --mfc')
|
||||
core.console('mem load -f t55xx_default_pwds --t55xx')
|
||||
core.console('mem load -f iclass_default_keys --iclass')
|
||||
print(dash)
|
||||
|
||||
-- T55x7 Device configuration
|
||||
|
|
|
@ -8,16 +8,13 @@
|
|||
// Proxmark3 RDV40 Flash memory commands
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "cmdflashmem.h"
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
#include "cmdparser.h" // command_t
|
||||
|
||||
#include "cmdparser.h" // command_t
|
||||
#include "cliparser.h"
|
||||
#include "pmflash.h"
|
||||
#include "fileutils.h" //saveFile
|
||||
#include "comms.h" //getfromdevice
|
||||
#include "fileutils.h" // saveFile
|
||||
#include "comms.h" // getfromdevice
|
||||
#include "cmdflashmemspiffs.h" // spiffs commands
|
||||
|
||||
#include "rsa.h"
|
||||
#include "sha1.h"
|
||||
|
||||
|
@ -29,90 +26,34 @@
|
|||
|
||||
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) {
|
||||
|
||||
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 (strlen(Cmd) < 1 || ctmp == 'h') {
|
||||
return usage_flashmem_spibaud();
|
||||
if (br == -1) {
|
||||
PrintAndLogEx(ERR, "failed to get baudrate");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
uint32_t baudrate = param_get32ex(Cmd, 0, 0, 10);
|
||||
baudrate = baudrate * 1000000;
|
||||
uint32_t baudrate = br * 1000000;
|
||||
if (baudrate != FLASH_BAUD && baudrate != FLASH_MINBAUD) {
|
||||
usage_flashmem_spibaud();
|
||||
PrintAndLogEx(ERR, "wrong baudrate. Only 24 or 48 is allowed");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
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) {
|
||||
|
||||
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};
|
||||
bool errors = false;
|
||||
uint8_t cmdp = 0;
|
||||
CLIParamStrToBuf(arg_get_str(ctx, 5), (uint8_t*)filename, FILE_PATH_SIZE, &fnlen);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
Dictionary_t d = DICTIONARY_NONE;
|
||||
|
||||
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
||||
switch (tolower(param_getchar(Cmd, cmdp))) {
|
||||
case 'h':
|
||||
return usage_flashmem_load();
|
||||
case 'f':
|
||||
if (param_getstr(Cmd, cmdp + 1, filename, FILE_PATH_SIZE) >= FILE_PATH_SIZE) {
|
||||
PrintAndLogEx(FAILED, "Filename too long");
|
||||
errors = true;
|
||||
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;
|
||||
}
|
||||
if (is_mfc) {
|
||||
d = DICTIONARY_MIFARE;
|
||||
PrintAndLogEx(INFO, "treating file as MIFARE Classic keys");
|
||||
} else if (is_iclass) {
|
||||
d = DICTIONARY_ICLASS;
|
||||
PrintAndLogEx(INFO, "treating file as iCLASS keys");
|
||||
} else if (is_t55xx) {
|
||||
d = DICTIONARY_T55XX;
|
||||
PrintAndLogEx(INFO, "treating file as T55xx passwords");
|
||||
}
|
||||
|
||||
//Validations
|
||||
if (errors || cmdp == 0) {
|
||||
usage_flashmem_load();
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
size_t datalen = 0;
|
||||
uint32_t keycount = 0;
|
||||
int res = 0;
|
||||
|
@ -174,7 +113,7 @@ static int CmdFlashMemLoad(const char *Cmd) {
|
|||
|
||||
switch (d) {
|
||||
case DICTIONARY_MIFARE:
|
||||
start_index = DEFAULT_MF_KEYS_OFFSET;
|
||||
offset = DEFAULT_MF_KEYS_OFFSET;
|
||||
res = loadFileDICTIONARY(filename, data + 2, &datalen, 6, &keycount);
|
||||
if (res || !keycount) {
|
||||
free(data);
|
||||
|
@ -189,7 +128,7 @@ static int CmdFlashMemLoad(const char *Cmd) {
|
|||
datalen += 2;
|
||||
break;
|
||||
case DICTIONARY_T55XX:
|
||||
start_index = DEFAULT_T55XX_KEYS_OFFSET;
|
||||
offset = DEFAULT_T55XX_KEYS_OFFSET;
|
||||
res = loadFileDICTIONARY(filename, data + 2, &datalen, 4, &keycount);
|
||||
if (res || !keycount) {
|
||||
free(data);
|
||||
|
@ -204,7 +143,7 @@ static int CmdFlashMemLoad(const char *Cmd) {
|
|||
datalen += 2;
|
||||
break;
|
||||
case DICTIONARY_ICLASS:
|
||||
start_index = DEFAULT_ICLASS_KEYS_OFFSET;
|
||||
offset = DEFAULT_ICLASS_KEYS_OFFSET;
|
||||
res = loadFileDICTIONARY(filename, data + 2, &datalen, 8, &keycount);
|
||||
if (res || !keycount) {
|
||||
free(data);
|
||||
|
@ -253,13 +192,13 @@ static int CmdFlashMemLoad(const char *Cmd) {
|
|||
|
||||
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_sent += bytes_in_packet;
|
||||
|
||||
PacketResponseNG resp;
|
||||
if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
|
||||
if (WaitForResponseTimeout(CMD_ACK, &resp, 2000) == false) {
|
||||
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
|
||||
conn.block_after_ACK = false;
|
||||
free(data);
|
||||
|
@ -276,54 +215,37 @@ static int CmdFlashMemLoad(const char *Cmd) {
|
|||
|
||||
conn.block_after_ACK = false;
|
||||
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;
|
||||
}
|
||||
|
||||
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};
|
||||
uint8_t cmdp = 0;
|
||||
bool errors = false;
|
||||
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;
|
||||
}
|
||||
CLIParamStrToBuf(arg_get_str(ctx, 4), (uint8_t*)filename, FILE_PATH_SIZE, &fnlen);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
uint8_t *dump = calloc(len, sizeof(uint8_t));
|
||||
if (!dump) {
|
||||
|
@ -331,14 +253,15 @@ static int CmdFlashMemDump(const char *Cmd) {
|
|||
return PM3_EMALLOC;
|
||||
}
|
||||
|
||||
PrintAndLogEx(INFO, "downloading "_YELLOW_("%u")" bytes from flashmem", len);
|
||||
if (!GetFromDevice(FLASH_MEM, dump, len, start_index, NULL, 0, NULL, -1, true)) {
|
||||
PrintAndLogEx(FAILED, "ERROR; downloading from flashmemory");
|
||||
PrintAndLogEx(INFO, "downloading "_YELLOW_("%u")" bytes from flash memory", len);
|
||||
if (!GetFromDevice(FLASH_MEM, dump, len, offset, NULL, 0, NULL, -1, true)) {
|
||||
PrintAndLogEx(FAILED, "ERROR; downloading from flash memory");
|
||||
free(dump);
|
||||
return PM3_EFLASH;
|
||||
}
|
||||
|
||||
if (print) {
|
||||
if (view) {
|
||||
PrintAndLogEx(INFO, "---- " _CYAN_("data") " ---------------");
|
||||
print_hex_break(dump, len, 32);
|
||||
}
|
||||
|
||||
|
@ -350,39 +273,32 @@ static int CmdFlashMemDump(const char *Cmd) {
|
|||
free(dump);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int CmdFlashMemWipe(const char *Cmd) {
|
||||
|
||||
uint8_t cmdp = 0;
|
||||
bool errors = false;
|
||||
bool initalwipe = false;
|
||||
uint8_t page = 0;
|
||||
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
||||
switch (tolower(param_getchar(Cmd, cmdp))) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
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"
|
||||
);
|
||||
|
||||
//Validations
|
||||
if (errors || cmdp == 0) {
|
||||
usage_flashmem_wipe();
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -393,59 +309,51 @@ static int CmdFlashMemWipe(const char *Cmd) {
|
|||
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
|
||||
const char* msg = "Flash WIPE ";
|
||||
uint8_t isok = resp.oldarg[0] & 0xFF;
|
||||
if (isok)
|
||||
PrintAndLogEx(SUCCESS, "Flash WIPE ok");
|
||||
PrintAndLogEx(SUCCESS, "%s ( " _GREEN_("ok")" )", msg);
|
||||
else {
|
||||
PrintAndLogEx(FAILED, "Flash WIPE failed");
|
||||
PrintAndLogEx(FAILED, "%s ( " _RED_("failed") " )", msg);
|
||||
return PM3_EFLASH;
|
||||
}
|
||||
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int CmdFlashMemInfo(const char *Cmd) {
|
||||
|
||||
uint8_t sha_hash[20] = {0};
|
||||
mbedtls_rsa_context rsa;
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "mem info",
|
||||
"Collect signature and verify it from flash memory",
|
||||
"mem info"
|
||||
// "mem info -s"
|
||||
);
|
||||
|
||||
uint8_t cmdp = 0;
|
||||
bool errors = false, shall_write = false, shall_sign = false;
|
||||
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
||||
switch (tolower(param_getchar(Cmd, cmdp))) {
|
||||
case 'h':
|
||||
return usage_flashmem_info();
|
||||
case 's': {
|
||||
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;
|
||||
}
|
||||
}
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
// arg_lit0("s", NULL, "create a signature"),
|
||||
// arg_lit0("w", NULL, "write signature to flash memory"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
|
||||
//Validations
|
||||
if (errors) {
|
||||
usage_flashmem_info();
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
bool shall_sign = false, shall_write = false;
|
||||
// shall_sign = arg_get_lit(ctx, 1);
|
||||
// shall_write = arg_get_lit(ctx, 2);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_FLASHMEM_INFO, NULL, 0);
|
||||
PacketResponseNG resp;
|
||||
if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) {
|
||||
PrintAndLogEx(WARNING, "timeout while waiting for reply.");
|
||||
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) {
|
||||
if (isok == false) {
|
||||
PrintAndLogEx(FAILED, "failed");
|
||||
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));
|
||||
|
||||
// Flash ID hash (sha1)
|
||||
uint8_t sha_hash[20] = {0};
|
||||
mbedtls_sha1(mem.flashid, sizeof(mem.flashid), sha_hash);
|
||||
|
||||
// print header
|
||||
PrintAndLogEx(INFO, "\n--- Flash memory Information ---------");
|
||||
PrintAndLogEx(INFO, "-------------------------------------------------------------");
|
||||
PrintAndLogEx(INFO, "ID | %s", sprint_hex(mem.flashid, sizeof(mem.flashid)));
|
||||
PrintAndLogEx(INFO, "SHA1 | %s", sprint_hex(sha_hash, sizeof(sha_hash)));
|
||||
PrintAndLogEx(INFO, "RSA SIGNATURE |");
|
||||
print_hex_break(mem.signature, sizeof(mem.signature), 32);
|
||||
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, "");
|
||||
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
|
||||
|
@ -473,7 +386,10 @@ static int CmdFlashMemInfo(const char *Cmd) {
|
|||
#define RSA_E "010001"
|
||||
|
||||
// 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)
|
||||
|
@ -516,9 +432,9 @@ static int CmdFlashMemInfo(const char *Cmd) {
|
|||
"F5A3B2A5D33605AEBBCCBA7FEB9F2D2F" \
|
||||
"A74206CEC169D74BF5A8C50D6F48EA08"
|
||||
|
||||
|
||||
#define KEY_LEN 128
|
||||
|
||||
mbedtls_rsa_context rsa;
|
||||
mbedtls_rsa_init(&rsa, MBEDTLS_RSA_PKCS_V15, 0);
|
||||
|
||||
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.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);
|
||||
|
||||
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)
|
||||
PrintAndLogEx(SUCCESS, "RSA key validation ok");
|
||||
PrintAndLogEx(SUCCESS, "%s( " _GREEN_("ok") " )", msgkey);
|
||||
else
|
||||
PrintAndLogEx(FAILED, "RSA key validation failed");
|
||||
PrintAndLogEx(FAILED, "%s( " _RED_("failed") " )", msgkey);
|
||||
|
||||
//
|
||||
uint8_t from_device[KEY_LEN];
|
||||
|
@ -554,10 +488,11 @@ static int CmdFlashMemInfo(const char *Cmd) {
|
|||
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, "RSA Signing ok");
|
||||
PrintAndLogEx(SUCCESS, "%s( " _GREEN_("ok") " )", msgsign);
|
||||
else
|
||||
PrintAndLogEx(FAILED, "RSA Signing failed");
|
||||
PrintAndLogEx(FAILED, "%s( " _RED_("failed") " )", msgsign);
|
||||
|
||||
if (shall_write) {
|
||||
// save to mem
|
||||
|
@ -574,29 +509,33 @@ static int CmdFlashMemInfo(const char *Cmd) {
|
|||
|
||||
}
|
||||
}
|
||||
PrintAndLogEx(INFO, "Signed | ");
|
||||
print_hex_break(sign, sizeof(sign), 32);
|
||||
PrintAndLogEx(INFO, "Signed");
|
||||
for (int i = 0; i < (sizeof(sign) / 32); i++) {
|
||||
PrintAndLogEx(INFO, " %s", sprint_hex_inrow(sign + (i * 32), 32));
|
||||
}
|
||||
}
|
||||
|
||||
// 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, "RSA Verification ok");
|
||||
PrintAndLogEx(SUCCESS, "%s( " _GREEN_("ok") " )", msgverify);
|
||||
else
|
||||
PrintAndLogEx(FAILED, "RSA Verification failed");
|
||||
PrintAndLogEx(FAILED, "%s( " _RED_("failed") " )", msgverify);
|
||||
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
mbedtls_rsa_free(&rsa);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static command_t CommandTable[] = {
|
||||
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
||||
{"spiffs", CmdFlashMemSpiFFS, IfPm3Flash, "High level SPI FileSystem Flash manipulation [rdv40]"},
|
||||
{"spibaud", CmdFlashmemSpiBaudrate, IfPm3Flash, "Set Flash memory Spi baudrate [rdv40]"},
|
||||
{"info", CmdFlashMemInfo, IfPm3Flash, "Flash memory information [rdv40]"},
|
||||
{"load", CmdFlashMemLoad, IfPm3Flash, "Load data into flash memory [rdv40]"},
|
||||
{"dump", CmdFlashMemDump, IfPm3Flash, "Dump data from flash memory [rdv40]"},
|
||||
{"wipe", CmdFlashMemWipe, IfPm3Flash, "Wipe data from flash memory [rdv40]"},
|
||||
{"baudrate", CmdFlashmemSpiBaudrate, IfPm3Flash, "Set Flash memory Spi baudrate"},
|
||||
{"spiffs", CmdFlashMemSpiFFS, IfPm3Flash, "High level SPI FileSystem Flash manipulation"},
|
||||
{"info", CmdFlashMemInfo, IfPm3Flash, "Flash memory information"},
|
||||
{"load", CmdFlashMemLoad, IfPm3Flash, "Load data into flash memory"},
|
||||
{"dump", CmdFlashMemDump, IfPm3Flash, "Dump data from flash memory"},
|
||||
{"wipe", CmdFlashMemWipe, IfPm3Flash, "Wipe data from flash memory"},
|
||||
{NULL, NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue