1use std::fmt;
2use std::hash::{Hash, Hasher};
3
4use yasna::models::ObjectIdentifier;
5use yasna::DERWriter;
6use yasna::Tag;
7
8#[cfg(feature = "crypto")]
9use crate::ring_like::signature::{self, EcdsaSigningAlgorithm, EdDSAParameters, RsaEncoding};
10use crate::Error;
11
12#[cfg(feature = "crypto")]
13pub(crate) enum SignAlgo {
14 EcDsa(&'static EcdsaSigningAlgorithm),
15 EdDsa(&'static EdDSAParameters),
16 Rsa(&'static dyn RsaEncoding),
17}
18
19#[derive(PartialEq, Eq, Hash)]
20pub(crate) enum SignatureAlgorithmParams {
21 None,
23 Null,
25 RsaPss {
27 hash_algorithm: &'static [u64],
28 salt_length: u64,
29 },
30}
31
32pub struct SignatureAlgorithm {
34 oids_sign_alg: &'static [&'static [u64]],
35 #[cfg(feature = "crypto")]
36 pub(crate) sign_alg: SignAlgo,
37 oid_components: &'static [u64],
38 params: SignatureAlgorithmParams,
39}
40
41impl fmt::Debug for SignatureAlgorithm {
42 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
43 use algo::*;
44 if self == &PKCS_RSA_SHA256 {
45 write!(f, "PKCS_RSA_SHA256")
46 } else if self == &PKCS_RSA_SHA384 {
47 write!(f, "PKCS_RSA_SHA384")
48 } else if self == &PKCS_RSA_SHA512 {
49 write!(f, "PKCS_RSA_SHA512")
50 } else if self == &PKCS_RSA_PSS_SHA256 {
51 write!(f, "PKCS_RSA_PSS_SHA256")
52 } else if self == &PKCS_ECDSA_P256_SHA256 {
53 write!(f, "PKCS_ECDSA_P256_SHA256")
54 } else if self == &PKCS_ECDSA_P384_SHA384 {
55 write!(f, "PKCS_ECDSA_P384_SHA384")
56 } else if self == &PKCS_ED25519 {
57 write!(f, "PKCS_ED25519")
58 } else {
59 #[cfg(feature = "aws_lc_rs")]
60 if self == &PKCS_ECDSA_P521_SHA512 {
61 return write!(f, "PKCS_ECDSA_P521_SHA512");
62 }
63
64 write!(f, "Unknown")
65 }
66 }
67}
68
69impl PartialEq for SignatureAlgorithm {
70 fn eq(&self, other: &Self) -> bool {
71 (self.oids_sign_alg, self.oid_components) == (other.oids_sign_alg, other.oid_components)
72 }
73}
74
75impl Eq for SignatureAlgorithm {}
76
77impl Hash for SignatureAlgorithm {
79 fn hash<H: Hasher>(&self, state: &mut H) {
80 self.oids_sign_alg.hash(state);
82 }
83}
84impl SignatureAlgorithm {
85 pub(crate) fn iter() -> std::slice::Iter<'static, &'static SignatureAlgorithm> {
86 use algo::*;
87 static ALGORITHMS: &[&SignatureAlgorithm] = &[
88 &PKCS_RSA_SHA256,
89 &PKCS_RSA_SHA384,
90 &PKCS_RSA_SHA512,
91 &PKCS_ECDSA_P256_SHA256,
93 &PKCS_ECDSA_P384_SHA384,
94 #[cfg(feature = "aws_lc_rs")]
95 &PKCS_ECDSA_P521_SHA512,
96 &PKCS_ED25519,
97 ];
98 ALGORITHMS.iter()
99 }
100
101 pub fn from_oid(oid: &[u64]) -> Result<&'static SignatureAlgorithm, Error> {
103 for algo in Self::iter() {
104 if algo.oid_components == oid {
105 return Ok(algo);
106 }
107 }
108 Err(Error::UnsupportedSignatureAlgorithm)
109 }
110}
111
112pub(crate) mod algo {
114 use crate::oid::*;
115
116 use super::*;
117
118 pub static PKCS_RSA_SHA256: SignatureAlgorithm = SignatureAlgorithm {
120 oids_sign_alg: &[&RSA_ENCRYPTION],
121 #[cfg(feature = "crypto")]
122 sign_alg: SignAlgo::Rsa(&signature::RSA_PKCS1_SHA256),
123 oid_components: &[1, 2, 840, 113549, 1, 1, 11],
125 params: SignatureAlgorithmParams::Null,
126 };
127
128 pub static PKCS_RSA_SHA384: SignatureAlgorithm = SignatureAlgorithm {
130 oids_sign_alg: &[&RSA_ENCRYPTION],
131 #[cfg(feature = "crypto")]
132 sign_alg: SignAlgo::Rsa(&signature::RSA_PKCS1_SHA384),
133 oid_components: &[1, 2, 840, 113549, 1, 1, 12],
135 params: SignatureAlgorithmParams::Null,
136 };
137
138 pub static PKCS_RSA_SHA512: SignatureAlgorithm = SignatureAlgorithm {
140 oids_sign_alg: &[&RSA_ENCRYPTION],
141 #[cfg(feature = "crypto")]
142 sign_alg: SignAlgo::Rsa(&signature::RSA_PKCS1_SHA512),
143 oid_components: &[1, 2, 840, 113549, 1, 1, 13],
145 params: SignatureAlgorithmParams::Null,
146 };
147
148 pub(crate) static PKCS_RSA_PSS_SHA256: SignatureAlgorithm = SignatureAlgorithm {
155 oids_sign_alg: &[&RSASSA_PSS],
158 #[cfg(feature = "crypto")]
159 sign_alg: SignAlgo::Rsa(&signature::RSA_PSS_SHA256),
160 oid_components: RSASSA_PSS, params: SignatureAlgorithmParams::RsaPss {
163 hash_algorithm: &[2, 16, 840, 1, 101, 3, 4, 2, 1],
165 salt_length: 20,
166 },
167 };
168
169 pub static PKCS_ECDSA_P256_SHA256: SignatureAlgorithm = SignatureAlgorithm {
171 oids_sign_alg: &[&EC_PUBLIC_KEY, &EC_SECP_256_R1],
172 #[cfg(feature = "crypto")]
173 sign_alg: SignAlgo::EcDsa(&signature::ECDSA_P256_SHA256_ASN1_SIGNING),
174 oid_components: &[1, 2, 840, 10045, 4, 3, 2],
176 params: SignatureAlgorithmParams::None,
177 };
178
179 pub static PKCS_ECDSA_P384_SHA384: SignatureAlgorithm = SignatureAlgorithm {
181 oids_sign_alg: &[&EC_PUBLIC_KEY, &EC_SECP_384_R1],
182 #[cfg(feature = "crypto")]
183 sign_alg: SignAlgo::EcDsa(&signature::ECDSA_P384_SHA384_ASN1_SIGNING),
184 oid_components: &[1, 2, 840, 10045, 4, 3, 3],
186 params: SignatureAlgorithmParams::None,
187 };
188 #[cfg(feature = "aws_lc_rs")]
191 pub static PKCS_ECDSA_P521_SHA512: SignatureAlgorithm = SignatureAlgorithm {
192 oids_sign_alg: &[&EC_PUBLIC_KEY, &EC_SECP_521_R1],
193 #[cfg(feature = "crypto")]
194 sign_alg: SignAlgo::EcDsa(&signature::ECDSA_P521_SHA512_ASN1_SIGNING),
195 oid_components: &[1, 2, 840, 10045, 4, 3, 4],
197 params: SignatureAlgorithmParams::None,
198 };
199
200 pub static PKCS_ED25519: SignatureAlgorithm = SignatureAlgorithm {
202 oids_sign_alg: &[&[1, 3, 101, 112]],
204 #[cfg(feature = "crypto")]
205 sign_alg: SignAlgo::EdDsa(&signature::ED25519),
206 oid_components: &[1, 3, 101, 112],
208 params: SignatureAlgorithmParams::None,
209 };
210}
211impl SignatureAlgorithm {
213 fn alg_ident_oid(&self) -> ObjectIdentifier {
214 ObjectIdentifier::from_slice(self.oid_components)
215 }
216 fn write_params(&self, writer: &mut yasna::DERWriterSeq) {
217 match self.params {
218 SignatureAlgorithmParams::None => (),
219 SignatureAlgorithmParams::Null => {
220 writer.next().write_null();
221 },
222 SignatureAlgorithmParams::RsaPss {
223 hash_algorithm,
224 salt_length,
225 } => {
226 writer.next().write_sequence(|writer| {
227 let oid = ObjectIdentifier::from_slice(hash_algorithm);
230 writer.next().write_tagged(Tag::context(0), |writer| {
232 writer.write_sequence(|writer| {
233 writer.next().write_oid(&oid);
234 });
235 });
236 writer.next().write_tagged(Tag::context(1), |writer| {
238 writer.write_sequence(|writer| {
239 const ID_MGF1: &[u64] = &[1, 2, 840, 113549, 1, 1, 8];
241 let oid = ObjectIdentifier::from_slice(ID_MGF1);
242 writer.next().write_oid(&oid);
243 writer.next().write_sequence(|writer| {
244 let oid = ObjectIdentifier::from_slice(hash_algorithm);
245 writer.next().write_oid(&oid);
246 writer.next().write_null();
247 });
248 });
249 });
250 writer.next().write_tagged(Tag::context(2), |writer| {
252 writer.write_u64(salt_length);
253 });
254 })
256 },
257 }
258 }
259 pub(crate) fn write_alg_ident(&self, writer: DERWriter) {
261 writer.write_sequence(|writer| {
262 writer.next().write_oid(&self.alg_ident_oid());
263 self.write_params(writer);
264 });
265 }
266 pub(crate) fn write_oids_sign_alg(&self, writer: DERWriter) {
268 writer.write_sequence(|writer| {
269 for oid in self.oids_sign_alg {
270 let oid = ObjectIdentifier::from_slice(oid);
271 writer.next().write_oid(&oid);
272 }
273 self.write_params(writer);
274 });
275 }
276}