1 // Copyright 2017 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 ANY
10 // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12 // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13 // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14 
15 #![cfg(feature = "alloc")]
16 
17 use ring::{
18     error,
19     io::der,
20     rand, rsa,
21     signature::{self, KeyPair},
22     test, test_file,
23 };
24 
25 #[cfg(target_arch = "wasm32")]
26 use wasm_bindgen_test::{wasm_bindgen_test as test, wasm_bindgen_test_configure};
27 
28 #[cfg(target_arch = "wasm32")]
29 wasm_bindgen_test_configure!(run_in_browser);
30 
31 #[test]
rsa_from_pkcs8_test()32 fn rsa_from_pkcs8_test() {
33     test::run(
34         test_file!("rsa_from_pkcs8_tests.txt"),
35         |section, test_case| {
36             assert_eq!(section, "");
37 
38             let input = test_case.consume_bytes("Input");
39             let error = test_case.consume_optional_string("Error");
40 
41             match (rsa::KeyPair::from_pkcs8(&input), error) {
42                 (Ok(_), None) => {}
43                 (Err(e), None) => panic!("Failed with error \"{}\", but expected to succeed", e),
44                 (Ok(_), Some(e)) => panic!("Succeeded, but expected error \"{}\"", e),
45                 (Err(actual), Some(expected)) => assert_eq!(format!("{}", actual), expected),
46             };
47 
48             Ok(())
49         },
50     );
51 }
52 
53 #[cfg(feature = "alloc")]
54 #[test]
test_signature_rsa_pkcs1_sign()55 fn test_signature_rsa_pkcs1_sign() {
56     let rng = rand::SystemRandom::new();
57     test::run(
58         test_file!("rsa_pkcs1_sign_tests.txt"),
59         |section, test_case| {
60             assert_eq!(section, "");
61 
62             let digest_name = test_case.consume_string("Digest");
63             let alg = match digest_name.as_ref() {
64                 "SHA256" => &signature::RSA_PKCS1_SHA256,
65                 "SHA384" => &signature::RSA_PKCS1_SHA384,
66                 "SHA512" => &signature::RSA_PKCS1_SHA512,
67                 _ => panic!("Unsupported digest: {}", digest_name),
68             };
69 
70             let private_key = test_case.consume_bytes("Key");
71             let msg = test_case.consume_bytes("Msg");
72             let expected = test_case.consume_bytes("Sig");
73             let result = test_case.consume_string("Result");
74 
75             let key_pair = rsa::KeyPair::from_der(&private_key);
76             if result == "Fail-Invalid-Key" {
77                 assert!(key_pair.is_err());
78                 return Ok(());
79             }
80             let key_pair = key_pair.unwrap();
81 
82             // XXX: This test is too slow on Android ARM Travis CI builds.
83             // TODO: re-enable these tests on Android ARM.
84             let mut actual = vec![0u8; key_pair.public().modulus_len()];
85             key_pair
86                 .sign(alg, &rng, &msg, actual.as_mut_slice())
87                 .unwrap();
88             assert_eq!(actual.as_slice() == &expected[..], result == "Pass");
89             Ok(())
90         },
91     );
92 }
93 
94 #[cfg(feature = "alloc")]
95 #[test]
test_signature_rsa_pss_sign()96 fn test_signature_rsa_pss_sign() {
97     test::run(
98         test_file!("rsa_pss_sign_tests.txt"),
99         |section, test_case| {
100             assert_eq!(section, "");
101 
102             let digest_name = test_case.consume_string("Digest");
103             let alg = match digest_name.as_ref() {
104                 "SHA256" => &signature::RSA_PSS_SHA256,
105                 "SHA384" => &signature::RSA_PSS_SHA384,
106                 "SHA512" => &signature::RSA_PSS_SHA512,
107                 _ => panic!("Unsupported digest: {}", digest_name),
108             };
109 
110             let result = test_case.consume_string("Result");
111             let private_key = test_case.consume_bytes("Key");
112             let key_pair = rsa::KeyPair::from_der(&private_key);
113             if key_pair.is_err() && result == "Fail-Invalid-Key" {
114                 return Ok(());
115             }
116             let key_pair = key_pair.unwrap();
117             let msg = test_case.consume_bytes("Msg");
118             let salt = test_case.consume_bytes("Salt");
119             let expected = test_case.consume_bytes("Sig");
120 
121             let rng = test::rand::FixedSliceRandom { bytes: &salt };
122 
123             let mut actual = vec![0u8; key_pair.public().modulus_len()];
124             key_pair.sign(alg, &rng, &msg, actual.as_mut_slice())?;
125             assert_eq!(actual.as_slice() == &expected[..], result == "Pass");
126             Ok(())
127         },
128     );
129 }
130 
131 // `KeyPair::sign` requires that the output buffer is the same length as
132 // the public key modulus. Test what happens when it isn't the same length.
133 #[test]
test_signature_rsa_pkcs1_sign_output_buffer_len()134 fn test_signature_rsa_pkcs1_sign_output_buffer_len() {
135     // Sign the message "hello, world", using PKCS#1 v1.5 padding and the
136     // SHA256 digest algorithm.
137     const MESSAGE: &[u8] = b"hello, world";
138     let rng = rand::SystemRandom::new();
139 
140     const PRIVATE_KEY_DER: &[u8] =
141         include_bytes!("../src/rsa/signature_rsa_example_private_key.der");
142     let key_pair = rsa::KeyPair::from_der(PRIVATE_KEY_DER).unwrap();
143 
144     // When the output buffer is not exactly the right length, `sign()` returns
145     // an error (and does not panic or invoke UB). if `sign` doesn't check that
146     // the length is correct at the beginning then there are various possible
147     // failure points when the output buffer is too small.
148     for len in 0..key_pair.public().modulus_len() + 1 {
149         let mut signature = vec![0; len];
150         assert_eq!(
151             len == key_pair.public().modulus_len(),
152             key_pair
153                 .sign(&signature::RSA_PKCS1_SHA256, &rng, MESSAGE, &mut signature)
154                 .is_ok()
155         );
156     }
157 }
158 
159 #[cfg(feature = "alloc")]
160 #[test]
test_signature_rsa_pkcs1_verify()161 fn test_signature_rsa_pkcs1_verify() {
162     let sha1_params = &[
163         (
164             &signature::RSA_PKCS1_1024_8192_SHA1_FOR_LEGACY_USE_ONLY,
165             1024,
166         ),
167         (
168             &signature::RSA_PKCS1_2048_8192_SHA1_FOR_LEGACY_USE_ONLY,
169             2048,
170         ),
171     ];
172     let sha256_params = &[
173         (
174             &signature::RSA_PKCS1_1024_8192_SHA256_FOR_LEGACY_USE_ONLY,
175             1024,
176         ),
177         (&signature::RSA_PKCS1_2048_8192_SHA256, 2048),
178     ];
179     let sha384_params = &[
180         (&signature::RSA_PKCS1_2048_8192_SHA384, 2048),
181         (&signature::RSA_PKCS1_3072_8192_SHA384, 3072),
182     ];
183     let sha512_params = &[
184         (
185             &signature::RSA_PKCS1_1024_8192_SHA512_FOR_LEGACY_USE_ONLY,
186             1024,
187         ),
188         (&signature::RSA_PKCS1_2048_8192_SHA512, 2048),
189     ];
190     test::run(
191         test_file!("rsa_pkcs1_verify_tests.txt"),
192         |section, test_case| {
193             assert_eq!(section, "");
194 
195             let digest_name = test_case.consume_string("Digest");
196             let params: &[_] = match digest_name.as_ref() {
197                 "SHA1" => sha1_params,
198                 "SHA256" => sha256_params,
199                 "SHA384" => sha384_params,
200                 "SHA512" => sha512_params,
201                 _ => panic!("Unsupported digest: {}", digest_name),
202             };
203 
204             let public_key = test_case.consume_bytes("Key");
205 
206             // Sanity check that we correctly DER-encoded the originally-
207             // provided separate (n, e) components. When we add test vectors
208             // for improperly-encoded signatures, we'll have to revisit this.
209             let key_bits = untrusted::Input::from(&public_key)
210                 .read_all(error::Unspecified, |input| {
211                     der::nested(input, der::Tag::Sequence, error::Unspecified, |input| {
212                         let n_bytes =
213                             der::positive_integer(input)?.big_endian_without_leading_zero();
214                         let _e = der::positive_integer(input)?;
215 
216                         // Because `n_bytes` has the leading zeros stripped and is big-endian, there
217                         // must be less than 8 leading zero bits.
218                         let n_leading_zeros = usize::try_from(n_bytes[0].leading_zeros()).unwrap();
219                         assert!(n_leading_zeros < 8);
220                         Ok((n_bytes.len() * 8) - n_leading_zeros)
221                     })
222                 })
223                 .expect("invalid DER");
224 
225             let msg = test_case.consume_bytes("Msg");
226             let sig = test_case.consume_bytes("Sig");
227             let is_valid = test_case.consume_string("Result") == "P";
228             for &(alg, min_bits) in params {
229                 let width_ok = key_bits >= min_bits;
230                 let actual_result =
231                     signature::UnparsedPublicKey::new(alg, &public_key).verify(&msg, &sig);
232                 assert_eq!(actual_result.is_ok(), is_valid && width_ok);
233             }
234 
235             Ok(())
236         },
237     );
238 }
239 
240 #[cfg(feature = "alloc")]
241 #[test]
test_signature_rsa_pss_verify()242 fn test_signature_rsa_pss_verify() {
243     test::run(
244         test_file!("rsa_pss_verify_tests.txt"),
245         |section, test_case| {
246             assert_eq!(section, "");
247 
248             let digest_name = test_case.consume_string("Digest");
249             let alg = match digest_name.as_ref() {
250                 "SHA256" => &signature::RSA_PSS_2048_8192_SHA256,
251                 "SHA384" => &signature::RSA_PSS_2048_8192_SHA384,
252                 "SHA512" => &signature::RSA_PSS_2048_8192_SHA512,
253                 _ => panic!("Unsupported digest: {}", digest_name),
254             };
255 
256             let public_key = test_case.consume_bytes("Key");
257 
258             // Sanity check that we correctly DER-encoded the originally-
259             // provided separate (n, e) components. When we add test vectors
260             // for improperly-encoded signatures, we'll have to revisit this.
261             assert!(untrusted::Input::from(&public_key)
262                 .read_all(error::Unspecified, |input| der::nested(
263                     input,
264                     der::Tag::Sequence,
265                     error::Unspecified,
266                     |input| {
267                         let _ = der::positive_integer(input)?;
268                         let _ = der::positive_integer(input)?;
269                         Ok(())
270                     }
271                 ))
272                 .is_ok());
273 
274             let msg = test_case.consume_bytes("Msg");
275             let sig = test_case.consume_bytes("Sig");
276             let is_valid = test_case.consume_string("Result") == "P";
277 
278             let actual_result =
279                 signature::UnparsedPublicKey::new(alg, &public_key).verify(&msg, &sig);
280             assert_eq!(actual_result.is_ok(), is_valid);
281 
282             Ok(())
283         },
284     );
285 }
286 
287 // Test for `primitive::verify()`. Read public key parts from a file
288 // and use them to verify a signature.
289 #[cfg(feature = "alloc")]
290 #[test]
test_signature_rsa_primitive_verification()291 fn test_signature_rsa_primitive_verification() {
292     test::run(
293         test_file!("rsa_primitive_verify_tests.txt"),
294         |section, test_case| {
295             assert_eq!(section, "");
296             let n = test_case.consume_bytes("n");
297             let e = test_case.consume_bytes("e");
298             let msg = test_case.consume_bytes("Msg");
299             let sig = test_case.consume_bytes("Sig");
300             let expected = test_case.consume_string("Result");
301             let public_key = signature::RsaPublicKeyComponents { n: &n, e: &e };
302             let result = public_key.verify(&signature::RSA_PKCS1_2048_8192_SHA256, &msg, &sig);
303             assert_eq!(result.is_ok(), expected == "Pass");
304             Ok(())
305         },
306     )
307 }
308 
309 #[cfg(feature = "alloc")]
310 #[test]
rsa_test_keypair_coverage()311 fn rsa_test_keypair_coverage() {
312     const PRIVATE_KEY: &[u8] = include_bytes!("rsa_test_private_key_2048.p8");
313 
314     let key_pair = rsa::KeyPair::from_pkcs8(PRIVATE_KEY).unwrap();
315 
316     // Test that `signature::KeyPair::PublicKey` is `rsa::PublicKey`; if it
317     // were a separate type then it would need to be tested separately.
318     let _: &rsa::PublicKey = key_pair.public_key();
319 
320     test_public_key_coverage(key_pair.public());
321     // Test clones.
322     test_public_key_coverage(&key_pair.public().clone());
323 
324     // Test `Debug`
325     assert_eq!(
326         format!("RsaKeyPair {{ public: {:?} }}", key_pair.public_key()),
327         format!("{:?}", key_pair)
328     );
329 }
330 
test_public_key_coverage(key: &rsa::PublicKey)331 fn test_public_key_coverage(key: &rsa::PublicKey) {
332     // Test `AsRef<[u8]>`
333     const PUBLIC_KEY: &[u8] = include_bytes!("rsa_test_public_key_2048.der");
334     assert_eq!(key.as_ref(), PUBLIC_KEY);
335 
336     // Test `Debug`.
337     const PUBLIC_KEY_DEBUG: &str = include_str!("rsa_test_public_key_2048_debug.txt");
338     assert_eq!(PUBLIC_KEY_DEBUG, format!("{:?}", key));
339 
340     let components = rsa::PublicKeyComponents::<Vec<_>>::from(key);
341     const PUBLIC_KEY_MODULUS_BE_BYTES: &[u8] = include_bytes!("rsa_test_public_modulus.bin");
342     assert_eq!(PUBLIC_KEY_MODULUS_BE_BYTES, &components.n);
343     const _65537: &[u8] = &[0x01, 0x00, 0x01];
344     assert_eq!(_65537, &components.e);
345 }
346