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

来源:互联网 发布:网络推广赚钱吗 编辑:程序博客网 时间:2024/05/29 14:27

   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 1280x10001080: 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 fileSDK_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 128ERROR: The operation attempted is unavailable due to readback protection inERROR: 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 ETMROMTableAddr = 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.
0 0