/rust/registry/src/index.crates.io-1949cf8c6b5b557f/rcgen-0.14.2/src/sign_algo.rs
Line | Count | Source |
1 | | use std::fmt; |
2 | | use std::hash::{Hash, Hasher}; |
3 | | |
4 | | use yasna::models::ObjectIdentifier; |
5 | | use yasna::DERWriter; |
6 | | use yasna::Tag; |
7 | | |
8 | | #[cfg(feature = "crypto")] |
9 | | use crate::ring_like::signature::{self, EcdsaSigningAlgorithm, EdDSAParameters, RsaEncoding}; |
10 | | use crate::Error; |
11 | | |
12 | | #[cfg(feature = "crypto")] |
13 | | #[derive(Clone, Copy, Debug)] |
14 | | pub(crate) enum SignAlgo { |
15 | | EcDsa(&'static EcdsaSigningAlgorithm), |
16 | | EdDsa(&'static EdDSAParameters), |
17 | | Rsa(&'static dyn RsaEncoding), |
18 | | } |
19 | | |
20 | | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] |
21 | | pub(crate) enum SignatureAlgorithmParams { |
22 | | /// Omit the parameters |
23 | | None, |
24 | | /// Write null parameters |
25 | | Null, |
26 | | /// RSASSA-PSS-params as per RFC 4055 |
27 | | RsaPss { |
28 | | hash_algorithm: &'static [u64], |
29 | | salt_length: u64, |
30 | | }, |
31 | | } |
32 | | |
33 | | /// Signature algorithm type |
34 | | #[derive(Clone)] |
35 | | pub struct SignatureAlgorithm { |
36 | | oids_sign_alg: &'static [&'static [u64]], |
37 | | #[cfg(feature = "crypto")] |
38 | | pub(crate) sign_alg: SignAlgo, |
39 | | oid_components: &'static [u64], |
40 | | params: SignatureAlgorithmParams, |
41 | | } |
42 | | |
43 | | impl fmt::Debug for SignatureAlgorithm { |
44 | 0 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
45 | | use algo::*; |
46 | 0 | if self == &PKCS_RSA_SHA256 { |
47 | 0 | write!(f, "PKCS_RSA_SHA256") |
48 | 0 | } else if self == &PKCS_RSA_SHA384 { |
49 | 0 | write!(f, "PKCS_RSA_SHA384") |
50 | 0 | } else if self == &PKCS_RSA_SHA512 { |
51 | 0 | write!(f, "PKCS_RSA_SHA512") |
52 | 0 | } else if self == &PKCS_RSA_PSS_SHA256 { |
53 | 0 | write!(f, "PKCS_RSA_PSS_SHA256") |
54 | 0 | } else if self == &PKCS_ECDSA_P256_SHA256 { |
55 | 0 | write!(f, "PKCS_ECDSA_P256_SHA256") |
56 | 0 | } else if self == &PKCS_ECDSA_P384_SHA384 { |
57 | 0 | write!(f, "PKCS_ECDSA_P384_SHA384") |
58 | 0 | } else if self == &PKCS_ED25519 { |
59 | 0 | write!(f, "PKCS_ED25519") |
60 | | } else { |
61 | | #[cfg(feature = "aws_lc_rs")] |
62 | 0 | if self == &PKCS_ECDSA_P521_SHA512 { |
63 | 0 | return write!(f, "PKCS_ECDSA_P521_SHA512"); |
64 | 0 | } |
65 | | |
66 | 0 | write!(f, "Unknown") |
67 | | } |
68 | 0 | } |
69 | | } |
70 | | |
71 | | impl PartialEq for SignatureAlgorithm { |
72 | 0 | fn eq(&self, other: &Self) -> bool { |
73 | 0 | (self.oids_sign_alg, self.oid_components) == (other.oids_sign_alg, other.oid_components) |
74 | 0 | } |
75 | | } |
76 | | |
77 | | impl Eq for SignatureAlgorithm {} |
78 | | |
79 | | /// The `Hash` trait is not derived, but implemented according to impl of the `PartialEq` trait |
80 | | impl Hash for SignatureAlgorithm { |
81 | 0 | fn hash<H: Hasher>(&self, state: &mut H) { |
82 | | // see SignatureAlgorithm::eq(), just this field is compared |
83 | 0 | self.oids_sign_alg.hash(state); |
84 | 0 | } |
85 | | } |
86 | | impl SignatureAlgorithm { |
87 | 0 | pub(crate) fn iter() -> std::slice::Iter<'static, &'static SignatureAlgorithm> { |
88 | | use algo::*; |
89 | | static ALGORITHMS: &[&SignatureAlgorithm] = &[ |
90 | | &PKCS_RSA_SHA256, |
91 | | &PKCS_RSA_SHA384, |
92 | | &PKCS_RSA_SHA512, |
93 | | //&PKCS_RSA_PSS_SHA256, |
94 | | &PKCS_ECDSA_P256_SHA256, |
95 | | &PKCS_ECDSA_P384_SHA384, |
96 | | #[cfg(feature = "aws_lc_rs")] |
97 | | &PKCS_ECDSA_P521_SHA512, |
98 | | &PKCS_ED25519, |
99 | | ]; |
100 | 0 | ALGORITHMS.iter() |
101 | 0 | } |
102 | | |
103 | | /// Retrieve the SignatureAlgorithm for the provided OID |
104 | 0 | pub fn from_oid(oid: &[u64]) -> Result<&'static SignatureAlgorithm, Error> { |
105 | 0 | for algo in Self::iter() { |
106 | 0 | if algo.oid_components == oid { |
107 | 0 | return Ok(algo); |
108 | 0 | } |
109 | | } |
110 | 0 | Err(Error::UnsupportedSignatureAlgorithm) |
111 | 0 | } |
112 | | } |
113 | | |
114 | | /// The list of supported signature algorithms |
115 | | pub(crate) mod algo { |
116 | | use crate::oid::*; |
117 | | |
118 | | use super::*; |
119 | | |
120 | | /// RSA signing with PKCS#1 1.5 padding and SHA-256 hashing as per [RFC 4055](https://tools.ietf.org/html/rfc4055) |
121 | | pub static PKCS_RSA_SHA256: SignatureAlgorithm = SignatureAlgorithm { |
122 | | oids_sign_alg: &[RSA_ENCRYPTION], |
123 | | #[cfg(feature = "crypto")] |
124 | | sign_alg: SignAlgo::Rsa(&signature::RSA_PKCS1_SHA256), |
125 | | // sha256WithRSAEncryption in RFC 4055 |
126 | | oid_components: &[1, 2, 840, 113549, 1, 1, 11], |
127 | | params: SignatureAlgorithmParams::Null, |
128 | | }; |
129 | | |
130 | | /// RSA signing with PKCS#1 1.5 padding and SHA-256 hashing as per [RFC 4055](https://tools.ietf.org/html/rfc4055) |
131 | | pub static PKCS_RSA_SHA384: SignatureAlgorithm = SignatureAlgorithm { |
132 | | oids_sign_alg: &[RSA_ENCRYPTION], |
133 | | #[cfg(feature = "crypto")] |
134 | | sign_alg: SignAlgo::Rsa(&signature::RSA_PKCS1_SHA384), |
135 | | // sha384WithRSAEncryption in RFC 4055 |
136 | | oid_components: &[1, 2, 840, 113549, 1, 1, 12], |
137 | | params: SignatureAlgorithmParams::Null, |
138 | | }; |
139 | | |
140 | | /// RSA signing with PKCS#1 1.5 padding and SHA-512 hashing as per [RFC 4055](https://tools.ietf.org/html/rfc4055) |
141 | | pub static PKCS_RSA_SHA512: SignatureAlgorithm = SignatureAlgorithm { |
142 | | oids_sign_alg: &[RSA_ENCRYPTION], |
143 | | #[cfg(feature = "crypto")] |
144 | | sign_alg: SignAlgo::Rsa(&signature::RSA_PKCS1_SHA512), |
145 | | // sha512WithRSAEncryption in RFC 4055 |
146 | | oid_components: &[1, 2, 840, 113549, 1, 1, 13], |
147 | | params: SignatureAlgorithmParams::Null, |
148 | | }; |
149 | | |
150 | | // TODO: not really sure whether the certs we generate actually work. |
151 | | // Both openssl and webpki reject them. It *might* be possible that openssl |
152 | | // accepts the certificate if the key is a proper RSA-PSS key, but ring doesn't |
153 | | // support those: https://github.com/briansmith/ring/issues/1353 |
154 | | // |
155 | | /// RSA signing with PKCS#1 2.1 RSASSA-PSS padding and SHA-256 hashing as per [RFC 4055](https://tools.ietf.org/html/rfc4055) |
156 | | pub(crate) static PKCS_RSA_PSS_SHA256: SignatureAlgorithm = SignatureAlgorithm { |
157 | | // We could also use RSA_ENCRYPTION here, but it's recommended |
158 | | // to use ID-RSASSA-PSS if possible. |
159 | | oids_sign_alg: &[RSASSA_PSS], |
160 | | #[cfg(feature = "crypto")] |
161 | | sign_alg: SignAlgo::Rsa(&signature::RSA_PSS_SHA256), |
162 | | oid_components: RSASSA_PSS, //&[1, 2, 840, 113549, 1, 1, 13], |
163 | | // rSASSA-PSS-SHA256-Params in RFC 4055 |
164 | | params: SignatureAlgorithmParams::RsaPss { |
165 | | // id-sha256 in https://datatracker.ietf.org/doc/html/rfc4055#section-2.1 |
166 | | hash_algorithm: &[2, 16, 840, 1, 101, 3, 4, 2, 1], |
167 | | salt_length: 20, |
168 | | }, |
169 | | }; |
170 | | |
171 | | /// ECDSA signing using the P-256 curves and SHA-256 hashing as per [RFC 5758](https://tools.ietf.org/html/rfc5758#section-3.2) |
172 | | pub static PKCS_ECDSA_P256_SHA256: SignatureAlgorithm = SignatureAlgorithm { |
173 | | oids_sign_alg: &[EC_PUBLIC_KEY, EC_SECP_256_R1], |
174 | | #[cfg(feature = "crypto")] |
175 | | sign_alg: SignAlgo::EcDsa(&signature::ECDSA_P256_SHA256_ASN1_SIGNING), |
176 | | // ecdsa-with-SHA256 in RFC 5758 |
177 | | oid_components: &[1, 2, 840, 10045, 4, 3, 2], |
178 | | params: SignatureAlgorithmParams::None, |
179 | | }; |
180 | | |
181 | | /// ECDSA signing using the P-384 curves and SHA-384 hashing as per [RFC 5758](https://tools.ietf.org/html/rfc5758#section-3.2) |
182 | | pub static PKCS_ECDSA_P384_SHA384: SignatureAlgorithm = SignatureAlgorithm { |
183 | | oids_sign_alg: &[EC_PUBLIC_KEY, EC_SECP_384_R1], |
184 | | #[cfg(feature = "crypto")] |
185 | | sign_alg: SignAlgo::EcDsa(&signature::ECDSA_P384_SHA384_ASN1_SIGNING), |
186 | | // ecdsa-with-SHA384 in RFC 5758 |
187 | | oid_components: &[1, 2, 840, 10045, 4, 3, 3], |
188 | | params: SignatureAlgorithmParams::None, |
189 | | }; |
190 | | /// ECDSA signing using the P-521 curves and SHA-512 hashing as per [RFC 5758](https://tools.ietf.org/html/rfc5758#section-3.2) |
191 | | /// Currently this is only supported with the `aws_lc_rs` feature |
192 | | #[cfg(feature = "aws_lc_rs")] |
193 | | pub static PKCS_ECDSA_P521_SHA512: SignatureAlgorithm = SignatureAlgorithm { |
194 | | oids_sign_alg: &[EC_PUBLIC_KEY, EC_SECP_521_R1], |
195 | | #[cfg(feature = "crypto")] |
196 | | sign_alg: SignAlgo::EcDsa(&signature::ECDSA_P521_SHA512_ASN1_SIGNING), |
197 | | // ecdsa-with-SHA512 in RFC 5758 |
198 | | oid_components: &[1, 2, 840, 10045, 4, 3, 4], |
199 | | params: SignatureAlgorithmParams::None, |
200 | | }; |
201 | | |
202 | | /// ED25519 curve signing as per [RFC 8410](https://tools.ietf.org/html/rfc8410) |
203 | | pub static PKCS_ED25519: SignatureAlgorithm = SignatureAlgorithm { |
204 | | // id-Ed25519 in RFC 8410 |
205 | | oids_sign_alg: &[&[1, 3, 101, 112]], |
206 | | #[cfg(feature = "crypto")] |
207 | | sign_alg: SignAlgo::EdDsa(&signature::ED25519), |
208 | | // id-Ed25519 in RFC 8410 |
209 | | oid_components: &[1, 3, 101, 112], |
210 | | params: SignatureAlgorithmParams::None, |
211 | | }; |
212 | | } |
213 | | // Signature algorithm IDs as per https://tools.ietf.org/html/rfc4055 |
214 | | impl SignatureAlgorithm { |
215 | 0 | fn alg_ident_oid(&self) -> ObjectIdentifier { |
216 | 0 | ObjectIdentifier::from_slice(self.oid_components) |
217 | 0 | } |
218 | 0 | fn write_params(&self, writer: &mut yasna::DERWriterSeq) { |
219 | 0 | match self.params { |
220 | 0 | SignatureAlgorithmParams::None => (), |
221 | 0 | SignatureAlgorithmParams::Null => { |
222 | 0 | writer.next().write_null(); |
223 | 0 | }, |
224 | | SignatureAlgorithmParams::RsaPss { |
225 | 0 | hash_algorithm, |
226 | 0 | salt_length, |
227 | | } => { |
228 | 0 | writer.next().write_sequence(|writer| { |
229 | | // https://datatracker.ietf.org/doc/html/rfc4055#section-3.1 |
230 | | |
231 | 0 | let oid = ObjectIdentifier::from_slice(hash_algorithm); |
232 | | // hashAlgorithm |
233 | 0 | writer.next().write_tagged(Tag::context(0), |writer| { |
234 | 0 | writer.write_sequence(|writer| { |
235 | 0 | writer.next().write_oid(&oid); |
236 | 0 | }); |
237 | 0 | }); |
238 | | // maskGenAlgorithm |
239 | 0 | writer.next().write_tagged(Tag::context(1), |writer| { |
240 | 0 | writer.write_sequence(|writer| { |
241 | | // id-mgf1 in RFC 4055 |
242 | | const ID_MGF1: &[u64] = &[1, 2, 840, 113549, 1, 1, 8]; |
243 | 0 | let oid = ObjectIdentifier::from_slice(ID_MGF1); |
244 | 0 | writer.next().write_oid(&oid); |
245 | 0 | writer.next().write_sequence(|writer| { |
246 | 0 | let oid = ObjectIdentifier::from_slice(hash_algorithm); |
247 | 0 | writer.next().write_oid(&oid); |
248 | 0 | writer.next().write_null(); |
249 | 0 | }); |
250 | 0 | }); |
251 | 0 | }); |
252 | | // saltLength |
253 | 0 | writer.next().write_tagged(Tag::context(2), |writer| { |
254 | 0 | writer.write_u64(salt_length); |
255 | 0 | }); |
256 | | // We *must* omit the trailerField element as per RFC 4055 section 3.1 |
257 | 0 | }) |
258 | | }, |
259 | | } |
260 | 0 | } |
261 | | /// Writes the algorithm identifier as it appears inside a signature |
262 | 0 | pub(crate) fn write_alg_ident(&self, writer: DERWriter) { |
263 | 0 | writer.write_sequence(|writer| { |
264 | 0 | writer.next().write_oid(&self.alg_ident_oid()); |
265 | 0 | self.write_params(writer); |
266 | 0 | }); |
267 | 0 | } |
268 | | /// Writes the algorithm identifier as it appears inside subjectPublicKeyInfo |
269 | 0 | pub(crate) fn write_oids_sign_alg(&self, writer: DERWriter) { |
270 | 0 | writer.write_sequence(|writer| { |
271 | 0 | for oid in self.oids_sign_alg { |
272 | 0 | let oid = ObjectIdentifier::from_slice(oid); |
273 | 0 | writer.next().write_oid(&oid); |
274 | 0 | } |
275 | 0 | self.write_params(writer); |
276 | 0 | }); |
277 | 0 | } |
278 | | } |