-
Notifications
You must be signed in to change notification settings - Fork 96
Secure element key creation foundation #157
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
Secure element key creation foundation #157
Conversation
psa_key_lifetime_t lifetime ) | ||
{ | ||
size_t i; | ||
if( lifetime == 0 ) |
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 the same remark as in a different PR - I would suggest swapping zero with a defined constant to signal what does this value mean.
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.
Here 0 means no entry. I'll add a comment to explain.
@@ -83,4 +123,10 @@ void psa_unregister_all_se_drivers( void ) | |||
memset( driver_table, 0, sizeof( driver_table ) ); | |||
} | |||
|
|||
|
|||
|
|||
/****************************************************************/ |
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.
What is the reason behind this 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.
Makes it visible that this finishes the "Driver registration" section.
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.
It's the end of the file anyway and there's nothing after this section, that's why I ask. It seems redundant to 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.
No changes planned here.
if( slot == NULL ) | ||
return; | ||
|
||
#if defined(MBEDTLS_PSA_CRYPTO_SE_C) | ||
/* TOnogrepDO: If the key has already been created in the secure |
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 shouldn't be here, at least not in such strange form.
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.
That's why it's a TODO. Spelled this way so that check-files
doesn't tell me something I already know.
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 fix check-files in a separate commit instead?
Also, please add a reference in this code comment to a GitHub issue for this TODO, if it's important enough to track fixing.
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.
It was a conscious decision to reject TODO
in check-files.sh
, so I'm respecting it. Changing our criteria for acceptable code is out of scope of this PR.
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.
TOnogrepDO will stay in this PR. When Mbed-TLS/mbedtls#2730 makes its way to this branch, we can use TODO.
slot->data.se.slot_number, | ||
slot->lifetime, slot->type, slot->policy.alg, slot->policy.usage, | ||
data, data_length ); | ||
/* TOnogrepDO: psa_check_key_slot_attributes? */ |
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 shouldn't be here, at least not in such strange form.
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.
Will be resolved in a follow-up PR.
include/psa/crypto_se_driver.h
Outdated
* \param before The end of the range. | ||
* It is not included in the search. | ||
* \param[out] found On success, a free slot number such that | ||
* `from <= found < before`. |
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.
What is the reason behind such rule? It will be hard to remember, since it's inconsistent even within this one function call.
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 understand. Why is it so strange that the slot is within an interval, since that's the whole point of the function? What inconsistency are you talking about?
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'm talking about having the beginning of the range inclusive, but the end - not.
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.
That's the usual way to do ranges, so that end - start = length. What would you expect?
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 expect having the same rules for both sides of the range. I'm not acquainted with other crypto APIs though, so I won't press on changing 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.
It's not about crypto APIs, it's about array slices. Most array slicing APIs take (start_inclusive, number_of_items) or (start_inclusive, end_exclusive) as parameters, with end_exclusive = start_inclusive + number_of_items. If you use start_inclusive and end_inclusive, a lot of operations need a +1 or -1, which is awkward and error-prone.
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.
But maybe this would look more familiar with a length parameter instead of an end parameter. I'm considering changing 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.
Moot because this interface has been completely redesigned.
include/psa/crypto_se_driver.h
Outdated
* Success. \c *found contains a slot number which is between | ||
* \p from and \p before-1 inclusive and which is currently free. | ||
* \retval #PSA_ERROR_INSUFFICIENT_STORAGE | ||
* All slots in the indicated range are occupied. |
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.
Minor suggestion: indicated
-> requested
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.
Moot because this chunk of text is no longer present.
library/psa_crypto_se.c
Outdated
return( PSA_ERROR_INSUFFICIENT_MEMORY ); | ||
drv->slot_usage->size = drv->methods->key_management->slot_count; | ||
|
||
/* TOnogrepDO: load */ |
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.
Leftover 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.
No, it's still to do.
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 PR be blocked on loading not being done yet?
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.
It shouldn't be merged as is because it includes a feature that's on by default (SE support) but leads to undefined behavior if used according to the documentation. I don't have precise criteria in mind for when this PR will be mergeable: ideally it would do everything but I also want it to be usable ASAP.
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'd recommend not making this PR do everything as a precondition to merging.
Let's try to pick a safe subset to enable by default, and implement that bit. Or, make this off by default until we are comfortable enough with the feature to turn it on by default. The latter approach is quite common and widely known in the industry as a "feature toggle".
We don't want a repeat of PRs we've had trouble merging in the past: ones that keep growing bigger and bigger, and more and more stale.
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'm not planning to remove TOnogrepDO's from this PR in general. This particular one has actually been done.
#define mbedtls_free free | ||
#endif | ||
|
||
|
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.
Triple whitespace
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.
What's triple whitespace and why is it a problem?
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.
Pars pro toto - Three consecutive newline whitespaces. I'm quite certain I haven't seen these in any of the previous MbedTLS files, they seem a bit spacious. Not sure if we have any rule against it though. Pointing it out just in case it's an oversight.
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.
No changes planned.
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.
Maybe we should make this 7 consecutive newlines...
7 is better than 3
if( slot == NULL ) | ||
return; | ||
|
||
#if defined(MBEDTLS_PSA_CRYPTO_SE_C) | ||
/* TOnogrepDO: If the key has already been created in the secure |
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 fix check-files in a separate commit instead?
Also, please add a reference in this code comment to a GitHub issue for this TODO, if it's important enough to track fixing.
library/psa_crypto_se.c
Outdated
return( PSA_ERROR_INSUFFICIENT_MEMORY ); | ||
drv->slot_usage->size = drv->methods->key_management->slot_count; | ||
|
||
/* TOnogrepDO: load */ |
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 PR be blocked on loading not being done yet?
status = PSA_ERROR_NOT_SUPPORTED; | ||
goto exit; | ||
} | ||
status = drv->key_management->p_import( |
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.
Bug found by 028eb3d: Lack of error checking
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.
What error checking specifically? Since we already have a test, whatever that bug is, I propose to fix it in a follow-up PR.
Expose the type of an entry in the SE driver table as an opaque type to other library modules. Soon, driver table entries will have state, and callers will need to be able to access this state through functions using this opaque type. Provide functions to look up a driver by its lifetime and to retrieve the method table from an entry.
Instead of having one giant table containing all possible methods, represent a driver's method table as a structure containing pointers to substructures. This way a driver that doesn't implement a certain class of operations can use NULL for this class as a whole instead of storing NULL for each method.
When creating a key with a lifetime that places it in a secure element, retrieve the appropriate driver table entry. This commit doesn't yet achieve behavior: so far the code only retrieves the driver, it doesn't call the driver.
This slightly increases storage requirements, but works in more use cases. In particular, it allows drivers to treat choose slot numbers with a monotonic counter that is incremented each time a key is created, without worrying about overflow in practice.
Define a structure that is to be instantiated once per driver instance. Define a driver initialization method and pass it the driver context.
Pass the driver context to all driver methods except the ones that operate on an already-setup operation context. Rename `p_context` arguments to `op_context` to avoid confusion between contexts.
Add a driver method to allocate a key slot for a key that is about to be created.
Most driver methods are not allowed to modify the persistent data, so the driver context structure contains a const pointer to it. Pass a non-const pointer to the persstent data to the driver methods that need it: init, allocate, destroy.
Create the driver context when registering the driver. Implement some helper functions to access driver information.
Since driver table entries contain the driver context, which is mutable, they can't be const anymore.
Be stylistically consistent.
Explain what it can be used for and when it is saved to storage.
@Patater @AndrzejKurek Thanks for the reviews. I believe I've addressed all your comments except for a few where I'm still waiting for further feedback. |
library/psa_crypto_storage.h
Outdated
* If the system crashes while a transaction is in progress, psa_crypto_init() | ||
* calls psa_crypto_load_transaction() and takes care of completing or | ||
* rewinding the transaction. This is done in psa_crypto_recover_transaction() | ||
* in psa_crypto.c. If you add a new type of transactions, be |
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 you add a new type of transactions
+ If you add a new type of transaction
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.
Fixed by amending the commit.
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.
LGTM
Just one English nit and the rest are non-blocking issues.
66be51c
cb2e247
to
66be51c
Compare
Nothing has been saved to disk yet, but there is stale data in psa_crypto_transaction. This stale data should not be reused, but do wipe it to reduce the risk of it mattering somehow in the future.
This PR lays some foundations for creating a key in a secure element. It's work in progress, not yet usable.
What it does so far:
export
). Every such function will need to have this mechanism. I don't think the existing code is the final word on this.This PR has reached the goals I wanted to reach for a foundation:
I think the path towards getting this merged is to implement just enough that doing something that isn't implemented yet on a key that is in a secure element would return an error instead of crashing. Implementing more secure element access hooks at this point would be premature: first we should beef up testing.
History: