Skip to content

Commit

Permalink
fixes for aws-lc-rs/ring feature switches
Browse files Browse the repository at this point in the history
  • Loading branch information
FlorianUekermann committed Feb 10, 2024
1 parent 47bbe01 commit c7c1856
Show file tree
Hide file tree
Showing 9 changed files with 98 additions and 25 deletions.
5 changes: 3 additions & 2 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,11 @@ jobs:
strategy:
matrix:
toolchain: ["stable", "beta", "nightly"]
default: ["", "--no-default-features"]
crypto: ["ring", "aws-lc-rs", "ring,aws-lc-rs", ""]
tokio: ["tokio", "tokio,axum", ""]
steps:
- uses: actions/checkout@v3
- run: rustup update ${{ matrix.toolchain }} && rustup default ${{ matrix.toolchain }}
- run: cargo build --verbose --features ${{ matrix.crypto }},${{ matrix.tokio }}
- run: cargo test --verbose --features ${{ matrix.crypto }},${{ matrix.tokio }}
- run: cargo build --verbose ${{ matrix.default }} --features ${{ matrix.crypto }},${{ matrix.tokio }}
- run: cargo test --verbose ${{ matrix.default }} --features ${{ matrix.crypto }},${{ matrix.tokio }}
9 changes: 7 additions & 2 deletions src/acceptor.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::acme::ACME_TLS_ALPN_NAME;
use crate::{is_tls_alpn_challenge, ResolvesServerCertAcme};
use crate::{crypto_provider, is_tls_alpn_challenge, ResolvesServerCertAcme};
use core::fmt;
use futures::prelude::*;
use futures_rustls::rustls::server::Acceptor;
Expand All @@ -16,9 +16,14 @@ pub struct AcmeAcceptor {
}

