aboutsummaryrefslogtreecommitdiff
path: root/src/params.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/params.rs')
-rw-r--r--src/params.rs314
1 files changed, 108 insertions, 206 deletions
diff --git a/src/params.rs b/src/params.rs
index 74a1ee4..e803473 100644
--- a/src/params.rs
+++ b/src/params.rs
@@ -1,23 +1,27 @@
//! PKCS#1 RSA parameters.
use crate::{Error, Result};
+use der::asn1::{AnyRef, ObjectIdentifier};
use der::{
- asn1::{AnyRef, ContextSpecificRef, ObjectIdentifier},
- oid::AssociatedOid,
- Decode, DecodeValue, Encode, EncodeValue, FixedTag, Length, Reader, Sequence, Tag, TagMode,
- TagNumber, Writer,
+ asn1::ContextSpecificRef, Decode, DecodeValue, Encode, EncodeValue, FixedTag, Reader, Sequence,
+ Tag, TagMode, TagNumber, Writer,
};
-use spki::{AlgorithmIdentifier, AlgorithmIdentifierRef};
+use spki::AlgorithmIdentifier;
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");
-const SHA_1_AI: AlgorithmIdentifierRef<'_> = AlgorithmIdentifierRef {
+// 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 {
oid: OID_SHA_1,
- parameters: Some(AnyRef::NULL),
+ parameters: None,
};
+const SALT_LEN_DEFAULT: u8 = 20;
+
/// `TrailerField` as defined in [RFC 8017 Appendix 2.3].
/// ```text
/// TrailerField ::= INTEGER { trailerFieldBC(1) }
@@ -46,11 +50,11 @@ impl<'a> DecodeValue<'a> for TrailerField {
}
impl EncodeValue for TrailerField {
- fn value_len(&self) -> der::Result<Length> {
- Ok(Length::ONE)
+ fn value_len(&self) -> der::Result<der::Length> {
+ Ok(der::Length::ONE)
}
- fn encode_value(&self, writer: &mut impl Writer) -> der::Result<()> {
+ fn encode_value(&self, writer: &mut dyn Writer) -> der::Result<()> {
(*self as u8).encode_value(writer)
}
}
@@ -77,10 +81,10 @@ impl FixedTag for TrailerField {
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct RsaPssParams<'a> {
/// Hash Algorithm
- pub hash: AlgorithmIdentifierRef<'a>,
+ pub hash: AlgorithmIdentifier<'a>,
/// Mask Generation Function (MGF)
- pub mask_gen: AlgorithmIdentifier<AlgorithmIdentifierRef<'a>>,
+ pub mask_gen: AlgorithmIdentifier<'a>,
/// Salt length
pub salt_len: u8,
@@ -89,89 +93,12 @@ pub struct RsaPssParams<'a> {
pub trailer_field: TrailerField,
}
-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<D>(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<ContextSpecificRef<'_, AlgorithmIdentifierRef<'a>>> {
- if self.hash == SHA_1_AI {
- None
- } else {
- Some(ContextSpecificRef {
- tag_number: TagNumber::N0,
- tag_mode: TagMode::Explicit,
- value: &self.hash,
- })
- }
- }
-
- fn context_specific_mask_gen(
- &self,
- ) -> Option<ContextSpecificRef<'_, AlgorithmIdentifier<AlgorithmIdentifierRef<'a>>>> {
- if self.mask_gen == default_mgf1_sha1() {
- None
- } else {
- Some(ContextSpecificRef {
- tag_number: TagNumber::N1,
- tag_mode: TagMode::Explicit,
- value: &self.mask_gen,
- })
- }
- }
-
- fn context_specific_salt_len(&self) -> Option<ContextSpecificRef<'_, u8>> {
- if self.salt_len == RsaPssParams::SALT_LEN_DEFAULT {
- None
- } else {
- Some(ContextSpecificRef {
- tag_number: TagNumber::N2,
- tag_mode: TagMode::Explicit,
- value: &self.salt_len,
- })
- }
- }
-
- fn context_specific_trailer_field(&self) -> Option<ContextSpecificRef<'_, TrailerField>> {
- if self.trailer_field == TrailerField::default() {
- None
- } else {
- Some(ContextSpecificRef {
- tag_number: TagNumber::N3,
- tag_mode: TagMode::Explicit,
- value: &self.trailer_field,
- })
- }
- }
-}
-
impl<'a> Default for RsaPssParams<'a> {
fn default() -> Self {
Self {
hash: SHA_1_AI,
mask_gen: default_mgf1_sha1(),
- salt_len: RsaPssParams::SALT_LEN_DEFAULT,
+ salt_len: SALT_LEN_DEFAULT,
trailer_field: Default::default(),
}
}
@@ -189,7 +116,7 @@ impl<'a> DecodeValue<'a> for RsaPssParams<'a> {
.unwrap_or_else(default_mgf1_sha1),
salt_len: reader
.context_specific(TagNumber::N2, TagMode::Explicit)?
- .unwrap_or(RsaPssParams::SALT_LEN_DEFAULT),
+ .unwrap_or(SALT_LEN_DEFAULT),
trailer_field: reader
.context_specific(TagNumber::N3, TagMode::Explicit)?
.unwrap_or_default(),
@@ -198,25 +125,52 @@ impl<'a> DecodeValue<'a> for RsaPssParams<'a> {
}
}
-impl EncodeValue for RsaPssParams<'_> {
- fn value_len(&self) -> der::Result<Length> {
- self.context_specific_hash().encoded_len()?
- + self.context_specific_mask_gen().encoded_len()?
- + self.context_specific_salt_len().encoded_len()?
- + self.context_specific_trailer_field().encoded_len()?
- }
-
- fn encode_value(&self, writer: &mut impl Writer) -> der::Result<()> {
- self.context_specific_hash().encode(writer)?;
- self.context_specific_mask_gen().encode(writer)?;
- self.context_specific_salt_len().encode(writer)?;
- self.context_specific_trailer_field().encode(writer)?;
- Ok(())
+impl<'a> Sequence<'a> for RsaPssParams<'a> {
+ fn fields<F, T>(&self, f: F) -> der::Result<T>
+ where
+ F: FnOnce(&[&dyn Encode]) -> der::Result<T>,
+ {
+ f(&[
+ &if self.hash == SHA_1_AI {
+ None
+ } else {
+ Some(ContextSpecificRef {
+ tag_number: TagNumber::N0,
+ tag_mode: TagMode::Explicit,
+ value: &self.hash,
+ })
+ },
+ &if self.mask_gen == default_mgf1_sha1() {
+ None
+ } else {
+ Some(ContextSpecificRef {
+ tag_number: TagNumber::N1,
+ tag_mode: TagMode::Explicit,
+ value: &self.mask_gen,
+ })
+ },
+ &if self.salt_len == SALT_LEN_DEFAULT {
+ None
+ } else {
+ Some(ContextSpecificRef {
+ tag_number: TagNumber::N2,
+ tag_mode: TagMode::Explicit,
+ value: &self.salt_len,
+ })
+ },
+ &if self.trailer_field == TrailerField::default() {
+ None
+ } else {
+ Some(ContextSpecificRef {
+ tag_number: TagNumber::N3,
+ tag_mode: TagMode::Explicit,
+ value: &self.trailer_field,
+ })
+ },
+ ])
}
}
-impl<'a> Sequence<'a> for RsaPssParams<'a> {}
-
impl<'a> TryFrom<&'a [u8]> for RsaPssParams<'a> {
type Error = Error;
@@ -226,10 +180,13 @@ impl<'a> TryFrom<&'a [u8]> for RsaPssParams<'a> {
}
/// Default Mask Generation Function (MGF): SHA-1.
-fn default_mgf1_sha1<'a>() -> AlgorithmIdentifier<AlgorithmIdentifierRef<'a>> {
- AlgorithmIdentifier::<AlgorithmIdentifierRef<'a>> {
+fn default_mgf1_sha1<'a>() -> AlgorithmIdentifier<'a> {
+ AlgorithmIdentifier {
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"),
+ ),
}
}
@@ -251,84 +208,13 @@ fn default_mgf1_sha1<'a>() -> AlgorithmIdentifier<AlgorithmIdentifierRef<'a>> {
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct RsaOaepParams<'a> {
/// Hash Algorithm
- pub hash: AlgorithmIdentifierRef<'a>,
+ pub hash: AlgorithmIdentifier<'a>,
/// Mask Generation Function (MGF)
- pub mask_gen: AlgorithmIdentifier<AlgorithmIdentifierRef<'a>>,
+ pub mask_gen: AlgorithmIdentifier<'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<D>() -> Self
- where
- D: AssociatedOid,
- {
- Self::new_with_label::<D>(&[])
- }
-
- /// Create new RsaPssParams for the provided digest and specified label
- pub fn new_with_label<D>(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<ContextSpecificRef<'_, AlgorithmIdentifierRef<'a>>> {
- if self.hash == SHA_1_AI {
- None
- } else {
- Some(ContextSpecificRef {
- tag_number: TagNumber::N0,
- tag_mode: TagMode::Explicit,
- value: &self.hash,
- })
- }
- }
-
- fn context_specific_mask_gen(
- &self,
- ) -> Option<ContextSpecificRef<'_, AlgorithmIdentifier<AlgorithmIdentifierRef<'a>>>> {
- if self.mask_gen == default_mgf1_sha1() {
- None
- } else {
- Some(ContextSpecificRef {
- tag_number: TagNumber::N1,
- tag_mode: TagMode::Explicit,
- value: &self.mask_gen,
- })
- }
- }
-
- fn context_specific_p_source(
- &self,
- ) -> Option<ContextSpecificRef<'_, AlgorithmIdentifierRef<'a>>> {
- if self.p_source == default_pempty_string() {
- None
- } else {
- Some(ContextSpecificRef {
- tag_number: TagNumber::N2,
- tag_mode: TagMode::Explicit,
- value: &self.p_source,
- })
- }
- }
+ pub p_source: AlgorithmIdentifier<'a>,
}
impl<'a> Default for RsaOaepParams<'a> {
@@ -359,23 +245,43 @@ impl<'a> DecodeValue<'a> for RsaOaepParams<'a> {
}
}
-impl EncodeValue for RsaOaepParams<'_> {
- fn value_len(&self) -> der::Result<Length> {
- self.context_specific_hash().encoded_len()?
- + self.context_specific_mask_gen().encoded_len()?
- + self.context_specific_p_source().encoded_len()?
- }
-
- fn encode_value(&self, writer: &mut impl Writer) -> der::Result<()> {
- self.context_specific_hash().encode(writer)?;
- self.context_specific_mask_gen().encode(writer)?;
- self.context_specific_p_source().encode(writer)?;
- Ok(())
+impl<'a> Sequence<'a> for RsaOaepParams<'a> {
+ fn fields<F, T>(&self, f: F) -> der::Result<T>
+ where
+ F: FnOnce(&[&dyn Encode]) -> der::Result<T>,
+ {
+ f(&[
+ &if self.hash == SHA_1_AI {
+ None
+ } else {
+ Some(ContextSpecificRef {
+ tag_number: TagNumber::N0,
+ tag_mode: TagMode::Explicit,
+ value: &self.hash,
+ })
+ },
+ &if self.mask_gen == default_mgf1_sha1() {
+ None
+ } else {
+ Some(ContextSpecificRef {
+ tag_number: TagNumber::N1,
+ tag_mode: TagMode::Explicit,
+ value: &self.mask_gen,
+ })
+ },
+ &if self.p_source == default_pempty_string() {
+ None
+ } else {
+ Some(ContextSpecificRef {
+ tag_number: TagNumber::N2,
+ tag_mode: TagMode::Explicit,
+ value: &self.p_source,
+ })
+ },
+ ])
}
}
-impl<'a> Sequence<'a> for RsaOaepParams<'a> {}
-
impl<'a> TryFrom<&'a [u8]> for RsaOaepParams<'a> {
type Error = Error;
@@ -384,16 +290,12 @@ impl<'a> TryFrom<&'a [u8]> for RsaOaepParams<'a> {
}
}
-fn pspecicied_algorithm_identifier(label: &impl AsRef<[u8]>) -> AlgorithmIdentifierRef<'_> {
- AlgorithmIdentifierRef {
+/// Default Source Algorithm, empty string
+fn default_pempty_string<'a>() -> AlgorithmIdentifier<'a> {
+ AlgorithmIdentifier {
oid: OID_PSPECIFIED,
parameters: Some(
- AnyRef::new(Tag::OctetString, label.as_ref()).expect("error creating OAEP params"),
+ AnyRef::new(Tag::OctetString, &[]).expect("error creating default OAEP params"),
),
}
}
-
-/// Default Source Algorithm, empty string
-fn default_pempty_string<'a>() -> AlgorithmIdentifierRef<'a> {
- pspecicied_algorithm_identifier(&[])
-}