Repository: rustls/rustls (language: rust)

Issue:
Rustls w/ aws-lc-rs on Windows requires NASM
The entire reason half the ecosystem is using rustls rather than openssl is because it "just works" without any dependencies.

Having upgraded to the latest version, I get the following error:
> error: failed to run custom build command for `aws-lc-sys v0.15.0`
> ...
> Missing dependency: nasm

It's very frustrating that `aws-lc` has been added to the default dependency list as many intermediate dependencies forget to add "default-features = false", making it in practice a hard dependency of rustls.

Please reconsider making `aws-lc` the default backend. The default backend should require *fewer* dependencies, not more. Any minor performance difference is a secondary concern.





Discussion / hints:
Which version of aws-lc-rs do you have in your tree? AIUI aws-lc-rs 1.7 requires fewer extra dependencies than before on the most common platforms at least.
1.7
This is on 64-bit windows using MSVC toolchain, so a fairly standard platform, and NASM is not listed as a required dependency anywhere that I could see.
> and NASM is not listed as a required dependency anywhere that I could see.

https://aws.github.io/aws-lc-rs/requirements/

Heard you on the frustration with additional dependencies, especially on Windows. See https://github.com/aws/aws-lc-rs/issues/364 upstream for the specific NASM requirement.
> AIUI aws-lc-rs 1.7 requires fewer extra dependencies than before

Indeed, but I think there's still a ways to go for Windows in particular w.r.t the `nasm` requirement. 

Hopefully these improvements continue!

> NASM is not listed as a required dependency anywhere that I could see.

The [0.23.0](https://github.com/rustls/rustls/releases/tag/v%2F0.23.0) release notes that brought the change to aws-lc-rs as default mentions it:  "Note that this has some implications on [platform support and build-time tool requirements](https://aws.github.io/aws-lc-rs/requirements/index.html) such as cmake on all platforms and **nasm on Windows.**"

Since then the `cmake` requirement has been relaxed in many cases but `nasm` is still req'd on Windows.


Please also consider users who are installing tools via `cargo install`. Now they are expected to find this build requirement from https://aws.github.io/aws-lc-rs/requirements/, download a random ZIP file from https://www.nasm.us/pub/nasm/releasebuilds/?C=M;O=D, and then go an manually configure an environment variable to point to the installed files?

This change has a huge negative impact across the whole Rust ecosystem. Please revert to using ring, or other pure rust implementation by default.
Agreed that this is a negative change, though in the meantime for my use case at least I was able to get around this with `default-features = false` - maybe this will help.
> Agreed that this is a negative change, though in the meantime for my use case at least I was able to get around this with `default-features = false` - maybe this will help.

Didnt expect to run into you here haha. This also fixed it for my use case. 
> > Agreed that this is a negative change, though in the meantime for my use case at least I was able to get around this with `default-features = false` - maybe this will help.
> 
> Didnt expect to run into you here haha. This also fixed it for my use case.

Small world :)
> I was able to get around this with default-features = false - maybe this will help.

