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::{der, equal, Error};
16use 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.
21pub 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`.
69pub(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.
96pub(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
148pub(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
169struct 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.
178fn 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.
190pub 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.
197pub 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.
204pub 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.
211pub 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.
218pub 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")]
228pub 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")]
238pub 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")]
248pub 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")]
258pub 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")]
271pub 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")]
284pub 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")]
297pub 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
304pub static ED25519: SignatureAlgorithm = SignatureAlgorithm {
305    public_key_alg_id: ED_25519,
306    signature_alg_id: ED_25519,
307    verification_alg: &signature::ED25519,
308};
309
310struct AlgorithmIdentifier {
311    asn1_id_value: untrusted::Input<'static>,
312}
313
314impl AlgorithmIdentifier {
315    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
322const ECDSA_P256: AlgorithmIdentifier = AlgorithmIdentifier {
323    asn1_id_value: untrusted::Input::from(include_bytes!("data/alg-ecdsa-p256.der")),
324};
325
326const ECDSA_P384: AlgorithmIdentifier = AlgorithmIdentifier {
327    asn1_id_value: untrusted::Input::from(include_bytes!("data/alg-ecdsa-p384.der")),
328};
329
330const ECDSA_SHA256: AlgorithmIdentifier = AlgorithmIdentifier {
331    asn1_id_value: untrusted::Input::from(include_bytes!("data/alg-ecdsa-sha256.der")),
332};
333
334const ECDSA_SHA384: AlgorithmIdentifier = AlgorithmIdentifier {
335    asn1_id_value: untrusted::Input::from(include_bytes!("data/alg-ecdsa-sha384.der")),
336};
337
338#[cfg(feature = "alloc")]
339const RSA_ENCRYPTION: AlgorithmIdentifier = AlgorithmIdentifier {
340    asn1_id_value: untrusted::Input::from(include_bytes!("data/alg-rsa-encryption.der")),
341};
342
343#[cfg(feature = "alloc")]
344const 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")]
349const 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")]
354const 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")]
359const 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")]
364const 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")]
369const RSA_PSS_SHA512: AlgorithmIdentifier = AlgorithmIdentifier {
370    asn1_id_value: untrusted::Input::from(include_bytes!("data/alg-rsa-pss-sha512.der")),
371};
372
373const ED_25519: AlgorithmIdentifier = AlgorithmIdentifier {
374    asn1_id_value: untrusted::Input::from(include_bytes!("data/alg-ed25519.der")),
375};
376
377#[cfg(test)]
378mod 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
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
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
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
727    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
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}