8000 Merge pull request #672 from pennam/boot-v25 · seaxwi/ArduinoCore-mbed@d3fa563 · GitHub
[go: up one dir, main page]

Skip to content

Commit d3fa563

Browse files
authored
Merge pull request arduino#672 from pennam/boot-v25
Bootloader v25 update proposal
2 parents d149870 + f48f635 commit d3fa563

11 files changed

+37700
-59073
lines changed
Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
/*
2+
This example enables secuity features of the MCUboot bootloader writing encryption
3+
and signing key into the microcontroller flash memory.
4+
5+
Once the keys are loaded you need to build and upload the future sketches enabling
6+
the Security Settings -> "Signing + Encryption" in the tools menu of the IDE. This
7+
will create an encrypted and signed binary conforming to the MCUboot image format
8+
using imgtool. See https://docs.mcuboot.com/design.html#image-format for more details
9+
about image format.
10+
11+
Writing the keys will also enable MCUboot image swap using a scratch area. This will
12+
increase the sketch update time after the upload, but also adds the possibility to
13+
revert to the previous image version if the update is not confirmed.
14+
See ConfirmSketch example for more details about setting the confirmed flag.
15+
16+
Circuit:
17+
- Arduino Portenta H7 board
18+
19+
This example code is in the public domain.
20+
*/
21+
22+
#include "FlashIAP.h"
23+
#include "QSPIFBlockDevice.h"
24+
#include "MBRBlockDevice.h"
25+
#include "LittleFileSystem.h"
26+
#include "FATFileSystem.h"
27+
#if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_OPTA) || defined(ARDUINO_GIGA)
28+
#include "ecdsa-p256-encrypt-key.h"
29+
#include "ecdsa-p256-signing-key.h"
30+
#else
31+
#error "Security features not available for this board"
32+
#endif
33+
34+
#ifndef CORE_CM7
35+
#error Update the bootloader by uploading the sketch to the M7 core instead of the M4 core.
36+
#endif
37+
38+
#define BOOTLOADER_ADDR (0x8000000)
39+
#define SIGNING_KEY_ADDR (0x8000300)
40+
#define ENCRYPT_KEY_ADDR (0x8000400)
41+
#define ENCRYPT_KEY_SIZE (0x0000100)
42+
#define SIGNING_KEY_SIZE (0x0000100)
43+
44+
mbed::FlashIAP flash;
45+
QSPIFBlockDevice root(QSPI_SO0, QSPI_SO1, QSPI_SO2, QSPI_SO3, QSPI_SCK, QSPI_CS, QSPIF_POLARITY_MODE_1, 40000000);
46+
47+
bool writeKeys = false;
48+
uint32_t bootloader_data_offset = 0x1F000;
49+
uint8_t* bootloader_data = (uint8_t*)(BOOTLOADER_ADDR + bootloader_data_offset);
50+
51+
uint32_t bootloader_identification_offset = 0x2F0;
52+
uint8_t* bootloader_identification = (uint8_t*)(BOOTLOADER_ADDR + bootloader_identification_offset);
53+
54+
void setup() {
55+
Serial.begin(115200);
56+
while (!Serial) {}
57+
58+
uint8_t currentBootloaderVersion = bootloader_data[1];
59+
String currentBootloaderIdentifier = String(bootloader_identification, 15);
60+
61+
if((currentBootloaderVersion > 24) && (currentBootloaderIdentifier.equals("MCUboot Arduino"))) {
62+
Serial.println("The sketch comes with a set of default keys to evaluate signing and encryption process");
63+
Serial.println("If you load the keys, you will need to upload the future sketches with Security Settings -> Signing + Encryption.");
64+
Serial.println("If you select Security Settings -> None, the sketches will not be executed.");
65+
Serial.println("Do you want to load the keys? Y/[n]");
66+
if (waitResponse()) {
67+
Serial.println("\nPlease notice that loading the keys will enable MCUboot Sketch swap. This will increase the sketch update time after the upload.");
68+
Serial.println("A violet LED will blink until the sketch is ready to run.");
69+
Serial.println("Do you want to proceed loading the default keys? Y/[n]");
70+
writeKeys = waitResponse();
71+
}
72+
} else {
73+
Serial.println("Security features not available for this bootloader version. Please update it using STM32H747_manageBootloader sketch");
74+
}
75+
76+
if (writeKeys) {
77+
applyUpdate();
78+
}
79+
Serial.println("It's now safe to reboot or disconnect your board.");
80+
}
81+
82+
void printProgress(uint32_t offset, uint32_t size, uint32_t threshold, bool reset) {
83+
static int percent_done = 0;
84+
if (reset == true) {
85+
percent_done = 0;
86+
Serial.println("Flashed " + String(percent_done) + "%");
87+
} else {
88+
uint32_t percent_done_new = offset * 100 / size;
89+
if (percent_done_new >= percent_done + threshold) {
90+
percent_done = percent_done_new;
91+
Serial.println("Flashed " + String(percent_done) + "%");
92+
}
93+
}
94+
}
95+
96+
bool waitResponse() {
97+
bool confirmation = false;
98+
while (confirmation == false) {
99+
if (Serial.available()) {
100+
char choice = Serial.read();
101+
switch (choice) {
102+
case 'y':
103+
case 'Y':
104+
confirmation = true;
105+
return true;
106+
break;
107+
case 'n':
108+
case 'N':
109+
confirmation = true;
110+
return false;
111+
break;
112+
default:
113+
continue;
114+
}
115+
}
116+
}
117+
}
118+
119+
void setupMCUBootOTAData() {
120+
mbed::MBRBlockDevice ota_data(&root, 2);
121+
mbed::FATFileSystem ota_data_fs("fs");
122+
123+
int err = ota_data_fs.reformat(&ota_data);
124+
if (err) {
125+
Serial.println("Error creating MCUboot files in OTA partition.");
126+
Serial.println("Run QSPIformat.ino sketch to format the QSPI flash and fix the issue.");
127+
}
128+
129+
FILE* fp = fopen("/fs/scratch.bin", "wb");
130+
const int scratch_file_size = 128 * 1024;
131+
const char buffer[128] = {0xFF};
132+
int size = 0;
133+
134+
Serial.println("\nCreating scratch file");
135+
printProgress(size, scratch_file_size, 10, true);
136+
while (size < scratch_file_size) {
137+
int ret = fwrite(buffer, sizeof(buffer), 1, fp);
138+
if (ret != 1) {
139+
Serial.println("Error writing scratch file");
140+
break;
141+
}
142+
size += sizeof(buffer);
143+
printProgress(size, scratch_file_size, 10, false);
144+
}
145+
fclose(fp);
146+
147+
fp = fopen("/fs/update.bin", "wb");
148+
const int update_file_size = 15 * 128 * 1024;
149+
size = 0;
150+
151+
Serial.println("\nCreating update file");
152+
printProgress(size, update_file_size, 10, true);
153+
while (size < update_file_size) {
154+
int ret = fwrite(buffer, sizeof(buffer), 1, fp);
155+
if (ret != 1) {
156+
Serial.println("Error writing scratch file");
157+
break;
158+
}
159+
size += sizeof(buffer);
160+
printProgress(size, update_file_size, 5, false);
161+
}
162+
163+
fclose(fp);
164+
}
165+
166+
void applyUpdate() {
167+
flash.init();
168+
setupMCUBootOTAData();
169+
flash.program(&enc_priv_key, ENCRYPT_KEY_ADDR, ENCRYPT_KEY_SIZE);
170+
flash.program(&ecdsa_pub_key, SIGNING_KEY_ADDR, SIGNING_KEY_SIZE);
171+
flash.deinit();
172+
Serial.println("\nSecurity features enabled. It's now safe to reboot or disconnect your board.");
173+
}
174+
175+
void loop() {
176+
delay(1000);
177+
}

0 commit comments

Comments
 (0)
0