|
|
View previous topic :: View next topic |
Author |
Message |
SergioMForster
Joined: 23 Jan 2019 Posts: 29 Location: Argentina
|
PIC24EP problems protecting bootloader on aux flash memory |
Posted: Mon Aug 12, 2019 7:33 pm |
|
|
I have developed a CAN bootloader that works very well, loading the user application that also works well.
The bootloader is in the auxiliary flash memory, while the user program is in the general flash memory.
I want to protect my code so that it cannot be read with external tools.
First I tried to read protect the bootloader.
These are the configuration fuses that works well:
Code: | #include <24EP512GP806.h>
#device ADC=8
#device ICSP=1
//#device ICD=true
#device PASS_STRINGS=IN_RAM
#use delay(clock=120000000,crystal=20000000)
#FUSES NOWDT //Watch Dog Timer
#FUSES WPRES32 //Watch Dog Timer PreScalar 1:32
#FUSES WPOSTS12 //Watch Dog Timer PostScalar 1:2048
#FUSES CKSFSM //Clock Switching is enabled, fail Safe clock monitor is enabled
#FUSES ALTI2C1 //I2C1 mapped to ASDA1/ASCL1 pins
#fuses RESET_AUX //arranca en la memoria auxiliar para bootloader
#build (AUX_MEMORY) //Build code for Auxiliary Memory
|
To protect the bootloader I added these fuses:
Code: |
#FUSES APROTECT //read protect Aux segment
#FUSES APLK
|
With these new fuses the bootloader does not start anymore.
Obviously, if I remove these two fuses, everything returns to normal.
What am I doing wrong? (I am using the 5.085 PCD compiler).
Second question:
Obviously I also want to protect the user program after being loaded by the bootloader.
For this, I need in runtime to disable the PROTECT and GSSK fuses and re-enable them after updating the user program.
Could someone give me an example of how to do it with write_configuration_memory() since it is not clear to me as explained in the CCS manual.
Thank you in advance. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19512
|
|
Posted: Tue Aug 13, 2019 12:45 am |
|
|
All PIC code, has to be able to read itself. If you disable code from
reading the actual code memory, this stops things like the loads done
at boot, which loads variables, from working. So just enable code
protection. This prevents external reads, but leaves the code able to read
itself.
Code protection can be left 'on'. You don't need to change things. Howver
your bootloader will need itself to have protection (encryption and a key)
otherwise this can be used to write a code block that then allows reading
of the memory.
Key to understand is that fuses that protect, generally cannot ever be
turned 'off' in a PIC without bulk erasing. This is done since otherwise
people could turn these off to access the chip. On chips with flexible
configuration, fuses like clock settings and ones affecting general
operation can be changed, but protection ones cannot. |
|
|
SergioMForster
Joined: 23 Jan 2019 Posts: 29 Location: Argentina
|
|
Posted: Tue Aug 13, 2019 8:57 am |
|
|
Ttelmah, Thank you very much for your help and your prompt response.
I understand what you are telling me, but I do not understand how I should do this code protection.
The only way I found in the documentation to protect the code, is using the PROTECT / GSSK fuses, for the general segment (the problem is that, with these fuses the bootloader resident in the aux memory cannot read the flash in the general segment, )
and APP / APK fuses for code protect the bootloader (with these fuses the bootloader does not start).
I am using the RESET_AUX fuse so that after the reset, the first thing to boot is the bootloader. At the beginning, the bootloader reads some flags in an external eeprom and a few bytes in the General segment flash to decide if it stays in bootloader mode or passes the control to the user program.
I have read in section 23.7.1 of Section 23. CodeGuard ™ Security document that it is necessary to disable the code protection in runtime to write/read the general segment and then in runtime to re-enable protection.
Once the boot loader verifies valid communication with the external programming tool, it can then
erase the code within the General Segment and clear the General Segment code protection.
As the boot loader finishes, it can program the Configuration bits to re-protect the general space,
make any necessary updates to the vectors and then return to the general application.
In summary
What I need is that the bootloader resident in aux memory can read and write without restrictions in the general segment flash.
And then from inside the chip the user program can read without restrictions within its own segment to read tables with read_rom_memory().
All I need is that neither the aux flash nor the general segment flash can be read from the outside using external tools.
Could you help me with some example of how to achieve it?
Thank you in advance. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19512
|
|
Posted: Tue Aug 13, 2019 1:07 pm |
|
|
Now I'm working on a different chip, so setting names may differ.
However what I had to do was set GSS, and APL. Then ensure GSSK and
APLK bits _matched_ these settings. This left the chio unreadable
by an external programmer, but still programmable and readable by
the bootloader. It was vital that the key bits had the same settiings.
Otherwise full protection turns on. |
|
|
SergioMForster
Joined: 23 Jan 2019 Posts: 29 Location: Argentina
|
|
Posted: Tue Aug 13, 2019 5:29 pm |
|
|
CCS support gave me a clue why the bootloader does not start when the auxiliary memory is protected, telling me that this problem is mentioned in the chip's errata sheet.
31. Module: Auxiliary Flash
When a device is set to obtain the RESET
instruction from Auxiliary Flash location,
0x7FFFFC (RSTPRI = 0), and Auxiliary Flash
code protection is enabled using the FAS register,
the device does not execute the application code
after a Reset. This configuration causes a security
trap resulting in a Reset.
This clears up one of the problems.
However, I cannot get the bootloader to update the general segment with the user's program with the protection of the FGS register (GSSK and GSS).
I can confirm that with the PROTECT and GSSK (0x31 on the FGS register) fuses the bootloader running from the Aux memory cannot read in the general segment flash (everything returns FF FF FF FF).
To write in the general segment flash, I am using the CCS library ><rom_write.c> that comes with the bootloader examples whose rom_modify (address, pointer, num) function needs to read from the flash with read_program_memory().
Code: |
if (page_start != _romw_curr_page)
{
rom_flush();
_romw_curr_page = page_start;
if (page_start > _ROMW_WRITABLE_SIZE)
{
debug_rom_write(debug_putc, "rom_modify(0x%LX,0x%LX,%lu) OVERRUN_SO_EXIT\r\n", location, src, size);
return;
}
read_program_memory(page_start, _romw_buffer, sizeof(_romw_buffer)); //read entire block to ram buffer
}
//read entire block to ram buffer
|
I tried to modify the protection in runtime using Write_configuration_memory (), but it only allows me to protect the FGS (0x0031) if it was not protected before, but it does not allow me to remove the protection (0x0003) in runtime once it was protected (either protected by fuses in the compiler, or protected in runtime) is a one-way road.
Conclusion: I could not protect my code from reading using external tools.
Do you have any suggestions? |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9226 Location: Greensville,Ontario
|
|
Posted: Tue Aug 13, 2019 5:42 pm |
|
|
OK, I have to ask 'why' do you need to 'protect your code' ? There are several 'low level' ways to deter 'reverse engineers', one of the simplest is to file/sand off the chips identity. One blob of epoxy looks the same as all the others ! This worked 4 decades ago...
Just curious..
Jay |
|
|
SergioMForster
Joined: 23 Jan 2019 Posts: 29 Location: Argentina
|
|
Posted: Fri Aug 16, 2019 8:51 am |
|
|
Finally I came to the conclusion that it is not possible, due to errata on the chip, to protect the code using bootloader in the aux flash memory
This was a comment from CCS Support with the same opinion
Unfortunately I don't see a way to use the Auxiliary Memory as the bootloader and protecting it or the General Segment from reads. Because of the errata when APROTECT is used it won't execute code from the Auxiliary memory. If you use Microchip's work around taking advantage of the other errata chip has by enabling read protection on the General Memory it also protects the General Memory from reads and writes from the Auxiliary Memory. As you found out once read protection is enabled in can't be disabled except for a bulk erase done with and programmer.
The only solutions I see is to not use the auxiliary memory as the bootloader and instead use a bootloader that is also located in the General Segment, see ex_pcd_bootloader.c for an example of this.
|
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|