Files
RustPython/examples/custom_tls_providers.rs
Joshua MegnauthandJeong, YunWon f347ae4fbb Support custom rustls providers (#7657)
* Modularize rustls as work towards providers

`rustls`'s architecture is very clean and trait-driven. There are many
providers for `rustls` including the built-in `aws-lc-rs` and `ring` as
well as backends for `boringssl`, `graviola`, `openssl`, `mbedtls`, etc.

This commit removes the hard dependency on `aws-lc-rs` and adds support
for `ring`. It works towards #7059 as well.

* Clean up rustls features

* Remove ring as an explicit feature
* ssl-rustls is the default and implies aws-lc

* Support custom rustls crypto providers

The new feature, `ssl-rustls-no-provider`, enables custom rustls
providers. By default, `aws-lc-rs` is enabled which matches the old
behavior and keeps backward compatibility.

I wrote a new type that abstracts what we need from crypto providers.
CryptoExt encapsulates the ticketer as well as cipher suites and KX
groups. I wrote fallbacks to help select a reasonable default if a
provider is missing features (they all seem to support the same things
though).

I also wrote an example to show how to actually use custom providers.

* Fix duplicate VERIFY_X509 constants and unused imports in ssl module

Remove duplicate VERIFY_X509_STRICT/VERIFY_X509_PARTIAL_CHAIN definitions
from compat.rs (already defined in _ssl module with #[pyattr]).
Remove unused imports: ClientConnection, ServerConnection.

* no-provider as default

* Fix CI failures: openssl build, wasm target, cargo-shear

- Update openssl.rs to use renamed sock_wait/SockWaitKind and add vm parameter
- Add skip_ssl for wasm32-wasip2 target (aws-lc-sys cannot build for wasm)
- Remove unused workspace dependency aws-lc-rs
- Fix foreign-types-shared version to match openssl's dependency (0.1)
- Restore Cargo.lock from upstream/main

---------

Co-authored-by: Jeong, YunWon <jeong@youknowone.org>
2026-05-28 11:07:09 +09:00

66 lines
2.1 KiB
Rust

//! Example project to demonstrate how to set a custom rustls provider for RustPython.
// spell-checker: ignore graviola
use std::env;
use rustls::crypto::ring;
use rustpython_pylib::FROZEN_STDLIB;
use rustpython_stdlib::{ssl::providers::CryptoExt, stdlib_module_defs};
use rustpython_vm::Interpreter;
const SCRIPT: &str = r#"
import urllib.request
with urllib.request.urlopen("https://python.org") as response:
assert response.status == 200
"#;
fn main() {
let provider = env::args()
.skip(1)
.find_map(|arg| match &*arg {
"--ring" => Some("ring"),
"--graviola" => Some("graviola"),
_ => None,
})
.unwrap_or("ring");
match provider {
"ring" => {
let ext = CryptoExt {
all_cipher_suites: Some(ring::ALL_CIPHER_SUITES),
all_kx_groups: Some(ring::ALL_KX_GROUPS),
any_supported_key: Some(ring::sign::any_supported_type),
ticketer: ring::Ticketer::new,
};
CryptoExt::set_provider(ring::default_provider(), ext).unwrap();
println!("Using ring for cryptography");
}
"graviola" => {
let ext = CryptoExt {
all_cipher_suites: Some(rustls_graviola::suites::ALL_CIPHER_SUITES),
all_kx_groups: Some(rustls_graviola::kx::ALL_KX_GROUPS),
any_supported_key: None,
ticketer: rustls_graviola::Ticketer::new,
};
CryptoExt::set_provider(rustls_graviola::default_provider(), ext).unwrap();
println!("Using Graviola for cryptography");
}
unsupported => panic!("Unsupported provider: {unsupported}"),
}
let builder = Interpreter::builder(Default::default());
let defs = stdlib_module_defs(&builder.ctx);
let result = builder
.add_native_modules(&defs)
.add_frozen_modules(FROZEN_STDLIB)
.build()
.run(|vm| {
let scope = vm.new_scope_with_builtins();
vm.run_block_expr(scope, SCRIPT).map(|_| ())
});
assert_eq!(0, result);
}