-
Notifications
You must be signed in to change notification settings - Fork 2k
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
random: added a random driver interface #939
Conversation
*/ | ||
void random_init(void); | ||
|
||
uint32_t random_get(void); |
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.
How about random_get_uint32
?
How are other systems I would have gone for bytes ( |
Regarding *arch: In any case this is something where we should look how other systems are doing it as well. |
@haukepetersen can you review? |
Just did. I think the interface looks well, just two remarks:
So getting a (larger) number of bytes could take significant time. This we need either to well document or leave this to a higher-level interface... |
@haukepetersen What do you suggest? Should the driver add TRNG values to a pool on its own or should there be something like a |
I agree that a higher level driver should provide blocking access to slow randomness. |
I would leave the interface 'as is'. For retrieving one 32-bit value waiting 84 cycles is ok (and other platforms may have significantly different numbers here -> e.g. 40 cycles on the STM32F4), as long as its documented. I would strongly argue against a pool or similar on the low-level driver layer, as I think the low level layer should be kept as slim as possible. |
Well, the driver could feed to an upper driver via callback.. |
Ok, I did a quit shot at an implementation for the SAM3X -> #1294, turned out to be quite simple :-) |
@haukepetersen what about an API like:
the driver tries to fill @thomaseichinger I think this is what you suggested some weeks ago, right? |
@mehlis I think this interface would work well, I would go with this. Any other opinions on this? |
/* | ||
* Copyright (C) 2014 Freie Universität Berlin | ||
* | ||
* This file is subject to the terms and conditions of the LGPLv2 License. |
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.
2.1
I think Regarding the initialization: wouldn't it make indeed sense to give a list of sources as parameters to this function? |
Well, the prototype mentioned in #939 (comment) I proposed with some future asynchronous functionality in mind especially for platforms needing more than <100 cycles and applications needing more than 4 bytes. Also it would result in one single function to feed a definable range of bytes. But I don't have a very strong opinion on this. |
I spend some further thought on this, maybe we can have an interface like the following, that provides synchronous as well as asynchronous access (similar to the UART interface): int random_get_blocking(*buf, num_of_bytes); // will block until random data is available
int random_get_async(void (*cb)(uint data)); // gets new bytes whenever ready
void random_done(); // will stop generating random data Using this interface, it should be easy to put a higher-level driver on top, that can asynchronously generate random number of any length and synchronize via messaging... This IF must surely be though over a little more, but what do you think about the general direction? |
I like the general idea. But I maybe /* gets new bytes whenever ready and stores in buf */
int random_get_async(void (*cb)(uint data, uint *buf, uint *read_bytes),
uint *buf,
uint *read_bytes); But |
Nope, I think we missunderstood each other. The callback gets intentionally only one parameter - the newly created random value. It is then up to the higher-level driver/consumer to do something with that value, e.g. to store it into some kind of buffer... |
@haukepetersen I updated the interface with your input, please review |
* | ||
* @param[in] buf destination buffer to write the bytes to | ||
* @param[in] num number of bytes to get from device, | ||
* only values < 0 are valid |
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.
values > 0
I presume
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.
agreed with @Kijewski
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.
@mehlis please change this
* @return the number of bytes written to buf, | ||
* a value <= 0 is returned on error | ||
*/ | ||
int random_blocking_get(char *buf, int num); |
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.
The number of bytes should be unsigned
. Return 0 on error.
@haukepetersen updated with your new input |
* @param[in] data one random byte | ||
* | ||
* @return 1 to notify the driver to call it once data is available, | ||
* 0 to stop the driver from calling it |
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.
I don't get this. Is returning 1 meant to signal that more random data is needed?
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.
@thomaseichinger yes, in case the callback returns 1, the driver is informed to call it again, if 0 is returned the driver will unregister the callback
@haukepetersen updated with your input |
I'd suggest a blocking API, similar to that @mehlis suggested. I do not see much use in a callback interface. Basically your application gets high quality entropy at start and initializes its CSRNG and can generate random numbers at a fast pace. Ideally the API would be similar to already known and existing APIs, e.g. OpenBSD's getentropy() [1] or soon Linux's getrandom() [2]. So basically like the already suggested [1] http://www.openbsd.org/cgi-bin/man.cgi/OpenBSD-current/man2/getentropy.2?&manpath=OpenBSD-current&arch=amd64&query=getentropy |
Is this still WIP and what's the state of this PR? |
Yes, still WIP, but I think as soon as @thomaseichinger is back, we should be able to merge this rather soon. |
Since @haukepetersen was quite nitpicky about putting |
@authmillenon I like to disagree here, I think most implementations would actually be using hardware peripherals as (Pseudo) random number generators to implement this interface, and therefore I would see it in the low-level drivers. |
@authmillenon I'd also say that the fact that a peripheral might make use of another peripheral driver does not in itself suffice to say it's not a low level driver. Or I don't understand the argument at all. |
Okay as I was saying: I just wanted to point out my understanding of this. But if you all think differently, then go on :-) |
We are the iBorg. |
Ok, given some more thought, I think the original proposed interface should be fine: int random_init(void);
int random_get(char *buffer, int length); The documentations should state, that you have to take a careful look at the comments on the implementation, which tell you details about (i) the timing behavior of the driver and (ii) the grade of randomness for the specific implementation. |
@haukepetersen updated, in case you want more changes, it's probably best you take care of this interface (by doing an updated PR) |
* | ||
* @param[in] buf destination buffer to write the bytes to | ||
* @param[in] num number of bytes to get from device, | ||
* only values >0 are valid |
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.
you can remove this line, unsigned int < 0
is very rare anyhow... :-)
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.
Well, 0 is still an invalid input.
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.
True. Ignore my comment above.
@mehlis I created a PR against your branch |
Looks good to me, ACK |
and go. |
random: added a random driver interface
how should this be designed?
I see this PR as a discussion forum for this long standing discussion