1use crate::error::X509Error;
2use crate::x509::AlgorithmIdentifier;
3use asn1_rs::{
4 oid, Any, CheckDerConstraints, Class, DerAutoDerive, Error, FromDer, Oid, OptTaggedExplicit,
5 OptTaggedParser, Tag,
6};
7use core::convert::TryFrom;
8use oid_registry::*;
9
10#[allow(non_camel_case_types)]
11#[derive(Debug, PartialEq)]
12pub enum SignatureAlgorithm<'a> {
13 RSA,
14 RSASSA_PSS(Box<RsaSsaPssParams<'a>>),
15 RSAAES_OAEP(Box<RsaAesOaepParams<'a>>),
16 DSA,
17 ECDSA,
18 ED25519,
19}
20
21impl<'a, 'b> TryFrom<&'b AlgorithmIdentifier<'a>> for SignatureAlgorithm<'a> {
22 type Error = X509Error;
23
24 fn try_from(value: &'b AlgorithmIdentifier<'a>) -> Result<Self, Self::Error> {
25 if value.algorithm.starts_with(&oid! {1.2.840.113549.1.1}) {
26 if value.algorithm == OID_PKCS1_RSASSAPSS {
29 let params = match value.parameters.as_ref() {
30 Some(any) => any,
31 None => return Err(X509Error::InvalidSignatureValue),
32 };
33 let params = RsaSsaPssParams::try_from(params)
34 .map_err(|_| X509Error::InvalidSignatureValue)?;
35 Ok(SignatureAlgorithm::RSASSA_PSS(Box::new(params)))
36 } else {
37 Ok(SignatureAlgorithm::RSA)
42 }
43 } else if test_ecdsa_oid(&value.algorithm) {
44 Ok(SignatureAlgorithm::ECDSA)
46 } else if value.algorithm.starts_with(&oid! {1.2.840.10040.4}) {
47 Ok(SignatureAlgorithm::DSA)
49 } else if value.algorithm == OID_SIG_ED25519 {
50 Ok(SignatureAlgorithm::ED25519)
51 } else if value.algorithm == oid! {1.2.840.113549.1.1.7} {
52 let params = match value.parameters.as_ref() {
53 Some(any) => any,
54 None => return Err(X509Error::InvalidSignatureValue),
55 };
56 let params =
57 RsaAesOaepParams::try_from(params).map_err(|_| X509Error::InvalidSignatureValue)?;
58 Ok(SignatureAlgorithm::RSAAES_OAEP(Box::new(params)))
59 } else {
60 if cfg!(debug_assertions) {
61 eprintln!("bad Signature AlgorithmIdentifier: {}", value.algorithm);
63 }
64 Err(X509Error::InvalidSignatureValue)
65 }
66 }
67}
68
69#[inline]
70fn test_ecdsa_oid(oid: &Oid) -> bool {
71 oid.starts_with(&oid! {1.2.840.10045.4})
73}
74
75#[derive(Debug, PartialEq)]
85pub struct RsaSsaPssParams<'a> {
86 hash_alg: Option<AlgorithmIdentifier<'a>>,
87 mask_gen_algorithm: Option<AlgorithmIdentifier<'a>>,
88 salt_length: Option<u32>,
89 trailer_field: Option<u32>,
90}
91
92impl<'a> RsaSsaPssParams<'a> {
93 pub fn hash_algorithm(&self) -> Option<&AlgorithmIdentifier> {
95 self.hash_alg.as_ref()
96 }
97
98 pub fn hash_algorithm_oid(&self) -> &'a Oid {
100 const SHA1: &Oid = &OID_HASH_SHA1;
101 self.hash_alg
102 .as_ref()
103 .map(|alg| &alg.algorithm)
104 .unwrap_or(SHA1)
105 }
106
107 pub fn mask_gen_algorithm_raw(&self) -> Option<&AlgorithmIdentifier> {
109 self.mask_gen_algorithm.as_ref()
110 }
111
112 pub fn mask_gen_algorithm(&self) -> Result<MaskGenAlgorithm, X509Error> {
116 match self.mask_gen_algorithm.as_ref() {
117 Some(alg) => {
118 let (_, hash) = alg
119 .parameters()
120 .and_then(|any| Oid::from_der(any.data).ok())
121 .ok_or(X509Error::InvalidAlgorithmIdentifier)?;
122 Ok(MaskGenAlgorithm::new(alg.algorithm.clone(), hash))
123 }
124 _ => {
125 Ok(MaskGenAlgorithm::new(
126 oid! {1.2.840.113549.1.1.8}, OID_HASH_SHA1,
128 ))
129 }
130 }
131 }
132
133 pub fn salt_length(&self) -> u32 {
135 self.salt_length.unwrap_or(20)
136 }
137
138 pub fn trailer_field(&self) -> u32 {
140 self.trailer_field.unwrap_or(1)
141 }
142}
143
144impl<'a> TryFrom<Any<'a>> for RsaSsaPssParams<'a> {
145 type Error = X509Error;
146
147 fn try_from(value: Any<'a>) -> Result<Self, Self::Error> {
148 Self::try_from(&value)
149 }
150}
151
152impl<'a, 'b> TryFrom<&'b Any<'a>> for RsaSsaPssParams<'a> {
153 type Error = X509Error;
154
155 fn try_from(value: &'b Any<'a>) -> Result<Self, Self::Error> {
156 value.tag().assert_eq(Tag::Sequence)?;
157 let i = &value.data;
158 let (i, hash_alg) = OptTaggedParser::new(Class::ContextSpecific, Tag(0))
160 .parse_der(i, |_, inner| AlgorithmIdentifier::from_der(inner))?;
161 let (i, mask_gen_algorithm) = OptTaggedParser::new(Class::ContextSpecific, Tag(1))
163 .parse_der(i, |_, inner| AlgorithmIdentifier::from_der(inner))?;
164 let (i, salt_length) = OptTaggedExplicit::<_, Error, 2>::from_der(i)?;
165 let (_, trailer_field) = OptTaggedExplicit::<_, Error, 3>::from_der(i)?;
166 let params = RsaSsaPssParams {
167 hash_alg,
168 mask_gen_algorithm,
169 salt_length: salt_length.map(|t| t.into_inner()),
170 trailer_field: trailer_field.map(|t| t.into_inner()),
171 };
172 Ok(params)
173 }
174}
175
176impl CheckDerConstraints for RsaSsaPssParams<'_> {
177 fn check_constraints(any: &Any) -> asn1_rs::Result<()> {
178 any.header.assert_constructed()?;
179 Ok(())
180 }
181}
182
183impl DerAutoDerive for RsaSsaPssParams<'_> {}
184
185#[derive(Debug, PartialEq, Eq)]
186pub struct MaskGenAlgorithm<'a, 'b> {
187 pub mgf: Oid<'a>,
188 pub hash: Oid<'b>,
189}
190
191impl<'a, 'b> MaskGenAlgorithm<'a, 'b> {
192 pub const fn new(mgf: Oid<'a>, hash: Oid<'b>) -> Self {
193 Self { mgf, hash }
194 }
195}
196
197#[derive(Debug, PartialEq)]
212pub struct RsaAesOaepParams<'a> {
213 hash_alg: Option<AlgorithmIdentifier<'a>>,
214 mask_gen_alg: Option<AlgorithmIdentifier<'a>>,
215 p_source_alg: Option<AlgorithmIdentifier<'a>>,
216}
217
218impl<'a> RsaAesOaepParams<'a> {
219 pub const EMPTY: &'static AlgorithmIdentifier<'static> = &AlgorithmIdentifier::new(
220 oid! {1.2.840.113549.1.1.9}, None,
222 );
223
224 pub fn hash_algorithm(&self) -> Option<&AlgorithmIdentifier> {
226 self.hash_alg.as_ref()
227 }
228
229 pub fn hash_algorithm_oid(&self) -> &'a Oid {
231 const SHA1: &Oid = &OID_HASH_SHA1;
232 self.hash_alg
233 .as_ref()
234 .map(|alg| &alg.algorithm)
235 .unwrap_or(SHA1)
236 }
237
238 pub fn mask_gen_algorithm_raw(&self) -> Option<&AlgorithmIdentifier> {
240 self.mask_gen_alg.as_ref()
241 }
242
243 pub fn mask_gen_algorithm(&self) -> Result<MaskGenAlgorithm, X509Error> {
247 match self.mask_gen_alg.as_ref() {
248 Some(alg) => {
249 let (_, hash) = alg
250 .parameters()
251 .and_then(|any| Oid::from_der(any.data).ok())
252 .ok_or(X509Error::InvalidAlgorithmIdentifier)?;
253 Ok(MaskGenAlgorithm::new(alg.algorithm.clone(), hash))
254 }
255 _ => {
256 Ok(MaskGenAlgorithm::new(
257 oid! {1.2.840.113549.1.1.8}, OID_HASH_SHA1,
259 ))
260 }
261 }
262 }
263
264 pub fn p_source_alg(&'a self) -> &'a AlgorithmIdentifier {
266 self.p_source_alg.as_ref().unwrap_or(Self::EMPTY)
267 }
268}
269
270impl<'a> TryFrom<Any<'a>> for RsaAesOaepParams<'a> {
271 type Error = X509Error;
272
273 fn try_from(value: Any<'a>) -> Result<Self, Self::Error> {
274 Self::try_from(&value)
275 }
276}
277
278impl<'a, 'b> TryFrom<&'b Any<'a>> for RsaAesOaepParams<'a> {
285 type Error = X509Error;
286
287 fn try_from(value: &'b Any<'a>) -> Result<Self, Self::Error> {
288 value.tag().assert_eq(Tag::Sequence)?;
289 let i = &value.data;
290 let (i, hash_alg) = OptTaggedParser::new(Class::ContextSpecific, Tag(0))
292 .parse_der(i, |_, inner| AlgorithmIdentifier::from_der(inner))?;
293 let (i, mask_gen_alg) = OptTaggedParser::new(Class::ContextSpecific, Tag(1))
295 .parse_der(i, |_, inner| AlgorithmIdentifier::from_der(inner))?;
296 let (_, p_source_alg) = OptTaggedParser::new(Class::ContextSpecific, Tag(2))
297 .parse_der(i, |_, inner| AlgorithmIdentifier::from_der(inner))?;
298 let params = RsaAesOaepParams {
299 hash_alg,
300 mask_gen_alg,
301 p_source_alg,
302 };
303 Ok(params)
304 }
305}
306
307impl CheckDerConstraints for RsaAesOaepParams<'_> {
308 fn check_constraints(any: &Any) -> asn1_rs::Result<()> {
309 any.header.assert_constructed()?;
310 Ok(())
311 }
312}
313
314impl DerAutoDerive for RsaAesOaepParams<'_> {}
315
316