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

openssl3 integration: use EVP_PKEY_get1_RSA to avoid modifying const RSA key #3473

Closed
wants to merge 5 commits into from

Conversation

toidiu
Copy link
Contributor

@toidiu toidiu commented Aug 30, 2022

This change is based on top of a previous PR and the relevant commit is a7f134e

#3442

Description of changes:

The API and behavior for EVP_PKEY_get0_RSA has change in openssl3. The main difference is that the return value is now marked as const, which triggers warnings across the codebase. The second difference is that the return value is no longer direct reference to the PKEY, but instead a reference to a pre-cached value.

oss1 EVP_PKEY_get0_RSA: direct reference, not-const, should not be freed
oss3 EVP_PKEY_get0_RSA: pre-cached copy, const, should not be freed

Our codebase is making a few assumptions at the moment:


Solution

  1. The solution to the above issue is that we should use the same implementation for s2n_rsa and s2n_rsa_pss keys.. switch to using EVP_PKEY_get1_RSA. Since EVP_PKEY_get1_RSA returns a copy, and needs to be freed, we need to free the key in s2n_rsa_pass.c.
  2. We need to update all usage of EVP_PKEY_get0_RSA -> EVP_PKEY_get1_RSA in tests and subsequently call free.
  3. We need to call EVP_PKEY_set1_RSA to set an PKEY since in ossl3 a pre-cached value is returned rather than the direct key

Testing:

  • openssl 1.0.2 (unit tests pass)
  • openssl 3 (unit tests and asan tests passes locally)
    Running /home/ubuntu/projects/rsync/s2n-tls/tests/unit/s2n_rsa_pss_rsae_test.c ... PASSED 213 tests

Code analysis:


Is this a refactor change? If so, how have you proved that the intended behavior hasn't changed?

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

@github-actions github-actions bot added the s2n-core team label Aug 30, 2022
@toidiu toidiu changed the title Ak openssl3 rsa openssl3 integration: use EVP_PKEY_get1_RSA to avoid modifying const RSA key Aug 30, 2022
@toidiu toidiu marked this pull request as ready for review August 30, 2022 19:49
@toidiu toidiu requested a review from a team as a code owner August 30, 2022 19:49
@toidiu toidiu requested review from lrstewart and maddeleine August 30, 2022 19:51
@toidiu toidiu requested a review from franklee26 August 30, 2022 20:26
@toidiu toidiu force-pushed the ak-openssl3_rsa branch 2 times, most recently from 576a0c1 to 0ba4d24 Compare August 30, 2022 23:34
@toidiu toidiu enabled auto-merge (squash) August 31, 2022 17:56
Comment on lines +202 to 203
RSA *priv_rsa_key = EVP_PKEY_get1_RSA(pkey);
POSIX_ENSURE_REF(priv_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.

Are you sure we don't want RSA* to be const? Now that the behavior has changed and modifying the RSA key isn't reflected back in the EVP_PKEY, isn't this likely to cause bugs? How do you know we're not relying on that behavior?

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 usage is consistent with rsa and ecdsa. That means that we make similar assumptions in all the other implementations also:

The assumptions in ossl1:

  • we are getting a raw ref to the key
  • the ref count is incremented so we need to call free
  • since its a raw ref, we can mutate it

The assumptions in ossl3:

  • we are getting a ref to a pre-cached copy of the key
  • the ref count of the copy is incremented so we need to call free
  • we can can mutate the copy, but the changes are not reflected back to the original key
    • this is ok since we dont modify the key (except free) (based on my investigation of methods allowed on keys)
    • this is ok if we store the copy in s2n_rsa_key(the copy) and dont actually use the original

In conclusion, why PR impl is Safe but brittle:

  • get1 allows us to get around the api changes introduced with get0
    • this forces us to call free on the key
  • ossl3 now returns a pre-cached copy, but that is ok since the key is not mutated
  • if we do mutate then we violate the above behavior

Alternative and reasons why I didnt go that route:

  • use PKEY directly: this is a large refactor change (if we are really uncomfortable with the current behavior then this would be the recommended approach. This can/should also be follow up work since the above is not a 1-way door)
  • use get0 and const: this is a large refactor change since s2n_rsa.c and rsa_signing will need to change. its also less prefered to using PKEY directly imo

Copy link
Contributor

Choose a reason for hiding this comment

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

As discussed offline, "if we do mutate then we violate the above behavior" is what I'm concerned about. The new Openssl 3.0 behavior effectively makes the RSA* object const, but that's not reflected anywhere in our code. Nothing will stop a future dev from trying to modify the key, and things will not behave as someone reading this code would expect them to. This seems like a recipe for bugs.

If we're not going to make RSA* const, then we minimally need very scary comments everywhere that they key is referenced.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

specifically here is an impl which stores PKEY and converts to RSA when needed. Its also the recommended ossl approach: b9fd783

@toidiu toidiu disabled auto-merge August 31, 2022 19:47
Comment on lines +179 to +180
return 0;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit

Suggested change
return 0;
}
return S2N_SUCCESS;
}

@toidiu
Copy link
Contributor Author

toidiu commented Sep 6, 2022

closing in favor of #3474

@toidiu toidiu closed this Sep 6, 2022
@toidiu
Copy link
Contributor Author

toidiu commented Sep 6, 2022

closing in favor of #3474

@toidiu toidiu deleted the ak-openssl3_rsa branch September 6, 2022 22:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants