Skip to content
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

subsys: jwt: add PSA crypto alternative to legacy libraries (TinyCrypt for ECDSA and Mbed TLS for RSA) #78243

Merged
merged 3 commits into from
Oct 8, 2024

Conversation

valeriosetti
Copy link
Collaborator

@valeriosetti valeriosetti commented Sep 10, 2024

Following the discussion of the Security WG meeting of September, 9th, TinyCrypt should be deprecated soon and jwt is the only place in Zephyr's codebase where there is no PSA/Mbed TLS alternative to TinyCrypt to perform ECDSA.
The main goal of this PR is to solve this limitation, but it also add some extra improvements:

  • a little reshape of subsys/jwt code, isolating signature functions;
  • improving the test coverage;
  • fix test's conf file.

Copy link
Collaborator

@d3zd3z d3zd3z left a comment

Choose a reason for hiding this comment

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

Looks good. Probably worth going through the clang-format suggestions just to keep the warnings down. Most seem to have to do with line breaks in function argument lists.


if JWT_SIGN_ECDSA

config JWT_SIGN_ECDSA_PSA
Copy link
Collaborator

Choose a reason for hiding this comment

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

Just curious, does the PSA configuration basically assume/assert that there is a proper CSPRNG enabled? Otherwise, should we check that. Signing multiple messages with the same nonce in EDCSA is a devastating failure.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I would say that the answer is yes, but it might depend on your configuration/platform capabilities.
I've recently done some change on how the Mbed TLS's PSA can handle random generation. You have basically 2 choices:

  • legacy, where psa_generate_random() calls to the legacy Mbed TLS modules (i.e. entropy + ctr/hmac drbg) to get random values; in this case the entropy module calls back to Zephyr to poll some random values. It first tries with CS sources, then it falls back to non-CS ones.

  • external, where psa_generate_random() calls to CS-only sources. In this case there is the possibility to use non-CS sources (via CONFIG_MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG_ALLOW_NON_CSPRNG), but there are warning during the build that clearly state that this is meant to be used only as test.

@valeriosetti
Copy link
Collaborator Author

Probably worth going through the clang-format suggestions just to keep the warnings down

I should have addressed most of them. There should be only complains about adding a space after casts, ex: (void) variable instead of (void)variable. Current clang-format wants the latter , but I prefer the former version. Wdyt?

In case my preference makes sense, can I edit the current .clang-format file adding SpaceAfterCStyleCast: True?

Copy link
Collaborator

@tomi-font tomi-font left a comment

Choose a reason for hiding this comment

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

Looks good. Just some minor comments.

subsys/jwt/Kconfig Outdated Show resolved Hide resolved
subsys/jwt/Kconfig Show resolved Hide resolved
subsys/jwt/jwt.c Outdated Show resolved Hide resolved
subsys/jwt/jwt.c Outdated Show resolved Hide resolved
subsys/jwt/jwt_ecdsa.c Outdated Show resolved Hide resolved
subsys/jwt/Kconfig Show resolved Hide resolved
subsys/jwt/jwt_ecdsa.c Outdated Show resolved Hide resolved
subsys/jwt/jwt_ecdsa.c Outdated Show resolved Hide resolved
tests/subsys/jwt/testcase.yaml Outdated Show resolved Hide resolved
tests/subsys/jwt/testcase.yaml Outdated Show resolved Hide resolved
@valeriosetti valeriosetti force-pushed the jwt-replace-tc branch 6 times, most recently from 7e409ee to 51d5e09 Compare September 12, 2024 14:37
prompt "Select crypto library to be used"

config JWT_USE_PSA
bool "PSA crypto API library"
Copy link
Collaborator

Choose a reason for hiding this comment

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

Don't you want to add some depends on here?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Right. I implemented what you proposed here

Copy link
Collaborator

Choose a reason for hiding this comment

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

As this is changing the default behavior (now defaulting to PSA, enabling what's needed) we may want a migration guide entry.

subsys/jwt/Kconfig Outdated Show resolved Hide resolved
subsys/jwt/Kconfig Outdated Show resolved Hide resolved
subsys/jwt/jwt.c Show resolved Hide resolved
subsys/jwt/CMakeLists.txt Outdated Show resolved Hide resolved
subsys/jwt/jwt.c Outdated Show resolved Hide resolved
subsys/jwt/jwt_psa.c Outdated Show resolved Hide resolved
subsys/jwt/jwt_psa.c Show resolved Hide resolved
subsys/jwt/jwt_psa.c Show resolved Hide resolved
subsys/jwt/jwt_ecdsa.c Outdated Show resolved Hide resolved
subsys/jwt/Kconfig Outdated Show resolved Hide resolved
prompt "Select crypto library to be used"

config JWT_USE_PSA
bool "PSA crypto API library"
Copy link
Collaborator

Choose a reason for hiding this comment

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

As this is changing the default behavior (now defaulting to PSA, enabling what's needed) we may want a migration guide entry.

@valeriosetti valeriosetti changed the title subsys: jwt: add PSA crypto alternative to TinyCrypt to perform ECDSA subsys: jwt: add PSA crypto alternative to legacy libraries (TinyCrypt for ECDSA and Mbed TLS for RSA) Sep 13, 2024
@zephyrbot zephyrbot added the Release Notes To be mentioned in the release notes label Sep 13, 2024
@valeriosetti
Copy link
Collaborator Author

In the last forced-push I just updated the documentation, so I assume the CI will still be fine and the PR is now ready for reviews again :)

doc/releases/migration-guide-4.0.rst Outdated Show resolved Hide resolved
tomi-font
tomi-font previously approved these changes Sep 24, 2024
@valeriosetti
Copy link
Collaborator Author

@d3zd3z @ceolin I think this is ready for reviews if/when you have some spare review bandwidth :)

