1use std::fmt;
2use std::hash::{Hash, Hasher};
3
4#[cfg(all(feature = "aws_lc_rs_unstable", not(feature = "fips")))]
5use aws_lc_rs::unstable::signature::{
6 PqdsaSigningAlgorithm, ML_DSA_44_SIGNING, ML_DSA_65_SIGNING, ML_DSA_87_SIGNING,
7};
8use yasna::models::ObjectIdentifier;
9use yasna::{DERWriter, Tag};
10
11#[cfg(feature = "crypto")]
12use crate::ring_like::signature::{self, EcdsaSigningAlgorithm, EdDSAParameters, RsaEncoding};
13use crate::Error;
14
15#[cfg(feature = "crypto")]
16#[derive(Clone, Copy, Debug)]
17pub(crate) enum SignAlgo {
18 EcDsa(&'static EcdsaSigningAlgorithm),
19 EdDsa(&'static EdDSAParameters),
20 #[cfg(all(feature = "aws_lc_rs_unstable", not(feature = "fips")))]
21 PqDsa(&'static PqdsaSigningAlgorithm),
22 Rsa(&'static dyn RsaEncoding),
23}
24
25#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
26pub(crate) enum SignatureAlgorithmParams {
27 None,
29 Null,
31 RsaPss {
33 hash_algorithm: &'static [u64],
34 salt_length: u64,
35 },
36}
37
38#[derive(Clone)]
40pub struct SignatureAlgorithm {
41 oids_sign_alg: &'static [&'static [u64]],
42 #[cfg(feature = "crypto")]
43 pub(crate) sign_alg: SignAlgo,
44 oid_components: &'static [u64],
45 params: SignatureAlgorithmParams,
46}
47
48impl fmt::Debug for SignatureAlgorithm {
49 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
50 use algo::*;
51 if self == &PKCS_RSA_SHA256 {
52 write!(f, "PKCS_RSA_SHA256")
53 } else if self == &PKCS_RSA_SHA384 {
54 write!(f, "PKCS_RSA_SHA384")
55 } else if self == &PKCS_RSA_SHA512 {
56 write!(f, "PKCS_RSA_SHA512")
57 } else if self == &PKCS_RSA_PSS_SHA256 {
58 write!(f, "PKCS_RSA_PSS_SHA256")
59 } else if self == &PKCS_ECDSA_P256_SHA256 {
60 write!(f, "PKCS_ECDSA_P256_SHA256")
61 } else if self == &PKCS_ECDSA_P384_SHA384 {
62 write!(f, "PKCS_ECDSA_P384_SHA384")
63 } else if self == &PKCS_ED25519 {
64 write!(f, "PKCS_ED25519")
65 } else {
66 #[cfg(feature = "aws_lc_rs")]
67 if self == &PKCS_ECDSA_P521_SHA512 {
68 return write!(f, "PKCS_ECDSA_P521_SHA512");
69 }
70
71 write!(f, "Unknown")
72 }
73 }
74}
75
76impl PartialEq for SignatureAlgorithm {
77 fn eq(&self, other: &Self) -> bool {
78 (self.oids_sign_alg, self.oid_components) == (other.oids_sign_alg, other.oid_components)
79 }
80}
81
82impl Eq for SignatureAlgorithm {}
83
84impl Hash for SignatureAlgorithm {
86 fn hash<H: Hasher>(&self, state: &mut H) {
87 self.oids_sign_alg.hash(state);
89 }
90}
91impl SignatureAlgorithm {
92 pub(crate) fn iter() -> std::slice::Iter<'static, &'static SignatureAlgorithm> {
93 use algo::*;
94 static ALGORITHMS: &[&SignatureAlgorithm] = &[
95 &PKCS_RSA_SHA256,
96 &PKCS_RSA_SHA384,
97 &PKCS_RSA_SHA512,
98 &PKCS_ECDSA_P256_SHA256,
100 &PKCS_ECDSA_P384_SHA384,
101 #[cfg(feature = "aws_lc_rs")]
102 &PKCS_ECDSA_P521_SHA512,
103 &PKCS_ED25519,
104 ];
105 ALGORITHMS.iter()
106 }
107
108 pub fn from_oid(oid: &[u64]) -> Result<&'static SignatureAlgorithm, Error> {
110 for algo in Self::iter() {
111 if algo.oid_components == oid {
112 return Ok(algo);
113 }
114 }
115 Err(Error::UnsupportedSignatureAlgorithm)
116 }
117}
118
119pub(crate) mod algo {
121 use super::*;
122 use crate::oid::*;
123
124 pub static PKCS_RSA_SHA256: SignatureAlgorithm = SignatureAlgorithm {
126 oids_sign_alg: &[RSA_ENCRYPTION],
127 #[cfg(feature = "crypto")]
128 sign_alg: SignAlgo::Rsa(&signature::RSA_PKCS1_SHA256),
129 oid_components: &[1, 2, 840, 113549, 1, 1, 11],
131 params: SignatureAlgorithmParams::Null,
132 };
133
134 pub static PKCS_RSA_SHA384: SignatureAlgorithm = SignatureAlgorithm {
136 oids_sign_alg: &[RSA_ENCRYPTION],
137 #[cfg(feature = "crypto")]
138 sign_alg: SignAlgo::Rsa(&signature::RSA_PKCS1_SHA384),
139 oid_components: &[1, 2, 840, 113549, 1, 1, 12],
141 params: SignatureAlgorithmParams::Null,
142 };
143
144 pub static PKCS_RSA_SHA512: SignatureAlgorithm = SignatureAlgorithm {
146 oids_sign_alg: &[RSA_ENCRYPTION],
147 #[cfg(feature = "crypto")]
148 sign_alg: SignAlgo::Rsa(&signature::RSA_PKCS1_SHA512),
149 oid_components: &[1, 2, 840, 113549, 1, 1, 13],
151 params: SignatureAlgorithmParams::Null,
152 };
153
154 pub(crate) static PKCS_RSA_PSS_SHA256: SignatureAlgorithm = SignatureAlgorithm {
161 oids_sign_alg: &[RSASSA_PSS],
164 #[cfg(feature = "crypto")]
165 sign_alg: SignAlgo::Rsa(&signature::RSA_PSS_SHA256),
166 oid_components: RSASSA_PSS, params: SignatureAlgorithmParams::RsaPss {
169 hash_algorithm: &[2, 16, 840, 1, 101, 3, 4, 2, 1],
171 salt_length: 20,
172 },
173 };
174
175 pub static PKCS_ECDSA_P256_SHA256: SignatureAlgorithm = SignatureAlgorithm {
177 oids_sign_alg: &[EC_PUBLIC_KEY, EC_SECP_256_R1],
178 #[cfg(feature = "crypto")]
179 sign_alg: SignAlgo::EcDsa(&signature::ECDSA_P256_SHA256_ASN1_SIGNING),
180 oid_components: &[1, 2, 840, 10045, 4, 3, 2],
182 params: SignatureAlgorithmParams::None,
183 };
184
185 pub static PKCS_ECDSA_P384_SHA384: SignatureAlgorithm = SignatureAlgorithm {
187 oids_sign_alg: &[EC_PUBLIC_KEY, EC_SECP_384_R1],
188 #[cfg(feature = "crypto")]
189 sign_alg: SignAlgo::EcDsa(&signature::ECDSA_P384_SHA384_ASN1_SIGNING),
190 oid_components: &[1, 2, 840, 10045, 4, 3, 3],
192 params: SignatureAlgorithmParams::None,
193 };
194 #[cfg(feature = "aws_lc_rs")]
197 pub static PKCS_ECDSA_P521_SHA512: SignatureAlgorithm = SignatureAlgorithm {
198 oids_sign_alg: &[EC_PUBLIC_KEY, EC_SECP_521_R1],
199 #[cfg(feature = "crypto")]
200 sign_alg: SignAlgo::EcDsa(&signature::ECDSA_P521_SHA512_ASN1_SIGNING),
201 oid_components: &[1, 2, 840, 10045, 4, 3, 4],
203 params: SignatureAlgorithmParams::None,
204 };
205
206 pub static PKCS_ED25519: SignatureAlgorithm = SignatureAlgorithm {
208 oids_sign_alg: &[&[1, 3, 101, 112]],
210 #[cfg(feature = "crypto")]
211 sign_alg: SignAlgo::EdDsa(&signature::ED25519),
212 oid_components: &[1, 3, 101, 112],
214 params: SignatureAlgorithmParams::None,
215 };
216
217 #[cfg(all(feature = "aws_lc_rs_unstable", not(feature = "fips")))]
219 pub static PKCS_ML_DSA_44: SignatureAlgorithm = SignatureAlgorithm {
220 oids_sign_alg: &[ML_DSA_44],
221 #[cfg(all(feature = "crypto", feature = "aws_lc_rs_unstable"))]
222 sign_alg: SignAlgo::PqDsa(&ML_DSA_44_SIGNING),
223 oid_components: ML_DSA_44,
224 params: SignatureAlgorithmParams::None,
225 };
226
227 #[cfg(all(feature = "aws_lc_rs_unstable", not(feature = "fips")))]
229 pub static PKCS_ML_DSA_65: SignatureAlgorithm = SignatureAlgorithm {
230 oids_sign_alg: &[ML_DSA_65],
231 #[cfg(all(feature = "crypto", feature = "aws_lc_rs_unstable"))]
232 sign_alg: SignAlgo::PqDsa(&ML_DSA_65_SIGNING),
233 oid_components: ML_DSA_65,
234 params: SignatureAlgorithmParams::None,
235 };
236
237 #[cfg(all(feature = "aws_lc_rs_unstable", not(feature = "fips")))]
239 pub static PKCS_ML_DSA_87: SignatureAlgorithm = SignatureAlgorithm {
240 oids_sign_alg: &[ML_DSA_87],
241 #[cfg(all(feature = "crypto", feature = "aws_lc_rs_unstable"))]
242 sign_alg: SignAlgo::PqDsa(&ML_DSA_87_SIGNING),
243 oid_components: ML_DSA_87,
244 params: SignatureAlgorithmParams::None,
245 };
246}
247impl SignatureAlgorithm {
249 fn alg_ident_oid(&self) -> ObjectIdentifier {
250 ObjectIdentifier::from_slice(self.oid_components)
251 }
252 fn write_params(&self, writer: &mut yasna::DERWriterSeq) {
253 match self.params {
254 SignatureAlgorithmParams::None => (),
255 SignatureAlgorithmParams::Null => {
256 writer.next().write_null();
257 },
258 SignatureAlgorithmParams::RsaPss {
259 hash_algorithm,
260 salt_length,
261 } => {
262 writer.next().write_sequence(|writer| {
263 let oid = ObjectIdentifier::from_slice(hash_algorithm);
266 writer.next().write_tagged(Tag::context(0), |writer| {
268 writer.write_sequence(|writer| {
269 writer.next().write_oid(&oid);
270 });
271 });
272 writer.next().write_tagged(Tag::context(1), |writer| {
274 writer.write_sequence(|writer| {
275 const ID_MGF1: &[u64] = &[1, 2, 840, 113549, 1, 1, 8];
277 let oid = ObjectIdentifier::from_slice(ID_MGF1);
278 writer.next().write_oid(&oid);
279 writer.next().write_sequence(|writer| {
280 let oid = ObjectIdentifier::from_slice(hash_algorithm);
281 writer.next().write_oid(&oid);
282 writer.next().write_null();
283 });
284 });
285 });
286 writer.next().write_tagged(Tag::context(2), |writer| {
288 writer.write_u64(salt_length);
289 });
290 })
292 },
293 }
294 }
295 pub(crate) fn write_alg_ident(&self, writer: DERWriter) {
297 writer.write_sequence(|writer| {
298 writer.next().write_oid(&self.alg_ident_oid());
299 self.write_params(writer);
300 });
301 }
302 pub(crate) fn write_oids_sign_alg(&self, writer: DERWriter) {
304 writer.write_sequence(|writer| {
305 for oid in self.oids_sign_alg {
306 let oid = ObjectIdentifier::from_slice(oid);
307 writer.next().write_oid(&oid);
308 }
309 self.write_params(writer);
310 });
311 }
312}