diff --git a/Cargo.toml b/Cargo.toml index f136e3c72..faa32e217 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -65,8 +65,8 @@ std = ["alloc", "dep:hashbrown", "bumpalo?/std", "bytes?/std", "octseq/s tracing = ["dep:log", "dep:tracing"] # Cryptographic backends -ring = ["dep:ring"] -openssl = ["dep:openssl"] +ring = ["dep:ring", "unstable-crypto-backend"] +openssl = ["dep:openssl", "unstable-crypto-backend"] # Crate features net = ["bytes", "futures-util", "rand", "std", "tokio"] @@ -79,11 +79,15 @@ zonefile = ["bytes", "serde", "std"] unstable-new = [] unstable-client-cache = ["unstable-client-transport", "moka"] unstable-client-transport = ["moka", "net", "tracing"] -unstable-crypto = ["bytes"] +unstable-crypto = ["bytes", "std"] unstable-crypto-sign = ["dep:secrecy", "unstable-crypto"] +# Internal; also requires 'ring' or 'openssl' to be enabled. +unstable-crypto-backend = ["unstable-crypto"] unstable-server-transport = ["arc-swap", "chrono/clock", "libc", "net", "siphasher", "tracing"] -unstable-sign = ["std", "dep:smallvec", "dep:serde", "time/formatting", "tracing", "unstable-crypto-sign"] +# Also requires 'ring' or 'openssl' to be enabled. +unstable-sign = ["std", "smallvec", "serde", "time/formatting", "tracing", "unstable-crypto-sign"] unstable-stelline = ["tokio/test-util", "tracing", "tracing-subscriber", "tsig", "unstable-client-transport", "unstable-server-transport", "zonefile"] +# Also requires 'ring' or 'openssl' to be enabled. unstable-validator = ["zonefile", "unstable-client-transport", "unstable-crypto", "moka"] unstable-xfr = ["net"] unstable-zonetree = ["futures-util", "parking_lot", "rustversion", "serde", "std", "tokio", "tracing", "unstable-xfr", "zonefile"] diff --git a/src/crypto/common.rs b/src/crypto/common.rs index 8e7853bcb..50e547fc4 100644 --- a/src/crypto/common.rs +++ b/src/crypto/common.rs @@ -3,10 +3,51 @@ //! This backend supports all the algorithms supported by Ring and OpenSSL, //! depending on whether the respective crate features are enabled. See the //! documentation for each backend for more information. - -#![cfg(any(feature = "ring", feature = "openssl"))] +//! +//! # Message digests +//! +//! Given some data compute a message digest. +//! +//! ``` +//! use domain::crypto::common::{DigestBuilder, DigestType}; +//! +//! let input = "Hello World!"; +//! let mut ctx = DigestBuilder::new(DigestType::Sha256); +//! ctx.update(input.as_bytes()); +//! ctx.finish().as_ref(); +//! ``` +//! +//! # Signature verification +//! +//! Given some data, a signature, and a DNSKEY, the signature can be verified. +//! +//! ```no_run +//! use domain::rdata::Dnskey; +//! use domain::crypto::common::PublicKey; +//! use domain::base::iana::SecurityAlgorithm; +//! +//! let keyraw = [0u8; 16]; +//! let input = "Hello World!"; +//! let bad_sig = [0u8; 16]; +//! let dnskey = Dnskey::new(256, 3, SecurityAlgorithm::ED25519, keyraw).unwrap(); +//! let public_key = PublicKey::from_dnskey(&dnskey).unwrap(); +//! let res = public_key.verify(input.as_bytes(), &bad_sig); +//! println!("verify result: {res:?}"); +//! ``` + +#![cfg(feature = "unstable-crypto-backend")] +// NOTE: Users should not interact with the `unstable-crypto-backend` feature +// directly, we deliberately show them the features they should use instead. #![cfg_attr(docsrs, doc(cfg(any(feature = "ring", feature = "openssl"))))] +// Fail if 'ring' or 'openssl' is not enabled. +const _: () = { + assert!( + cfg!(any(feature = "ring", feature = "openssl")), + "Do not enable the 'unstable-crypto-backend' feature directly, enable 'ring' or 'openssl' instead", + ); +}; + use core::fmt; use std::error; use std::vec::Vec; diff --git a/src/crypto/mod.rs b/src/crypto/mod.rs index a35077d74..c79bf8ed2 100644 --- a/src/crypto/mod.rs +++ b/src/crypto/mod.rs @@ -12,8 +12,8 @@ //! weaker key sizes). A #![cfg_attr(feature = "unstable-crypto-sign", doc = "[`sign`]")] #![cfg_attr(not(feature = "unstable-crypto-sign"), doc = "`sign`")] -//! backend is provided for users that wish -//! to use either or both backends at runtime. +//! backend is provided for users that wish to use either or both backends at +//! runtime. //! //! Each backend module ( #![cfg_attr( @@ -36,10 +36,8 @@ //! , and #![cfg_attr(feature = "unstable-crypto-sign", doc = "[`sign`]")] #![cfg_attr(not(feature = "unstable-crypto-sign"), doc = "`sign`")] -//! ) -//! exposes a -//! `KeyPair` type, representing a cryptographic key that can be used for -//! signing, and a `generate()` function for creating new keys. +//! ) exposes a `KeyPair` type, representing a cryptographic key that can be +//! used for signing, and a `generate()` function for creating new keys. //! //! Users can choose to bring their own cryptography by providing their own //! `KeyPair` type that implements the @@ -66,64 +64,38 @@ not(feature = "unstable-crypto-sign"), doc = "`sign::GenerateParams`" )] -//! ) support a limited -//! number of algorithms. Even with custom cryptographic backends, -//! this module can only -//! support these algorithms. +//! ) support a limited number of algorithms. Even with custom cryptographic +//! backends, this module can only support these algorithms. //! //! In addition to private key operations, this module provides the #![cfg_attr( - any(feature = "ring", feature = "openssl"), + feature = "unstable-crypto-backend", doc = "[`common::PublicKey`]" )] #![cfg_attr( - not(any(feature = "ring", feature = "openssl")), + not(feature = "unstable-crypto-backend"), doc = "`common::PublicKey`" )] //! type for signature verification. //! //! The module also support computing message digests using the #![cfg_attr( - any(feature = "ring", feature = "openssl"), + feature = "unstable-crypto-backend", doc = "[`common::DigestBuilder`]" )] #![cfg_attr( - not(any(feature = "ring", feature = "openssl")), + not(feature = "unstable-crypto-backend"), doc = "`common::DigestBuilder`" )] //! type. //! -//! # Message digests -//! -//! Given some data compute a message digest. -//! -//! ``` -//! use domain::crypto::common::{DigestBuilder, DigestType}; -//! -//! let input = "Hello World!"; -//! let mut ctx = DigestBuilder::new(DigestType::Sha256); -//! ctx.update(input.as_bytes()); -//! ctx.finish().as_ref(); -//! ``` -//! -//! # Signature verification -//! -//! Given some data, a signature, and a DNSKEY, the signature can be verified. -//! -//! ```no_run -//! use domain::rdata::Dnskey; -//! use domain::crypto::common::PublicKey; -//! use domain::base::iana::SecurityAlgorithm; -//! -//! let keyraw = [0u8; 16]; -//! let input = "Hello World!"; -//! let bad_sig = [0u8; 16]; -//! let dnskey = Dnskey::new(256, 3, SecurityAlgorithm::ED25519, keyraw).unwrap(); -//! let public_key = PublicKey::from_dnskey(&dnskey).unwrap(); -//! let res = public_key.verify(input.as_bytes(), &bad_sig); -//! println!("verify result: {res:?}"); -//! ``` +//! For examples, see the +#![cfg_attr(feature = "unstable-crypto-backend", doc = "[`common`]")] +#![cfg_attr(not(feature = "unstable-crypto-backend"), doc = "`common`")] +//! module. +#![cfg(feature = "unstable-crypto")] +#![cfg_attr(docsrs, doc(cfg(feature = "unstable-crypto")))] #![warn(missing_docs)] #![warn(clippy::missing_docs_in_private_items)] diff --git a/src/dnssec/mod.rs b/src/dnssec/mod.rs index 6d1520919..b9623ea60 100644 --- a/src/dnssec/mod.rs +++ b/src/dnssec/mod.rs @@ -1,40 +1,13 @@ //! DNSSEC signing and validation //! -#![cfg_attr(any(feature = "ring", feature = "openssl"), doc = "* [common]:")] -#![cfg_attr( - not(any(feature = "ring", feature = "openssl")), - doc = "* common:" -)] +#![cfg_attr(feature = "unstable-crypto-backend", doc = "* [common]:")] +#![cfg_attr(not(feature = "unstable-crypto-backend"), doc = "* common:")] //! Types and functions that are common between signing and validation. -#![cfg_attr( - all( - feature = "unstable-sign", - any(feature = "ring", feature = "openssl") - ), - doc = "* [sign]:" -)] -#![cfg_attr( - not(all( - feature = "unstable-sign", - any(feature = "ring", feature = "openssl") - )), - doc = "* sign:" -)] +#![cfg_attr(feature = "unstable-sign", doc = "* [sign]:")] +#![cfg_attr(not(feature = "unstable-sign"), doc = "* sign:")] //! Experimental support for DNSSEC signing. -#![cfg_attr( - all( - feature = "unstable-validator", - any(feature = "ring", feature = "openssl") - ), - doc = "* [validator]:" -)] -#![cfg_attr( - not(all( - feature = "unstable-validator", - any(feature = "ring", feature = "openssl") - )), - doc = "* validator:" -)] +#![cfg_attr(feature = "unstable-validator", doc = "* [validator]:")] +#![cfg_attr(not(feature = "unstable-validator"), doc = "* validator:")] //! Experimental support for DNSSEC validation. //! //! Note that in addition to the feature flags that enable the various modules diff --git a/src/dnssec/sign/mod.rs b/src/dnssec/sign/mod.rs index 4f452df82..f3272070b 100644 --- a/src/dnssec/sign/mod.rs +++ b/src/dnssec/sign/mod.rs @@ -104,10 +104,9 @@ //! [`SortedRecords`]: crate::sign::SortedRecords //! [`Zone`]: crate::zonetree::Zone -#![cfg(all( - feature = "unstable-sign", - any(feature = "ring", feature = "openssl") -))] +#![cfg(feature = "unstable-sign")] +// NOTE: Users should not interact with the `unstable-crypto-backend` feature +// directly, we deliberately show them the features they should use instead. #![cfg_attr( docsrs, doc(cfg(all( @@ -116,6 +115,14 @@ ))) )] +// Fail if 'ring' or 'openssl' is not enabled. +const _: () = { + assert!( + cfg!(feature = "unstable-crypto-backend"), + "'unstable-sign' cannot be used without enabling 'ring' or 'openssl'", + ); +}; + pub mod config; pub mod denial; pub mod error; diff --git a/src/dnssec/validator/mod.rs b/src/dnssec/validator/mod.rs index 33bf13353..a22baad58 100644 --- a/src/dnssec/validator/mod.rs +++ b/src/dnssec/validator/mod.rs @@ -1,17 +1,3 @@ -// Validator - -#![cfg(all( - feature = "unstable-validator", - any(feature = "ring", feature = "openssl") -))] -#![cfg_attr( - docsrs, - doc(cfg(all( - feature = "unstable-validator", - any(feature = "ring", feature = "openssl") - ))) -)] - //! This module provides a DNSSEC validator as described in RFCs //! [4033](https://www.rfc-editor.org/info/rfc4033), //! [4034](https://www.rfc-editor.org/info/rfc4034), @@ -115,9 +101,27 @@ //! # } //! ``` +#![cfg(feature = "unstable-validator")] +// NOTE: Users should not interact with the `unstable-crypto-backend` feature +// directly, we deliberately show them the features they should use instead. +#![cfg_attr( + docsrs, + doc(cfg(all( + feature = "unstable-validator", + any(feature = "ring", feature = "openssl") + ))) +)] #![warn(missing_docs)] #![warn(clippy::missing_docs_in_private_items)] +// Fail if 'ring' or 'openssl' is not enabled. +const _: () = { + assert!( + cfg!(feature = "unstable-crypto-backend"), + "'unstable-validator' cannot be used without enabling 'ring' or 'openssl'", + ); +}; + pub mod anchor; pub mod base; pub mod context;