Skip to content

Commit 71e2046

Browse files
authored
Measure the SP on SP_RESET signal interrupt (#1946)
On SP_RESET asserted, the RoT will measure the entire active SP Hubris bank (Hubris plus 0xff padding from 0x800_0000 to 0x80f_ffff). The measurement reliably takes about 0.482 seconds since neither the SP nor the RoT are doing anything else during this time. This low measurement time and the existing timeouts and retries used by the control plane mitigate concerns that were present when the duration was measured in multiple seconds. This time could be further reduced. It is currently taking 0.245 seconds to inject the measurement program into the SP. Each u32 is being sent and read back separately and retried if there is any error (no errors have been seen as of yet). If all is well with the SP, the measurement will match the `Sha3_256` value represented in the SP Hubris archive in the file named "img/final.fwid". # Testing SP measurement Checkout hubris branch `attest-sp` ```sh APP=$PWD/app/oxide-rot-1/app-dev.toml ARCHIVE=$(cargo -q xtask print --archive --image-name a $APP) cargo xtask flash $APP ``` ## Measure on SP Reset: Hit the reset button on the SP or use the SpCtrl.db_reset_sp function: ```sh humility --archive=$ARCHIVE hiffy -c SpCtrl.db_reset_sp -a delay_ms=10 sleep 13 ``` ## See traces The ringbuf trace in `swd` and `attest` tasks have the interesting information including the time expended: ```sh humility --archive=$ARCHIVE ringbuf ``` ## Dump the attestation log: ```sh humility --archive=$ARCHIVE hiffy -c Attest.log -a offset=0 -n 256 -o out hexdump -C out ``` The hexdump is not hard to read directly. The first four bytes are a LE u32 giving the number of valid entries. Each entry is a 1-byte discriminator that is 0_u8 for `Sha3_256` followed by the 32-byte measurement (FWID). There is space for 16 measurements. ## Notes - The RoT only attempts a measurement if it detects an SP reset. - Existing measurements are cleared if an STLINK power-on is detected or if an STLINK is on during a measurement attempt. It is observed that powered-off STLINKs have no effect. - No SP reset can be captured until the `swd` task has initialized. If needed, the control plane can request the SP to reset itself which will result in the RoT measuring the SP. - The `attest` task has a `reset_log_and_record` function usable only by the `swd` task (and hiffy for debug builds). - Closes #2020 by reserving the first slot of the attestation log for the `swd` task.
1 parent 3324a9c commit 71e2046

File tree

26 files changed

+2478
-149
lines changed

26 files changed

+2478
-149
lines changed

.cargo/config.toml

+3
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,6 @@ xtask = "run --package xtask --"
88
# overridden within xtask for Hubris programs, so this only affects host tools like
99
# xtask.
1010
rustflags = ["-Zallow-features=proc_macro_diagnostic,asm_const,naked_functions,used_with_arg"]
11+
12+
[unstable]
13+
bindeps = true

Cargo.lock

+37-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+15
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,21 @@ opt-level = "z" # smaller optimizations
2020
[profile.dev]
2121
opt-level = 1 # no optimizations was just too painful in terms of flash size
2222

23+
[profile.release.package.endoscope]
24+
codegen-units = 1
25+
debug = 2
26+
opt-level = "z"
27+
28+
[profile.dev.package.endoscope]
29+
codegen-units = 1
30+
debug = 2
31+
opt-level = "z"
32+
33+
[profile.bench.package.endoscope]
34+
codegen-units = 1
35+
debug = 2
36+
opt-level = "z"
37+
2338
[patch."https://github.com/oxidecomputer/hubris".userlib]
2439
path = "sys/userlib"
2540

app/oxide-rot-1/app-dev.toml

+14-26
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,6 @@ start = true
5353
[tasks.update_server]
5454
name = "lpc55-update-server"
5555
priority = 3
56-
max-sizes = {flash = 26080, ram = 17000, usbsram = 4096}
57-
# TODO: Size this appropriately
5856
stacksize = 8192
5957
start = true
6058
sections = {bootstate = "usbsram"}
@@ -82,7 +80,6 @@ task-slots = ["syscon_driver"]
8280
[tasks.sprot]
8381
name = "drv-lpc55-sprot-server"
8482
priority = 6
85-
max-sizes = {flash = 54016, ram = 32768}
8683
uses = ["flexcomm8", "bootrom"]
8784
features = ["spi0", "sp-ctrl"]
8885
start = true
@@ -103,20 +100,18 @@ pins = [
103100
{ name = "CHIP_SELECT", pin = { port = 1, pin = 1}, alt = 5},
104101
# ROT_IRQ = P0_18 = FUN0
105102
{ name = "ROT_IRQ", pin = { port = 0, pin = 18}, alt = 0, direction = "output"},
106-
# SP_RESET = P0_9 = FUN0
107-
{ name = "SP_RESET", pin = { port = 0, pin = 9}, alt = 0, direction = "input"},
108103
]
109104

110105
[tasks.swd]
111106
name = "drv-lpc55-swd"
112107
priority = 4
113-
max-sizes = {flash = 16384, ram = 4096}
114108
uses = ["flexcomm5", "iocon"]
115109
start = true
116-
stacksize = 1000
117-
task-slots = ["gpio_driver", "syscon_driver"]
118-
notifications = ["spi-irq", "timer"]
119-
interrupts = {"flexcomm5.irq" = "spi-irq"}
110+
stacksize = 1280
111+
task-slots = ["gpio_driver", "syscon_driver", "attest"]
112+
notifications = ["spi-irq", "timer", "sp_reset-irq", "jtag_detect-irq"]
113+
interrupts = {"flexcomm5.irq" = "spi-irq", "pint.irq0" = "sp_reset-irq", "pint.irq1" = "jtag_detect-irq" }
114+
features = ["enable_ext_sp_reset"]
120115

121116
[tasks.swd.config]
122117
# MOSI = PIO0_8
@@ -136,8 +131,10 @@ in_cfg = [
136131
pins = [
137132
# SCK
138133
{ pin = { port = 0, pin = 7 }, alt = 3 },
139-
{ name = "SP_TO_ROT_JTAG_DETECT_L", pin = { port = 0, pin = 20 }, alt = 0, direction = "input" },
140-
{ name = "ROT_TO_SP_RESET_L", pin = { port = 0, pin = 13 }, alt = 0, value = true, direction = "output", opendrain = "opendrain" },
134+
{ name = "SP_TO_ROT_JTAG_DETECT_L", pin = { port = 0, pin = 20 }, alt = 0, direction = "input", mode = "nopull", pint = 1 },
135+
# SP NRST has an internal 30-50k pull-up in SP
136+
{ name = "ROT_TO_SP_RESET_L_IN", pin = { port = 0, pin = 13 }, alt = 0, direction = "input", mode = "nopull", pint = 0 },
137+
{ name = "ROT_TO_SP_RESET_L_OUT", pin = { port = 0, pin = 13 }, alt = 0, direction = "output", mode = "nopull", opendrain = "opendrain", setup = false },
141138
]
142139
spi_num = 5
143140

@@ -149,26 +146,17 @@ start = true
149146
stacksize = 2600
150147
task-slots = ["swd"]
151148

152-
# We intentionally do not start this task to avoid conflicts with the SP
153-
# debug connection.
154-
[tasks.sp_measure]
155-
name = "task-sp-measure"
156-
priority = 6
157-
max-sizes = {flash = 131072, ram = 8192}
158-
task-slots = ["swd"]
159-
stacksize = 2048
160-
161-
[tasks.sp_measure.config]
162-
binary_path = "../../target/gimlet-c/dist/default/final.bin"
163-
164149
[tasks.attest]
165150
name = "task-attest"
166-
priority = 5
167-
max-sizes = {flash = 35072, ram = 16384}
151+
priority = 3
152+
max-sizes = {flash = 35400, ram = 16384}
168153
stacksize = 12304
169154
start = true
170155
extern-regions = ["dice_alias", "dice_certs"]
171156

157+
[tasks.attest.config]
158+
permit_log_reset = ["swd", "hiffy"]
159+
172160
[signing.certs]
173161
signing-certs = ["../../support/fake_certs/fake_certificate.der.crt"]
174162
root-certs = ["../../support/fake_certs/fake_certificate.der.crt"]

app/oxide-rot-1/app.toml

+12-10
Original file line numberDiff line numberDiff line change
@@ -88,20 +88,17 @@ pins = [
8888
{ name = "CHIP_SELECT", pin = { port = 1, pin = 1}, alt = 5},
8989
# ROT_IRQ = P0_18 = FUN0
9090
{ name = "ROT_IRQ", pin = { port = 0, pin = 18}, alt = 0, direction = "output"},
91-
# SP_RESET = P0_9 = FUN0
92-
{ name = "SP_RESET", pin = { port = 0, pin = 9}, alt = 0, direction = "input"},
9391
]
9492

9593
[tasks.swd]
9694
name = "drv-lpc55-swd"
9795
priority = 4
98-
max-sizes = {flash = 16384, ram = 4096}
9996
uses = ["flexcomm5", "iocon"]
10097
start = true
101-
stacksize = 1000
102-
task-slots = ["gpio_driver", "syscon_driver"]
103-
notifications = ["spi-irq", "timer"]
104-
interrupts = {"flexcomm5.irq" = "spi-irq"}
98+
stacksize = 1280
99+
task-slots = ["gpio_driver", "syscon_driver", "attest"]
100+
notifications = ["spi-irq", "timer", "sp_reset-irq", "jtag_detect-irq"]
101+
interrupts = {"flexcomm5.irq" = "spi-irq", "pint.irq0" = "sp_reset-irq", "pint.irq1" = "jtag_detect-irq" }
105102

106103
[tasks.swd.config]
107104
# MOSI = PIO0_8
@@ -121,8 +118,10 @@ in_cfg = [
121118
pins = [
122119
# SCK
123120
{ pin = { port = 0, pin = 7 }, alt = 3 },
124-
{ name = "SP_TO_ROT_JTAG_DETECT_L", pin = { port = 0, pin = 20 }, alt = 0, direction = "input" },
125-
{ name = "ROT_TO_SP_RESET_L", pin = { port = 0, pin = 13 }, alt = 0, value = true, direction = "output", opendrain = "opendrain" },
121+
{ name = "SP_TO_ROT_JTAG_DETECT_L", pin = { port = 0, pin = 20 }, alt = 0, direction = "input", mode = "nopull", pint = 1 },
122+
# SP NRST has an internal 30-50k pull-up in SP
123+
{ name = "ROT_TO_SP_RESET_L_IN", pin = { port = 0, pin = 13 }, alt = 0, direction = "input", mode = "nopull", pint = 0 },
124+
{ name = "ROT_TO_SP_RESET_L_OUT", pin = { port = 0, pin = 13 }, alt = 0, direction = "output", mode = "nopull", opendrain = "opendrain", setup = false },
126125
]
127126
spi_num = 5
128127

@@ -136,12 +135,15 @@ task-slots = ["swd"]
136135

137136
[tasks.attest]
138137
name = "task-attest"
139-
priority = 5
138+
priority = 3
140139
max-sizes = {flash = 35400, ram = 16384}
141140
stacksize = 12304
142141
start = true
143142
extern-regions = ["dice_alias", "dice_certs"]
144143

144+
[tasks.attest.config]
145+
permit_log_reset = ["swd"]
146+
145147
[signing.certs]
146148
signing-certs = ["../../support/fake_certs/fake_certificate.der.crt"]
147149
root-certs = ["../../support/fake_certs/fake_certificate.der.crt"]

drv/lpc55-swd/Cargo.toml

+11-1
Original file line numberDiff line numberDiff line change
@@ -10,24 +10,34 @@ idol-runtime = { workspace = true }
1010
lpc55-pac = { workspace = true }
1111
num-traits = { workspace = true }
1212
zerocopy = { workspace = true }
13+
bitflags = { workspace = true }
14+
static_assertions = { workspace = true }
1315

16+
attest-api = { path = "../../task/attest-api" }
1417
drv-lpc55-gpio-api = { path = "../lpc55-gpio-api" }
1518
drv-lpc55-spi = { path = "../lpc55-spi" }
1619
drv-lpc55-syscon-api = { path = "../lpc55-syscon-api" }
1720
drv-sp-ctrl-api = { path = "../sp-ctrl-api" }
1821
ringbuf = { path = "../../lib/ringbuf" }
1922
userlib = { path = "../../sys/userlib", features = ["panic-messages"] }
23+
endoscope-abi = { path = "../../lib/endoscope-abi" }
2024

2125
[build-dependencies]
26+
anyhow = { workspace = true }
2227
build-lpc55pins = { path = "../../build/lpc55pins" }
2328
build-util = { path = "../../build/util" }
24-
anyhow = { workspace = true }
29+
call_rustfmt = { path = "../../build/call_rustfmt" }
30+
endoscope-abi = { path = "../../lib/endoscope-abi" }
31+
endoscope = { path = "../../lib/endoscope", artifact="bin:endoscope", target = "thumbv7em-none-eabihf", features = ["soc_stm32h753"]}
32+
goblin = { workspace = true }
2533
idol = { workspace = true }
2634
quote = { workspace = true }
35+
rustc-demangle = { workspace = true }
2736
serde = { workspace = true }
2837

2938
[features]
3039
no-ipc-counters = ["idol/no-counters"]
40+
enable_ext_sp_reset = []
3141

3242
# This section is here to discourage RLS/rust-analyzer from doing test builds,
3343
# since test builds don't work for cross compilation.

0 commit comments

Comments
 (0)