eigen_crypto/ec/suite_b/ecdsa/signing.rs
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.
16use std::prelude::v1::*;
17
18use super::digest_scalar::digest_scalar;
19use crate::{
20 arithmetic::montgomery::*,
21 ec::{
22 self,
23 suite_b::{ops::*, private_key},
24 },
25 errors::{Error, ErrorKind, Result},
26 io::der,
27 limb,
28};
29use ring::digest;
30
31/// An ECDSA signing algorithm.
32pub 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 format_rs: fn(ops: &'static ScalarOps, r: &Scalar, s: &Scalar, out: &mut [u8]) -> usize,
38 id: AlgorithmID,
39}
40
41#[derive(Debug, Eq, PartialEq)]
42enum AlgorithmID {
43 ECDSA_P256_SHA256_ASN1_SIGNING,
44}
45
46derive_debug_via_id!(EcdsaSigningAlgorithm);
47
48impl PartialEq for EcdsaSigningAlgorithm {
49 fn eq(&self, other: &Self) -> bool {
50 self.id == other.id
51 }
52}
53
54impl Eq for EcdsaSigningAlgorithm {}
55
56/// An ECDSA key pair, used for signing.
57pub struct EcdsaKeyPair {
58 d: Scalar<R>,
59 alg: &'static EcdsaSigningAlgorithm,
60 public_key: PublicKey,
61 seed: Vec<u8>, // For backup
62}
63
64derive_debug_via_field!(EcdsaKeyPair, stringify!(EcdsaKeyPair), public_key);
65
66impl EcdsaKeyPair {
67 /// Generates a new key pair and returns the key pair serialized as a
68 /// PKCS#8 document.
69 ///
70 /// The PKCS#8 document will be a v1 `OneAsymmetricKey` with the public key
71 /// included in the `ECPrivateKey` structure, as described in
72 /// [RFC 5958 Section 2] and [RFC 5915]. The `ECPrivateKey` structure will
73 /// not have a `parameters` field so the generated key is compatible with
74 /// PKCS#11.
75 ///
76 /// [RFC 5915]: https://tools.ietf.org/html/rfc5915
77 /// [RFC 5958 Section 2]: https://tools.ietf.org/html/rfc5958#section-2
78 /*
79 pub fn generate_pkcs8(
80 alg: &'static EcdsaSigningAlgorithm,
81 rng: &dyn rand::SecureRandom,
82 ) -> Result<pkcs8::Document> {
83 let private_key = ec::Seed::generate(alg.curve, rng, cpu::features())?;
84 let public_key = private_key.compute_public_key()?;
85 Ok(pkcs8::wrap_key(
86 &alg.pkcs8_template,
87 private_key.bytes_less_safe(),
88 public_key.as_ref(),
89 ))
90 }
91 */
92
93 /// Constructs an ECDSA key pair by parsing an unencrypted PKCS#8 v1
94 /// id-ecPublicKey `ECPrivateKey` key.
95 ///
96 /// The input must be in PKCS#8 v1 format. It must contain the public key in
97 /// the `ECPrivateKey` structure; `from_pkcs8()` will verify that the public
98 /// key and the private key are consistent with each other. The algorithm
99 /// identifier must identify the curve by name; it must not use an
100 /// "explicit" encoding of the curve. The `parameters` field of the
101 /// `ECPrivateKey`, if present, must be the same named curve that is in the
102 /// algorithm identifier in the PKCS#8 header.
103 /*
104 pub fn from_pkcs8(
105 alg: &'static EcdsaSigningAlgorithm,
106 pkcs8: &[u8],
107 ) -> Result<Self, error::KeyRejected> {
108 let key_pair = ec::suite_b::key_pair_from_pkcs8(
109 alg.curve,
110 alg.pkcs8_template,
111 untrusted::Input::from(pkcs8),
112 cpu::features(),
113 )?;
114 Ok(Self::new(alg, key_pair))
115 }
116 */
117
118 pub fn from_seed_unchecked(
119 alg: &'static EcdsaSigningAlgorithm,
120 salt: untrusted::Input,
121 ) -> Result<Self> {
122 let seed = ec::Seed::from_bytes(alg.curve, salt)?;
123 let key_pair = ec::KeyPair::derive(seed)?;
124 Ok(Self::new(alg, key_pair))
125 }
126
127 fn new(alg: &'static EcdsaSigningAlgorithm, key_pair: ec::KeyPair) -> Self {
128 let (seed, public_key) = key_pair.split();
129 let d = private_key::private_key_as_scalar(alg.private_key_ops, &seed);
130 let d = alg
131 .private_scalar_ops
132 .scalar_ops
133 .scalar_product(&d, &alg.private_scalar_ops.oneRR_mod_n);
134
135 Self {
136 seed: seed.bytes_less_safe().to_vec(),
137 d,
138 alg,
139 public_key: PublicKey(public_key),
140 }
141 }
142
143 pub fn seed_as_bytes(&self) -> Vec<u8> {
144 self.seed.to_owned().into()
145 }
146
147 /// Returns the signature of the `message` using a random nonce
148 /// generated by `rng`.
149 pub fn sign(&self, message: &[u8]) -> Result<crate::sign::ecdsa::Signature> {
150 // Step 4 (out of order).
151 let h = digest::digest(self.alg.digest_alg, message);
152 self.sign_(h)
153 }
154
155 /// Returns the signature of message digest `h` using a "random" nonce
156 /// generated by `rng`.
157 fn sign_(&self, h: digest::Digest) -> Result<crate::sign::ecdsa::Signature> {
158 // NSA Suite B Implementer's Guide to ECDSA Section 3.4.1: ECDSA
159 // Signature Generation.
160
161 // NSA Guide Prerequisites:
162 //
163 // Prior to generating an ECDSA signature, the signatory shall
164 // obtain:
165 //
166 // 1. an authentic copy of the domain parameters,
167 // 2. a digital signature key pair (d,Q), either generated by a
168 // method from Appendix A.1, or obtained from a trusted third
169 // party,
170 // 3. assurance of the validity of the public key Q (see Appendix
171 // A.3), and
172 // 4. assurance that he/she/it actually possesses the associated
173 // private key d (see [SP800-89] Section 6).
174 //
175 // The domain parameters are hard-coded into the source code.
176 // `EcdsaKeyPair::generate_pkcs8()` can be used to meet the second
177 // requirement; otherwise, it is up to the user to ensure the key pair
178 // was obtained from a trusted private key. The constructors for
179 // `EcdsaKeyPair` ensure that #3 and #4 are met subject to the caveats
180 // in SP800-89 Section 6.
181
182 let ops = self.alg.private_scalar_ops;
183 let scalar_ops = ops.scalar_ops;
184 let cops = scalar_ops.common;
185 let private_key_ops = self.alg.private_key_ops;
186
187 for _ in 0..100 {
188 // XXX: iteration conut?
189 // Step 1.
190 let k = private_key::random_scalar(self.alg.private_key_ops)?;
191 let k_inv = scalar_ops.scalar_inv_to_mont(&k);
192
193 // Step 2.
194 let r = private_key_ops.point_mul_base(&k);
195
196 // Step 3.
197 let r = {
198 let (x, _) = private_key::affine_from_jacobian(private_key_ops, &r)?;
199 let x = cops.elem_unencoded(&x);
200 elem_reduced_to_scalar(cops, &x)
201 };
202 if cops.is_zero(&r) {
203 continue;
204 }
205
206 // Step 4 is done by the caller.
207
208 // Step 5.
209 let e = digest_scalar(scalar_ops, h);
210
211 // Step 6.
212 let s = {
213 let dr = scalar_ops.scalar_product(&self.d, &r);
214 let e_plus_dr = scalar_sum(cops, &e, &dr);
215 scalar_ops.scalar_product(&k_inv, &e_plus_dr)
216 };
217 if cops.is_zero(&s) {
218 continue;
219 }
220
221 // Step 7 with encoding.
222 return Ok(crate::sign::ecdsa::Signature::new(|sig_bytes| {
223 (self.alg.format_rs)(scalar_ops, &r, &s, sig_bytes)
224 }));
225 }
226
227 Err(Error::from(ErrorKind::CryptoError))
228 }
229}
230
231impl crate::sign::ecdsa::KeyPair for EcdsaKeyPair {
232 type PublicKey = PublicKey;
233
234 fn public_key(&self) -> &Self::PublicKey {
235 &self.public_key
236 }
237}
238
239#[derive(Clone, Copy)]
240pub struct PublicKey(ec::PublicKey);
241
242derive_debug_self_as_ref_hex_bytes!(PublicKey);
243
244impl AsRef<[u8]> for PublicKey {
245 fn as_ref(&self) -> &[u8] {
246 self.0.as_ref()
247 }
248}
249
250/// Signing of ASN.1 DER-encoded ECDSA signatures using the P-256 curve and
251/// SHA-256.
252///
253/// See "`ECDSA_*_ASN1` Details" in `ring::signature`'s module-level
254/// documentation for more details.
255pub static ECDSA_P256_SHA256_ASN1_SIGNING: EcdsaSigningAlgorithm = EcdsaSigningAlgorithm {
256 curve: &ec::suite_b::curve::P256,
257 private_scalar_ops: &p256::PRIVATE_SCALAR_OPS,
258 private_key_ops: &p256::PRIVATE_KEY_OPS,
259 digest_alg: &digest::SHA256,
260 format_rs: format_rs_asn1,
261 id: AlgorithmID::ECDSA_P256_SHA256_ASN1_SIGNING,
262};
263
264fn format_rs_asn1(ops: &'static ScalarOps, r: &Scalar, s: &Scalar, out: &mut [u8]) -> usize {
265 // This assumes `a` is not zero since neither `r` or `s` is allowed to be
266 // zero.
267 fn format_integer_tlv(ops: &ScalarOps, a: &Scalar, out: &mut [u8]) -> usize {
268 let mut fixed = [0u8; ec::SCALAR_MAX_BYTES + 1];
269 let fixed = &mut fixed[..(ops.scalar_bytes_len() + 1)];
270 limb::big_endian_from_limbs(&a.limbs[..ops.common.num_limbs], &mut fixed[1..]);
271
272 // Since `a_fixed_out` is an extra byte long, it is guaranteed to start
273 // with a zero.
274 debug_assert_eq!(fixed[0], 0);
275
276 // There must be at least one non-zero byte since `a` isn't zero.
277 let first_index = fixed.iter().position(|b| *b != 0).unwrap();
278
279 // If the first byte has its high bit set, it needs to be prefixed with 0x00.
280 let first_index = if fixed[first_index] & 0x80 != 0 {
281 first_index - 1
282 } else {
283 first_index
284 };
285 let value = &fixed[first_index..];
286
287 out[0] = der::Tag::Integer as u8;
288
289 // Lengths less than 128 are encoded in one byte.
290 assert!(value.len() < 128);
291 out[1] = value.len() as u8;
292
293 out[2..][..value.len()].copy_from_slice(&value);
294
295 2 + value.len()
296 }
297
298 out[0] = der::Tag::Sequence as u8;
299 let r_tlv_len = format_integer_tlv(ops, r, &mut out[2..]);
300 let s_tlv_len = format_integer_tlv(ops, s, &mut out[2..][r_tlv_len..]);
301
302 // Lengths less than 128 are encoded in one byte.
303 let value_len = r_tlv_len + s_tlv_len;
304 assert!(value_len < 128);
305 out[1] = value_len as u8;
306
307 2 + value_len
308}