aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFelipe Balbi <[email protected]>2025-12-11 09:44:35 -0800
committerFelipe Balbi <[email protected]>2025-12-11 09:48:15 -0800
commitaf02ef481498441289a6decfe3baf7f3878f7871 (patch)
tree6e6a8e5d5bc030619b572d98069fd2fd56c4855b
parentb99a7213126db708553143bb18e64bdcb76bb447 (diff)
trng: Add dedicated constructors without configuration
These three constructors guarantee TRNG will work for the requested amount of entropy samples.
-rw-r--r--embassy-mcxa/src/trng.rs214
-rw-r--r--examples/mcxa/src/bin/trng.rs22
2 files changed, 197 insertions, 39 deletions
diff --git a/embassy-mcxa/src/trng.rs b/embassy-mcxa/src/trng.rs
index 65f06a1d8..ed11019cd 100644
--- a/embassy-mcxa/src/trng.rs
+++ b/embassy-mcxa/src/trng.rs
@@ -1,7 +1,7 @@
1//! True Random Number Generator 1//! True Random Number Generator
2 2
3use embassy_hal_internal::Peri;
4use embassy_hal_internal::interrupt::InterruptExt; 3use embassy_hal_internal::interrupt::InterruptExt;
4use embassy_hal_internal::Peri;
5use maitake_sync::WaitCell; 5use maitake_sync::WaitCell;
6use mcxa_pac::trng0::osc2_ctl::TrngEntCtl; 6use mcxa_pac::trng0::osc2_ctl::TrngEntCtl;
7 7
@@ -19,8 +19,63 @@ pub struct Trng<'d> {
19} 19}
20 20
21impl<'d> Trng<'d> { 21impl<'d> Trng<'d> {
22 /// Instantiates a new TRNG peripheral driver with 128 samples of entropy.
23 pub fn new_128(_peri: Peri<'d, TRNG0>) -> Self {
24 Self::new_inner(
25 _peri,
26 Config {
27 sample_size: 128,
28 retry_count: 1,
29 long_run_limit_max: 29,
30 monobit_limit_max: 94,
31 monobit_limit_range: 61,
32 run_length1_limit_max: 39,
33 run_length1_limit_range: 39,
34 run_length2_limit_max: 24,
35 run_length2_limit_range: 25,
36 run_length3_limit_max: 17,
37 run_length3_limit_range: 18,
38 ..Default::default()
39 },
40 )
41 }
42
43 /// Instantiates a new TRNG peripheral driver with 256 samples of entropy.
44 pub fn new_256(_peri: Peri<'d, TRNG0>) -> Self {
45 Self::new_inner(
46 _peri,
47 Config {
48 sample_size: 256,
49 retry_count: 1,
50 long_run_limit_max: 31,
51 monobit_limit_max: 171,
52 monobit_limit_range: 86,
53 run_length1_limit_max: 63,
54 run_length1_limit_range: 56,
55 run_length2_limit_max: 38,
56 run_length2_limit_range: 38,
57 run_length3_limit_max: 25,
58 run_length3_limit_range: 26,
59 ..Default::default()
60 },
61 )
62 }
63
64 /// Instantiates a new TRNG peripheral driver with 512 samples of entropy.
65 pub fn new_512(_peri: Peri<'d, TRNG0>) -> Self {
66 Self::new_inner(_peri, Default::default())
67 }
68
22 /// Instantiates a new TRNG peripheral driver. 69 /// Instantiates a new TRNG peripheral driver.
23 pub fn new(_peri: Peri<'d, TRNG0>, config: Config) -> Self { 70 ///
71 /// NOTE: this constructor makes not attempt at validating the
72 /// parameters. If you get this wrong, the security guarantees of
73 /// the TRNG with regards to entropy may be violated
74 pub fn new_with_custom_config(_peri: Peri<'d, TRNG0>, config: Config) -> Self {
75 Self::new_inner(_peri, config)
76 }
77
78 fn new_inner(_peri: Peri<'d, TRNG0>, config: Config) -> Self {
24 _ = unsafe { enable_and_reset::<TRNG0>(&NoConfig) }; 79 _ = unsafe { enable_and_reset::<TRNG0>(&NoConfig) };
25 80
26 Self::configure(config); 81 Self::configure(config);
@@ -36,49 +91,49 @@ impl<'d> Trng<'d> {
36 w.mono_max() 91 w.mono_max()
37 .bits(config.monobit_limit_max) 92 .bits(config.monobit_limit_max)
38 .mono_rng() 93 .mono_rng()
39 .bits(config.monobit_limit_max - config.monobit_limit_min) 94 .bits(config.monobit_limit_range)
40 }); 95 });
41 96
42 regs().scr1l().write(|w| unsafe { 97 regs().scr1l().write(|w| unsafe {
43 w.run1_max() 98 w.run1_max()
44 .bits(config.run_length1_limit_max) 99 .bits(config.run_length1_limit_max)
45 .run1_rng() 100 .run1_rng()
46 .bits(config.run_length1_limit_max - config.run_length1_limit_min) 101 .bits(config.run_length1_limit_range)
47 }); 102 });
48 103
49 regs().scr2l().write(|w| unsafe { 104 regs().scr2l().write(|w| unsafe {
50 w.run2_max() 105 w.run2_max()
51 .bits(config.run_length2_limit_max) 106 .bits(config.run_length2_limit_max)
52 .run2_rng() 107 .run2_rng()
53 .bits(config.run_length2_limit_max - config.run_length2_limit_min) 108 .bits(config.run_length2_limit_range)
54 }); 109 });
55 110
56 regs().scr3l().write(|w| unsafe { 111 regs().scr3l().write(|w| unsafe {
57 w.run3_max() 112 w.run3_max()
58 .bits(config.run_length3_limit_max) 113 .bits(config.run_length3_limit_max)
59 .run3_rng() 114 .run3_rng()
60 .bits(config.run_length3_limit_max - config.run_length3_limit_min) 115 .bits(config.run_length3_limit_range)
61 }); 116 });
62 117
63 regs().scr4l().write(|w| unsafe { 118 regs().scr4l().write(|w| unsafe {
64 w.run4_max() 119 w.run4_max()
65 .bits(config.run_length4_limit_max) 120 .bits(config.run_length4_limit_max)
66 .run4_rng() 121 .run4_rng()
67 .bits(config.run_length4_limit_max - config.run_length4_limit_min) 122 .bits(config.run_length4_limit_range)
68 }); 123 });
69 124
70 regs().scr5l().write(|w| unsafe { 125 regs().scr5l().write(|w| unsafe {
71 w.run5_max() 126 w.run5_max()
72 .bits(config.run_length5_limit_max) 127 .bits(config.run_length5_limit_max)
73 .run5_rng() 128 .run5_rng()
74 .bits(config.run_length5_limit_max - config.run_length5_limit_min) 129 .bits(config.run_length5_limit_range)
75 }); 130 });
76 131
77 regs().scr6pl().write(|w| unsafe { 132 regs().scr6pl().write(|w| unsafe {
78 w.run6p_max() 133 w.run6p_max()
79 .bits(config.run_length6_limit_max) 134 .bits(config.run_length6_limit_max)
80 .run6p_rng() 135 .run6p_rng()
81 .bits(config.run_length6_limit_max - config.run_length6_limit_min) 136 .bits(config.run_length6_limit_range)
82 }); 137 });
83 138
84 regs() 139 regs()
@@ -206,8 +261,78 @@ pub struct AsyncTrng<'d> {
206} 261}
207 262
208impl<'d> AsyncTrng<'d> { 263impl<'d> AsyncTrng<'d> {
264 /// Instantiates a new TRNG peripheral driver with 128 samples of entropy.
265 pub fn new_128(
266 _peri: Peri<'d, TRNG0>,
267 _irq: impl crate::interrupt::typelevel::Binding<typelevel::TRNG0, InterruptHandler> + 'd,
268 ) -> Self {
269 Self::new_inner(
270 _peri,
271 _irq,
272 Config {
273 sample_size: 128,
274 retry_count: 1,
275 long_run_limit_max: 29,
276 monobit_limit_max: 94,
277 monobit_limit_range: 61,
278 run_length1_limit_max: 39,
279 run_length1_limit_range: 39,
280 run_length2_limit_max: 24,
281 run_length2_limit_range: 25,
282 run_length3_limit_max: 17,
283 run_length3_limit_range: 18,
284 ..Default::default()
285 },
286 )
287 }
288
289 /// Instantiates a new TRNG peripheral driver with 256 samples of entropy.
290 pub fn new_256(
291 _peri: Peri<'d, TRNG0>,
292 _irq: impl crate::interrupt::typelevel::Binding<typelevel::TRNG0, InterruptHandler> + 'd,
293 ) -> Self {
294 Self::new_inner(
295 _peri,
296 _irq,
297 Config {
298 sample_size: 256,
299 retry_count: 1,
300 long_run_limit_max: 31,
301 monobit_limit_max: 171,
302 monobit_limit_range: 86,
303 run_length1_limit_max: 63,
304 run_length1_limit_range: 56,
305 run_length2_limit_max: 38,
306 run_length2_limit_range: 38,
307 run_length3_limit_max: 25,
308 run_length3_limit_range: 26,
309 ..Default::default()
310 },
311 )
312 }
313
314 /// Instantiates a new TRNG peripheral driver with 512 samples of entropy.
315 pub fn new_512(
316 _peri: Peri<'d, TRNG0>,
317 _irq: impl crate::interrupt::typelevel::Binding<typelevel::TRNG0, InterruptHandler> + 'd,
318 ) -> Self {
319 Self::new_inner(_peri, _irq, Default::default())
320 }
321
209 /// Instantiates a new TRNG peripheral driver. 322 /// Instantiates a new TRNG peripheral driver.
210 pub fn new( 323 ///
324 /// NOTE: this constructor makes not attempt at validating the
325 /// parameters. If you get this wrong, the security guarantees of
326 /// the TRNG with regards to entropy may be violated
327 pub fn new_with_custom_config(
328 _peri: Peri<'d, TRNG0>,
329 _irq: impl crate::interrupt::typelevel::Binding<typelevel::TRNG0, InterruptHandler> + 'd,
330 config: Config,
331 ) -> Self {
332 Self::new_inner(_peri, _irq, config)
333 }
334
335 fn new_inner(
211 _peri: Peri<'d, TRNG0>, 336 _peri: Peri<'d, TRNG0>,
212 _irq: impl crate::interrupt::typelevel::Binding<typelevel::TRNG0, InterruptHandler> + 'd, 337 _irq: impl crate::interrupt::typelevel::Binding<typelevel::TRNG0, InterruptHandler> + 'd,
213 config: Config, 338 config: Config,
@@ -413,44 +538,44 @@ pub struct Config {
413 /// Statistical check monobit max limit 538 /// Statistical check monobit max limit
414 pub monobit_limit_max: u16, 539 pub monobit_limit_max: u16,
415 540
416 /// Statistical check monobit min limit 541 /// Statistical check monobit range
417 pub monobit_limit_min: u16, 542 pub monobit_limit_range: u16,
418 543
419 /// Statistical check run length 1 limit max 544 /// Statistical check run length 1 limit max
420 pub run_length1_limit_max: u16, 545 pub run_length1_limit_max: u16,
421 546
422 /// Statistical check run length 1 limit min 547 /// Statistical check run length 1 limit range
423 pub run_length1_limit_min: u16, 548 pub run_length1_limit_range: u16,
424 549
425 /// Statistical check run length 2 limit max 550 /// Statistical check run length 2 limit max
426 pub run_length2_limit_max: u16, 551 pub run_length2_limit_max: u16,
427 552
428 /// Statistical check run length 2 limit min 553 /// Statistical check run length 2 limit range
429 pub run_length2_limit_min: u16, 554 pub run_length2_limit_range: u16,
430 555
431 /// Statistical check run length 3 limit max 556 /// Statistical check run length 3 limit max
432 pub run_length3_limit_max: u16, 557 pub run_length3_limit_max: u16,
433 558
434 /// Statistical check run length 3 limit min 559 /// Statistical check run length 3 limit range
435 pub run_length3_limit_min: u16, 560 pub run_length3_limit_range: u16,
436 561
437 /// Statistical check run length 4 limit max 562 /// Statistical check run length 4 limit max
438 pub run_length4_limit_max: u16, 563 pub run_length4_limit_max: u16,
439 564
440 /// Statistical check run length 4 limit min 565 /// Statistical check run length 4 limit range
441 pub run_length4_limit_min: u16, 566 pub run_length4_limit_range: u16,
442 567
443 /// Statistical check run length 5 limit max 568 /// Statistical check run length 5 limit max
444 pub run_length5_limit_max: u16, 569 pub run_length5_limit_max: u16,
445 570
446 /// Statistical check run length 5 limit min 571 /// Statistical check run length 5 limit range
447 pub run_length5_limit_min: u16, 572 pub run_length5_limit_range: u16,
448 573
449 /// Statistical check run length 6 limit max 574 /// Statistical check run length 6 limit max
450 pub run_length6_limit_max: u16, 575 pub run_length6_limit_max: u16,
451 576
452 /// Statistical check run length 6 limit min 577 /// Statistical check run length 6 limit range
453 pub run_length6_limit_min: u16, 578 pub run_length6_limit_range: u16,
454 579
455 /// Retry count 580 /// Retry count
456 pub retry_count: u8, 581 pub retry_count: u8,
@@ -471,26 +596,26 @@ pub struct Config {
471impl Default for Config { 596impl Default for Config {
472 fn default() -> Self { 597 fn default() -> Self {
473 Self { 598 Self {
474 sample_size: 1024, 599 sample_size: 512,
475 entropy_delay: 32_000, 600 entropy_delay: 32_000,
476 self_test: SelfTest::Enabled, 601 self_test: SelfTest::Enabled,
477 freq_counter_max: 75_000, 602 freq_counter_max: 75_000,
478 freq_counter_min: 30_000, 603 freq_counter_min: 30_000,
479 monobit_limit_max: 596, 604 monobit_limit_max: 317,
480 monobit_limit_min: 427, 605 monobit_limit_range: 122,
481 run_length1_limit_max: 187, 606 run_length1_limit_max: 107,
482 run_length1_limit_min: 57, 607 run_length1_limit_range: 80,
483 run_length2_limit_max: 105, 608 run_length2_limit_max: 62,
484 run_length2_limit_min: 28, 609 run_length2_limit_range: 55,
485 run_length3_limit_max: 97, 610 run_length3_limit_max: 39,
486 run_length3_limit_min: 33, 611 run_length3_limit_range: 39,
487 run_length4_limit_max: 0, 612 run_length4_limit_max: 0,
488 run_length4_limit_min: 0, 613 run_length4_limit_range: 0,
489 run_length5_limit_max: 0, 614 run_length5_limit_max: 0,
490 run_length5_limit_min: 0, 615 run_length5_limit_range: 0,
491 run_length6_limit_max: 0, 616 run_length6_limit_max: 0,
492 run_length6_limit_min: 0, 617 run_length6_limit_range: 0,
493 retry_count: 2, 618 retry_count: 1,
494 long_run_limit_max: 32, 619 long_run_limit_max: 32,
495 sparse_bit_limit: 0, 620 sparse_bit_limit: 0,
496 poker_limit_max: 0, 621 poker_limit_max: 0,
@@ -499,6 +624,21 @@ impl Default for Config {
499 } 624 }
500} 625}
501 626
627/// Sample size.
628#[derive(Clone, Copy, Debug)]
629#[cfg_attr(feature = "defmt", derive(defmt::Format))]
630#[non_exhaustive]
631pub enum SampleSize {
632 /// 128 bits
633 _128,
634
635 /// 256 bits
636 _256,
637
638 /// 512 bits
639 _512,
640}
641
502/// Enable or disable internal self-tests. 642/// Enable or disable internal self-tests.
503#[derive(Clone, Copy, Debug)] 643#[derive(Clone, Copy, Debug)]
504#[cfg_attr(feature = "defmt", derive(defmt::Format))] 644#[cfg_attr(feature = "defmt", derive(defmt::Format))]
diff --git a/examples/mcxa/src/bin/trng.rs b/examples/mcxa/src/bin/trng.rs
index 95b4d0a88..bdd1f1041 100644
--- a/examples/mcxa/src/bin/trng.rs
+++ b/examples/mcxa/src/bin/trng.rs
@@ -21,8 +21,26 @@ async fn main(_spawner: Spawner) {
21 21
22 defmt::info!("TRNG example"); 22 defmt::info!("TRNG example");
23 23
24 let mut trng = Trng::new_128(p.TRNG0.reborrow());
25 let rand = trng.blocking_next_u32();
26 defmt::info!("128-bit {}", rand);
27
28 drop(trng);
29
30 let mut trng = Trng::new_256(p.TRNG0.reborrow());
31 let rand = trng.blocking_next_u32();
32 defmt::info!("256-bit {}", rand);
33
34 drop(trng);
35
36 let mut trng = Trng::new_512(p.TRNG0.reborrow());
37 let rand = trng.blocking_next_u32();
38 defmt::info!("512-bit {}", rand);
39
40 drop(trng);
41
24 let config = trng::Config::default(); 42 let config = trng::Config::default();
25 let mut trng = Trng::new(p.TRNG0.reborrow(), config); 43 let mut trng = Trng::new_with_custom_config(p.TRNG0.reborrow(), config);
26 44
27 defmt::info!("========== BLOCKING =========="); 45 defmt::info!("========== BLOCKING ==========");
28 46
@@ -57,7 +75,7 @@ async fn main(_spawner: Spawner) {
57 75
58 defmt::info!("========== ASYNC =========="); 76 defmt::info!("========== ASYNC ==========");
59 77
60 let mut trng = AsyncTrng::new(p.TRNG0.reborrow(), Irqs, config); 78 let mut trng = AsyncTrng::new_with_custom_config(p.TRNG0.reborrow(), Irqs, config);
61 79
62 defmt::info!("Generate 10 u32"); 80 defmt::info!("Generate 10 u32");
63 for _ in 0..10 { 81 for _ in 0..10 {