-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Feature unavailable unified error support #2124
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
Feature unavailable unified error support #2124
Conversation
Note: documentation updated in https://github.com/ARMmbed/mbed-tls-docs/pull/112 |
updated changeLog, although I am not sure this change in tests and the benchmark application requires a ChangeLog entry. |
4a6f04f
to
9aa3d09
Compare
7ecb4ba
to
f3d2595
Compare
#2054 has been merged, so no more waiting for preceding PR |
f3d2595
to
9f9594b
Compare
9f9594b
to
c2d37de
Compare
After rebase I have tested on PC, to check nothing got broken. I am currently building on target with unsupported features, and fix if new issues arise from the rebase ( such as new tests introduced that require the new macro) |
I have tested on target NRF52840_DK. |
Add @mpg as a reviewer on the x509 module |
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.
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 reviewed the PR except for the changes to the tests to use TEST_ASSERT_RET
or TEST_ASSERT_FLAGS
.
With respect to the design:
- This PR makes some functions return an unadorned
MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED
when other low-level errors are combined with a high-level error. This isn't necessarily a bad thing, but I need to think further about the possible implications, and I'd like @mpg's opinion on this change. - I'm mostly ok with the test case skipping feature, but it should use a tristate, not two booleans. Please take a look at Tolerate failures from unsupported operations in RSA test suites #1308 which introduced a test case skipping feature to see if there would be problems reconciling them. Do we want a different message for “skipped because of an unsupported feature in the hardware” and “skipped because of an unmet assumption”? Cc @hanno-arm
- The change in the X509 module needs design approval from @sbutcher-arm or someone delegated by him.
programs/test/benchmark.c
Outdated
@@ -441,7 +449,21 @@ int main( int argc, char *argv[] ) | |||
|
|||
memset( buf, 0, sizeof( buf ) ); | |||
memset( tmp, 0, sizeof( tmp ) ); | |||
mbedtls_aes_setkey_enc( &aes, tmp, keysize ); | |||
ret = mbedtls_aes_setkey_enc( &aes, tmp, keysize ); | |||
if( ret != 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.
This whole sequence is repeated many times. How about making it a macro, or a small number of macros (with and without 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.
ok
programs/test/benchmark.c
Outdated
@@ -884,18 +1062,41 @@ int main( int argc, char *argv[] ) | |||
curve_info++ ) | |||
{ | |||
mbedtls_ecdh_init( &ecdh ); | |||
mbedtls_snprintf( title, sizeof( title ), "ECDHE-%s", | |||
curve_info->name ); | |||
if( mbedtls_ecp_group_load( &ecdh.grp, curve_info->grp_id ) != 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.
Why no check for FEATURE_UNSUPPORTED
here? We don't currently provide a hook there, but I'd prefer to keep the benchmark code consistent rather than micro-optimize 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.
ok
programs/test/benchmark.c
Outdated
if( ret != 0 ) \ | ||
if( ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED ) \ | ||
{ \ | ||
mbedtls_printf( "Feature Not Supported. Skipping.\n" ); \ |
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: “Feature not supported.” (here and elsewhere)
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
tests/suites/helpers.function
Outdated
@@ -119,6 +136,7 @@ static struct | |||
const char *test; | |||
const char *filename; | |||
int line_no; | |||
int skipped; |
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.
There are only 3 possible outcomes, not 4: pass, skip, fail. I'd prefer a single variable with 3 possible states (an enum) rather than two boolean variables with one unused combination. Like #1308 but using an enum instead of magic constants (0, 1, 2).
tests/suites/helpers.function
Outdated
|
||
|
||
/*----------------------------------------------------------------------------*/ | ||
/* Macros */ | ||
|
||
#define TEST_ASSERT_RET( TEST, EXP_RET ) \ | ||
do { \ | ||
int ret = (TEST); \ |
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.
Please don't use a generic name like ret
inside a macro: it is likely to conflict with a name used outside of the macro. Use e.g. TEST_ASSERT_RET__ret
.
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.
yes, this is why I renamed all ret
in the tests to something like exp_ret
library/ecdsa.c
Outdated
mbedtls_ecp_gen_keypair( &ctx->grp, &ctx->d, &ctx->Q, f_rng, p_rng ) ); | ||
int ret = 0; | ||
ret = mbedtls_ecp_group_load( &ctx->grp, gid ); | ||
if( ret == 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.
Minor: I think it would be more readable to use the common idiom if( ret != 0 ) return( ret );
library/ecdsa.c
Outdated
@@ -752,8 +752,12 @@ int mbedtls_ecdsa_read_signature_restartable( mbedtls_ecdsa_context *ctx, | |||
int mbedtls_ecdsa_genkey( mbedtls_ecdsa_context *ctx, mbedtls_ecp_group_id gid, | |||
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) | |||
{ | |||
return( mbedtls_ecp_group_load( &ctx->grp, gid ) || | |||
mbedtls_ecp_gen_keypair( &ctx->grp, &ctx->d, &ctx->Q, f_rng, p_rng ) ); | |||
int ret = 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.
Oooh, the old code had a bug and the fix should be backported. f() || g()
returned 1 on failure. This broke application code that looks for errors with if (mbedtls_ecdsa_genkey(…) < 0)
, which should be correct because the library normally returns negative values on error. This should also be mentioned in the changelog as a bugfix.
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.
Backported to 2.7 in #2296
library/pkparse.c
Outdated
@@ -529,7 +530,11 @@ static int pk_get_rsapubkey( unsigned char **p, | |||
|
|||
if( ( ret = mbedtls_rsa_import_raw( rsa, *p, len, NULL, 0, NULL, 0, | |||
NULL, 0, NULL, 0 ) ) != 0 ) | |||
return( MBEDTLS_ERR_PK_INVALID_PUBKEY ); | |||
{ | |||
if( ret != MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED ) |
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 documentation in pk.h
needs to be updated to add MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED
as a possible error where applicable.
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 disagree. See the answer to comment #2054 (comment)
The error code MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED can be returned by any underlying hw driver, and it is documented in our articles. I don't think that pk.h should have a special treatment. This is a generic error code that cipher.h
could also return
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.
My objection stands. We don't expect users to read our articles and deduce that statements in the documentation are wrong. If the documentation merely says “a negative value on error”, that's not ideal, but it's ok. But if the documentation explicitly lists the possible errors, then the list must include MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED
. It can do so by name or by saying that generic platform errors are possible, or any other form of statement that doesn't explicitly exclude this error.
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 disagree that we should mention generic error codes in our function description, however, I'm willing to add the generic platform errors are possible statement (MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED
is also an option)
library/pkparse.c
Outdated
@@ -1343,7 +1361,9 @@ int mbedtls_pk_parse_key( mbedtls_pk_context *pk, | |||
* also ok and in line with the mbedtls_pk_free() calls | |||
* on failed PEM parsing attempts. */ | |||
|
|||
return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); | |||
if( ret & MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED ) |
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.
Masking an error code doesn't make sense. Did you mean “if the low-level error is feature-unsupported then mask out the high-level error”? That would be
if( ( ret & -0x7f ) == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED )
library/pkparse.c
Outdated
@@ -1343,7 +1361,9 @@ int mbedtls_pk_parse_key( mbedtls_pk_context *pk, | |||
* also ok and in line with the mbedtls_pk_free() calls | |||
* on failed PEM parsing attempts. */ | |||
|
|||
return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); | |||
if( ret & MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED ) | |||
return( MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED ); |
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 does MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED
get this special treatment of masking out the high-level error? And similarly in other places why does it get the special treatment of not masking in a high-level error?
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 didn't want to change behavior of function, so returning MBEDTLS_ERR_PK_KEY_INVALID_FORMAT
on failure.
MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED
is a special use case, as user need to know that it might not be a "real" failure, and tests should skip on this failure.
I can consider returning ret
in this case, or MBEDTLS_ERR_PK_KEY_INVALID_FORMAT | MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED
@gilles-peskine-arm Thank you for the review. I addressed your comments, and will make the fixes shortly. As for your general comments:
I did this only when the low level flags are
Ok, I'll change. Actually, The behavior should be the same for both PRs. This PR already handle rsa feature unsupported as well. I believe in rsa_alt case as well.
As you can see from #2124 (review) , @mpg already reviewed and approved the changes in the x509 module. |
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.
Look mostly good. I've left a few fairly minor comments, please take a look.
library/pkparse.c
Outdated
|
||
*p += len; | ||
|
||
if( mbedtls_rsa_complete( rsa ) != 0 || | ||
mbedtls_rsa_check_pubkey( rsa ) != 0 ) | ||
if( ( ret = mbedtls_rsa_complete( rsa ) ) != 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.
which value of ret do you check later? seems to me that you would only check the second one below?
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 Boolean condition. If the first statement fails, then we return the first ret
, if the second statement fails then the second ret
is returned
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.
scratch 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.
Actually, don't scratch it. If the first statement is true ( ret != 0
) then we don't call the second statement
library/rsa.c
Outdated
{ | ||
return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); | ||
return( ret ); |
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.
same as above seems that the second error is returned in case both return error, is the this the desired behavior?
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 first statement fails, then the second statement is not even called
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.
scratch 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.
Actually, don't scratch it. If the first statement is true ( ret != 0
) then we don't call the second statement
@NirSonnenschein I have modified according to your comment, in order to make the code more readable. Note that the original change in |
ce31dad
to
d7c33c6
Compare
d7c33c6
to
e1e7bea
Compare
1. Return error in `crypt_and_hash` in case `mbedtls_cipher_finish()` fails. 2. Support the `MBEDTLS_PLATFORM_FEATURE_UNSUPPORTED` in the benchmark application, to be skipped.
Introduce `TEST_ASSERT_RET` to skip tests with functions that return `MBEDTLS_PLATFORM_FEATURE_UNSUPPORTED`.
1. Change `TEST_ASSERT` to `TEST_ASSERT_RET` in all the tests of the symmetric ciphers, aead and digests. 2. Modify the `cipher` module to return the error returned by the underlying chacha error. 3. In aead tests, set the expected decryption return code prior to decryption, to distinguish between negative and positive paths. 4. Have xtea return error code of `mbedtls_xtea_crypt_ecb`, and zeroize output on failure.
1. Add verification failure flags for feature unsupported. 2. Add the verification flag when verifying certificate, to distinguish between verification failure because the underlying hw does not support the speciic feature, such as curve, rsa key size, and a verification failure because the certificate might be tampered.
1. Change `TEST_ASSERT` to `TEST_ASSERT_RET`. 2. Add dependency in `MBEDTLS_RSA_C` in one of the tests that was missing.
Add ChangeLog entry.
Add an error for Feature Unsupported to be returned to the host, and to be skipped.
1. Change typo in log. 2. Create a macro for the symmetric set key functionality. 3. Check for Feature not supported error in des key setting.
1. Define an enum for test result. 2. Rename `ret` to a less generic name, inside `TEST_ASSERT_RET`.
Rephrase comments.
Adjust the invalid param tests to the unsupported feature error returned by the underlying platform: 1. Skip the test in case `MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED` is returned. 2. Adjust to `test_info.result` enum. 3. Change `TEST_ASSERT` to `TEST_ASSERT_RET`.
Fix typo in the x509 module.
Fix a typo in `mbedtls_test.py` script.
Remove redundant extra lines in the benchmark application.
Add `CHECK_AND_BREAK` for the tests that run inside a timing loop, and add declaration of `mbedtls_snprintf` in case platform doesn't exist.
The uint32 is given as a bigendian stream, in the tests, however, the char buffer that collected the stream read it as is, without converting it. Add a temporary buffer, to call `greentea_getc()` 8 times, and then put it in the correct endianity for input to `unhexify()`.
Include `platform.h` even if `MBEDTLS_PLATFORM_C` is undefined, to include the feature unsupported error.
e1e7bea
to
57643d5
Compare
Rebased to resolve conflicts |
This PR is about improving support for |
Description
This PR adds support for
MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED
introduced in #2054Tests that receive this error, skip to the next step, as the underlying HW accelerator does not support that specific feature.
Exception are the entropy, when the SHA function returns such an error, as the specific entropy source is dependent on the SHA function, and not configurable, and the ctr_drbg, when the specific AES functionality is not supported, as it is dependent on it to work. Skipping the tests may result in security issue, if developer assumes the test passes.
Second PR that supersedes #1716
Status
READY
Requires Backporting
NO
Migrations
Error codes have been removed, so we may consider this as an API changeAdditional comments
ctr_drbg requires
MBEDTLS_CTR_DRBG_USE_128_BIT_KEY
to be defined, in case AES 256 is not supported by the HW,once PR #1902 will be merged.Note: Once #2054 will be merged, I will rebase to have the support for the on target testing to run, but this PR can start the reviewTodos