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