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