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