From 7e7e030661ffbc5fde193d72d7941000c0d6c680 Mon Sep 17 00:00:00 2001 From: Martin Beynon Date: Thu, 25 Nov 2021 14:13:17 +0000 Subject: [PATCH] wip: adding pubkey programming --- src/lattice.cpp | 276 ++++++++++++++++++++++++++++++++++++++++++++++++ src/lattice.hpp | 7 +- 2 files changed, 281 insertions(+), 2 deletions(-) diff --git a/src/lattice.cpp b/src/lattice.cpp index f5f7b8d..43712a4 100644 --- a/src/lattice.cpp +++ b/src/lattice.cpp @@ -132,6 +132,8 @@ using namespace std; #define READ_ECDSA_PUBKEY3 0x64 /* This command is used to read the fourth 128 bits of the ECDSA Public Key. */ #define ISC_NOOP 0xff /* This command is no operation command (NOOP) or null operation. */ +#define PUBKEY_LENGTH_BYTES 64 /* length of the public key (MachXO3D) in bytes */ + Lattice::Lattice(Jtag *jtag, const string filename, const string &file_type, Device::prog_type_t prg_type, std::string flash_sector, bool verify, int8_t verbose): Device(jtag, filename, file_type, verify, verbose), @@ -182,6 +184,9 @@ Lattice::Lattice(Jtag *jtag, const string filename, const string &file_type, } else if (flash_sector == "FEA") { _flash_sector = LATTICE_FLASH_FEA; printInfo("Flash Sector: FEA", true); + } else if (flash_sector == "PKEY") { + _flash_sector = LATTICE_FLASH_PKEY; + printInfo("Flash Sector: PKEY", true); } else { printError("Unknown flash sector"); throw std::exception(); @@ -610,6 +615,9 @@ bool Lattice::program_flash(unsigned int offset) else if (_file_extension == "fea") { retval = program_fea_MachXO3D(); } + else if (_file_extension == "pub") { + retval = program_pubkey_MachXO3D(); + } else retval = program_extFlash(offset); @@ -1397,6 +1405,104 @@ bool Lattice::programFeabits_MachXO3D(uint32_t feabits) return true; } +bool Lattice::programPubKey_MachXO3D(uint8_t* pubkey) +{ + uint8_t rxkey[PUBKEY_LENGTH_BYTES] = { 0 }; + uint8_t tx[16]; + int i; + + if (_verbose) { + printf("\tProgramming ECDSA PubKey: ["); + for (i = 0; i < PUBKEY_LENGTH_BYTES; i++) { + printf("%02x", pubkey[i]); + } + printf("]\n"); + } + + for(i = 0; i < 16; i++) { + tx[i] = pubkey[63 - i]; + } + wr_rd(PROG_ECDSA_PUBKEY0, tx, 16, NULL, 0); + _jtag->set_state(Jtag::RUN_TEST_IDLE); + _jtag->toggleClk(2); + + wr_rd(0xff, NULL, 0, NULL, 0); + if (!pollBusyFlag()) + return false; + + for(i = 0; i < 16; i++) { + tx[i] = pubkey[47 - i]; + } + wr_rd(PROG_ECDSA_PUBKEY1, tx, 16, NULL, 0); + _jtag->set_state(Jtag::RUN_TEST_IDLE); + _jtag->toggleClk(2); + + wr_rd(0xff, NULL, 0, NULL, 0); + if (!pollBusyFlag()) + return false; + + for(i = 0; i < 16; i++) { + tx[i] = pubkey[31 - i]; + } + wr_rd(PROG_ECDSA_PUBKEY2, tx, 16, NULL, 0); + _jtag->set_state(Jtag::RUN_TEST_IDLE); + _jtag->toggleClk(2); + + wr_rd(0xff, NULL, 0, NULL, 0); + if (!pollBusyFlag()) + return false; + + for(i = 0; i < 16; i++) { + tx[i] = pubkey[15 - i]; + } + wr_rd(PROG_ECDSA_PUBKEY3, tx, 16, NULL, 0); + _jtag->set_state(Jtag::RUN_TEST_IDLE); + _jtag->toggleClk(2); + + wr_rd(0xff, NULL, 0, NULL, 0); + if (!pollBusyFlag()) + return false; + + if (_verbose || _verify) { + /* read the current feature row */ + wr_rd(READ_ECDSA_PUBKEY0, NULL, 0, rxkey, 16); + _jtag->set_state(Jtag::RUN_TEST_IDLE); + _jtag->toggleClk(2); + + wr_rd(READ_ECDSA_PUBKEY1, NULL, 0, rxkey + 16, 16); + _jtag->set_state(Jtag::RUN_TEST_IDLE); + _jtag->toggleClk(2); + + wr_rd(READ_ECDSA_PUBKEY2, NULL, 0, rxkey + 32, 16); + _jtag->set_state(Jtag::RUN_TEST_IDLE); + _jtag->toggleClk(2); + + wr_rd(READ_ECDSA_PUBKEY3, NULL, 0, rxkey + 48, 16); + _jtag->set_state(Jtag::RUN_TEST_IDLE); + _jtag->toggleClk(2); + } + + if (_verbose) { + printf("Readback PubKey: ["); + for (i=PUBKEY_LENGTH_BYTES-1; i >= 0; i--) { + printf("%02x", rxkey[i]); + if (i && (i%16 == 0)) printf(" "); + } + printf("]\n"); + } + + if (_verify) { + for (int i = 0; i < PUBKEY_LENGTH_BYTES; i++) { + if (pubkey[i] != rxkey[PUBKEY_LENGTH_BYTES - i - 1]) { + printf("\tVerify Failed...\n"); + return false; + } + } + } + + return true; +} + bool Lattice::program_fea_MachXO3D() { bool err; @@ -1787,3 +1893,173 @@ bool Lattice::program_intFlash_MachXO3D(JedParser& _jed) return true; } + +bool Lattice::program_pubkey_MachXO3D() +{ + bool err, same = true; + int len, i, j; + uint8_t pubkey[PUBKEY_LENGTH_BYTES]; + uint8_t rxkey[PUBKEY_LENGTH_BYTES]; + + RawParser _pk(_filename, false); + printInfo("Open file: ", false); + printSuccess("DONE"); + + err = _pk.parse(); + printInfo("Parse file: ", false); + if (err == EXIT_FAILURE) { + printError("FAIL"); + return false; + } else { + printSuccess("DONE"); + } + + uint8_t* data = _pk.getData(); + len = _pk.getLength()/8; + + if (data[0] == 0x0f && data[1] == 0xf0) { + for (i = 2; i < len; i++) { + if (data[i] == 0xf0 && data[i+1] == 0x0f) { + if (_verbose) printf("Header: [%.*s]\n", i-2, ((char *)data)+2); + i+=2; + break; + } + } + + memcpy(pubkey, data+i, PUBKEY_LENGTH_BYTES); + i += PUBKEY_LENGTH_BYTES; +/* + As read from file: + ... + 7dbc273a6e614a0f5289070524a1a59d + 3a5d518b5cff00bc521f1ef62c4227ce + dd7987ecb63768e3310864f4b44daf90 + ebf86ce8a9b17842821551a85b2235cc + ... + + As Sent by diamond programmer: + 0x59: cc35225ba85115824278b1a9e86cf8eb + 0x5B: 90af4db4f4640831e36837b6ec8779dd + 0x61: ce27422cf61e1f52bc00ff5c8b515d3a + 0x63: 9da5a124050789520f4a616e3a27bc7d +*/ + if (_verbose) { + printf("PubKey: ["); + for (j=0; j < PUBKEY_LENGTH_BYTES; j++) { + if (j && (j%16 == 0)) printf(" "); + printf("%02x", pubkey[j]); + } + printf("]\n"); + } + + if (_verbose) { + printf("Trailing bytes: ["); + for (; i < len; i++) { + printf("%02x ", data[i]); + } + printf("\b]\n"); + } + } + else { + printError("Failed to find header in public key file"); + return false; + } + + + /* bypass */ + wr_rd(ISC_NOOP, NULL, 0, NULL, 0); + /* ISC Enable 0xC6 with operand of 0x08 (Enable Offline mode) */ + printInfo("Enable configuration: ", false); + if (!EnableISC(0x08)) { + printError("FAIL"); + displayReadReg(readStatusReg()); + return false; + } else { + printSuccess("DONE"); + } + + /* read the current feature row */ + wr_rd(READ_ECDSA_PUBKEY0, NULL, 0, rxkey, 16); + _jtag->set_state(Jtag::RUN_TEST_IDLE); + _jtag->toggleClk(2); + + wr_rd(READ_ECDSA_PUBKEY1, NULL, 0, rxkey + 16, 16); + _jtag->set_state(Jtag::RUN_TEST_IDLE); + _jtag->toggleClk(2); + + wr_rd(READ_ECDSA_PUBKEY2, NULL, 0, rxkey + 32, 16); + _jtag->set_state(Jtag::RUN_TEST_IDLE); + _jtag->toggleClk(2); + + wr_rd(READ_ECDSA_PUBKEY3, NULL, 0, rxkey + 48, 16); + _jtag->set_state(Jtag::RUN_TEST_IDLE); + _jtag->toggleClk(2); + + if (_verbose) { + printf("Read PubKey: ["); + for (j=PUBKEY_LENGTH_BYTES-1; j >= 0; j--) { + printf("%02x", rxkey[j]); + if (j && (j%16 == 0)) printf(" "); + } + printf("]\n"); + } + + for (int i = 0; i < PUBKEY_LENGTH_BYTES; i++) { + if (pubkey[i] != rxkey[PUBKEY_LENGTH_BYTES - i - 1]) + same = false; + } + + printf("PubKey Compare: %s\n", same ? "Same" : "Different"); + if (same == false) { + uint8_t tx[2]; + /* LSC_INIT_ADDRESS */ + tx[0] = (uint8_t)((FLASH_SEC_PKEY >> 8) & 0xff); + tx[1] = (uint8_t)((FLASH_SEC_PKEY >> 16) & 0xff); + if (_verbose) + printf("Selected address (I): 0x%x 0x%x\n", tx[0], tx[1]); + wr_rd(RESET_CFG_ADDR, tx, 2, NULL, 0); + + /* ISC ERASE */ + printInfo("Flash erase: ", false); + if (flashErase(FLASH_SEC_PKEY) == false) { + printError("FAIL"); + return false; + } + else { + printSuccess("DONE"); + } + + /* Public Key */ + printInfo("Program Public Key: ", true); + if (!programPubKey_MachXO3D(pubkey)) { + printError("FAIL"); + return false; + } + else { + printSuccess("DONE"); + } + } + + /* ISC program done 0x5E */ + printInfo("Write program Done: ", false); + if (writeProgramDone() == false) { + printError("FAIL"); + return false; + } else { + printSuccess("DONE"); + } + + /* bypass */ + wr_rd(ISC_NOOP, NULL, 0, NULL, 0); + + /* disable configuration mode */ + printInfo("Disable configuration: ", false); + if (!DisableISC()) { + printError("FAIL"); + return false; + } else { + printSuccess("DONE"); + } + + return true; +} diff --git a/src/lattice.hpp b/src/lattice.hpp index 984030d..afb9990 100644 --- a/src/lattice.hpp +++ b/src/lattice.hpp @@ -96,9 +96,12 @@ class Lattice: public Device, SPIInterface { }; lattice_flash_sector_t _flash_sector; - bool program_intFlash_MachXO3D(JedParser& _jed); - bool program_fea_MachXO3D(); bool programFeatureRow_MachXO3D(uint8_t* feature_row); bool programFeabits_MachXO3D(uint32_t feabits); + bool programPubKey_MachXO3D(uint8_t* pubkey); + + bool program_intFlash_MachXO3D(JedParser& _jed); + bool program_fea_MachXO3D(); + bool program_pubkey_MachXO3D(); }; #endif // LATTICE_HPP_