style
[RRG-proxmark3.git] / client / src / cmdflashmem.c
bloba43989886a13779c9aff467c9fad232f70c9795c
1 //-----------------------------------------------------------------------------
2 // Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // See LICENSE.txt for the text of the license.
15 //-----------------------------------------------------------------------------
16 // Proxmark3 RDV40 Flash memory commands
17 //-----------------------------------------------------------------------------
18 #include "cmdflashmem.h"
19 #include <ctype.h>
20 #include "cmdparser.h" // command_t
21 #include "cliparser.h"
22 #include "pmflash.h" // rdv40validation_t
23 #include "fileutils.h" // saveFile
24 #include "comms.h" // getfromdevice
25 #include "cmdflashmemspiffs.h" // spiffs commands
26 #include "rsa.h"
27 #include "sha1.h"
28 #include "pk.h" // PEM key load functions
30 #define MCK 48000000
31 #define FLASH_MINFAST 24000000 //33000000
32 #define FLASH_BAUD MCK/2
33 #define FLASH_FASTBAUD MCK
34 #define FLASH_MINBAUD FLASH_FASTBAUD
36 static int CmdHelp(const char *Cmd);
38 //-------------------------------------------------------------------------------------
39 // RRG Public RSA Key
40 #define RRG_RSA_KEY_LEN 128
42 // public key Exponent E
43 #define RRG_RSA_E "010001"
45 // public key modulus N
46 #define RRG_RSA_N "E28D809BF323171D11D1ACA4C32A5B7E0A8974FD171E75AD120D60E9B76968FF" \
47 "4B0A6364AE50583F9555B8EE1A725F279E949246DF0EFCE4C02B9F3ACDCC623F" \
48 "9337F21C0C066FFB703D8BFCB5067F309E056772096642C2B1A8F50305D5EC33" \
49 "DB7FB5A3C8AC42EB635AE3C148C910750ABAA280CE82DC2F180F49F30A1393B5"
51 //-------------------------------------------------------------------------------------
53 int rdv4_get_signature(rdv40_validation_t *out) {
54 if (out == NULL) {
55 return PM3_EINVARG;
58 clearCommandBuffer();
59 SendCommandNG(CMD_FLASHMEM_INFO, NULL, 0);
60 PacketResponseNG resp;
61 if (WaitForResponseTimeout(CMD_ACK, &resp, 2500) == false) {
62 PrintAndLogEx(WARNING, "timeout while waiting for reply");
63 return PM3_ETIMEOUT;
66 uint8_t isok = resp.oldarg[0] & 0xFF;
67 if (isok == false) {
68 PrintAndLogEx(FAILED, "fail reading from flashmemory");
69 return PM3_EFLASH;
72 //rdv40_validation_t mem;
73 memcpy(out, (rdv40_validation_t *)resp.data.asBytes, sizeof(rdv40_validation_t));
74 return PM3_SUCCESS;
77 // validate signature
78 int rdv4_validate(rdv40_validation_t *mem) {
79 // Flash ID hash (sha1)
80 uint8_t sha_hash[20] = {0};
81 mbedtls_sha1(mem->flashid, sizeof(mem->flashid), sha_hash);
83 // set up RSA
84 mbedtls_rsa_context rsa;
85 mbedtls_rsa_init(&rsa, MBEDTLS_RSA_PKCS_V15, 0);
86 rsa.len = RRG_RSA_KEY_LEN;
87 mbedtls_mpi_read_string(&rsa.N, 16, RRG_RSA_N);
88 mbedtls_mpi_read_string(&rsa.E, 16, RRG_RSA_E);
90 // Verify (public key)
91 int is_verified = mbedtls_rsa_pkcs1_verify(&rsa, NULL, NULL, MBEDTLS_RSA_PUBLIC, MBEDTLS_MD_SHA1, 20, sha_hash, mem->signature);
92 mbedtls_rsa_free(&rsa);
94 if (is_verified == 0) {
95 return PM3_SUCCESS;
97 return PM3_EFAILED;
100 static int rdv4_sign_write(uint8_t *signature, uint8_t slen) {
101 flashmem_old_write_t payload = {
102 .startidx = FLASH_MEM_SIGNATURE_OFFSET,
103 .len = FLASH_MEM_SIGNATURE_LEN,
105 memcpy(payload.data, signature, slen);
107 clearCommandBuffer();
108 PacketResponseNG resp;
109 SendCommandNG(CMD_FLASHMEM_WRITE, (uint8_t *)&payload, sizeof(payload));
111 if (WaitForResponseTimeout(CMD_FLASHMEM_WRITE, &resp, 2000) == false) {
112 PrintAndLogEx(WARNING, "timeout while waiting for reply");
113 return PM3_EFAILED;
114 } else {
115 if (resp.status != PM3_SUCCESS) {
116 PrintAndLogEx(FAILED, "Writing signature ( "_RED_("fail") ")");
117 return PM3_EFAILED;
120 PrintAndLogEx(SUCCESS, "Writing signature at offset %u ( "_GREEN_("ok") " )", FLASH_MEM_SIGNATURE_OFFSET);
121 return PM3_SUCCESS;
124 static int CmdFlashmemSpiBaud(const char *Cmd) {
126 CLIParserContext *ctx;
127 CLIParserInit(&ctx, "mem baudrate",
128 "Set the baudrate for the SPI flash memory communications.\n"
129 "Reading Flash ID will virtually always fail under 48MHz setting.\n"
130 "Unless you know what you are doing, please stay at 24MHz.\n"
131 "If >= 24MHz, FASTREADS instead of READS instruction will be used.",
132 "mem baudrate --mhz 48"
135 void *argtable[] = {
136 arg_param_begin,
137 arg_int1(NULL, "mhz", "<24|48>", "SPI baudrate in MHz"),
138 arg_param_end
140 CLIExecWithReturn(ctx, Cmd, argtable, false);
141 int br = arg_get_int_def(ctx, 1, -1);
142 CLIParserFree(ctx);
144 if (br == -1) {
145 PrintAndLogEx(ERR, "failed to get baudrate");
146 return PM3_EINVARG;
149 uint32_t baudrate = br * 1000000;
150 if (baudrate != FLASH_BAUD && baudrate != FLASH_MINBAUD) {
151 PrintAndLogEx(ERR, "wrong baudrate. Only 24 or 48 is allowed");
152 return PM3_EINVARG;
154 SendCommandNG(CMD_FLASHMEM_SET_SPIBAUDRATE, (uint8_t *)&baudrate, sizeof(uint32_t));
155 return PM3_SUCCESS;
158 static int CmdFlashMemLoad(const char *Cmd) {
160 CLIParserContext *ctx;
161 CLIParserInit(&ctx, "mem load",
162 "Loads binary file into flash memory on device\n"
163 "Warning: mem area to be written must have been wiped first\n"
164 "( this is already taken care when loading dictionaries )",
165 "mem load -f myfile -> upload file myfile values at default offset 0\n"
166 "mem load -f myfile -o 1024 -> upload file myfile values at offset 1024\n"
167 "mem load -f mfc_default_keys -m -> upload MFC keys\n"
168 "mem load -f t55xx_default_pwds -t -> upload T55XX passwords\n"
169 "mem load -f iclass_default_keys -i -> upload iCLASS keys\n"
172 void *argtable[] = {
173 arg_param_begin,
174 arg_int0("o", "offset", "<dec>", "offset in memory"),
175 arg_lit0("m", "mifare,mfc", "upload 6 bytes keys (mifare key dictionary)"),
176 arg_lit0("i", "iclass", "upload 8 bytes keys (iClass key dictionary)"),
177 arg_lit0("t", "t55xx", "upload 4 bytes keys (password dictionary)"),
178 arg_str1("f", "file", "<fn>", "file name"),
179 arg_param_end
181 CLIExecWithReturn(ctx, Cmd, argtable, false);
183 int offset = arg_get_int_def(ctx, 1, 0);
184 bool is_mfc = arg_get_lit(ctx, 2);
185 bool is_iclass = arg_get_lit(ctx, 3);
186 bool is_t55xx = arg_get_lit(ctx, 4);
187 int fnlen = 0;
188 char filename[FILE_PATH_SIZE] = {0};
189 CLIParamStrToBuf(arg_get_str(ctx, 5), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
190 CLIParserFree(ctx);
192 Dictionary_t d = DICTIONARY_NONE;
193 if (is_mfc) {
194 d = DICTIONARY_MIFARE;
195 PrintAndLogEx(INFO, "treating file as MIFARE Classic keys");
196 } else if (is_iclass) {
197 d = DICTIONARY_ICLASS;
198 PrintAndLogEx(INFO, "treating file as iCLASS keys");
199 } else if (is_t55xx) {
200 d = DICTIONARY_T55XX;
201 PrintAndLogEx(INFO, "treating file as T55xx passwords");
204 size_t datalen = 0;
205 uint32_t keycount = 0;
206 int res = 0;
207 uint8_t keylen = 0;
208 uint8_t *data = calloc(FLASH_MEM_MAX_SIZE, sizeof(uint8_t));
210 switch (d) {
211 case DICTIONARY_MIFARE:
212 offset = DEFAULT_MF_KEYS_OFFSET;
213 keylen = 6;
214 res = loadFileDICTIONARY(filename, data + 2, &datalen, keylen, &keycount);
215 if (res || !keycount) {
216 free(data);
217 return PM3_EFILE;
219 // limited space on flash mem
220 if (keycount > DEFAULT_MF_KEYS_MAX) {
221 keycount = DEFAULT_MF_KEYS_MAX;
222 datalen = keycount * keylen;
225 data[0] = (keycount >> 0) & 0xFF;
226 data[1] = (keycount >> 8) & 0xFF;
227 datalen += 2;
228 break;
229 case DICTIONARY_T55XX:
230 offset = DEFAULT_T55XX_KEYS_OFFSET;
231 keylen = 4;
232 res = loadFileDICTIONARY(filename, data + 2, &datalen, keylen, &keycount);
233 if (res || !keycount) {
234 free(data);
235 return PM3_EFILE;
237 // limited space on flash mem
238 if (keycount > DEFAULT_T55XX_KEYS_MAX) {
239 keycount = DEFAULT_T55XX_KEYS_MAX;
240 datalen = keycount * keylen;
243 data[0] = (keycount >> 0) & 0xFF;
244 data[1] = (keycount >> 8) & 0xFF;
245 datalen += 2;
246 break;
247 case DICTIONARY_ICLASS:
248 offset = DEFAULT_ICLASS_KEYS_OFFSET;
249 res = loadFileDICTIONARY(filename, data + 2, &datalen, keylen, &keycount);
250 if (res || !keycount) {
251 free(data);
252 return PM3_EFILE;
254 // limited space on flash mem
255 if (keycount > DEFAULT_ICLASS_KEYS_MAX) {
256 keycount = DEFAULT_ICLASS_KEYS_MAX;
257 datalen = keycount * keylen;
260 data[0] = (keycount >> 0) & 0xFF;
261 data[1] = (keycount >> 8) & 0xFF;
262 datalen += 2;
263 break;
264 case DICTIONARY_NONE:
265 res = loadFile_safe(filename, ".bin", (void **)&data, &datalen);
266 if (res != PM3_SUCCESS) {
267 free(data);
268 return PM3_EFILE;
271 if (datalen > FLASH_MEM_MAX_SIZE) {
272 PrintAndLogEx(ERR, "error, filesize is larger than available memory");
273 free(data);
274 return PM3_EOVFLOW;
276 break;
279 // ICEMAN: not needed when we transite to loadxxxx_safe methods
280 uint8_t *newdata = realloc(data, datalen);
281 if (newdata == NULL) {
282 free(data);
283 return PM3_EMALLOC;
284 } else {
285 data = newdata;
288 //Send to device
289 uint32_t bytes_sent = 0;
290 uint32_t bytes_remaining = datalen;
293 // fast push mode
294 g_conn.block_after_ACK = true;
296 while (bytes_remaining > 0) {
297 uint32_t bytes_in_packet = MIN(FLASH_MEM_BLOCK_SIZE, bytes_remaining);
299 clearCommandBuffer();
301 flashmem_old_write_t payload = {
302 .startidx = offset + bytes_sent,
303 .len = bytes_in_packet,
305 memcpy(payload.data, data + bytes_sent, bytes_in_packet);
306 SendCommandNG(CMD_FLASHMEM_WRITE, (uint8_t *)&payload, sizeof(payload));
308 bytes_remaining -= bytes_in_packet;
309 bytes_sent += bytes_in_packet;
311 PacketResponseNG resp;
312 if (WaitForResponseTimeout(CMD_FLASHMEM_WRITE, &resp, 2000) == false) {
313 PrintAndLogEx(WARNING, "timeout while waiting for reply.");
314 g_conn.block_after_ACK = false;
315 free(data);
316 return PM3_ETIMEOUT;
319 if (resp.status != PM3_SUCCESS) {
320 g_conn.block_after_ACK = false;
321 PrintAndLogEx(FAILED, "Flash write fail [offset %u]", bytes_sent);
322 free(data);
323 return PM3_EFLASH;
327 g_conn.block_after_ACK = false;
328 free(data);
329 PrintAndLogEx(SUCCESS, "Wrote "_GREEN_("%zu")" bytes to offset "_GREEN_("%u"), datalen, offset);
330 return PM3_SUCCESS;
333 static int CmdFlashMemDump(const char *Cmd) {
335 CLIParserContext *ctx;
336 CLIParserInit(&ctx, "mem dump",
337 "Dumps flash memory on device into a file or view in console",
338 "mem dump -f myfile -> download all flashmem to file\n"
339 "mem dump --view -o 262015 --len 128 -> display 128 bytes from offset 262015 (RSA sig)\n"
340 "mem dump --view -f myfile -o 241664 --len 58 -> display 58 bytes from offset 241664 and save to file"
343 void *argtable[] = {
344 arg_param_begin,
345 arg_int0("o", "offset", "<dec>", "offset in memory"),
346 arg_int0("l", "len", "<dec>", "length"),
347 arg_lit0("v", "view", "view dump"),
348 arg_str0("f", "file", "<fn>", "save filename"),
349 arg_int0("c", "cols", "<dec>", "column breaks (def 32)"),
350 arg_param_end
352 CLIExecWithReturn(ctx, Cmd, argtable, false);
354 int offset = arg_get_int_def(ctx, 1, 0);
355 int len = arg_get_int_def(ctx, 2, FLASH_MEM_MAX_SIZE);
356 bool view = arg_get_lit(ctx, 3);
357 int fnlen = 0;
358 char filename[FILE_PATH_SIZE] = {0};
359 CLIParamStrToBuf(arg_get_str(ctx, 4), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
360 int breaks = arg_get_int_def(ctx, 5, 32);
361 CLIParserFree(ctx);
363 uint8_t *dump = calloc(len, sizeof(uint8_t));
364 if (!dump) {
365 PrintAndLogEx(ERR, "error, cannot allocate memory ");
366 return PM3_EMALLOC;
369 PrintAndLogEx(INFO, "downloading "_YELLOW_("%u")" bytes from flash memory", len);
370 if (!GetFromDevice(FLASH_MEM, dump, len, offset, NULL, 0, NULL, -1, true)) {
371 PrintAndLogEx(FAILED, "ERROR; downloading from flash memory");
372 free(dump);
373 return PM3_EFLASH;
376 if (view) {
377 PrintAndLogEx(INFO, "---- " _CYAN_("data") " ---------------");
378 print_hex_break(dump, len, breaks);
381 if (filename[0] != '\0') {
382 pm3_save_dump(filename, dump, len, jsfRaw);
385 free(dump);
386 return PM3_SUCCESS;
389 static int CmdFlashMemWipe(const char *Cmd) {
391 CLIParserContext *ctx;
392 CLIParserInit(&ctx, "mem wipe",
393 "Wipe flash memory on device, which fills it with 0xFF\n"
394 _WHITE_("[ ") _RED_("!!! OBS") _WHITE_(" ] use with caution"),
395 "mem wipe -p 0 -> wipes first page"
396 // "mem wipe -i -> initial total wipe"
399 void *argtable[] = {
400 arg_param_begin,
401 arg_int0("p", NULL, "<dec>", "0,1,2 page memory"),
402 // arg_lit0("i", NULL, "initial total wipe"),
403 arg_param_end
405 CLIExecWithReturn(ctx, Cmd, argtable, false);
407 bool initialwipe = false;
408 int page = arg_get_int_def(ctx, 1, -1);
409 // initialwipe = arg_get_lit(ctx, 2);
410 CLIParserFree(ctx);
412 if (page < 0 || page > 2) {
413 PrintAndLogEx(WARNING, "page must be 0, 1 or 2");
414 return PM3_EINVARG;
417 clearCommandBuffer();
418 SendCommandMIX(CMD_FLASHMEM_WIPE, page, initialwipe, 0, NULL, 0);
419 PacketResponseNG resp;
420 if (!WaitForResponseTimeout(CMD_ACK, &resp, 8000)) {
421 PrintAndLogEx(WARNING, "timeout while waiting for reply.");
422 return PM3_ETIMEOUT;
425 const char *msg = "Flash WIPE ";
426 uint8_t isok = resp.oldarg[0] & 0xFF;
427 if (isok)
428 PrintAndLogEx(SUCCESS, "%s ( " _GREEN_("ok")" )", msg);
429 else {
430 PrintAndLogEx(FAILED, "%s ( " _RED_("failed") " )", msg);
431 return PM3_EFLASH;
434 return PM3_SUCCESS;
437 static int CmdFlashMemInfo(const char *Cmd) {
439 CLIParserContext *ctx;
440 CLIParserInit(&ctx, "mem info",
441 "Collect signature and verify it from flash memory",
442 "mem info"
445 void *argtable[] = {
446 arg_param_begin,
447 arg_lit0("s", "sign", "create a signature"),
448 arg_str0("d", NULL, "<hex>", "flash memory id, 8 hex bytes"),
449 arg_str0("p", "pem", "<fn>", "key in PEM format"),
450 arg_lit0("v", "verbose", "verbose output"),
451 // arg_lit0("w", "write", "write signature to flash memory"),
452 arg_param_end
454 CLIExecWithReturn(ctx, Cmd, argtable, true);
456 bool shall_sign = arg_get_lit(ctx, 1);
458 int dlen = 0;
459 uint8_t id[8] = {0};
460 int res = CLIParamHexToBuf(arg_get_str(ctx, 2), id, sizeof(id), &dlen);
462 int pemlen = 0;
463 char pem_fn[FILE_PATH_SIZE] = {0};
464 CLIParamStrToBuf(arg_get_str(ctx, 3), (uint8_t *)pem_fn, FILE_PATH_SIZE, &pemlen);
466 bool verbose = arg_get_lit(ctx, 4);
467 bool shall_write = false;
468 // shall_write = arg_get_lit(ctx, 5);
469 CLIParserFree(ctx);
471 if (res) {
472 return PM3_EINVARG;
475 if (dlen > 0 && dlen < sizeof(id)) {
476 PrintAndLogEx(FAILED, "Error parsing flash memory id, expect 8, got %d", dlen);
477 return PM3_EINVARG;
480 // set up PK key context now.
481 mbedtls_pk_context pkctx;
482 mbedtls_pk_init(&pkctx);
483 bool got_private = false;
484 // PEM
485 if (pemlen) {
486 // PEM file
487 char *path = NULL;
488 if (searchFile(&path, RESOURCES_SUBDIR, pem_fn, ".pem", true) != PM3_SUCCESS) {
489 if (searchFile(&path, RESOURCES_SUBDIR, pem_fn, "", false) != PM3_SUCCESS) {
490 return PM3_EFILE;
494 PrintAndLogEx(INFO, "loading file `" _YELLOW_("%s") "`" NOLF, path);
496 // load private
497 res = mbedtls_pk_parse_keyfile(&pkctx, path, NULL);
498 free(path);
499 //res = mbedtls_pk_parse_public_keyfile(&pkctx, path);
500 if (res == 0) {
501 PrintAndLogEx(NORMAL, " ( " _GREEN_("ok") " )");
502 } else {
503 PrintAndLogEx(NORMAL, " ( " _RED_("fail") " )");
504 mbedtls_pk_free(&pkctx);
505 return PM3_EFILE;
508 mbedtls_rsa_context *rsa = (mbedtls_rsa_context *)pkctx.pk_ctx;
509 if (rsa == NULL) {
510 PrintAndLogEx(FAILED, "failed to allocate rsa context memory");
511 return PM3_EMALLOC;
513 got_private = true;
514 } else {
516 // it not loaded, we need to setup the context manually
517 if (mbedtls_pk_setup(&pkctx, mbedtls_pk_info_from_type((mbedtls_pk_type_t) MBEDTLS_PK_RSA)) != 0) {
518 PrintAndLogEx(FAILED, "failed, mbedtls_pk_setup returned ");
519 return PM3_ESOFT;
523 // validate devicesignature data
524 rdv40_validation_t mem;
525 res = rdv4_get_signature(&mem);
526 if (res != PM3_SUCCESS) {
527 return res;
530 res = rdv4_validate(&mem);
532 // Flash ID hash (sha1)
533 uint8_t sha_hash[20] = {0};
534 mbedtls_sha1(mem.flashid, sizeof(mem.flashid), sha_hash);
536 // print header
537 PrintAndLogEx(NORMAL, "");
538 PrintAndLogEx(INFO, "--- " _CYAN_("Flash memory Information") " ---------");
539 PrintAndLogEx(INFO, "ID................... %s", sprint_hex_inrow(mem.flashid, sizeof(mem.flashid)));
540 PrintAndLogEx(INFO, "SHA1................. %s", sprint_hex_inrow(sha_hash, sizeof(sha_hash)));
541 PrintAndLogEx(NORMAL, "");
542 PrintAndLogEx(INFO, "--- " _CYAN_("RDV4 RSA signature") " ---------------");
543 for (int i = 0; i < (sizeof(mem.signature) / 32); i++) {
544 PrintAndLogEx(INFO, " %s", sprint_hex_inrow(mem.signature + (i * 32), 32));
546 PrintAndLogEx(
547 (res == PM3_SUCCESS) ? SUCCESS : FAILED,
548 "Signature............ ( %s )",
549 (res == PM3_SUCCESS) ? _GREEN_("ok") : _RED_("fail")
551 PrintAndLogEx(NORMAL, "");
553 mbedtls_rsa_context *rsa = NULL;
555 if (got_private) {
556 rsa = mbedtls_pk_rsa(pkctx);
557 rsa->padding = MBEDTLS_RSA_PKCS_V15;
558 rsa->hash_id = 0;
559 rsa->len = RRG_RSA_KEY_LEN;
560 } else {
562 rsa = (mbedtls_rsa_context *)calloc(1, sizeof(mbedtls_rsa_context));
563 mbedtls_rsa_init(rsa, MBEDTLS_RSA_PKCS_V15, 0);
564 rsa->len = RRG_RSA_KEY_LEN;
566 // add public key
567 mbedtls_mpi_read_string(&rsa->N, 16, RRG_RSA_N);
568 mbedtls_mpi_read_string(&rsa->E, 16, RRG_RSA_E);
571 PrintAndLogEx(INFO, "--- " _CYAN_("RDV4 RSA Public key") " --------------");
572 if (verbose) {
573 char str_exp[10];
574 char str_pk[261];
575 size_t exlen = 0, pklen = 0;
576 mbedtls_mpi_write_string(&rsa->E, 16, str_exp, sizeof(str_exp), &exlen);
577 mbedtls_mpi_write_string(&rsa->N, 16, str_pk, sizeof(str_pk), &pklen);
579 PrintAndLogEx(INFO, "Len.................. %"PRIu64, rsa->len);
580 PrintAndLogEx(INFO, "Exponent............. %s", str_exp);
581 PrintAndLogEx(INFO, "Public key modulus N");
582 PrintAndLogEx(INFO, " %.64s", str_pk);
583 PrintAndLogEx(INFO, " %.64s", str_pk + 64);
584 PrintAndLogEx(INFO, " %.64s", str_pk + 128);
585 PrintAndLogEx(INFO, " %.64s", str_pk + 192);
586 PrintAndLogEx(NORMAL, "");
589 bool is_keyok = (mbedtls_rsa_check_pubkey(rsa) == 0);
590 PrintAndLogEx(
591 (is_keyok) ? SUCCESS : FAILED,
592 "RDV4 RSA public key check.... ( %s )",
593 (is_keyok) ? _GREEN_("ok") : _RED_("fail")
596 is_keyok = (mbedtls_rsa_check_privkey(rsa) == 0);
597 if (verbose) {
598 PrintAndLogEx(
599 (is_keyok) ? SUCCESS : FAILED,
600 "RDV4 RSA private key check... ( %s )",
601 (is_keyok) ? _GREEN_("ok") : _YELLOW_("n/aA")
605 // to be verified
606 uint8_t from_device[RRG_RSA_KEY_LEN];
607 memcpy(from_device, mem.signature, RRG_RSA_KEY_LEN);
609 // to be signed
610 uint8_t sign[RRG_RSA_KEY_LEN];
611 memset(sign, 0, RRG_RSA_KEY_LEN);
613 // Signing (private key)
614 if (shall_sign) {
616 if (is_keyok) {
618 PrintAndLogEx(NORMAL, "");
619 PrintAndLogEx(INFO, "--- " _CYAN_("Enter signing") " --------------------");
621 if (dlen == 8) {
622 mbedtls_sha1(id, sizeof(id), sha_hash);
624 PrintAndLogEx(INFO, "Signing....... %s", sprint_hex_inrow(sha_hash, sizeof(sha_hash)));
626 int is_signed = mbedtls_rsa_pkcs1_sign(rsa, NULL, NULL, MBEDTLS_RSA_PRIVATE, MBEDTLS_MD_SHA1, 20, sha_hash, sign);
627 PrintAndLogEx(
628 (is_signed == 0) ? SUCCESS : FAILED,
629 "RSA signing... ( %s )",
630 (is_signed == 0) ? _GREEN_("ok") : _RED_("fail")
633 if (shall_write) {
634 rdv4_sign_write(sign, RRG_RSA_KEY_LEN);
636 PrintAndLogEx(INFO, "New signature");
637 for (int i = 0; i < (sizeof(sign) / 32); i++) {
638 PrintAndLogEx(INFO, " %s", sprint_hex_inrow(sign + (i * 32), 32));
640 } else {
641 PrintAndLogEx(FAILED, "no private key available to sign");
645 // Verify (public key)
646 bool is_verified = (mbedtls_rsa_pkcs1_verify(rsa, NULL, NULL, MBEDTLS_RSA_PUBLIC, MBEDTLS_MD_SHA1, 20, sha_hash, from_device) == 0);
648 if (got_private == false) {
649 mbedtls_rsa_free(rsa);
650 free(rsa);
653 mbedtls_pk_free(&pkctx);
655 PrintAndLogEx(NORMAL, "");
656 PrintAndLogEx(
657 (is_verified) ? SUCCESS : FAILED,
658 "Genuine Proxmark3 RDV4 signature detected... %s",
659 (is_verified) ? ":heavy_check_mark:" : ":x:"
661 PrintAndLogEx(NORMAL, "");
662 return PM3_SUCCESS;
665 static command_t CommandTable[] = {
666 {"spiffs", CmdFlashMemSpiFFS, IfPm3Flash, "{ SPI File system }"},
667 {"help", CmdHelp, AlwaysAvailable, "This help"},
668 {"baudrate", CmdFlashmemSpiBaud, IfPm3Flash, "Set Flash memory Spi baudrate"},
669 {"dump", CmdFlashMemDump, IfPm3Flash, "Dump data from flash memory"},
670 {"info", CmdFlashMemInfo, IfPm3Flash, "Flash memory information"},
671 {"load", CmdFlashMemLoad, IfPm3Flash, "Load data to flash memory"},
672 {"wipe", CmdFlashMemWipe, IfPm3Flash, "Wipe data from flash memory"},
673 {NULL, NULL, NULL, NULL}
676 static int CmdHelp(const char *Cmd) {
677 (void)Cmd; // Cmd is not used so far
678 CmdsHelp(CommandTable);
679 return PM3_SUCCESS;
682 int CmdFlashMem(const char *Cmd) {
683 clearCommandBuffer();
684 return CmdsParse(CommandTable, Cmd);