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