mundane/public/ec/
mod.rs

1// Copyright 2020 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5//! Elliptic Curve-based cryptographic algorithms over NIST P curves.
6//!
7//! This module only supports elliptic curve cryptography over NIST's P curves,
8//! defined in FIPS 186-3. These are the P-256, P-384, and P-521 curves (P-224
9//! is considered insecure, and thus is not supported). The ECDSA and ECDH
10//! algorithms are both defined over P curves, and so are exposed in this
11//! module.
12//!
13//! Other elliptic curve algorithms on non-P curves live in other modules (e.g.,
14//! operations on the Edwards 25519 curve live in the [`ed25519`] module).
15//!
16//! [`ed25519`]: ::public::ed25519
17
18mod curve;
19
20pub use public::ec::curve::{PCurve, P256, P384, P521};
21
22use std::fmt::{self, Debug, Formatter};
23
24use boringssl::{CHeapWrapper, CStackWrapper};
25use public::ec::curve::CurveKind;
26use public::ec::inner::EcKey;
27use public::inner::DerKey;
28use public::{DerPrivateKey, DerPublicKey, PrivateKey, PublicKey};
29use util::Sealed;
30use Error;
31
32mod inner {
33    use std::marker::PhantomData;
34
35    use boringssl::{self, BoringError, CHeapWrapper, CStackWrapper};
36    use public::ec::curve::PCurve;
37    use public::inner::BoringDerKey;
38    use Error;
39
40    // A convenience wrapper around boringssl::EC_KEY.
41    //
42    // EcKey maintains the following invariants:
43    // - The key is valid.
44    // - The key is on the curve C.
45    //
46    // This is marked pub and put in this (non-public) module so that using it in impls of
47    // the Key trait don't result in public-in-private errors.
48    #[derive(Clone)]
49    pub struct EcKey<C: PCurve> {
50        pub key: CHeapWrapper<boringssl::EC_KEY>,
51        _marker: PhantomData<C>,
52    }
53
54    impl<C: PCurve> EcKey<C> {
55        pub fn generate() -> Result<EcKey<C>, BoringError> {
56            let mut key = CHeapWrapper::default();
57            // EC_KEY_set_group only errors if there's already a group set
58            key.ec_key_set_group(&C::group()).unwrap();
59            key.ec_key_generate_key()?;
60            Ok(EcKey { key, _marker: PhantomData })
61        }
62
63        /// Creates an `EcKey` from a BoringSSL `EC_KEY`.
64        ///
65        /// `from_EC_KEY` validates that `key`'s curve is `C`.
66        ///
67        /// # Panics
68        ///
69        /// `from_EC_KEY` panics if `key`'s group is not set.
70        #[allow(non_snake_case)]
71        pub fn from_EC_KEY(key: CHeapWrapper<boringssl::EC_KEY>) -> Result<EcKey<C>, Error> {
72            // ec_key_get0_group returns the EC_KEY's internal group pointer,
73            // which is guaranteed to be set by the caller.
74            C::validate_group(key.ec_key_get0_group().unwrap())?;
75            Ok(EcKey { key, _marker: PhantomData })
76        }
77    }
78
79    impl<C: PCurve> BoringDerKey for EcKey<C> {
80        fn pkey_assign(&self, pkey: &mut CHeapWrapper<boringssl::EVP_PKEY>) {
81            pkey.evp_pkey_assign_ec_key(self.key.clone())
82        }
83
84        // NOTE: panics if the key is an EC key and doesn't have a group set
85        // (due to EcKey::from_EC_KEY)
86        fn pkey_get(pkey: &mut CHeapWrapper<boringssl::EVP_PKEY>) -> Result<Self, Error> {
87            let key = pkey.evp_pkey_get1_ec_key()?;
88            EcKey::from_EC_KEY(key)
89        }
90
91        fn parse_private_key(cbs: &mut CStackWrapper<boringssl::CBS>) -> Result<EcKey<C>, Error> {
92            // The last argument is a group. If it's not None, then it is either
93            // used as the group or, if the DER encoding also contains a group,
94            // the encoded group is validated against the group passed as an
95            // argument. Note that this validation is mostly redundant - similar
96            // validation is performed in EcKey::from_EC_KEY - however, it's not
97            // fully redundant, since it allows keys to be parsed which have no
98            // group.
99            let key = CHeapWrapper::ec_key_parse_private_key(cbs, Some(C::group()))?;
100            EcKey::from_EC_KEY(key)
101        }
102
103        fn marshal_private_key(
104            &self,
105            cbb: &mut CStackWrapper<boringssl::CBB>,
106        ) -> Result<(), Error> {
107            self.key.ec_key_marshal_private_key(cbb).map_err(From::from)
108        }
109    }
110
111    #[cfg(test)]
112    mod tests {
113        use std::mem;
114
115        use super::*;
116        use public::ec::{P256, P384, P521};
117
118        #[test]
119        fn test_refcount() {
120            fn test<C: PCurve>() {
121                let key = EcKey::<C>::generate().unwrap();
122                for i in 0..8 {
123                    // make i clones and then free them all
124                    let mut keys = Vec::new();
125                    for _ in 0..i {
126                        keys.push(key.clone());
127                    }
128                    mem::drop(keys);
129                }
130                mem::drop(key);
131            }
132
133            test::<P256>();
134            test::<P384>();
135            test::<P521>();
136        }
137    }
138}
139
140/// An elliptic curve public key over a P curve.
141///
142/// `EcPubKey` is a public key over the curve `C`.
143pub struct EcPubKey<C: PCurve> {
144    inner: EcKey<C>,
145}
146
147impl<C: PCurve> Sealed for EcPubKey<C> {}
148impl<C: PCurve> DerPublicKey for EcPubKey<C> {}
149
150impl<C: PCurve> DerKey for EcPubKey<C> {
151    type Boring = EcKey<C>;
152    fn boring(&self) -> &EcKey<C> {
153        &self.inner
154    }
155    fn from_boring(inner: EcKey<C>) -> EcPubKey<C> {
156        EcPubKey { inner }
157    }
158}
159
160impl<C: PCurve> PublicKey for EcPubKey<C> {
161    type Private = EcPrivKey<C>;
162}
163
164impl<C: PCurve> Debug for EcPubKey<C> {
165    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
166        write!(f, "EcPubKey")
167    }
168}
169
170/// An elliptic curve private key over a P curve.
171///
172/// `EcPrivKey` is a private key over the curve `C`.
173pub struct EcPrivKey<C: PCurve> {
174    inner: EcKey<C>,
175}
176
177impl<C: PCurve> EcPrivKey<C> {
178    /// Generates a new private key.
179    #[must_use]
180    pub fn generate() -> Result<EcPrivKey<C>, Error> {
181        Ok(EcPrivKey { inner: EcKey::generate()? })
182    }
183}
184
185impl<C: PCurve> Sealed for EcPrivKey<C> {}
186impl<C: PCurve> DerPrivateKey for EcPrivKey<C> {}
187
188impl<C: PCurve> DerKey for EcPrivKey<C> {
189    type Boring = EcKey<C>;
190    fn boring(&self) -> &EcKey<C> {
191        &self.inner
192    }
193    fn from_boring(inner: EcKey<C>) -> EcPrivKey<C> {
194        EcPrivKey { inner }
195    }
196}
197
198impl<C: PCurve> PrivateKey for EcPrivKey<C> {
199    type Public = EcPubKey<C>;
200
201    fn public(&self) -> EcPubKey<C> {
202        EcPubKey { inner: self.inner.clone() }
203    }
204}
205
206impl<C: PCurve> Debug for EcPrivKey<C> {
207    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
208        write!(f, "EcPrivKey")
209    }
210}
211
212/// An elliptic curve public key whose curve is unknown at compile time.
213///
214/// An `EcPubKeyAnyCurve` is an enum of [`EcPubKey`]s over the three supported
215/// curves.
216#[allow(missing_docs)]
217#[derive(Debug)]
218pub enum EcPubKeyAnyCurve {
219    P256(EcPubKey<P256>),
220    P384(EcPubKey<P384>),
221    P521(EcPubKey<P521>),
222}
223
224impl EcPubKeyAnyCurve {
225    /// Parses a public key in DER format with any curve.
226    ///
227    /// `parse_from_der` is like [`DerPublicKey::parse_from_der`], but it
228    /// accepts any [`PCurve`] rather than a particular, static curve.
229    ///
230    /// Since [`EcPubKey`] requires a static [`PCurve`] type parameter, the
231    /// `parse_from_der` function on `EcPubKey`'s `DerPublicKey` implementation
232    /// can only be called when the curve is known ahead of time. This function,
233    /// on the other hand, accepts any curve.
234    ///
235    /// Because the curve is not known statically, one must be specified in the DER
236    /// input.
237    ///
238    /// [`DerPublicKey::parse_from_der`]: ::public::DerPublicKey::parse_from_der
239    /// [`PublicKey`]: ::public::PublicKey
240    #[must_use]
241    pub fn parse_from_der(bytes: &[u8]) -> Result<EcPubKeyAnyCurve, Error> {
242        CStackWrapper::cbs_with_temp_buffer(bytes, |cbs| {
243            let mut evp_pkey = CHeapWrapper::evp_parse_public_key(cbs)?;
244            let key = evp_pkey.evp_pkey_get1_ec_key()?;
245            if cbs.cbs_len() > 0 {
246                return Err(Error::new("excess data provided after valid DER input".to_string()));
247            }
248
249            // EVP_parse_public_key guarantees that the returned key has its group
250            // set, so this unwrap is safe.
251            let group = key.ec_key_get0_group().unwrap();
252            Ok(match CurveKind::from_nid(group.ec_group_get_curve_name())? {
253                CurveKind::P256 => {
254                    EcPubKeyAnyCurve::P256(EcPubKey { inner: EcKey::from_EC_KEY(key.clone())? })
255                }
256                CurveKind::P384 => {
257                    EcPubKeyAnyCurve::P384(EcPubKey { inner: EcKey::from_EC_KEY(key.clone())? })
258                }
259                CurveKind::P521 => {
260                    EcPubKeyAnyCurve::P521(EcPubKey { inner: EcKey::from_EC_KEY(key.clone())? })
261                }
262            })
263        })
264    }
265}
266
267/// An elliptic curve private key whose curve is unknown at compile time.
268///
269/// An `EcPrivKeyAnyCurve` is an enum of [`EcPrivKey`]s over the three supported
270/// curves.
271#[allow(missing_docs)]
272#[derive(Debug)]
273pub enum EcPrivKeyAnyCurve {
274    P256(EcPrivKey<P256>),
275    P384(EcPrivKey<P384>),
276    P521(EcPrivKey<P521>),
277}
278
279impl EcPrivKeyAnyCurve {
280    /// Gets the public key corresponding to this private key.
281    #[must_use]
282    pub fn public(&self) -> EcPubKeyAnyCurve {
283        match self {
284            EcPrivKeyAnyCurve::P256(key) => EcPubKeyAnyCurve::P256(key.public()),
285            EcPrivKeyAnyCurve::P384(key) => EcPubKeyAnyCurve::P384(key.public()),
286            EcPrivKeyAnyCurve::P521(key) => EcPubKeyAnyCurve::P521(key.public()),
287        }
288    }
289
290    /// Parses a private key in DER format with any curve.
291    ///
292    /// `parse_from_der` is like [`DerPrivateKey::parse_from_der`], but it
293    /// accepts any [`PCurve`] rather than a particular, static curve.
294    ///
295    /// Since [`EcPrivKey`] requires a static [`PCurve`] type parameter, the
296    /// `parse_from_der` function on `EcPrivKey`'s `DerPrivateKey`
297    /// implementation can only be called when the curve is known ahead of time.
298    /// This function, on the other hand, accepts any curve.
299    ///
300    /// Because the curve is not known statically, one must be specified in the DER
301    /// input.
302    ///
303    /// [`DerPrivateKey::parse_from_der`]: ::public::DerPrivateKey::parse_from_der
304    /// [`PrivateKey`]: ::public::PrivateKey
305    #[must_use]
306    pub fn parse_from_der(bytes: &[u8]) -> Result<EcPrivKeyAnyCurve, Error> {
307        CStackWrapper::cbs_with_temp_buffer(bytes, |cbs| {
308            // The last argument is a group. Since it's None,
309            // EC_KEY_parse_private_key will require the DER to name the group.
310            let key = CHeapWrapper::ec_key_parse_private_key(cbs, None)?;
311            if cbs.cbs_len() > 0 {
312                return Err(Error::new("excess data provided after valid DER input".to_string()));
313            }
314
315            // TODO(joshlf): Add documentation to EC_KEY_parse_private_key
316            // guaranteeing that the internal group pointer is set.
317            let group = key.ec_key_get0_group().unwrap();
318            Ok(match CurveKind::from_nid(group.ec_group_get_curve_name())? {
319                CurveKind::P256 => {
320                    EcPrivKeyAnyCurve::P256(EcPrivKey { inner: EcKey::from_EC_KEY(key.clone())? })
321                }
322                CurveKind::P384 => {
323                    EcPrivKeyAnyCurve::P384(EcPrivKey { inner: EcKey::from_EC_KEY(key.clone())? })
324                }
325                CurveKind::P521 => {
326                    EcPrivKeyAnyCurve::P521(EcPrivKey { inner: EcKey::from_EC_KEY(key.clone())? })
327                }
328            })
329        })
330    }
331}
332
333/// The Elliptic Curve Digital Signature Algorithm.
334pub mod ecdsa {
335    use std::fmt::{self, Debug, Formatter};
336    use std::marker::PhantomData;
337
338    use hash::inner::Digest;
339    #[cfg(feature = "experimental-sha512-ec")]
340    use hash::Sha512;
341    use hash::{Hasher, Sha256, Sha384};
342    use public::ec::{EcPrivKey, EcPubKey, PCurve, P256, P384, P521};
343    use public::Signature;
344    use util::Sealed;
345    use {boringssl, Error};
346
347    /// A hash function which is compatible with ECDSA signatures over the curve
348    /// `C`.
349    ///
350    /// An ECDSA signature is constructed by hashing the message and then
351    /// signing the resulting digest. However, EC keys over certain curves may
352    /// not be compatible with all hashes. In particular, some digests may be
353    /// too long (in number of bytes) and thus not correspond to a point on the
354    /// curve. `EcdsaHash<C>` is implemented by all hash functions whose digests
355    /// are compatible with ECDSA signatures over the curve `C`.
356    pub trait EcdsaHash<C: PCurve>: Sealed {}
357
358    impl EcdsaHash<P256> for Sha256 {}
359    impl EcdsaHash<P384> for Sha256 {}
360    impl EcdsaHash<P384> for Sha384 {}
361    impl EcdsaHash<P521> for Sha256 {}
362    impl EcdsaHash<P521> for Sha384 {}
363
364    #[cfg(feature = "experimental-sha512-ec")]
365    impl EcdsaHash<P384> for Sha512 {}
366
367    #[cfg(feature = "experimental-sha512-ec")]
368    impl EcdsaHash<P521> for Sha512 {}
369
370    // The maximum length of an ECDSA signature over P-521. Since this isn't
371    // exposed in the API, we can increase later if we add support for curves
372    // with larger signatures.
373    //
374    // This was calculated with the following equation, which is thanks to
375    // agl@google.com:
376    //
377    //  r = s = (521 + 7)/8              # Bytes to store the integers r and s
378    //        = 66
379    //  DER encoded bytes =   (1         # type byte 0x02
380    //                      +  1         # length byte
381    //                      +  1         # possible 0 padding
382    //                      +  66) * 2   # one for each of r and s
383    //                      +  1         # ASN.1 SEQUENCE type byte
384    //                      +  2         # outer length
385    //                    =    141
386    const MAX_SIGNATURE_LEN: usize = 141;
387
388    /// A DER-encoded ECDSA signature.
389    #[must_use]
390    pub struct EcdsaSignature<C: PCurve, H: Hasher + EcdsaHash<C>> {
391        bytes: [u8; MAX_SIGNATURE_LEN],
392        // Invariant: len is in [0; MAX_SIGNATURE_LEN). If len is 0, it
393        // indicates an invalid signature. Invalid signatures can be produced
394        // when a caller invokes from_bytes with a byte slice longer than
395        // MAX_SIGNATURE_LEN. Such signatures cannot possibly have been
396        // generated by an ECDSA signature over any of the curves we support,
397        // and so it could not possibly be valid. In other words, it would never
398        // be correct for Signature::is_valid to return true when invoked on such a
399        // signature.
400        //
401        // However, if we were to simply truncate the byte slice and store a
402        // subset of it, then we might open ourselves up to attacks in which an
403        // attacker induces a mismatch between the signature that the caller
404        // /thinks/ is being verified and the signature that is /actually/ being
405        // verified. Thus, it's important that we always reject such signatures.
406        //
407        // Finally, it's OK for us to use 0 as the sentinal value to mean
408        // "invalid signature" because ECDSA can never produce a 0-byte
409        // signature. Thus, we will never produce a 0-byte signature from
410        // ecdsa_sign, and similarly, if the caller constructs a 0-byte
411        // signature using from_bytes, it's correct for us to treat it as
412        // invalid.
413        len: usize,
414        _marker: PhantomData<(C, H)>,
415    }
416
417    impl<C: PCurve, H: Hasher + EcdsaHash<C>> EcdsaSignature<C, H> {
418        /// Constructs an `EcdsaSignature` from raw bytes.
419        #[must_use]
420        pub fn from_bytes(bytes: &[u8]) -> EcdsaSignature<C, H> {
421            if bytes.len() > MAX_SIGNATURE_LEN {
422                // see comment on the len field for why we do this
423                return Self::empty();
424            }
425            let mut ret = Self::empty();
426            (&mut ret.bytes[..bytes.len()]).copy_from_slice(bytes);
427            ret.len = bytes.len();
428            ret
429        }
430
431        // TODO(joshlf): Once we have const generics, have this return a
432        // fixed-length array.
433
434        /// Gets the raw bytes of this `EcdsaSignature`.
435        #[must_use]
436        pub fn bytes(&self) -> &[u8] {
437            &self.bytes[..self.len]
438        }
439
440        fn is_valid_format(&self) -> bool {
441            self.len != 0
442        }
443
444        fn empty() -> EcdsaSignature<C, H> {
445            EcdsaSignature { bytes: [0u8; MAX_SIGNATURE_LEN], len: 0, _marker: PhantomData }
446        }
447    }
448
449    impl<C: PCurve, H: Hasher + EcdsaHash<C>> Sealed for EcdsaSignature<C, H> {}
450    impl<C: PCurve, H: Hasher + EcdsaHash<C>> Signature for EcdsaSignature<C, H> {
451        type PrivateKey = EcPrivKey<C>;
452
453        fn sign(key: &EcPrivKey<C>, message: &[u8]) -> Result<EcdsaSignature<C, H>, Error> {
454            let digest = H::hash(message);
455            let mut sig = EcdsaSignature::empty();
456            sig.len = boringssl::ecdsa_sign(digest.as_ref(), &mut sig.bytes[..], &key.inner.key)?;
457            Ok(sig)
458        }
459
460        fn is_valid(&self, key: &EcPubKey<C>, message: &[u8]) -> bool {
461            if !self.is_valid_format() {
462                // see comment on EcdsaSignature::len for why we do this
463                return false;
464            }
465            let digest = H::hash(message);
466            boringssl::ecdsa_verify(digest.as_ref(), self.bytes(), &key.inner.key)
467        }
468    }
469
470    impl<C: PCurve, H: Hasher + EcdsaHash<C>> Debug for EcdsaSignature<C, H> {
471        fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
472            write!(f, "EcdsaSignature")
473        }
474    }
475
476    #[cfg(test)]
477    mod tests {
478        use super::super::*;
479        use super::*;
480        use public::testutil::test_signature_smoke;
481
482        #[test]
483        fn test_smoke() {
484            let p256 = EcPrivKey::<P256>::generate().unwrap();
485            let p384 = EcPrivKey::<P384>::generate().unwrap();
486            let p521 = EcPrivKey::<P521>::generate().unwrap();
487
488            test_signature_smoke(
489                &p256,
490                EcdsaSignature::<_, Sha256>::from_bytes,
491                EcdsaSignature::bytes,
492            );
493            test_signature_smoke(
494                &p384,
495                EcdsaSignature::<_, Sha256>::from_bytes,
496                EcdsaSignature::bytes,
497            );
498            test_signature_smoke(
499                &p384,
500                EcdsaSignature::<_, Sha384>::from_bytes,
501                EcdsaSignature::bytes,
502            );
503            test_signature_smoke(
504                &p521,
505                EcdsaSignature::<_, Sha256>::from_bytes,
506                EcdsaSignature::bytes,
507            );
508            test_signature_smoke(
509                &p521,
510                EcdsaSignature::<_, Sha384>::from_bytes,
511                EcdsaSignature::bytes,
512            );
513            #[cfg(feature = "experimental-sha512-ec")]
514            {
515                test_signature_smoke(
516                    &p384,
517                    EcdsaSignature::<_, Sha512>::from_bytes,
518                    EcdsaSignature::bytes,
519                );
520                test_signature_smoke(
521                    &p521,
522                    EcdsaSignature::<_, Sha512>::from_bytes,
523                    EcdsaSignature::bytes,
524                );
525            }
526        }
527
528        #[test]
529        fn test_invalid_signature() {
530            fn test_is_invalid(sig: &EcdsaSignature<P256, Sha256>) {
531                assert_eq!(sig.len, 0);
532                assert!(!sig.is_valid_format());
533                assert!(!sig.is_valid(&EcPrivKey::<P256>::generate().unwrap().public(), &[],));
534            }
535            test_is_invalid(&EcdsaSignature::from_bytes(&[0; MAX_SIGNATURE_LEN + 1]));
536            test_is_invalid(&EcdsaSignature::from_bytes(&[]));
537        }
538    }
539}
540
541#[cfg(test)]
542mod tests {
543    use super::*;
544    use hash::Sha256;
545    use public::ec::ecdsa::*;
546    use public::Signature;
547    use util::should_fail;
548
549    #[test]
550    fn test_generate() {
551        EcPrivKey::<P256>::generate().unwrap();
552        EcPrivKey::<P384>::generate().unwrap();
553        EcPrivKey::<P521>::generate().unwrap();
554    }
555
556    #[test]
557    fn test_marshal_parse() {
558        // Test various combinations of parsing and serializing keys.
559        //
560        // Since we need to test dynamic parsing (the
561        // parse_private_key_der_any_curve and parse_public_key_der_any_curve
562        // functions), we need a way of unwrapping their return values into a
563        // static key type. Unfortunately, there's no way (on stable Rust) to do
564        // that generically, so the caller must pass a function which will do
565        // it.
566        fn test<
567            C: PCurve,
568            F: Fn(EcPrivKeyAnyCurve) -> EcPrivKey<C>,
569            G: Fn(EcPubKeyAnyCurve) -> EcPubKey<C>,
570        >(
571            unwrap_priv_any: F,
572            unwrap_pub_any: G,
573        ) where
574            Sha256: EcdsaHash<C>,
575        {
576            const MESSAGE: &[u8] = &[0, 1, 2, 3, 4, 5, 6, 7];
577            let key = EcPrivKey::<C>::generate().unwrap();
578
579            let parsed_key = EcPrivKey::<C>::parse_from_der(&key.marshal_to_der()).unwrap();
580            let parsed_key_any_curve =
581                unwrap_priv_any(EcPrivKeyAnyCurve::parse_from_der(&key.marshal_to_der()).unwrap());
582            let pubkey = key.public();
583            let parsed_pubkey = EcPubKey::<C>::parse_from_der(&pubkey.marshal_to_der()).unwrap();
584            let parsed_pubkey_any_curve =
585                unwrap_pub_any(EcPubKeyAnyCurve::parse_from_der(&pubkey.marshal_to_der()).unwrap());
586
587            fn sign_and_verify<C: PCurve>(privkey: &EcPrivKey<C>, pubkey: &EcPubKey<C>)
588            where
589                Sha256: EcdsaHash<C>,
590            {
591                let sig = EcdsaSignature::<C, Sha256>::sign(&privkey, MESSAGE).unwrap();
592                assert!(
593                    EcdsaSignature::<C, Sha256>::from_bytes(sig.bytes()).is_valid(&pubkey, MESSAGE)
594                )
595            }
596
597            // Sign and verify with every pair of keys to make sure we parsed
598            // the same key we marshaled.
599            sign_and_verify(&key, &pubkey);
600            sign_and_verify(&key, &parsed_pubkey);
601            sign_and_verify(&key, &parsed_pubkey_any_curve);
602            sign_and_verify(&parsed_key, &pubkey);
603            sign_and_verify(&parsed_key, &parsed_pubkey);
604            sign_and_verify(&parsed_key, &parsed_pubkey_any_curve);
605            sign_and_verify(&parsed_key_any_curve, &pubkey);
606            sign_and_verify(&parsed_key_any_curve, &parsed_pubkey);
607            sign_and_verify(&parsed_key_any_curve, &parsed_pubkey_any_curve);
608
609            let _ = EcPubKey::<C>::marshal_to_der;
610            let _ = EcPubKey::<C>::parse_from_der;
611        }
612
613        macro_rules! unwrap_any_curve {
614            ($name:ident, $any_type:ty, $key_type:ty, $curve_variant:path) => {
615                fn $name(key: $any_type) -> $key_type {
616                    match key {
617                        $curve_variant(key) => key,
618                        _ => panic!("unexpected curve"),
619                    }
620                }
621            };
622        }
623
624        unwrap_any_curve!(
625            unwrap_priv_key_any_p256,
626            EcPrivKeyAnyCurve,
627            EcPrivKey<P256>,
628            EcPrivKeyAnyCurve::P256
629        );
630        unwrap_any_curve!(
631            unwrap_priv_key_any_p384,
632            EcPrivKeyAnyCurve,
633            EcPrivKey<P384>,
634            EcPrivKeyAnyCurve::P384
635        );
636        unwrap_any_curve!(
637            unwrap_priv_key_any_p521,
638            EcPrivKeyAnyCurve,
639            EcPrivKey<P521>,
640            EcPrivKeyAnyCurve::P521
641        );
642        unwrap_any_curve!(
643            unwrap_pub_key_any_p256,
644            EcPubKeyAnyCurve,
645            EcPubKey<P256>,
646            EcPubKeyAnyCurve::P256
647        );
648        unwrap_any_curve!(
649            unwrap_pub_key_any_p384,
650            EcPubKeyAnyCurve,
651            EcPubKey<P384>,
652            EcPubKeyAnyCurve::P384
653        );
654        unwrap_any_curve!(
655            unwrap_pub_key_any_p521,
656            EcPubKeyAnyCurve,
657            EcPubKey<P521>,
658            EcPubKeyAnyCurve::P521
659        );
660
661        test::<P256, _, _>(unwrap_priv_key_any_p256, unwrap_pub_key_any_p256);
662        test::<P384, _, _>(unwrap_priv_key_any_p384, unwrap_pub_key_any_p384);
663        test::<P521, _, _>(unwrap_priv_key_any_p521, unwrap_pub_key_any_p521);
664    }
665
666    #[test]
667    fn test_parse_fail() {
668        // Test that invalid input is rejected.
669        fn test_parse_invalid<C: PCurve>() {
670            should_fail(
671                EcPrivKey::<C>::parse_from_der(&[]),
672                "EcPrivKey::parse_from_der",
673                "elliptic curve routines:OPENSSL_internal:DECODE_ERROR",
674            );
675            should_fail(
676                EcPubKey::<C>::parse_from_der(&[]),
677                "EcPubKey::parse_from_der",
678                "public key routines:OPENSSL_internal:DECODE_ERROR",
679            );
680            should_fail(
681                EcPrivKeyAnyCurve::parse_from_der(&[]),
682                "EcPrivKeyAnyCurve::parse_from_der",
683                "elliptic curve routines:OPENSSL_internal:DECODE_ERROR",
684            );
685            should_fail(
686                EcPubKeyAnyCurve::parse_from_der(&[]),
687                "EcPubKeyAnyCurve::parse_from_der",
688                "public key routines:OPENSSL_internal:DECODE_ERROR",
689            );
690        }
691
692        test_parse_invalid::<P256>();
693        test_parse_invalid::<P384>();
694        test_parse_invalid::<P521>();
695
696        // Test that, when a particular curve is expected, other curves are
697        // rejected.
698        fn test_parse_wrong_curve<C1: PCurve, C2: PCurve>() {
699            let privkey = EcPrivKey::<C1>::generate().unwrap();
700            let key_der = privkey.marshal_to_der();
701            should_fail(
702                EcPrivKey::<C2>::parse_from_der(&key_der),
703                "EcPrivKey::parse_from_der",
704                "elliptic curve routines:OPENSSL_internal:GROUP_MISMATCH",
705            );
706            let key_der = privkey.public().marshal_to_der();
707            should_fail(
708                EcPubKey::<C2>::parse_from_der(&key_der),
709                "EcPubKey::parse_from_der",
710                "unexpected curve:",
711            );
712        }
713
714        // All pairs of curves, (X, Y), such that X != Y.
715        test_parse_wrong_curve::<P256, P384>();
716        test_parse_wrong_curve::<P256, P521>();
717        test_parse_wrong_curve::<P384, P256>();
718        test_parse_wrong_curve::<P384, P521>();
719        test_parse_wrong_curve::<P521, P256>();
720        test_parse_wrong_curve::<P521, P384>();
721    }
722}