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