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