9
9
#![ no_std]
10
10
#![ no_main]
11
11
12
- use core:: { cmp, usize} ;
12
+ mod config;
13
+
14
+ use config:: DataRegion ;
15
+ use core:: { cmp, slice, usize} ;
13
16
use drv_lpc55_syscon_api:: Syscon ;
14
17
use drv_rng_api:: RngError ;
18
+ use hubpack:: SerializedSize ;
15
19
use idol_runtime:: { ClientError , NotificationHandler , RequestError } ;
20
+ use lib_dice:: { RngData , RngSeed , SeedBuf } ;
16
21
use lib_lpc55_rng:: Lpc55Rng ;
17
22
use rand_chacha:: ChaCha20Rng ;
18
23
use rand_core:: { impls, Error , RngCore , SeedableRng } ;
24
+ use ringbuf:: { ringbuf, ringbuf_entry} ;
25
+ use serde:: Deserialize ;
19
26
use sha3:: {
20
27
digest:: crypto_common:: { generic_array:: GenericArray , OutputSizeUser } ,
21
28
digest:: FixedOutputReset ,
22
29
Digest , Sha3_256 ,
23
30
} ;
31
+ use stage0_handoff:: { HandoffData , HandoffDataLoadError } ;
24
32
use userlib:: * ;
25
33
use zeroize:: Zeroizing ;
26
34
35
+ // This file is generated by the crate build.rs. It contains instances of
36
+ // config::DataRegion structs describing regions of memory configured &
37
+ // exposed to this task by the hubris build.
38
+ mod build {
39
+ include ! ( concat!( env!( "OUT_DIR" ) , "/rng-config.rs" ) ) ;
40
+ }
41
+
42
+ use build:: RNG_DATA ;
43
+
27
44
task_slot ! ( SYSCON , syscon_driver) ;
28
45
46
+ #[ derive( Copy , Clone , PartialEq ) ]
47
+ enum Trace {
48
+ HandoffError ( HandoffDataLoadError ) ,
49
+ None ,
50
+ }
51
+
52
+ ringbuf ! ( Trace , 16 , Trace :: None ) ;
53
+
29
54
// low-budget rand::rngs::adapter::ReseedingRng w/o fork stuff
30
55
struct ReseedingRng < T : SeedableRng , R : RngCore , H : Digest > {
31
56
inner : T ,
@@ -42,19 +67,35 @@ where
42
67
H : FixedOutputReset + Default + Digest ,
43
68
[ u8 ; 32 ] : From < GenericArray < u8 , <H as OutputSizeUser >:: OutputSize > > ,
44
69
{
45
- fn new ( mut reseeder : R , threshold : usize ) -> Result < Self , Error > {
70
+ fn new (
71
+ seed : RngSeed ,
72
+ mut reseeder : R ,
73
+ threshold : usize ,
74
+ ) -> Result < Self , Error > {
46
75
let threshold = if threshold == 0 {
47
76
usize:: MAX
48
77
} else {
49
78
threshold
50
79
} ;
51
80
81
+ let mut mixer = H :: default ( ) ;
82
+ // mix platform unique seed drived by measured boot
83
+ Digest :: update ( & mut mixer, seed. as_bytes ( ) ) ;
84
+
85
+ // w/ 32 bytes from HRNG
86
+ let mut buf = Zeroizing :: new ( T :: Seed :: default ( ) ) ;
87
+ reseeder. try_fill_bytes ( buf. as_mut ( ) ) ?;
88
+ Digest :: update ( & mut mixer, buf. as_ref ( ) ) ;
89
+
90
+ // create initial instance of the SeedableRng from the seed
91
+ let inner = T :: from_seed ( mixer. finalize_fixed_reset ( ) . into ( ) ) ;
92
+
52
93
Ok ( ReseedingRng {
53
- inner : T :: from_rng ( & mut reseeder ) ? ,
94
+ inner,
54
95
reseeder,
55
96
threshold,
56
97
bytes_until_reseed : threshold,
57
- mixer : H :: default ( ) ,
98
+ mixer,
58
99
} )
59
100
}
60
101
}
@@ -116,8 +157,14 @@ where
116
157
struct Lpc55RngServer ( ReseedingRng < ChaCha20Rng , Lpc55Rng , Sha3_256 > ) ;
117
158
118
159
impl Lpc55RngServer {
119
- fn new ( reseeder : Lpc55Rng , threshold : usize ) -> Result < Self , Error > {
120
- Ok ( Lpc55RngServer ( ReseedingRng :: new ( reseeder, threshold) ?) )
160
+ fn new (
161
+ seed : RngSeed ,
162
+ reseeder : Lpc55Rng ,
163
+ threshold : usize ,
164
+ ) -> Result < Self , Error > {
165
+ Ok ( Lpc55RngServer ( ReseedingRng :: new (
166
+ seed, reseeder, threshold,
167
+ ) ?) )
121
168
}
122
169
}
123
170
@@ -156,12 +203,41 @@ impl NotificationHandler for Lpc55RngServer {
156
203
}
157
204
}
158
205
206
+ /// Load a type implementing HandoffData (and others) from a config::DataRegion.
207
+ /// Errors will be reported in the ringbuf and will return in None.
208
+ fn load_data_from_region <
209
+ T : for < ' a > Deserialize < ' a > + HandoffData + SerializedSize ,
210
+ > (
211
+ region : & DataRegion ,
212
+ ) -> Option < T > {
213
+ // Safety: This memory is setup by code executed before hubris and
214
+ // exposed using the kernel `extern-regions` mechanism. The safety of
215
+ // this code is an extension of our trust in the hubris kernel / build.
216
+ let data = unsafe {
217
+ slice:: from_raw_parts ( region. address as * mut u8 , region. size as usize )
218
+ } ;
219
+
220
+ // this can be replaced w/ .ok() if we get rid of the ringbuf entry
221
+ match T :: load_from_addr ( data) {
222
+ Ok ( d) => Some ( d) ,
223
+ Err ( e) => {
224
+ ringbuf_entry ! ( Trace :: HandoffError ( e) ) ;
225
+ None
226
+ }
227
+ }
228
+ }
229
+
159
230
#[ export_name = "main" ]
160
231
fn main ( ) -> ! {
232
+ let seed = {
233
+ load_data_from_region :: < RngData > ( & RNG_DATA )
234
+ . unwrap_lite ( )
235
+ . seed
236
+ } ;
161
237
let rng = Lpc55Rng :: new ( & Syscon :: from ( SYSCON . get_task_id ( ) ) ) ;
162
238
163
239
let threshold = 0x100000 ; // 1 MiB
164
- let mut rng = Lpc55RngServer :: new ( rng, threshold)
240
+ let mut rng = Lpc55RngServer :: new ( seed , rng, threshold)
165
241
. expect ( "Failed to create Lpc55RngServer" ) ;
166
242
let mut buffer = [ 0u8 ; idl:: INCOMING_SIZE ] ;
167
243
0 commit comments