Unfortunately that doesn't help when intermediate dependencies don't specify this which is the case for eg. `ureq` and others. (Unsurprising since this crate didn't used to have default features afaik)
FWIW, I don't really know how to deal [with this situation in ureq](https://github.com/algesten/ureq/issues/751). I absolutely need to support windows users and rustls has so far been brilliant in how little dependencies and complexity it introduced. 

In ureq we also want as few dependencies as possible, however `rustls-webpki` still seem to use `ring` as its default provider, which means I either need to override the default feature flags or accept that I get both `ring` and `aws-lc-rs` as deps. I can obviously solve that with feature flags, but as a library author, I prefer not to do that, since every feature flag I require on ureq's deps takes away some choice for the user of ureq.

For now I hope I can just stall on upgrading rustls until the dust settles, but so far life seemed simpler when it was just ring…
Why do you have a direct dependency on rustls-webpki? In either case, it seems like you can simply use `default-features = false` for your rustls-webpki dependency. For that matter, you could declare both your rustls and rustls-webpki dependency with `default-features = false` and then add back the crypto provider you prefer (sounds like it might be *ring*).
> Why do you have a direct dependency on rustls-webpki?

LOL. I don't know! Just realize it seems to work without it 🤦 … Thanks! 

> For that matter, you could declare both your rustls and rustls-webpki dependency with default-features = false and then add back the crypto provider you prefer (sounds like it might be ring).

Sure, I can do that, but that also means I take a stand for/against some default choices rustls has made for me, and you are the experts on this. From my perspective FIPS is an enterprise compliance requirement – the kind of entities that can afford to spend more time tinkering with their builds.

I understand aws-lc-rs is required for FIPS, and there is a small performance gain, but are there more reasons rustls decided to change the default? Maybe there's a discussion somewhere I missed?
> I understand aws-lc-rs is required for FIPS, and there is a small performance gain, but are there more reasons rustls decided to change the default? Maybe there's a discussion somewhere I missed?

We have found aws-lc-rs has a number of features that *ring* does not support, and upstream is generally more responsive/moving faster. Things like P-521 support, RSA keygen support, better support for SEC-1 keys, support for the PQC KYBER key exchange mechanism, support for HPKE (which is a prerequisite for Encrypted ClientHello support) are now supported in aws-lc-rs but not in *ring* (even though there have been long-standing feature requests). We've also seen fairly rapid support in the build system requirement from aws-lc-rs (and note that *ring* effectively ships pre-built binary code for Windows to avoid these issues -- which has other problems).

Due to this issue we've been having a discussion about how to better communicate the advantages of the aws-lc-rs choice, and this is something we expect to work on soon, but please assume the choice is well-motivated.

That said, the more cumbersome build process is a downside for the time being. IMO for your minimal-dependencies use case it is fine to stick with *ring* for the time being -- and I don't think you're the only library making that choice.
@djc thank you for elaborating!

> but please assume the choice is well-motivated.

I apologize if I came across as questioning your motives. That was not my intent.

> That said, the more cumbersome build process is a downside for the time being. IMO for your minimal-dependencies use case it is fine to stick with ring for the time being -- and I don't think you're the only library making that choice.

Sounds good! I'll make a PR to that today. Thank you!
> We have found aws-lc-rs has a number of features that ring does not support

That's great as a motivation for users to enable the `aws-lc` feature in order to get access to the new functionality, but IMO it's not a rationale for making `aws-lc` required by default.

> We've also seen fairly rapid support in the build system requirement from aws-lc-rs

That's great, and when the build system requirements are as low as ring, then it might make sense to switch.

>  (and note that ring effectively ships pre-built binary code for Windows to avoid these issues -- which has other problems).

It's fairly normal to ship binary code on Windows. The source can still be reviewed and the build can be reproduced, so I don't see a huge difference from a security perspective (and most people aren't reviewing the source code before running `cargo install` anyway...)

> but IMO it's not a rationale for making aws-lc required by default.

Diggsey: It sounds like you're prioritizing minimal build time requirements as the most important factor in a cryptography provider dependency. That's reasonable and we hear you, but I don't think you've made a case for why that should be the default prioritization for everyone. 

As @djc outlined there are several concurrent factors that make aws-lc-rs appealing as a default even though for Windows users it requires an additional build dependency. The fact that several classes of users all have their own justifiable prioritizations (build reqs, performance, post-quantum ciphersuites, FIPS mode, national ciphersuites, a pure Rust impl (note: not ring), etc) is why the backend is now selectable. There's no one provider that could make everyone happy.

I think it's expected there will be some bumps in the road short-term that make it harder to opt-in to using `*ring*` and not `aws-lc-rs` than it should be, such as with `ureq`, but these are problems that can and are being solved.  I think the best path forward is to make that choice ergonomic.  Concurrently the challenges from build tool requirements will continue to get better with time.

> since this crate didn't used to have default features afaik

This crate has had default features for a very long time. At least back to 0.10.0.
> It sounds like you're prioritizing minimal build time requirements as the most important factor in a cryptography provider dependency. That's reasonable and we hear you, but I don't think you've made a case for why that should be the default prioritization for everyone.

Rustls is not just any cryptography provider - we already had the openssl crate which worked just fine. What made rustls special was precisely the minimal build dependencies.

> but I don't think you've made a case for why that should be the default prioritization for everyone.

It seems pretty clear to me: opting into aws-lc is easy, but opting out is essentially impossible when it's provided under a default feature. Therefore the question is not whether to prioritise build requirements vs say performance, but whether to prioritize giving people a choice vs not giving them the choice.

> > It sounds like you're prioritizing minimal build time requirements as the most important factor in a cryptography provider dependency. That's reasonable and we hear you, but I don't think you've made a case for why that should be the default prioritization for everyone.
> 
> Rustls is not just any cryptography provider - we already had the openssl crate which worked just fine. What made rustls special was precisely the minimal build dependencies.

I hardly think that's the only thing (or even necessarily most important) thing that makes rustls an attractive option.

> > but I don't think you've made a case for why that should be the default prioritization for everyone.
> 
> It seems pretty clear to me: opting into aws-lc is easy, but opting out is essentially impossible when it's provided under a default feature. Therefore the question is not whether to prioritise build requirements vs say performance, but whether to prioritize giving people a choice vs not giving them the choice.

It's not "essentially impossible" -- get the intermediate libraries to fix their feature usage, and/or advocate for/contribute to [Cargo efforts](https://internals.rust-lang.org/t/pre-rfc-mutually-excusive-global-features/19618) to improve general handling of the feature situation.
> I hardly think that's the only thing (or even necessarily most important) thing that makes rustls an attractive option.

Have you surveyed your users? I promise you, the only thing most people care about is having a TLS library that just works.

To quote someone else, who phrases it better than I can:

> I always thought Rustls ambition was to provide a "pure Rust" TLS implementation. The original README said "Rustls is a modern TLS library written in Rust". However, I clearly read things into that which was never stated.
>
> With ring, it was of course never pure (it's a mix of asm/C/Rust) and from my limited understanding of crypto, many of the optimizations required for modern crypto primitives are hand written assembly, which will take a long time, if ever, to replace with any Rust equivalent (or at least the asm! macro). However I used to believe Rustls ambition was to aim towards a pure Rust TLS library.

This is the way a lot of people feel, myself included, and the way rustls has been portrayed.

Also 
> It's not "essentially impossible" -- get the intermediate libraries to fix their feature usage, and/or advocate for/contribute to [Cargo efforts](https://internals.rust-lang.org/t/pre-rfc-mutually-excusive-global-features/19618) to improve general handling of the feature situation.

As a user, those things are not in my control. hence "essentially impossible". Sure, I can go and fork every intermediate crate to fix the feature usage - is that practical? No.

If your goal is a true "pure Rust" TLS implementation top-to-bottom then it seems as though the recent work has improved Rustls for you. Unlike before when the cryptography provider was not a choice you can now build rustls without `aws-lc-rs` _or_ `*ring*` so that a cryptography provider like [rustls-rustcrypto](https://github.com/RustCrypto/rustls-rustcrypto) can be used. Unlike `*ring*`, `aws-lc-rs`, BoringSSL, or any other OpenSSL derived cryptography libraries (_they all share the same common heredity_) it includes **only** Rust code. A world where *ring* is the implied default does not meet the goal of pure Rust and so you will still require intermediate dependencies adjust to the "no default" world so you can slot in your pure Rust choice. I continue to believe helping those intermediate deps. make this ergonomic is the best solution both for you, and our other users.

In general it seems like this is becoming an unproductive conversation. I would characterize your attitude as rather combative from the outset and the goal posts keep being moved as we explain our decisions. It's clear you're unhappy with the decision and you've made the reasons why understood. Perhaps we should call that a conclusion and let this thread lie unless there are new perspectives to weigh?
> If your goal is a true "pure Rust" TLS implementation top-to-bottom

That's not *my* goal, I'm saying that the name "rustls" has given users the (apparantly false) impression that this library was striving to provide a TLS implementation with fewer external dependencies that what we had before with openssl, and that this is the main reason this library ever became popular with users.

> I would characterize your attitude as rather combative from the outset

Yes, I'm upset that yet again someone has decided to break the world for no reason (the new features would work perfectly well under a feature flag) and expects everyone else to fix it.

> the goal posts keep being moved as we explain our decisions

I don't think I've moved the goalposts at all? Prior versions of this crate just worked with a standard Rust install, new versions don't. That's bad.

> Perhaps we should call that a conclusion and let this thread lie unless there are new perspectives to weigh?

Sure, at least until the maintainers of all 728 direct dependencies of this crate - https://crates.io/crates/rustls/reverse_dependencies - start receiving complaints from all the users of *those* crates asking why the new version no longer builds correctly. Or when the person who's not even a Rust programmer tries to `cargo install` their favourite tool and now gets an error because of something called nasm? or cmake?


Why use `nasm` specifically? Major compiler toolchains already include an assembler (gcc, clang, msvc with masm64) why can't that be used to prevent an external dependency?

Or even more portabley, using inline asm?
@gimbling-away this is a question for the aws-lc-rs folks, please follow-up with them upstream:

https://github.com/aws/aws-lc-rs/issues/364
https://github.com/aws/aws-lc/issues/1477
And so it begins... https://corteximplant.com/@0x0/112331561273951072
I've also just hit this issue trying to `cargo install` tools depending on rustls. I fully agree that requiring extra binaries installed for a default build is bad choice in general.
Here's what fixed the nasm errors for me, in case this helps anyone else:

```
[dependencies]
ring = "0.17.8"
rustls = { version = "0.22.4", default-features = false }
webpki = "0.22.4"
webpki-roots = "0.26.1"
```
@clairewood I think you fixed it because on version 0.22.4 aws-lc is not used

I have this on my cargo.toml:
```
rustls = { version = "=0.23.5", default-features = false, features = ["ring"]}
```

However, `aws-lc-rs` is still present on the lock file.

```
[[package]]
name = "rustls"
version = "0.23.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "afabcee0551bd1aa3e18e5adbf2c0544722014b899adb31bd186ec638d3da97e"
dependencies = [
 "aws-lc-rs",
 "log",
 "once_cell",
 "ring",
 "rustls-pki-types",
 "rustls-webpki",
 "subtle",
 "zeroize",
]
```

Anyone know why?
> Anyone know why?

Other crates in your dependency graph might be pulling in rustls with default features? Or maybe https://github.com/rust-lang/cargo/issues/10801?
This is an issue that is being discussed, but we want to be cautious.

Ring seems to get around this requirement by pregenerating/embedding the NASM object files into the crate:
```
❯ cargo download ring > ring.tar.gz
INFO: cargo-download v0.1.2
INFO: Latest version of crate ring=* is 0.17.8
INFO: Crate `ring==0.17.8` downloaded successfully

❯ tar ztf ring.tar.gz | egrep '\.o$'
ring-0.17.8/pregenerated/aesni-gcm-x86_64-nasm.o
ring-0.17.8/pregenerated/aesni-x86-win32n.o
ring-0.17.8/pregenerated/aesni-x86_64-nasm.o
ring-0.17.8/pregenerated/chacha-x86-win32n.o
ring-0.17.8/pregenerated/chacha-x86_64-nasm.o
ring-0.17.8/pregenerated/chacha20_poly1305_x86_64-nasm.o
ring-0.17.8/pregenerated/ghash-x86-win32n.o
ring-0.17.8/pregenerated/ghash-x86_64-nasm.o
ring-0.17.8/pregenerated/p256-x86_64-asm-nasm.o
ring-0.17.8/pregenerated/sha256-x86_64-nasm.o
ring-0.17.8/pregenerated/sha512-x86_64-nasm.o
ring-0.17.8/pregenerated/vpaes-x86-win32n.o
ring-0.17.8/pregenerated/vpaes-x86_64-nasm.o
ring-0.17.8/pregenerated/x86-mont-win32n.o
ring-0.17.8/pregenerated/x86_64-mont-nasm.o
ring-0.17.8/pregenerated/x86_64-mont5-nasm.o
```
Yeah.  Ok well I'm going to stick with older versions till someone decides to make a rustls that's actually rustls.  If I had known that in 2024 I'd still be running into issues building tls dependencies I'd have been a carpenter.
I have a sub-crate which uses rustls and specifies aws-lc-rs. I cannot get it to build on android.
@narodnik Since your problem is unrelated to Windows/NASM I think it deserves a separate discussion. Please open a new issue, filling out the issue template with as much information as you have. We would need many more details than you've provided in order to help. 
Folks following this issue may be interested in providing feedback on [this upstream PR](https://github.com/aws/aws-lc-rs/pull/491) that offers a route to using pre-generated assembly artifacts for `aws-lc-rs` on Windows, similar to how `*ring*` avoids a `nasm` build-time dependency: https://github.com/aws/aws-lc-rs/pull/491

Fix patch:
diff --git a/Cargo.lock b/Cargo.lock
index 0243187ec7c..27fbe78a6da 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -366,9 +366,9 @@ dependencies = [
 
 [[package]]
 name = "aws-lc-rs"
-version = "1.8.1"
+version = "1.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4ae74d9bd0a7530e8afd1770739ad34b36838829d6ad61818f9230f683f5ad77"
+checksum = "2f95446d919226d587817a7d21379e6eb099b97b45110a7f272a444ca5c54070"
 dependencies = [
  "aws-lc-fips-sys",
  "aws-lc-sys",
@@ -380,9 +380,9 @@ dependencies = [
 
 [[package]]
 name = "aws-lc-sys"
-version = "0.20.1"
+version = "0.21.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0f0e249228c6ad2d240c2dc94b714d711629d52bad946075d8e9b2f5391f0703"
+checksum = "5055edc4a9a1b2a917a818258cdfb86a535947feebd9981adc99667a062c6f85"
 dependencies = [
  "bindgen",
  "cc",
@@ -495,7 +495,7 @@ version = "0.1.0"
 dependencies = [
  "base64",
  "env_logger",
- "rustls 0.23.12",
+ "rustls 0.23.13",
  "rustls-pemfile",
  "rustls-pki-types",
  "rustls-post-quantum",
@@ -1232,7 +1232,7 @@ dependencies = [
  "ipnet",
  "once_cell",
  "rand",
- "rustls 0.23.12 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustls 0.23.12",
  "rustls-pemfile",
  "thiserror",
  "time",
@@ -1259,7 +1259,7 @@ dependencies = [
  "parking_lot",
  "rand",
  "resolv-conf",
- "rustls 0.23.12 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustls 0.23.12",
  "smallvec",
  "thiserror",
  "tokio",
@@ -1524,7 +1524,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4"
 dependencies = [
  "cfg-if",
- "windows-targets 0.52.6",
+ "windows-targets 0.48.5",
 ]
 
 [[package]]
@@ -2212,6 +2212,21 @@ dependencies = [
 [[package]]
 name = "rustls"
 version = "0.23.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c58f8c84392efc0a126acce10fa59ff7b3d2ac06ab451a33f2741989b806b044"
+dependencies = [
+ "log",
+ "once_cell",
+ "ring",
+ "rustls-pki-types",
+ "rustls-webpki",
+ "subtle",
+ "zeroize",
+]
+
+[[package]]
+name = "rustls"
+version = "0.23.13"
 dependencies = [
  "aws-lc-rs",
  "base64",
@@ -2242,21 +2257,6 @@ dependencies = [
  "zlib-rs",
 ]
 
-[[package]]
-name = "rustls"
-version = "0.23.12"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c58f8c84392efc0a126acce10fa59ff7b3d2ac06ab451a33f2741989b806b044"
-dependencies = [
- "log",
- "once_cell",
- "ring",
- "rustls-pki-types",
- "rustls-webpki",
- "subtle",
- "zeroize",
-]
-
 [[package]]
 name = "rustls-ci-bench"
 version = "0.0.1"
@@ -2268,7 +2268,7 @@ dependencies = [
  "fxhash",
  "itertools 0.13.0",
  "rayon",
- "rustls 0.23.12",
+ "rustls 0.23.13",
  "rustls-pemfile",
  "rustls-pki-types",
  "tikv-jemallocator",
@@ -2281,7 +2281,7 @@ dependencies = [
  "hickory-resolver",
  "regex",
  "ring",
- "rustls 0.23.12",
+ "rustls 0.23.13",
 ]
 
 [[package]]
@@ -2295,7 +2295,7 @@ dependencies = [
  "log",
  "mio 0.8.11",
  "rcgen",
- "rustls 0.23.12",
+ "rustls 0.23.13",
  "rustls-pemfile",
  "rustls-pki-types",
  "serde",
@@ -2313,7 +2313,7 @@ dependencies = [
  "num-bigint",
  "once_cell",
  "openssl",
- "rustls 0.23.12",
+ "rustls 0.23.13",
  "rustls-pemfile",
  "rustls-pki-types",
 ]
@@ -2340,7 +2340,7 @@ version = "0.1.0"
 dependencies = [
  "aws-lc-rs",
  "env_logger",
- "rustls 0.23.12",
+ "rustls 0.23.13",
  "webpki-roots",
 ]
 
@@ -2361,7 +2361,7 @@ dependencies = [
  "rand_core",
  "rcgen",
  "rsa",
- "rustls 0.23.12",
+ "rustls 0.23.13",
  "rustls-pki-types",
  "rustls-webpki",
  "sha2",
@@ -2375,7 +2375,7 @@ name = "rustls-provider-test"
 version = "0.1.0"
 dependencies = [
  "hex",
- "rustls 0.23.12",
+ "rustls 0.23.13",
  "rustls-provider-example",
  "serde",
  "serde_json",
@@ -2383,9 +2383,9 @@ dependencies = [
 
 [[package]]
 name = "rustls-webpki"
-version = "0.102.7"
+version = "0.102.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "84678086bd54edf2b415183ed7a94d0efb049f1b646a33e22a36f3794be6ae56"
+checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9"
 dependencies = [
  "aws-lc-rs",
  "ring",
@@ -2697,7 +2697,7 @@ version = "0.26.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4"
 dependencies = [
- "rustls 0.23.12 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustls 0.23.12",
  "rustls-pki-types",
  "tokio",
 ]
diff --git a/fuzz/Cargo.lock b/fuzz/Cargo.lock
index 7c2daf62156..3498134e553 100644
--- a/fuzz/Cargo.lock
+++ b/fuzz/Cargo.lock
@@ -19,9 +19,9 @@ checksum = "64cf76cb6e2222ed0ea86b2b0ee2f71c96ec6edd5af42e84d59160e91b836ec4"
 
 [[package]]
 name = "aws-lc-rs"
-version = "1.8.1"
+version = "1.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4ae74d9bd0a7530e8afd1770739ad34b36838829d6ad61818f9230f683f5ad77"
+checksum = "2f95446d919226d587817a7d21379e6eb099b97b45110a7f272a444ca5c54070"
 dependencies = [
  "aws-lc-sys",
  "mirai-annotations",
@@ -31,9 +31,9 @@ dependencies = [
 
 [[package]]
 name = "aws-lc-sys"
-version = "0.20.1"
+version = "0.21.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0f0e249228c6ad2d240c2dc94b714d711629d52bad946075d8e9b2f5391f0703"
+checksum = "5055edc4a9a1b2a917a818258cdfb86a535947feebd9981adc99667a062c6f85"
 dependencies = [
  "bindgen",
  "cc",
@@ -373,7 +373,7 @@ dependencies = [
 
 [[package]]
 name = "rustls"
-version = "0.23.12"
+version = "0.23.13"
 dependencies = [
  "aws-lc-rs",
  "log",
@@ -401,9 +401,9 @@ checksum = "fc0a2ce646f8655401bb81e7927b812614bd5d91dbc968696be50603510fcaf0"
 
 [[package]]
 name = "rustls-webpki"
-version = "0.102.7"
+version = "0.102.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "84678086bd54edf2b415183ed7a94d0efb049f1b646a33e22a36f3794be6ae56"
+checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9"
 dependencies = [
  "aws-lc-rs",
  "ring",
@@ -548,17 +548,3 @@ name = "zeroize"
 version = "1.8.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde"
-dependencies = [
- "zeroize_derive",
-]
-
-[[package]]
-name = "zeroize_derive"
-version = "1.4.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
diff --git a/rustls-post-quantum/Cargo.toml b/rustls-post-quantum/Cargo.toml
index df887806a1e..343878daf94 100644
--- a/rustls-post-quantum/Cargo.toml
+++ b/rustls-post-quantum/Cargo.toml
@@ -11,7 +11,7 @@ categories = ["network-programming", "cryptography"]
 
 [dependencies]
 rustls = { version = "0.23.2", features = ["aws_lc_rs"], path = "../rustls" }
-aws-lc-rs = { version = "1.8.1", features = ["unstable"], default-features = false }
+aws-lc-rs = { version = "1.9", features = ["unstable"], default-features = false }
 
 [dev-dependencies]
 env_logger = "0.10" # 0.11 requires 1.71 MSRV even as a dev-dep (due to manifest features)
diff --git a/rustls/Cargo.toml b/rustls/Cargo.toml
index 9dab5fd5826..80da599ea0e 100644
--- a/rustls/Cargo.toml
+++ b/rustls/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "rustls"
-version = "0.23.12"
+version = "0.23.13"
 edition = "2021"
 rust-version = "1.63"
 license = "Apache-2.0 OR ISC OR MIT"
@@ -18,7 +18,7 @@ build = "build.rs"
 rustversion = { version = "1.0.6", optional = true }
 
 [dependencies]
-aws-lc-rs = { version = "1.8.1", optional = true, default-features = false, features = ["aws-lc-sys"] }
+aws-lc-rs = { version = "1.9", optional = true, default-features = false, features = ["aws-lc-sys", "prebuilt-nasm"] }
 brotli = { version = "6", optional = true, default-features = false, features = ["std"] }
 brotli-decompressor = { version = "4.0.1", optional = true } # 4.0.1 required for panic fix
 hashbrown = { version = "0.14", optional = true, default-features = false, features = ["ahash", "inline-more"] }
@@ -27,7 +27,7 @@ log = { version = "0.4.8", optional = true }
 once_cell = { version = "1.16", default-features = false, features = ["alloc", "race"] }
 ring = { version = "0.17", optional = true }
 subtle = { version = "2.5.0", default-features = false }
-webpki = { package = "rustls-webpki", version = "0.102.6", features = ["alloc"], default-features = false }
+webpki = { package = "rustls-webpki", version = "0.102.8", features = ["alloc"], default-features = false }
 pki-types = { package = "rustls-pki-types", version = "1.7", features = ["alloc"] }
 zeroize = "1.7"
 zlib-rs = { version = "0.3", optional = true }
diff --git a/rustls/src/crypto/ring/kx.rs b/rustls/src/crypto/ring/kx.rs
index 8c267e9ea2e..8c019d2ef25 100644
--- a/rustls/src/crypto/ring/kx.rs
+++ b/rustls/src/crypto/ring/kx.rs
@@ -26,6 +26,20 @@ struct KxGroup {
     /// `SupportedKxGroup::fips()` is true if and only if the algorithm is allowed,
     /// _and_ the implementation is FIPS-validated.
     fips_allowed: bool,
+
+    /// aws-lc-rs 1.9 and later accepts more formats of public keys than
+    /// just uncompressed.
+    ///
+    /// That is not compatible with TLS:
+    /// - TLS1.3 outlaws other encodings,
+    /// - TLS1.2 negotiates other encodings (we only offer uncompressed), and
+    ///   defaults to uncompressed if negotiation is not done.
+    ///
+    /// This function should return `true` if the basic shape of its argument
+    /// is consistent with an uncompressed point encoding.  It does not need
+    /// to verify that the point is on the curve (if the curve requires that
+    /// for security); aws-lc-rs/ring must do that.
+    pub_key_validator: fn(&[u8]) -> bool,
 }
 
 impl SupportedKxGroup for KxGroup {
@@ -43,6 +57,7 @@ impl SupportedKxGroup for KxGroup {
             agreement_algorithm: self.agreement_algorithm,
             priv_key,
             pub_key,
+            pub_key_validator: self.pub_key_validator,
         }))
     }
 
@@ -76,6 +91,8 @@ pub static X25519: &dyn SupportedKxGroup = &KxGroup {
     //  are not compliant to SP 800-56Arev3."
     // -- <https://csrc.nist.gov/csrc/media/Projects/cryptographic-module-validation-program/documents/fips%20140-3/FIPS%20140-3%20IG.pdf>
     fips_allowed: false,
+
+    pub_key_validator: |point: &[u8]| point.len() == 32,
 };
 
 /// Ephemeral ECDH on secp256r1 (aka NIST-P256)
@@ -83,6 +100,7 @@ pub static SECP256R1: &dyn SupportedKxGroup = &KxGroup {
     name: NamedGroup::secp256r1,
     agreement_algorithm: &agreement::ECDH_P256,
     fips_allowed: true,
+    pub_key_validator: uncompressed_point,
 };
 
 /// Ephemeral ECDH on secp384r1 (aka NIST-P384)
@@ -90,8 +108,16 @@ pub static SECP384R1: &dyn SupportedKxGroup = &KxGroup {
     name: NamedGroup::secp384r1,
     agreement_algorithm: &agreement::ECDH_P384,
     fips_allowed: true,
+    pub_key_validator: uncompressed_point,
 };
 
+fn uncompressed_point(point: &[u8]) -> bool {
+    // See `UncompressedPointRepresentation`, which is a retelling of
+    // SEC1 section 2.3.3 "Elliptic-Curve-Point-to-Octet-String Conversion"
+    // <https://datatracker.ietf.org/doc/html/rfc8446#section-4.2.8.2>
+    matches!(point.first(), Some(0x04))
+}
+
 /// A list of all the key exchange groups supported by rustls.
 pub static ALL_KX_GROUPS: &[&dyn SupportedKxGroup] = &[X25519, SECP256R1, SECP384R1];
 
@@ -102,11 +128,15 @@ struct KeyExchange {
     agreement_algorithm: &'static agreement::Algorithm,
     priv_key: agreement::EphemeralPrivateKey,
     pub_key: agreement::PublicKey,
+    pub_key_validator: fn(&[u8]) -> bool,
 }
 
 impl ActiveKeyExchange for KeyExchange {
     /// Completes the key exchange, given the peer's public key.
     fn complete(self: Box<Self>, peer: &[u8]) -> Result<SharedSecret, Error> {
+        if !(self.pub_key_validator)(peer) {
+            return Err(PeerMisbehaved::InvalidKeyShare.into());
+        }
         let peer_key = agreement::UnparsedPublicKey::new(self.agreement_algorithm, peer);
         super::ring_shim::agree_ephemeral(self.priv_key, &peer_key)
             .map_err(|_| PeerMisbehaved::InvalidKeyShare.into())


Test patch: