1use core::cell::Cell;
31
32use kernel::grant::{AllowRoCount, AllowRwCount, Grant, UpcallCount};
33use kernel::hil::entropy;
34use kernel::hil::entropy::{Entropy32, Entropy8};
35use kernel::hil::rng;
36use kernel::hil::rng::{Client, Continue, Random, Rng};
37use kernel::processbuffer::WriteableProcessBuffer;
38use kernel::syscall::{CommandReturn, SyscallDriver};
39use kernel::utilities::cells::OptionalCell;
40use kernel::{ErrorCode, ProcessId};
41
42use crate::driver;
44pub const DRIVER_NUM: usize = driver::NUM::Rng as usize;
45
46mod rw_allow {
48 pub const BUFFER: usize = 0;
49 pub const COUNT: u8 = 1;
51}
52
53#[derive(Default)]
54pub struct App {
55 remaining: usize,
56 idx: usize,
57}
58
59pub struct RngDriver<'a, R: Rng<'a>> {
60 rng: &'a R,
61 apps: Grant<App, UpcallCount<1>, AllowRoCount<0>, AllowRwCount<{ rw_allow::COUNT }>>,
62 getting_randomness: Cell<bool>,
63}
64
65impl<'a, R: Rng<'a>> RngDriver<'a, R> {
66 pub fn new(
67 rng: &'a R,
68 grant: Grant<App, UpcallCount<1>, AllowRoCount<0>, AllowRwCount<{ rw_allow::COUNT }>>,
69 ) -> Self {
70 Self {
71 rng,
72 apps: grant,
73 getting_randomness: Cell::new(false),
74 }
75 }
76}
77
78impl<'a, R: Rng<'a>> rng::Client for RngDriver<'a, R> {
79 fn randomness_available(
80 &self,
81 randomness: &mut dyn Iterator<Item = u32>,
82 _error: Result<(), ErrorCode>,
83 ) -> rng::Continue {
84 let mut done = true;
85 for cntr in self.apps.iter() {
86 cntr.enter(|app, kernel_data| {
87 if app.remaining > 0 {
89 let (oldidx, oldremaining) = (app.idx, app.remaining);
91
92 let (newidx, newremaining) = kernel_data
93 .get_readwrite_processbuffer(rw_allow::BUFFER)
94 .and_then(|buffer| {
95 buffer.mut_enter(|buffer| {
96 let mut idx = oldidx;
97 let mut remaining = oldremaining;
98
99 if buffer.len() < idx {
102 return (0, 0);
106 } else if buffer.len() < idx + remaining {
107 remaining = buffer.len() - idx;
108 }
109
110 let buf = &buffer[idx..(idx + remaining)];
114 let remaining_ints = if remaining % 4 == 0 {
117 remaining / 4
118 } else {
119 remaining / 4 + 1
120 };
121
122 for (inp, outs) in
125 randomness.take(remaining_ints).zip(buf.chunks(4))
126 {
127 let inbytes = u32::to_le_bytes(inp);
130 outs.iter().zip(inbytes.iter()).for_each(|(out, inb)| {
131 out.set(*inb);
132 remaining -= 1;
133 idx += 1;
134 });
135 }
136
137 (idx, remaining)
138 })
139 })
140 .unwrap_or(
141 (0, 0),
146 );
147
148 app.idx = newidx;
150 app.remaining = newremaining;
151
152 if app.remaining > 0 {
153 done = false;
154 } else {
155 kernel_data.schedule_upcall(0, (0, newidx, 0)).ok();
156 }
157 }
158 });
159
160 if !done {
164 break;
165 }
166 }
167
168 if done {
169 self.getting_randomness.set(false);
170 rng::Continue::Done
171 } else {
172 rng::Continue::More
173 }
174 }
175}
176
177impl<'a, R: Rng<'a>> SyscallDriver for RngDriver<'a, R> {
178 fn command(
179 &self,
180 command_num: usize,
181 data: usize,
182 _: usize,
183 processid: ProcessId,
184 ) -> CommandReturn {
185 match command_num {
186 0 => CommandReturn::success(),
188
189 1 => {
191 let mut needs_get = false;
192 let result = self
193 .apps
194 .enter(processid, |app, _| {
195 app.remaining = data;
196 app.idx = 0;
197
198 if !self.getting_randomness.get() {
202 self.getting_randomness.set(true);
203 needs_get = true;
204 }
205
206 CommandReturn::success()
207 })
208 .unwrap_or_else(|err| CommandReturn::failure(err.into()));
209 if needs_get {
210 let _ = self.rng.get();
211 }
212 result
213 }
214 _ => CommandReturn::failure(ErrorCode::NOSUPPORT),
215 }
216 }
217
218 fn allocate_grant(&self, processid: ProcessId) -> Result<(), kernel::process::Error> {
219 self.apps.enter(processid, |_, _| {})
220 }
221}
222
223pub struct Entropy32ToRandom<'a, E: Entropy32<'a>> {
224 egen: &'a E,
225 client: OptionalCell<&'a dyn rng::Client>,
226}
227
228impl<'a, E: Entropy32<'a>> Entropy32ToRandom<'a, E> {
229 pub fn new(egen: &'a E) -> Self {
230 Self {
231 egen,
232 client: OptionalCell::empty(),
233 }
234 }
235}
236
237impl<'a, E: Entropy32<'a>> Rng<'a> for Entropy32ToRandom<'a, E> {
238 fn get(&self) -> Result<(), ErrorCode> {
239 self.egen.get()
240 }
241
242 fn cancel(&self) -> Result<(), ErrorCode> {
243 self.egen.cancel()
244 }
245
246 fn set_client(&'a self, client: &'a dyn rng::Client) {
247 self.egen.set_client(self);
248 self.client.set(client);
249 }
250}
251
252impl<'a, E: Entropy32<'a>> entropy::Client32 for Entropy32ToRandom<'a, E> {
253 fn entropy_available(
254 &self,
255 entropy: &mut dyn Iterator<Item = u32>,
256 error: Result<(), ErrorCode>,
257 ) -> entropy::Continue {
258 self.client.map_or(entropy::Continue::Done, |client| {
259 if error != Ok(()) {
260 match client.randomness_available(&mut Entropy32ToRandomIter(entropy), error) {
261 rng::Continue::More => entropy::Continue::More,
262 rng::Continue::Done => entropy::Continue::Done,
263 }
264 } else {
265 match client.randomness_available(&mut Entropy32ToRandomIter(entropy), Ok(())) {
266 rng::Continue::More => entropy::Continue::More,
267 rng::Continue::Done => entropy::Continue::Done,
268 }
269 }
270 })
271 }
272}
273
274struct Entropy32ToRandomIter<'a>(&'a mut dyn Iterator<Item = u32>);
275
276impl Iterator for Entropy32ToRandomIter<'_> {
277 type Item = u32;
278
279 fn next(&mut self) -> Option<u32> {
280 self.0.next()
281 }
282}
283
284pub struct Entropy8To32<'a, E: Entropy8<'a>> {
285 egen: &'a E,
286 client: OptionalCell<&'a dyn entropy::Client32>,
287 count: Cell<usize>,
288 bytes: Cell<u32>,
289}
290
291impl<'a, E: Entropy8<'a>> Entropy8To32<'a, E> {
292 pub fn new(egen: &'a E) -> Self {
293 Self {
294 egen,
295 client: OptionalCell::empty(),
296 count: Cell::new(0),
297 bytes: Cell::new(0),
298 }
299 }
300}
301
302impl<'a, E: Entropy8<'a>> Entropy32<'a> for Entropy8To32<'a, E> {
303 fn get(&self) -> Result<(), ErrorCode> {
304 self.egen.get()
305 }
306
307 fn cancel(&self) -> Result<(), ErrorCode> {
316 self.egen.cancel()
317 }
318
319 fn set_client(&'a self, client: &'a dyn entropy::Client32) {
320 self.egen.set_client(self);
321 self.client.set(client);
322 }
323}
324
325impl<'a, E: Entropy8<'a>> entropy::Client8 for Entropy8To32<'a, E> {
326 fn entropy_available(
327 &self,
328 entropy: &mut dyn Iterator<Item = u8>,
329 error: Result<(), ErrorCode>,
330 ) -> entropy::Continue {
331 self.client.map_or(entropy::Continue::Done, |client| {
332 if error != Ok(()) {
333 client.entropy_available(&mut Entropy8To32Iter(self), error)
334 } else {
335 let mut count = self.count.get();
336 while count < 4 {
341 let byte = entropy.next();
342 match byte {
343 None => {
344 return entropy::Continue::More;
345 }
346 Some(val) => {
347 let current = self.bytes.get();
348 let bits = val as u32;
349 let result = current | (bits << (8 * count));
350 count += 1;
351 self.count.set(count);
352 self.bytes.set(result)
353 }
354 }
355 }
356 let rval = client.entropy_available(&mut Entropy8To32Iter(self), Ok(()));
357 self.bytes.set(0);
358 rval
359 }
360 })
361 }
362}
363
364struct Entropy8To32Iter<'a, 'b: 'a, E: Entropy8<'b>>(&'a Entropy8To32<'b, E>);
365
366impl<'a, 'b: 'a, E: Entropy8<'b>> Iterator for Entropy8To32Iter<'a, 'b, E> {
367 type Item = u32;
368
369 fn next(&mut self) -> Option<u32> {
370 let count = self.0.count.get();
371 if count == 4 {
372 self.0.count.set(0);
373 Some(self.0.bytes.get())
374 } else {
375 None
376 }
377 }
378}
379
380pub struct Entropy32To8<'a, E: Entropy32<'a>> {
381 egen: &'a E,
382 client: OptionalCell<&'a dyn entropy::Client8>,
383 entropy: Cell<u32>,
384 bytes_consumed: Cell<usize>,
385}
386
387impl<'a, E: Entropy32<'a>> Entropy32To8<'a, E> {
388 pub fn new(egen: &'a E) -> Self {
389 Self {
390 egen,
391 client: OptionalCell::empty(),
392 entropy: Cell::new(0),
393 bytes_consumed: Cell::new(0),
394 }
395 }
396}
397
398impl<'a, E: Entropy32<'a>> Entropy8<'a> for Entropy32To8<'a, E> {
399 fn get(&self) -> Result<(), ErrorCode> {
400 self.egen.get()
401 }
402
403 fn cancel(&self) -> Result<(), ErrorCode> {
412 self.egen.cancel()
413 }
414
415 fn set_client(&'a self, client: &'a dyn entropy::Client8) {
416 self.egen.set_client(self);
417 self.client.set(client);
418 }
419}
420
421impl<'a, E: Entropy32<'a>> entropy::Client32 for Entropy32To8<'a, E> {
422 fn entropy_available(
423 &self,
424 entropy: &mut dyn Iterator<Item = u32>,
425 error: Result<(), ErrorCode>,
426 ) -> entropy::Continue {
427 self.client.map_or(entropy::Continue::Done, |client| {
428 if error != Ok(()) {
429 client.entropy_available(&mut Entropy32To8Iter::<E>(self), error)
430 } else {
431 let r = entropy.next();
432 match r {
433 None => return entropy::Continue::More,
434 Some(val) => {
435 self.entropy.set(val);
436 self.bytes_consumed.set(0);
437 }
438 }
439 client.entropy_available(&mut Entropy32To8Iter(self), Ok(()))
440 }
441 })
442 }
443}
444
445struct Entropy32To8Iter<'a, 'b: 'a, E: Entropy32<'b>>(&'a Entropy32To8<'b, E>);
446
447impl<'a, 'b: 'a, E: Entropy32<'b>> Iterator for Entropy32To8Iter<'a, 'b, E> {
448 type Item = u8;
449
450 fn next(&mut self) -> Option<u8> {
451 let bytes_consumed = self.0.bytes_consumed.get();
452 if bytes_consumed < 4 {
453 let entropy = self.0.entropy.get();
456 let byte = (entropy & 0xff) as u8;
457 self.0.entropy.set(entropy >> 8);
458 self.0.bytes_consumed.set(bytes_consumed + 1);
459 Some(byte)
460 } else {
461 None
462 }
463 }
464}
465
466pub struct SynchronousRandom<'a, R: Rng<'a>> {
467 rgen: &'a R,
468 seed: Cell<u32>,
469}
470
471#[allow(dead_code)]
472impl<'a, R: Rng<'a>> SynchronousRandom<'a, R> {
473 fn new(rgen: &'a R) -> Self {
474 Self {
475 rgen,
476 seed: Cell::new(0),
477 }
478 }
479}
480
481impl<'a, R: Rng<'a>> Random<'a> for SynchronousRandom<'a, R> {
482 fn initialize(&'a self) {
483 self.rgen.set_client(self);
484 let _ = self.rgen.get();
485 }
486
487 fn reseed(&self, seed: u32) {
488 self.seed.set(seed);
489 }
490
491 fn random(&self) -> u32 {
497 const LCG_MULTIPLIER: u32 = 1_644_525;
498 const LCG_INCREMENT: u32 = 1_013_904_223;
499 let val = self.seed.get();
500 let val = val.wrapping_mul(LCG_MULTIPLIER);
501 let val = val.wrapping_add(LCG_INCREMENT);
502 self.seed.set(val);
503 val
504 }
505}
506
507impl<'a, R: Rng<'a>> Client for SynchronousRandom<'a, R> {
508 fn randomness_available(
509 &self,
510 randomness: &mut dyn Iterator<Item = u32>,
511 _error: Result<(), ErrorCode>,
512 ) -> Continue {
513 match randomness.next() {
514 None => Continue::More,
515 Some(val) => {
516 self.seed.set(val);
517 Continue::Done
518 }
519 }
520 }
521}