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

Use features to set key exchange preferences #145

Merged
merged 1 commit into from
Sep 1, 2023

Conversation

cjpatton
Copy link
Collaborator

@cjpatton cjpatton commented Aug 9, 2023

Overwrite boringSSL's default key exchange preferences with safe
defaults using feature flags:

  • "kx-client-pq-supported" enables support for PQ key exchange algorithms.
    Classical key exchange is still preferred, but will be upgraded to PQ
    if requested.

  • "kx-client-pq-preferred" enables preference for PQ key exchange,
    with fallback to classical key exchange if requested.

  • "kx-client-nist-required" disables non-FIPS-compliant algorithms on the client side.

If any of these "kx-*" features are enabled, then don't compile bindings
for SSL_CTX_set1_curves(). This is to prevent the feature flags from
silently overriding curve preferences chosen by the user.

Ideally we'd allow both: that is, use "kx-*" to set defaults, but still
allow the user to manually override them. However, this doesn't work
because by the time the SSL_CTX is constructed, we don't yet know
whether we're the client or server. (The "kx-*" features set different
preferences for each.)

@cjpatton cjpatton requested a review from inikulin August 9, 2023 15:11
@cjpatton cjpatton marked this pull request as draft August 9, 2023 21:14
@cjpatton
Copy link
Collaborator Author

cjpatton commented Aug 9, 2023

I've updated the commit based on feedback on this PR and clarification of the semantics of "fips" and "fips-link-compiled". Please take another look!

@cjpatton cjpatton marked this pull request as ready for review August 9, 2023 23:55
@cjpatton cjpatton requested a review from rushilmehra August 9, 2023 23:55
@cjpatton cjpatton requested a review from inikulin August 10, 2023 23:00
@cjpatton cjpatton marked this pull request as draft August 11, 2023 00:00
@cjpatton cjpatton force-pushed the pq-by-default branch 7 times, most recently from 2300577 to de3c36c Compare August 15, 2023 17:15
@cjpatton cjpatton changed the title Use features to set default key exchange preference Use features to set default algorithm preference Aug 15, 2023
@cjpatton cjpatton force-pushed the pq-by-default branch 8 times, most recently from d70dbb9 to b960339 Compare August 15, 2023 21:59
@cjpatton cjpatton marked this pull request as ready for review August 16, 2023 01:18
@cjpatton cjpatton force-pushed the pq-by-default branch 2 times, most recently from 3aa916a to f083a08 Compare August 17, 2023 23:01
@cjpatton cjpatton force-pushed the pq-by-default branch 3 times, most recently from b3537a8 to 3c94f05 Compare August 18, 2023 15:03
@nox
Copy link
Collaborator

nox commented Aug 25, 2023

Cargo features are supposed to be strictly additive so I'm not sure that's the correct vehicle to use. That being said, I offer no alternative.

@cjpatton
Copy link
Collaborator Author

cjpatton commented Aug 25, 2023

Cargo features are supposed to be strictly additive so I'm not sure that's the correct vehicle to use.

Are you referring to the fact that "kx-safe-default" disables SslContextBuilder::set_curves()?

Hmm, I definitely we agree we should try to follow best practice if we can. (I was not aware of this convention.) I guess one option is to put the set_curves API behind its own feature. The downside would be yet another feature flag for controlling key exchange preference.

Stepping back, the intent of this PR is to make it easy as possible for our Cloudflare-internal users to enable PQ key exchange without having to manually call set_curves. There might be other ways to do this, but based on my own assessment of the code (and my abilities with Rust), this is the lowest-complexity option with the fewest side-effects. See #145 (comment).

@inikulin inikulin requested a review from nox August 29, 2023 12:16
@inikulin
Copy link
Collaborator

@nox @cjpatton my understanding is that these features are mutually exclusive, so if we add a compile time check that ensures that features are not enabled simultaneously, won't it solve the conceptual problem?

@cjpatton
Copy link
Collaborator Author

@nox @cjpatton my understanding is that these features are mutually exclusive, so if we add a compile time check that ensures that features are not enabled simultaneously, won't it solve the conceptual problem?

Yes, they're mutually exclusive. What would we want to check at compile time? That if "kx-safe-defaults" is set, then set_curves() is missing? How would we do this?

@inikulin
Copy link
Collaborator

Yes, they're mutually exclusive. What would we want to check at compile time? That if "kx-safe-defaults" is set, then set_curves() is missing? How would we do this?

in build.rs we can do something like:

let enabled_count = [
    cfg!(feature = "kx-client-pq-supported"),
    cfg!(feature = "kx-client-pq-preferred") 
    cfg!(feature = "kx-client-nist-required")
]
.iter()
.filter(|f| f)
.count();

if enabled_count > 1 {
     panic!("...");
}

we can do similar checks for feature dependencies.
Btw, we should also document feature deps: either this features should implicitly enable PQ patch feature or we need to check if it's enabled in build.rs as shown above and error if not

@cjpatton
Copy link
Collaborator Author

in build.rs we can do something like:

let enabled_count = [
    cfg!(feature = "kx-client-pq-supported"),
    cfg!(feature = "kx-client-pq-preferred") 
    cfg!(feature = "kx-client-nist-required")
]
.iter()
.filter(|f| f)
.count();

if enabled_count > 1 {
     panic!("...");
}

But where would we do this? If I understand correctly what you're after, the goal is something like: if cfg!(feature = "kx-safe-defaults") and SslContextBuilder::set_curves() is defined, then fail to build. How do we express the second condition?

Also, note that it suffices to check if "kx-safe-defaults" is set because this is implied by any of the "kx-*" features.

we can do similar checks for feature dependencies. Btw, we should also document feature deps: either this features should implicitly enable PQ patch feature or we need to check if it's enabled in build.rs as shown above and error if not

Got, will do after rebasing this PR.

@cjpatton
Copy link
Collaborator Author

Rebased.

@cjpatton
Copy link
Collaborator Author

Squashed.

@cjpatton
Copy link
Collaborator Author

cjpatton commented Sep 1, 2023

Rebased.

@cjpatton
Copy link
Collaborator Author

cjpatton commented Sep 1, 2023

Changed "nist-required" to "fips-required". Eventually X25519 might be FIPS-validated.

@inikulin
Copy link
Collaborator

inikulin commented Sep 1, 2023

@cjpatton

But where would we do this?

I think there was a misunderstanding here, I thought that @nox complained that features are mutually exclusive, i.e. kx-client-pq-preferred and kx-client-nist-required can't be used together. Apparently it's not a case.

Changed "nist-required" to "fips-required". Eventually X25519 might be FIPS-validated.

not sure how do I feel about that, this seems to be relatively distant future thing and might be confusing considering currently FIPS-validated revision

@cjpatton
Copy link
Collaborator Author

cjpatton commented Sep 1, 2023

@cjpatton

But where would we do this?

I think there was a misunderstanding here, I thought that @nox complained that features are mutually exclusive, i.e. kx-client-pq-preferred and kx-client-nist-required can't be used together. Apparently it's not a case.

Ah, OK! In fact, "kx-client-pq-preferred" and "kx-client-nist-required" can be used at the same time. The effect is that P256Kyber768Draft00 is the client's preferred key exchange algorithm.

Changed "nist-required" to "fips-required". Eventually X25519 might be FIPS-validated.

not sure how do I feel about that, this seems to be relatively distant future thing and might be confusing considering currently FIPS-validated revision

No problem, reverted.

Overwrite boringSSL's default key exchange preferences with safe
defaults using feature flags:

* "kx-pq-supported" enables support for PQ key exchange algorithms.
  Classical key exchange is still preferred, but will be upgraded to PQ
  if requested.

* "kx-pq-preferred" enables preference for PQ key exchange,
  with fallback to classical key exchange if requested.

* "kx-nist-required" disables non-NIST key exchange.

Each feature implies "kx-safe-default". When this feature is enabled,
don't compile bindings for `SSL_CTX_set1_curves()` and `SslCurve`. This
is to prevent the feature flags from silently overriding curve
preferences chosen by the user.

Ideally we'd allow both: that is, use "kx-*" to set defaults, but still
allow the user to manually override them. However, this doesn't work
because by the time the `SSL_CTX` is constructed, we don't yet know
whether we're the client or server. (The "kx-*" features set different
preferences for each.) If "kx-sfe-default" is set, then the curve
preferences are set just before initiating a TLS handshake
(`SslStreamBuilder::connect()`) or waiting for a TLS handshake
(`SslStreamBuilder::accept()`).
@cjpatton
Copy link
Collaborator Author

cjpatton commented Sep 1, 2023

Fixed up commit message.

@cjpatton cjpatton merged commit 2fa3d96 into cloudflare:master Sep 1, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants