1 // Copyright 2015 Brian Smith.
2 //
3 // Permission to use, copy, modify, and/or distribute this software for any
4 // purpose with or without fee is hereby granted, provided that the above
5 // copyright notice and this permission notice appear in all copies.
6 //
7 // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
8 // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
10 // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
12 // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
13 // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14 
15 use crate::{der, equal, Error};
16 use ring::signature;
17 
18 /// X.509 certificates and related items that are signed are almost always
19 /// encoded in the format "tbs||signatureAlgorithm||signature". This structure
20 /// captures this pattern.
21 pub struct SignedData<'a> {
22     /// The signed data. This would be `tbsCertificate` in the case of an X.509
23     /// certificate, `tbsResponseData` in the case of an OCSP response, and the
24     /// data nested in the `digitally-signed` construct for TLS 1.2 signed
25     /// data.
26     data: untrusted::Input<'a>,
27 
28     /// The value of the `AlgorithmIdentifier`. This would be
29     /// `signatureAlgorithm` in the case of an X.509 certificate or OCSP
30     /// response. This would have to be synthesized in the case of TLS 1.2
31     /// signed data, since TLS does not identify algorithms by ASN.1 OIDs.
32     pub(crate) algorithm: untrusted::Input<'a>,
33 
34     /// The value of the signature. This would be `signature` in an X.509
35     /// certificate or OCSP response. This would be the value of
36     /// `DigitallySigned.signature` for TLS 1.2 signed data.
37     signature: untrusted::Input<'a>,
38 }
39 
40 /// Parses the concatenation of "tbs||signatureAlgorithm||signature" that
41 /// is common in the X.509 certificate and OCSP response syntaxes.
42 ///
43 /// X.509 Certificates (RFC 5280) look like this:
44 ///
45 /// ```ASN.1
46 /// Certificate (SEQUENCE) {
47 ///     tbsCertificate TBSCertificate,
48 ///     signatureAlgorithm AlgorithmIdentifier,
49 ///     signatureValue BIT STRING
50 /// }
51 /// ```
52 ///
53 /// OCSP responses (RFC 6960) look like this:
54 /// ```ASN.1
55 /// BasicOCSPResponse {
56 ///     tbsResponseData ResponseData,
57 ///     signatureAlgorithm AlgorithmIdentifier,
58 ///     signature BIT STRING,
59 ///     certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL
60 /// }
61 /// ```
62 ///
63 /// Note that this function does NOT parse the outermost `SEQUENCE` or the
64 /// `certs` value.
65 ///
66 /// The return value's first component is the contents of
67 /// `tbsCertificate`/`tbsResponseData`; the second component is a `SignedData`
68 /// structure that can be passed to `verify_signed_data`.
parse_signed_data<'a>( der: &mut untrusted::Reader<'a>, ) -> Result<(untrusted::Input<'a>, SignedData<'a>), Error>69 pub(crate) fn parse_signed_data<'a>(
70     der: &mut untrusted::Reader<'a>,
71 ) -> Result<(untrusted::Input<'a>, SignedData<'a>), Error> {
72     let (data, tbs) =
73         der.read_partial(|input| der::expect_tag_and_get_value(input, der::Tag::Sequence))?;
74     let algorithm = der::expect_tag_and_get_value(der, der::Tag::Sequence)?;
75     let signature = der::bit_string_with_no_unused_bits(der)?;
76 
77     Ok((
78         tbs,
79         SignedData {
80             data,
81             algorithm,
82             signature,
83         },
84     ))
85 }
86 
87 /// Verify `signed_data` using the public key in the DER-encoded
88 /// SubjectPublicKeyInfo `spki` using one of the algorithms in
89 /// `supported_algorithms`.
90 ///
91 /// The algorithm is chosen based on the algorithm information encoded in the
92 /// algorithm identifiers in `public_key` and `signed_data.algorithm`. The
93 /// ordering of the algorithms in `supported_algorithms` does not really matter,
94 /// but generally more common algorithms should go first, as it is scanned
95 /// linearly for matches.
verify_signed_data( supported_algorithms: &[&SignatureAlgorithm], spki_value: untrusted::Input, signed_data: &SignedData, ) -> Result<(), Error>96 pub(crate) fn verify_signed_data(
97     supported_algorithms: &[&SignatureAlgorithm],
98     spki_value: untrusted::Input,
99     signed_data: &SignedData,
100 ) -> Result<(), Error> {
101     // We need to verify the signature in `signed_data` using the public key
102     // in `public_key`. In order to know which *ring* signature verification
103     // algorithm to use, we need to know the public key algorithm (ECDSA,
104     // RSA PKCS#1, etc.), the curve (if applicable), and the digest algorithm.
105     // `signed_data` identifies only the public key algorithm and the digest
106     // algorithm, and `public_key` identifies only the public key algorithm and
107     // the curve (if any). Thus, we have to combine information from both
108     // inputs to figure out which `ring::signature::VerificationAlgorithm` to
109     // use to verify the signature.
110     //
111     // This is all further complicated by the fact that we don't have any
112     // implicit knowledge about any algorithms or identifiers, since all of
113     // that information is encoded in `supported_algorithms.` In particular, we
114     // avoid hard-coding any of that information so that (link-time) dead code
115     // elimination will work effectively in eliminating code for unused
116     // algorithms.
117 
118     // Parse the signature.
119     //
120     let mut found_signature_alg_match = false;
121     for supported_alg in supported_algorithms.iter().filter(|alg| {
122         alg.signature_alg_id
123             .matches_algorithm_id_value(signed_data.algorithm)
124     }) {
125         match verify_signature(
126             supported_alg,
127             spki_value,
128             signed_data.data,
129             signed_data.signature,
130         ) {
131             Err(Error::UnsupportedSignatureAlgorithmForPublicKey) => {
132                 found_signature_alg_match = true;
133                 continue;
134             }
135             result => {
136                 return result;
137             }
138         }
139     }
140 
141     if found_signature_alg_match {
142         Err(Error::UnsupportedSignatureAlgorithmForPublicKey)
143     } else {
144         Err(Error::UnsupportedSignatureAlgorithm)
145     }
146 }
147 
verify_signature( signature_alg: &SignatureAlgorithm, spki_value: untrusted::Input, msg: untrusted::Input, signature: untrusted::Input, ) -> Result<(), Error>148 pub(crate) fn verify_signature(
149     signature_alg: &SignatureAlgorithm,
150     spki_value: untrusted::Input,
151     msg: untrusted::Input,
152     signature: untrusted::Input,
153 ) -> Result<(), Error> {
154     let spki = parse_spki_value(spki_value)?;
155     if !signature_alg
156         .public_key_alg_id
157         .matches_algorithm_id_value(spki.algorithm_id_value)
158     {
159         return Err(Error::UnsupportedSignatureAlgorithmForPublicKey);
160     }
161     signature::UnparsedPublicKey::new(
162         signature_alg.verification_alg,
163         spki.key_value.as_slice_less_safe(),
164     )
165     .verify(msg.as_slice_less_safe(), signature.as_slice_less_safe())
166     .map_err(|_| Error::InvalidSignatureForPublicKey)
167 }
168 
169 struct SubjectPublicKeyInfo<'a> {
170     algorithm_id_value: untrusted::Input<'a>,
171     key_value: untrusted::Input<'a>,
172 }
173 
174 // Parse the public key into an algorithm OID, an optional curve OID, and the
175 // key value. The caller needs to check whether these match the
176 // `PublicKeyAlgorithm` for the `SignatureAlgorithm` that is matched when
177 // parsing the signature.
parse_spki_value(input: untrusted::Input) -> Result<SubjectPublicKeyInfo, Error>178 fn parse_spki_value(input: untrusted::Input) -> Result<SubjectPublicKeyInfo, Error> {
179     input.read_all(Error::BadDer, |input| {
180         let algorithm_id_value = der::expect_tag_and_get_value(input, der::Tag::Sequence)?;
181         let key_value = der::bit_string_with_no_unused_bits(input)?;
182         Ok(SubjectPublicKeyInfo {
183             algorithm_id_value,
184             key_value,
185         })
186     })
187 }
188 
189 /// A signature algorithm.
190 pub struct SignatureAlgorithm {
191     public_key_alg_id: AlgorithmIdentifier,
192     signature_alg_id: AlgorithmIdentifier,
193     verification_alg: &'static dyn signature::VerificationAlgorithm,
194 }
195 
196 /// ECDSA signatures using the P-256 curve and SHA-256.
197 pub static ECDSA_P256_SHA256: SignatureAlgorithm = SignatureAlgorithm {
198     public_key_alg_id: ECDSA_P256,
199     signature_alg_id: ECDSA_SHA256,
200     verification_alg: &signature::ECDSA_P256_SHA256_ASN1,
201 };
202 
203 /// ECDSA signatures using the P-256 curve and SHA-384. Deprecated.
204 pub static ECDSA_P256_SHA384: SignatureAlgorithm = SignatureAlgorithm {
205     public_key_alg_id: ECDSA_P256,
206     signature_alg_id: ECDSA_SHA384,
207     verification_alg: &signature::ECDSA_P256_SHA384_ASN1,
208 };
209 
210 /// ECDSA signatures using the P-384 curve and SHA-256. Deprecated.
211 pub static ECDSA_P384_SHA256: SignatureAlgorithm = SignatureAlgorithm {
212     public_key_alg_id: ECDSA_P384,
213     signature_alg_id: ECDSA_SHA256,
214     verification_alg: &signature::ECDSA_P384_SHA256_ASN1,
215 };
216 
217 /// ECDSA signatures using the P-384 curve and SHA-384.
218 pub static ECDSA_P384_SHA384: SignatureAlgorithm = SignatureAlgorithm {
219     public_key_alg_id: ECDSA_P384,
220     signature_alg_id: ECDSA_SHA384,
221     verification_alg: &signature::ECDSA_P384_SHA384_ASN1,
222 };
223 
224 /// RSA PKCS#1 1.5 signatures using SHA-256 for keys of 2048-8192 bits.
225 ///
226 /// Requires the `alloc` feature.
227 #[cfg(feature = "alloc")]
228 pub static RSA_PKCS1_2048_8192_SHA256: SignatureAlgorithm = SignatureAlgorithm {
229     public_key_alg_id: RSA_ENCRYPTION,
230     signature_alg_id: RSA_PKCS1_SHA256,
231     verification_alg: &signature::RSA_PKCS1_2048_8192_SHA256,
232 };
233 
234 /// RSA PKCS#1 1.5 signatures using SHA-384 for keys of 2048-8192 bits.
235 ///
236 /// Requires the `alloc` feature.
237 #[cfg(feature = "alloc")]
238 pub static RSA_PKCS1_2048_8192_SHA384: SignatureAlgorithm = SignatureAlgorithm {
239     public_key_alg_id: RSA_ENCRYPTION,
240     signature_alg_id: RSA_PKCS1_SHA384,
241     verification_alg: &signature::RSA_PKCS1_2048_8192_SHA384,
242 };
243 
244 /// RSA PKCS#1 1.5 signatures using SHA-512 for keys of 2048-8192 bits.
245 ///
246 /// Requires the `alloc` feature.
247 #[cfg(feature = "alloc")]
248 pub static RSA_PKCS1_2048_8192_SHA512: SignatureAlgorithm = SignatureAlgorithm {
249     public_key_alg_id: RSA_ENCRYPTION,
250     signature_alg_id: RSA_PKCS1_SHA512,
251     verification_alg: &signature::RSA_PKCS1_2048_8192_SHA512,
252 };
253 
254 /// RSA PKCS#1 1.5 signatures using SHA-384 for keys of 3072-8192 bits.
255 ///
256 /// Requires the `alloc` feature.
257 #[cfg(feature = "alloc")]
258 pub static RSA_PKCS1_3072_8192_SHA384: SignatureAlgorithm = SignatureAlgorithm {
259     public_key_alg_id: RSA_ENCRYPTION,
260     signature_alg_id: RSA_PKCS1_SHA384,
261     verification_alg: &signature::RSA_PKCS1_3072_8192_SHA384,
262 };
263 
264 /// RSA PSS signatures using SHA-256 for keys of 2048-8192 bits and of
265 /// type rsaEncryption; see [RFC 4055 Section 1.2].
266 ///
267 /// [RFC 4055 Section 1.2]: https://tools.ietf.org/html/rfc4055#section-1.2
268 ///
269 /// Requires the `alloc` feature.
270 #[cfg(feature = "alloc")]
271 pub static RSA_PSS_2048_8192_SHA256_LEGACY_KEY: SignatureAlgorithm = SignatureAlgorithm {
272     public_key_alg_id: RSA_ENCRYPTION,
273     signature_alg_id: RSA_PSS_SHA256,
274     verification_alg: &signature::RSA_PSS_2048_8192_SHA256,
275 };
276 
277 /// RSA PSS signatures using SHA-384 for keys of 2048-8192 bits and of
278 /// type rsaEncryption; see [RFC 4055 Section 1.2].
279 ///
280 /// [RFC 4055 Section 1.2]: https://tools.ietf.org/html/rfc4055#section-1.2
281 ///
282 /// Requires the `alloc` feature.
283 #[cfg(feature = "alloc")]
284 pub static RSA_PSS_2048_8192_SHA384_LEGACY_KEY: SignatureAlgorithm = SignatureAlgorithm {
285     public_key_alg_id: RSA_ENCRYPTION,
286     signature_alg_id: RSA_PSS_SHA384,
287     verification_alg: &signature::RSA_PSS_2048_8192_SHA384,
288 };
289 
290 /// RSA PSS signatures using SHA-512 for keys of 2048-8192 bits and of
291 /// type rsaEncryption; see [RFC 4055 Section 1.2].
292 ///
293 /// [RFC 4055 Section 1.2]: https://tools.ietf.org/html/rfc4055#section-1.2
294 ///
295 /// Requires the `alloc` feature.
296 #[cfg(feature = "alloc")]
297 pub static RSA_PSS_2048_8192_SHA512_LEGACY_KEY: SignatureAlgorithm = SignatureAlgorithm {
298     public_key_alg_id: RSA_ENCRYPTION,
299     signature_alg_id: RSA_PSS_SHA512,
300     verification_alg: &signature::RSA_PSS_2048_8192_SHA512,
301 };
302 
303 /// ED25519 signatures according to RFC 8410
304 pub static ED25519: SignatureAlgorithm = SignatureAlgorithm {
305     public_key_alg_id: ED_25519,
306     signature_alg_id: ED_25519,
307     verification_alg: &signature::ED25519,
308 };
309 
310 struct AlgorithmIdentifier {
311     asn1_id_value: untrusted::Input<'static>,
312 }
313 
314 impl AlgorithmIdentifier {
matches_algorithm_id_value(&self, encoded: untrusted::Input) -> bool315     fn matches_algorithm_id_value(&self, encoded: untrusted::Input) -> bool {
316         equal(encoded, self.asn1_id_value)
317     }
318 }
319 
320 // See src/data/README.md.
321 
322 const ECDSA_P256: AlgorithmIdentifier = AlgorithmIdentifier {
323     asn1_id_value: untrusted::Input::from(include_bytes!("data/alg-ecdsa-p256.der")),
324 };
325 
326 const ECDSA_P384: AlgorithmIdentifier = AlgorithmIdentifier {
327     asn1_id_value: untrusted::Input::from(include_bytes!("data/alg-ecdsa-p384.der")),
328 };
329 
330 const ECDSA_SHA256: AlgorithmIdentifier = AlgorithmIdentifier {
331     asn1_id_value: untrusted::Input::from(include_bytes!("data/alg-ecdsa-sha256.der")),
332 };
333 
334 const ECDSA_SHA384: AlgorithmIdentifier = AlgorithmIdentifier {
335     asn1_id_value: untrusted::Input::from(include_bytes!("data/alg-ecdsa-sha384.der")),
336 };
337 
338 #[cfg(feature = "alloc")]
339 const RSA_ENCRYPTION: AlgorithmIdentifier = AlgorithmIdentifier {
340     asn1_id_value: untrusted::Input::from(include_bytes!("data/alg-rsa-encryption.der")),
341 };
342 
343 #[cfg(feature = "alloc")]
344 const RSA_PKCS1_SHA256: AlgorithmIdentifier = AlgorithmIdentifier {
345     asn1_id_value: untrusted::Input::from(include_bytes!("data/alg-rsa-pkcs1-sha256.der")),
346 };
347 
348 #[cfg(feature = "alloc")]
349 const RSA_PKCS1_SHA384: AlgorithmIdentifier = AlgorithmIdentifier {
350     asn1_id_value: untrusted::Input::from(include_bytes!("data/alg-rsa-pkcs1-sha384.der")),
351 };
352 
353 #[cfg(feature = "alloc")]
354 const RSA_PKCS1_SHA512: AlgorithmIdentifier = AlgorithmIdentifier {
355     asn1_id_value: untrusted::Input::from(include_bytes!("data/alg-rsa-pkcs1-sha512.der")),
356 };
357 
358 #[cfg(feature = "alloc")]
359 const RSA_PSS_SHA256: AlgorithmIdentifier = AlgorithmIdentifier {
360     asn1_id_value: untrusted::Input::from(include_bytes!("data/alg-rsa-pss-sha256.der")),
361 };
362 
363 #[cfg(feature = "alloc")]
364 const RSA_PSS_SHA384: AlgorithmIdentifier = AlgorithmIdentifier {
365     asn1_id_value: untrusted::Input::from(include_bytes!("data/alg-rsa-pss-sha384.der")),
366 };
367 
368 #[cfg(feature = "alloc")]
369 const RSA_PSS_SHA512: AlgorithmIdentifier = AlgorithmIdentifier {
370     asn1_id_value: untrusted::Input::from(include_bytes!("data/alg-rsa-pss-sha512.der")),
371 };
372 
373 const ED_25519: AlgorithmIdentifier = AlgorithmIdentifier {
374     asn1_id_value: untrusted::Input::from(include_bytes!("data/alg-ed25519.der")),
375 };
376 
377 #[cfg(test)]
378 mod tests {
379     use crate::{der, signed_data, Error};
380     use alloc::{string::String, vec::Vec};
381 
382     macro_rules! test_file_bytes {
383         ( $file_name:expr ) => {
384             include_bytes!(concat!(
385                 "../third-party/chromium/data/verify_signed_data/",
386                 $file_name
387             ))
388         };
389     }
390 
391     // TODO: The expected results need to be modified for SHA-1 deprecation.
392 
393     macro_rules! test_verify_signed_data {
394         ($fn_name:ident, $file_name:expr, $expected_result:expr) => {
395             #[test]
396             fn $fn_name() {
397                 test_verify_signed_data(test_file_bytes!($file_name), $expected_result);
398             }
399         };
400     }
401 
test_verify_signed_data(file_contents: &[u8], expected_result: Result<(), Error>)402     fn test_verify_signed_data(file_contents: &[u8], expected_result: Result<(), Error>) {
403         let tsd = parse_test_signed_data(file_contents);
404         let spki_value = untrusted::Input::from(&tsd.spki);
405         let spki_value = spki_value
406             .read_all(Error::BadDer, |input| {
407                 der::expect_tag_and_get_value(input, der::Tag::Sequence)
408             })
409             .unwrap();
410 
411         // we can't use `parse_signed_data` because it requires `data`
412         // to be an ASN.1 SEQUENCE, and that isn't the case with
413         // Chromium's test data. TODO: The test data set should be
414         // expanded with SEQUENCE-wrapped data so that we can actually
415         // test `parse_signed_data`.
416 
417         let algorithm = untrusted::Input::from(&tsd.algorithm);
418         let algorithm = algorithm
419             .read_all(Error::BadDer, |input| {
420                 der::expect_tag_and_get_value(input, der::Tag::Sequence)
421             })
422             .unwrap();
423 
424         let signature = untrusted::Input::from(&tsd.signature);
425         let signature = signature
426             .read_all(Error::BadDer, |input| {
427                 der::bit_string_with_no_unused_bits(input)
428             })
429             .unwrap();
430 
431         let signed_data = signed_data::SignedData {
432             data: untrusted::Input::from(&tsd.data),
433             algorithm,
434             signature,
435         };
436 
437         assert_eq!(
438             expected_result,
439             signed_data::verify_signed_data(
440                 SUPPORTED_ALGORITHMS_IN_TESTS,
441                 spki_value,
442                 &signed_data
443             )
444         );
445     }
446 
447     // XXX: This is testing code that isn't even in this module.
448     macro_rules! test_verify_signed_data_signature_outer {
449         ($fn_name:ident, $file_name:expr, $expected_result:expr) => {
450             #[test]
451             fn $fn_name() {
452                 test_verify_signed_data_signature_outer(
453                     test_file_bytes!($file_name),
454                     $expected_result,
455                 );
456             }
457         };
458     }
459 
test_verify_signed_data_signature_outer(file_contents: &[u8], expected_error: Error)460     fn test_verify_signed_data_signature_outer(file_contents: &[u8], expected_error: Error) {
461         let tsd = parse_test_signed_data(file_contents);
462         let signature = untrusted::Input::from(&tsd.signature);
463         assert_eq!(
464             expected_error,
465             signature
466                 .read_all(Error::BadDer, |input| {
467                     der::bit_string_with_no_unused_bits(input)
468                 })
469                 .unwrap_err()
470         );
471     }
472 
473     // XXX: This is testing code that is not even in this module.
474     macro_rules! test_parse_spki_bad_outer {
475         ($fn_name:ident, $file_name:expr, $error:expr) => {
476             #[test]
477             fn $fn_name() {
478                 test_parse_spki_bad_outer(test_file_bytes!($file_name), $error)
479             }
480         };
481     }
482 
test_parse_spki_bad_outer(file_contents: &[u8], expected_error: Error)483     fn test_parse_spki_bad_outer(file_contents: &[u8], expected_error: Error) {
484         let tsd = parse_test_signed_data(file_contents);
485         let spki = untrusted::Input::from(&tsd.spki);
486         assert_eq!(
487             expected_error,
488             spki.read_all(Error::BadDer, |input| {
489                 der::expect_tag_and_get_value(input, der::Tag::Sequence)
490             })
491             .unwrap_err()
492         );
493     }
494 
495     const UNSUPPORTED_SIGNATURE_ALGORITHM_FOR_RSA_KEY: Error = if cfg!(feature = "alloc") {
496         Error::UnsupportedSignatureAlgorithmForPublicKey
497     } else {
498         Error::UnsupportedSignatureAlgorithm
499     };
500 
501     const INVALID_SIGNATURE_FOR_RSA_KEY: Error = if cfg!(feature = "alloc") {
502         Error::InvalidSignatureForPublicKey
503     } else {
504         Error::UnsupportedSignatureAlgorithm
505     };
506 
507     const OK_IF_RSA_AVAILABLE: Result<(), Error> = if cfg!(feature = "alloc") {
508         Ok(())
509     } else {
510         Err(Error::UnsupportedSignatureAlgorithm)
511     };
512 
513     // XXX: Some of the BadDER tests should have better error codes, maybe?
514 
515     // XXX: We should have a variant of this test with a SHA-256 digest that gives
516     // `Error::UnsupportedSignatureAlgorithmForPublicKey`.
517     test_verify_signed_data!(
518         test_ecdsa_prime256v1_sha512_spki_params_null,
519         "ecdsa-prime256v1-sha512-spki-params-null.pem",
520         Err(Error::UnsupportedSignatureAlgorithm)
521     );
522     test_verify_signed_data_signature_outer!(
523         test_ecdsa_prime256v1_sha512_unused_bits_signature,
524         "ecdsa-prime256v1-sha512-unused-bits-signature.pem",
525         Error::BadDer
526     );
527     // XXX: We should have a variant of this test with a SHA-256 digest that gives
528     // `Error::UnsupportedSignatureAlgorithmForPublicKey`.
529     test_verify_signed_data!(
530         test_ecdsa_prime256v1_sha512_using_ecdh_key,
531         "ecdsa-prime256v1-sha512-using-ecdh-key.pem",
532         Err(Error::UnsupportedSignatureAlgorithm)
533     );
534     // XXX: We should have a variant of this test with a SHA-256 digest that gives
535     // `Error::UnsupportedSignatureAlgorithmForPublicKey`.
536     test_verify_signed_data!(
537         test_ecdsa_prime256v1_sha512_using_ecmqv_key,
538         "ecdsa-prime256v1-sha512-using-ecmqv-key.pem",
539         Err(Error::UnsupportedSignatureAlgorithm)
540     );
541     test_verify_signed_data!(
542         test_ecdsa_prime256v1_sha512_using_rsa_algorithm,
543         "ecdsa-prime256v1-sha512-using-rsa-algorithm.pem",
544         Err(UNSUPPORTED_SIGNATURE_ALGORITHM_FOR_RSA_KEY)
545     );
546     // XXX: We should have a variant of this test with a SHA-256 digest that gives
547     // `Error::InvalidSignatureForPublicKey`.
548     test_verify_signed_data!(
549         test_ecdsa_prime256v1_sha512_wrong_signature_format,
550         "ecdsa-prime256v1-sha512-wrong-signature-format.pem",
551         Err(Error::UnsupportedSignatureAlgorithm)
552     );
553     // Differs from Chromium because we don't support P-256 with SHA-512.
554     test_verify_signed_data!(
555         test_ecdsa_prime256v1_sha512,
556         "ecdsa-prime256v1-sha512.pem",
557         Err(Error::UnsupportedSignatureAlgorithm)
558     );
559     test_verify_signed_data!(
560         test_ecdsa_secp384r1_sha256_corrupted_data,
561         "ecdsa-secp384r1-sha256-corrupted-data.pem",
562         Err(Error::InvalidSignatureForPublicKey)
563     );
564     test_verify_signed_data!(
565         test_ecdsa_secp384r1_sha256,
566         "ecdsa-secp384r1-sha256.pem",
567         Ok(())
568     );
569     test_verify_signed_data!(
570         test_ecdsa_using_rsa_key,
571         "ecdsa-using-rsa-key.pem",
572         Err(Error::UnsupportedSignatureAlgorithmForPublicKey)
573     );
574 
575     test_parse_spki_bad_outer!(
576         test_rsa_pkcs1_sha1_bad_key_der_length,
577         "rsa-pkcs1-sha1-bad-key-der-length.pem",
578         Error::BadDer
579     );
580     test_parse_spki_bad_outer!(
581         test_rsa_pkcs1_sha1_bad_key_der_null,
582         "rsa-pkcs1-sha1-bad-key-der-null.pem",
583         Error::BadDer
584     );
585     test_verify_signed_data!(
586         test_rsa_pkcs1_sha1_key_params_absent,
587         "rsa-pkcs1-sha1-key-params-absent.pem",
588         Err(Error::UnsupportedSignatureAlgorithm)
589     );
590     test_verify_signed_data!(
591         test_rsa_pkcs1_sha1_using_pss_key_no_params,
592         "rsa-pkcs1-sha1-using-pss-key-no-params.pem",
593         Err(Error::UnsupportedSignatureAlgorithm)
594     );
595     test_verify_signed_data!(
596         test_rsa_pkcs1_sha1_wrong_algorithm,
597         "rsa-pkcs1-sha1-wrong-algorithm.pem",
598         Err(INVALID_SIGNATURE_FOR_RSA_KEY)
599     );
600     test_verify_signed_data!(
601         test_rsa_pkcs1_sha1,
602         "rsa-pkcs1-sha1.pem",
603         Err(Error::UnsupportedSignatureAlgorithm)
604     );
605     // XXX: RSA PKCS#1 with SHA-1 is a supported algorithm, but we only accept
606     // 2048-8192 bit keys, and this test file is using a 1024 bit key. Thus,
607     // our results differ from Chromium's. TODO: this means we need a 2048+ bit
608     // version of this test.
609     test_verify_signed_data!(
610         test_rsa_pkcs1_sha256,
611         "rsa-pkcs1-sha256.pem",
612         Err(INVALID_SIGNATURE_FOR_RSA_KEY)
613     );
614     test_parse_spki_bad_outer!(
615         test_rsa_pkcs1_sha256_key_encoded_ber,
616         "rsa-pkcs1-sha256-key-encoded-ber.pem",
617         Error::BadDer
618     );
619     test_verify_signed_data!(
620         test_rsa_pkcs1_sha256_spki_non_null_params,
621         "rsa-pkcs1-sha256-spki-non-null-params.pem",
622         Err(UNSUPPORTED_SIGNATURE_ALGORITHM_FOR_RSA_KEY)
623     );
624     test_verify_signed_data!(
625         test_rsa_pkcs1_sha256_using_ecdsa_algorithm,
626         "rsa-pkcs1-sha256-using-ecdsa-algorithm.pem",
627         Err(Error::UnsupportedSignatureAlgorithmForPublicKey)
628     );
629     test_verify_signed_data!(
630         test_rsa_pkcs1_sha256_using_id_ea_rsa,
631         "rsa-pkcs1-sha256-using-id-ea-rsa.pem",
632         Err(UNSUPPORTED_SIGNATURE_ALGORITHM_FOR_RSA_KEY)
633     );
634 
635     // Chromium's PSS test are for parameter combinations we don't support.
636     test_verify_signed_data!(
637         test_rsa_pss_sha1_salt20_using_pss_key_no_params,
638         "rsa-pss-sha1-salt20-using-pss-key-no-params.pem",
639         Err(Error::UnsupportedSignatureAlgorithm)
640     );
641     test_verify_signed_data!(
642         test_rsa_pss_sha1_salt20_using_pss_key_with_null_params,
643         "rsa-pss-sha1-salt20-using-pss-key-with-null-params.pem",
644         Err(Error::UnsupportedSignatureAlgorithm)
645     );
646     test_verify_signed_data!(
647         test_rsa_pss_sha1_salt20,
648         "rsa-pss-sha1-salt20.pem",
649         Err(Error::UnsupportedSignatureAlgorithm)
650     );
651     test_verify_signed_data!(
652         test_rsa_pss_sha1_wrong_salt,
653         "rsa-pss-sha1-wrong-salt.pem",
654         Err(Error::UnsupportedSignatureAlgorithm)
655     );
656     test_verify_signed_data!(
657         test_rsa_pss_sha256_mgf1_sha512_salt33,
658         "rsa-pss-sha256-mgf1-sha512-salt33.pem",
659         Err(Error::UnsupportedSignatureAlgorithm)
660     );
661     test_verify_signed_data!(
662         test_rsa_pss_sha256_salt10_using_pss_key_with_params,
663         "rsa-pss-sha256-salt10-using-pss-key-with-params.pem",
664         Err(Error::UnsupportedSignatureAlgorithm)
665     );
666     test_verify_signed_data!(
667         test_rsa_pss_sha256_salt10_using_pss_key_with_wrong_params,
668         "rsa-pss-sha256-salt10-using-pss-key-with-wrong-params.pem",
669         Err(Error::UnsupportedSignatureAlgorithm)
670     );
671     test_verify_signed_data!(
672         test_rsa_pss_sha256_salt10,
673         "rsa-pss-sha256-salt10.pem",
674         Err(Error::UnsupportedSignatureAlgorithm)
675     );
676 
677     // Our PSS tests that should work.
678     test_verify_signed_data!(
679         test_rsa_pss_sha256_salt32,
680         "ours/rsa-pss-sha256-salt32.pem",
681         OK_IF_RSA_AVAILABLE
682     );
683     test_verify_signed_data!(
684         test_rsa_pss_sha384_salt48,
685         "ours/rsa-pss-sha384-salt48.pem",
686         OK_IF_RSA_AVAILABLE
687     );
688     test_verify_signed_data!(
689         test_rsa_pss_sha512_salt64,
690         "ours/rsa-pss-sha512-salt64.pem",
691         OK_IF_RSA_AVAILABLE
692     );
693     test_verify_signed_data!(
694         test_rsa_pss_sha256_salt32_corrupted_data,
695         "ours/rsa-pss-sha256-salt32-corrupted-data.pem",
696         Err(INVALID_SIGNATURE_FOR_RSA_KEY)
697     );
698     test_verify_signed_data!(
699         test_rsa_pss_sha384_salt48_corrupted_data,
700         "ours/rsa-pss-sha384-salt48-corrupted-data.pem",
701         Err(INVALID_SIGNATURE_FOR_RSA_KEY)
702     );
703     test_verify_signed_data!(
704         test_rsa_pss_sha512_salt64_corrupted_data,
705         "ours/rsa-pss-sha512-salt64-corrupted-data.pem",
706         Err(INVALID_SIGNATURE_FOR_RSA_KEY)
707     );
708 
709     test_verify_signed_data!(
710         test_rsa_using_ec_key,
711         "rsa-using-ec-key.pem",
712         Err(UNSUPPORTED_SIGNATURE_ALGORITHM_FOR_RSA_KEY)
713     );
714     test_verify_signed_data!(
715         test_rsa2048_pkcs1_sha512,
716         "rsa2048-pkcs1-sha512.pem",
717         OK_IF_RSA_AVAILABLE
718     );
719 
720     struct TestSignedData {
721         spki: Vec<u8>,
722         data: Vec<u8>,
723         algorithm: Vec<u8>,
724         signature: Vec<u8>,
725     }
726 
parse_test_signed_data(file_contents: &[u8]) -> TestSignedData727     fn parse_test_signed_data(file_contents: &[u8]) -> TestSignedData {
728         let mut lines = core::str::from_utf8(file_contents).unwrap().lines();
729         let spki = read_pem_section(&mut lines, "PUBLIC KEY");
730         let algorithm = read_pem_section(&mut lines, "ALGORITHM");
731         let data = read_pem_section(&mut lines, "DATA");
732         let signature = read_pem_section(&mut lines, "SIGNATURE");
733 
734         TestSignedData {
735             spki,
736             data,
737             algorithm,
738             signature,
739         }
740     }
741 
742     use alloc::str::Lines;
743 
read_pem_section(lines: &mut Lines, section_name: &str) -> Vec<u8>744     fn read_pem_section(lines: &mut Lines, section_name: &str) -> Vec<u8> {
745         // Skip comments and header
746         let begin_section = format!("-----BEGIN {}-----", section_name);
747         loop {
748             let line = lines.next().unwrap();
749             if line == begin_section {
750                 break;
751             }
752         }
753 
754         let mut base64 = String::new();
755 
756         let end_section = format!("-----END {}-----", section_name);
757         loop {
758             let line = lines.next().unwrap();
759             if line == end_section {
760                 break;
761             }
762             base64.push_str(line);
763         }
764 
765         base64::decode(&base64).unwrap()
766     }
767 
768     static SUPPORTED_ALGORITHMS_IN_TESTS: &[&signed_data::SignatureAlgorithm] = &[
769         // Reasonable algorithms.
770         &signed_data::ECDSA_P256_SHA256,
771         &signed_data::ECDSA_P384_SHA384,
772         &signed_data::ED25519,
773         #[cfg(feature = "alloc")]
774         &signed_data::RSA_PKCS1_2048_8192_SHA256,
775         #[cfg(feature = "alloc")]
776         &signed_data::RSA_PKCS1_2048_8192_SHA384,
777         #[cfg(feature = "alloc")]
778         &signed_data::RSA_PKCS1_2048_8192_SHA512,
779         #[cfg(feature = "alloc")]
780         &signed_data::RSA_PKCS1_3072_8192_SHA384,
781         #[cfg(feature = "alloc")]
782         &signed_data::RSA_PSS_2048_8192_SHA256_LEGACY_KEY,
783         #[cfg(feature = "alloc")]
784         &signed_data::RSA_PSS_2048_8192_SHA384_LEGACY_KEY,
785         #[cfg(feature = "alloc")]
786         &signed_data::RSA_PSS_2048_8192_SHA512_LEGACY_KEY,
787         // Algorithms deprecated because they are annoying (P-521) or because
788         // they are nonsensical combinations.
789         &signed_data::ECDSA_P256_SHA384, // Truncates digest.
790         &signed_data::ECDSA_P384_SHA256, // Digest is unnecessarily short.
791     ];
792 }
793