-
Notifications
You must be signed in to change notification settings - Fork 2.6k
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
Implement MD dispatch to PSA #7242
Conversation
Please ignore while reviewing this PR. Will be removed by rebasing after Mbed-TLS#7242 is merged. Signed-off-by: Manuel Pégourié-Gonnard <manuel.pegourie-gonnard@arm.com>
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.
Changes and tests looks good. Left 2 comments with for places that needs clarification.
#if !defined(MBEDTLS_PSA_CRYPTO_C) | ||
#define PSA_INIT() ((void) 0) | ||
#define PSA_DONE() ((void) 0) | ||
#endif /* MBEDTLS_PSA_CRYPTO_C */ | ||
|
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 sure if this is correct at least needs clarification. We are overwriting macros that are defined earlier in the header and are used by other macros.
I think we should have something like this:
#if defined(MBEDTLS_PSA_CRYPTO_C)
#define PSA_INIT() PSA_ASSERT(psa_crypto_init())
#else
#define PSA_INIT() ((void) 0)
#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.
I think in builds without MBEDTLS_PSA_CRYPTO_C
, we're not overwriting anything as those macros have not been defined before. (Evidence: before I added that, I got "undeclared function" warnings, and also if we were re-defining the macros I think we'd get warnings about it.)
But I take your point that the way it's done is not clear enough and I agree that what you're suggesting is much clearer. I'll rework that.
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.
Some comments left.
Also: Can the decision on where to use PSA_INIT() in tests and where not be somehow justified, explained, or highlighted? What I mean is, we have a couple of tests in test_suite_md
(and in fact in other test suites using md explicitly or under the hood too) that will now dispatch the calls to different places based on PSA_INIT()
. Should we identify these places to find if there are any that specifically shouldn't use PSA_INIT()
? Starting from test_suite_md
itself, tests like md_text, md_hex - why shouldn't these be run with PSA_INIT()
?
|
||
static int mbedtls_md_error_from_psa(psa_status_t status) | ||
{ | ||
switch (status) { |
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 could use/adapt the newly merged https://github.com/Mbed-TLS/mbedtls/pull/6829/files#diff-ca89f54f744763de9f77c774fa7854f1f7ae92ade1e99676329cf161248e87b2R37
, as shown for example 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.
Thanks for the info, I didn't noticed this had been merged! If that's OK with you, I'd like to leave that for the "size optimization" part - I've added a note about it to an existing issue: #6993 (comment)
library/md.c
Outdated
} | ||
} | ||
|
||
static int md_uses_psa(const mbedtls_md_info_t *info) |
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.
Isn't this more like md_can_use_psa
? Even it this returns 1, but the engine is set to legacy, a given info
will not use psa, right?
@@ -7108,6 +7115,13 @@ psa_status_t psa_crypto_init(void) | |||
return PSA_SUCCESS; | |||
} | |||
|
|||
/* Init drivers */ | |||
status = psa_driver_wrapper_init(); |
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.
https://github.com/Mbed-TLS/mbedtls/blob/development/docs/architecture/psa-migration/strategy.md
mentions that
There is a problem with the modules used for the PSA RNG, as currently the RNG is initialized before drivers and the key store.
I'm not sure if this part should be updated, or maybe some studies have been done on impact (and it'll be good to link them here), but it seems to me that this might have some additional effects.
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 think this part should be updated - it probably should have been worded "The might be a problem" because IIRC it's not that we were sure there was a problem, more that there was something to do and we weren't sure it wouldn't cause issues. Now it's done and have not been causing issues.
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.
Ah, that's in strategy.md
, not md-cipher-dispatch.md
. In that case, if you don't mind I'd rather fix that as part of #7156 because there's potentially a lot more that's out-of-date in that file right now. I've left a note.
@@ -7108,6 +7115,13 @@ psa_status_t psa_crypto_init(void) | |||
return PSA_SUCCESS; | |||
} | |||
|
|||
/* Init drivers */ | |||
status = psa_driver_wrapper_init(); |
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 we want to check if the drivers were initialized to not initialize them again? Documentation on psa_driver_wrapper_init
is quite scarce.
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.
Currently initializing just the drivers is not supported (psa_driver_wrapper_init()
is a private function), the only thing that's supported is initializing everything with psa_crypto_init()
which already has a guard, so I think that's OK.
(Note: #6636 will change that but it's not in 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.
What's the gain of introducing drivers_initialized
then? I assumed that it should support partial psa_crypto_init
success:
- If
psa_crypto_init
succeeds, then indeed,global_data.initialized
is equal to 1 and there's no need to checkdrivers_initialized
; - If
psa_crypto_init
fails afterpsa_driver_wrapper_init
was called succesfully then the state is inconsistent and we could prevent a second call to drivers that were already initialized, during a second call topsa_crypto_init
;
If that's not the point and we don't want to support partial initialization, then why add drivers_initialized
at all?
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.
Ah, excellent question! Indeed in the context of this PR there's not point yet, I'm just anticipating on #7155 where the entropy module will start using MD, with the goal of having it work when hashes are provided by drivers. The entropy module is first used at the "init RNG" stage in psa_crypto_init()
, so when it will call MD, global_data.initialized
will still be 0 (it's only changed to 1 at the end of the function), but we'll want MD to dispatch to drivers nonetheless (which is also the reason for the change of ordering).
Now that you mention it, my PR structure is not clean: in this PR indeed I shouldn't have changed the order or introduced drivers_initialized
, but instead use global_data.initialized
in psa_can_do_hash()
, and left the rest for the PR about the entropy module. I'm afraid I got a bit ahead of myself 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.
Ah, now it makes sense! Thanks for explaining. I still think that we could optimize to not call init on drivers if they are already initialized, but it's a minor.
include/mbedtls/md.h
Outdated
|
||
/* | ||
* - MBEDTLS_MD_CAN_xxx is defined if the md module can perform xxx. | ||
* - MBEDTLS_MD_xxx_VIA_PSA is defined if the md module performs xxx via PSA. |
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 is a bit misleading, as the md module will still perform xxx via legacy if the engine states that it should.
@mprse @AndrzejKurek Thanks for your reviews! I think I've addressed all of your feedback, either by changes in the code, or making a note to address it later if that's OK with you, or in one instance explaining why I think no change's needed.
Ah, I think I just added PSA_INIT() when a test would otherwise fail, which is a very weak rationale now that you make me spell it out :) Indeed when thinking about it, all tests that call |
tests/suites/test_suite_md.function
Outdated
#define MD_PSA_INIT() PSA_INIT() | ||
#define MD_PSA_DONE() PSA_DONE() | ||
#else /* MBEDTLS_MD_SOME_PSA */ | ||
#define PSA_INIT() ((void) 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.
#define PSA_INIT() ((void) 0) | |
#define MD_PSA_INIT() ((void) 0) |
Without this change (and line below) the code will not compile out of the box.
include/mbedtls/md.h
Outdated
@@ -36,7 +36,8 @@ | |||
|
|||
/* | |||
* - MBEDTLS_MD_CAN_xxx is defined if the md module can perform xxx. | |||
* - MBEDTLS_MD_xxx_VIA_PSA is defined if the md module performs xxx via PSA. | |||
* - MBEDTLS_MD_xxx_VIA_PSA is defined if the md module performs xxx via PSA | |||
* (when PSA Crypto is initialized). |
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: this applies to all lines below, or maybe it would be just better to say that "PSA can perform xxx", just as with MD above.
What about other test suites that call it indirectly? ECJPAKE, pkcs12, x509write, ct, RSA (in rsaes_oaep, which aparently isn't tested in |
I was thinking about that. I think for now they don't need Note: RSA-OAEP is tested in |
I've labelled "do not merge" as I'd rather wait until after the code freeze for the release to merge this. This is not really complete without #6991, and while I think breaking the work in multiple issues makes sense to avoid overly large PRs, I think in a release it's better to either not have this PR, or have #6991 to go with 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.
Looks good given the constraints discussed in comments and planned follow-up work.
For multi-part operations, we want to make the decision to use PSA or not only once, during setup(), and remember it afterwards. This supports the introduction, in the next few commits, of a dynamic component to that decision: has the PSA driver sub-system been initialized yet? Signed-off-by: Manuel Pégourié-Gonnard <manuel.pegourie-gonnard@arm.com>
This will be used in the next commit. While at it, move driver initialization before RNG init - this will be handy when the entropy module wants to use drivers for hashes. Signed-off-by: Manuel Pégourié-Gonnard <manuel.pegourie-gonnard@arm.com>
We shouldn't dispatch to PSA when drivers have not been initialized yet. Signed-off-by: Manuel Pégourié-Gonnard <manuel.pegourie-gonnard@arm.com>
- Support for PSA_CRYPTO_CLIENT without PSA_CRYPTO_C is out of scope for now but might be added later (the architecture supports that). - While we're using a void pointer for md_ctx, we don't need a union here; the union will be useful only if & when we remove the indirection. Signed-off-by: Manuel Pégourié-Gonnard <manuel.pegourie-gonnard@arm.com>
Signed-off-by: Manuel Pégourié-Gonnard <manuel.pegourie-gonnard@arm.com>
Signed-off-by: Manuel Pégourié-Gonnard <manuel.pegourie-gonnard@arm.com>
The test driver library tries to only build what's necessary, but must use the same PSA_WANT macros as the main library. So, for things that are not needed, it undefines MBEDTLS_PSA_BUILTIN_xxx and defines MBEDTLS_PSA_ACCEL_xxx, unless the ACCEL symbol was defined on the command line, in which case it undefines it and defineds BUILTIN instead. This negation happens in crypto_config_test_driver_extension.h and reflects the fact that what we want accelerated in the main library is what we want built-in in the driver library (and vice versa if we want to minimize the size of the driver library). So, the ACCEL symbols in inside the test driver library (while it's being built, not those on the command line) are a bit of a white lie: they don't actually mean "there's an accelerator for this" but instead "I won't include a built-in for this even though the corresponding PSA_WANT symbol is defined". This was quite harmless until MD started making dispatch decisions based on the ACCEL symbols: when it tries to dispatch to an accelerator that doesn't actually exist, things tend to go badly. The minimal fix for this is to change how we enable extra hashes in the test driver library: by defining the ACCEL symbol on the command line, in the build we'll end up with the BUILTIN symbol (and implementation!) and no ACCEL symbol, which is exactly what we want. Long version: https://arm-ce.slack.com/archives/GTM3SM1K5/p1675071671707599 Signed-off-by: Manuel Pégourié-Gonnard <manuel.pegourie-gonnard@arm.com>
Signed-off-by: Manuel Pégourié-Gonnard <manuel.pegourie-gonnard@arm.com>
Signed-off-by: Manuel Pégourié-Gonnard <manuel.pegourie-gonnard@arm.com>
Signed-off-by: Manuel Pégourié-Gonnard <manuel.pegourie-gonnard@arm.com>
All tests that call md_setup() or compute a hash of a HMAC may now need it in some builds. Signed-off-by: Manuel Pégourié-Gonnard <manuel.pegourie-gonnard@arm.com>
Signed-off-by: Manuel Pégourié-Gonnard <manuel.pegourie-gonnard@arm.com>
Rebased and force-pushed to resolve the conflict (a trivial one: development had whitespace changes in the definition of |
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!
I only found one possible suggestion about the mbedtls_md_error_from_psa() function, but then I saw it was already discussed and found a plan for it, so I'm OK with this PR.
Just wait for the CI to be OK as well.
@@ -114,6 +128,8 @@ void md_info(int md_type, char *md_name, int md_size) | |||
(void) md_name; | |||
#endif | |||
|
|||
/* Note: PSA Crypto init not needed to info 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.
Very minor:
/* Note: PSA Crypto init not needed to info functions */ | |
/* Note: PSA Crypto init not needed for info 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.
I'll fix that in a follow-up in order to avoid another round of CI 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.
Description
Resolves #6990
See https://github.com/Mbed-TLS/mbedtls/blob/development/docs/architecture/psa-migration/md-cipher-dispatch.md#md-light specifically sub-sections "MD algorithm support macros" to "Error code conversion". (The first subsection was #7120.)
The first few commits just port the implementation from Gilles's original prototype, with a few related additions (for example, handle size macros at the same time as utility functions). Then changes between the original prototype and the final design document (that is, the dynamic aspect of dispatch) are implemented.
Gatekeeper checklist