Copy link
Contributor

@dkalowsk dkalowsk left a comment

Choose a reason for hiding this comment

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

Minor comment, with the rest looking overall good to me.

* SPDX-License-Identifier: Apache-2.0
*/

int jwt_sign_impl(struct jwt_builder *builder, const unsigned char *der_key,
Copy link
Contributor

Choose a reason for hiding this comment

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

you may want some header guards here. Additionally for this to be stand-alone the include where jwt_builder is defined should be added to the file... or forward declared as it's a pointer to force the compiler to warn about transitive includes.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

You're absolutely right. Thanks for both suggestions!

JWT (JSON Web Token)
====================

* By default signature is now computed through PSA Crypto API for both RSA and ECDSA.
Copy link
Contributor

Choose a reason for hiding this comment

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

I think you're missing a word here... By default, <something> signature is now...

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Rather than a word I would say an article, "the". JWT assumes that the JSON content is signed and "signature" is the subject of this sentence, so I would say that "by default, the signature" should be fine.
However I'm not a native english speaker, so I might miss something so please I apologize for any mistake.

Copy link
Collaborator

Choose a reason for hiding this comment

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

To be even more precise you could add JWT: the JWT signature is now

tomi-font
tomi-font previously approved these changes Oct 3, 2024
@d3zd3z
Copy link
Collaborator

d3zd3z commented Oct 4, 2024

Probably worth going through the clang-format suggestions just to keep the warnings down

I should have addressed most of them. There should be only complains about adding a space after casts, ex: (void) variable instead of (void)variable. Current clang-format wants the latter , but I prefer the former version. Wdyt?

In case my preference makes sense, can I edit the current .clang-format file adding SpaceAfterCStyleCast: True?

Not using a space between a cast and the value is almost universal across programming conventions. I'd suggest getting used to it.

Copy link
Collaborator

@d3zd3z d3zd3z left a comment

Choose a reason for hiding this comment

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

I think you should fix the spacing on casts, and use the ARG_UNUSED() macro. The others from clang-format are not good, and maybe we want to propose fixing that in another PR.

sys_rand_get(entropy, sizeof(entropy));

int res = tc_ctr_prng_init(&prng_state, (const uint8_t *) &entropy, sizeof(entropy),
personalize, sizeof(personalize));
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'd suggest fixing this, not using a space after a cast is near universal in C style conventions.

struct tc_sha256_state_struct ctx;
uint8_t hash[32];
int res;
(void) sig_size;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Please use ARG_UNUSED(sig_size);

psa_set_key_type(&attr, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
psa_set_key_algorithm(&attr, PSA_ALG_ECDSA(PSA_ALG_SHA_256));
alg = PSA_ALG_ECDSA(PSA_ALG_SHA_256);
#else /* CONFIG_JWT_SIGN_RSA */
Copy link
Collaborator

Choose a reason for hiding this comment

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

This is rather silly and picky of it, but might as well comply.

return -EINVAL;
}

status = psa_sign_message(key_id, alg,
Copy link
Collaborator

Choose a reason for hiding this comment

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

I care less about this, since I think your formatting is slightly more readable, as it groups the things that go together.

* $ openssl ecparam -name prime256v1 -genkey | openssl ec -outform der | xxd -ps
* - copy the content to https://lapo.it/asn1js/
* - get the first OCTECT STRING, which is the private key, and copy it here
*/

unsigned char jwt_test_private_der[] = {
Copy link
Collaborator

Choose a reason for hiding this comment

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

In this case, the clang format output is actively terrible. If you have ideas on improving the config for this one, perhaps that should be proposed. But, not in this PR, just leave it.

This commit:

- creates 2 new files, jwt_ecdsa.c and jwt_rsa.c, to hold the
  implementations of the corresponding ECDSA/RSA signature
  algorithms;
- RSA signature is stil done through Mbed TLS's PK module which
  can optionally make use of PSA (if enabled);
- ECDSA signature will instead use PSA, if possible, or TinyCrypt
  as fallback.

Signed-off-by: Valerio Setti <vsetti@baylibre.com>
- Some files (PEM/DER files, jwt-test-cert.c, user-tls-conf.h)
  were removed because they are not used or no longer necessary.
  Private keys used in the test are now in the jwt-test-private.c
  file as arrays.
- testcase.yaml has been improved in order to test all possible
  use cases: ECDSA with TC, ECDSA with PSA, RSA;
- unnecessary Kconfigs were removed from prj.conf.

Signed-off-by: Valerio Setti <vsetti@baylibre.com>
Update JWT subsystem documentation concerning the changes related
to:

- default library used
- new Kconfigs added

Signed-off-by: Valerio Setti <vsetti@baylibre.com>
@nashif nashif merged commit 64ecbea into zephyrproject-rtos:main Oct 8, 2024
23 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: JSON Release Notes To be mentioned in the release notes
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants