Skip to content

Commit fbaff6a

Browse files
committed
Use ROSC randomisation instead of CK_JITTER
1 parent 23cc699 commit fbaff6a

File tree

4 files changed

+133
-12
lines changed

4 files changed

+133
-12
lines changed

enc_bootloader/CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ if (NOT USE_PRECOMPILED)
55

66
set(PICO_NO_PICOTOOL 1)
77

8-
# Ensure we're using a Release build - MinSizeRel doesn't work for some reason
9-
set(CMAKE_BUILD_TYPE Release)
8+
# Ensure we're using a MinSizeRel build
9+
set(CMAKE_BUILD_TYPE MinSizeRel)
1010

1111
# If the user set these environment variables to influence the picotool
1212
# build, unset them here so that they do not influence the pico-sdk

enc_bootloader/config.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747
#endif
4848

4949
#ifndef CK_JITTER
50-
#define CK_JITTER 1 // occasionally switch CPU clock to ROSC for extra timing variability
50+
#define CK_JITTER 0 // occasionally switch CPU clock to ROSC for extra timing variability
5151
#endif
5252

5353

enc_bootloader/enc_bootloader.c

Lines changed: 130 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@
1616

1717
#include "pico/binary_info.h"
1818

19+
#include "hardware/clocks.h"
20+
#include "hardware/xosc.h"
21+
#include "hardware/structs/rosc.h"
22+
1923
#include "config.h"
2024

