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 //! ECDSA Signatures using the P-256 and P-384 curves.
16
17 use super::digest_scalar::digest_scalar;
18 use crate::{
19 arithmetic::montgomery::*,
20 cpu, digest,
21 ec::{
22 self,
23 suite_b::{ops::*, private_key},
24 },
25 error,
26 io::der,
27 limb, pkcs8, rand, sealed, signature,
28 };
29 use untrusted;
30
31 /// An ECDSA signing algorithm.
32 pub struct EcdsaSigningAlgorithm {
33 curve: &'static ec::Curve,
34 private_scalar_ops: &'static PrivateScalarOps,
35 private_key_ops: &'static PrivateKeyOps,
36 digest_alg: &'static digest::Algorithm,
37 pkcs8_template: &'static pkcs8::Template,
38 format_rs: fn(ops: &'static ScalarOps, r: &Scalar, s: &Scalar, out: &mut [u8]) -> usize,
39 id: AlgorithmID,
40 }
41
42 #[derive(Debug, Eq, PartialEq)]
43 enum AlgorithmID {
44 ECDSA_P256_SHA256_FIXED_SIGNING,
45 ECDSA_P384_SHA384_FIXED_SIGNING,
46 ECDSA_P256_SHA256_ASN1_SIGNING,
47 ECDSA_P384_SHA384_ASN1_SIGNING,
48 }
49
50 derive_debug_via_id!(EcdsaSigningAlgorithm);
51
52 impl PartialEq for EcdsaSigningAlgorithm {
eq(&self, other: &Self) -> bool53 fn eq(&self, other: &Self) -> bool {
54 self.id == other.id
55 }
56 }
57
58 impl Eq for EcdsaSigningAlgorithm {}
59
60 impl sealed::Sealed for EcdsaSigningAlgorithm {}
61
62 /// An ECDSA key pair, used for signing.
63 pub struct EcdsaKeyPair {
64 d: Scalar<R>,
65 nonce_key: NonceRandomKey,
66 alg: &'static EcdsaSigningAlgorithm,
67 public_key: PublicKey,
68 }
69
70 derive_debug_via_field!(EcdsaKeyPair, stringify!(EcdsaKeyPair), public_key);
71
72 impl EcdsaKeyPair {
73 /// Generates a new key pair and returns the key pair serialized as a
74 /// PKCS#8 document.
75 ///
76 /// The PKCS#8 document will be a v1 `OneAsymmetricKey` with the public key
77 /// included in the `ECPrivateKey` structure, as described in
78 /// [RFC 5958 Section 2] and [RFC 5915]. The `ECPrivateKey` structure will
79 /// not have a `parameters` field so the generated key is compatible with
80 /// PKCS#11.
81 ///
82 /// [RFC 5915]: https://tools.ietf.org/html/rfc5915
83 /// [RFC 5958 Section 2]: https://tools.ietf.org/html/rfc5958#section-2
generate_pkcs8( alg: &'static EcdsaSigningAlgorithm, rng: &dyn rand::SecureRandom, ) -> Result<pkcs8::Document, error::Unspecified>84 pub fn generate_pkcs8(
85 alg: &'static EcdsaSigningAlgorithm,
86 rng: &dyn rand::SecureRandom,
87 ) -> Result<pkcs8::Document, error::Unspecified> {
88 let private_key = ec::Seed::generate(alg.curve, rng, cpu::features())?;
89 let public_key = private_key.compute_public_key()?;
90 Ok(pkcs8::wrap_key(
91 &alg.pkcs8_template,
92 private_key.bytes_less_safe(),
93 public_key.as_ref(),
94 ))
95 }
96
97 /// Constructs an ECDSA key pair by parsing an unencrypted PKCS#8 v1
98 /// id-ecPublicKey `ECPrivateKey` key.
99 ///
100 /// The input must be in PKCS#8 v1 format. It must contain the public key in
101 /// the `ECPrivateKey` structure; `from_pkcs8()` will verify that the public
102 /// key and the private key are consistent with each other. The algorithm
103 /// identifier must identify the curve by name; it must not use an
104 /// "explicit" encoding of the curve. The `parameters` field of the
105 /// `ECPrivateKey`, if present, must be the same named curve that is in the
106 /// algorithm identifier in the PKCS#8 header.
from_pkcs8( alg: &'static EcdsaSigningAlgorithm, pkcs8: &[u8], ) -> Result<Self, error::KeyRejected>107 pub fn from_pkcs8(
108 alg: &'static EcdsaSigningAlgorithm,
109 pkcs8: &[u8],
110 ) -> Result<Self, error::KeyRejected> {
111 let key_pair = ec::suite_b::key_pair_from_pkcs8(
112 alg.curve,
113 alg.pkcs8_template,
114 untrusted::Input::from(pkcs8),
115 cpu::features(),
116 )?;
117 let rng = rand::SystemRandom::new(); // TODO: make this a parameter.
118 Self::new(alg, key_pair, &rng)
119 }
120
121 /// Constructs an ECDSA key pair directly from the big-endian-encoded
122 /// private key and public key bytes.
123 ///
124 /// This is intended for use by code that deserializes key pairs. It is
125 /// recommended to use `EcdsaKeyPair::from_pkcs8()` (with a PKCS#8-encoded
126 /// key) instead.
from_private_key_and_public_key( alg: &'static EcdsaSigningAlgorithm, private_key: &[u8], public_key: &[u8], ) -> Result<Self, error::KeyRejected>127 pub fn from_private_key_and_public_key(
128 alg: &'static EcdsaSigningAlgorithm,
129 private_key: &[u8],
130 public_key: &[u8],
131 ) -> Result<Self, error::KeyRejected> {
132 let key_pair = ec::suite_b::key_pair_from_bytes(
133 alg.curve,
134 untrusted::Input::from(private_key),
135 untrusted::Input::from(public_key),
136 cpu::features(),
137 )?;
138 let rng = rand::SystemRandom::new(); // TODO: make this a parameter.
139 Self::new(alg, key_pair, &rng)
140 }
141
new( alg: &'static EcdsaSigningAlgorithm, key_pair: ec::KeyPair, rng: &dyn rand::SecureRandom, ) -> Result<Self, error::KeyRejected>142 fn new(
143 alg: &'static EcdsaSigningAlgorithm,
144 key_pair: ec::KeyPair,
145 rng: &dyn rand::SecureRandom,
146 ) -> Result<Self, error::KeyRejected> {
147 let (seed, public_key) = key_pair.split();
148 let d = private_key::private_key_as_scalar(alg.private_key_ops, &seed);
149 let d = alg
150 .private_scalar_ops
151 .scalar_ops
152 .scalar_product(&d, &alg.private_scalar_ops.oneRR_mod_n);
153
154 let nonce_key = NonceRandomKey::new(alg, &seed, rng)?;
155 Ok(Self {
156 d,
157 nonce_key,
158 alg,
159 public_key: PublicKey(public_key),
160 })
161 }
162
163 /// Deprecated. Returns the signature of the `message` using a random nonce
164 /// generated by `rng`.
sign( &self, rng: &dyn rand::SecureRandom, message: &[u8], ) -> Result<signature::Signature, error::Unspecified>165 pub fn sign(
166 &self,
167 rng: &dyn rand::SecureRandom,
168 message: &[u8],
169 ) -> Result<signature::Signature, error::Unspecified> {
170 // Step 4 (out of order).
171 let h = digest::digest(self.alg.digest_alg, message);
172
173 // Incorporate `h` into the nonce to hedge against faulty RNGs. (This
174 // is not an approved random number generator that is mandated in
175 // the spec.)
176 let nonce_rng = NonceRandom {
177 key: &self.nonce_key,
178 message_digest: &h,
179 rng,
180 };
181
182 self.sign_digest(h, &nonce_rng)
183 }
184
185 #[cfg(test)]
sign_with_fixed_nonce_during_test( &self, rng: &dyn rand::SecureRandom, message: &[u8], ) -> Result<signature::Signature, error::Unspecified>186 fn sign_with_fixed_nonce_during_test(
187 &self,
188 rng: &dyn rand::SecureRandom,
189 message: &[u8],
190 ) -> Result<signature::Signature, error::Unspecified> {
191 // Step 4 (out of order).
192 let h = digest::digest(self.alg.digest_alg, message);
193
194 self.sign_digest(h, rng)
195 }
196
197 /// Returns the signature of message digest `h` using a "random" nonce
198 /// generated by `rng`.
sign_digest( &self, h: digest::Digest, rng: &dyn rand::SecureRandom, ) -> Result<signature::Signature, error::Unspecified>199 fn sign_digest(
200 &self,
201 h: digest::Digest,
202 rng: &dyn rand::SecureRandom,
203 ) -> Result<signature::Signature, error::Unspecified> {
204 // NSA Suite B Implementer's Guide to ECDSA Section 3.4.1: ECDSA
205 // Signature Generation.
206
207 // NSA Guide Prerequisites:
208 //
209 // Prior to generating an ECDSA signature, the signatory shall
210 // obtain:
211 //
212 // 1. an authentic copy of the domain parameters,
213 // 2. a digital signature key pair (d,Q), either generated by a
214 // method from Appendix A.1, or obtained from a trusted third
215 // party,
216 // 3. assurance of the validity of the public key Q (see Appendix
217 // A.3), and
218 // 4. assurance that he/she/it actually possesses the associated
219 // private key d (see [SP800-89] Section 6).
220 //
221 // The domain parameters are hard-coded into the source code.
222 // `EcdsaKeyPair::generate_pkcs8()` can be used to meet the second
223 // requirement; otherwise, it is up to the user to ensure the key pair
224 // was obtained from a trusted private key. The constructors for
225 // `EcdsaKeyPair` ensure that #3 and #4 are met subject to the caveats
226 // in SP800-89 Section 6.
227
228 let ops = self.alg.private_scalar_ops;
229 let scalar_ops = ops.scalar_ops;
230 let cops = scalar_ops.common;
231 let private_key_ops = self.alg.private_key_ops;
232
233 for _ in 0..100 {
234 // XXX: iteration conut?
235 // Step 1.
236 let k = private_key::random_scalar(self.alg.private_key_ops, rng)?;
237 let k_inv = scalar_ops.scalar_inv_to_mont(&k);
238
239 // Step 2.
240 let r = private_key_ops.point_mul_base(&k);
241
242 // Step 3.
243 let r = {
244 let (x, _) = private_key::affine_from_jacobian(private_key_ops, &r)?;
245 let x = cops.elem_unencoded(&x);
246 elem_reduced_to_scalar(cops, &x)
247 };
248 if cops.is_zero(&r) {
249 continue;
250 }
251
252 // Step 4 is done by the caller.
253
254 // Step 5.
255 let e = digest_scalar(scalar_ops, h);
256
257 // Step 6.
258 let s = {
259 let dr = scalar_ops.scalar_product(&self.d, &r);
260 let e_plus_dr = scalar_sum(cops, &e, &dr);
261 scalar_ops.scalar_product(&k_inv, &e_plus_dr)
262 };
263 if cops.is_zero(&s) {
264 continue;
265 }
266
267 // Step 7 with encoding.
268 return Ok(signature::Signature::new(|sig_bytes| {
269 (self.alg.format_rs)(scalar_ops, &r, &s, sig_bytes)
270 }));
271 }
272
273 Err(error::Unspecified)
274 }
275 }
276
277 /// Generates an ECDSA nonce in a way that attempts to protect against a faulty
278 /// `SecureRandom`.
279 struct NonceRandom<'a> {
280 key: &'a NonceRandomKey,
281 message_digest: &'a digest::Digest,
282 rng: &'a dyn rand::SecureRandom,
283 }
284
285 impl core::fmt::Debug for NonceRandom<'_> {
fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result286 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
287 f.debug_struct("NonceRandom").finish()
288 }
289 }
290
291 impl rand::sealed::SecureRandom for NonceRandom<'_> {
fill_impl(&self, dest: &mut [u8]) -> Result<(), error::Unspecified>292 fn fill_impl(&self, dest: &mut [u8]) -> Result<(), error::Unspecified> {
293 // Use the same digest algorithm that will be used to digest the
294 // message. The digest algorithm's output is exactly the right size;
295 // this is checked below.
296 //
297 // XXX(perf): The single iteration will require two digest block
298 // operations because the amount of data digested is larger than one
299 // block.
300 let digest_alg = self.key.0.algorithm();
301 let mut ctx = digest::Context::new(digest_alg);
302
303 // Digest the randomized digest of the private key.
304 let key = self.key.0.as_ref();
305 ctx.update(key);
306
307 // The random value is digested between the key and the message so that
308 // the key and the message are not directly digested in the same digest
309 // block.
310 assert!(key.len() <= digest_alg.block_len / 2);
311 {
312 let mut rand = [0u8; digest::MAX_BLOCK_LEN];
313 let rand = &mut rand[..digest_alg.block_len - key.len()];
314 assert!(rand.len() >= dest.len());
315 self.rng.fill(rand)?;
316 ctx.update(rand);
317 }
318
319 ctx.update(self.message_digest.as_ref());
320
321 let nonce = ctx.finish();
322
323 // `copy_from_slice()` panics if the lengths differ, so we don't have
324 // to separately assert that the lengths are the same.
325 dest.copy_from_slice(nonce.as_ref());
326
327 Ok(())
328 }
329 }
330
331 impl<'a> sealed::Sealed for NonceRandom<'a> {}
332
333 struct NonceRandomKey(digest::Digest);
334
335 impl NonceRandomKey {
new( alg: &EcdsaSigningAlgorithm, seed: &ec::Seed, rng: &dyn rand::SecureRandom, ) -> Result<Self, error::KeyRejected>336 fn new(
337 alg: &EcdsaSigningAlgorithm,
338 seed: &ec::Seed,
339 rng: &dyn rand::SecureRandom,
340 ) -> Result<Self, error::KeyRejected> {
341 let mut rand = [0; digest::MAX_OUTPUT_LEN];
342 let rand = &mut rand[0..alg.curve.elem_scalar_seed_len];
343
344 // XXX: `KeyRejected` isn't the right way to model failure of the RNG,
345 // but to fix that we'd need to break the API by changing the result type.
346 // TODO: Fix the API in the next breaking release.
347 rng.fill(rand)
348 .map_err(|error::Unspecified| error::KeyRejected::rng_failed())?;
349
350 let mut ctx = digest::Context::new(alg.digest_alg);
351 ctx.update(rand);
352 ctx.update(seed.bytes_less_safe());
353 Ok(NonceRandomKey(ctx.finish()))
354 }
355 }
356
357 impl signature::KeyPair for EcdsaKeyPair {
358 type PublicKey = PublicKey;
359
public_key(&self) -> &Self::PublicKey360 fn public_key(&self) -> &Self::PublicKey {
361 &self.public_key
362 }
363 }
364
365 #[derive(Clone, Copy)]
366 pub struct PublicKey(ec::PublicKey);
367
368 derive_debug_self_as_ref_hex_bytes!(PublicKey);
369
370 impl AsRef<[u8]> for PublicKey {
as_ref(&self) -> &[u8]371 fn as_ref(&self) -> &[u8] {
372 self.0.as_ref()
373 }
374 }
375
format_rs_fixed(ops: &'static ScalarOps, r: &Scalar, s: &Scalar, out: &mut [u8]) -> usize376 fn format_rs_fixed(ops: &'static ScalarOps, r: &Scalar, s: &Scalar, out: &mut [u8]) -> usize {
377 let scalar_len = ops.scalar_bytes_len();
378
379 let (r_out, rest) = out.split_at_mut(scalar_len);
380 limb::big_endian_from_limbs(&r.limbs[..ops.common.num_limbs], r_out);
381
382 let (s_out, _) = rest.split_at_mut(scalar_len);
383 limb::big_endian_from_limbs(&s.limbs[..ops.common.num_limbs], s_out);
384
385 2 * scalar_len
386 }
387
format_rs_asn1(ops: &'static ScalarOps, r: &Scalar, s: &Scalar, out: &mut [u8]) -> usize388 fn format_rs_asn1(ops: &'static ScalarOps, r: &Scalar, s: &Scalar, out: &mut [u8]) -> usize {
389 // This assumes `a` is not zero since neither `r` or `s` is allowed to be
390 // zero.
391 fn format_integer_tlv(ops: &ScalarOps, a: &Scalar, out: &mut [u8]) -> usize {
392 let mut fixed = [0u8; ec::SCALAR_MAX_BYTES + 1];
393 let fixed = &mut fixed[..(ops.scalar_bytes_len() + 1)];
394 limb::big_endian_from_limbs(&a.limbs[..ops.common.num_limbs], &mut fixed[1..]);
395
396 // Since `a_fixed_out` is an extra byte long, it is guaranteed to start
397 // with a zero.
398 debug_assert_eq!(fixed[0], 0);
399
400 // There must be at least one non-zero byte since `a` isn't zero.
401 let first_index = fixed.iter().position(|b| *b != 0).unwrap();
402
403 // If the first byte has its high bit set, it needs to be prefixed with 0x00.
404 let first_index = if fixed[first_index] & 0x80 != 0 {
405 first_index - 1
406 } else {
407 first_index
408 };
409 let value = &fixed[first_index..];
410
411 out[0] = der::Tag::Integer as u8;
412
413 // Lengths less than 128 are encoded in one byte.
414 assert!(value.len() < 128);
415 out[1] = value.len() as u8;
416
417 out[2..][..value.len()].copy_from_slice(&value);
418
419 2 + value.len()
420 }
421
422 out[0] = der::Tag::Sequence as u8;
423 let r_tlv_len = format_integer_tlv(ops, r, &mut out[2..]);
424 let s_tlv_len = format_integer_tlv(ops, s, &mut out[2..][r_tlv_len..]);
425
426 // Lengths less than 128 are encoded in one byte.
427 let value_len = r_tlv_len + s_tlv_len;
428 assert!(value_len < 128);
429 out[1] = value_len as u8;
430
431 2 + value_len
432 }
433
434 /// Signing of fixed-length (PKCS#11 style) ECDSA signatures using the
435 /// P-256 curve and SHA-256.
436 ///
437 /// See "`ECDSA_*_FIXED` Details" in `ring::signature`'s module-level
438 /// documentation for more details.
439 pub static ECDSA_P256_SHA256_FIXED_SIGNING: EcdsaSigningAlgorithm = EcdsaSigningAlgorithm {
440 curve: &ec::suite_b::curve::P256,
441 private_scalar_ops: &p256::PRIVATE_SCALAR_OPS,
442 private_key_ops: &p256::PRIVATE_KEY_OPS,
443 digest_alg: &digest::SHA256,
444 pkcs8_template: &EC_PUBLIC_KEY_P256_PKCS8_V1_TEMPLATE,
445 format_rs: format_rs_fixed,
446 id: AlgorithmID::ECDSA_P256_SHA256_FIXED_SIGNING,
447 };
448
449 /// Signing of fixed-length (PKCS#11 style) ECDSA signatures using the
450 /// P-384 curve and SHA-384.
451 ///
452 /// See "`ECDSA_*_FIXED` Details" in `ring::signature`'s module-level
453 /// documentation for more details.
454 pub static ECDSA_P384_SHA384_FIXED_SIGNING: EcdsaSigningAlgorithm = EcdsaSigningAlgorithm {
455 curve: &ec::suite_b::curve::P384,
456 private_scalar_ops: &p384::PRIVATE_SCALAR_OPS,
457 private_key_ops: &p384::PRIVATE_KEY_OPS,
458 digest_alg: &digest::SHA384,
459 pkcs8_template: &EC_PUBLIC_KEY_P384_PKCS8_V1_TEMPLATE,
460 format_rs: format_rs_fixed,
461 id: AlgorithmID::ECDSA_P384_SHA384_FIXED_SIGNING,
462 };
463
464 /// Signing of ASN.1 DER-encoded ECDSA signatures using the P-256 curve and
465 /// SHA-256.
466 ///
467 /// See "`ECDSA_*_ASN1` Details" in `ring::signature`'s module-level
468 /// documentation for more details.
469 pub static ECDSA_P256_SHA256_ASN1_SIGNING: EcdsaSigningAlgorithm = EcdsaSigningAlgorithm {
470 curve: &ec::suite_b::curve::P256,
471 private_scalar_ops: &p256::PRIVATE_SCALAR_OPS,
472 private_key_ops: &p256::PRIVATE_KEY_OPS,
473 digest_alg: &digest::SHA256,
474 pkcs8_template: &EC_PUBLIC_KEY_P256_PKCS8_V1_TEMPLATE,
475 format_rs: format_rs_asn1,
476 id: AlgorithmID::ECDSA_P256_SHA256_ASN1_SIGNING,
477 };
478
479 /// Signing of ASN.1 DER-encoded ECDSA signatures using the P-384 curve and
480 /// SHA-384.
481 ///
482 /// See "`ECDSA_*_ASN1` Details" in `ring::signature`'s module-level
483 /// documentation for more details.
484 pub static ECDSA_P384_SHA384_ASN1_SIGNING: EcdsaSigningAlgorithm = EcdsaSigningAlgorithm {
485 curve: &ec::suite_b::curve::P384,
486 private_scalar_ops: &p384::PRIVATE_SCALAR_OPS,
487 private_key_ops: &p384::PRIVATE_KEY_OPS,
488 digest_alg: &digest::SHA384,
489 pkcs8_template: &EC_PUBLIC_KEY_P384_PKCS8_V1_TEMPLATE,
490 format_rs: format_rs_asn1,
491 id: AlgorithmID::ECDSA_P384_SHA384_ASN1_SIGNING,
492 };
493
494 static EC_PUBLIC_KEY_P256_PKCS8_V1_TEMPLATE: pkcs8::Template = pkcs8::Template {
495 bytes: include_bytes!("ecPublicKey_p256_pkcs8_v1_template.der"),
496 alg_id_range: core::ops::Range { start: 8, end: 27 },
497 curve_id_index: 9,
498 private_key_index: 0x24,
499 };
500
501 static EC_PUBLIC_KEY_P384_PKCS8_V1_TEMPLATE: pkcs8::Template = pkcs8::Template {
502 bytes: include_bytes!("ecPublicKey_p384_pkcs8_v1_template.der"),
503 alg_id_range: core::ops::Range { start: 8, end: 24 },
504 curve_id_index: 9,
505 private_key_index: 0x23,
506 };
507
508 #[cfg(test)]
509 mod tests {
510 use crate::{signature, test};
511
512 #[test]
signature_ecdsa_sign_fixed_test()513 fn signature_ecdsa_sign_fixed_test() {
514 test::run(
515 test_file!("ecdsa_sign_fixed_tests.txt"),
516 |section, test_case| {
517 assert_eq!(section, "");
518
519 let curve_name = test_case.consume_string("Curve");
520 let digest_name = test_case.consume_string("Digest");
521 let msg = test_case.consume_bytes("Msg");
522 let d = test_case.consume_bytes("d");
523 let q = test_case.consume_bytes("Q");
524 let k = test_case.consume_bytes("k");
525
526 let expected_result = test_case.consume_bytes("Sig");
527
528 let alg = match (curve_name.as_str(), digest_name.as_str()) {
529 ("P-256", "SHA256") => &signature::ECDSA_P256_SHA256_FIXED_SIGNING,
530 ("P-384", "SHA384") => &signature::ECDSA_P384_SHA384_FIXED_SIGNING,
531 _ => {
532 panic!("Unsupported curve+digest: {}+{}", curve_name, digest_name);
533 }
534 };
535
536 let private_key =
537 signature::EcdsaKeyPair::from_private_key_and_public_key(alg, &d, &q).unwrap();
538 let rng = test::rand::FixedSliceRandom { bytes: &k };
539
540 let actual_result = private_key
541 .sign_with_fixed_nonce_during_test(&rng, &msg)
542 .unwrap();
543
544 assert_eq!(actual_result.as_ref(), &expected_result[..]);
545
546 Ok(())
547 },
548 );
549 }
550
551 #[test]
signature_ecdsa_sign_asn1_test()552 fn signature_ecdsa_sign_asn1_test() {
553 test::run(
554 test_file!("ecdsa_sign_asn1_tests.txt"),
555 |section, test_case| {
556 assert_eq!(section, "");
557
558 let curve_name = test_case.consume_string("Curve");
559 let digest_name = test_case.consume_string("Digest");
560 let msg = test_case.consume_bytes("Msg");
561 let d = test_case.consume_bytes("d");
562 let q = test_case.consume_bytes("Q");
563 let k = test_case.consume_bytes("k");
564
565 let expected_result = test_case.consume_bytes("Sig");
566
567 let alg = match (curve_name.as_str(), digest_name.as_str()) {
568 ("P-256", "SHA256") => &signature::ECDSA_P256_SHA256_ASN1_SIGNING,
569 ("P-384", "SHA384") => &signature::ECDSA_P384_SHA384_ASN1_SIGNING,
570 _ => {
571 panic!("Unsupported curve+digest: {}+{}", curve_name, digest_name);
572 }
573 };
574
575 let private_key =
576 signature::EcdsaKeyPair::from_private_key_and_public_key(alg, &d, &q).unwrap();
577 let rng = test::rand::FixedSliceRandom { bytes: &k };
578
579 let actual_result = private_key
580 .sign_with_fixed_nonce_during_test(&rng, &msg)
581 .unwrap();
582
583 assert_eq!(actual_result.as_ref(), &expected_result[..]);
584
585 Ok(())
586 },
587 );
588 }
589 }
590