nRF51/52 ROM Protection : Prevent Someone Else From Dumping the Hex File


   To avoid piracy is very important for software and firmware development. Of course, you should protect your source code would not be spread out. But from firmware prospect, it is a way to piracy your intelligence: he might clone your WHOLE device, including the mechanism, circuit and firmware. It is not necessary to get your source code.
  In nRF51822 and 52832, There is a mechanism to prevent that happens. I will demonstrate that:
 My SDK versions are 10 for nRF51, and 11 for nRF52.

  To Simplify the demonstration. I copy the peripheral\uicr_config\uicr_config.h to my project folder, and the main.c include the file.
    Open the uicr_config.h, you could read that there is many address listed, you could modify the values on those addresses. The values I changing be :

// const uint32_t UICR_CLENR0    __attribute__((at(0x10001000))) __attribute__((used)) = 0xFFFFFFFF;
// const uint32_t UICR_RBPCONF   __attribute__((at(0x10001004))) __attribute__((used)) = 0xFFFFFFFF;
// const uint32_t UICR_XTALFREQ  __attribute__((at(0x10001008))) __attribute__((used)) = 0xFFFFFFFF;

const uint32_t UICR_ADDR_0x80 __attribute__((at(0x10001080))) __attribute__((used)) = 0x12345678;
// const uint32_t UICR_ADDR_0x84 __attribute__((at(0x10001084))) __attribute__((used)) = 0xFFFFFFFF;
// const uint32_t UICR_ADDR_0x88 __attribute__((at(0x10001088))) __attribute__((used)) = 0xFFFFFFFF;
// const uint32_t UICR_ADDR_0x8C __attribute__((at(0x1000108C))) __attribute__((used)) = 0xFFFFFFFF;
 const uint32_t UICR_ADDR_0x90 __attribute__((at(0x10001090))) __attribute__((used)) = 0x11223344;
 const uint32_t UICR_ADDR_0x94 __attribute__((at(0x10001094))) __attribute__((used)) = 0x55667788;
// const uint32_t UICR_ADDR_0x98 __attribute__((at(0x10001098))) __attribute__((used)) = 0xFFFFFFFF;
// const uint32_t UICR_ADDR_0x9C __attribute__((at(0x1000109C))) __attribute__((used)) = 0xFFFFFFFF;
// const uint32_t UICR_ADDR_0xA0 __attribute__((at(0x100010A0))) __attribute__((used)) = 0xFFFFFFFF;
// const uint32_t UICR_ADDR_0xA4 __attribute__((at(0x100010A4))) __attribute__((used)) = 0xFFFFFFFF;
// const uint32_t UICR_ADDR_0xA8 __attribute__((at(0x100010A8))) __attribute__((used)) = 0xFFFFFFFF;
// const uint32_t UICR_ADDR_0xAC __attribute__((at(0x100010AC))) __attribute__((used)) = 0xFFFFFFFF;
// const uint32_t UICR_ADDR_0xB0 __attribute__((at(0x100010B0))) __attribute__((used)) = 0xFFFFFFFF;
 const uint32_t UICR_ADDR_0xB4 __attribute__((at(0x100010B4))) __attribute__((used)) = 0xAABBCCDD;
// const uint32_t UICR_ADDR_0xB8 __attribute__((at(0x100010B8))) __attribute__((used)) = 0xFFFFFFFF;
// const uint32_t UICR_ADDR_0xBC __attribute__((at(0x100010BC))) __attribute__((used)) = 0xFFFFFFFF;
// const uint32_t UICR_ADDR_0xC0 __attribute__((at(0x100010C0))) __attribute__((used)) = 0xFFFFFFFF;
// const uint32_t UICR_ADDR_0xC4 __attribute__((at(0x100010C4))) __attribute__((used)) = 0xFFFFFFFF;
// const uint32_t UICR_ADDR_0xC8 __attribute__((at(0x100010C8))) __attribute__((used)) = 0xFFFFFFFF;
// const uint32_t UICR_ADDR_0xCC __attribute__((at(0x100010CC))) __attribute__((used)) = 0xFFFFFFFF;
// const uint32_t UICR_ADDR_0xD0 __attribute__((at(0x100010D0))) __attribute__((used)) = 0xFFFFFFFF;
// const uint32_t UICR_ADDR_0xD4 __attribute__((at(0x100010D4))) __attribute__((used)) = 0xFFFFFFFF;

  By the way,  What is UICR ? UICR is the short for User Information Configuration Registers, where the values are non-alterable. The purpose for UICR is to make a space for manufacturer signing.


