Skip to content

[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

Merged
merged 5 commits into from
Apr 6, 2017

Conversation

stevew817
Copy link
Contributor

Description

Adding support for the TRNG peripheral present on Series 1 Configuration 2 devices.

Status

READY

Migrations

NO

@0xc0170 0xc0170 requested review from yanesca and simonbutcher March 28, 2017 11:46
@0xc0170
Copy link
Contributor

0xc0170 commented Mar 28, 2017

/morph test

@mbed-bot
Copy link

Result: SUCCESS

Your command has finished executing! Here's what you wrote!

/morph test

Output

mbed Build Number: 1759

All builds and test passed!

@0xc0170
Copy link
Contributor

0xc0170 commented Mar 28, 2017

How was this tested? Can you share any tests you run?

@stevew817
Copy link
Contributor Author

stevew817 commented Mar 28, 2017

@0xc0170 mbedTLS authcrypt example, two resets:
plaintext message: 536f6d65207468696e67732061726520626574746572206c65667420756e7265616400
ciphertext: 4ca1015c1eaea91a446c6746827766dc3ea0b154a82a377528b5f4862b13422cf89f22d02736c789930be51ab6f6acf83069209f6306368365bcce
decrypted: 536f6d65207468696e67732061726520626574746572206c65667420756e7265616400

DONE

plaintext message: 536f6d65207468696e67732061726520626574746572206c65667420756e7265616400
ciphertext: b31cefd3511b903a325e5d0a69b6b5b1c91c3841fb2548a211e1eb2306c05df2e2bdd0360e5519e90f02f5b73d21a36a5f9af3bbc6035e961772dc
decrypted: 536f6d65207468696e67732061726520626574746572206c65667420756e7265616400

DONE

void trng_init(trng_t *obj)
{
/* Use TRNG0 for all HW entropy collection */
obj->instance = TRNG0;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sg- Done.

@sg- sg- added needs: work and removed needs: CI labels Mar 28, 2017
@bridadan
Copy link
Contributor

/morph test

@mbed-bot
Copy link

Result: SUCCESS

Your command has finished executing! Here's what you wrote!

/morph test

Output

mbed Build Number: 1774

All builds and test passed!

@0xc0170 0xc0170 removed the needs: CI label Mar 29, 2017
Adding support for the TRNG peripheral present on Series 1 Configuration 2 devices.
@stevew817
Copy link
Contributor Author

@sg- rebased and merge conflict resolved

@0xc0170
Copy link
Contributor

0xc0170 commented Mar 30, 2017

/morph test

@mbed-bot
Copy link

Result: SUCCESS

Your command has finished executing! Here's what you wrote!

/morph test

Output

mbed Build Number: 1793

All builds and test passed!

@stevew817
Copy link
Contributor Author

@0xc0170 retest uvisor ?

@0xc0170
Copy link
Contributor

0xc0170 commented Apr 3, 2017

retest uvisor

@0xc0170
Copy link
Contributor

0xc0170 commented Apr 3, 2017

@yanesca @sbutcher-arm @RonEld review pls

@0xc0170
Copy link
Contributor

0xc0170 commented Apr 5, 2017

@yanesca @sbutcher-arm @RonEld review pls

update?

Copy link
Contributor

@RonEld RonEld left a 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)
Copy link
Contributor

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?

Copy link
Contributor Author

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 )
Copy link
Contributor

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)

Copy link
Contributor Author

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?

Copy link
Contributor

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 )
Copy link
Contributor

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

Copy link
Contributor Author

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?

Copy link
Contributor

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

Copy link
Contributor Author

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.

Copy link
Contributor Author

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 );
Copy link
Contributor

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?

Copy link
Contributor Author

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.

Copy link
Contributor

@RonEld RonEld Apr 6, 2017

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

Copy link
Contributor Author

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;
Copy link
Contributor

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?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See my other comment.

Copy link
Contributor

@RonEld RonEld left a 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

@sg- sg- merged commit 1b2aa9d into ARMmbed:mbed-os-workshop-17q2 Apr 6, 2017
Copy link

@andresag01 andresag01 left a 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;

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;

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?

Copy link
Contributor Author

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...

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)
Copy link
Contributor

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)

Copy link

@gilles-peskine-arm gilles-peskine-arm left a 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 );

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 )

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 )

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;

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?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants