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

RSA key check consolidation part 1a #1349

Merged
merged 11 commits into from
Feb 26, 2024

Conversation

dkostic
Copy link
Contributor

@dkostic dkostic commented Dec 8, 2023

Issues:

CryptoAlg-2280

Description of changes:

This is the first PR in a series of PRs that will attempt to
consolidate the RSA key checking in AWS-LC. The high level
plan is to do the following:

  1. Implement RSA_check_key| that performs checks equivalent to
    those in OpenSSL 1.x versions and 3.x non-FIPS versions of
    RSA_check_key with the exception of the primality tests, while
    retaining the ability to process public keys.
  2. Implement RSA_check_fips that performs SP 800-56b checks
    as OpenSSL 3.x RSA_check_key does when built in FIPS mode.
  3. When ready, modify RSA_check_key function to call
    RSA_check_fips when AWS-LC is built in FIPS mode,
    and deprecate RSA_check_fips.

Two temporary functions will be introduced and used for development,
until the whole solution is done:

  • wip_do_not_use_rsa_check_key,
  • wip_do_not_use_rsa_check_key_fips.

After completing step 1 from above, wip_do_not_use_rsa_check_key
should become RSA_check_key function.
After completing step 2 from above, wip_do_not_use_rsa_check_key_fips
should become RSA_check_fips function.
After completing step 3 from above, RSA_check_key function should
perform the RSA_check_fips checks when built in FIPS mode, and
RSA_check_fips could be deprecated.

This change introduces the two temporary functions, implements a few
checks and adds tests alongside the existing tests for RSA_check_key.

Call-outs:

Point out areas that need special attention or support during the review process. Discuss architecture or design changes.

Testing:

How is this change tested (unit tests, fuzz tests, etc.)? Are there any testing steps to be verified by the reviewer?

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license and the ISC license.

@dkostic dkostic requested a review from a team as a code owner December 8, 2023 00:06
@dkostic dkostic changed the title RSA key check consolidation RSA key check consolidation part 1a Dec 8, 2023
@codecov-commenter
Copy link

codecov-commenter commented Dec 8, 2023

Codecov Report

Attention: 26 lines in your changes are missing coverage. Please review.

Comparison is base (eaa19c7) 76.89% compared to head (454e828) 76.85%.
Report is 36 commits behind head on main.

Files Patch % Lines
crypto/fipsmodule/rsa/rsa.c 77.19% 26 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1349       /-   ##
==========================================
- Coverage   76.89%   76.85%   -0.04%     
==========================================
  Files         425      425              
  Lines       71527    71614       87     
==========================================
  Hits        55000    55040       40     
- Misses      16527    16574       47     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@nebeid nebeid self-requested a review December 12, 2023 21:20
crypto/fipsmodule/rsa/rsa.c Outdated Show resolved Hide resolved
crypto/fipsmodule/rsa/rsa.c Outdated Show resolved Hide resolved
@dkostic dkostic marked this pull request as draft December 21, 2023 19:34
@dkostic dkostic force-pushed the rsa-key-check-consolidation branch 2 times, most recently from ca05c66 to a9dfbc4 Compare January 31, 2024 22:15
@dkostic dkostic marked this pull request as ready for review January 31, 2024 22:31
// - 1 < log(e, 2) <= 33,
// - n and e are odd,
// - n > e.
static int is_public_component_of_rsa_key_good(const RSA *key) {
Copy link
Contributor

@nebeid nebeid Feb 9, 2024

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.

I wanted to start with a clean slate so that we can clearly define the requirements, implement, and properly document them (I think part of the reason for the current mess is updating different functions over time without proper documentation and checking where and how they are used). Once the new key checking functions are done I intend to delete the old ones.

return 0;
}

if (!BN_is_odd(key->n)) {
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 keep comments from rsa_check_public_key()?
https://github.com/aws/aws-lc/blob/main/crypto/fipsmodule/rsa/rsa_impl.c#L76

Copy link
Contributor Author

Choose a reason for hiding this comment

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

added a comment.

// the limit based on the recommendations in:
// - https://www.imperialviolet.org/2012/03/16/rsae.html
// - https://www.imperialviolet.org/2012/03/17/rsados.html
if (e_bits < 2 || e_bits > 33) {
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 keep kMaxExponentBits instead of 33?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

don't see a reason for that, the comment states 33 explicitly and also justifies it.

return 0;
}

if (!BN_is_odd(key->e)) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Can be combined with the check above as in the original code.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I know, but I like it more this way. I was also able to add a comment explaining why is e odd.

return 0;
}

if (BN_ucmp(key->n, key->e) <= 0) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Isn't the original check which compares if (n_bits <= kMaxExponentBits) then error more economical?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

this is pointless optimization in my opinion and it only makes it harder to reason about the code.

Copy link
Contributor

Choose a reason for hiding this comment

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

The way I see it is that we already calculated n_bits. I think the check on n_bits <= kMaxExponentBits is not hard to read, if we also keep that constant name. What do you think?

Copy link
Contributor

Choose a reason for hiding this comment

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

We agreed to leave it as is.

//
// Note: see the rsa_key_type_for_checking enum for details on types of keys
// the function can work with.
int wip_do_not_use_rsa_check_key(const RSA *key) {
Copy link
Contributor

Choose a reason for hiding this comment

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

There is a "multi-prime" check in the original function (which I didn't dive into); will we replace it here or in another function?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

not sure what you mean by multi-prime check?

Copy link
Contributor

@nebeid nebeid Feb 16, 2024

Choose a reason for hiding this comment

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

Sorry, I cannot find where I was looking, maybe an old version. multi-prime was removed from aws-lc (boringssl), I believe starting here 4a2cc28

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ah yeah, we don't support multi-prime RSA (OpenSSL does).

// (n, e, d, p, q, dmp1, dmq1, iqmp)
if (key->d != NULL && key->p != NULL && key->q != NULL &&
key->dmp1 != NULL && key->dmq1 != NULL && key->iqmp != NULL) {
return RSA_KEY_TYPE_FOR_CHECKING_PRIVATE_CRT;
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we want to handle the special case of returning RSA_R_INCONSISTENT_SET_OF_CRT_VALUES as in

int has_crt_values = key->dmp1 != NULL;
if (has_crt_values != (key->dmq1 != NULL) ||
has_crt_values != (key->iqmp != NULL)) {
OPENSSL_PUT_ERROR(RSA, RSA_R_INCONSISTENT_SET_OF_CRT_VALUES);
goto out;
}
?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I was thinking about that but decided not to (OpenSSL doesn't have this error either, in fact, they'll allow inconsistent set of CRT values).

nebeid
nebeid previously approved these changes Feb 16, 2024
return 0;
}

if (BN_ucmp(key->n, key->e) <= 0) {
Copy link
Contributor

Choose a reason for hiding this comment

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

We agreed to leave it as is.

Comment on lines 1199 to 1200
// Keys that reach this point are either private keys (n, e, p, q, d),
// or CRT keys with (dmp1, dmq1, iqmp) values precomputed.
Copy link
Member

Choose a reason for hiding this comment

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

Should we check that key_type matches this assumption? It would be more for the unlikely event we were to add another key type to the enum but don't update any check logic.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

good idea, added

Comment on lines 1267 to 1269
// - dmp1 == d mod (p - 1),
// - dmq1 == d mod (q - 1),
// - (iqmp * q) mod (p) == 1.
Copy link
Member

Choose a reason for hiding this comment

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

Do we actually use any of these CRT parameters in RSA key operations?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yes, take a look here https://github.com/aws/aws-lc/blob/main/crypto/fipsmodule/rsa/rsa_impl.c#L792, the modular exponentiation function mod_exp uses the CRT parameters. RSA private key operations are very slow if you don't use them.

@dkostic dkostic merged commit 0a470e4 into aws:main Feb 26, 2024
38 of 39 checks passed
@dkostic dkostic deleted the rsa-key-check-consolidation branch February 26, 2024 16:13
dkostic added a commit that referenced this pull request Mar 14, 2024
This is the second PR in a series of PRs that will attempt to
consolidate the RSA key checking in AWS-LC. In this PR:
  - replace RSA_check_key with the new implementation from #1349:
    (0a470e4)
  - add support for stripped private keys (JCA),
  - remove RSA_validate_key.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants