espressif / arduino-esp32

Arduino core for the ESP32
GNU Lesser General Public License v2.1
13.6k stars 7.4k forks source link

Flash Encryption (FLASH_CRYPT_CNT) #1387

Open Buffalchill opened 6 years ago

Buffalchill commented 6 years ago

Hardware:

Board: ESP32 Dev Module Core Installation/update date: 11/jul/2017 IDE name: Arduino IDE 1.8.3. Flash Frequency: 40Mhz Upload Speed: 115200

Hi, I'm trying to enable Flash Encryption. The ESP IDF documentation says (http://esp-idf.readthedocs.io/en/latest/security/flash-encryption.html)

"Flash Encryption Initialisation The bootloader must be compiled with flash encryption support enabled. In make menuconfig, navigate to “Security Features” and select “Yes” for “Enable flash encryption on boot”.

how is this possible in Arduino IDE ?

lbernstone commented 6 years ago

See my instructions in https://github.com/espressif/arduino-esp32/issues/1142

Buffalchill commented 6 years ago

Is it possible to set the fuses for the flash encryption in arduino or maybe with the espefuse.py script, and then compile and upload my sketch with arduino ?

Buffalchill commented 6 years ago

OK i have now changed the sdkconfig in the "make menuconfig". I changed the Security features and did Enable flash encryption on boot.

this new sdkconfig i copied into: C:\Users\Documents\Arduino\hardware\espressiv\esp32\tools\sdk also I copied build/esp32/libesp32.a into arduino-esp32/tools/sdk/lib/ . Then i started ardino, built and uploaded it. Then i checked if the FLASH_CRYPT_CNT got increased after upload. but it wasn't, it was still 0. So does this now mean enable_flash_encryption didn't work in Arduino IDE even with the changed SDKconfig...

Buffalchill commented 6 years ago

i just tried to enable flash encryption it in the ESP-IDF with the blink example, and this worked so far. now i would like to have this in arduino-esp32 :-/ I checked it with the espefuse.py issue1

Buffalchill commented 6 years ago

Next Try: Now I used Arduino-esp32 as an ESP-IDF component. I used "make menuconfig" to change the secutity options -> "enable flash encryption on boot" Then it compiled with ESP-IDF with msys32. But flash encryption didn't happen, the FLASH_CRYPT_CNT was still 0.

Can you help me please to get the "flash encryption on boot" running ?

lbernstone commented 6 years ago

You enable encryption by running espefuse.py burn_efuse FLASH_CRYPT_CNT. Did you read the documentation thoroughly?

Buffalchill commented 6 years ago

yes i read the documentation veeeery often :) If I just do espefuse.py burn_efuse FLASH_CRYPT_CNT the flash and the firmware does not get encrypted. But the bootloader trys to decrypt a unencrypted firmware. That simply ends up with Error message 1000. It currently seems for me that Flash encryption on boot seems not to work with the arduino-esp32 not even as an ESP-IDF-component. I would be glad to hear if it is somehow it would be possible to copy some files into the Arduino-esp32 to make it work.

lbernstone commented 6 years ago

Getting error 1000 seems like some progress. Follow the serial reflashing procedure from that point and see if it will encrypt on its own.

Buffalchill commented 6 years ago

Ok I tried it like you said but, it seems just like i broke another esp32 board ⚡️

1 "make menuconfig" -> "sercurity options" -> "enable flash encryption on boot"

2 "make flash" (at this point, a normal ESP-IDF example got encrypted, but not the "arduino-esp32" as an esp-idf component )

3 burned the efuse manually by using script espefuse.py

1

4 I got the error 1000...

2

5 Burn the FLASH_CRYPT_CNT efuse again with the python script

3

6 this time i put some code inside my arduino sketch which will figure out if hardware encyption is enabled or not...

4 5

the answer is, it is not enabled. It is disabled.

7 Now, I reset the device, and the documentation says, it will re-encrypt plaintext partitions.

Then I burn the FLASH_CRYPT_CNT efuse again to re-enable encryption.

6

8 The flash is not encrypted, but the esp32 board trys to decrypt it, ending up with "Err 100" again.

and another Board is broken 🗡

7

Buffalchill commented 6 years ago

The point is, i think if arduino-esp32 is used as an ESP-IDF component, flash encryption seems not to work.

In normal ESP-IDF example, i was able to enable flash encryption. 🌵

Buffalchill commented 6 years ago

Next try:

I took a new ESP32 board and tried the Pre-generated-Key Encryption.

1 flashed my sketch in plain text.

1

2 generated the key and burned it to the esp32

2

3 Followed the instructions....

4

4 Strange things happend: Read_disable and write_disable became set, but the flash "encryption on boot" did not work again, even with the pregenerated key. Flash encryption is still disabled.

Arduino-esp32 as an ESP-IDF Component

3

Next, I will try the "reflash pregenrated key procedure"...

lbernstone commented 6 years ago

Um, Ok. Then don't do that. Just flash the esp-idf OTA example with the encryption turned on. Then you can put whatever you want on there. There may very well be something in the arduino-esp32 code that overrides the sdkconfig setting, and that is probably a reasonable security feature to keep people that don't understand the consequences from bricking their devices.

Buffalchill commented 6 years ago

Success ! Today I found a way to use flash encryption with Arduino-esp32 👍 👍 👍

1 Generated the flash Encryption Key and burned it to the ESP32 board

1

2 check if the RD_Dis and WR_Dis have changed after BURN the key (before burn they are 0, after burn they must look like on this picture :

2

3# Use a NORMAL "ESP-IDF" example like Hello World... make menuconfig -> security options -> enable encryption on boot save that and make the project and flash it to the esp32 board.

3

4 after openning serial monitor I had "Err 1000", so I flashed it again. Then the error was gone and my the Hello_world example was running on the board

5 Then check the FLASH_CRYPT_CNT counter it must be 1 now because the "flash encryption on boot" must have increased it after encrytion of the flash.

4

in my example i added some code to make the firmware check if the encryption is working: 5

serial monitor shows, encryption is working: 6

So far so good, esp-idf flash encryption worked out with our own flash encryption key, which we stored on our PC.

Now lets make the Arduino-ESP32 project as a ESP-IDF component.

6 this time in this project I DISABLED "encryption on boot"

make menuconfig -> security options -> enable encryption on boot <<- DISABLE that!

7 make the project. Now the will be a .bin file in the project folder like this : /build/my-app.bin

8 encrypt this .bin file of the project with our own generated encryption-key by using the espsecure.py script :

7

9 Flash the encrypted .bin File to the ESP-32 Board by using the esptool.py script.

8

10 Check out the FLASH_CRYPT_CNT with espefuse.py --port "COM3" summary

it should still have the value: 1

11 The Arduino-esp32 as an ESP-IDF component Firmware should now run... encrypted !!!

9

🥇 🍦 ⚡️

Buffalchill commented 6 years ago

If i use Arduino-IDE to compile and upload my arduino-esp32 sketch, in which directory can i find the .bin file after compiling, which is used to get uploaded to the esp32 board?

I am asking, because I wanna try to encrypt that file directly without using the arduino as an idf component.

lbernstone commented 6 years ago

If you turn on verbose output during compilation in the preferences, you will see the location in a few places. I really think flashing a basic OTA + CONFIG_FLASH_ENCRYPTION_ENABLED firmware and then having the devices connect to a rpi/esp set up as an AP/webserver will be easier and mass repeatable. You could also get a list of mac addresses that way.

Buffalchill commented 6 years ago

Today I took the .bin file which was compiled by Arduino-IDE and my encryption key which I created yesterday and which is already burned into my ESP32-Board.

Flashed the .bin file into the esp-board with esptool.py The Arduino-IDE sketch, which was compiled by the Arduino-IDE runs with flash encryption.

Is it possible to use SPIFFS when the flash encryption is enabled ? My sketch uses spiffs and had error messages : SPIFFS partition not found" after i removed the Spiffs out of my sketch it worked...

spiffserror

me-no-dev commented 6 years ago

@Buffalchill that is probably the only way that flash encryption will be available for Arduino users. Since it's not for everyone and could cause any novice an issue, it would require you to run Arduino as IDF component.

SPIFFS does not run on encrypted flash ;) FATFS does

lbernstone commented 6 years ago

I don't know whether the partition table has been encrypted or not, but maybe you initially uploaded a partition table without spiffs? Maybe it just needs a format (though that should give you a different error)? Here's some quick code to show the spiffs location:

#include <esp_partition.h>
void setup() {
  Serial.begin(115200);
    const esp_partition_t *data_partition = NULL;
    data_partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA,
            ESP_PARTITION_SUBTYPE_DATA_SPIFFS, "spiffs");
    if (data_partition != NULL) {
        Serial.printf("partiton addr: 0x%08x; size: %d; label: %s\n", data_partition->address, data_partition->size, data_partition->label);
    }
}
void loop() {}
Buffalchill commented 6 years ago

Ibernstone i tried your code. Thank you for that! There seems to be no partition table on my ESP32 board

lbernstone commented 6 years ago

Well, there certainly is a partition table, just no spiffs partition. Try running esptool.py read_flash 0x8000 0xc00 /tmp/parts (/tmp/parts is the output file). If that file has readable text in it (nvs, app0, eeprom, etc) then you can directly use esptool to put a new partition table on there. Otherwise, you may have to encrypt the partition table before flashing(?).

Buffalchill commented 6 years ago

Ya i got something but its not plain text :) flash

TØkGEÅӍÞúmp6mlXs¥M¼kÒ$‘òu_"‚QáÕm[Mf=Ã^Ï(ÒªsNú¤Þx¿Õô‘+¹©3=O­ZŸ+–6ãþ"Z3(ã…yúd¹Ï€’ tö®6.‰ˆ00f+G IqÉü:ÞE ¦NЧà¶\©’æ¬moùa¦NЧà¶\©’æ¬moùa½©û}Å0¸gC[ñ½·Îù½©û}Å0¸gC[ñ½·ÎùfjΞìi”à÷°³²¶Ùð´fjΞìi”à÷°³²¶Ùð´^%j÷Ë]‡‡ÂÈßœõ’^%j÷Ë]‡‡ÂÈßœõ’a]§ÚÜ@I‚¬ýò¦4a]§ÚÜ@I‚¬ýò¦4Îíð‘ÚéI b=ÎÄϐkÎíð‘ÚéI b=ÎÄϐk“_cKRÙ%‰ÃNm ø“cKRÙ%‰ÃNm øÖn“L¥´Þl±W EDÑÖn“L¥´Þl±W EDÑÃnvYqæÁ‹}™Y1%2£ÃnvYqæÁ‹}™Y1%2£ýÕoß)‹…ÛQkndEýÕoß)‹…ÛQkndEÿ‡IQ¨@ô¹O Œìel6“ÿ‡IQ¨@ô¹O Œìel6“ìø»‰3HèÇ8Sâìø»_‰3HèÇ8Sâ”]qbÅQ¤«³ªtbÊÈv”]qbÅQ¤«³ªtbÊÈvÂËßä7õÞÚo$\ž,ÝDËßä7õÞÚo$\ž,ÝDâ{q°‚ö–^˜–Q ¦xâ{q°‚ö–^˜–Q ¦x—Å—¸®Ê Ÿp|w8„Bà—Å—¸®Ê Ÿp|w8„BàëœäîÌàgV32èiëœäîÌàgV32èiÂ’Îiƒ^ÂœvŠ›;:8ÉÂ’Îiƒ^ÂœvŠ›;:8ÉìM4øÔòt,UìM4øÔòt,U<i_½<:btË@D/<i½<:btË@D/(°U‡\d+ÿWâqXú ’{(°U‡\d+ÿWâqXú ’{Òο‚d„w 38{,:—Òο‚d„w 38{,:—<þܨ¬O™4ß8×È<þܨ¬O™4ß8×ÈW@uîÏÛÍ:ªI»‹QÉ^üW@uîÏÛÍ:ªI»‹QÉ^üEní{D!ÈÕ©f!»¢C…ÉEní{D!ÈÕ©f!»¢C…É%Y¼hhnhX¦Ã¸•aˆ%Y¼hhnhX¦Ã¸•aˆ]öÏ«µ „l¯Ñ u4<]öÏ«µ „l¯Ñ u4<=yL¦¸}ÅYlJõ{ZÀ5=yL¦¸}ÅYlJõ{ZÀ5BÍgP>ÐÉ¡Q®ÜÅÜ1BÍgP>ÐÉ¡Q®ÜÅÜ1v½KaÝ4óWBÐp-µ¡Fv½KaÝ4óWBÐp-µ¡F©Ô·aÖVDF"=Q©Ô·aÖVDF"=Q#™æÕNq+‹JŠNÆšù#™æÕNq+‹JŠNÆšù4®•c¤×5¬ÿÁ“4®•c¤×5¬ÿÁ“£àyI‡®Æc긏ƒ4£àyI‡®Æc긏ƒ4H ,.·÷Ђ• N!;” H ,.·÷Ђ• N!;” õ}&n+ô»Tá·Òp¥õ}&n+ô»Tá·Òp¥ €'œBTY@‘zj‚ €'œBTY@‘zj‚ dr¤=lSµÜ·úbV$ëdr¤=lSµÜ·úbV$ëz'(Ãk^Õú)Þ¹[z'(Ãk^Õú)Þ¹[vQ¥–R³|Þð 30…vQ¥–R³|Þð 30…z?!¸–‰öñ;ÔG Ò¡z?!¸–‰öñ;ÔG Ò¡qìJ²ùxVËApÌqìJ²ùxVËApÌ_”Ä4§@½µ<¦AK –”Ä4§@½µ<¦AK –ìwÓóB3˜~mÙÙ$ÔìwÓóB3˜~mÙÙ$Ôþ+ûHL­Þm/1 Wq‡þ+ûHL­Þm/1 Wq‡Ù³55ðb= zZ M•ÙtÙ³55ðb= zZ M•Ùt©ó –±—½ïÙY‡ùq©ó –±—½ïÙY‡ùq°‘7D 5hˆo€uEF½°‘7D 5hˆo€uEF½Û²½›|; ϸ"Å[09Û²½›|; ϸ"Å[09ì bä2>²³<H“Ÿ4&ì bä2>²³<H“Ÿ4&v½íììvw‡ûóAÎIAv½íììvw‡ûóAÎIA˜3) ƒCN[‰G;„û˜3) ƒCN[‰G;„ûS­Ö¼ÿ«*—ÊNÿœzmS­Ö¼ÿ«—ÊNÿœzmbpè)¼‹þÁp!À7nÈãØbpè)¼‹þÁp!À7nÈãØÝÈ?×w°œªošÖ(x~ËÝÈ?×w°œªošÖ(x~Ë -S(JSªyíßÏ,ó -S(JSªyíßÏ,ó̯šˆÈÞ Ö€áò$R2æ̯šˆÈÞ Ö€áò$R2æç¼4¾ÐOhoA6g‡Öç¼4¾ÐOhoA6g‡Öêq8ZÆ,#§4LDÏ™ˆêq8ZÆ,#§4LDÏ™ˆÁÕZÍöz I hhaÁÕZÍöz I hha½] êȁPxZQàG½] êȁPxZQàG¿Vž’+‹A' t¡Áɨ«¿Vž’+‹A' t¡Áɨ«sR²¶8ßþ o:òJˆFsR²¶8ßþ o:òJˆFŸŸÓшˆJ¢ˆÿÃfqŽÊ™ŸŸÓшˆJ¢ˆÿÃfqŽÊ™{ÅŽ—¿„,ŠÉBïP¤” {ÅŽ—¿„,ŠÉBïP¤” ä+GéÚp:Ûw31þ‹·\ä+GéÚp:Ûw31þ‹·\ÁîBs«_hŽÇ<¶Ý'ÁîBs«_hŽÇ<¶Ý'î!ÏxnwÑyáùZè”-ìî!ÏxnwÑyáùZè”-쟤;û„ý¤kׂq©qŸ¤;û„ý¤kׂq©q.ã&æn'[—ÂÆØq»Ùê.ã&æn'[—ÂÆØq»Ùê”ï>ú%awèº7T–ÿ”ï>ú%awèº7T–ÿy”vÂä𰪼¤~_HQëy”vÂä𰪼¤~_HQëiž‡Èw:ø¦òé%ñ4iž‡*Èw:ø¦òé%ñ4&:ˁA8¡ÕU¶?Þ|O&:ˁA8¡ÕU¶?Þ|OÝ" …=¦u˜¿g ®—òÝ" …=¦u˜¿g ®—ò¹Ôˆ-ajùó~Ó7®-¹Ôˆ-ajùó~Ó7®-Qý7œ1ýiùB²3BVdQý7œ1ýiùB²3BVdˆmó„ÀìŒÿ'!MìȈmó„ÀìŒÿ'!MìÈ"^¦¸ÈÜM<îKBT‚ñÇB"^¦¸ÈÜM<îKBT‚ñÇBÍg°ºþYOˆÿpLÓAÿBÍg°ºþYOˆÿpLÓAÿBª¶bÉn¯S–yú啾ת¶bÉn¯S–yú啾צ¯“÷"‘°¼vÐõ‰@g¦¯“÷"‘°¼vÐõ‰@g%1ü¦èJm‘×$ ýâ8%1ü¦èJm‘×$ ýâ8í5™\$Œ…Z.;E"z !í5™\$Œ…Z.;E"z !~ãbºgΏÿæÒOø£+~ãbºgΏÿæÒOø£+»Ü­¹K´.~"é2i^»Ü­¹K´.~"é2i^êxÂÌj]€|ãL˜îZêxÂÌj]€|ãL˜îZIµ©z_ZËô@X5ˆ’Iµ©z_ZËô@X5ˆ’úÆ:wèVl¥´N~»húÆ:wèVl¥´N~»hœkWýÀã$ªl>G 'NÆ¡œkWýÀã$ªl>G 'NÆ¡½Gðšÿ"bòmé€˜’^~½Gðšÿ"bòmé€˜’^~ÿå¿×J÷¢F¿24uûÿå¿×J÷¢F¿24uû`

If i wanna flash the partition table only as a bin file, I guess the the adress is 0x8000 ? and Where in the project folder do i find the partition table file ?

lbernstone commented 6 years ago

There are a few available at https://github.com/espressif/arduino-esp32/tree/master/tools/partitions and the doco is at http://esp-idf.readthedocs.io/en/latest/api-guides/partition-tables.html. NB at the very bottom it mentions that make partition_table will give you the command to flash the table.

Buffalchill commented 6 years ago

So far thank you for your help 👍 I didn't have much time the last week to work on this, but maybe i'll get back on track today

lbernstone commented 6 years ago

Bringing in another comment from gitter for reference.

Buffalchill @Buffalchill Is it possible to use the fatfs with the arduino-esp32 ?

lbernstone @lbernstone @Buffalchill : Certainly it is possible, but there is not a library written for it. The esp-idf functions are there, though. https://esp-idf.readthedocs.io/en/latest/api-reference/storage/wear-levelling.html#_CPPv226esp_vfs_fat_spiflash_mountPKcPKcPK26esp_vfs_fat_mount_config_tP11wl_handle_t and example at https://github.com/espressif/esp-idf/tree/master/examples/storage/wear_levelling

Buffalchill commented 6 years ago

Today i tried to use the NVS ( Preferences ) ... it works with flash encryption and an pregenerated flash encryption key...

rst:0x10 (RTCWDT_RTC_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0018,len:4
load:0x3fff001c,len:7428
load:0x40078000,len:0
load:0x40078000,len:16816
entry 0x4007916c
I (29) boot: ESP-IDF v3.1-dev-661-gf586f5e6 2nd stage bootloader
I (29) boot: compile time 12:32:30
I (29) boot: Enabling RNG early entropy source...
I (35) boot: SPI Speed      : 40MHz
I (39) boot: SPI Mode       : DIO
I (43) boot: SPI Flash Size : 4MB
I (47) boot: Partition Table:
I (50) boot: ## Label            Usage          Type ST Offset   Length
I (58) boot:  0 nvs              WiFi data        01 02 00009000 00006000
I (65) boot:  1 phy_init         RF data          01 01 0000f000 00001000
I (73) boot:  2 factory          factory app      00 00 00010000 00100000
I (80) boot:  3 storage          Unknown data     01 82 00110000 000f0000
I (88) boot: End of partition table
I (92) esp_image: segment 0: paddr=0x00010020 vaddr=0x3f400020 size=0x068e4 ( 26852) map
I (110) esp_image: segment 1: paddr=0x0001690c vaddr=0x3ffb0000 size=0x0219c (  8604) load
I (114) esp_image: segment 2: paddr=0x00018ab0 vaddr=0x40080000 size=0x00400 (  1024) load
I (119) esp_image: segment 3: paddr=0x00018eb8 vaddr=0x40080400 size=0x07158 ( 29016) load
I (140) esp_image: segment 4: paddr=0x00020018 vaddr=0x400d0018 size=0x158d0 ( 88272) map
I (171) esp_image: segment 5: paddr=0x000358f0 vaddr=0x40087558 size=0x016b0 (  5808) load
I (173) esp_image: segment 6: paddr=0x00036fa8 vaddr=0x400c0000 size=0x00000 (     0) load
I (183) boot: Loaded app from partition at offset 0x10000
I (183) boot: Checking flash encryption...
W (188) flash_encrypt: Using pre-loaded flash encryption key in EFUSE block 1
I (196) flash_encrypt: Setting CRYPT_CONFIG efuse to 0xF
I (214) flash_encrypt: Disable UART bootloader encryption...
I (214) flash_encrypt: Disable UART bootloader decryption...
I (217) flash_encrypt: Disable UART bootloader MMU cache...
I (223) flash_encrypt: Disable JTAG...
I (228) flash_encrypt: Disable ROM BASIC interpreter fallback...
I (246) esp_image: segment 0: paddr=0x00001020 vaddr=0x3fff0018 size=0x00004 (     4) 
I (246) esp_image: segment 1: paddr=0x0000102c vaddr=0x3fff001c size=0x01d04 (  7428) 
I (256) esp_image: segment 2: paddr=0x00002d38 vaddr=0x40078000 size=0x00000 (     0) 
I (262) esp_image: segment 3: paddr=0x00002d40 vaddr=0x40078000 size=0x041b0 ( 16816) 
I (628) esp_image: segment 0: paddr=0x00010020 vaddr=0x3f400020 size=0x068e4 ( 26852) map
I (637) esp_image: segment 1: paddr=0x0001690c vaddr=0x3ffb0000 size=0x0219c (  8604) 
I (641) esp_image: segment 2: paddr=0x00018ab0 vaddr=0x40080000 size=0x00400 (  1024) 
I (645) esp_image: segment 3: paddr=0x00018eb8 vaddr=0x40080400 size=0x07158 ( 29016) 
I (664) esp_image: segment 4: paddr=0x00020018 vaddr=0x400d0018 size=0x158d0 ( 88272) map
I (695) esp_image: segment 5: paddr=0x000358f0 vaddr=0x40087558 size=0x016b0 (  5808) 
I (697) esp_image: segment 6: paddr=0x00036fa8 vaddr=0x400c0000 size=0x00000 (     0) 
I (701) flash_encrypt: Encrypting partition 2 at offset 0x10000...
[0;3⸮ets Jun  8 2016 00:22:57

rst:0x3 (SW_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0018,len:4
load:0x3fff001c,len:7428
load:0x40078000,len:0
load:0x40078000,len:16816
entry 0x4007916c
I (28) boot: ESP-IDF v3.1-dev-661-gf586f5e6 2nd stage bootloader
I (28) boot: compile time 12:32:30
I (28) boot: Enabling RNG early entropy source...
I (35) boot: SPI Speed      : 40MHz
I (39) boot: SPI Mode       : DIO
I (43) boot: SPI Flash Size : 4MB
I (47) boot: Partition Table:
I (50) boot: ## Label            Usage          Type ST Offset   Length
I (58) boot:  0 nvs              WiFi data        01 02 00009000 00006000
I (65) boot:  1 phy_init         RF data          01 01 0000f000 00001000
I (73) boot:  2 factory          factory app      00 00 00010000 00100000
I (80) boot:  3 storage          Unknown data     01 82 00110000 000f0000
I (88) boot: End of partition table
I (92) esp_image: segment 0: paddr=0x00010020 vaddr=0x3f400020 size=0x068e4 ( 26852) map
I (110) esp_image: segment 1: paddr=0x0001690c vaddr=0x3ffb0000 size=0x0219c (  8604) load
I (114) esp_image: segment 2: paddr=0x00018ab0 vaddr=0x40080000 size=0x00400 (  1024) load
I (119) esp_image: segment 3: paddr=0x00018eb8 vaddr=0x40080400 size=0x07158 ( 29016) load
I (140) esp_image: segment 4: paddr=0x00020018 vaddr=0x400d0018 size=0x158d0 ( 88272) map
I (172) esp_image: segment 5: paddr=0x000358f0 vaddr=0x40087558 size=0x016b0 (  5808) load
I (175) esp_image: segment 6: paddr=0x00036fa8 vaddr=0x400c0000 size=0x00000 (     0) load
I (184) boot: Loaded app from partition at offset 0x10000
I (185) boot: Checking flash encryption...
I (190) flash_encrypt: flash encryption is enabled (3 plaintext flashes left)
I (197) boot: Disabling RNG early entropy source...
I (203) cpu_start: Pro cpu up.
I (207) cpu_start: Starting app cpu, entry point is 0x40080e40
I (0) cpu_start: App cpu up.
I (217) heap_init: Initializing. RAM available for dynamic allocation:
I (224) heap_init: At 3FFAE6E0 len 00001920 (6 KiB): DRAM
I (230) heap_init: At 3FFB29D0 len 0002D630 (181 KiB): DRAM
I (236) heap_init: At 3FFE0440 len 00003BC0 (14 KiB): D/IRAM
I (243) heap_init: At 3FFE4350 len 0001BCB0 (111 KiB): D/IRAM
I (249) heap_init: At 40088C08 len 000173F8 (92 KiB): IRAM
I (255) cpu_start: Pro cpu start user code
I (273) cpu_start: Starting scheduler on PRO CPU.
I (0) cpu_start: Starting scheduler on APP CPU.

Opening Non-Volatile Storage (NVS) handle... Done
Reading restart counter from NVS ... Done
Restart counter = 78
Updating restart counter in NVS ... Done
Committing updates in NVS ... Done

Restarting in 10 seconds...
Restarting in 9 seconds...
Restarting in 8 seconds...
Restarting in 7 seconds...
Restarting in 6 seconds...
Restarting in 5 seconds...
Restarting in 4 seconds...
Restarting in 3 seconds...
Restarting in 2 seconds...
Restarting in 1 seconds...
Restarting in 0 seconds...
Restarting now.
Buffalchill commented 6 years ago

@me-no-dev are you sure that spiffs don't work when flash encryption is enabled ? I think i just had a wrong partition table flashed on my board, and would like to investigate that again. luckily NVS work with arduino-esp32 and flash encryption 🥇

Buffalchill commented 6 years ago

great news. today I investigated that NVS (preferences) and SPIFFS do work with Flash_encryption !

spiffs_work

venkat3344 commented 6 years ago

I got the error 1000...

rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) flash read err, 1000 ets_main.c 371 ets Jun 8 2016 00:22:57

rst:0x10 (RTCWDT_RTC_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) flash read err, 1000 ets_main.c 371 ets Jun 8 2016 00:22:57 rst:0x10 (RTCWDT_RTC_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) flash read err, 1000 ets_main.c 371 ets Jun 8 2016 00:22:57 Burn the FLASH_CRYPT_CNT efuse again with the python script getting error : A fatal error occurred : Efuse FLASH_ENCRYPT_CNT failed to burn. Protected? 3. Check out the FLASH_CRYPT_CNT with espefuse.py --port "COM3" summary it should still have the value: 1
mau-lopez commented 6 years ago

Hi Buffalchill, thanks a lot for your explanation on encryption and re-flashing, just one silly question because I don't know c and don't seem to be lucky googling for this one : what library(ies) do I have to include in order to use esp_flash_encryption_enabled() in my code and also how do I declare it so I can use it? Thanks in advance

dharmeshchovatiya7567 commented 5 years ago

I am Try to work on Flash Encryption in ESP32 board and try to Sample Code. I tried with compile/Build Secure Boot with Command 'idf.py bootloader'.

For Flash the Code With Command 'idf.py -p PORT bootloader-flash'.

monitor_Code

Now, I need to monitor the Code which i Flash on Hardware ESP32 But i can't apply Any Command for the "Monitor" and for test the Hardware.

Have You any one Working on ESP32 With Flash Encryption Than please Help me on for the Same.


wrybread commented 4 years ago

How did it all come out? Did you get it encryption working using the Arduino IDE? And did you get SPIFFS working?

I'm trying to do the same.

Buffalchill commented 4 years ago

Well there is a workaround. After compiling in arduino IDE you have to use the .bin of your sketch. Like i have shown in this documentation.

wrybread commented 4 years ago

Thanks. So you got it all working with that method?

And were you able to use the SPIFFS filesystem? Or did you switch to FatFS?

Buffalchill commented 4 years ago

Yes as mentioned up above it works with spiffs and preferences.

In general it is the same procedure as with the esp-idf the only thing that differs is, that you use the compiled .bin file from your arduino sketch and encrypt it with your pre-generated encryption-key

wrybread commented 4 years ago

Fantastic, thanks so much.

WebDust21 commented 4 years ago

So I've successfully gotten ESP32 firmware encryption working (one minor issue yet to figure out, but it doesn't affect operation) with the Arduino IDE. I am also using NVS and SPIFFS; both are working fine.

It was a LITTLE simpler than I thought. Basically, I had to create an ESP-IDF environment (NOT the easiest thing to do for a weekend hobbyist!), then beat around the bush trying so hard to figure out the GIT commands for GitHub in order to compile with an older version of IDF (it doesn't work if you simply download a ZIP from GitHub--no, you have to get it with Git. #%!&@#* all this stuff!) So, obviously, the ESP-IDF version must match the version that the Arduino libraries were compiled with. At least as of this time, that is "IDF release/v3.3 (#3339)", for Arduino-ESP32 1.0.4. (There ain't no such thing as a free lunch; this is just a rough guideline. Details that helped me immeasurably are in GitHub #1142.

I had to run the ESP-IDF menuconfig on the "blinky" sample project to configure the bootloader (4MB chip, 80MHz, QIO, enable encrypt on boot, release mode). I also had to disable some debug output options, as IDF v3.3 has a few too many features compiled into the bootloader--causing it to easily overflow the default 0x7000 (28,672) byte bootloader partition. The resulting "bootloader.bin" was 28,448 bytes in size, with a couple frogs' hair to spare in the partition... Once I had the "bootloader.bin", it was a very simple matter of taking it, and replacing the bootloader BIN (that comes precompiled with the Arduino libraries)...specifically, the one used by the chosen project configuration. In my case (on Ubuntu 18.04 LTS 64 bit), the bootloader files can be found at "/home/USERNAME/.arduino15/packages/esp32/hardware/esp32/1.0.4/tools/sdk/bin/". The default Arduino ESP32 FLASH configuration is QIO, 80MHz, corresponding to "bootloader_qio_80m.bin". I renamed that file to "ORIGINALbootloader_qio_80m.bin" (so I could revert back), and then renamed the new ESP-IDF "bootloader.bin" to "bootloader_qio_80m.bin" I have to admit that I tried replacing precompiled object files (as mentioned in here: https://github.com/espressif/arduino-esp32/issues/1142#issuecomment-478862922 ), but that only resulted in compile errors. In the end, the only file I ended up replacing was the "bootloader_qio_80m.bin" file.

After FLASHING the ESP32 through Arduino IDE (no other changes needed), I cycled power to my ESP32. I have to admit when my project didn't come alive, I forgot that I had the encryption bootloader installed, and cycled power again--interrupting the encryption process. Fortunately, this did not brick my ESP32, though I got the famous "err:1000" repeating error. After swapping the bootloader back to the original Arduino bootloader, I was able to reflash the ESP32 (with the Arduino IDE) and do a few more bug tests on unrelated things. It bears mentioning that the encryption key had already been set in the ESP32's fuses, and a number of other fuses had also been blown by the bootloader. Upon powerup, I got an "err:1000", followed by a restart and normal boot (unencrypted at this point).

After running a number of non-encrypted programming cycles (implementing an emergency OTA door, in case I was unable to "upload ESP32 Sketch Data" with an encrypted ESP32), I swapped the ESP-IDF compiled encryption bootloader back into the Arduino folder, and hit the Arduino IDE Upload button again. It successfully programmed, and upon power cycling my ESP32, the bootloader self-encrypted the ESP32, followed by automatically resetting... ...and the ESP32 is running encrypted, with no issues. Didn't brick a single ESP32.

I'd paste the serial output log here, except that Arduino IDE 1.8.11 decided to refuse to allow me to copy the output. Ctrl+A would select all of it, but Ctrl+C would not copy anything. I tried multiple times, then ended up just taking a photo with my smartphone.

The only error I got during the FLASH encryption process was as follows (and I will mention that I am using the Arduino "minimal SPIFFS" partition table):

[0;31mE (24725) esp_image: image at 0x1f0000 has invalid magic byte[0m [0;33mW (24725) esp_image: image at 0x1f0000 has invalid SPI mode 255[0m [0;33mW (24727) esp_image: image at 0x1f0000 has invalid SPI size 15[0m [0;33mW (24733) flash_encrypt: Not disabling FLASH_CRYPT_CNT - plaintext flashing is still possible[0m [0;32mI (24754) flash_encrypt: Flash encryption completed[0m [0;32mI (24754) boot: Resetting with flash encryption enabled...[0m

The cause of the error is quite obvious: there is nothing in the 2nd OTA partition. I don't understand why the bootloader is trying to encrypt it if there is nothing there--but it did not seem to hurt the actual encryption process, apart from not disabling plaintext flashing. If I figure out what's up with that (perhaps a result from my aborted programming cycle???), I'll try to remember to comment here.

In the event that it helps anyone else, I have attached the bootloader compiled with ESP-IDF (ZIPPED per GitHub requirement), FLASH encryption on boot + Release (not Development). This is for Arduino "esp32 1.0.4", and likely will not work with any other version, older or newer. I have tested it on Arduino 1.8.11 on Ubuntu 18.04 LTS 64-bit.

I will note that "Secure boot" is NOT POSSIBLE with the Arduino IDE (well, just about the time I say that, someone else will figure out how to rewrite the Arduino IDE scripts to enable it!) All you have to do is replace the existing QIO 80MHz Arduino bootloader with this one, and click the Upload button. That is, assuming that you're on "esp32 1.0.4" AND you are using a 4MB FLASH chip AND that the FLASH settings are QIO 80MHz.

By the way, this should theoretically be a VERY easy thing to implement in the Arduino-ESP32 port--obviously, it is very easy for people to damage things with such a "final" feature as firmware encryption (no more serial programming--you can only update it OTA), but just to swap out one file? The bootloaders are already being compiled, shouldn't it be easy to just have a second set of bootloaders for encryption? And 2 pages of warnings followed by a 30-page test (requiring a 100% score) before allowing users to use the encryption bootloaders? Just some thoughts.

bootloader_qio_80m.zip

chegewara commented 4 years ago

I am wondering how could create encrypted spiffs: https://esp32.com/viewtopic.php?t=10059#p41527

So encrypted SPIFFS will never be supported.

@projectgus any comments on this?

WebDust21 commented 4 years ago

The issue is with the rest of that comment you linked, namely:

Unfortunately, SPIFFS makes a lot of optimisations about the way NOR flash works (being able to write any bit 1 to bit 0 with no other effects) and this is incompatible with flash encryption.

In FLASH, you can (depending on the processor and architecture) write as little as one byte at a time. However, you can ONLY change bits from "1" to "0". It is impossible to change a "0" to a "1" by writing to FLASH. The only way to change bits from "0" to "1" is by erasing the entire block. Depending on the FLASH chip, this can be anywhere from 4KB to 64KB (or more) of memory. And this poses the entire reason why encrypted SPIFFS is not possible (if you are writing to it, that is. Notice in the rest of that comment that FATFS is suggested, but only in read-only mode.) I do not know a whole lot about SPIFFS, but I am aware that it puts huge spaces between the files (or blocks--I'm not sure which!) This makes it extremely easy to simply mark a file as "bad" (by changing a single bit from "1" to "0", and then writing the new file version in the open space afterwards. If this file is modified again, they only have to mark the file "bad", and use more empty space. Eventually, they can erase the entire block, and start over. Not only is this very efficient from a CPU and time standpoint, it also dramatically multiplies the number of erase-write cycles you can make before the FLASH itself begins to wear out and fail--simply because it is not erasing the FLASH until the entire block fills up.

The reason this is completely incompatible with encryption, is because for encryption to be secure, a single bit change can potentially affect the ENTIRE partition (depending on the encryption method), necessitating erasing and rewriting of the entire partition. First of all, that is very slow. And secondly, it dramatically reduces the number of write cycles possible before the FLASH chip starts to wear out and make errors. Basically, it negates the entire advantage of SPIFFS, thus the reason encrypted SPIFFS will never be supported.

chegewara commented 4 years ago

I understand comments on forum, i am trying to understand comments in this issue suggesting that SPIFFS partition is encrypted too.

WebDust21 commented 4 years ago

OK, got it. I did not say that SPIFFS was encrypted, just that I was using NVS and SPIFFS in my program with the ESP32's bootloader FLASH encryption--which does not encrypt SPIFFS. From the docs (https://docs.espressif.com/projects/esp-idf/en/latest/security/flash-encryption.html):

With flash encryption enabled, following kinds of flash data are encrypted by default:

    Bootloader
    Partition Table
    All “app” type partitions

Other types of flash data are encrypted conditionally:

    Secure boot bootloader digest (if secure boot is enabled)
    Any partition marked with the “encrypted” flag in the partition table

The SPIFFS and NVS are "data" partitions, per the partition files, as you can see here (for me, the partition file I'm using is found at: /home/USERNAME/.arduino15/packages/esp32/hardware/esp32/1.0.4/tools/partitions/min_spiffs.csv):

Name, Type, SubType, Offset, Size, Flags nvs, data, nvs, 0x9000, 0x5000, otadata, data, ota, 0xe000, 0x2000, app0, app, ota_0, 0x10000, 0x1E0000, app1, app, ota_1, 0x1F0000,0x1E0000, spiffs, data, spiffs, 0x3D0000,0x30000,

You will notice that NVS, OTADATA and SPIFFS are all "data" partitions, which the bootloader does NOT encrypt. My comment was intended as sort of response to a comment earlier on this issue (https://github.com/espressif/arduino-esp32/issues/1387#issuecomment-391986730), that I am using both NVS and SPIFFS in my project, and running the bootloader FLASH encryption process did not break either.

WebDust21 commented 4 years ago

@me-no-dev A thought...since it was relatively easy to get encryption enabled using the Arduino IDE and a precompiled bootloader, I have a suggestion, piqued from the following link on the ESP32 forums (https://www.esp32.com/viewtopic.php?t=9994#p41278). This is actually similar to what I really wanted in the first place...and would prevent casual users from selecting an option they don't fully understand--because it won't be there. Basically, if the Arduino bootloaders are precompiled with the encryption routines included, BUT patched so they don't encrypt unless "activated", everyone would benefit significantly.

As in something like this: 1) After debugging the product, and getting it ready for production, the programmer throws in a small routine in setup(), and programs the ESP32 2) Upon startup, "the small routine" checks to see if the ESP32 is running encrypted. If not, the routine initializes the product's display, putting up a message, "Initial encryption in progress, please wait"...then blows an ESP32 configuration fuse, enabling the encryption process in the bootloader. Followed by an ESP.restart() command. 3) The bootloader notices the blown fuse, and promptly goes to work encrypting all of the partitions. After it completes, it restarts the ESP32. 4) When the user application starts, "the small routine" finds that the ESP32 is running encrypted, and the user application starts.

It would be relatively trivial to specify another fuse to determine whether the bootloader uses "development" or "release" mode. This being of some complexity, it would avoid casual users from inadvertently selecting a menu option and bricking their ESP32. But for more advanced programmers who are gearing towards a production environment, it would make this process immensely easier.

Thoughts?

EDIT: looking through the Arduino-ESP32 "esp_flash_encrypt.h" and found the "esp_flash_encrypt_check_and_update()" command. I'm not a super ESP32 geek like you...but if this points to the ESP32's bootloader...maybe a blowing a fuse and restarting is not necessary. Just have the "production" code call that routine to encrypt the ESP32?

projectgus commented 4 years ago

@WebDust21 I've replied to your forum post (which was the same as your post above), here: https://esp32.com/viewtopic.php?f=13&t=10798&p=56154#p56154

Regarding the most recent post, we're unlikely to add support for hardware security features in Arduino. There are a lot of variables which can be configured, and it's a lot of additional work to test and make sure it's actually secure as recommended. The supported way to use Arduino in a production system with physical security features is to use ESP-IDF with Arduino libraries as a component.

WebDust21 commented 4 years ago

Yes, I understand that there are a lot of variables that can be configured...but there's just as many variables to be configured for an unencrypted bootloader. The principle of Arduino is not to provide the Swiss army knife of features, but rather to provide a smaller subset of features that are tested and easy to use. I don't see why it's difficult to simply modify the bootloader (that's already compiled and provided with the ESP32 Arduino libraries) to include support for FLASH encryption--and whether the user uses it or not is completely up to them. Heck, there's already 8 different bootloaders to give support for some of said variables! All I did was drop in a replacement BIN file, which (to my surprise) works perfectly, apart from a minor configuration error. What could be easier than that?

Here I've just spent an hour fighting with ESP-IDF that for whatever reason unknown to me, decided it was time to refuse to initialize because of some GIT error. I used it perfectly fine last week, and now it refuses to start (apparently there was some magic context in the terminal window that I was unaware of)--which is incredibly frustrating. If FLASH encryption was enabled in a slightly modified bootloader in the Arduino port, I am certain that hundreds of people would benefit. Yes, I could try to port over to ESP-IDF--but it's not giving me a very good first (or second) impression. Not to mention that due to the library changes or other unknown gremlins, I would then have to debug and rewrite over 410KB of source code for my current project (NOT including libraries--this is all code I have personally written. Yes, there's a reason I'm using the "minimal SPIFFS" partition scheme!)

Buffalchill commented 4 years ago

I dont GET the point why arduino shouldnt support this Feature. Just because people could mess up? Why not implement it and make it hard to mess it up like @WebDust21 mentioned. The esp idf is so super complicated to use and using arduino as a component is real frustrating too. I tried it and it sucks for me.

WebDust21 commented 4 years ago

Final report: in the above bootloader file, I had not checked "Disable Plaintext Flashing" in the bootloader configuration, resulting in it not fully locking down the ESP32. Due to some other issues, I was unable to use my ESP-IDF installation to recompile the bootloader with the setting enabled...and I had to start over.

Attached to this post is a ZIP file with a bootloader compiled and tested with the following configuration:

Assuming your Arduino ESP32 project fits the above requirements, use the bootloader as follows:

  1. Find the bootloader files in your Arduino installation. In my case, on Ubuntu 18.04 LTS 64-bit, they can be found at "/home/USERNAME/.arduino15/packages/esp32/hardware/esp32/1.0.4/tools/sdk/bin/"
  2. Rename the original "bootloader_qio_80m.bin" to something else ("ORIGINALbootloader_qio_80m.bin") so you can swap it back for regular debug testing
  3. Extract the ZIP file, so "bootloader_qio_80m.bin" is in the folder.
  4. Go to Arduino IDE, and upload your sketch like normal.
  5. Cycle power to the ESP32, and wait. In my case, with a 1.4MB app, it takes about 25 seconds to fully encrypt and automatically start my program. If you connect over the serial monitor @ 115200 baud (standard), you should see something like the following output:

rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) configsip: 0, SPIWP:0xee clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00 mode:DIO, clock div:1 load:0x3fff0018,len:4 load:0x3fff001c,len:5232 ho 0 tail 12 room 4 load:0x40078000,len:12792 ho 0 tail 12 room 4 load:0x40080400,len:5960 entry 0x400806a4 {ESP32 IS ENCRYPTING WITH A SELF-GENERATED KEY} E (27445) esp_image: image at 0x1f0000 has invalid magic byte E (27445) boot_comm: mismatch chip ID, expected 0, found 18770 ets Jun 8 2016 00:22:57

rst:0x3 (SW_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) configsip: 0, SPIWP:0xee clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00 mode:DIO, clock div:1 load:0x3fff0018,len:4 load:0x3fff001c,len:5232 ho 0 tail 12 room 4 load:0x40078000,len:12792 ho 0 tail 12 room 4 load:0x40080400,len:5960 entry 0x400806a4 {YOUR APPLICATION IS RUNNING}

And last but not least, SWAP THE ORIGINAL ARDUINO BOOTLOADER BACK BEFORE YOU FORGET!

NOTES:

Enjoy ;-)

bootloader_qio_80m.zip

DNThomas commented 4 years ago

@WebDust21 Many thanks for the efforts above, it was exactly the solution I was looking for at the time. Given recent developments in circumventing the flash protection on earlier revisions of the ESP32 (<v2), would you be willing to create a bootloader that also disables the UART loader on the v3 silicon ?

I'd be more than happy to provide sacrificial units for you to use.

WebDust21 commented 4 years ago

Shouldn't be difficult, as long as disabling the UART is a bootloader option. (It wasn't last I checked). I would have to check the ESP-IDF (difficult beast that it is to manage) and see if the bootloader can support these updates. I believe the v3 silicon changes did not require a bootloader change (that's why it's a silicon change, not a firmware fix), so it shouldn't be too difficult.

Don't think I need any sacrificial units yet per se...if I can create the necessary bootloader files, you could test them.

LusterWong commented 4 years ago

Final report: in the above bootloader file, I had not checked "Disable Plaintext Flashing" in the bootloader configuration, resulting in it not fully locking down the ESP32. Due to some other issues, I was unable to use my ESP-IDF installation to recompile the bootloader with the setting enabled...and I had to start over.

Attached to this post is a ZIP file with a bootloader compiled and tested with the following configuration:

  • ESP-WROOM-32
  • 4MB FLASH
  • QIO, 80MHz
  • FLASH encryption enabled on boot, Release mode (NOT Development)
  • Bootloader output: error only (bootloader is too big if left on the default "Info" setting)

Assuming your Arduino ESP32 project fits the above requirements, use the bootloader as follows:

  1. Find the bootloader files in your Arduino installation. In my case, on Ubuntu 18.04 LTS 64-bit, they can be found at "/home/USERNAME/.arduino15/packages/esp32/hardware/esp32/1.0.4/tools/sdk/bin/"
  2. Rename the original "bootloader_qio_80m.bin" to something else ("ORIGINALbootloader_qio_80m.bin") so you can swap it back for regular debug testing
  3. Extract the ZIP file, so "bootloader_qio_80m.bin" is in the folder.
  4. Go to Arduino IDE, and upload your sketch like normal.
  5. Cycle power to the ESP32, and wait. In my case, with a 1.4MB app, it takes about 25 seconds to fully encrypt and automatically start my program. If you connect over the serial monitor @ 115200 baud (standard), you should see something like the following output:

rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) configsip: 0, SPIWP:0xee clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00 mode:DIO, clock div:1 load:0x3fff0018,len:4 load:0x3fff001c,len:5232 ho 0 tail 12 room 4 load:0x40078000,len:12792 ho 0 tail 12 room 4 load:0x40080400,len:5960 entry 0x400806a4 {ESP32 IS ENCRYPTING WITH A SELF-GENERATED KEY} �[0;31mE (27445) esp_image: image at 0x1f0000 has invalid magic byte�[0m �[0;31mE (27445) boot_comm: mismatch chip ID, expected 0, found 18770�[0m ets Jun 8 2016 00:22:57 rst:0x3 (SW_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) configsip: 0, SPIWP:0xee clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00 mode:DIO, clock div:1 load:0x3fff0018,len:4 load:0x3fff001c,len:5232 ho 0 tail 12 room 4 load:0x40078000,len:12792 ho 0 tail 12 room 4 load:0x40080400,len:5960 entry 0x400806a4 {YOUR APPLICATION IS RUNNING}

And last but not least, SWAP THE ORIGINAL ARDUINO BOOTLOADER BACK BEFORE YOU FORGET!

NOTES:

  • If you accidentally interrupt power to the ESP32 while it is encrypting, simply re-upload your sketch, and try again. I did that by accident once (while programming and encrypting 18 ESP32s), and it worked fine.
  • If you are in a semi-production environment, and have an SPIFFS upload to make, don't worry. Simply upload the sketch to the ESP32, then restart it in programming mode (hold EN, or however you access programming mode on your project)...don't let it enter "run" mode, or it will start to encrypt. Upload the SPIFFS data, then restart the ESP32 in "run" mode.
  • You will not be able to upload another sketch to the ESP32 via Arduino IDE (or even ESP-IDF). The only way to update the ESP32 is via internal update, where your application receives the binary, and calls the appropriate ESP flash write functions to update it. Any attempt to upload code via RS-232 (Arduino or otherwise) will result in a bootloop with errors, as it is impossible to call the encryption functions in the bootloader again (due to the write-protected FLASH_CRYPT_CNT fuses.)
  • Note that secure boot is not possible to implement (without a lot of difficulty) with Arduino. However, this is not a problem if you devise your own protection against updating with "non-official" firmwares. Basically, secure boot prevents "non-signed" binaries from running if they get OTA'd into the ESP. But if your OTA code simply rejects "non-official" binaries, you have a better end result than Secure Boot.

Enjoy ;-)

bootloader_qio_80m.zip

I also developed with Arduino and was ready to deliver the factory to burn images. However, the failure to provide unencrypted images for use by the factory exposes the risk.

Does the method you provide apply only to your own PC download and prevent others from reading it?

Idf is very complicated, I have studied it for a long time, but I still don't understand how to generate the encrypted image to the factory. But see that the steps on "secure Boot" mention the need for public key and private key, but your method doesn't seem to have these steps?

Thank you.

WebDust21 commented 4 years ago

In brief... The initial programming of an ESP32 will always be plaintext/unencrypted in some form or fashion. Using "secure boot" requires that one of the keys (not very familiar with it, have never used it!) to be FLASHed to each and every ESP32 before they will boot the "secured" and pre-encrypted binary. And if the factory has access to the key (as they will in order to program the ESP32), then you're right back where you started, as they will be able to use your binary together with the key just the same as you do.

In short, like other people have mentioned in such nontrustworthy environments, your best bet is to provide the factory with a "bootloader stub" of sorts (if even that) that will self-encrypt the ESP32...then connect to a WiFi network, download the actual binary (which you may want to encrypt in some form or fashion to prevent the downloaded file from functioning in an ESP32 if directly downloaded)...and update itself. That way at least the actual binary is out of their hands. If they went rogue on you, however, they can still program ESP32s--at least until you take the file down.

If you can't program the ESP32s yourself, you're in a sticky tough situation. In short: if the factory can fully program the ESP32 to the final required specification, they can also steal your code. Various methods can be used to make this more difficult, but the end problem remains the same.

LusterWong commented 4 years ago

In brief... The initial programming of an ESP32 will always be plaintext/unencrypted in some form or fashion. Using "secure boot" requires that one of the keys (not very familiar with it, have never used it!) to be FLASHed to each and every ESP32 before they will boot the "secured" and pre-encrypted binary. And if the factory has access to the key (as they will in order to program the ESP32), then you're right back where you started, as they will be able to use your binary together with the key just the same as you do.

In short, like other people have mentioned in such nontrustworthy environments, your best bet is to provide the factory with a "bootloader stub" of sorts (if even that) that will self-encrypt the ESP32...then connect to a WiFi network, download the actual binary (which you may want to encrypt in some form or fashion to prevent the downloaded file from functioning in an ESP32 if directly downloaded)...and update itself. That way at least the actual binary is out of their hands. If they went rogue on you, however, they can still program ESP32s--at least until you take the file down.

If you can't program the ESP32s yourself, you're in a sticky tough situation. In short: if the factory can fully program the ESP32 to the final required specification, they can also steal your code. Various methods can be used to make this more difficult, but the end problem remains the same.

I don't understand why the official don't provide the tools, and the encryption is so complicated and inconvenience. I think there should be some tools that can encrypt the BIN on any platform (ARDUINO or IDF), such as public key pre-burning, and then private key encrypting the BIN and publishing it so that the problem can be solved. It took me more than half a year to develop it, but I can't produce it now because of the encryption problem. I have quite a headache and can't sleep....