1use crate::{Error, Result};
4use der::asn1::{AnyRef, ObjectIdentifier};
5use der::{
6 asn1::ContextSpecificRef, Decode, DecodeValue, Encode, EncodeValue, FixedTag, Reader, Sequence,
7 Tag, TagMode, TagNumber, Writer,
8};
9use spki::AlgorithmIdentifier;
10
11const OID_SHA_1: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.3.14.3.2.26");
12const OID_MGF_1: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.8");
13const OID_PSPECIFIED: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.9");
14
15const SEQ_OID_SHA_1_DER: &[u8] = &[0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a];
17
18const SHA_1_AI: AlgorithmIdentifier<'_> = AlgorithmIdentifier {
19 oid: OID_SHA_1,
20 parameters: None,
21};
22
23const SALT_LEN_DEFAULT: u8 = 20;
24
25#[derive(Clone, Debug, Copy, PartialEq, Eq)]
31#[repr(u8)]
32pub enum TrailerField {
33 BC = 1,
35}
36
37impl Default for TrailerField {
38 fn default() -> Self {
39 Self::BC
40 }
41}
42
43impl<'a> DecodeValue<'a> for TrailerField {
44 fn decode_value<R: Reader<'a>>(decoder: &mut R, header: der::Header) -> der::Result<Self> {
45 match u8::decode_value(decoder, header)? {
46 1 => Ok(TrailerField::BC),
47 _ => Err(Self::TAG.value_error()),
48 }
49 }
50}
51
52impl EncodeValue for TrailerField {
53 fn value_len(&self) -> der::Result<der::Length> {
54 Ok(der::Length::ONE)
55 }
56
57 fn encode_value(&self, writer: &mut dyn Writer) -> der::Result<()> {
58 (*self as u8).encode_value(writer)
59 }
60}
61
62impl FixedTag for TrailerField {
63 const TAG: Tag = Tag::Integer;
64}
65
66#[derive(Clone, Debug, Eq, PartialEq)]
82pub struct RsaPssParams<'a> {
83 pub hash: AlgorithmIdentifier<'a>,
85
86 pub mask_gen: AlgorithmIdentifier<'a>,
88
89 pub salt_len: u8,
91
92 pub trailer_field: TrailerField,
94}
95
96impl<'a> Default for RsaPssParams<'a> {
97 fn default() -> Self {
98 Self {
99 hash: SHA_1_AI,
100 mask_gen: default_mgf1_sha1(),
101 salt_len: SALT_LEN_DEFAULT,
102 trailer_field: Default::default(),
103 }
104 }
105}
106
107impl<'a> DecodeValue<'a> for RsaPssParams<'a> {
108 fn decode_value<R: Reader<'a>>(reader: &mut R, header: der::Header) -> der::Result<Self> {
109 reader.read_nested(header.length, |reader| {
110 Ok(Self {
111 hash: reader
112 .context_specific(TagNumber::N0, TagMode::Explicit)?
113 .unwrap_or(SHA_1_AI),
114 mask_gen: reader
115 .context_specific(TagNumber::N1, TagMode::Explicit)?
116 .unwrap_or_else(default_mgf1_sha1),
117 salt_len: reader
118 .context_specific(TagNumber::N2, TagMode::Explicit)?
119 .unwrap_or(SALT_LEN_DEFAULT),
120 trailer_field: reader
121 .context_specific(TagNumber::N3, TagMode::Explicit)?
122 .unwrap_or_default(),
123 })
124 })
125 }
126}
127
128impl<'a> Sequence<'a> for RsaPssParams<'a> {
129 fn fields<F, T>(&self, f: F) -> der::Result<T>
130 where
131 F: FnOnce(&[&dyn Encode]) -> der::Result<T>,
132 {
133 f(&[
134 &if self.hash == SHA_1_AI {
135 None
136 } else {
137 Some(ContextSpecificRef {
138 tag_number: TagNumber::N0,
139 tag_mode: TagMode::Explicit,
140 value: &self.hash,
141 })
142 },
143 &if self.mask_gen == default_mgf1_sha1() {
144 None
145 } else {
146 Some(ContextSpecificRef {
147 tag_number: TagNumber::N1,
148 tag_mode: TagMode::Explicit,
149 value: &self.mask_gen,
150 })
151 },
152 &if self.salt_len == SALT_LEN_DEFAULT {
153 None
154 } else {
155 Some(ContextSpecificRef {
156 tag_number: TagNumber::N2,
157 tag_mode: TagMode::Explicit,
158 value: &self.salt_len,
159 })
160 },
161 &if self.trailer_field == TrailerField::default() {
162 None
163 } else {
164 Some(ContextSpecificRef {
165 tag_number: TagNumber::N3,
166 tag_mode: TagMode::Explicit,
167 value: &self.trailer_field,
168 })
169 },
170 ])
171 }
172}
173
174impl<'a> TryFrom<&'a [u8]> for RsaPssParams<'a> {
175 type Error = Error;
176
177 fn try_from(bytes: &'a [u8]) -> Result<Self> {
178 Ok(Self::from_der(bytes)?)
179 }
180}
181
182fn default_mgf1_sha1<'a>() -> AlgorithmIdentifier<'a> {
184 AlgorithmIdentifier {
185 oid: OID_MGF_1,
186 parameters: Some(
187 AnyRef::new(Tag::Sequence, SEQ_OID_SHA_1_DER)
188 .expect("error creating default MGF1 params"),
189 ),
190 }
191}
192
193#[derive(Clone, Debug, Eq, PartialEq)]
209pub struct RsaOaepParams<'a> {
210 pub hash: AlgorithmIdentifier<'a>,
212
213 pub mask_gen: AlgorithmIdentifier<'a>,
215
216 pub p_source: AlgorithmIdentifier<'a>,
218}
219
220impl<'a> Default for RsaOaepParams<'a> {
221 fn default() -> Self {
222 Self {
223 hash: SHA_1_AI,
224 mask_gen: default_mgf1_sha1(),
225 p_source: default_pempty_string(),
226 }
227 }
228}
229
230impl<'a> DecodeValue<'a> for RsaOaepParams<'a> {
231 fn decode_value<R: Reader<'a>>(reader: &mut R, header: der::Header) -> der::Result<Self> {
232 reader.read_nested(header.length, |reader| {
233 Ok(Self {
234 hash: reader
235 .context_specific(TagNumber::N0, TagMode::Explicit)?
236 .unwrap_or(SHA_1_AI),
237 mask_gen: reader
238 .context_specific(TagNumber::N1, TagMode::Explicit)?
239 .unwrap_or_else(default_mgf1_sha1),
240 p_source: reader
241 .context_specific(TagNumber::N2, TagMode::Explicit)?
242 .unwrap_or_else(default_pempty_string),
243 })
244 })
245 }
246}
247
248impl<'a> Sequence<'a> for RsaOaepParams<'a> {
249 fn fields<F, T>(&self, f: F) -> der::Result<T>
250 where
251 F: FnOnce(&[&dyn Encode]) -> der::Result<T>,
252 {
253 f(&[
254 &if self.hash == SHA_1_AI {
255 None
256 } else {
257 Some(ContextSpecificRef {
258 tag_number: TagNumber::N0,
259 tag_mode: TagMode::Explicit,
260 value: &self.hash,
261 })
262 },
263 &if self.mask_gen == default_mgf1_sha1() {
264 None
265 } else {
266 Some(ContextSpecificRef {
267 tag_number: TagNumber::N1,
268 tag_mode: TagMode::Explicit,
269 value: &self.mask_gen,
270 })
271 },
272 &if self.p_source == default_pempty_string() {
273 None
274 } else {
275 Some(ContextSpecificRef {
276 tag_number: TagNumber::N2,
277 tag_mode: TagMode::Explicit,
278 value: &self.p_source,
279 })
280 },
281 ])
282 }
283}
284
285impl<'a> TryFrom<&'a [u8]> for RsaOaepParams<'a> {
286 type Error = Error;
287
288 fn try_from(bytes: &'a [u8]) -> Result<Self> {
289 Ok(Self::from_der(bytes)?)
290 }
291}
292
293fn default_pempty_string<'a>() -> AlgorithmIdentifier<'a> {
295 AlgorithmIdentifier {
296 oid: OID_PSPECIFIED,
297 parameters: Some(
298 AnyRef::new(Tag::OctetString, &[]).expect("error creating default OAEP params"),
299 ),
300 }
301}