From 0a5071d34b8298ba8664764337c90aa4c8d6682c Mon Sep 17 00:00:00 2001 From: Arthur Gautier Date: Wed, 22 May 2024 20:23:59 -0700 Subject: [PATCH 1/7] der: introduce an `AnyLike` trait to mark parameters --- der/src/asn1.rs | 2 +- der/src/asn1/any.rs | 22 ++++++++++++++-------- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/der/src/asn1.rs b/der/src/asn1.rs index b04b1b58f..f04d1803f 100644 --- a/der/src/asn1.rs +++ b/der/src/asn1.rs @@ -31,7 +31,7 @@ mod utf8_string; mod videotex_string; pub use self::{ - any::AnyRef, + any::{AnyLike, AnyRef}, bit_string::{BitStringIter, BitStringRef}, choice::Choice, context_specific::{ContextSpecific, ContextSpecificRef}, diff --git a/der/src/asn1/any.rs b/der/src/asn1/any.rs index 1ed9286c0..93a2e4409 100644 --- a/der/src/asn1/any.rs +++ b/der/src/asn1/any.rs @@ -11,6 +11,12 @@ use core::cmp::Ordering; #[cfg(feature = "alloc")] use crate::SliceWriter; +/// Trait representing value that will be serialized as Any +pub trait AnyLike { + /// Is this value an ASN.1 `NULL` value? + fn is_null(&self) -> bool; +} + /// ASN.1 `ANY`: represents any explicitly tagged ASN.1 value. /// /// This is a zero-copy reference type which borrows from the input data. @@ -74,11 +80,6 @@ impl<'a> AnyRef<'a> { Ok(decoder.finish(result)?) } - /// Is this value an ASN.1 `NULL` value? - pub fn is_null(self) -> bool { - self == Self::NULL - } - /// Attempt to decode this value an ASN.1 `SEQUENCE`, creating a new /// nested reader and calling the provided argument with it. pub fn sequence(self, f: F) -> Result @@ -93,6 +94,12 @@ impl<'a> AnyRef<'a> { } } +impl<'a> AnyLike for AnyRef<'a> { + fn is_null(&self) -> bool { + *self == Self::NULL + } +} + impl<'a> Choice<'a> for AnyRef<'a> { fn can_decode(_: Tag) -> bool { true @@ -316,9 +323,8 @@ mod allocating { } } - impl Any { - /// Is this value an ASN.1 `NULL` value? - pub fn is_null(&self) -> bool { + impl AnyLike for Any { + fn is_null(&self) -> bool { self.owned_to_ref() == AnyRef::NULL } } From 52ce7fdd557d7cd7c2a742bc2faa26b74d5060ed Mon Sep 17 00:00:00 2001 From: Arthur Gautier Date: Wed, 22 May 2024 20:24:51 -0700 Subject: [PATCH 2/7] spki: ensure params are encoded with `Any` --- spki/src/algorithm.rs | 16 ++++++++-------- spki/src/lib.rs | 3 ++- spki/src/spki.rs | 25 ++++++++++++++----------- spki/src/traits.rs | 6 +++--- spki/tests/spki.rs | 2 +- 5 files changed, 28 insertions(+), 24 deletions(-) diff --git a/spki/src/algorithm.rs b/spki/src/algorithm.rs index baa89cc4f..f932bc49d 100644 --- a/spki/src/algorithm.rs +++ b/spki/src/algorithm.rs @@ -3,7 +3,7 @@ use crate::{Error, Result}; use core::cmp::Ordering; use der::{ - asn1::{AnyRef, Choice, ObjectIdentifier}, + asn1::{AnyLike, AnyRef, Choice, ObjectIdentifier}, Decode, DecodeValue, DerOrd, Encode, EncodeValue, Header, Length, Reader, Sequence, ValueOrd, Writer, }; @@ -22,7 +22,7 @@ use der::asn1::Any; /// [RFC 5280 Section 4.1.1.2]: https://tools.ietf.org/html/rfc5280#section-4.1.1.2 #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] -pub struct AlgorithmIdentifier { +pub struct AlgorithmIdentifier { /// Algorithm OID, i.e. the `algorithm` field in the `AlgorithmIdentifier` /// ASN.1 schema. pub oid: ObjectIdentifier, @@ -31,7 +31,7 @@ pub struct AlgorithmIdentifier { pub parameters: Option, } -impl<'a, Params> DecodeValue<'a> for AlgorithmIdentifier +impl<'a, Params: AnyLike> DecodeValue<'a> for AlgorithmIdentifier where Params: Choice<'a, Error = der::Error>, { @@ -47,7 +47,7 @@ where } } -impl EncodeValue for AlgorithmIdentifier +impl EncodeValue for AlgorithmIdentifier where Params: Encode, { @@ -62,12 +62,12 @@ where } } -impl<'a, Params> Sequence<'a> for AlgorithmIdentifier where +impl<'a, Params: AnyLike> Sequence<'a> for AlgorithmIdentifier where Params: Choice<'a, Error = der::Error> + Encode { } -impl<'a, Params> TryFrom<&'a [u8]> for AlgorithmIdentifier +impl<'a, Params: AnyLike> TryFrom<&'a [u8]> for AlgorithmIdentifier where Params: Choice<'a, Error = der::Error> + Encode, { @@ -78,7 +78,7 @@ where } } -impl ValueOrd for AlgorithmIdentifier +impl ValueOrd for AlgorithmIdentifier where Params: DerOrd, { @@ -100,7 +100,7 @@ pub type AlgorithmIdentifierWithOid = AlgorithmIdentifier; #[cfg(feature = "alloc")] pub type AlgorithmIdentifierOwned = AlgorithmIdentifier; -impl AlgorithmIdentifier { +impl AlgorithmIdentifier { /// Assert the `algorithm` OID is an expected value. pub fn assert_algorithm_oid(&self, expected_oid: ObjectIdentifier) -> Result { if self.oid == expected_oid { diff --git a/spki/src/lib.rs b/spki/src/lib.rs index 6c0caa72a..76d2554bc 100644 --- a/spki/src/lib.rs +++ b/spki/src/lib.rs @@ -21,6 +21,7 @@ //! Borrow the [`ObjectIdentifier`] first then use [`der::AnyRef::from`] or `.into()`: //! //! ``` +//! use der::asn1::AnyRef; //! use spki::{AlgorithmIdentifier, ObjectIdentifier}; //! //! let alg_oid = "1.2.840.10045.2.1".parse::().unwrap(); @@ -28,7 +29,7 @@ //! //! let alg_id = AlgorithmIdentifier { //! oid: alg_oid, -//! parameters: Some(params_oid) +//! parameters: Some(AnyRef::from(¶ms_oid)) //! }; //! ``` diff --git a/spki/src/spki.rs b/spki/src/spki.rs index b2972a62e..1cdfb6e77 100644 --- a/spki/src/spki.rs +++ b/spki/src/spki.rs @@ -3,7 +3,7 @@ use crate::{AlgorithmIdentifier, Error, Result}; use core::cmp::Ordering; use der::{ - asn1::{AnyRef, BitStringRef}, + asn1::{AnyLike, AnyRef, BitStringRef}, Choice, Decode, DecodeValue, DerOrd, Encode, EncodeValue, FixedTag, Header, Length, Reader, Sequence, ValueOrd, Writer, }; @@ -41,7 +41,7 @@ pub type SubjectPublicKeyInfoOwned = SubjectPublicKeyInfo; /// [RFC 5280 ยง 4.1.2.7]: https://tools.ietf.org/html/rfc5280#section-4.1.2.7 #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] #[derive(Clone, Debug, Eq, PartialEq)] -pub struct SubjectPublicKeyInfo { +pub struct SubjectPublicKeyInfo { /// X.509 [`AlgorithmIdentifier`] for the public key type pub algorithm: AlgorithmIdentifier, @@ -51,7 +51,7 @@ pub struct SubjectPublicKeyInfo { impl<'a, Params, Key> SubjectPublicKeyInfo where - Params: Choice<'a, Error = der::Error> + Encode, + Params: AnyLike + Choice<'a, Error = der::Error> + Encode, // TODO: replace FixedTag with FixedTag once // https://github.com/rust-lang/rust/issues/92827 is fixed Key: Decode<'a, Error = der::Error> + Encode + FixedTag, @@ -84,7 +84,7 @@ where impl<'a: 'k, 'k, Params, Key: 'k> DecodeValue<'a> for SubjectPublicKeyInfo where - Params: Choice<'a, Error = der::Error> + Encode, + Params: AnyLike + Choice<'a, Error = der::Error> + Encode, Key: Decode<'a, Error = der::Error>, { type Error = der::Error; @@ -101,7 +101,7 @@ where impl<'a, Params, Key> EncodeValue for SubjectPublicKeyInfo where - Params: Choice<'a, Error = der::Error> + Encode, + Params: AnyLike + Choice<'a, Error = der::Error> + Encode, Key: Encode, { fn value_len(&self) -> der::Result { @@ -117,14 +117,14 @@ where impl<'a, Params, Key> Sequence<'a> for SubjectPublicKeyInfo where - Params: Choice<'a, Error = der::Error> + Encode, + Params: AnyLike + Choice<'a, Error = der::Error> + Encode, Key: Decode<'a, Error = der::Error> + Encode + FixedTag, { } impl<'a, Params, Key> TryFrom<&'a [u8]> for SubjectPublicKeyInfo where - Params: Choice<'a, Error = der::Error> + Encode, + Params: AnyLike + Choice<'a, Error = der::Error> + Encode, Key: Decode<'a, Error = der::Error> + Encode + FixedTag, { type Error = Error; @@ -136,7 +136,7 @@ where impl<'a, Params, Key> ValueOrd for SubjectPublicKeyInfo where - Params: Choice<'a, Error = der::Error> + DerOrd + Encode, + Params: AnyLike + Choice<'a, Error = der::Error> + DerOrd + Encode, Key: ValueOrd, { fn value_cmp(&self, other: &Self) -> der::Result { @@ -150,7 +150,7 @@ where #[cfg(feature = "alloc")] impl<'a: 'k, 'k, Params, Key: 'k> TryFrom> for Document where - Params: Choice<'a, Error = der::Error> + Encode, + Params: AnyLike + Choice<'a, Error = der::Error> + Encode, Key: Decode<'a, Error = der::Error> + Encode + FixedTag, BitStringRef<'a>: From<&'k Key>, { @@ -164,7 +164,7 @@ where #[cfg(feature = "alloc")] impl<'a: 'k, 'k, Params, Key: 'k> TryFrom<&SubjectPublicKeyInfo> for Document where - Params: Choice<'a, Error = der::Error> + Encode, + Params: AnyLike + Choice<'a, Error = der::Error> + Encode, Key: Decode<'a, Error = der::Error> + Encode + FixedTag, BitStringRef<'a>: From<&'k Key>, { @@ -176,7 +176,10 @@ where } #[cfg(feature = "pem")] -impl PemLabel for SubjectPublicKeyInfo { +impl PemLabel for SubjectPublicKeyInfo +where + Params: AnyLike, +{ const PEM_LABEL: &'static str = "PUBLIC KEY"; } diff --git a/spki/src/traits.rs b/spki/src/traits.rs index f80bf69d7..af2b31e43 100644 --- a/spki/src/traits.rs +++ b/spki/src/traits.rs @@ -1,7 +1,7 @@ //! Traits for encoding/decoding SPKI public keys. use crate::{AlgorithmIdentifier, Error, Result, SubjectPublicKeyInfoRef}; -use der::{EncodeValue, Tagged}; +use der::{asn1::AnyLike, EncodeValue, Tagged}; #[cfg(feature = "alloc")] use { @@ -103,7 +103,7 @@ pub trait EncodePublicKey { /// This is useful for e.g. keys for digital signature algorithms. pub trait AssociatedAlgorithmIdentifier { /// Algorithm parameters. - type Params: Tagged + EncodeValue; + type Params: Tagged + EncodeValue + AnyLike; /// `AlgorithmIdentifier` for this structure. const ALGORITHM_IDENTIFIER: AlgorithmIdentifier; @@ -141,7 +141,7 @@ where /// private keys. pub trait SignatureAlgorithmIdentifier { /// Algorithm parameters. - type Params: Tagged + EncodeValue; + type Params: Tagged + EncodeValue + AnyLike; /// `AlgorithmIdentifier` for the corresponding singature system. const SIGNATURE_ALGORITHM_IDENTIFIER: AlgorithmIdentifier; diff --git a/spki/tests/spki.rs b/spki/tests/spki.rs index f912d4875..3ea759cda 100644 --- a/spki/tests/spki.rs +++ b/spki/tests/spki.rs @@ -1,6 +1,6 @@ //! `SubjectPublicKeyInfo` tests. -use der::asn1::ObjectIdentifier; +use der::asn1::{AnyLike, ObjectIdentifier}; use hex_literal::hex; use spki::SubjectPublicKeyInfoRef; From 22a7231132f04d89bc04b64e4b7c637e6b7e64aa Mon Sep 17 00:00:00 2001 From: Arthur Gautier Date: Wed, 22 May 2024 20:52:23 -0700 Subject: [PATCH 3/7] pkcs5: use newly defined `AnyLike` trait --- pkcs5/src/pbes2/kdf.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkcs5/src/pbes2/kdf.rs b/pkcs5/src/pbes2/kdf.rs index b5e55563f..20379d294 100644 --- a/pkcs5/src/pbes2/kdf.rs +++ b/pkcs5/src/pbes2/kdf.rs @@ -6,7 +6,7 @@ pub use self::salt::Salt; use crate::{AlgorithmIdentifierRef, Error, Result}; use der::{ - asn1::{AnyRef, ObjectIdentifier}, + asn1::{AnyLike, AnyRef, ObjectIdentifier}, Decode, DecodeValue, Encode, EncodeValue, ErrorKind, Length, Reader, Sequence, Tag, Tagged, Writer, }; From 7203ea64628d0531040a2ad884ad177ad22439d9 Mon Sep 17 00:00:00 2001 From: Arthur Gautier Date: Wed, 22 May 2024 20:52:49 -0700 Subject: [PATCH 4/7] pkcs8: use newly defined `AnyLike` trait --- pkcs8/tests/private_key.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkcs8/tests/private_key.rs b/pkcs8/tests/private_key.rs index d1dce2b54..0a71a9419 100644 --- a/pkcs8/tests/private_key.rs +++ b/pkcs8/tests/private_key.rs @@ -1,6 +1,6 @@ //! PKCS#8 private key tests -use der::asn1::ObjectIdentifier; +use der::asn1::{AnyLike, ObjectIdentifier}; use hex_literal::hex; use pkcs8::{PrivateKeyInfo, Version}; From e28a8eaab46f1b813708bb46824f28e05fd21bfc Mon Sep 17 00:00:00 2001 From: Arthur Gautier Date: Thu, 23 May 2024 13:18:05 -0700 Subject: [PATCH 5/7] [wip] pkcs1: make sure `AlgorithmIdentifier` is encoded with `Any` reverts parts of #799 and #1010 --- pkcs1/src/params.rs | 121 +++++++++++++++++++++++--------------------- 1 file changed, 63 insertions(+), 58 deletions(-) diff --git a/pkcs1/src/params.rs b/pkcs1/src/params.rs index 52ce89642..293d4c5ab 100644 --- a/pkcs1/src/params.rs +++ b/pkcs1/src/params.rs @@ -3,16 +3,18 @@ use crate::{Error, Result}; use der::{ asn1::{AnyRef, ContextSpecificRef, ObjectIdentifier}, - oid::AssociatedOid, Decode, DecodeValue, Encode, EncodeValue, FixedTag, Length, Reader, Sequence, Tag, TagMode, TagNumber, Writer, }; -use spki::{AlgorithmIdentifier, AlgorithmIdentifierRef}; +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"); const OID_PSPECIFIED: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.9"); +// 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: AlgorithmIdentifierRef<'_> = AlgorithmIdentifierRef { oid: OID_SHA_1, parameters: Some(AnyRef::NULL), @@ -82,7 +84,7 @@ pub struct RsaPssParams<'a> { pub hash: AlgorithmIdentifierRef<'a>, /// Mask Generation Function (MGF) - pub mask_gen: AlgorithmIdentifier>, + pub mask_gen: AlgorithmIdentifierRef<'a>, /// Salt length pub salt_len: u8, @@ -95,27 +97,27 @@ impl<'a> RsaPssParams<'a> { /// Default RSA PSS Salt length in RsaPssParams pub const SALT_LEN_DEFAULT: u8 = 20; - /// Create new RsaPssParams for the provided digest and salt len - pub fn new(salt_len: u8) -> Self - where - D: AssociatedOid, - { - Self { - hash: AlgorithmIdentifierRef { - oid: D::OID, - parameters: Some(AnyRef::NULL), - }, - mask_gen: AlgorithmIdentifier { - oid: OID_MGF_1, - parameters: Some(AlgorithmIdentifierRef { - oid: D::OID, - parameters: Some(AnyRef::NULL), - }), - }, - salt_len, - trailer_field: Default::default(), - } - } + // /// Create new RsaPssParams for the provided digest and salt len + // pub fn new(salt_len: u8) -> Self + // where + // D: AssociatedOid, + // { + // Self { + // hash: AlgorithmIdentifierRef { + // oid: D::OID, + // parameters: Some(AnyRef::NULL), + // }, + // mask_gen: AlgorithmIdentifier { + // oid: OID_MGF_1, + // parameters: Some(AlgorithmIdentifierRef { + // oid: D::OID, + // parameters: Some(AnyRef::NULL), + // }), + // }, + // salt_len, + // trailer_field: Default::default(), + // } + // } fn context_specific_hash(&self) -> Option>> { if self.hash == SHA_1_AI { @@ -131,7 +133,7 @@ impl<'a> RsaPssParams<'a> { fn context_specific_mask_gen( &self, - ) -> Option>>> { + ) -> Option>> { if self.mask_gen == default_mgf1_sha1() { None } else { @@ -230,10 +232,13 @@ impl<'a> TryFrom<&'a [u8]> for RsaPssParams<'a> { } /// Default Mask Generation Function (MGF): SHA-1. -fn default_mgf1_sha1<'a>() -> AlgorithmIdentifier> { - AlgorithmIdentifier::> { +fn default_mgf1_sha1<'a>() -> AlgorithmIdentifierRef<'a> { + AlgorithmIdentifierRef { oid: OID_MGF_1, - parameters: Some(SHA_1_AI), + parameters: Some( + AnyRef::new(Tag::Sequence, SEQ_OID_SHA_1_DER) + .expect("error creating default MGF1 params"), + ), } } @@ -258,41 +263,41 @@ pub struct RsaOaepParams<'a> { pub hash: AlgorithmIdentifierRef<'a>, /// Mask Generation Function (MGF) - pub mask_gen: AlgorithmIdentifier>, + pub mask_gen: AlgorithmIdentifierRef<'a>, /// The source (and possibly the value) of the label L pub p_source: AlgorithmIdentifierRef<'a>, } impl<'a> RsaOaepParams<'a> { - /// Create new RsaPssParams for the provided digest and default (empty) label - pub fn new() -> Self - where - D: AssociatedOid, - { - Self::new_with_label::(&[]) - } - - /// Create new RsaPssParams for the provided digest and specified label - pub fn new_with_label(label: &'a impl AsRef<[u8]>) -> Self - where - D: AssociatedOid, - { - Self { - hash: AlgorithmIdentifierRef { - oid: D::OID, - parameters: Some(AnyRef::NULL), - }, - mask_gen: AlgorithmIdentifier { - oid: OID_MGF_1, - parameters: Some(AlgorithmIdentifierRef { - oid: D::OID, - parameters: Some(AnyRef::NULL), - }), - }, - p_source: pspecicied_algorithm_identifier(label), - } - } + // /// Create new RsaPssParams for the provided digest and default (empty) label + // pub fn new() -> Self + // where + // D: AssociatedOid, + // { + // Self::new_with_label::(&[]) + // } + // + // /// Create new RsaPssParams for the provided digest and specified label + // pub fn new_with_label(label: &'a impl AsRef<[u8]>) -> Self + // where + // D: AssociatedOid, + // { + // Self { + // hash: AlgorithmIdentifierRef { + // oid: D::OID, + // parameters: Some(AnyRef::NULL), + // }, + // mask_gen: AlgorithmIdentifier { + // oid: OID_MGF_1, + // parameters: Some(AlgorithmIdentifierRef { + // oid: D::OID, + // parameters: Some(AnyRef::NULL), + // }), + // }, + // p_source: pspecicied_algorithm_identifier(label), + // } + // } fn context_specific_hash(&self) -> Option>> { if self.hash == SHA_1_AI { @@ -308,7 +313,7 @@ impl<'a> RsaOaepParams<'a> { fn context_specific_mask_gen( &self, - ) -> Option>>> { + ) -> Option>> { if self.mask_gen == default_mgf1_sha1() { None } else { From d918cb53856c06d113dd9539ee33c0d2cdafb9d8 Mon Sep 17 00:00:00 2001 From: Arthur Gautier Date: Thu, 23 May 2024 19:24:44 -0700 Subject: [PATCH 6/7] spki: impl `From for Any` --- spki/src/algorithm.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/spki/src/algorithm.rs b/spki/src/algorithm.rs index f932bc49d..20e100ee4 100644 --- a/spki/src/algorithm.rs +++ b/spki/src/algorithm.rs @@ -175,7 +175,7 @@ impl<'a> AlgorithmIdentifierRef<'a> { #[cfg(feature = "alloc")] mod allocating { use super::*; - use der::referenced::*; + use der::{referenced::*, Tag}; impl<'a> RefToOwned<'a> for AlgorithmIdentifierRef<'a> { type Owned = AlgorithmIdentifierOwned; @@ -196,4 +196,12 @@ mod allocating { } } } + + impl From<&AlgorithmIdentifierRef<'_>> for Any { + fn from(alg: &AlgorithmIdentifierRef<'_>) -> Any { + let bytes = alg.to_der().expect("Algorithm invariant violated"); + + Any::new(Tag::Sequence, bytes).expect("Algorithm invariant violated") + } + } } From 68cef0e8cac55577c2f5c6cd8d42a3fb7e86989c Mon Sep 17 00:00:00 2001 From: Arthur Gautier Date: Thu, 23 May 2024 19:25:12 -0700 Subject: [PATCH 7/7] pkcs1: restore `RsaPssParams::new` --- pkcs1/src/params.rs | 225 ++++++++++++++++++++++---------------------- 1 file changed, 110 insertions(+), 115 deletions(-) diff --git a/pkcs1/src/params.rs b/pkcs1/src/params.rs index 293d4c5ab..e307e4833 100644 --- a/pkcs1/src/params.rs +++ b/pkcs1/src/params.rs @@ -2,11 +2,13 @@ use crate::{Error, Result}; use der::{ - asn1::{AnyRef, ContextSpecificRef, ObjectIdentifier}, + asn1::{Any, AnyRef, ContextSpecific, ObjectIdentifier}, + oid::AssociatedOid, + referenced::{OwnedToRef, RefToOwned}, Decode, DecodeValue, Encode, EncodeValue, FixedTag, Length, Reader, Sequence, Tag, TagMode, TagNumber, Writer, }; -use spki::AlgorithmIdentifierRef; +use spki::{AlgorithmIdentifier, AlgorithmIdentifierOwned, 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"); @@ -79,12 +81,12 @@ impl FixedTag for TrailerField { /// /// [RFC 8017 Appendix 2.3]: https://datatracker.ietf.org/doc/html/rfc8017#appendix-A.2.3 #[derive(Clone, Debug, Eq, PartialEq)] -pub struct RsaPssParams<'a> { +pub struct RsaPssParams { /// Hash Algorithm - pub hash: AlgorithmIdentifierRef<'a>, + pub hash: AlgorithmIdentifierOwned, /// Mask Generation Function (MGF) - pub mask_gen: AlgorithmIdentifierRef<'a>, + pub mask_gen: AlgorithmIdentifierOwned, /// Salt length pub salt_len: u8, @@ -93,87 +95,85 @@ pub struct RsaPssParams<'a> { pub trailer_field: TrailerField, } -impl<'a> RsaPssParams<'a> { +impl RsaPssParams { /// Default RSA PSS Salt length in RsaPssParams pub const SALT_LEN_DEFAULT: u8 = 20; - // /// Create new RsaPssParams for the provided digest and salt len - // pub fn new(salt_len: u8) -> Self - // where - // D: AssociatedOid, - // { - // Self { - // hash: AlgorithmIdentifierRef { - // oid: D::OID, - // parameters: Some(AnyRef::NULL), - // }, - // mask_gen: AlgorithmIdentifier { - // oid: OID_MGF_1, - // parameters: Some(AlgorithmIdentifierRef { - // oid: D::OID, - // parameters: Some(AnyRef::NULL), - // }), - // }, - // salt_len, - // trailer_field: Default::default(), - // } - // } - - fn context_specific_hash(&self) -> Option>> { - if self.hash == SHA_1_AI { + /// Create new RsaPssParams for the provided digest and salt len + pub fn new(salt_len: u8) -> Self + where + D: AssociatedOid, + { + Self { + hash: AlgorithmIdentifier { + oid: D::OID, + parameters: Some(Any::null()), + }, + mask_gen: AlgorithmIdentifier { + oid: OID_MGF_1, + parameters: Some(Any::from(&AlgorithmIdentifierRef { + oid: D::OID, + parameters: Some(AnyRef::NULL), + })), + }, + salt_len, + trailer_field: Default::default(), + } + } + + fn context_specific_hash(&self) -> Option> { + if self.hash.owned_to_ref() == SHA_1_AI { None } else { - Some(ContextSpecificRef { + Some(ContextSpecific { tag_number: TagNumber::N0, tag_mode: TagMode::Explicit, - value: &self.hash, + value: self.hash.clone(), }) } } - fn context_specific_mask_gen( - &self, - ) -> Option>> { + fn context_specific_mask_gen(&self) -> Option> { if self.mask_gen == default_mgf1_sha1() { None } else { - Some(ContextSpecificRef { + Some(ContextSpecific { tag_number: TagNumber::N1, tag_mode: TagMode::Explicit, - value: &self.mask_gen, + value: self.mask_gen.clone(), }) } } - fn context_specific_salt_len(&self) -> Option> { + fn context_specific_salt_len(&self) -> Option> { if self.salt_len == RsaPssParams::SALT_LEN_DEFAULT { None } else { - Some(ContextSpecificRef { + Some(ContextSpecific { tag_number: TagNumber::N2, tag_mode: TagMode::Explicit, - value: &self.salt_len, + value: self.salt_len, }) } } - fn context_specific_trailer_field(&self) -> Option> { + fn context_specific_trailer_field(&self) -> Option> { if self.trailer_field == TrailerField::default() { None } else { - Some(ContextSpecificRef { + Some(ContextSpecific { tag_number: TagNumber::N3, tag_mode: TagMode::Explicit, - value: &self.trailer_field, + value: self.trailer_field, }) } } } -impl<'a> Default for RsaPssParams<'a> { +impl Default for RsaPssParams { fn default() -> Self { Self { - hash: SHA_1_AI, + hash: SHA_1_AI.ref_to_owned(), mask_gen: default_mgf1_sha1(), salt_len: RsaPssParams::SALT_LEN_DEFAULT, trailer_field: Default::default(), @@ -181,7 +181,7 @@ impl<'a> Default for RsaPssParams<'a> { } } -impl<'a> DecodeValue<'a> for RsaPssParams<'a> { +impl<'a> DecodeValue<'a> for RsaPssParams { type Error = der::Error; fn decode_value>(reader: &mut R, header: der::Header) -> der::Result { @@ -189,7 +189,7 @@ impl<'a> DecodeValue<'a> for RsaPssParams<'a> { Ok(Self { hash: reader .context_specific(TagNumber::N0, TagMode::Explicit)? - .unwrap_or(SHA_1_AI), + .unwrap_or_else(|| SHA_1_AI.ref_to_owned()), mask_gen: reader .context_specific(TagNumber::N1, TagMode::Explicit)? .unwrap_or_else(default_mgf1_sha1), @@ -204,7 +204,7 @@ impl<'a> DecodeValue<'a> for RsaPssParams<'a> { } } -impl EncodeValue for RsaPssParams<'_> { +impl EncodeValue for RsaPssParams { fn value_len(&self) -> der::Result { self.context_specific_hash().encoded_len()? + self.context_specific_mask_gen().encoded_len()? @@ -221,23 +221,22 @@ impl EncodeValue for RsaPssParams<'_> { } } -impl<'a> Sequence<'a> for RsaPssParams<'a> {} +impl<'a> Sequence<'a> for RsaPssParams {} -impl<'a> TryFrom<&'a [u8]> for RsaPssParams<'a> { +impl TryFrom<&[u8]> for RsaPssParams { type Error = Error; - fn try_from(bytes: &'a [u8]) -> Result { + fn try_from(bytes: &[u8]) -> Result { Ok(Self::from_der(bytes)?) } } /// Default Mask Generation Function (MGF): SHA-1. -fn default_mgf1_sha1<'a>() -> AlgorithmIdentifierRef<'a> { - AlgorithmIdentifierRef { +fn default_mgf1_sha1() -> AlgorithmIdentifierOwned { + AlgorithmIdentifier { oid: OID_MGF_1, parameters: Some( - AnyRef::new(Tag::Sequence, SEQ_OID_SHA_1_DER) - .expect("error creating default MGF1 params"), + Any::new(Tag::Sequence, SEQ_OID_SHA_1_DER).expect("error creating default MGF1 params"), ), } } @@ -258,106 +257,102 @@ fn default_mgf1_sha1<'a>() -> AlgorithmIdentifierRef<'a> { /// /// [RFC 8017 Appendix 2.1]: https://datatracker.ietf.org/doc/html/rfc8017#appendix-A.2.1 #[derive(Clone, Debug, Eq, PartialEq)] -pub struct RsaOaepParams<'a> { +pub struct RsaOaepParams { /// Hash Algorithm - pub hash: AlgorithmIdentifierRef<'a>, + pub hash: AlgorithmIdentifierOwned, /// Mask Generation Function (MGF) - pub mask_gen: AlgorithmIdentifierRef<'a>, + pub mask_gen: AlgorithmIdentifierOwned, /// The source (and possibly the value) of the label L - pub p_source: AlgorithmIdentifierRef<'a>, + pub p_source: AlgorithmIdentifierOwned, } -impl<'a> RsaOaepParams<'a> { - // /// Create new RsaPssParams for the provided digest and default (empty) label - // pub fn new() -> Self - // where - // D: AssociatedOid, - // { - // Self::new_with_label::(&[]) - // } - // - // /// Create new RsaPssParams for the provided digest and specified label - // pub fn new_with_label(label: &'a impl AsRef<[u8]>) -> Self - // where - // D: AssociatedOid, - // { - // Self { - // hash: AlgorithmIdentifierRef { - // oid: D::OID, - // parameters: Some(AnyRef::NULL), - // }, - // mask_gen: AlgorithmIdentifier { - // oid: OID_MGF_1, - // parameters: Some(AlgorithmIdentifierRef { - // oid: D::OID, - // parameters: Some(AnyRef::NULL), - // }), - // }, - // p_source: pspecicied_algorithm_identifier(label), - // } - // } - - fn context_specific_hash(&self) -> Option>> { - if self.hash == SHA_1_AI { +impl RsaOaepParams { + /// Create new RsaPssParams for the provided digest and default (empty) label + pub fn new() -> Self + where + D: AssociatedOid, + { + Self::new_with_label::(&[]) + } + + /// Create new RsaPssParams for the provided digest and specified label + pub fn new_with_label(label: &impl AsRef<[u8]>) -> Self + where + D: AssociatedOid, + { + Self { + hash: AlgorithmIdentifier { + oid: D::OID, + parameters: Some(Any::null()), + }, + mask_gen: AlgorithmIdentifier { + oid: OID_MGF_1, + parameters: Some(Any::from(&AlgorithmIdentifierRef { + oid: D::OID, + parameters: Some(AnyRef::NULL), + })), + }, + p_source: pspecicied_algorithm_identifier(label), + } + } + + fn context_specific_hash(&self) -> Option> { + if self.hash.owned_to_ref() == SHA_1_AI { None } else { - Some(ContextSpecificRef { + Some(ContextSpecific { tag_number: TagNumber::N0, tag_mode: TagMode::Explicit, - value: &self.hash, + value: self.hash.clone(), }) } } - fn context_specific_mask_gen( - &self, - ) -> Option>> { + fn context_specific_mask_gen(&self) -> Option> { if self.mask_gen == default_mgf1_sha1() { None } else { - Some(ContextSpecificRef { + Some(ContextSpecific { tag_number: TagNumber::N1, tag_mode: TagMode::Explicit, - value: &self.mask_gen, + value: self.mask_gen.clone(), }) } } - fn context_specific_p_source( - &self, - ) -> Option>> { + fn context_specific_p_source(&self) -> Option> { if self.p_source == default_pempty_string() { None } else { - Some(ContextSpecificRef { + Some(ContextSpecific { tag_number: TagNumber::N2, tag_mode: TagMode::Explicit, - value: &self.p_source, + value: self.p_source.clone(), }) } } } -impl<'a> Default for RsaOaepParams<'a> { +impl Default for RsaOaepParams { fn default() -> Self { Self { - hash: SHA_1_AI, + hash: SHA_1_AI.ref_to_owned(), mask_gen: default_mgf1_sha1(), p_source: default_pempty_string(), } } } -impl<'a> DecodeValue<'a> for RsaOaepParams<'a> { +impl<'a> DecodeValue<'a> for RsaOaepParams { type Error = der::Error; fn decode_value>(reader: &mut R, header: der::Header) -> der::Result { reader.read_nested(header.length, |reader| { Ok(Self { hash: reader .context_specific(TagNumber::N0, TagMode::Explicit)? - .unwrap_or(SHA_1_AI), + .unwrap_or_else(|| SHA_1_AI.ref_to_owned()), mask_gen: reader .context_specific(TagNumber::N1, TagMode::Explicit)? .unwrap_or_else(default_mgf1_sha1), @@ -369,7 +364,7 @@ impl<'a> DecodeValue<'a> for RsaOaepParams<'a> { } } -impl EncodeValue for RsaOaepParams<'_> { +impl EncodeValue for RsaOaepParams { fn value_len(&self) -> der::Result { self.context_specific_hash().encoded_len()? + self.context_specific_mask_gen().encoded_len()? @@ -384,26 +379,26 @@ impl EncodeValue for RsaOaepParams<'_> { } } -impl<'a> Sequence<'a> for RsaOaepParams<'a> {} +impl<'a> Sequence<'a> for RsaOaepParams {} -impl<'a> TryFrom<&'a [u8]> for RsaOaepParams<'a> { +impl TryFrom<&[u8]> for RsaOaepParams { type Error = Error; - fn try_from(bytes: &'a [u8]) -> Result { + fn try_from(bytes: &[u8]) -> Result { Ok(Self::from_der(bytes)?) } } -fn pspecicied_algorithm_identifier(label: &impl AsRef<[u8]>) -> AlgorithmIdentifierRef<'_> { - AlgorithmIdentifierRef { +fn pspecicied_algorithm_identifier(label: &impl AsRef<[u8]>) -> AlgorithmIdentifierOwned { + AlgorithmIdentifier { oid: OID_PSPECIFIED, parameters: Some( - AnyRef::new(Tag::OctetString, label.as_ref()).expect("error creating OAEP params"), + Any::new(Tag::OctetString, label.as_ref()).expect("error creating OAEP params"), ), } } /// Default Source Algorithm, empty string -fn default_pempty_string<'a>() -> AlgorithmIdentifierRef<'a> { +fn default_pempty_string() -> AlgorithmIdentifierOwned { pspecicied_algorithm_identifier(&[]) }