2125
extern uint32_t rstate_sha[4];
@@ -145,6 +149,125 @@ void init_rstate() {
145149
// No need to wait for SHA, as we polled the EHR one extra time, which
146150
// takes longer than the SHA.
147151
for(i=0;i<4;i++) rstate_sha[i]=sha256->sum[i];
152+
153+
rosc_hw->random = rstate_sha[0];
154+
}
155+
156+
// These just have to be higher than the actual frequency, to prevent overclocking unused peripherals
157+
#define ROSC_HZ 300*MHZ
158+
#define OTHER_CLK_DIV 30
159+
160+
void runtime_init_clocks(void) {
161+
// Disable resus that may be enabled from previous software
162+
clocks_hw->resus.ctrl = 0;
163+
164+
bi_decl(bi_ptr_int32(0, 0, rosc_div, 2)); // default divider 2
165+
bi_decl(bi_ptr_int32(0, 0, rosc_drive, 0x0000)); // default drives of 0
166+
bi_decl(bi_ptr_int32(0, 0, xosc_mhz, 12)); // xosc freq in MHz
167+
bi_decl(bi_ptr_int32(0, 0, clk_mhz, 150)); // xosc freq in MHz
168+
169+
// Bump up ROSC speed to ~90MHz
170+
rosc_hw->freqa = 0; // reset the drive strengths
171+
rosc_hw->div = rosc_div | ROSC_DIV_VALUE_PASS; // set divider
172+
// Increment the freqency range one step at a time - this is safe provided the current config is not TOOHIGH
173+
// because ROSC_CTRL_FREQ_RANGE_VALUE_MEDIUM | ROSC_CTRL_FREQ_RANGE_VALUE_HIGH == ROSC_CTRL_FREQ_RANGE_VALUE_HIGH
174+
static_assert(ROSC_CTRL_FREQ_RANGE_VALUE_LOW | ROSC_CTRL_FREQ_RANGE_VALUE_MEDIUM == ROSC_CTRL_FREQ_RANGE_VALUE_MEDIUM);
175+
static_assert(ROSC_CTRL_FREQ_RANGE_VALUE_MEDIUM | ROSC_CTRL_FREQ_RANGE_VALUE_HIGH == ROSC_CTRL_FREQ_RANGE_VALUE_HIGH);
176+
hw_set_bits(&rosc_hw->ctrl, ROSC_CTRL_FREQ_RANGE_VALUE_MEDIUM);
177+
hw_set_bits(&rosc_hw->ctrl, ROSC_CTRL_FREQ_RANGE_VALUE_HIGH);
178+
179+
// Enable rosc randomisation
180+
rosc_hw->freqa = (ROSC_FREQA_PASSWD_VALUE_PASS << ROSC_FREQA_PASSWD_LSB) |
181+
rosc_drive | ROSC_FREQA_DS1_RANDOM_BITS | ROSC_FREQA_DS0_RANDOM_BITS; // enable randomisation
182+
183+
// Not used with FREQ_RANGE_VALUE_HIGH, but should still be set
184+
rosc_hw->freqb = (ROSC_FREQB_PASSWD_VALUE_PASS << ROSC_FREQB_PASSWD_LSB) |
185+
rosc_drive;
186+
187+
// Calibrate ROSC frequency if XOSC present - otherwise just configure
188+
uint32_t rosc_freq_mhz = 0;
189+
if (xosc_mhz) {
190+
xosc_init();
191+
// CLK_REF = XOSC
192+
clock_configure_int_divider(clk_ref,
193+
CLOCKS_CLK_REF_CTRL_SRC_VALUE_XOSC_CLKSRC,
194+
0,
195+
xosc_mhz * MHZ,
196+
1);
197+
// CLK_SYS = CLK_REF
198+
clock_configure_int_divider(clk_sys,
199+
CLOCKS_CLK_SYS_CTRL_SRC_VALUE_CLK_REF,
200+
CLOCKS_CLK_SYS_CTRL_AUXSRC_VALUE_ROSC_CLKSRC, // leave the aux source on ROSC
201+
xosc_mhz * MHZ,
202+
1);
203+
204+
// Max out rosc
205+
rosc_hw->div = 1 | ROSC_DIV_VALUE_PASS;
206+
rosc_hw->freqa = (ROSC_FREQA_PASSWD_VALUE_PASS << ROSC_FREQA_PASSWD_LSB) |
207+
ROSC_FREQA_DS3_BITS | ROSC_FREQA_DS2_BITS |
208+
ROSC_FREQA_DS1_RANDOM_BITS | ROSC_FREQA_DS0_RANDOM_BITS; // enable randomisation
209+
rosc_hw->freqb = (ROSC_FREQB_PASSWD_VALUE_PASS << ROSC_FREQB_PASSWD_LSB) |
210+
ROSC_FREQB_DS7_LSB | ROSC_FREQB_DS6_LSB | ROSC_FREQB_DS5_LSB | ROSC_FREQB_DS4_LSB;
211+
212+
// Wait for ROSC to be stable
213+
while(!(rosc_hw->status & ROSC_STATUS_STABLE_BITS)) {
214+
tight_loop_contents();
215+
}
216+
217+
rosc_freq_mhz = frequency_count_khz(CLOCKS_FC0_SRC_VALUE_ROSC_CLKSRC_PH) / KHZ;
218+
}
219+
if (rosc_freq_mhz > clk_mhz) {
220+
// CLK SYS = ROSC divided down to clk_mhz, according to XOSC calibration
221+
clock_configure_mhz(clk_sys,
222+
CLOCKS_CLK_SYS_CTRL_SRC_VALUE_CLKSRC_CLK_SYS_AUX,
223+
CLOCKS_CLK_SYS_CTRL_AUXSRC_VALUE_ROSC_CLKSRC,
224+
rosc_freq_mhz,
225+
clk_mhz);
226+
} else { // Either ROSC is running too slowly, or there was no XOSC to calibrate it against
227+
// CLK SYS = ROSC directly, as it's running slowly enough
228+
clock_configure_int_divider(clk_sys,
229+
CLOCKS_CLK_SYS_CTRL_SRC_VALUE_CLKSRC_CLK_SYS_AUX,
230+
CLOCKS_CLK_SYS_CTRL_AUXSRC_VALUE_ROSC_CLKSRC,
231+
ROSC_HZ, // this doesn't have to be accurate
232+
1);
233+
}
234+
235+
// Configure other clocks - none of these need to be accurate
236+
237+
// CLK_REF = ROSC / OTHER_CLK_DIV - this and other clocks aren't really used, so just need to be set to a low enough frequency
238+
clock_configure_int_divider(clk_ref,
239+
CLOCKS_CLK_REF_CTRL_SRC_VALUE_ROSC_CLKSRC_PH,
240+
0,
241+
ROSC_HZ,
242+
OTHER_CLK_DIV);
243+
244+
// CLK USB (not used)
245+
clock_configure_int_divider(clk_usb,
246+
0, // No GLMUX
247+
CLOCKS_CLK_USB_CTRL_AUXSRC_VALUE_ROSC_CLKSRC_PH,
248+
ROSC_HZ,
249+
OTHER_CLK_DIV);
250+
251+
// CLK ADC (not used)
252+
clock_configure_int_divider(clk_adc,
253+
0, // No GLMUX
254+
CLOCKS_CLK_ADC_CTRL_AUXSRC_VALUE_ROSC_CLKSRC_PH,
255+
ROSC_HZ,
256+
OTHER_CLK_DIV);
257+
258+
// CLK PERI Used as reference clock for UART and SPI serial. (not used)
259+
clock_configure_int_divider(clk_peri,
260+
0,
261+
CLOCKS_CLK_PERI_CTRL_AUXSRC_VALUE_CLK_SYS,
262+
ROSC_HZ,
263+
OTHER_CLK_DIV);
264+
265+
// CLK_HSTX Transmit bit clock for the HSTX peripheral. (not used)
266+
clock_configure_int_divider(clk_hstx,
267+
0,
268+
CLOCKS_CLK_HSTX_CTRL_AUXSRC_VALUE_CLK_SYS,
269+
ROSC_HZ,
270+
OTHER_CLK_DIV);
148271
}
149272

