forked from lowRISC/opentitan
-
Notifications
You must be signed in to change notification settings - Fork 0
/
rom_ctrl.hjson
320 lines (311 loc) · 9.99 KB
/
rom_ctrl.hjson
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
{
name: "rom_ctrl",
human_name: "ROM Controller",
one_line_desc: "Interfaces scrambled boot ROM with system bus and KMAC for initial health check after reset",
one_paragraph_desc: '''
ROM Controller interfaces between the system bus and the scrambled ROM.
It is responsible for descrambling on memory fetches.
It also has a checker block that interfaces KMAC Accelerator to perform a cryptographic hash of the ROM contents at boot to detect any malicious changes to the ROM itself while in reset.
ROM Controller also has status registers for ROM integrity errors or checker block FSM glitches.
'''
design_spec: "../doc",
dv_doc: "../doc/dv",
hw_checklist: "../doc/checklist",
sw_checklist: "/sw/device/lib/dif/dif_rom_ctrl",
revisions: [
{
version: "1.0",
life_stage: "L1",
design_stage: "D3",
verification_stage: "V2S",
dif_stage: "S2",
},
]
clocking: [{clock: "clk_i", reset: "rst_ni"}],
regwidth: "32"
bus_interfaces: [
{ protocol: "tlul", direction: "device", name: "regs" }
{ protocol: "tlul", direction: "device", name: "rom" },
],
param_list: [
{ name: "BootRomInitFile",
type: "",
default: '""',
desc: "Contents of ROM"
local: "false",
expose: "true"
}
{ name: "RndCnstScrNonce",
type: "bit [63:0]",
desc: "Fixed nonce used for address / data scrambling"
randcount: "64",
randtype: "data"
}
{ name: "RndCnstScrKey",
type: "bit [127:0]",
desc: "Randomised constant used as a scrambling key for ROM data"
randcount: "128",
randtype: "data"
}
{ name: "SecDisableScrambling",
type: "bit",
desc: '''
Disable scrambling and checking in rom_ctrl, turning the block into a
simple ROM wrapper. This isn't intended for real chips, but is useful
for small FPGA targets where there's not space for the PRINCE
primitives.
'''
local: "false",
expose: "true",
default: "1'b0"
}
]
alert_list: [
{ name: "fatal"
desc: "A fatal error. Fatal alerts are non-recoverable and will be asserted until a hard reset."
}
],
inter_signal_list: [
// Interface to memory configuration
{ name: "rom_cfg",
package: "prim_rom_pkg",
struct: "rom_cfg",
act: "rcv"
type: "uni",
},
// Power manager interface
{ name: "pwrmgr_data"
package: "rom_ctrl_pkg"
struct: "pwrmgr_data"
act: "req"
type: "uni"
},
// Keymgr interface
{ name: "keymgr_data"
package: "rom_ctrl_pkg"
struct: "keymgr_data"
act: "req"
type: "uni"
},
// KMAC interface
{ name: "kmac_data"
package: "kmac_pkg"
struct: "app"
act: "req"
type: "req_rsp"
},
],
countermeasures: [
{
name: "CHECKER.CTR.CONSISTENCY",
desc: '''
Once rom_ctrl has handed control of the mux to the bus, the internal
FSM counter should point at the top of ROM (where we ensure the word
has invalid ECC bits). The unexpected_counter_change signal in
rom_ctrl_fsm goes high and generates a fatal alert if that counter is
perturbed in any way.
'''
},
{
name: "CHECKER.CTRL_FLOW.CONSISTENCY",
desc: '''
The main checker FSM steps on internal 'done' signals, coming
from its address counter, the KMAC response and its comparison
counter. If any of these are asserted at times we don't
expect, the FSM jumps to an invalid state. This triggers an
alert and will not set the external 'done' signal for pwrmgr
to continue boot.
'''
},
{
name: "CHECKER.FSM.LOCAL_ESC",
desc: '''
The main checker FSM moves to an invalid state on local escalation.
'''
},
{
name: "COMPARE.CTRL_FLOW.CONSISTENCY",
desc: '''
The hash comparison module triggers a fatal error if the checker FSM
triggers a second comparison after a reset. This is handled by the
start_alert signal in the rom_ctrl_compare module and could be
triggered if the checker FSM was somehow glitched to jump backwards.
'''
},
{
name: "COMPARE.CTR.CONSISTENCY",
desc: '''
The hash comparison module has an internal count (indexing 32-bit words
in the 256-bit digests). If this glitches to a nonzero value before the
comparison starts or to a value other than the last index after the
comparison ends then an fatal alert is generated. This is handled by
the wait_addr_alert and done_addr_alert signals in rom_ctrl_compare.
'''
},
{
name: "COMPARE.CTR.REDUN",
desc: '''
The hash comparison module has an internal count (indexing 32-bit words
in the 256-bit digests) implemented using a redundant counter module.
In case a mismatch is detected between the redundant counters a fatal
alert is generated.
'''
},
{
name: "FSM.SPARSE",
desc: '''
FSMs are sparsely encoded. There are two FSMs. The first is in
rom_ctrl_fsm. The second, simpler FSM is in rom_ctrl_compare.
'''
},
{
name: "MEM.SCRAMBLE",
desc: "The ROM is scrambled."
},
{
name: "MEM.DIGEST",
desc: "A cSHAKE digest is computed of the ROM contents."
},
{
name: "INTERSIG.MUBI",
desc: '''
Checker FSM 'done' signal is multi-bit encoded when passed to pwrmgr.
This signal is derived from the (multi-bit) sparse FSM state in the
rom_ctrl_fsm module.
'''
},
{
name: "BUS.INTEGRITY",
desc: '''
TL bus control and data signals are integrity protected (using the system-wide end-to-end
integrity scheme).
'''
},
{ name: "BUS.LOCAL_ESC",
desc: '''
To avoid responding to a request with erroneous data, even though an
alert went out, the bus_rom_rvalid signal used to signal a response to
the ROM-side TL bus can only be high if no internal consistency error
has been spotted.
'''
}
{
name: "MUX.MUBI",
desc: '''
The mux that arbitrates between the checker and the bus is multi-bit
encoded. An invalid value generates a fatal alert with the sel_invalid
signal in the rom_ctrl_mux module.
'''
},
{
name: "MUX.CONSISTENCY",
desc: '''
The mux that arbitrates between the checker and the bus gives access to
the checker at the start of time and then switches to the bus, never
going back. If a glitch does cause it to switch back, a fatal alert is
generated with the sel_reverted or sel_q_reverted signals in the
rom_ctrl_mux module.
'''
},
{
name: "CTRL.REDUN",
desc: '''
Addresses from TL accesses are passed redundantly to the scrambled ROM
module, to ensure the address lines are not independently faultable
downstream of the bus integrity ECC check. See the bus_rom_prince_index
and bus_rom_rom_index signals in the rom_ctrl module.
'''
},
{
name: "CTRL.MEM.INTEGRITY"
desc: "End-to-end data/memory integrity scheme."
},
{ name: "TLUL_FIFO.CTR.REDUN",
desc: "The TL-UL response FIFO pointers are implemented with duplicate counters."
}
]
regwidth: "32"
registers: {
regs: [
{ name: "FATAL_ALERT_CAUSE",
desc: '''
The cause of a fatal alert.
The bits of this register correspond to errors that can cause a fatal
alert. Software can read these bits to see what went wrong. Once set,
these bits cannot be cleared.
'''
swaccess: "ro",
hwaccess: "hwo",
fields: [
{ bits: "0",
name: "checker_error",
resval: 0,
desc: "Set on a fatal error detected by the ROM checker."
}
{ bits: "1",
name: "integrity_error",
resval: 0,
desc: "Set on an integrity error from the register interface."
}
]
}
{
multireg: {
cname: "ROM_CTRL",
name: "DIGEST",
desc: "The digest computed from the contents of ROM"
count: "8"
swaccess: "ro"
hwaccess: "hrw"
fields: [
{
bits: "31:0"
name: "DIGEST"
desc: "32 bits of the digest"
}
]
// Disable CSR checks for digest registers, since their values will
// change under the feet of the CSR package as the ROM checker computes
// a digest. These values are checked instead by the rom_ctrl TB.
tags: ["excl:CsrAllTests:CsrExclCheck"]
}
}
{
multireg: {
cname: "ROM_CTRL",
name: "EXP_DIGEST",
desc: "The expected digest, stored in the top words of ROM"
count: "8"
swaccess: "ro"
hwaccess: "hrw"
fields: [
{
bits: "31:0"
name: "DIGEST"
desc: "32 bits of the digest"
}
]
// As with DIGEST, these values are checked by the rom_ctrl TB.
tags: ["excl:CsrAllTests:CsrExclCheck"]
}
}
],
rom: [
// ROM size (given as `items` below) must be a power of two.
//
// NOTE: This number is replicated in ../util/scramble_image.py: keep the
// two in sync.
{ window: {
name: "ROM"
items: "8192" // 32 KiB
swaccess: "ro",
data-intg-passthru: "true",
desc: '''ROM data'''
}
}
]
}
}