1use crate::{Error, Result};
4use der::{
5 Decode, DecodeValue, Encode, EncodeValue, FixedTag, Length, Reader, Sequence, Tag, TagMode,
6 TagNumber, Writer,
7 asn1::{AnyRef, ContextSpecificRef, ObjectIdentifier},
8 oid::AssociatedOid,
9};
10use spki::{AlgorithmIdentifier, AlgorithmIdentifierRef};
11
12const OID_SHA_1: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.3.14.3.2.26");
13const OID_MGF_1: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.8");
14const OID_PSPECIFIED: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.9");
15
16const SHA_1_AI: AlgorithmIdentifierRef<'_> = AlgorithmIdentifierRef {
17 oid: OID_SHA_1,
18 parameters: Some(AnyRef::NULL),
19};
20
21#[derive(Clone, Debug, Copy, PartialEq, Eq)]
27#[repr(u8)]
28pub enum TrailerField {
29 BC = 1,
31}
32
33impl Default for TrailerField {
34 fn default() -> Self {
35 Self::BC
36 }
37}
38
39impl<'a> DecodeValue<'a> for TrailerField {
40 type Error = der::Error;
41
42 fn decode_value<R: Reader<'a>>(reader: &mut R, header: der::Header) -> der::Result<Self> {
43 match u8::decode_value(reader, header)? {
44 1 => Ok(TrailerField::BC),
45 _ => Err(reader.error(Self::TAG.value_error())),
46 }
47 }
48}
49
50impl EncodeValue for TrailerField {
51 fn value_len(&self) -> der::Result<Length> {
52 Ok(Length::ONE)
53 }
54
55 fn encode_value(&self, writer: &mut impl Writer) -> der::Result<()> {
56 (*self as u8).encode_value(writer)
57 }
58}
59
60impl FixedTag for TrailerField {
61 const TAG: Tag = Tag::Integer;
62}
63
64#[derive(Clone, Debug, Eq, PartialEq)]
80pub struct RsaPssParams<'a> {
81 pub hash: AlgorithmIdentifierRef<'a>,
83
84 pub mask_gen: AlgorithmIdentifier<AlgorithmIdentifierRef<'a>>,
86
87 pub salt_len: u8,
89
90 pub trailer_field: TrailerField,
92}
93
94impl<'a> RsaPssParams<'a> {
95 pub const SALT_LEN_DEFAULT: u8 = 20;
97
98 pub fn new<D>(salt_len: u8) -> Self
100 where
101 D: AssociatedOid,
102 {
103 Self {
104 hash: AlgorithmIdentifierRef {
105 oid: D::OID,
106 parameters: Some(AnyRef::NULL),
107 },
108 mask_gen: AlgorithmIdentifier {
109 oid: OID_MGF_1,
110 parameters: Some(AlgorithmIdentifierRef {
111 oid: D::OID,
112 parameters: Some(AnyRef::NULL),
113 }),
114 },
115 salt_len,
116 trailer_field: Default::default(),
117 }
118 }
119
120 fn context_specific_hash(&self) -> Option<ContextSpecificRef<'_, AlgorithmIdentifierRef<'a>>> {
121 if self.hash == SHA_1_AI {
122 None
123 } else {
124 Some(ContextSpecificRef {
125 tag_number: TagNumber(0),
126 tag_mode: TagMode::Explicit,
127 value: &self.hash,
128 })
129 }
130 }
131
132 fn context_specific_mask_gen(
133 &self,
134 ) -> Option<ContextSpecificRef<'_, AlgorithmIdentifier<AlgorithmIdentifierRef<'a>>>> {
135 if self.mask_gen == default_mgf1_sha1() {
136 None
137 } else {
138 Some(ContextSpecificRef {
139 tag_number: TagNumber(1),
140 tag_mode: TagMode::Explicit,
141 value: &self.mask_gen,
142 })
143 }
144 }
145
146 fn context_specific_salt_len(&self) -> Option<ContextSpecificRef<'_, u8>> {
147 if self.salt_len == RsaPssParams::SALT_LEN_DEFAULT {
148 None
149 } else {
150 Some(ContextSpecificRef {
151 tag_number: TagNumber(2),
152 tag_mode: TagMode::Explicit,
153 value: &self.salt_len,
154 })
155 }
156 }
157
158 fn context_specific_trailer_field(&self) -> Option<ContextSpecificRef<'_, TrailerField>> {
159 if self.trailer_field == TrailerField::default() {
160 None
161 } else {
162 Some(ContextSpecificRef {
163 tag_number: TagNumber(3),
164 tag_mode: TagMode::Explicit,
165 value: &self.trailer_field,
166 })
167 }
168 }
169}
170
171impl Default for RsaPssParams<'_> {
172 fn default() -> Self {
173 Self {
174 hash: SHA_1_AI,
175 mask_gen: default_mgf1_sha1(),
176 salt_len: RsaPssParams::SALT_LEN_DEFAULT,
177 trailer_field: Default::default(),
178 }
179 }
180}
181
182impl<'a> DecodeValue<'a> for RsaPssParams<'a> {
183 type Error = der::Error;
184
185 fn decode_value<R: Reader<'a>>(reader: &mut R, _header: der::Header) -> der::Result<Self> {
186 Ok(Self {
187 hash: reader
188 .context_specific(TagNumber(0), TagMode::Explicit)?
189 .unwrap_or(SHA_1_AI),
190 mask_gen: reader
191 .context_specific(TagNumber(1), TagMode::Explicit)?
192 .unwrap_or_else(default_mgf1_sha1),
193 salt_len: reader
194 .context_specific(TagNumber(2), TagMode::Explicit)?
195 .unwrap_or(RsaPssParams::SALT_LEN_DEFAULT),
196 trailer_field: reader
197 .context_specific(TagNumber(3), TagMode::Explicit)?
198 .unwrap_or_default(),
199 })
200 }
201}
202
203impl EncodeValue for RsaPssParams<'_> {
204 fn value_len(&self) -> der::Result<Length> {
205 self.context_specific_hash().encoded_len()?
206 + self.context_specific_mask_gen().encoded_len()?
207 + self.context_specific_salt_len().encoded_len()?
208 + self.context_specific_trailer_field().encoded_len()?
209 }
210
211 fn encode_value(&self, writer: &mut impl Writer) -> der::Result<()> {
212 self.context_specific_hash().encode(writer)?;
213 self.context_specific_mask_gen().encode(writer)?;
214 self.context_specific_salt_len().encode(writer)?;
215 self.context_specific_trailer_field().encode(writer)?;
216 Ok(())
217 }
218}
219
220impl<'a> Sequence<'a> for RsaPssParams<'a> {}
221
222impl<'a> TryFrom<&'a [u8]> for RsaPssParams<'a> {
223 type Error = Error;
224
225 fn try_from(bytes: &'a [u8]) -> Result<Self> {
226 Ok(Self::from_der(bytes)?)
227 }
228}
229
230fn default_mgf1_sha1<'a>() -> AlgorithmIdentifier<AlgorithmIdentifierRef<'a>> {
232 AlgorithmIdentifier::<AlgorithmIdentifierRef<'a>> {
233 oid: OID_MGF_1,
234 parameters: Some(SHA_1_AI),
235 }
236}
237
238#[derive(Clone, Debug, Eq, PartialEq)]
254pub struct RsaOaepParams<'a> {
255 pub hash: AlgorithmIdentifierRef<'a>,
257
258 pub mask_gen: AlgorithmIdentifier<AlgorithmIdentifierRef<'a>>,
260
261 pub p_source: AlgorithmIdentifierRef<'a>,
263}
264
265impl<'a> RsaOaepParams<'a> {
266 pub fn new<D>() -> Self
268 where
269 D: AssociatedOid,
270 {
271 Self::new_with_label::<D>(&[])
272 }
273
274 pub fn new_with_label<D>(label: &'a impl AsRef<[u8]>) -> Self
276 where
277 D: AssociatedOid,
278 {
279 Self {
280 hash: AlgorithmIdentifierRef {
281 oid: D::OID,
282 parameters: Some(AnyRef::NULL),
283 },
284 mask_gen: AlgorithmIdentifier {
285 oid: OID_MGF_1,
286 parameters: Some(AlgorithmIdentifierRef {
287 oid: D::OID,
288 parameters: Some(AnyRef::NULL),
289 }),
290 },
291 p_source: pspecified_algorithm_identifier(label),
292 }
293 }
294
295 fn context_specific_hash(&self) -> Option<ContextSpecificRef<'_, AlgorithmIdentifierRef<'a>>> {
296 if self.hash == SHA_1_AI {
297 None
298 } else {
299 Some(ContextSpecificRef {
300 tag_number: TagNumber(0),
301 tag_mode: TagMode::Explicit,
302 value: &self.hash,
303 })
304 }
305 }
306
307 fn context_specific_mask_gen(
308 &self,
309 ) -> Option<ContextSpecificRef<'_, AlgorithmIdentifier<AlgorithmIdentifierRef<'a>>>> {
310 if self.mask_gen == default_mgf1_sha1() {
311 None
312 } else {
313 Some(ContextSpecificRef {
314 tag_number: TagNumber(1),
315 tag_mode: TagMode::Explicit,
316 value: &self.mask_gen,
317 })
318 }
319 }
320
321 fn context_specific_p_source(
322 &self,
323 ) -> Option<ContextSpecificRef<'_, AlgorithmIdentifierRef<'a>>> {
324 if self.p_source == default_pempty_string() {
325 None
326 } else {
327 Some(ContextSpecificRef {
328 tag_number: TagNumber(2),
329 tag_mode: TagMode::Explicit,
330 value: &self.p_source,
331 })
332 }
333 }
334}
335
336impl Default for RsaOaepParams<'_> {
337 fn default() -> Self {
338 Self {
339 hash: SHA_1_AI,
340 mask_gen: default_mgf1_sha1(),
341 p_source: default_pempty_string(),
342 }
343 }
344}
345
346impl<'a> DecodeValue<'a> for RsaOaepParams<'a> {
347 type Error = der::Error;
348
349 fn decode_value<R: Reader<'a>>(reader: &mut R, _header: der::Header) -> der::Result<Self> {
350 Ok(Self {
351 hash: reader
352 .context_specific(TagNumber(0), TagMode::Explicit)?
353 .unwrap_or(SHA_1_AI),
354 mask_gen: reader
355 .context_specific(TagNumber(1), TagMode::Explicit)?
356 .unwrap_or_else(default_mgf1_sha1),
357 p_source: reader
358 .context_specific(TagNumber(2), TagMode::Explicit)?
359 .unwrap_or_else(default_pempty_string),
360 })
361 }
362}
363
364impl EncodeValue for RsaOaepParams<'_> {
365 fn value_len(&self) -> der::Result<Length> {
366 self.context_specific_hash().encoded_len()?
367 + self.context_specific_mask_gen().encoded_len()?
368 + self.context_specific_p_source().encoded_len()?
369 }
370
371 fn encode_value(&self, writer: &mut impl Writer) -> der::Result<()> {
372 self.context_specific_hash().encode(writer)?;
373 self.context_specific_mask_gen().encode(writer)?;
374 self.context_specific_p_source().encode(writer)?;
375 Ok(())
376 }
377}
378
379impl<'a> Sequence<'a> for RsaOaepParams<'a> {}
380
381impl<'a> TryFrom<&'a [u8]> for RsaOaepParams<'a> {
382 type Error = Error;
383
384 fn try_from(bytes: &'a [u8]) -> Result<Self> {
385 Ok(Self::from_der(bytes)?)
386 }
387}
388
389fn pspecified_algorithm_identifier(label: &impl AsRef<[u8]>) -> AlgorithmIdentifierRef<'_> {
390 AlgorithmIdentifierRef {
391 oid: OID_PSPECIFIED,
392 parameters: Some(
393 AnyRef::new(Tag::OctetString, label.as_ref()).expect("error creating OAEP params"),
394 ),
395 }
396}
397
398fn default_pempty_string<'a>() -> AlgorithmIdentifierRef<'a> {
400 pspecified_algorithm_identifier(&[])
401}