From 4a495845aad861591ade26ca3790ea99f9ba0e8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Iv=C3=A1n=20Vieitez=20Parra?= <3857362+corrideat@users.noreply.github.com> Date: Mon, 29 Jan 2024 15:05:28 +0100 Subject: [PATCH] Support compiling without cryptography primitives (#208) This makes all of the crypto libraries optional. My use case requires simply generating the binary ASN.1 structures and all cryptography is handled externally with HSMs. This change removes unnecessary code and build complexity (for example, I'm targeting WASM, and I need to take extra steps to build the dependencies I don't need). Note to the maintainer: this is a clean (and ideally better) rework of a previous PR, #207. Because I deleted the older and messier branch, the previous PR couldn't be updated, so I closed it. --- .github/workflows/ci.yml | 3 ++ rcgen/Cargo.toml | 11 +++++-- rcgen/src/crl.rs | 19 ++++++++++- rcgen/src/error.rs | 5 +++ rcgen/src/key_pair.rs | 58 ++++++++++++++++++++++++++------- rcgen/src/lib.rs | 70 +++++++++++++++++++++++++++++----------- rcgen/src/ring_like.rs | 12 ++++--- rcgen/src/sign_algo.rs | 16 +++++++-- rcgen/tests/botan.rs | 2 +- rcgen/tests/generic.rs | 2 ++ rcgen/tests/util.rs | 2 ++ rcgen/tests/webpki.rs | 2 ++ 12 files changed, 160 insertions(+), 42 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7a90d40a..d8d2b4e5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -33,6 +33,7 @@ jobs: matrix: features: - --all-features + - --no-default-features - --no-default-features --features ring - --no-default-features --features aws_lc_rs - --no-default-features --features aws_lc_rs,pem @@ -137,6 +138,8 @@ jobs: run: cargo test --verbose --features x509-parser --all-targets - name: Run the tests with aws_lc_rs backend enabled run: cargo test --verbose --no-default-features --features aws_lc_rs,pem --all-targets + - name: Run the tests with no features enabled + run: cargo test --verbose --no-default-features --all-targets build: strategy: diff --git a/rcgen/Cargo.toml b/rcgen/Cargo.toml index e4a1506f..c237bc7b 100644 --- a/rcgen/Cargo.toml +++ b/rcgen/Cargo.toml @@ -21,6 +21,10 @@ required-features = ["pem"] name = "sign-leaf-with-ca" required-features = ["pem", "x509-parser"] +[[example]] +name = "simple" +required-features = ["crypto"] + [dependencies] aws-lc-rs = { version = "1.0.0", optional = true } yasna = { version = "0.5.2", features = ["time", "std"] } @@ -31,9 +35,10 @@ x509-parser = { workspace = true, features = ["verify"], optional = true } zeroize = { version = "1.2", optional = true } [features] -default = ["pem", "ring"] -aws_lc_rs = ["dep:aws-lc-rs"] -ring = ["dep:ring"] +default = ["crypto", "pem", "ring"] +crypto = [] +aws_lc_rs = ["crypto", "dep:aws-lc-rs"] +ring = ["crypto", "dep:ring"] [package.metadata.docs.rs] diff --git a/rcgen/src/crl.rs b/rcgen/src/crl.rs index 78a539e1..7ea51c49 100644 --- a/rcgen/src/crl.rs +++ b/rcgen/src/crl.rs @@ -21,12 +21,26 @@ use crate::{Certificate, Error, KeyIdMethod, KeyUsagePurpose, SerialNumber}; /// extern crate rcgen; /// use rcgen::*; /// +/// #[cfg(not(feature = "crypto"))] +/// struct MyKeyPair { public_key: Vec } +/// #[cfg(not(feature = "crypto"))] +/// impl RemoteKeyPair for MyKeyPair { +/// fn public_key(&self) -> &[u8] { &self.public_key } +/// fn sign(&self, _: &[u8]) -> Result, rcgen::Error> { Ok(vec![]) } +/// fn algorithm(&self) -> &'static SignatureAlgorithm { &PKCS_ED25519 } +/// } /// # fn main () { /// // Generate a CRL issuer. -/// let mut issuer_params = CertificateParams::new(vec!["crl.issuer.example.com".to_string()]); +/// let mut issuer_params = CertificateParams::new(vec!["crl.issuer.example.com".to_string()]).unwrap(); +/// issuer_params.serial_number = Some(SerialNumber::from(9999)); /// issuer_params.is_ca = IsCa::Ca(BasicConstraints::Unconstrained); /// issuer_params.key_usages = vec![KeyUsagePurpose::KeyCertSign, KeyUsagePurpose::DigitalSignature, KeyUsagePurpose::CrlSign]; +/// #[cfg(feature = "crypto")] /// let key_pair = KeyPair::generate().unwrap(); +/// #[cfg(not(feature = "crypto"))] +/// let remote_key_pair = MyKeyPair { public_key: vec![] }; +/// #[cfg(not(feature = "crypto"))] +/// let key_pair = KeyPair::from_remote(Box::new(remote_key_pair)).unwrap(); /// let issuer = Certificate::generate_self_signed(issuer_params, &key_pair).unwrap(); /// // Describe a revoked certificate. /// let revoked_cert = RevokedCertParams{ @@ -42,7 +56,10 @@ use crate::{Certificate, Error, KeyIdMethod, KeyUsagePurpose, SerialNumber}; /// crl_number: SerialNumber::from(1234), /// issuing_distribution_point: None, /// revoked_certs: vec![revoked_cert], +/// #[cfg(feature = "crypto")] /// key_identifier_method: KeyIdMethod::Sha256, +/// #[cfg(not(feature = "crypto"))] +/// key_identifier_method: KeyIdMethod::PreSpecified(vec![]), /// }; /// let crl = CertificateRevocationList::from_params(crl).unwrap(); ///# } diff --git a/rcgen/src/error.rs b/rcgen/src/error.rs index 16835ff5..3f86ee01 100644 --- a/rcgen/src/error.rs +++ b/rcgen/src/error.rs @@ -42,6 +42,9 @@ pub enum Error { InvalidCrlNextUpdate, /// CRL issuer specifies Key Usages that don't include cRLSign. IssuerNotCrlSigner, + #[cfg(not(feature = "crypto"))] + /// Missing serial number + MissingSerialNumber, } impl fmt::Display for Error { @@ -86,6 +89,8 @@ impl fmt::Display for Error { f, "CRL issuer must specify no key usage, or key usage including cRLSign" )?, + #[cfg(not(feature = "crypto"))] + MissingSerialNumber => write!(f, "A serial number must be specified")?, }; Ok(()) } diff --git a/rcgen/src/key_pair.rs b/rcgen/src/key_pair.rs index fef14edd..84d5d0aa 100644 --- a/rcgen/src/key_pair.rs +++ b/rcgen/src/key_pair.rs @@ -1,30 +1,38 @@ #[cfg(feature = "pem")] use pem::Pem; +#[cfg(feature = "crypto")] use std::convert::TryFrom; use std::fmt; use yasna::DERWriter; +#[cfg(any(feature = "crypto", feature = "pem"))] use crate::error::ExternalError; -use crate::ring_like::error as ring_error; -use crate::ring_like::rand::SystemRandom; -use crate::ring_like::signature::{ - self, EcdsaKeyPair, Ed25519KeyPair, KeyPair as RingKeyPair, RsaEncoding, RsaKeyPair, +#[cfg(feature = "crypto")] +use crate::ring_like::{ + error as ring_error, + rand::SystemRandom, + signature::{ + self, EcdsaKeyPair, Ed25519KeyPair, KeyPair as RingKeyPair, RsaEncoding, RsaKeyPair, + }, + {ecdsa_from_pkcs8, rsa_key_pair_public_modulus_len}, }; -use crate::ring_like::{ecdsa_from_pkcs8, rsa_key_pair_public_modulus_len}; -use crate::sign_algo::algo::*; -use crate::sign_algo::SignAlgo; +#[cfg(feature = "crypto")] +use crate::sign_algo::{algo::*, SignAlgo}; #[cfg(feature = "pem")] use crate::ENCODE_CONFIG; -use crate::{Error, SignatureAlgorithm}; +use crate::{sign_algo::SignatureAlgorithm, Error}; /// A key pair variant #[allow(clippy::large_enum_variant)] pub(crate) enum KeyPairKind { /// A Ecdsa key pair + #[cfg(feature = "crypto")] Ec(EcdsaKeyPair), /// A Ed25519 key pair + #[cfg(feature = "crypto")] Ed(Ed25519KeyPair), /// A RSA key pair + #[cfg(feature = "crypto")] Rsa(RsaKeyPair, &'static dyn RsaEncoding), /// A remote key pair Remote(Box), @@ -33,8 +41,11 @@ pub(crate) enum KeyPairKind { impl fmt::Debug for KeyPairKind { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { + #[cfg(feature = "crypto")] Self::Ec(key_pair) => write!(f, "{:?}", key_pair), + #[cfg(feature = "crypto")] Self::Ed(key_pair) => write!(f, "{:?}", key_pair), + #[cfg(feature = "crypto")] Self::Rsa(key_pair, _) => write!(f, "{:?}", key_pair), Self::Remote(_) => write!(f, "Box"), } @@ -57,6 +68,7 @@ pub struct KeyPair { impl KeyPair { /// Generate a new random [`PKCS_ECDSA_P256_SHA256`] key pair + #[cfg(feature = "crypto")] pub fn generate() -> Result { Self::generate_for(&PKCS_ECDSA_P256_SHA256) } @@ -64,6 +76,7 @@ impl KeyPair { /// Generate a new random key pair for the specified signature algorithm /// /// If you're not sure which algorithm to use, [`PKCS_ECDSA_P256_SHA256`] is a good choice. + #[cfg(feature = "crypto")] pub fn generate_for(alg: &'static SignatureAlgorithm) -> Result { let rng = &SystemRandom::new(); @@ -102,6 +115,7 @@ impl KeyPair { /// Parses the key pair from the DER format /// /// Equivalent to using the [`TryFrom`] implementation. + #[cfg(feature = "crypto")] pub fn from_der(der: &[u8]) -> Result { Ok(der.try_into()?) } @@ -112,7 +126,7 @@ impl KeyPair { } /// Parses the key pair from the ASCII PEM format - #[cfg(feature = "pem")] + #[cfg(all(feature = "pem", feature = "crypto"))] pub fn from_pem(pem_str: &str) -> Result { let private_key = pem::parse(pem_str)._err()?; let private_key_der: &[_] = private_key.contents(); @@ -132,7 +146,7 @@ impl KeyPair { /// using the specified [`SignatureAlgorithm`] /// /// Same as [from_pem_and_sign_algo](Self::from_pem_and_sign_algo). - #[cfg(feature = "pem")] + #[cfg(all(feature = "pem", feature = "crypto"))] pub fn from_pem_and_sign_algo( pem_str: &str, alg: &'static SignatureAlgorithm, @@ -151,6 +165,7 @@ impl KeyPair { /// key pair. However, sometimes multiple signature algorithms fit for the /// same der key. In that instance, you can use this function to precisely /// specify the `SignatureAlgorithm`. + #[cfg(feature = "crypto")] pub fn from_der_and_sign_algo( pkcs8: &[u8], alg: &'static SignatureAlgorithm, @@ -195,6 +210,7 @@ impl KeyPair { }) } + #[cfg(feature = "crypto")] pub(crate) fn from_raw( pkcs8: &[u8], ) -> Result<(KeyPairKind, &'static SignatureAlgorithm), Error> { @@ -242,17 +258,20 @@ impl KeyPair { pub(crate) fn sign(&self, msg: &[u8], writer: DERWriter) -> Result<(), Error> { match &self.kind { + #[cfg(feature = "crypto")] KeyPairKind::Ec(kp) => { let system_random = SystemRandom::new(); let signature = kp.sign(&system_random, msg)._err()?; let sig = &signature.as_ref(); writer.write_bitvec_bytes(&sig, &sig.len() * 8); }, + #[cfg(feature = "crypto")] KeyPairKind::Ed(kp) => { let signature = kp.sign(msg); let sig = &signature.as_ref(); writer.write_bitvec_bytes(&sig, &sig.len() * 8); }, + #[cfg(feature = "crypto")] KeyPairKind::Rsa(kp, padding_alg) => { let system_random = SystemRandom::new(); let mut signature = vec![0; rsa_key_pair_public_modulus_len(kp)]; @@ -292,6 +311,7 @@ impl KeyPair { /// /// Panics if called on a remote key pair. pub fn serialize_der(&self) -> Vec { + #[cfg_attr(not(feature = "crypto"), allow(irrefutable_let_patterns))] if let KeyPairKind::Remote(_) = self.kind { panic!("Serializing a remote key pair is not supported") } @@ -304,6 +324,7 @@ impl KeyPair { /// /// Panics if called on a remote key pair. pub fn serialized_der(&self) -> &[u8] { + #[cfg_attr(not(feature = "crypto"), allow(irrefutable_let_patterns))] if let KeyPairKind::Remote(_) = self.kind { panic!("Serializing a remote key pair is not supported") } @@ -313,6 +334,7 @@ impl KeyPair { /// Access the remote key pair if it is a remote one pub fn as_remote(&self) -> Option<&(dyn RemoteKeyPair + Send + Sync)> { + #[cfg_attr(not(feature = "crypto"), allow(irrefutable_let_patterns))] if let KeyPairKind::Remote(remote) = &self.kind { Some(remote.as_ref()) } else { @@ -329,6 +351,7 @@ impl KeyPair { } } +#[cfg(feature = "crypto")] impl TryFrom<&[u8]> for KeyPair { type Error = Error; @@ -342,6 +365,7 @@ impl TryFrom<&[u8]> for KeyPair { } } +#[cfg(feature = "crypto")] impl TryFrom> for KeyPair { type Error = Error; @@ -361,8 +385,11 @@ impl PublicKeyData for KeyPair { } fn raw_bytes(&self) -> &[u8] { match &self.kind { + #[cfg(feature = "crypto")] KeyPairKind::Ec(kp) => kp.public_key().as_ref(), + #[cfg(feature = "crypto")] KeyPairKind::Ed(kp) => kp.public_key().as_ref(), + #[cfg(feature = "crypto")] KeyPairKind::Rsa(kp, _) => kp.public_key().as_ref(), KeyPairKind::Remote(kp) => kp.public_key(), } @@ -384,12 +411,14 @@ pub trait RemoteKeyPair { fn algorithm(&self) -> &'static SignatureAlgorithm; } +#[cfg(feature = "crypto")] impl ExternalError for Result { fn _err(self) -> Result { self.map_err(|e| Error::RingKeyRejected(e.to_string())) } } +#[cfg(feature = "crypto")] impl ExternalError for Result { fn _err(self) -> Result { self.map_err(|_| Error::RingUnspecified) @@ -419,11 +448,16 @@ pub(crate) trait PublicKeyData { #[cfg(test)] mod test { + #[cfg(crypto)] use super::*; - use crate::ring_like::rand::SystemRandom; - use crate::ring_like::signature::{EcdsaKeyPair, ECDSA_P256_SHA256_FIXED_SIGNING}; + #[cfg(crypto)] + use crate::ring_like::{ + rand::SystemRandom, + signature::{EcdsaKeyPair, ECDSA_P256_SHA256_FIXED_SIGNING}, + }; + #[cfg(crypto)] #[test] fn test_algorithm() { let rng = SystemRandom::new(); diff --git a/rcgen/src/lib.rs b/rcgen/src/lib.rs index 217d01aa..0b8689a2 100644 --- a/rcgen/src/lib.rs +++ b/rcgen/src/lib.rs @@ -35,6 +35,7 @@ println!("{}", key_pair.serialize_pem()); #[cfg(feature = "pem")] use pem::Pem; +#[cfg(feature = "crypto")] use ring_like::digest; use std::collections::HashMap; use std::convert::TryFrom; @@ -93,6 +94,7 @@ this function fills in the other generation parameters with reasonable defaults and generates a self signed certificate and key pair as output. */ +#[cfg(feature = "crypto")] #[cfg_attr( feature = "pem", doc = r##" @@ -577,7 +579,10 @@ impl Default for CertificateParams { crl_distribution_points: Vec::new(), custom_extensions: Vec::new(), use_authority_key_identifier_extension: false, + #[cfg(feature = "crypto")] key_identifier_method: KeyIdMethod::Sha256, + #[cfg(not(feature = "crypto"))] + key_identifier_method: KeyIdMethod::PreSpecified(Vec::new()), } } } @@ -638,15 +643,24 @@ impl CertificateParams { let name_constraints = Self::convert_x509_name_constraints(&x509)?; let serial_number = Some(x509.serial.to_bytes_be().into()); - let key_identifier_method = x509 - .iter_extensions() - .find_map(|ext| match ext.parsed_extension() { - x509_parser::extensions::ParsedExtension::SubjectKeyIdentifier(key_id) => { - Some(KeyIdMethod::PreSpecified(key_id.0.into())) - }, - _ => None, - }) - .unwrap_or(KeyIdMethod::Sha256); + let key_identifier_method = + x509.iter_extensions() + .find_map(|ext| match ext.parsed_extension() { + x509_parser::extensions::ParsedExtension::SubjectKeyIdentifier(key_id) => { + Some(KeyIdMethod::PreSpecified(key_id.0.into())) + }, + _ => None, + }); + + let key_identifier_method = match key_identifier_method { + Some(method) => method, + None => { + #[cfg(not(feature = "crypto"))] + return Err(Error::UnsupportedSignatureAlgorithm); + #[cfg(feature = "crypto")] + KeyIdMethod::Sha256 + }, + }; Ok(CertificateParams { is_ca, @@ -959,11 +973,18 @@ impl CertificateParams { if let Some(ref serial) = self.serial_number { writer.next().write_bigint_bytes(serial.as_ref(), true); } else { - let hash = digest::digest(&digest::SHA256, pub_key.raw_bytes()); - // RFC 5280 specifies at most 20 bytes for a serial number - let mut sl = hash.as_ref()[0..20].to_vec(); - sl[0] = sl[0] & 0x7f; // MSB must be 0 to ensure encoding bignum in 20 bytes - writer.next().write_bigint_bytes(&sl, true); + #[cfg(feature = "crypto")] + { + let hash = digest::digest(&digest::SHA256, pub_key.raw_bytes()); + // RFC 5280 specifies at most 20 bytes for a serial number + let mut sl = hash.as_ref()[0..20].to_vec(); + sl[0] = sl[0] & 0x7f; // MSB must be 0 to ensure encoding bignum in 20 bytes + writer.next().write_bigint_bytes(&sl, true); + } + #[cfg(not(feature = "crypto"))] + if self.serial_number.is_none() { + return Err(Error::MissingSerialNumber); + } }; // Write signature algorithm issuer.alg.write_alg_ident(writer.next()); @@ -1166,7 +1187,6 @@ impl CertificateParams { Ok(()) }) } - fn serialize_der_with_signer( &self, pub_key: &K, @@ -1366,10 +1386,13 @@ impl CustomExtension { #[non_exhaustive] pub enum KeyIdMethod { /// RFC 7093 method 1 - a truncated SHA256 digest. + #[cfg(feature = "crypto")] Sha256, /// RFC 7093 method 2 - a truncated SHA384 digest. + #[cfg(feature = "crypto")] Sha384, /// RFC 7093 method 3 - a truncated SHA512 digest. + #[cfg(feature = "crypto")] Sha512, /// Pre-specified identifier. The exact given value is used as the key identifier. PreSpecified(Vec), @@ -1383,17 +1406,24 @@ impl KeyIdMethod { /// /// This key identifier is used in the SubjectKeyIdentifier and AuthorityKeyIdentifier /// X.509v3 extensions. + #[allow(unused_variables)] pub(crate) fn derive(&self, subject_public_key_info: impl AsRef<[u8]>) -> Vec { let digest_method = match &self { + #[cfg(feature = "crypto")] Self::Sha256 => &digest::SHA256, + #[cfg(feature = "crypto")] Self::Sha384 => &digest::SHA384, + #[cfg(feature = "crypto")] Self::Sha512 => &digest::SHA512, Self::PreSpecified(b) => { return b.to_vec(); }, }; - let digest = digest::digest(digest_method, subject_public_key_info.as_ref()); - digest.as_ref()[0..20].to_vec() + #[cfg(feature = "crypto")] + { + let digest = digest::digest(digest_method, subject_public_key_info.as_ref()); + digest.as_ref()[0..20].to_vec() + } } } @@ -1808,6 +1838,7 @@ mod tests { } } + #[cfg(crypto)] #[test] fn test_with_key_usages() { let mut params: CertificateParams = Default::default(); @@ -1850,6 +1881,7 @@ mod tests { assert!(found); } + #[cfg(crypto)] #[test] fn test_with_key_usages_decipheronly_only() { let mut params: CertificateParams = Default::default(); @@ -1888,6 +1920,7 @@ mod tests { assert!(found); } + #[cfg(crypto)] #[test] fn test_with_extended_key_usages_any() { let mut params: CertificateParams = Default::default(); @@ -1908,6 +1941,7 @@ mod tests { assert!(extension.value.any); } + #[cfg(crypto)] #[test] fn test_with_extended_key_usages_other() { use x509_parser::der_parser::asn1_rs::Oid; @@ -2041,7 +2075,7 @@ mod tests { } } - #[cfg(feature = "x509-parser")] + #[cfg(all(feature = "pem", feature = "x509-parser"))] mod test_key_identifier_from_ca { use super::*; diff --git a/rcgen/src/ring_like.rs b/rcgen/src/ring_like.rs index 59089fa7..1388b6dc 100644 --- a/rcgen/src/ring_like.rs +++ b/rcgen/src/ring_like.rs @@ -1,12 +1,15 @@ -#[cfg(feature = "ring")] +#[cfg(all(feature = "crypto", feature = "ring"))] pub(crate) use ring::*; -#[cfg(all(not(feature = "ring"), feature = "aws_lc_rs"))] +#[cfg(all(feature = "crypto", not(feature = "ring"), feature = "aws_lc_rs"))] pub(crate) use aws_lc_rs::*; +#[cfg(feature = "crypto")] use crate::error::ExternalError; +#[cfg(feature = "crypto")] use crate::Error; +#[cfg(feature = "crypto")] pub(crate) fn ecdsa_from_pkcs8( alg: &'static signature::EcdsaSigningAlgorithm, pkcs8: &[u8], @@ -23,6 +26,7 @@ pub(crate) fn ecdsa_from_pkcs8( } } +#[cfg(feature = "crypto")] pub(crate) fn rsa_key_pair_public_modulus_len(kp: &signature::RsaKeyPair) -> usize { #[cfg(feature = "ring")] { @@ -35,5 +39,5 @@ pub(crate) fn rsa_key_pair_public_modulus_len(kp: &signature::RsaKeyPair) -> usi } } -#[cfg(not(any(feature = "ring", feature = "aws_lc_rs")))] -compile_error!("At least one of the 'ring' or 'aws_lc_rs' features must be activated"); +#[cfg(all(feature = "crypto", not(any(feature = "ring", feature = "aws_lc_rs"))))] +compile_error!("At least one of the 'ring' or 'aws_lc_rs' features must be activated when the 'crypto' feature is enabled"); diff --git a/rcgen/src/sign_algo.rs b/rcgen/src/sign_algo.rs index c4d8e174..598b3e45 100644 --- a/rcgen/src/sign_algo.rs +++ b/rcgen/src/sign_algo.rs @@ -4,17 +4,18 @@ use yasna::models::ObjectIdentifier; use yasna::DERWriter; use yasna::Tag; -use crate::oid::*; +#[cfg(feature = "crypto")] use crate::ring_like::signature::{self, EcdsaSigningAlgorithm, EdDSAParameters}; use crate::Error; +#[cfg(feature = "crypto")] pub(crate) enum SignAlgo { EcDsa(&'static EcdsaSigningAlgorithm), EdDsa(&'static EdDSAParameters), Rsa(), } -#[derive(PartialEq, Eq)] +#[derive(PartialEq, Eq, Hash)] pub(crate) enum SignatureAlgorithmParams { /// Omit the parameters None, @@ -30,6 +31,7 @@ pub(crate) enum SignatureAlgorithmParams { /// Signature algorithm type pub struct SignatureAlgorithm { oids_sign_alg: &'static [&'static [u64]], + #[cfg(feature = "crypto")] pub(crate) sign_alg: SignAlgo, oid_components: &'static [u64], params: SignatureAlgorithmParams, @@ -73,7 +75,6 @@ impl Hash for SignatureAlgorithm { self.oids_sign_alg.hash(state); } } - impl SignatureAlgorithm { pub(crate) fn iter() -> std::slice::Iter<'static, &'static SignatureAlgorithm> { use algo::*; @@ -102,11 +103,14 @@ impl SignatureAlgorithm { /// The list of supported signature algorithms pub mod algo { + use crate::oid::*; + use super::*; /// RSA signing with PKCS#1 1.5 padding and SHA-256 hashing as per [RFC 4055](https://tools.ietf.org/html/rfc4055) pub static PKCS_RSA_SHA256: SignatureAlgorithm = SignatureAlgorithm { oids_sign_alg: &[&OID_RSA_ENCRYPTION], + #[cfg(feature = "crypto")] sign_alg: SignAlgo::Rsa(), // sha256WithRSAEncryption in RFC 4055 oid_components: &[1, 2, 840, 113549, 1, 1, 11], @@ -116,6 +120,7 @@ pub mod algo { /// RSA signing with PKCS#1 1.5 padding and SHA-256 hashing as per [RFC 4055](https://tools.ietf.org/html/rfc4055) pub static PKCS_RSA_SHA384: SignatureAlgorithm = SignatureAlgorithm { oids_sign_alg: &[&OID_RSA_ENCRYPTION], + #[cfg(feature = "crypto")] sign_alg: SignAlgo::Rsa(), // sha384WithRSAEncryption in RFC 4055 oid_components: &[1, 2, 840, 113549, 1, 1, 12], @@ -125,6 +130,7 @@ pub mod algo { /// RSA signing with PKCS#1 1.5 padding and SHA-512 hashing as per [RFC 4055](https://tools.ietf.org/html/rfc4055) pub static PKCS_RSA_SHA512: SignatureAlgorithm = SignatureAlgorithm { oids_sign_alg: &[&OID_RSA_ENCRYPTION], + #[cfg(feature = "crypto")] sign_alg: SignAlgo::Rsa(), // sha512WithRSAEncryption in RFC 4055 oid_components: &[1, 2, 840, 113549, 1, 1, 13], @@ -141,6 +147,7 @@ pub mod algo { // We could also use OID_RSA_ENCRYPTION here, but it's recommended // to use ID-RSASSA-PSS if possible. oids_sign_alg: &[&OID_RSASSA_PSS], + #[cfg(feature = "crypto")] sign_alg: SignAlgo::Rsa(), oid_components: &OID_RSASSA_PSS, //&[1, 2, 840, 113549, 1, 1, 13], // rSASSA-PSS-SHA256-Params in RFC 4055 @@ -154,6 +161,7 @@ pub mod algo { /// ECDSA signing using the P-256 curves and SHA-256 hashing as per [RFC 5758](https://tools.ietf.org/html/rfc5758#section-3.2) pub static PKCS_ECDSA_P256_SHA256: SignatureAlgorithm = SignatureAlgorithm { oids_sign_alg: &[&OID_EC_PUBLIC_KEY, &OID_EC_SECP_256_R1], + #[cfg(feature = "crypto")] sign_alg: SignAlgo::EcDsa(&signature::ECDSA_P256_SHA256_ASN1_SIGNING), // ecdsa-with-SHA256 in RFC 5758 oid_components: &[1, 2, 840, 10045, 4, 3, 2], @@ -163,6 +171,7 @@ pub mod algo { /// ECDSA signing using the P-384 curves and SHA-384 hashing as per [RFC 5758](https://tools.ietf.org/html/rfc5758#section-3.2) pub static PKCS_ECDSA_P384_SHA384: SignatureAlgorithm = SignatureAlgorithm { oids_sign_alg: &[&OID_EC_PUBLIC_KEY, &OID_EC_SECP_384_R1], + #[cfg(feature = "crypto")] sign_alg: SignAlgo::EcDsa(&signature::ECDSA_P384_SHA384_ASN1_SIGNING), // ecdsa-with-SHA384 in RFC 5758 oid_components: &[1, 2, 840, 10045, 4, 3, 3], @@ -175,6 +184,7 @@ pub mod algo { pub static PKCS_ED25519: SignatureAlgorithm = SignatureAlgorithm { // id-Ed25519 in RFC 8410 oids_sign_alg: &[&[1, 3, 101, 112]], + #[cfg(feature = "crypto")] sign_alg: SignAlgo::EdDsa(&signature::ED25519), // id-Ed25519 in RFC 8410 oid_components: &[1, 3, 101, 112], diff --git a/rcgen/tests/botan.rs b/rcgen/tests/botan.rs index 3103305e..9d1b9b0a 100644 --- a/rcgen/tests/botan.rs +++ b/rcgen/tests/botan.rs @@ -1,4 +1,4 @@ -#![cfg(feature = "x509-parser")] +#![cfg(all(feature = "crypto", feature = "x509-parser"))] use rcgen::{BasicConstraints, Certificate, CertificateParams, DnType, IsCa}; use rcgen::{ diff --git a/rcgen/tests/generic.rs b/rcgen/tests/generic.rs index 7013e3fa..5aa8ff4e 100644 --- a/rcgen/tests/generic.rs +++ b/rcgen/tests/generic.rs @@ -1,3 +1,5 @@ +#![cfg(feature = "crypto")] + mod util; #[cfg(feature = "pem")] diff --git a/rcgen/tests/util.rs b/rcgen/tests/util.rs index c2c1f10a..26cdddca 100644 --- a/rcgen/tests/util.rs +++ b/rcgen/tests/util.rs @@ -1,3 +1,5 @@ +#![cfg(feature = "crypto")] + use rcgen::{BasicConstraints, Certificate, CertificateParams, KeyPair}; use rcgen::{ CertificateRevocationList, CrlDistributionPoint, CrlIssuingDistributionPoint, CrlScope, diff --git a/rcgen/tests/webpki.rs b/rcgen/tests/webpki.rs index 25f0f4c5..9588c55c 100644 --- a/rcgen/tests/webpki.rs +++ b/rcgen/tests/webpki.rs @@ -1,3 +1,5 @@ +#![cfg(feature = "crypto")] + use pki_types::{CertificateDer, ServerName, SignatureVerificationAlgorithm, UnixTime}; use rcgen::{ BasicConstraints, Certificate, CertificateParams, DnType, Error, IsCa, KeyPair, RemoteKeyPair,