From 2aadc03ef15cb5ca5cc2af8a7c08e070742f0ac4 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 4 May 2024 14:47:55 +0200 Subject: Adding upstream version 0.70.1+ds1. Signed-off-by: Daniel Baumann --- vendor/signature/src/encoding.rs | 31 ++++++ vendor/signature/src/error.rs | 103 ++++++++++++++++++ vendor/signature/src/hazmat.rs | 70 +++++++++++++ vendor/signature/src/keypair.rs | 29 ++++++ vendor/signature/src/lib.rs | 168 ++++++++++++++++++++++++++++++ vendor/signature/src/prehash_signature.rs | 31 ++++++ vendor/signature/src/signer.rs | 118 +++++++++++++++++++++ vendor/signature/src/verifier.rs | 41 ++++++++ 8 files changed, 591 insertions(+) create mode 100644 vendor/signature/src/encoding.rs create mode 100644 vendor/signature/src/error.rs create mode 100644 vendor/signature/src/hazmat.rs create mode 100644 vendor/signature/src/keypair.rs create mode 100644 vendor/signature/src/lib.rs create mode 100644 vendor/signature/src/prehash_signature.rs create mode 100644 vendor/signature/src/signer.rs create mode 100644 vendor/signature/src/verifier.rs (limited to 'vendor/signature/src') diff --git a/vendor/signature/src/encoding.rs b/vendor/signature/src/encoding.rs new file mode 100644 index 0000000..8bc475b --- /dev/null +++ b/vendor/signature/src/encoding.rs @@ -0,0 +1,31 @@ +//! Encoding support. + +#[cfg(feature = "alloc")] +use alloc::vec::Vec; + +/// Support for decoding/encoding signatures as bytes. +pub trait SignatureEncoding: + Clone + Sized + for<'a> TryFrom<&'a [u8]> + TryInto +{ + /// Byte representation of a signature. + type Repr: 'static + AsRef<[u8]> + Clone + Send + Sync; + + /// Encode signature as its byte representation. + fn to_bytes(&self) -> Self::Repr { + self.clone() + .try_into() + .ok() + .expect("signature encoding error") + } + + /// Encode signature as a byte vector. + #[cfg(feature = "alloc")] + fn to_vec(&self) -> Vec { + self.to_bytes().as_ref().to_vec() + } + + /// Get the length of this signature when encoded. + fn encoded_len(&self) -> usize { + self.to_bytes().as_ref().len() + } +} diff --git a/vendor/signature/src/error.rs b/vendor/signature/src/error.rs new file mode 100644 index 0000000..1bfaf33 --- /dev/null +++ b/vendor/signature/src/error.rs @@ -0,0 +1,103 @@ +//! Signature error types + +use core::fmt::{self, Debug, Display}; + +#[cfg(feature = "std")] +use std::boxed::Box; + +/// Result type. +/// +/// A result with the `signature` crate's [`Error`] type. +pub type Result = core::result::Result; + +/// Signature errors. +/// +/// This type is deliberately opaque as to avoid sidechannel leakage which +/// could potentially be used recover signing private keys or forge signatures +/// (e.g. [BB'06]). +/// +/// When the `std` feature is enabled, it impls [`std::error::Error`] and +/// supports an optional [`std::error::Error::source`], which can be used by +/// things like remote signers (e.g. HSM, KMS) to report I/O or auth errors. +/// +/// [BB'06]: https://en.wikipedia.org/wiki/Daniel_Bleichenbacher +#[derive(Default)] +#[non_exhaustive] +pub struct Error { + /// Source of the error (if applicable). + #[cfg(feature = "std")] + source: Option>, +} + +impl Error { + /// Create a new error with no associated source + pub fn new() -> Self { + Self::default() + } + + /// Create a new error with an associated source. + /// + /// **NOTE:** The "source" should **NOT** be used to propagate cryptographic + /// errors e.g. signature parsing or verification errors. The intended use + /// cases are for propagating errors related to external signers, e.g. + /// communication/authentication errors with HSMs, KMS, etc. + #[cfg(feature = "std")] + pub fn from_source( + source: impl Into>, + ) -> Self { + Self { + source: Some(source.into()), + } + } +} + +impl Debug for Error { + #[cfg(not(feature = "std"))] + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("signature::Error {}") + } + + #[cfg(feature = "std")] + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("signature::Error { source: ")?; + + if let Some(source) = &self.source { + write!(f, "Some({})", source)?; + } else { + f.write_str("None")?; + } + + f.write_str(" }") + } +} + +impl Display for Error { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("signature error")?; + + #[cfg(feature = "std")] + { + if let Some(source) = &self.source { + write!(f, ": {}", source)?; + } + } + + Ok(()) + } +} + +#[cfg(feature = "std")] +impl From> for Error { + fn from(source: Box) -> Error { + Self::from_source(source) + } +} + +#[cfg(feature = "std")] +impl std::error::Error for Error { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + self.source + .as_ref() + .map(|source| source.as_ref() as &(dyn std::error::Error + 'static)) + } +} diff --git a/vendor/signature/src/hazmat.rs b/vendor/signature/src/hazmat.rs new file mode 100644 index 0000000..d2f3e95 --- /dev/null +++ b/vendor/signature/src/hazmat.rs @@ -0,0 +1,70 @@ +//! Hazardous Materials: low-level APIs which can be insecure if misused. +//! +//! The traits in this module are not generally recommended, and should only be +//! used in special cases where they are specifically needed. +//! +//! Using them incorrectly can introduce security vulnerabilities. Please +//! carefully read the documentation before attempting to use them. + +use crate::Error; + +#[cfg(feature = "rand_core")] +use crate::rand_core::CryptoRngCore; + +/// Sign the provided message prehash, returning a digital signature. +pub trait PrehashSigner { + /// Attempt to sign the given message digest, returning a digital signature + /// on success, or an error if something went wrong. + /// + /// The `prehash` parameter should be the output of a secure cryptographic + /// hash function. + /// + /// This API takes a `prehash` byte slice as there can potentially be many + /// compatible lengths for the message digest for a given concrete signature + /// algorithm. + /// + /// Allowed lengths are algorithm-dependent and up to a particular + /// implementation to decide. + fn sign_prehash(&self, prehash: &[u8]) -> Result; +} + +/// Sign the provided message prehash using the provided external randomness source, returning a digital signature. +#[cfg(feature = "rand_core")] +pub trait RandomizedPrehashSigner { + /// Attempt to sign the given message digest, returning a digital signature + /// on success, or an error if something went wrong. + /// + /// The `prehash` parameter should be the output of a secure cryptographic + /// hash function. + /// + /// This API takes a `prehash` byte slice as there can potentially be many + /// compatible lengths for the message digest for a given concrete signature + /// algorithm. + /// + /// Allowed lengths are algorithm-dependent and up to a particular + /// implementation to decide. + fn sign_prehash_with_rng( + &self, + rng: &mut impl CryptoRngCore, + prehash: &[u8], + ) -> Result; +} + +/// Verify the provided message prehash using `Self` (e.g. a public key) +pub trait PrehashVerifier { + /// Use `Self` to verify that the provided signature for a given message + /// `prehash` is authentic. + /// + /// The `prehash` parameter should be the output of a secure cryptographic + /// hash function. + /// + /// Returns `Error` if it is inauthentic or some other error occurred, or + /// otherwise returns `Ok(())`. + /// + /// # ⚠️ Security Warning + /// + /// If `prehash` is something other than the output of a cryptographically + /// secure hash function, an attacker can potentially forge signatures by + /// solving a system of linear equations. + fn verify_prehash(&self, prehash: &[u8], signature: &S) -> Result<(), Error>; +} diff --git a/vendor/signature/src/keypair.rs b/vendor/signature/src/keypair.rs new file mode 100644 index 0000000..d4795f2 --- /dev/null +++ b/vendor/signature/src/keypair.rs @@ -0,0 +1,29 @@ +//! Signing keypairs. + +/// Signing keypair with an associated verifying key. +/// +/// This represents a type which holds both a signing key and a verifying key. +pub trait Keypair { + /// Verifying key type for this keypair. + type VerifyingKey: Clone; + + /// Get the verifying key which can verify signatures produced by the + /// signing key portion of this keypair. + fn verifying_key(&self) -> Self::VerifyingKey; +} + +/// Signing keypair with an associated verifying key. +/// +/// This represents a type which holds both a signing key and a verifying key. +pub trait KeypairRef: AsRef { + /// Verifying key type for this keypair. + type VerifyingKey: Clone; +} + +impl Keypair for K { + type VerifyingKey = ::VerifyingKey; + + fn verifying_key(&self) -> Self::VerifyingKey { + self.as_ref().clone() + } +} diff --git a/vendor/signature/src/lib.rs b/vendor/signature/src/lib.rs new file mode 100644 index 0000000..ba1feb4 --- /dev/null +++ b/vendor/signature/src/lib.rs @@ -0,0 +1,168 @@ +#![no_std] +#![doc = include_str!("../README.md")] +#![doc( + html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/8f1a9894/logo.svg", + html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/8f1a9894/logo.svg" +)] +#![cfg_attr(docsrs, feature(doc_auto_cfg))] +#![forbid(unsafe_code)] +#![warn( + clippy::mod_module_files, + clippy::unwrap_used, + missing_docs, + rust_2018_idioms, + unused_lifetimes, + unused_qualifications +)] + +//! # Design +//! +//! This crate provides a common set of traits for signing and verifying +//! digital signatures intended to be implemented by libraries which produce +//! or contain implementations of digital signature algorithms, and used by +//! libraries which want to produce or verify digital signatures while +//! generically supporting any compatible backend. +//! +//! ## Goals +//! +//! The traits provided by this crate were designed with the following goals +//! in mind: +//! +//! - Provide an easy-to-use, misuse resistant API optimized for consumers +//! (as opposed to implementers) of its traits. +//! - Support common type-safe wrappers around "bag-of-bytes" representations +//! which can be directly parsed from or written to the "wire". +//! - Expose a trait/object-safe API where signers/verifiers spanning multiple +//! homogeneous provider implementations can be seamlessly leveraged together +//! in the same logical "keyring" so long as they operate on the same +//! underlying signature type. +//! - Allow one provider type to potentially implement support (including +//! being generic over) several signature types. +//! - Keep signature algorithm customizations / "knobs" out-of-band from the +//! signing/verification APIs, ideally pushing such concerns into the type +//! system so that algorithm mismatches are caught as type errors. +//! - Opaque error type which minimizes information leaked from cryptographic +//! failures, as "rich" error types in these scenarios are often a source +//! of sidechannel information for attackers (e.g. [BB'06]) +//! +//! [BB'06]: https://en.wikipedia.org/wiki/Daniel_Bleichenbacher +//! +//! ## Implementation +//! +//! To accomplish the above goals, the [`Signer`] and [`Verifier`] traits +//! provided by this are generic over a signature value, and use generic +//! parameters rather than associated types. Notably, they use such a parameter +//! for the return value, allowing it to be inferred by the type checker based +//! on the desired signature type. +//! +//! ## Alternatives considered +//! +//! This crate is based on many years of exploration of how to encapsulate +//! digital signature systems in the most flexible, developer-friendly way. +//! During that time many design alternatives were explored, tradeoffs +//! compared, and ultimately the provided API was selected. +//! +//! The tradeoffs made in this API have all been to improve simplicity, +//! ergonomics, type safety, and flexibility for *consumers* of the traits. +//! At times, this has come at a cost to implementers. Below are some concerns +//! we are cognizant of which were considered in the design of the API: +//! +//! - "Bag-of-bytes" serialization precludes signature providers from using +//! their own internal representation of a signature, which can be helpful +//! for many reasons (e.g. advanced signature system features like batch +//! verification). +//! - Associated types, rather than generic parameters of traits, could allow +//! more customization of the types used by a particular signature system, +//! e.g. using custom error types. +//! +//! It may still make sense to continue to explore the above tradeoffs, but +//! with a *new* set of traits which are intended to be implementor-friendly, +//! rather than consumer friendly. The existing [`Signer`] and [`Verifier`] +//! traits could have blanket impls for the "provider-friendly" traits. +//! However, as noted above this is a design space easily explored after +//! stabilizing the consumer-oriented traits, and thus we consider these +//! more important. +//! +//! That said, below are some caveats of trying to design such traits, and +//! why we haven't actively pursued them: +//! +//! - Generics in the return position are already used to select which trait +//! impl to use, i.e. for a particular signature algorithm/system. Avoiding +//! a unified, concrete signature type adds another dimension to complexity +//! and compiler errors, and in our experience makes them unsuitable for this +//! sort of API. We believe such an API is the natural one for signature +//! systems, reflecting the natural way they are written absent a trait. +//! - Associated types preclude multiple (or generic) implementations of the +//! same trait. These parameters are common in signature systems, notably +//! ones which support different digest algorithms. +//! - Digital signatures are almost always larger than the present 32-entry +//! trait impl limitation on array types, which complicates trait signatures +//! for these types (particularly things like `From` or `Borrow` bounds). +//! This may be more interesting to explore after const generics. +//! +//! ## Unstable features +//! +//! Despite being post-1.0, this crate includes off-by-default unstable +//! optional features, each of which depends on a pre-1.0 +//! crate. +//! +//! These features are considered exempt from SemVer. See the +//! [SemVer policy](#semver-policy) above for more information. +//! +//! The following unstable features are presently supported: +//! +//! - `derive`: for implementers of signature systems using [`DigestSigner`] +//! and [`DigestVerifier`], the `derive` feature can be used to +//! derive [`Signer`] and [`Verifier`] traits which prehash the input +//! message using the [`PrehashSignature::Digest`] algorithm for +//! a given signature type. When the `derive` feature is enabled +//! import the proc macros with `use signature::{Signer, Verifier}` and then +//! add a `derive(Signer)` or `derive(Verifier)` attribute to the given +//! digest signer/verifier type. Enabling this feature also enables `digest` +//! support (see immediately below). +//! - `digest`: enables the [`DigestSigner`] and [`DigestVerifier`] +//! traits which are based on the [`Digest`] trait from the [`digest`] crate. +//! These traits are used for representing signature systems based on the +//! [Fiat-Shamir heuristic] which compute a random challenge value to sign +//! by computing a cryptographically secure digest of the input message. +//! - `rand_core`: enables the [`RandomizedSigner`] trait for signature +//! systems which rely on a cryptographically secure random number generator +//! for security. +//! +//! NOTE: the [`async-signature`] crate contains experimental `async` support +//! for [`Signer`] and [`DigestSigner`]. +//! +//! [`async-signature`]: https://docs.rs/async-signature +//! [`digest`]: https://docs.rs/digest/ +//! [`Digest`]: https://docs.rs/digest/latest/digest/trait.Digest.html +//! [Fiat-Shamir heuristic]: https://en.wikipedia.org/wiki/Fiat%E2%80%93Shamir_heuristic + +#[cfg(feature = "alloc")] +extern crate alloc; +#[cfg(feature = "std")] +extern crate std; + +pub mod hazmat; + +mod encoding; +mod error; +mod keypair; +mod signer; +mod verifier; + +#[cfg(feature = "digest")] +mod prehash_signature; + +pub use crate::{encoding::*, error::*, keypair::*, signer::*, verifier::*}; + +#[cfg(feature = "derive")] +pub use derive::{Signer, Verifier}; + +#[cfg(all(feature = "derive", feature = "digest"))] +pub use derive::{DigestSigner, DigestVerifier}; + +#[cfg(feature = "digest")] +pub use {crate::prehash_signature::*, digest}; + +#[cfg(feature = "rand_core")] +pub use rand_core; diff --git a/vendor/signature/src/prehash_signature.rs b/vendor/signature/src/prehash_signature.rs new file mode 100644 index 0000000..d9a8645 --- /dev/null +++ b/vendor/signature/src/prehash_signature.rs @@ -0,0 +1,31 @@ +//! `PrehashSignature` trait. + +/// For intra-doc link resolution. +#[allow(unused_imports)] +use crate::{ + signer::{DigestSigner, Signer}, + verifier::{DigestVerifier, Verifier}, +}; + +/// Marker trait for `Signature` types computable as `𝐒(𝐇(𝒎))` +/// i.e. ones which prehash a message to be signed as `𝐇(𝒎)` +/// +/// Where: +/// +/// - `𝐒`: signature algorithm +/// - `𝐇`: hash (a.k.a. digest) function +/// - `𝒎`: message +/// +/// This approach is relatively common in signature schemes based on the +/// [Fiat-Shamir heuristic]. +/// +/// For signature types that implement this trait, when the `derive` crate +/// feature is enabled a custom derive for [`Signer`] is available for any +/// types that impl [`DigestSigner`], and likewise for deriving [`Verifier`] for +/// types which impl [`DigestVerifier`]. +/// +/// [Fiat-Shamir heuristic]: https://en.wikipedia.org/wiki/Fiat%E2%80%93Shamir_heuristic +pub trait PrehashSignature { + /// Preferred `Digest` algorithm to use when computing this signature type. + type Digest: digest::Digest; +} diff --git a/vendor/signature/src/signer.rs b/vendor/signature/src/signer.rs new file mode 100644 index 0000000..b339ddf --- /dev/null +++ b/vendor/signature/src/signer.rs @@ -0,0 +1,118 @@ +//! Traits for generating digital signatures + +use crate::error::Error; + +#[cfg(feature = "digest")] +use crate::digest::Digest; + +#[cfg(feature = "rand_core")] +use crate::rand_core::CryptoRngCore; + +/// Sign the provided message bytestring using `Self` (e.g. a cryptographic key +/// or connection to an HSM), returning a digital signature. +pub trait Signer { + /// Sign the given message and return a digital signature + fn sign(&self, msg: &[u8]) -> S { + self.try_sign(msg).expect("signature operation failed") + } + + /// Attempt to sign the given message, returning a digital signature on + /// success, or an error if something went wrong. + /// + /// The main intended use case for signing errors is when communicating + /// with external signers, e.g. cloud KMS, HSMs, or other hardware tokens. + fn try_sign(&self, msg: &[u8]) -> Result; +} + +/// Sign the provided message bytestring using `&mut Self` (e.g. an evolving +/// cryptographic key such as a stateful hash-based signature), returning a +/// digital signature. +pub trait SignerMut { + /// Sign the given message, update the state, and return a digital signature. + fn sign(&mut self, msg: &[u8]) -> S { + self.try_sign(msg).expect("signature operation failed") + } + + /// Attempt to sign the given message, updating the state, and returning a + /// digital signature on success, or an error if something went wrong. + /// + /// Signing can fail, e.g., if the number of time periods allowed by the + /// current key is exceeded. + fn try_sign(&mut self, msg: &[u8]) -> Result; +} + +/// Blanket impl of [`SignerMut`] for all [`Signer`] types. +impl> SignerMut for T { + fn try_sign(&mut self, msg: &[u8]) -> Result { + T::try_sign(self, msg) + } +} + +/// Sign the given prehashed message [`Digest`] using `Self`. +/// +/// ## Notes +/// +/// This trait is primarily intended for signature algorithms based on the +/// [Fiat-Shamir heuristic], a method for converting an interactive +/// challenge/response-based proof-of-knowledge protocol into an offline +/// digital signature through the use of a random oracle, i.e. a digest +/// function. +/// +/// The security of such protocols critically rests upon the inability of +/// an attacker to solve for the output of the random oracle, as generally +/// otherwise such signature algorithms are a system of linear equations and +/// therefore doing so would allow the attacker to trivially forge signatures. +/// +/// To prevent misuse which would potentially allow this to be possible, this +/// API accepts a [`Digest`] instance, rather than a raw digest value. +/// +/// [Fiat-Shamir heuristic]: https://en.wikipedia.org/wiki/Fiat%E2%80%93Shamir_heuristic +#[cfg(feature = "digest")] +pub trait DigestSigner { + /// Sign the given prehashed message [`Digest`], returning a signature. + /// + /// Panics in the event of a signing error. + fn sign_digest(&self, digest: D) -> S { + self.try_sign_digest(digest) + .expect("signature operation failed") + } + + /// Attempt to sign the given prehashed message [`Digest`], returning a + /// digital signature on success, or an error if something went wrong. + fn try_sign_digest(&self, digest: D) -> Result; +} + +/// Sign the given message using the provided external randomness source. +#[cfg(feature = "rand_core")] +pub trait RandomizedSigner { + /// Sign the given message and return a digital signature + fn sign_with_rng(&self, rng: &mut impl CryptoRngCore, msg: &[u8]) -> S { + self.try_sign_with_rng(rng, msg) + .expect("signature operation failed") + } + + /// Attempt to sign the given message, returning a digital signature on + /// success, or an error if something went wrong. + /// + /// The main intended use case for signing errors is when communicating + /// with external signers, e.g. cloud KMS, HSMs, or other hardware tokens. + fn try_sign_with_rng(&self, rng: &mut impl CryptoRngCore, msg: &[u8]) -> Result; +} + +/// Combination of [`DigestSigner`] and [`RandomizedSigner`] with support for +/// computing a signature over a digest which requires entropy from an RNG. +#[cfg(all(feature = "digest", feature = "rand_core"))] +pub trait RandomizedDigestSigner { + /// Sign the given prehashed message `Digest`, returning a signature. + /// + /// Panics in the event of a signing error. + fn sign_digest_with_rng(&self, rng: &mut impl CryptoRngCore, digest: D) -> S { + self.try_sign_digest_with_rng(rng, digest) + .expect("signature operation failed") + } + + /// Attempt to sign the given prehashed message `Digest`, returning a + /// digital signature on success, or an error if something went wrong. + fn try_sign_digest_with_rng(&self, rng: &mut impl CryptoRngCore, digest: D) + -> Result; +} diff --git a/vendor/signature/src/verifier.rs b/vendor/signature/src/verifier.rs new file mode 100644 index 0000000..65409a9 --- /dev/null +++ b/vendor/signature/src/verifier.rs @@ -0,0 +1,41 @@ +//! Trait for verifying digital signatures + +use crate::error::Error; + +#[cfg(feature = "digest")] +use crate::digest::Digest; + +/// Verify the provided message bytestring using `Self` (e.g. a public key) +pub trait Verifier { + /// Use `Self` to verify that the provided signature for a given message + /// bytestring is authentic. + /// + /// Returns `Error` if it is inauthentic, or otherwise returns `()`. + fn verify(&self, msg: &[u8], signature: &S) -> Result<(), Error>; +} + +/// Verify the provided signature for the given prehashed message [`Digest`] +/// is authentic. +/// +/// ## Notes +/// +/// This trait is primarily intended for signature algorithms based on the +/// [Fiat-Shamir heuristic], a method for converting an interactive +/// challenge/response-based proof-of-knowledge protocol into an offline +/// digital signature through the use of a random oracle, i.e. a digest +/// function. +/// +/// The security of such protocols critically rests upon the inability of +/// an attacker to solve for the output of the random oracle, as generally +/// otherwise such signature algorithms are a system of linear equations and +/// therefore doing so would allow the attacker to trivially forge signatures. +/// +/// To prevent misuse which would potentially allow this to be possible, this +/// API accepts a [`Digest`] instance, rather than a raw digest value. +/// +/// [Fiat-Shamir heuristic]: https://en.wikipedia.org/wiki/Fiat%E2%80%93Shamir_heuristic +#[cfg(feature = "digest")] +pub trait DigestVerifier { + /// Verify the signature against the given [`Digest`] output. + fn verify_digest(&self, digest: D, signature: &S) -> Result<(), Error>; +} -- cgit v1.2.3