-
Notifications
You must be signed in to change notification settings - Fork 3k
[Silicon Labs] Add TRNG support #4051
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
Conversation
/morph test |
Result: SUCCESSYour command has finished executing! Here's what you wrote!
OutputAll builds and test passed! |
How was this tested? Can you share any tests you run? |
@0xc0170 mbedTLS authcrypt example, two resets: DONE plaintext message: 536f6d65207468696e67732061726520626574746572206c65667420756e7265616400 DONE |
void trng_init(trng_t *obj) | ||
{ | ||
/* Use TRNG0 for all HW entropy collection */ | ||
obj->instance = TRNG0; |
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.
Should be 4 spaces, not 2 https://docs.mbed.com/docs/mbed-os-handbook/en/latest/cont/code_style/
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.
@sg- Done.
/morph test |
Result: SUCCESSYour command has finished executing! Here's what you wrote!
OutputAll builds and test passed! |
Adding support for the TRNG peripheral present on Series 1 Configuration 2 devices.
d48e6ee
to
f8be297
Compare
@sg- rebased and merge conflict resolved |
/morph test |
Result: SUCCESSYour command has finished executing! Here's what you wrote!
OutputAll builds and test passed! |
@0xc0170 retest uvisor ? |
retest uvisor |
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 have put some comments, waiting for answers before I can approve
*/ | ||
#include "sl_trng.h" | ||
|
||
#if defined(TRNG_PRESENT) |
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.
why not use the existing DEVICE_TRNG define?
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.
TRNG_PRESENT comes from our own device headers, and is the authority for knowing whether a device has TRNG or not. DEVICE_TRNG is an mbed define to use the mbed TRNG HAL. Considering sl_trng.c is a Silicon Labs file, and the mbed HAL doesn't directly interface with it (that'd be trng_api.c), we are using Silicon Labs defines.
return 0; | ||
} | ||
|
||
int sl_trng_check_entropy( TRNG_TypeDef *device ) |
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.
where is this API being called?
The entropy check should be wither done in you trng_get_bytes function, to verify that the collected noise has good entropy, or later from the entropy pool (TBD)
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.
@RonEld This is a self-test function (see my other comment), and is only used during TRNG bringup. The TRNG peripheral has built-in entropy checks (called 'Noise Alarms') which are being checked in the polling function.
Should I get rid of this function for the driver that we ship with mbed, or can I leave it as-is?
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.
see previous comment, but I think this function has less impact than previous test funciton
return 0; | ||
} | ||
|
||
int sl_trng_check_conditioning( TRNG_TypeDef *device ) |
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.
where is this API being called?
If I understand this API correct, you are now supplying an API for setting a constant output. am I right?
@yanesca I would like to hear your input on 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.
@RonEld No, this is a self-test function. It should never be used in regular operation, which is why it is never being called from the driver. We use it for internal test purposes, and since this driver was copied verbatim, the test function ended up here.
Should I get rid of it instead?
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.
In my opinion, internal test functions should not be added, in addition that they also might be exploited for other reasons
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.
Okay, I'll remove both test functions.
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.
@RonEld removed now.
#if !defined(SL_TRNG_IGNORE_ALL_ALARMS) | ||
/* Check status for current data in FIFO | ||
* and handle any error conditions. */ | ||
ret = sl_trng_check_status( device ); |
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.
Is the check status an irrecoverable failure? Perhaps wait for an interrupt until check_status will succeed?
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, on a noise alarm you really should throw away the generated data and reset the TRNG (which is already happening in check_status). Thus, the polling 'failed'. IMO, this should bubble up to the user, who can then decide whether or not to retry.
The other statuses are irrecoverable in the sense that they point to a larger issue, most likely someone tampering with the TRNG ring oscillators.
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.
Could you point me to the location where you poll on fail? It seems to me that on failure, you stop collecting and return an error to the user
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.
Changed now. Upon noise alarm, we throw away the collected entropy and continue collecting. For the other alarms (which are more severe, see my previous comment), we throw away the collected entropy, and return an error.
if (ret != 0) | ||
{ | ||
output_len = 0; | ||
break; |
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.
should this be changed to continue
? Do you want to continue collecting?
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.
See my other comment.
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 would remove dead code such as the test vectors that are not used anymore.
Other than that, it's ok by me
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 code seems OK, but to me it looks like there are some limitations because the implementation of mbedtls_entropy_hardware_poll()
continually resets the TRNG device. This PR is trying to get around the problem, but there are other issues, such as not being able to turn off the TRNG device.
void trng_free(trng_t *obj) | ||
{ | ||
/* Don't turn off the TRNG to avoid clearing its FIFO */ | ||
(void) obj; |
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.
Does this mean that an application can never really turn off the TRNG?
|
||
if(!is_trng_enabled) { | ||
sl_trng_init(obj->instance); | ||
is_trng_enabled = true; |
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.
If I understand correctly, the reasoning behind this is_trng_enabled
flag is to avoid restarting the TRNG device every time there is a call to mbedtls_hardware_poll()
to improve performance. The main problem is that mbedtls_hardware_poll()
is setup to start and shutdown the TRNG on every call, which seems a little inefficient. @gilles-peskine-arm: Any thoughts?
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.
Our Hardware TRNG is setup to fill a 2K FIFO with entropy when it starts, and only start up the ring oscillators again when it needs to replenish entropy. Therefore, actually shutting down the TRNG peripheral is counter-productive, since you'd be generating 2K of entropy (plus peripheral start-up time) on each request for entropy...
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.
Ok
break; | ||
} | ||
|
||
#if !defined(SL_TRNG_IGNORE_ALL_ALARMS) |
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.
Could somebody please help me understand why we need these alarm suppression options? (I mean SL_TRNG_IGNORE_ALL_ALARMS
and SL_TRNG_IGNORE_NOISE_ALARMS
)
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 have a few observations which may be due to my lack of familiarity with the hardware.
* \return | ||
* 0 if success. Error code if failure. | ||
*/ | ||
int sl_trng_set_key( TRNG_TypeDef *ctx, const unsigned char *key ); |
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.
Where is the conditioning key set? Should it be?
return 0; | ||
} | ||
|
||
static int sl_trng_check_status( TRNG_TypeDef *device ) |
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.
This function changes the device state. A name like check_status
does not convey this. How about sl_trng_retrieve_alarms
?
return 0; | ||
} | ||
|
||
if ( status & TRNG_STATUS_PREIF ) |
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.
If the preliminary noise alarm is raised, other alarms are ignored. Is this desirable? Or is the point moot because the alarms are mutually exclusive?
(ret == SL_TRNG_ERR_NOISE_ALARM) ) | ||
{ | ||
ret = 0; | ||
continue; |
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.
Like yanesca I wonder why there's a compilation option to ignore alarms. Assuming that the mode SL_TRNG_IGNORE_NOISE_ALARMS
is useful, I don't understand the logic here. If there is a physical condition that causes the alarm to keep being raised, wouldn't this cause a tight loop?
Description
Adding support for the TRNG peripheral present on Series 1 Configuration 2 devices.
Status
READY
Migrations
NO