impl AcmeAcceptor {
#[cfg(any(feature = "ring", feature = "aws-lc-rs"))]
#[deprecated(note = "please use high-level API via `AcmeState::incoming()` instead or refer to updated low-level API examples")]
pub(crate) fn new(resolver: Arc<ResolvesServerCertAcme>) -> Self {
let mut config = ServerConfig::builder().with_no_client_auth().with_cert_resolver(resolver.clone());
let mut config = ServerConfig::builder_with_provider(crypto_provider().into())
.with_safe_default_protocol_versions()
.unwrap()
.with_no_client_auth()
.with_cert_resolver(resolver.clone());
config.alpn_protocols.push(ACME_TLS_ALPN_NAME.to_vec());
Self { config: Arc::new(config) }
}
Expand Down
8 changes: 4 additions & 4 deletions src/acme.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
use std::sync::Arc;

use crate::any_ecdsa_type;
use crate::crypto::error::{KeyRejected, Unspecified};
use crate::crypto::rand::SystemRandom;
use crate::crypto::signature::{EcdsaKeyPair, EcdsaSigningAlgorithm, ECDSA_P256_SHA256_FIXED_SIGNING};
use crate::https_helper::{https, HttpsRequestError};
use crate::jose::{key_authorization_sha256, sign, JoseError};
use crate::ring::error::{KeyRejected, Unspecified};
use crate::ring::rand::SystemRandom;
use crate::ring::signature::{EcdsaKeyPair, EcdsaSigningAlgorithm, ECDSA_P256_SHA256_FIXED_SIGNING};
use base64::prelude::*;
use futures_rustls::pki_types::{CertificateDer, PrivateKeyDer, PrivatePkcs8KeyDer};
use futures_rustls::rustls::{sign::CertifiedKey, ClientConfig};
Expand Down Expand Up @@ -57,7 +57,7 @@ impl Account {
ALG,
key_pair,
// ring 0.17 has a third argument here; aws-lc-rs doesn't.
#[cfg(feature = "ring")]
#[cfg(all(feature = "ring", not(feature = "aws-lc-rs")))]
&SystemRandom::new(),
)?;
let contact: Vec<&'a str> = contact.into_iter().map(AsRef::<str>::as_ref).collect();
Expand Down
2 changes: 1 addition & 1 deletion src/caches/dir.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::ring::digest::{Context, SHA256};
use crate::crypto::digest::{Context, SHA256};
use crate::{AccountCache, CertCache};
use async_trait::async_trait;
use base64::prelude::*;
Expand Down
18 changes: 15 additions & 3 deletions src/config.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
use crate::acme::{LETS_ENCRYPT_PRODUCTION_DIRECTORY, LETS_ENCRYPT_STAGING_DIRECTORY};
use crate::caches::{BoxedErrCache, CompositeCache, NoCache};
use crate::{AccountCache, Cache, CertCache};
use crate::{crypto_provider, AccountCache, Cache, CertCache};
use crate::{AcmeState, Incoming};
use core::fmt;
use futures::{AsyncRead, AsyncWrite, Stream};
use futures_rustls::pki_types::TrustAnchor;
use futures_rustls::rustls::crypto::CryptoProvider;
use futures_rustls::rustls::{ClientConfig, RootCertStore};
use std::convert::Infallible;
use std::fmt::Debug;
Expand Down Expand Up @@ -48,8 +49,13 @@ impl AcmeConfig<Infallible, Infallible> {
/// # type EA = EC;
/// let config: AcmeConfig<EC, EA> = AcmeConfig::new(["example.com"]).cache(NoCache::new());
/// ```
///
#[cfg(any(feature = "ring", feature = "aws-lc-rs"))]
pub fn new(domains: impl IntoIterator<Item = impl AsRef<str>>) -> Self {
Self::new_with_provider(domains, crypto_provider().into())
}

/// Same as [AcmeConfig::new], with a specific [CryptoProvider].
pub fn new_with_provider(domains: impl IntoIterator<Item = impl AsRef<str>>, provider: Arc<CryptoProvider>) -> Self {
let mut root_store = RootCertStore::empty();
root_store.extend(TLS_SERVER_ROOTS.iter().map(|ta| {
let ta = ta.to_owned();
Expand All @@ -59,7 +65,13 @@ impl AcmeConfig<Infallible, Infallible> {
name_constraints: ta.name_constraints.map(Into::into),
}
}));
let client_config = Arc::new(ClientConfig::builder().with_root_certificates(root_store).with_no_client_auth());
let client_config = Arc::new(
ClientConfig::builder_with_provider(provider)
.with_safe_default_protocol_versions()
.unwrap()
.with_root_certificates(root_store)
.with_no_client_auth(),
);
AcmeConfig {
client_config,
directory_url: LETS_ENCRYPT_STAGING_DIRECTORY.into(),
Expand Down
21 changes: 19 additions & 2 deletions src/incoming.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use crate::acceptor::{AcmeAccept, AcmeAcceptor};
use crate::AcmeState;
use crate::{crypto_provider, AcmeState};
use core::fmt;
use futures::stream::{FusedStream, FuturesUnordered};
use futures::{AsyncRead, AsyncWrite, Stream};
use futures_rustls::rustls::crypto::CryptoProvider;
use futures_rustls::rustls::ServerConfig;
use futures_rustls::server::TlsStream;
use futures_rustls::Accept;
Expand Down Expand Up @@ -47,8 +48,24 @@ impl<TCP: AsyncRead + AsyncWrite + Unpin, ETCP, ITCP: Stream<Item = Result<TCP,
impl<TCP: AsyncRead + AsyncWrite + Unpin, ETCP, ITCP: Stream<Item = Result<TCP, ETCP>> + Unpin, EC: Debug + 'static, EA: Debug + 'static>
Incoming<TCP, ETCP, ITCP, EC, EA>
{
#[cfg(any(feature = "ring", feature = "aws-lc-rs"))]
pub fn new(tcp_incoming: ITCP, state: AcmeState<EC, EA>, acceptor: AcmeAcceptor, alpn_protocols: Vec<Vec<u8>>) -> Self {
let mut config = ServerConfig::builder().with_no_client_auth().with_cert_resolver(state.resolver());
Self::new_with_provider(tcp_incoming, state, acceptor, alpn_protocols, crypto_provider().into())
}

/// Same as [Incoming::new], with a specific [CryptoProvider].
pub fn new_with_provider(
tcp_incoming: ITCP,
state: AcmeState<EC, EA>,
acceptor: AcmeAcceptor,
alpn_protocols: Vec<Vec<u8>>,
provider: Arc<CryptoProvider>,
) -> Self {
let mut config = ServerConfig::builder_with_provider(provider)
.with_safe_default_protocol_versions()
.unwrap()
.with_no_client_auth()
.with_cert_resolver(state.resolver());
config.alpn_protocols = alpn_protocols;
Self {
state,
Expand Down
8 changes: 4 additions & 4 deletions src/jose.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::ring::digest::{digest, Digest, SHA256};
use crate::ring::rand::SystemRandom;
use crate::ring::signature::{EcdsaKeyPair, KeyPair};
use crate::crypto::digest::{digest, Digest, SHA256};
use crate::crypto::rand::SystemRandom;
use crate::crypto::signature::{EcdsaKeyPair, KeyPair};
use base64::prelude::*;
use serde::Serialize;
use thiserror::Error;
Expand Down Expand Up @@ -110,5 +110,5 @@ pub enum JoseError {
#[error("json serialization failed: {0}")]
Json(#[from] serde_json::Error),
#[error("crypto error: {0}")]
Crypto(#[from] crate::ring::error::Unspecified),
Crypto(#[from] crate::crypto::error::Unspecified),
}
23 changes: 21 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,9 +134,28 @@ pub use resolver::*;
pub use state::*;

#[cfg(feature = "aws-lc-rs")]
use ::{aws_lc_rs as ring, futures_rustls::rustls::crypto::aws_lc_rs::sign::any_ecdsa_type};
use ::aws_lc_rs as crypto;
#[cfg(all(feature = "ring", not(feature = "aws-lc-rs")))]
use ::{futures_rustls::rustls::crypto::ring::sign::any_ecdsa_type, ring};
use ::ring as crypto;

// TODO: Can we use something like CryptoProvider for rustls, but for ring to drop this requirement?
#[cfg(not(any(feature = "ring", feature = "aws-lc-rs")))]
compile_error!("rustls-acme requires either the ring or aws-lc-rs feature enabled");

#[cfg(any(feature = "ring", feature = "aws-lc-rs"))]
pub(crate) fn any_ecdsa_type(
der: &futures_rustls::pki_types::PrivateKeyDer,
) -> Result<std::sync::Arc<dyn futures_rustls::rustls::sign::SigningKey>, futures_rustls::rustls::Error> {
#[cfg(all(feature = "ring", not(feature = "aws-lc-rs")))]
return futures_rustls::rustls::crypto::ring::sign::any_ecdsa_type(&der);
#[cfg(feature = "aws-lc-rs")]
return futures_rustls::rustls::crypto::aws_lc_rs::sign::any_ecdsa_type(&der);
}

#[cfg(any(feature = "ring", feature = "aws-lc-rs"))]
pub(crate) fn crypto_provider() -> futures_rustls::rustls::crypto::CryptoProvider {
#[cfg(all(feature = "ring", not(feature = "aws-lc-rs")))]
return futures_rustls::rustls::crypto::ring::default_provider();
#[cfg(feature = "aws-lc-rs")]
return futures_rustls::rustls::crypto::aws_lc_rs::default_provider();
}
29 changes: 24 additions & 5 deletions src/state.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
use crate::acceptor::AcmeAcceptor;
use crate::acme::{Account, AcmeError, Auth, AuthStatus, Directory, Identifier, Order, OrderStatus, ACME_TLS_ALPN_NAME};
use crate::{AcmeConfig, Incoming, ResolvesServerCertAcme};
use crate::{any_ecdsa_type, crypto_provider, AcmeConfig, Incoming, ResolvesServerCertAcme};
use async_io::Timer;
use chrono::{DateTime, TimeZone, Utc};
use core::fmt;
use futures::future::try_join_all;
use futures::prelude::*;
use futures::ready;
use futures_rustls::pki_types::{CertificateDer as RustlsCertificate, PrivateKeyDer, PrivatePkcs8KeyDer};
use futures_rustls::rustls::crypto::CryptoProvider;
use futures_rustls::rustls::sign::CertifiedKey;
use futures_rustls::rustls::{crypto::ring::sign::any_ecdsa_type, ServerConfig};
use futures_rustls::rustls::ServerConfig;
use rcgen::{CertificateParams, DistinguishedName, PKCS_ECDSA_P256_SHA256};
use std::convert::Infallible;
use std::fmt::Debug;
Expand Down Expand Up @@ -139,16 +140,34 @@ impl<EC: 'static + Debug, EA: 'static + Debug> AcmeState<EC, EA> {
self.resolver.clone()
}
/// Creates a [rustls::ServerConfig] for tls-alpn-01 challenge connections. Use this if [crate::is_tls_alpn_challenge] returns `true`.
#[cfg(any(feature = "ring", feature = "aws-lc-rs"))]
pub fn challenge_rustls_config(&self) -> Arc<ServerConfig> {
let mut rustls_config = ServerConfig::builder().with_no_client_auth().with_cert_resolver(self.resolver());
self.challenge_rustls_config_with_provider(crypto_provider().into())
}
/// Same as [AcmeState::challenge_rustls_config], with a specific [CryptoProvider].
pub fn challenge_rustls_config_with_provider(&self, provider: Arc<CryptoProvider>) -> Arc<ServerConfig> {
let mut rustls_config = ServerConfig::builder_with_provider(provider)
.with_safe_default_protocol_versions()
.unwrap()
.with_no_client_auth()
.with_cert_resolver(self.resolver());
rustls_config.alpn_protocols.push(ACME_TLS_ALPN_NAME.to_vec());
return Arc::new(rustls_config);
}
/// Creates a default [rustls::ServerConfig] for accepting regular tls connections. Use this if [crate::is_tls_alpn_challenge] returns `false`.
/// If you need a [rustls::ServerConfig], which uses the certificates acquired by this [AcmeState],
/// you may build your own using the output of [AcmeState::resolver].
#[cfg(any(feature = "ring", feature = "aws-lc-rs"))]
pub fn default_rustls_config(&self) -> Arc<ServerConfig> {
let rustls_config = ServerConfig::builder().with_no_client_auth().with_cert_resolver(self.resolver());
self.default_rustls_config_with_provider(crypto_provider().into())
}
/// Same as [AcmeState::default_rustls_config], with a specific [CryptoProvider].
pub fn default_rustls_config_with_provider(&self, provider: Arc<CryptoProvider>) -> Arc<ServerConfig> {
let rustls_config = ServerConfig::builder_with_provider(provider)
.with_safe_default_protocol_versions()
.unwrap()
.with_no_client_auth()
.with_cert_resolver(self.resolver());
return Arc::new(rustls_config);
}
pub fn new(config: AcmeConfig<EC, EA>) -> Self {
Expand All @@ -171,7 +190,7 @@ impl<EC: 'static + Debug, EA: 'static + Debug> AcmeState<EC, EA> {
wait: None,
}
}
fn parse_cert(pem: &[u8]) -> Result<(futures_rustls::rustls::sign::CertifiedKey, [DateTime<Utc>; 2]), CertParseError> {
fn parse_cert(pem: &[u8]) -> Result<(CertifiedKey, [DateTime<Utc>; 2]), CertParseError> {
let mut pems = pem::parse_many(&pem)?;
if pems.len() < 2 {
return Err(CertParseError::TooFewPem(pems.len()));
Expand Down

0 comments on commit c7c1856

Please sign in to comment.