From 630514d844a3f0b52e18a5a34566eb54322bd9a5 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Fri, 25 Nov 2022 15:01:36 -0700 Subject: [PATCH 1/5] [WIP] spki: make `AlgorithmIdentifier` generic around `Params` NOTE: breaking change. Previously `AlgorithmIdentifier::parameters` were always `AnyRef`. This commit changes them to a generic parameter `Params`. An alias `AlgorithmIdentifierRef` provides a type identical to the original with `AnyRef` as its `parameters`, which is used in all of the other crates in this repo. --- pkcs1/src/lib.rs | 2 +- pkcs1/src/params.rs | 22 +++--- pkcs5/src/lib.rs | 12 ++-- pkcs5/src/pbes1.rs | 8 +-- pkcs5/src/pbes2.rs | 20 +++--- pkcs5/src/pbes2/kdf.rs | 22 +++--- pkcs7/src/enveloped_data_content.rs | 4 +- pkcs7/tests/content_tests.rs | 4 +- pkcs8/src/error.rs | 2 +- pkcs8/src/lib.rs | 2 +- pkcs8/src/private_key_info.rs | 10 +-- sec1/src/traits.rs | 2 +- spki/src/algorithm.rs | 101 ++++++++++++++++------------ spki/src/lib.rs | 6 +- spki/src/spki.rs | 7 +- x509-cert/src/certificate.rs | 6 +- x509-cert/src/crl.rs | 6 +- x509-cert/src/request.rs | 4 +- x509-cert/tests/certificate.rs | 4 +- x509-ocsp/src/lib.rs | 12 ++-- 20 files changed, 138 insertions(+), 118 deletions(-) diff --git a/pkcs1/src/lib.rs b/pkcs1/src/lib.rs index 84dc6ab44..cf18ef593 100644 --- a/pkcs1/src/lib.rs +++ b/pkcs1/src/lib.rs @@ -52,7 +52,7 @@ pub const ALGORITHM_OID: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.2.84 /// `AlgorithmIdentifier` for RSA. #[cfg(feature = "pkcs8")] #[cfg_attr(docsrs, doc(cfg(feature = "pkcs8")))] -pub const ALGORITHM_ID: pkcs8::AlgorithmIdentifier<'static> = pkcs8::AlgorithmIdentifier { +pub const ALGORITHM_ID: pkcs8::AlgorithmIdentifierRef<'static> = pkcs8::AlgorithmIdentifierRef { oid: ALGORITHM_OID, parameters: Some(der::asn1::AnyRef::NULL), }; diff --git a/pkcs1/src/params.rs b/pkcs1/src/params.rs index e803473e0..b2080893f 100644 --- a/pkcs1/src/params.rs +++ b/pkcs1/src/params.rs @@ -6,7 +6,7 @@ use der::{ asn1::ContextSpecificRef, Decode, DecodeValue, Encode, EncodeValue, FixedTag, Reader, Sequence, Tag, TagMode, TagNumber, Writer, }; -use spki::AlgorithmIdentifier; +use spki::AlgorithmIdentifierRef; const OID_SHA_1: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.3.14.3.2.26"); const OID_MGF_1: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.8"); @@ -15,7 +15,7 @@ const OID_PSPECIFIED: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.2.840.1 // TODO(tarcieri): make `AlgorithmIdentifier` generic around params; use `OID_SHA_1` const SEQ_OID_SHA_1_DER: &[u8] = &[0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a]; -const SHA_1_AI: AlgorithmIdentifier<'_> = AlgorithmIdentifier { +const SHA_1_AI: AlgorithmIdentifierRef<'_> = AlgorithmIdentifierRef { oid: OID_SHA_1, parameters: None, }; @@ -81,10 +81,10 @@ impl FixedTag for TrailerField { #[derive(Clone, Debug, Eq, PartialEq)] pub struct RsaPssParams<'a> { /// Hash Algorithm - pub hash: AlgorithmIdentifier<'a>, + pub hash: AlgorithmIdentifierRef<'a>, /// Mask Generation Function (MGF) - pub mask_gen: AlgorithmIdentifier<'a>, + pub mask_gen: AlgorithmIdentifierRef<'a>, /// Salt length pub salt_len: u8, @@ -180,8 +180,8 @@ impl<'a> TryFrom<&'a [u8]> for RsaPssParams<'a> { } /// Default Mask Generation Function (MGF): SHA-1. -fn default_mgf1_sha1<'a>() -> AlgorithmIdentifier<'a> { - AlgorithmIdentifier { +fn default_mgf1_sha1<'a>() -> AlgorithmIdentifierRef<'a> { + AlgorithmIdentifierRef { oid: OID_MGF_1, parameters: Some( AnyRef::new(Tag::Sequence, SEQ_OID_SHA_1_DER) @@ -208,13 +208,13 @@ fn default_mgf1_sha1<'a>() -> AlgorithmIdentifier<'a> { #[derive(Clone, Debug, Eq, PartialEq)] pub struct RsaOaepParams<'a> { /// Hash Algorithm - pub hash: AlgorithmIdentifier<'a>, + pub hash: AlgorithmIdentifierRef<'a>, /// Mask Generation Function (MGF) - pub mask_gen: AlgorithmIdentifier<'a>, + pub mask_gen: AlgorithmIdentifierRef<'a>, /// The source (and possibly the value) of the label L - pub p_source: AlgorithmIdentifier<'a>, + pub p_source: AlgorithmIdentifierRef<'a>, } impl<'a> Default for RsaOaepParams<'a> { @@ -291,8 +291,8 @@ impl<'a> TryFrom<&'a [u8]> for RsaOaepParams<'a> { } /// Default Source Algorithm, empty string -fn default_pempty_string<'a>() -> AlgorithmIdentifier<'a> { - AlgorithmIdentifier { +fn default_pempty_string<'a>() -> AlgorithmIdentifierRef<'a> { + AlgorithmIdentifierRef { oid: OID_PSPECIFIED, parameters: Some( AnyRef::new(Tag::OctetString, &[]).expect("error creating default OAEP params"), diff --git a/pkcs5/src/lib.rs b/pkcs5/src/lib.rs index 7019ee439..f658307c3 100644 --- a/pkcs5/src/lib.rs +++ b/pkcs5/src/lib.rs @@ -12,7 +12,7 @@ //! //! The main API for this crate is the [`EncryptionScheme`] enum, which impls //! the [`Decode`] and [`Encode`] traits from the [`der`] crate, and can be -//! used for decoding/encoding PKCS#5 [`AlgorithmIdentifier`] fields. +//! used for decoding/encoding PKCS#5 `AlgorithmIdentifier` fields. //! //! [RFC 8018]: https://tools.ietf.org/html/rfc8018 @@ -26,7 +26,7 @@ pub mod pbes2; pub use crate::error::{Error, Result}; pub use der::{self, asn1::ObjectIdentifier}; -pub use spki::AlgorithmIdentifier; +pub use spki::AlgorithmIdentifierRef; use der::{Decode, DecodeValue, Encode, Header, Reader, Sequence, Tag}; @@ -136,7 +136,7 @@ impl<'a> EncryptionScheme<'a> { impl<'a> DecodeValue<'a> for EncryptionScheme<'a> { fn decode_value>(decoder: &mut R, header: Header) -> der::Result { - AlgorithmIdentifier::decode_value(decoder, header)?.try_into() + AlgorithmIdentifierRef::decode_value(decoder, header)?.try_into() } } @@ -164,10 +164,10 @@ impl<'a> From> for EncryptionScheme<'a> { } } -impl<'a> TryFrom> for EncryptionScheme<'a> { +impl<'a> TryFrom> for EncryptionScheme<'a> { type Error = der::Error; - fn try_from(alg: AlgorithmIdentifier<'a>) -> der::Result> { + fn try_from(alg: AlgorithmIdentifierRef<'a>) -> der::Result> { if alg.oid == pbes2::PBES2_OID { match alg.parameters { Some(params) => pbes2::Parameters::try_from(params).map(Into::into), @@ -183,6 +183,6 @@ impl<'a> TryFrom<&'a [u8]> for EncryptionScheme<'a> { type Error = der::Error; fn try_from(bytes: &'a [u8]) -> der::Result> { - AlgorithmIdentifier::from_der(bytes)?.try_into() + AlgorithmIdentifierRef::from_der(bytes)?.try_into() } } diff --git a/pkcs5/src/pbes1.rs b/pkcs5/src/pbes1.rs index 735070562..7a1165f8e 100644 --- a/pkcs5/src/pbes1.rs +++ b/pkcs5/src/pbes1.rs @@ -2,7 +2,7 @@ //! //! [RFC 8018 Section 6.1]: https://tools.ietf.org/html/rfc8018#section-6.1 -use crate::AlgorithmIdentifier; +use crate::AlgorithmIdentifierRef; use der::{ asn1::{AnyRef, ObjectIdentifier, OctetStringRef}, Decode, Encode, ErrorKind, Length, Reader, Sequence, Tag, Writer, @@ -68,7 +68,7 @@ impl Algorithm { impl<'a> Decode<'a> for Algorithm { fn decode>(decoder: &mut R) -> der::Result { - AlgorithmIdentifier::decode(decoder)?.try_into() + AlgorithmIdentifierRef::decode(decoder)?.try_into() } } @@ -81,10 +81,10 @@ impl Sequence<'_> for Algorithm { } } -impl<'a> TryFrom> for Algorithm { +impl<'a> TryFrom> for Algorithm { type Error = der::Error; - fn try_from(alg: AlgorithmIdentifier<'a>) -> der::Result { + fn try_from(alg: AlgorithmIdentifierRef<'a>) -> der::Result { // Ensure that we have a supported PBES1 algorithm identifier let encryption = EncryptionScheme::try_from(alg.oid) .map_err(|_| der::Tag::ObjectIdentifier.value_error())?; diff --git a/pkcs5/src/pbes2.rs b/pkcs5/src/pbes2.rs index 8d63f114b..288dee407 100644 --- a/pkcs5/src/pbes2.rs +++ b/pkcs5/src/pbes2.rs @@ -12,7 +12,7 @@ pub use self::kdf::{ PBKDF2_OID, SCRYPT_OID, }; -use crate::{AlgorithmIdentifier, Error, Result}; +use crate::{AlgorithmIdentifierRef, Error, Result}; use der::{ asn1::{AnyRef, ObjectIdentifier, OctetStringRef}, Decode, Encode, ErrorKind, Length, Reader, Sequence, Tag, Writer, @@ -220,8 +220,8 @@ impl<'a> TryFrom> for Parameters<'a> { fn try_from(any: AnyRef<'a>) -> der::Result { any.sequence(|params| { - let kdf = AlgorithmIdentifier::decode(params)?; - let encryption = AlgorithmIdentifier::decode(params)?; + let kdf = AlgorithmIdentifierRef::decode(params)?; + let encryption = AlgorithmIdentifierRef::decode(params)?; Ok(Self { kdf: kdf.try_into()?, @@ -305,14 +305,14 @@ impl<'a> EncryptionScheme<'a> { impl<'a> Decode<'a> for EncryptionScheme<'a> { fn decode>(reader: &mut R) -> der::Result { - AlgorithmIdentifier::decode(reader).and_then(TryInto::try_into) + AlgorithmIdentifierRef::decode(reader).and_then(TryInto::try_into) } } -impl<'a> TryFrom> for EncryptionScheme<'a> { +impl<'a> TryFrom> for EncryptionScheme<'a> { type Error = der::Error; - fn try_from(alg: AlgorithmIdentifier<'a>) -> der::Result { + fn try_from(alg: AlgorithmIdentifierRef<'a>) -> der::Result { // TODO(tarcieri): support for non-AES algorithms? let iv = match alg.parameters { Some(params) => params.octet_string()?.as_bytes(), @@ -352,7 +352,7 @@ impl<'a> TryFrom> for EncryptionScheme<'a> { } } -impl<'a> TryFrom> for AlgorithmIdentifier<'a> { +impl<'a> TryFrom> for AlgorithmIdentifierRef<'a> { type Error = der::Error; fn try_from(scheme: EncryptionScheme<'a>) -> der::Result { @@ -366,7 +366,7 @@ impl<'a> TryFrom> for AlgorithmIdentifier<'a> { EncryptionScheme::DesEde3Cbc { iv } => iv, })?; - Ok(AlgorithmIdentifier { + Ok(AlgorithmIdentifierRef { oid: scheme.oid(), parameters: Some(parameters.into()), }) @@ -375,10 +375,10 @@ impl<'a> TryFrom> for AlgorithmIdentifier<'a> { impl<'a> Encode for EncryptionScheme<'a> { fn encoded_len(&self) -> der::Result { - AlgorithmIdentifier::try_from(*self)?.encoded_len() + AlgorithmIdentifierRef::try_from(*self)?.encoded_len() } fn encode(&self, writer: &mut dyn Writer) -> der::Result<()> { - AlgorithmIdentifier::try_from(*self)?.encode(writer) + AlgorithmIdentifierRef::try_from(*self)?.encode(writer) } } diff --git a/pkcs5/src/pbes2/kdf.rs b/pkcs5/src/pbes2/kdf.rs index 3fc107488..eb389ff71 100644 --- a/pkcs5/src/pbes2/kdf.rs +++ b/pkcs5/src/pbes2/kdf.rs @@ -1,6 +1,6 @@ //! Key derivation functions. -use crate::{AlgorithmIdentifier, Error, Result}; +use crate::{AlgorithmIdentifierRef, Error, Result}; use der::{ asn1::{AnyRef, ObjectIdentifier, OctetStringRef}, Decode, Encode, ErrorKind, Length, Reader, Sequence, Tag, Tagged, Writer, @@ -100,7 +100,7 @@ impl<'a> Kdf<'a> { impl<'a> Decode<'a> for Kdf<'a> { fn decode>(reader: &mut R) -> der::Result { - AlgorithmIdentifier::decode(reader)?.try_into() + AlgorithmIdentifierRef::decode(reader)?.try_into() } } @@ -128,10 +128,10 @@ impl<'a> From> for Kdf<'a> { } } -impl<'a> TryFrom> for Kdf<'a> { +impl<'a> TryFrom> for Kdf<'a> { type Error = der::Error; - fn try_from(alg: AlgorithmIdentifier<'a>) -> der::Result { + fn try_from(alg: AlgorithmIdentifierRef<'a>) -> der::Result { if let Some(params) = alg.parameters { match alg.oid { PBKDF2_OID => params.try_into().map(Self::Pbkdf2), @@ -242,7 +242,7 @@ impl<'a> TryFrom> for Pbkdf2Params<'a> { salt: OctetStringRef::decode(reader)?.as_bytes(), iteration_count: reader.decode()?, key_length: reader.decode()?, - prf: Option::>::decode(reader)? + prf: Option::>::decode(reader)? .map(TryInto::try_into) .transpose()? .unwrap_or_default(), @@ -298,10 +298,10 @@ impl Default for Pbkdf2Prf { } } -impl<'a> TryFrom> for Pbkdf2Prf { +impl<'a> TryFrom> for Pbkdf2Prf { type Error = der::Error; - fn try_from(alg: AlgorithmIdentifier<'a>) -> der::Result { + fn try_from(alg: AlgorithmIdentifierRef<'a>) -> der::Result { if let Some(params) = alg.parameters { // TODO(tarcieri): support non-NULL parameters? if !params.is_null() { @@ -323,12 +323,12 @@ impl<'a> TryFrom> for Pbkdf2Prf { } } -impl<'a> From for AlgorithmIdentifier<'a> { +impl<'a> From for AlgorithmIdentifierRef<'a> { fn from(prf: Pbkdf2Prf) -> Self { // TODO(tarcieri): support non-NULL parameters? let parameters = der::asn1::Null; - AlgorithmIdentifier { + AlgorithmIdentifierRef { oid: prf.oid(), parameters: Some(parameters.into()), } @@ -337,11 +337,11 @@ impl<'a> From for AlgorithmIdentifier<'a> { impl Encode for Pbkdf2Prf { fn encoded_len(&self) -> der::Result { - AlgorithmIdentifier::try_from(*self)?.encoded_len() + AlgorithmIdentifierRef::try_from(*self)?.encoded_len() } fn encode(&self, writer: &mut dyn Writer) -> der::Result<()> { - AlgorithmIdentifier::try_from(*self)?.encode(writer) + AlgorithmIdentifierRef::try_from(*self)?.encode(writer) } } diff --git a/pkcs7/src/enveloped_data_content.rs b/pkcs7/src/enveloped_data_content.rs index 2efe404d6..02e4f053b 100644 --- a/pkcs7/src/enveloped_data_content.rs +++ b/pkcs7/src/enveloped_data_content.rs @@ -6,9 +6,9 @@ use der::{ asn1::{ContextSpecific, OctetStringRef}, DecodeValue, Encode, Header, Reader, Sequence, TagMode, TagNumber, }; -use spki::AlgorithmIdentifier; +use spki::AlgorithmIdentifierRef; -type ContentEncryptionAlgorithmIdentifier<'a> = AlgorithmIdentifier<'a>; +type ContentEncryptionAlgorithmIdentifier<'a> = AlgorithmIdentifierRef<'a>; const ENCRYPTED_CONTENT_TAG: TagNumber = TagNumber::new(0); diff --git a/pkcs7/tests/content_tests.rs b/pkcs7/tests/content_tests.rs index b542e8139..be8dca179 100644 --- a/pkcs7/tests/content_tests.rs +++ b/pkcs7/tests/content_tests.rs @@ -9,7 +9,7 @@ use pkcs7::{ encrypted_data_content::EncryptedDataContent, enveloped_data_content::EncryptedContentInfo, ContentInfo, ContentType, }; -use spki::AlgorithmIdentifier; +use spki::AlgorithmIdentifierRef; use std::fs; fn encode_content_info<'a>(content_info: &ContentInfo<'a>, buf: &'a mut [u8]) -> &'a [u8] { @@ -52,7 +52,7 @@ fn decode_encrypted_key_example() { EncryptedContentInfo { content_type: ContentType::Data, content_encryption_algorithm: - AlgorithmIdentifier { + AlgorithmIdentifierRef { oid, parameters: Some(any), }, diff --git a/pkcs8/src/error.rs b/pkcs8/src/error.rs index bc4c2eafe..70c60aedb 100644 --- a/pkcs8/src/error.rs +++ b/pkcs8/src/error.rs @@ -26,7 +26,7 @@ pub enum Error { /// or [`SubjectPublicKeyInfo::subject_public_key`][`crate::SubjectPublicKeyInfo::subject_public_key`]. KeyMalformed, - /// [`AlgorithmIdentifier::parameters`][`crate::AlgorithmIdentifier::parameters`] + /// [`AlgorithmIdentifier::parameters`][`crate::AlgorithmIdentifierRef::parameters`] /// is malformed or otherwise encoded in an unexpected manner. ParametersMalformed, diff --git a/pkcs8/src/lib.rs b/pkcs8/src/lib.rs index a7ea0b725..05fc94d7c 100644 --- a/pkcs8/src/lib.rs +++ b/pkcs8/src/lib.rs @@ -83,7 +83,7 @@ pub use crate::{ version::Version, }; pub use der::{self, asn1::ObjectIdentifier, oid::AssociatedOid}; -pub use spki::{self, AlgorithmIdentifier, DecodePublicKey, SubjectPublicKeyInfo}; +pub use spki::{self, AlgorithmIdentifierRef, DecodePublicKey, SubjectPublicKeyInfo}; #[cfg(feature = "alloc")] #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] diff --git a/pkcs8/src/private_key_info.rs b/pkcs8/src/private_key_info.rs index 52f0878d7..cf23cf228 100644 --- a/pkcs8/src/private_key_info.rs +++ b/pkcs8/src/private_key_info.rs @@ -1,6 +1,6 @@ //! PKCS#8 `PrivateKeyInfo`. -use crate::{AlgorithmIdentifier, Error, Result, Version}; +use crate::{AlgorithmIdentifierRef, Error, Result, Version}; use core::fmt; use der::{ asn1::{AnyRef, BitStringRef, ContextSpecific, OctetStringRef}, @@ -29,7 +29,7 @@ const PUBLIC_KEY_TAG: TagNumber = TagNumber::N1; /// PKCS#8 `PrivateKeyInfo`. /// -/// ASN.1 structure containing an [`AlgorithmIdentifier`], private key +/// ASN.1 structure containing an `AlgorithmIdentifier`, private key /// data in an algorithm specific format, and optional attributes /// (ignored by this implementation). /// @@ -90,8 +90,8 @@ const PUBLIC_KEY_TAG: TagNumber = TagNumber::N1; /// [RFC 5958 Section 2]: https://datatracker.ietf.org/doc/html/rfc5958#section-2 #[derive(Clone)] pub struct PrivateKeyInfo<'a> { - /// X.509 [`AlgorithmIdentifier`] for the private key type. - pub algorithm: AlgorithmIdentifier<'a>, + /// X.509 `AlgorithmIdentifier` for the private key type. + pub algorithm: AlgorithmIdentifierRef<'a>, /// Private key data. pub private_key: &'a [u8], @@ -105,7 +105,7 @@ impl<'a> PrivateKeyInfo<'a> { /// /// This is a helper method which initializes `attributes` and `public_key` /// to `None`, helpful if you aren't using those. - pub fn new(algorithm: AlgorithmIdentifier<'a>, private_key: &'a [u8]) -> Self { + pub fn new(algorithm: AlgorithmIdentifierRef<'a>, private_key: &'a [u8]) -> Self { Self { algorithm, private_key, diff --git a/sec1/src/traits.rs b/sec1/src/traits.rs index cf0d9711e..5bff2f03e 100644 --- a/sec1/src/traits.rs +++ b/sec1/src/traits.rs @@ -103,7 +103,7 @@ impl DecodeEcPrivateKey for T { .parameters .and_then(|params| params.named_curve()); - let algorithm = pkcs8::AlgorithmIdentifier { + let algorithm = pkcs8::AlgorithmIdentifierRef { oid: ALGORITHM_OID, parameters: params_oid.as_ref().map(Into::into), }; diff --git a/spki/src/algorithm.rs b/spki/src/algorithm.rs index 2a8b6c7f9..6f76d6d35 100644 --- a/spki/src/algorithm.rs +++ b/spki/src/algorithm.rs @@ -2,8 +2,10 @@ use crate::{Error, Result}; use core::cmp::Ordering; -use der::asn1::{AnyRef, ObjectIdentifier}; -use der::{Decode, DecodeValue, DerOrd, Encode, Header, Reader, Sequence, ValueOrd}; +use der::{ + asn1::{AnyRef, Choice, ObjectIdentifier}, + Decode, DecodeValue, DerOrd, Encode, Header, Reader, Sequence, ValueOrd, +}; /// X.509 `AlgorithmIdentifier` as defined in [RFC 5280 Section 4.1.1.2]. /// @@ -15,16 +17,68 @@ use der::{Decode, DecodeValue, DerOrd, Encode, Header, Reader, Sequence, ValueOr /// /// [RFC 5280 Section 4.1.1.2]: https://tools.ietf.org/html/rfc5280#section-4.1.1.2 #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] -pub struct AlgorithmIdentifier<'a> { +pub struct AlgorithmIdentifier { /// Algorithm OID, i.e. the `algorithm` field in the `AlgorithmIdentifier` /// ASN.1 schema. pub oid: ObjectIdentifier, /// Algorithm `parameters`. - pub parameters: Option>, + pub parameters: Option, } -impl<'a> AlgorithmIdentifier<'a> { +impl<'a, Params> DecodeValue<'a> for AlgorithmIdentifier +where + Params: Choice<'a>, +{ + fn decode_value>(reader: &mut R, header: Header) -> der::Result { + reader.read_nested(header.length, |reader| { + Ok(Self { + oid: reader.decode()?, + parameters: reader.decode()?, + }) + }) + } +} + +impl<'a, Params> Sequence<'a> for AlgorithmIdentifier +where + Params: Choice<'a> + Encode, +{ + fn fields(&self, f: F) -> der::Result + where + F: FnOnce(&[&dyn Encode]) -> der::Result, + { + f(&[&self.oid, &self.parameters]) + } +} + +impl<'a, Params> TryFrom<&'a [u8]> for AlgorithmIdentifier +where + Params: Choice<'a> + Encode, +{ + type Error = Error; + + fn try_from(bytes: &'a [u8]) -> Result { + Ok(Self::from_der(bytes)?) + } +} + +impl ValueOrd for AlgorithmIdentifier +where + Params: DerOrd, +{ + fn value_cmp(&self, other: &Self) -> der::Result { + match self.oid.der_cmp(&other.oid)? { + Ordering::Equal => self.parameters.der_cmp(&other.parameters), + other => Ok(other), + } + } +} + +/// `AlgorithmIdentifier` reference which has `AnyRef` parameters. +pub type AlgorithmIdentifierRef<'a> = AlgorithmIdentifier>; + +impl<'a> AlgorithmIdentifierRef<'a> { /// Assert the `algorithm` OID is an expected value. pub fn assert_algorithm_oid(&self, expected_oid: ObjectIdentifier) -> Result { if self.oid == expected_oid { @@ -93,40 +147,3 @@ impl<'a> AlgorithmIdentifier<'a> { )) } } - -impl<'a> DecodeValue<'a> for AlgorithmIdentifier<'a> { - fn decode_value>(reader: &mut R, header: Header) -> der::Result { - reader.read_nested(header.length, |reader| { - Ok(Self { - oid: reader.decode()?, - parameters: reader.decode()?, - }) - }) - } -} - -impl<'a> Sequence<'a> for AlgorithmIdentifier<'a> { - fn fields(&self, f: F) -> der::Result - where - F: FnOnce(&[&dyn Encode]) -> der::Result, - { - f(&[&self.oid, &self.parameters]) - } -} - -impl<'a> TryFrom<&'a [u8]> for AlgorithmIdentifier<'a> { - type Error = Error; - - fn try_from(bytes: &'a [u8]) -> Result { - Ok(Self::from_der(bytes)?) - } -} - -impl ValueOrd for AlgorithmIdentifier<'_> { - fn value_cmp(&self, other: &Self) -> der::Result { - match self.oid.der_cmp(&other.oid)? { - Ordering::Equal => self.parameters.der_cmp(&other.parameters), - other => Ok(other), - } - } -} diff --git a/spki/src/lib.rs b/spki/src/lib.rs index cd11da857..ada8ca3d2 100644 --- a/spki/src/lib.rs +++ b/spki/src/lib.rs @@ -15,14 +15,14 @@ //! Borrow the [`ObjectIdentifier`] first then use [`der::AnyRef::from`] or `.into()`: //! //! ``` -//! use spki::{AlgorithmIdentifier, ObjectIdentifier, der::AnyRef}; +//! use spki::{AlgorithmIdentifier, ObjectIdentifier}; //! //! let alg_oid = "1.2.840.10045.2.1".parse::().unwrap(); //! let params_oid = "1.2.840.10045.3.1.7".parse::().unwrap(); //! //! let alg_id = AlgorithmIdentifier { //! oid: alg_oid, -//! parameters: Some(AnyRef::from(¶ms_oid)) +//! parameters: Some(params_oid) //! }; //! ``` @@ -41,7 +41,7 @@ mod traits; mod fingerprint; pub use crate::{ - algorithm::AlgorithmIdentifier, + algorithm::{AlgorithmIdentifier, AlgorithmIdentifierRef}, error::{Error, Result}, spki::SubjectPublicKeyInfo, traits::DecodePublicKey, diff --git a/spki/src/spki.rs b/spki/src/spki.rs index 9058e49c7..8dbcda699 100644 --- a/spki/src/spki.rs +++ b/spki/src/spki.rs @@ -1,6 +1,6 @@ //! X.509 `SubjectPublicKeyInfo` -use crate::{AlgorithmIdentifier, Error, Result}; +use crate::{AlgorithmIdentifierRef, Error, Result}; use core::cmp::Ordering; use der::{ asn1::BitStringRef, Decode, DecodeValue, DerOrd, Encode, Header, Reader, Sequence, ValueOrd, @@ -21,6 +21,9 @@ use { #[cfg(feature = "pem")] use der::pem::PemLabel; +#[cfg(doc)] +use crate::AlgorithmIdentifier; + /// X.509 `SubjectPublicKeyInfo` (SPKI) as defined in [RFC 5280 § 4.1.2.7]. /// /// ASN.1 structure containing an [`AlgorithmIdentifier`] and public key @@ -36,7 +39,7 @@ use der::pem::PemLabel; #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub struct SubjectPublicKeyInfo<'a> { /// X.509 [`AlgorithmIdentifier`] for the public key type - pub algorithm: AlgorithmIdentifier<'a>, + pub algorithm: AlgorithmIdentifierRef<'a>, /// Public key data pub subject_public_key: &'a [u8], diff --git a/x509-cert/src/certificate.rs b/x509-cert/src/certificate.rs index 3083d7bf9..99d1385cd 100644 --- a/x509-cert/src/certificate.rs +++ b/x509-cert/src/certificate.rs @@ -7,7 +7,7 @@ use alloc::vec::Vec; use const_oid::AssociatedOid; use der::asn1::{BitStringRef, UIntRef}; use der::{Decode, Enumerated, Error, ErrorKind, Sequence}; -use spki::{AlgorithmIdentifier, SubjectPublicKeyInfo}; +use spki::{AlgorithmIdentifierRef, SubjectPublicKeyInfo}; #[cfg(feature = "pem")] use der::pem::PemLabel; @@ -77,7 +77,7 @@ pub struct TbsCertificate<'a> { pub version: Version, pub serial_number: UIntRef<'a>, - pub signature: AlgorithmIdentifier<'a>, + pub signature: AlgorithmIdentifierRef<'a>, pub issuer: Name<'a>, pub validity: Validity, pub subject: Name<'a>, @@ -142,7 +142,7 @@ impl<'a> TbsCertificate<'a> { #[allow(missing_docs)] pub struct Certificate<'a> { pub tbs_certificate: TbsCertificate<'a>, - pub signature_algorithm: AlgorithmIdentifier<'a>, + pub signature_algorithm: AlgorithmIdentifierRef<'a>, pub signature: BitStringRef<'a>, } diff --git a/x509-cert/src/crl.rs b/x509-cert/src/crl.rs index 3e630435b..8b1bfa564 100644 --- a/x509-cert/src/crl.rs +++ b/x509-cert/src/crl.rs @@ -9,7 +9,7 @@ use alloc::vec::Vec; use der::asn1::{BitStringRef, UIntRef}; use der::Sequence; -use spki::AlgorithmIdentifier; +use spki::AlgorithmIdentifierRef; /// `CertificateList` as defined in [RFC 5280 Section 5.1]. /// @@ -26,7 +26,7 @@ use spki::AlgorithmIdentifier; #[allow(missing_docs)] pub struct CertificateList<'a> { pub tbs_cert_list: TbsCertList<'a>, - pub signature_algorithm: AlgorithmIdentifier<'a>, + pub signature_algorithm: AlgorithmIdentifierRef<'a>, pub signature: BitStringRef<'a>, } @@ -75,7 +75,7 @@ pub struct RevokedCert<'a> { #[allow(missing_docs)] pub struct TbsCertList<'a> { pub version: Version, - pub signature: AlgorithmIdentifier<'a>, + pub signature: AlgorithmIdentifierRef<'a>, pub issuer: Name<'a>, pub this_update: Time, pub next_update: Option