webpki/
signed_data.rs

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