-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add RNG #37
base: master
Are you sure you want to change the base?
Add RNG #37
Conversation
Thanks for the PR! Will you be getting hardware to be able to test this? I'll take more of a look in the next few days to a week, but my first inclination is that it would be nice to use generics instead of macros here. From my cursory look, it seems like it would be possible to create a generic RNG type that takes a numeric type as a parameter. That would probably require a trait bound that informs the compiler that the type implements whatever functionality is needed. |
We have ordered a Nucleo-H533 which should arrive any day now. The plan is to later make a custom pcb with the H523. So we will most likely shift our focus to #38 before we ca do any real tests with this |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! I think this is a good start, but would like to see some seed error recovery, a non-blocking API and removal of the CryptoRng marker trait as mentioned in the comments. I know you brought this directly over from the H7 where it is already in use, but these feel like important changes to me.
|
||
impl Rng { | ||
/// Returns 32 bits of randomness, or error | ||
pub fn value(&mut self) -> Result<u32, ErrorKind> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you provide a non-blocking version of this function (value_nb
) that returns an nb::Result
(see nb crate) indicating that it would block if the data is not ready, and then call the non-blocking function using the nb::block!
macro here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note: nb
is being brought in as a dependency in #27. There is also an open comment thread about it's use here: #27 (comment) (I'm hoping to get some closure on that soon!)
src/rng.rs
Outdated
return Err(ErrorKind::ClockError); | ||
} | ||
if status.secs().bit() { | ||
return Err(ErrorKind::SeedError); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's a seed error recovery process documented in the manual. Would you mind implementing that so when this error occurs, the recovery process can be run? As it stands, if this occurs the RNG would hang and be unrecoverable afterwards, except by using the PAC directly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you want this implemented as its own method on the Rng
type which the user then calls whenever they get an ErrorKind::SeedError
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So the general approach I've been taking is to expose non-blocking and blocking functions for each driver (you can see that in the I2C driver, but the SPI and USART drivers I have written and am intending to publish as PRs when the I2C driver lands follow then same pattern). This is intended to facilitate various use cases (interrupts vs spin-loop polling) and async extensions later.
For this case I can actually see 3 behaviours that are worth exposing:
- Non-blocking calls ((e.g.
value_nb
+recover_nb
) that return nb::Result and which do not automatically recover from the error - Blocking calls (e.g.
value
+recover
, which probably just call the above functions in a loop) that do not automatically recover from the error - Blocking calls that automatically recover
The last is necessary for the module to be useful for the rand_core
trait implementations, as they don't return Result
s
} | ||
} | ||
|
||
impl core::iter::Iterator for Rng { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
neat 👍
|
||
#[derive(Debug)] | ||
#[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
pub enum ErrorKind { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: I've been using Error
for Error enums
We have now added the three configurations described in the reference manuals and the application note. All three configurations seems to work on the Nucleo-H533 (the nist configuration when the We still have the recovery thing left to do and your other comments |
This looks great so far. Really appreciate the effort in implementing the different configurations that ST notes. I realized that I was looking at an older version of RM0492 that did not directly state that configuration B and C were AIS-31 compliant, but Rev 3 does. I'm not really familiar with crypto standards, but according to some cursory internet searching, that does lend some credibility to using those configurations as entropy sources for key generation, and given that the note that they are for both the STM32H503 and STM32H56x/STM32H573, perhaps we can implement the CryptoRng trait for those implementations too? Sorry for the back and forth there. I also think it's worth noting in the documentation that they are AIS-31 compliant according to ST and can be used as entropy sources if that is the standard the user requires. |
#[cfg(any( | ||
feature = "stm32h562", | ||
feature = "stm32h563", | ||
feature = "stm32h573" | ||
))] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's a nist configuration for the STM32H503 isn't there?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure how we want to do here,
taken from rm0492:
RNG configurations are described in Table 156. Note that only configuration A can be
certified NIST SP800-90B. Refer to Table 157 to select the best configuration for the
application.
• Configuration C can be used when configuration A is not flagged as certified
and according to an4230, stm32h503 configuration A is not certified.
Should we still use configuration A for stm32503 or configuration C?
It's a bit unclear to me atleast.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh interesting. I hadn't noticed that. Looking at AN4230, the way I understand it is that those are the recommended settings for NIST verification, but only the processor lines indicated were actually certified by ST, but that you could certify using those settings. Maybe we should include it but note that ST recommends, but did not certify themselves with these settings?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good to me 👍
self.htcr().write(|w| unsafe { w.bits(0xAAC7) }); | ||
|
||
// Set noise source control register | ||
#[cfg(not(feature = "stm32h503"))] // Not available on H503 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Huh. I see this register is missing from the PAC, and the SVD, but it is documented in the reference manual. This is probably not a blocker, because the STM32H503 configurations for B, C require that the register stays at default, and if the register is not exposed via the PAC it is hard to modify. I'll submit a PR to stm32-rs to add it, but we don't need to depend on it to merge this, IMO. Can you leave a note in a comment to this effect here?
/// This uses the register values specified in AN4230 but have not | ||
/// performed the verification (buyer beware, users can/should do their own verification) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit:
/// This uses the register values specified in AN4230 but have not | |
/// performed the verification (buyer beware, users can/should do their own verification) | |
/// Note: | |
/// This uses the register values specified in AN4230 but verification | |
/// using this HAL has not been performed. Users can/should do their. | |
/// own verification or request documentation from ST directly. |
Added RNG as per #34, it compiles but I haven't been able to test it since I don't have access to a processor yet.