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}