Build and download the hex to your device, and type the command line (I use nRF52832 as my target device):


> nrfjprog --family NRF52 --memrd 0x10001080 --n 128
0x10001080: 12345678 FFFFFFFF FFFFFFFF FFFFFFFF   |xV4.............|
0x10001090: 11223344 55667788 FFFFFFFF FFFFFFFF   |D3"..wfU........|
0x100010A0: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF   |................|
0x100010B0: FFFFFFFF AABBCCDD FFFFFFFF FFFFFFFF   |................|
0x100010C0: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF   |................|
0x100010D0: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF   |................|
0x100010E0: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF   |................|
0x100010F0: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF   |................|

 The address values have been changed.

You could use the command the dump the whole hex :


> nrfjprog --family NRF52 --readcode output.hex

That is what I prevent from.


To avoid the dumping, Add below code in the beginning of main function :


#include "ble_flash.h"

/**@brief Function for application main entry.
 */
int main(void)
{
#if(1)
 if(UICR_RBPCONF_PALL_Enabled !=
  (uint32_t)((NRF_UICR->RBPCONF & UICR_RBPCONF_PALL_Msk) >> UICR_RBPCONF_PALL_Pos)) 
 {
  ble_flash_word_write((uint32_t *)&NRF_UICR->RBPCONF, 
   (NRF_UICR->RBPCONF & ~UICR_RBPCONF_PALL_Msk));
 }/*if */
#endif 
    uint32_t err_code;
    bool erase_bonds;

and you should include folder SDK_ROOT\components\drivers_nrf\ble_flash and the file SDK_ROOT\components\drivers_nrf\ble_flash\ble_flash.c in your working porject.

Take Keil C as the project modification example:




After download to the device, you could find the readback command would not work:


> nrfjprog --family NRF52 --memrd 0x10001080 --n 128
ERROR: The operation attempted is unavailable due to readback protection in
ERROR: your device. Please use --recover to unlock the device.

  That is, the SWD (Serial Wired Debug) function has been forbidden, the SWD could accept recover request from now.

NOTE :If you use Keil C, the IDE would not reset the device after the downloading. but you could press the download button twice to make sure the SWD has been disabled:

* JLink Info: Found SWD-DP with ID 0x2BA01477
* JLink Info: Found Cortex-M4 r0p1, Little endian.
* JLink Info: FPUnit: 6 code (BP) slots and 2 literal slots
* JLink Info: CoreSight components:
* JLink Info: ROMTbl 0 @ E00FF000
* JLink Info: ROMTbl 0 [0]: FFF0F000, CID: B105E00D, PID: 000BB00C SCS
* JLink Info: ROMTbl 0 [1]: FFF02000, CID: B105E00D, PID: 003BB002 DWT
* JLink Info: ROMTbl 0 [2]: FFF03000, CID: B105E00D, PID: 002BB003 FPB
* JLink Info: ROMTbl 0 [3]: FFF01000, CID: B105E00D, PID: 003BB001 ITM
* JLink Info: ROMTbl 0 [4]: FFF41000, CID: B105900D, PID: 000BB9A1 TPIU
* JLink Info: ROMTbl 0 [5]: FFF42000, CID: B105900D, PID: 000BB925 ETM
ROMTableAddr = 0xE00FF000
* JLink Info: SYSRESETREQ has confused core. Trying to reconnect and use VECTRESET.
* JLink Info: Found SWD-DP with ID 0x2BA01477
**JLink Warning: Failed to reset CPU. VECTRESET has confused core.
* JLink Info: Core is locked-up, trying to disable WDT.
**JLink Warning: Could not set S_RESET_ST
* JLink Info: Found SWD-DP with ID 0x2BA01477
* JLink Info: SYSRESETREQ has confused core. Trying to reconnect and use VECTRESET.
* JLink Info: Found SWD-DP with ID 0x2BA01477
**JLink Warning: Failed to reset CPU. VECTRESET has confused core.
* JLink Info: Core is locked-up, trying to disable WDT.
**JLink Warning: Could not set S_RESET_ST


Now you could see, the dumping has not been permitted, the only way to manipulate the storage (ROM) is to recover whole space: it is, erase all.

猜你喜欢

转载自blog.csdn.net/u013606170/article/details/70261546
hex
ROM