1 // Copyright 2015-2016 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 #![forbid(
16 anonymous_parameters,
17 box_pointers,
18 missing_copy_implementations,
19 missing_debug_implementations,
20 missing_docs,
21 trivial_casts,
22 trivial_numeric_casts,
23 unsafe_code,
24 unstable_features,
25 unused_extern_crates,
26 unused_import_braces,
27 unused_qualifications,
28 unused_results,
29 variant_size_differences,
30 warnings
31 )]
32
33 use ring::{
34 rand,
35 signature::{self, KeyPair},
36 test, test_file,
37 };
38
39 // ECDSA *signing* tests are in src/ec/ecdsa/signing.rs.
40
41 #[test]
ecdsa_from_pkcs8_test()42 fn ecdsa_from_pkcs8_test() {
43 test::run(
44 test_file!("ecdsa_from_pkcs8_tests.txt"),
45 |section, test_case| {
46 assert_eq!(section, "");
47
48 let curve_name = test_case.consume_string("Curve");
49 let ((this_fixed, this_asn1), (other_fixed, other_asn1)) = match curve_name.as_str() {
50 "P-256" => (
51 (
52 &signature::ECDSA_P256_SHA256_FIXED_SIGNING,
53 &signature::ECDSA_P256_SHA256_ASN1_SIGNING,
54 ),
55 (
56 &signature::ECDSA_P384_SHA384_FIXED_SIGNING,
57 &signature::ECDSA_P384_SHA384_ASN1_SIGNING,
58 ),
59 ),
60 "P-384" => (
61 (
62 &signature::ECDSA_P384_SHA384_FIXED_SIGNING,
63 &signature::ECDSA_P384_SHA384_ASN1_SIGNING,
64 ),
65 (
66 &signature::ECDSA_P256_SHA256_FIXED_SIGNING,
67 &signature::ECDSA_P256_SHA256_ASN1_SIGNING,
68 ),
69 ),
70 _ => unreachable!(),
71 };
72
73 let input = test_case.consume_bytes("Input");
74
75 let error = test_case.consume_optional_string("Error");
76
77 match (
78 signature::EcdsaKeyPair::from_pkcs8(this_fixed, &input),
79 error.clone(),
80 ) {
81 (Ok(_), None) => (),
82 (Err(e), None) => panic!("Failed with error \"{}\", but expected to succeed", e),
83 (Ok(_), Some(e)) => panic!("Succeeded, but expected error \"{}\"", e),
84 (Err(actual), Some(expected)) => assert_eq!(format!("{}", actual), expected),
85 };
86
87 match (
88 signature::EcdsaKeyPair::from_pkcs8(this_asn1, &input),
89 error.clone(),
90 ) {
91 (Ok(_), None) => (),
92 (Err(e), None) => panic!("Failed with error \"{}\", but expected to succeed", e),
93 (Ok(_), Some(e)) => panic!("Succeeded, but expected error \"{}\"", e),
94 (Err(actual), Some(expected)) => assert_eq!(format!("{}", actual), expected),
95 };
96
97 assert!(signature::EcdsaKeyPair::from_pkcs8(other_fixed, &input).is_err());
98 assert!(signature::EcdsaKeyPair::from_pkcs8(other_asn1, &input).is_err());
99
100 Ok(())
101 },
102 );
103 }
104
105 // Verify that, at least, we generate PKCS#8 documents that we can read.
106 #[test]
ecdsa_generate_pkcs8_test()107 fn ecdsa_generate_pkcs8_test() {
108 let rng = rand::SystemRandom::new();
109
110 for alg in &[
111 &signature::ECDSA_P256_SHA256_ASN1_SIGNING,
112 &signature::ECDSA_P256_SHA256_FIXED_SIGNING,
113 &signature::ECDSA_P384_SHA384_ASN1_SIGNING,
114 &signature::ECDSA_P384_SHA384_FIXED_SIGNING,
115 ] {
116 let pkcs8 = signature::EcdsaKeyPair::generate_pkcs8(alg, &rng).unwrap();
117 println!();
118 for b in pkcs8.as_ref() {
119 print!("{:02x}", *b);
120 }
121 println!();
122 println!();
123
124 #[cfg(feature = "alloc")]
125 let _ = signature::EcdsaKeyPair::from_pkcs8(*alg, pkcs8.as_ref()).unwrap();
126 }
127 }
128
129 #[test]
signature_ecdsa_verify_asn1_test()130 fn signature_ecdsa_verify_asn1_test() {
131 test::run(
132 test_file!("ecdsa_verify_asn1_tests.txt"),
133 |section, test_case| {
134 assert_eq!(section, "");
135
136 let curve_name = test_case.consume_string("Curve");
137 let digest_name = test_case.consume_string("Digest");
138 let msg = test_case.consume_bytes("Msg");
139 let public_key = test_case.consume_bytes("Q");
140 let sig = test_case.consume_bytes("Sig");
141 let is_valid = test_case.consume_string("Result") == "P (0 )";
142
143 let alg = match (curve_name.as_str(), digest_name.as_str()) {
144 ("P-256", "SHA256") => &signature::ECDSA_P256_SHA256_ASN1,
145 ("P-256", "SHA384") => &signature::ECDSA_P256_SHA384_ASN1,
146 ("P-384", "SHA256") => &signature::ECDSA_P384_SHA256_ASN1,
147 ("P-384", "SHA384") => &signature::ECDSA_P384_SHA384_ASN1,
148 _ => {
149 panic!("Unsupported curve+digest: {}+{}", curve_name, digest_name);
150 }
151 };
152
153 let actual_result =
154 signature::UnparsedPublicKey::new(alg, &public_key).verify(&msg, &sig);
155 assert_eq!(actual_result.is_ok(), is_valid);
156
157 Ok(())
158 },
159 );
160 }
161
162 #[test]
signature_ecdsa_verify_fixed_test()163 fn signature_ecdsa_verify_fixed_test() {
164 test::run(
165 test_file!("ecdsa_verify_fixed_tests.txt"),
166 |section, test_case| {
167 assert_eq!(section, "");
168
169 let curve_name = test_case.consume_string("Curve");
170 let digest_name = test_case.consume_string("Digest");
171
172 let msg = test_case.consume_bytes("Msg");
173 let public_key = test_case.consume_bytes("Q");
174 let sig = test_case.consume_bytes("Sig");
175 let expected_result = test_case.consume_string("Result");
176
177 let alg = match (curve_name.as_str(), digest_name.as_str()) {
178 ("P-256", "SHA256") => &signature::ECDSA_P256_SHA256_FIXED,
179 ("P-384", "SHA384") => &signature::ECDSA_P384_SHA384_FIXED,
180 _ => {
181 panic!("Unsupported curve+digest: {}+{}", curve_name, digest_name);
182 }
183 };
184
185 let is_valid = expected_result == "P (0 )";
186
187 let actual_result =
188 signature::UnparsedPublicKey::new(alg, &public_key).verify(&msg, &sig);
189 assert_eq!(actual_result.is_ok(), is_valid);
190
191 Ok(())
192 },
193 );
194 }
195
196 #[test]
ecdsa_test_public_key_coverage()197 fn ecdsa_test_public_key_coverage() {
198 const PRIVATE_KEY: &[u8] = include_bytes!("ecdsa_test_private_key_p256.p8");
199 const PUBLIC_KEY: &[u8] = include_bytes!("ecdsa_test_public_key_p256.der");
200 const PUBLIC_KEY_DEBUG: &str = include_str!("ecdsa_test_public_key_p256_debug.txt");
201
202 let key_pair = signature::EcdsaKeyPair::from_pkcs8(
203 &signature::ECDSA_P256_SHA256_FIXED_SIGNING,
204 PRIVATE_KEY,
205 )
206 .unwrap();
207
208 // Test `AsRef<[u8]>`
209 assert_eq!(key_pair.public_key().as_ref(), PUBLIC_KEY);
210
211 // Test `Clone`.
212 #[allow(clippy::clone_on_copy)]
213 let _: <signature::EcdsaKeyPair as KeyPair>::PublicKey = key_pair.public_key().clone();
214
215 // Test `Copy`.
216 let _: <signature::EcdsaKeyPair as KeyPair>::PublicKey = *key_pair.public_key();
217
218 // Test `Debug`.
219 assert_eq!(PUBLIC_KEY_DEBUG, format!("{:?}", key_pair.public_key()));
220 assert_eq!(
221 format!("EcdsaKeyPair {{ public_key: {:?} }}", key_pair.public_key()),
222 format!("{:?}", key_pair)
223 );
224 }
225
226 // This test is not a known-answer test, though it re-uses the known-answer
227 // test vectors. Because the nonce is randomized, the signature will be
228 // different each time. Because of that, here we simply verify that the
229 // signature verifies correctly. The known-answer tests themselves are in
230 // ecsda/signing.rs.
231 #[test]
signature_ecdsa_sign_fixed_sign_and_verify_test()232 fn signature_ecdsa_sign_fixed_sign_and_verify_test() {
233 let rng = rand::SystemRandom::new();
234
235 test::run(
236 test_file!("../src/ec/suite_b/ecdsa/ecdsa_sign_fixed_tests.txt"),
237 |section, test_case| {
238 assert_eq!(section, "");
239
240 let curve_name = test_case.consume_string("Curve");
241 let digest_name = test_case.consume_string("Digest");
242
243 let msg = test_case.consume_bytes("Msg");
244 let d = test_case.consume_bytes("d");
245 let q = test_case.consume_bytes("Q");
246
247 // Ignored since the actual signature will use a randomized nonce.
248 let _k = test_case.consume_bytes("k");
249 let _expected_result = test_case.consume_bytes("Sig");
250
251 let (signing_alg, verification_alg) = match (curve_name.as_str(), digest_name.as_str())
252 {
253 ("P-256", "SHA256") => (
254 &signature::ECDSA_P256_SHA256_FIXED_SIGNING,
255 &signature::ECDSA_P256_SHA256_FIXED,
256 ),
257 ("P-384", "SHA384") => (
258 &signature::ECDSA_P384_SHA384_FIXED_SIGNING,
259 &signature::ECDSA_P384_SHA384_FIXED,
260 ),
261 _ => {
262 panic!("Unsupported curve+digest: {}+{}", curve_name, digest_name);
263 }
264 };
265
266 let private_key =
267 signature::EcdsaKeyPair::from_private_key_and_public_key(signing_alg, &d, &q)
268 .unwrap();
269
270 let signature = private_key.sign(&rng, &msg).unwrap();
271
272 let public_key = signature::UnparsedPublicKey::new(verification_alg, q);
273 assert_eq!(public_key.verify(&msg, signature.as_ref()), Ok(()));
274
275 Ok(())
276 },
277 );
278 }
279
280 // This test is not a known-answer test, though it re-uses the known-answer
281 // test vectors. Because the nonce is randomized, the signature will be
282 // different each time. Because of that, here we simply verify that the
283 // signature verifies correctly. The known-answer tests themselves are in
284 // ecsda/signing.rs.
285 #[test]
signature_ecdsa_sign_asn1_test()286 fn signature_ecdsa_sign_asn1_test() {
287 let rng = rand::SystemRandom::new();
288
289 test::run(
290 test_file!("../src/ec/suite_b/ecdsa/ecdsa_sign_asn1_tests.txt"),
291 |section, test_case| {
292 assert_eq!(section, "");
293
294 let curve_name = test_case.consume_string("Curve");
295 let digest_name = test_case.consume_string("Digest");
296
297 let msg = test_case.consume_bytes("Msg");
298 let d = test_case.consume_bytes("d");
299 let q = test_case.consume_bytes("Q");
300
301 // Ignored since the actual signature will use a randomized nonce.
302 let _k = test_case.consume_bytes("k");
303 let _expected_result = test_case.consume_bytes("Sig");
304
305 let (signing_alg, verification_alg) = match (curve_name.as_str(), digest_name.as_str())
306 {
307 ("P-256", "SHA256") => (
308 &signature::ECDSA_P256_SHA256_ASN1_SIGNING,
309 &signature::ECDSA_P256_SHA256_ASN1,
310 ),
311 ("P-384", "SHA384") => (
312 &signature::ECDSA_P384_SHA384_ASN1_SIGNING,
313 &signature::ECDSA_P384_SHA384_ASN1,
314 ),
315 _ => {
316 panic!("Unsupported curve+digest: {}+{}", curve_name, digest_name);
317 }
318 };
319
320 let private_key =
321 signature::EcdsaKeyPair::from_private_key_and_public_key(signing_alg, &d, &q)
322 .unwrap();
323
324 let signature = private_key.sign(&rng, &msg).unwrap();
325
326 let public_key = signature::UnparsedPublicKey::new(verification_alg, q);
327 assert_eq!(public_key.verify(&msg, signature.as_ref()), Ok(()));
328
329 Ok(())
330 },
331 );
332 }
333