diff options
| -rw-r--r-- | embassy-mcxa/src/trng.rs | 214 | ||||
| -rw-r--r-- | examples/mcxa/src/bin/trng.rs | 22 |
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 | ||
| 3 | use embassy_hal_internal::Peri; | ||
| 4 | use embassy_hal_internal::interrupt::InterruptExt; | 3 | use embassy_hal_internal::interrupt::InterruptExt; |
| 4 | use embassy_hal_internal::Peri; | ||
| 5 | use maitake_sync::WaitCell; | 5 | use maitake_sync::WaitCell; |
| 6 | use mcxa_pac::trng0::osc2_ctl::TrngEntCtl; | 6 | use mcxa_pac::trng0::osc2_ctl::TrngEntCtl; |
| 7 | 7 | ||
| @@ -19,8 +19,63 @@ pub struct Trng<'d> { | |||
| 19 | } | 19 | } |
| 20 | 20 | ||
| 21 | impl<'d> Trng<'d> { | 21 | impl<'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 | ||
| 208 | impl<'d> AsyncTrng<'d> { | 263 | impl<'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 { | |||
| 471 | impl Default for Config { | 596 | impl 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] | ||
| 631 | pub 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 { |
