oasis_runtime_sdk/crypto/
random.rs1use std::cell::RefCell;
3
4use anyhow::anyhow;
5use merlin::{Transcript, TranscriptRng};
6use rand_core::{CryptoRng, OsRng, RngCore};
7use schnorrkel::keys::{ExpansionMode, Keypair, MiniSecretKey};
8
9use oasis_core_runtime::common::crypto::hash::Hash;
10
11use crate::{
12 context::Context, dispatcher, keymanager::KeyManagerError, modules::core::Error, state::Mode,
13};
14
15const RNG_CONTEXT: &[u8] = b"oasis-runtime-sdk/crypto: rng v1";
17const VRF_KEY_CONTEXT: &[u8] = b"oasis-runtime-sdk/crypto: root vrf key v1";
19
20pub struct RootRng {
22 inner: RefCell<Inner>,
23 mode: Mode,
24 valid: bool,
25}
26
27struct Inner {
28 transcript: Transcript,
30 rng: Option<TranscriptRng>,
32}
33
34impl RootRng {
35 pub fn new(mode: Mode) -> Self {
37 Self {
38 inner: RefCell::new(Inner {
39 transcript: Transcript::new(RNG_CONTEXT),
40 rng: None,
41 }),
42 mode,
43 valid: true,
44 }
45 }
46
47 pub fn invalid() -> Self {
49 Self {
50 inner: RefCell::new(Inner {
51 transcript: Transcript::new(&[]),
52 rng: None,
53 }),
54 mode: Mode::Simulate, valid: false,
56 }
57 }
58
59 fn derive_root_vrf_key<C: Context + ?Sized>(ctx: &C, mode: Mode) -> Result<Keypair, Error> {
60 let km = ctx
61 .key_manager()
62 .ok_or(Error::Abort(dispatcher::Error::KeyManagerFailure(
63 KeyManagerError::NotInitialized,
64 )))?;
65 let round_header_hash = ctx.runtime_header().encoded_hash();
66 let key_id = crate::keymanager::get_key_pair_id([
67 VRF_KEY_CONTEXT,
68 &[mode as u8],
69 round_header_hash.as_ref(),
70 ]);
71 let km_kp = km
72 .get_or_create_ephemeral_keys(key_id, ctx.epoch())
73 .map_err(|err| Error::Abort(dispatcher::Error::KeyManagerFailure(err)))?
74 .input_keypair;
75 let kp = MiniSecretKey::from_bytes(km_kp.sk.0.as_ref())
78 .map_err(|err| {
79 Error::Abort(dispatcher::Error::KeyManagerFailure(
80 KeyManagerError::Other(anyhow::anyhow!("{}", err)),
81 ))
82 })?
83 .expand_to_keypair(ExpansionMode::Uniform);
84
85 Ok(kp)
86 }
87
88 pub fn append_local_entropy(&self) {
94 if !self.valid {
95 return;
96 }
97
98 let mut bytes = [0u8; 32];
99 OsRng.fill_bytes(&mut bytes);
100
101 let mut inner = self.inner.borrow_mut();
102 inner.transcript.append_message(b"local-rng", &bytes);
103 }
104
105 pub fn append_tx(&self, tx_hash: Hash) {
107 if !self.valid {
108 return;
109 }
110
111 let mut inner = self.inner.borrow_mut();
112 inner.transcript.append_message(b"tx", tx_hash.as_ref());
113 }
114
115 pub fn append_subcontext(&self) {
117 if !self.valid {
118 return;
119 }
120
121 let mut inner = self.inner.borrow_mut();
122 inner.transcript.append_message(b"subctx", &[]);
123 }
124
125 pub fn fork<C: Context + ?Sized>(&self, ctx: &C, pers: &[u8]) -> Result<LeafRng, Error> {
127 if !self.valid {
128 return Err(Error::InvalidArgument(anyhow!("rng is not available")));
129 }
130
131 let mut inner = self.inner.borrow_mut();
132
133 if inner.rng.is_none() {
135 let root_vrf_key = Self::derive_root_vrf_key(ctx, self.mode)?;
137
138 let rng = root_vrf_key
140 .vrf_create_hash(&mut inner.transcript)
141 .make_merlin_rng(&[]);
142 inner.rng = Some(rng);
143 }
144
145 inner.transcript.append_message(b"fork", pers);
147
148 let rng_builder = inner.transcript.build_rng();
149 let parent_rng = inner.rng.as_mut().expect("rng must be initialized");
150 let rng = rng_builder.finalize(parent_rng);
151
152 Ok(LeafRng(rng))
153 }
154}
155
156pub struct LeafRng(TranscriptRng);
158
159impl RngCore for LeafRng {
160 fn next_u32(&mut self) -> u32 {
161 self.0.next_u32()
162 }
163
164 fn next_u64(&mut self) -> u64 {
165 self.0.next_u64()
166 }
167
168 fn fill_bytes(&mut self, dest: &mut [u8]) {
169 self.0.fill_bytes(dest)
170 }
171
172 fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand_core::Error> {
173 self.0.try_fill_bytes(dest)
174 }
175}
176
177impl CryptoRng for LeafRng {}
178
179#[cfg(test)]
180mod test {
181 use super::*;
182
183 use crate::{state::Mode, testing::mock};
184
185 #[test]
186 fn test_rng_basic() {
187 let mut mock = mock::Mock::default();
188 let ctx = mock.create_ctx_for_runtime::<mock::EmptyRuntime>(true);
189
190 let root_rng = RootRng::new(Mode::Execute);
192
193 let mut leaf_rng = root_rng.fork(&ctx, &[]).expect("rng fork should work");
194 let mut bytes1 = [0u8; 32];
195 leaf_rng.fill_bytes(&mut bytes1);
196
197 let mut leaf_rng = root_rng.fork(&ctx, &[]).expect("rng fork should work");
198 let mut bytes1_1 = [0u8; 32];
199 leaf_rng.fill_bytes(&mut bytes1_1);
200
201 assert_ne!(bytes1, bytes1_1, "rng should apply domain separation");
202
203 let root_rng = RootRng::new(Mode::Execute);
205
206 let mut leaf_rng = root_rng.fork(&ctx, &[]).expect("rng fork should work");
207 let mut bytes2 = [0u8; 32];
208 leaf_rng.fill_bytes(&mut bytes2);
209
210 assert_eq!(bytes1, bytes2, "rng should be deterministic");
211
212 let mut leaf_rng = root_rng.fork(&ctx, &[]).expect("rng fork should work");
213 let mut bytes2_1 = [0u8; 32];
214 leaf_rng.fill_bytes(&mut bytes2_1);
215
216 assert_ne!(bytes2, bytes2_1, "rng should apply domain separation");
217 assert_eq!(bytes1_1, bytes2_1, "rng should be deterministic");
218
219 let root_rng = RootRng::new(Mode::Execute);
221
222 let mut leaf_rng = root_rng
223 .fork(&ctx, b"domsep")
224 .expect("rng fork should work");
225 let mut bytes3 = [0u8; 32];
226 leaf_rng.fill_bytes(&mut bytes3);
227
228 assert_ne!(bytes2, bytes3, "rng should apply domain separation");
229
230 let root_rng = RootRng::new(Mode::Execute);
232 root_rng
233 .append_tx("0000000000000000000000000000000000000000000000000000000000000001".into());
234
235 let mut leaf_rng = root_rng.fork(&ctx, &[]).expect("rng fork should work");
236 let mut bytes4 = [0u8; 32];
237 leaf_rng.fill_bytes(&mut bytes4);
238
239 assert_ne!(bytes2, bytes4, "rng should apply domain separation");
240
241 let root_rng = RootRng::new(Mode::Execute);
243 root_rng
244 .append_tx("0000000000000000000000000000000000000000000000000000000000000002".into());
245
246 let mut leaf_rng = root_rng.fork(&ctx, &[]).expect("rng fork should work");
247 let mut bytes5 = [0u8; 32];
248 leaf_rng.fill_bytes(&mut bytes5);
249
250 assert_ne!(bytes4, bytes5, "rng should apply domain separation");
251
252 let root_rng = RootRng::new(Mode::Execute);
254 root_rng
255 .append_tx("0000000000000000000000000000000000000000000000000000000000000001".into());
256
257 let mut leaf_rng = root_rng.fork(&ctx, &[]).expect("rng fork should work");
258 let mut bytes6 = [0u8; 32];
259 leaf_rng.fill_bytes(&mut bytes6);
260
261 assert_eq!(bytes4, bytes6, "rng should be deterministic");
262
263 let root_rng = RootRng::new(Mode::Execute);
265 root_rng
266 .append_tx("0000000000000000000000000000000000000000000000000000000000000001".into());
267 root_rng
268 .append_tx("0000000000000000000000000000000000000000000000000000000000000002".into());
269
270 let mut leaf_rng = root_rng.fork(&ctx, &[]).expect("rng fork should work");
271 let mut bytes7 = [0u8; 32];
272 leaf_rng.fill_bytes(&mut bytes7);
273
274 assert_ne!(bytes4, bytes7, "rng should apply domain separation");
275
276 let root_rng = RootRng::new(Mode::Execute);
278 root_rng
279 .append_tx("0000000000000000000000000000000000000000000000000000000000000001".into());
280 let _ = root_rng.fork(&ctx, &[]).expect("rng fork should work"); root_rng
282 .append_tx("0000000000000000000000000000000000000000000000000000000000000002".into());
283
284 let mut leaf_rng = root_rng.fork(&ctx, &[]).expect("rng fork should work");
285 let mut bytes8 = [0u8; 32];
286 leaf_rng.fill_bytes(&mut bytes8);
287
288 assert_ne!(bytes7, bytes8, "rng should apply domain separation");
289 assert_ne!(bytes6, bytes8, "rng should apply domain separation");
290 }
291
292 #[test]
293 fn test_rng_fail_nonconfidential() {
294 let mut mock = mock::Mock::default();
295 let ctx = mock.create_ctx_for_runtime::<mock::EmptyRuntime>(false);
296
297 let root_rng = RootRng::new(Mode::Execute);
298 assert!(
299 root_rng.fork(&ctx, &[]).is_err(),
300 "rng fork should fail on non-confidential runtimes"
301 );
302 }
303
304 #[test]
305 fn test_rng_local_entropy() {
306 let mut mock = mock::Mock::default();
307 let ctx = mock.create_ctx_for_runtime::<mock::EmptyRuntime>(true);
308
309 let root_rng = RootRng::new(Mode::Execute);
311
312 let mut leaf_rng = root_rng.fork(&ctx, &[]).expect("rng fork should work");
313 let mut bytes1 = [0u8; 32];
314 leaf_rng.fill_bytes(&mut bytes1);
315
316 let root_rng = RootRng::new(Mode::Execute);
318 root_rng.append_local_entropy();
319
320 let mut leaf_rng = root_rng.fork(&ctx, &[]).expect("rng fork should work");
321 let mut bytes2 = [0u8; 32];
322 leaf_rng.fill_bytes(&mut bytes2);
323
324 assert_ne!(bytes1, bytes2, "rng should apply domain separation");
325 }
326
327 #[test]
328 fn test_rng_parent_fork_propagation() {
329 let mut mock = mock::Mock::default();
330 let ctx = mock.create_ctx_for_runtime::<mock::EmptyRuntime>(true);
331
332 let root_rng = RootRng::new(Mode::Execute);
334
335 let mut leaf_rng = root_rng.fork(&ctx, b"a").expect("rng fork should work");
336 let mut bytes1 = [0u8; 32];
337 leaf_rng.fill_bytes(&mut bytes1);
338
339 let mut leaf_rng = root_rng.fork(&ctx, b"a").expect("rng fork should work");
340 let mut bytes1_1 = [0u8; 32];
341 leaf_rng.fill_bytes(&mut bytes1_1);
342
343 let root_rng = RootRng::new(Mode::Execute);
345
346 let mut leaf_rng = root_rng.fork(&ctx, b"b").expect("rng fork should work");
347 let mut bytes2 = [0u8; 32];
348 leaf_rng.fill_bytes(&mut bytes2);
349
350 let mut leaf_rng = root_rng.fork(&ctx, b"a").expect("rng fork should work");
351 let mut bytes2_1 = [0u8; 32];
352 leaf_rng.fill_bytes(&mut bytes2_1);
353
354 assert_ne!(
355 bytes1_1, bytes2_1,
356 "forks should propagate domain separator to parent"
357 );
358 }
359
360 #[test]
361 fn test_rng_invalid() {
362 let mut mock = mock::Mock::default();
363 let ctx = mock.create_ctx_for_runtime::<mock::EmptyRuntime>(true);
364
365 let root_rng = RootRng::invalid();
366 assert!(
367 root_rng.fork(&ctx, b"a").is_err(),
368 "rng fork should fail for invalid rng"
369 );
370 }
371}