150273

@@ -158,14 +281,13 @@ int main() {
158281
otp_hw->crt_key_w[i] = key_i;
159282
}
160283

161-
bi_decl(bi_program_feature_group(0x1111, 0x2222, "encryption_config"));
162-
bi_decl(bi_ptr_int32(0x1111, 0x2222, data_start_addr, 0x20000000));
163-
bi_decl(bi_ptr_int32(0x1111, 0x2222, data_size, 0x78000));
164-
bi_decl(bi_ptr_int32(0x1111, 0x2222, iv0, 0));
165-
bi_decl(bi_ptr_int32(0x1111, 0x2222, iv1, 1));
166-
bi_decl(bi_ptr_int32(0x1111, 0x2222, iv2, 2));
167-
bi_decl(bi_ptr_int32(0x1111, 0x2222, iv3, 3));
168-
bi_decl(bi_ptr_int32(0x1111, 0x2222, otp_key_page, 30));
284+
bi_decl(bi_ptr_int32(0, 0, data_start_addr, 0x20000000));
285+
bi_decl(bi_ptr_int32(0, 0, data_size, 0x78000));
286+
bi_decl(bi_ptr_int32(0, 0, iv0, 0));
287+
bi_decl(bi_ptr_int32(0, 0, iv1, 1));
288+
bi_decl(bi_ptr_int32(0, 0, iv2, 2));
289+
bi_decl(bi_ptr_int32(0, 0, iv3, 3));
290+
bi_decl(bi_ptr_int32(0, 0, otp_key_page, 30));
169291

170292
// Initialise IV from binary info words
171293
uint8_t iv[16];

main.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4998,7 +4998,6 @@ bool encrypt_command::execute(device_map &devices) {
49984998
auto program = get_iostream_memory_access<iostream_memory_access>(tmp, filetype::elf, true);
49994999
program.set_model(rp2350);
50005000

5001-
settings.config.group = "encryption_config";
50025001
// data_start_addr
50035002
settings.config.key = "data_start_addr";
50045003
settings.config.value = hex_string(data_start_address);

0 commit comments

Comments
 (0)