192f3ab15Sopenharmony_ci//! Elliptic Curve
292f3ab15Sopenharmony_ci//!
392f3ab15Sopenharmony_ci//! Cryptography relies on the difficulty of solving mathematical problems, such as the factor
492f3ab15Sopenharmony_ci//! of large integers composed of two large prime numbers and the discrete logarithm of a
592f3ab15Sopenharmony_ci//! random elliptic curve.  This module provides low-level features of the latter.
692f3ab15Sopenharmony_ci//! Elliptic Curve protocols can provide the same security with smaller keys.
792f3ab15Sopenharmony_ci//!
892f3ab15Sopenharmony_ci//! There are 2 forms of elliptic curves, `Fp` and `F2^m`.  These curves use irreducible
992f3ab15Sopenharmony_ci//! trinomial or pentanomial.  Being a generic interface to a wide range of algorithms,
1092f3ab15Sopenharmony_ci//! the curves are generally referenced by [`EcGroup`].  There are many built-in groups
1192f3ab15Sopenharmony_ci//! found in [`Nid`].
1292f3ab15Sopenharmony_ci//!
1392f3ab15Sopenharmony_ci//! OpenSSL Wiki explains the fields and curves in detail at [Elliptic Curve Cryptography].
1492f3ab15Sopenharmony_ci//!
1592f3ab15Sopenharmony_ci//! [`EcGroup`]: struct.EcGroup.html
1692f3ab15Sopenharmony_ci//! [`Nid`]: ../nid/struct.Nid.html
1792f3ab15Sopenharmony_ci//! [Elliptic Curve Cryptography]: https://wiki.openssl.org/index.php/Elliptic_Curve_Cryptography
1892f3ab15Sopenharmony_ciuse cfg_if::cfg_if;
1992f3ab15Sopenharmony_ciuse foreign_types::{ForeignType, ForeignTypeRef};
2092f3ab15Sopenharmony_ciuse libc::c_int;
2192f3ab15Sopenharmony_ciuse std::fmt;
2292f3ab15Sopenharmony_ciuse std::ptr;
2392f3ab15Sopenharmony_ci
2492f3ab15Sopenharmony_ciuse crate::bn::{BigNum, BigNumContextRef, BigNumRef};
2592f3ab15Sopenharmony_ciuse crate::error::ErrorStack;
2692f3ab15Sopenharmony_ciuse crate::nid::Nid;
2792f3ab15Sopenharmony_ciuse crate::pkey::{HasParams, HasPrivate, HasPublic, Params, Private, Public};
2892f3ab15Sopenharmony_ciuse crate::util::ForeignTypeRefExt;
2992f3ab15Sopenharmony_ciuse crate::{cvt, cvt_n, cvt_p, init};
3092f3ab15Sopenharmony_ciuse openssl_macros::corresponds;
3192f3ab15Sopenharmony_ci
3292f3ab15Sopenharmony_cicfg_if! {
3392f3ab15Sopenharmony_ci    if #[cfg(not(boringssl))] {
3492f3ab15Sopenharmony_ci        use std::ffi::CString;
3592f3ab15Sopenharmony_ci        use crate::string::OpensslString;
3692f3ab15Sopenharmony_ci    }
3792f3ab15Sopenharmony_ci}
3892f3ab15Sopenharmony_ci
3992f3ab15Sopenharmony_ci/// Compressed or Uncompressed conversion
4092f3ab15Sopenharmony_ci///
4192f3ab15Sopenharmony_ci/// Conversion from the binary value of the point on the curve is performed in one of
4292f3ab15Sopenharmony_ci/// compressed, uncompressed, or hybrid conversions.  The default is compressed, except
4392f3ab15Sopenharmony_ci/// for binary curves.
4492f3ab15Sopenharmony_ci///
4592f3ab15Sopenharmony_ci/// Further documentation is available in the [X9.62] standard.
4692f3ab15Sopenharmony_ci///
4792f3ab15Sopenharmony_ci/// [X9.62]: http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.202.2977&rep=rep1&type=pdf
4892f3ab15Sopenharmony_ci#[derive(Copy, Clone)]
4992f3ab15Sopenharmony_cipub struct PointConversionForm(ffi::point_conversion_form_t);
5092f3ab15Sopenharmony_ci
5192f3ab15Sopenharmony_ciimpl PointConversionForm {
5292f3ab15Sopenharmony_ci    /// Compressed conversion from point value.
5392f3ab15Sopenharmony_ci    pub const COMPRESSED: PointConversionForm =
5492f3ab15Sopenharmony_ci        PointConversionForm(ffi::point_conversion_form_t::POINT_CONVERSION_COMPRESSED);
5592f3ab15Sopenharmony_ci
5692f3ab15Sopenharmony_ci    /// Uncompressed conversion from point value.
5792f3ab15Sopenharmony_ci    pub const UNCOMPRESSED: PointConversionForm =
5892f3ab15Sopenharmony_ci        PointConversionForm(ffi::point_conversion_form_t::POINT_CONVERSION_UNCOMPRESSED);
5992f3ab15Sopenharmony_ci
6092f3ab15Sopenharmony_ci    /// Performs both compressed and uncompressed conversions.
6192f3ab15Sopenharmony_ci    pub const HYBRID: PointConversionForm =
6292f3ab15Sopenharmony_ci        PointConversionForm(ffi::point_conversion_form_t::POINT_CONVERSION_HYBRID);
6392f3ab15Sopenharmony_ci}
6492f3ab15Sopenharmony_ci
6592f3ab15Sopenharmony_ci/// Named Curve or Explicit
6692f3ab15Sopenharmony_ci///
6792f3ab15Sopenharmony_ci/// This type acts as a boolean as to whether the `EcGroup` is named or explicit.
6892f3ab15Sopenharmony_ci#[derive(Copy, Clone, Debug, PartialEq)]
6992f3ab15Sopenharmony_cipub struct Asn1Flag(c_int);
7092f3ab15Sopenharmony_ci
7192f3ab15Sopenharmony_ciimpl Asn1Flag {
7292f3ab15Sopenharmony_ci    /// Curve defined using polynomial parameters
7392f3ab15Sopenharmony_ci    ///
7492f3ab15Sopenharmony_ci    /// Most applications use a named EC_GROUP curve, however, support
7592f3ab15Sopenharmony_ci    /// is included to explicitly define the curve used to calculate keys
7692f3ab15Sopenharmony_ci    /// This information would need to be known by both endpoint to make communication
7792f3ab15Sopenharmony_ci    /// effective.
7892f3ab15Sopenharmony_ci    ///
7992f3ab15Sopenharmony_ci    /// OPENSSL_EC_EXPLICIT_CURVE, but that was only added in 1.1.
8092f3ab15Sopenharmony_ci    /// Man page documents that 0 can be used in older versions.
8192f3ab15Sopenharmony_ci    ///
8292f3ab15Sopenharmony_ci    /// OpenSSL documentation at [`EC_GROUP`]
8392f3ab15Sopenharmony_ci    ///
8492f3ab15Sopenharmony_ci    /// [`EC_GROUP`]: https://www.openssl.org/docs/manmaster/crypto/EC_GROUP_get_seed_len.html
8592f3ab15Sopenharmony_ci    pub const EXPLICIT_CURVE: Asn1Flag = Asn1Flag(0);
8692f3ab15Sopenharmony_ci
8792f3ab15Sopenharmony_ci    /// Standard Curves
8892f3ab15Sopenharmony_ci    ///
8992f3ab15Sopenharmony_ci    /// Curves that make up the typical encryption use cases.  The collection of curves
9092f3ab15Sopenharmony_ci    /// are well known but extensible.
9192f3ab15Sopenharmony_ci    ///
9292f3ab15Sopenharmony_ci    /// OpenSSL documentation at [`EC_GROUP`]
9392f3ab15Sopenharmony_ci    ///
9492f3ab15Sopenharmony_ci    /// [`EC_GROUP`]: https://www.openssl.org/docs/manmaster/man3/EC_GROUP_order_bits.html
9592f3ab15Sopenharmony_ci    pub const NAMED_CURVE: Asn1Flag = Asn1Flag(ffi::OPENSSL_EC_NAMED_CURVE);
9692f3ab15Sopenharmony_ci}
9792f3ab15Sopenharmony_ci
9892f3ab15Sopenharmony_ciforeign_type_and_impl_send_sync! {
9992f3ab15Sopenharmony_ci    type CType = ffi::EC_GROUP;
10092f3ab15Sopenharmony_ci    fn drop = ffi::EC_GROUP_free;
10192f3ab15Sopenharmony_ci
10292f3ab15Sopenharmony_ci    /// Describes the curve
10392f3ab15Sopenharmony_ci    ///
10492f3ab15Sopenharmony_ci    /// A curve can be of the named curve type.  These curves can be discovered
10592f3ab15Sopenharmony_ci    /// using openssl binary `openssl ecparam -list_curves`.  Other operations
10692f3ab15Sopenharmony_ci    /// are available in the [wiki].  These named curves are available in the
10792f3ab15Sopenharmony_ci    /// [`Nid`] module.
10892f3ab15Sopenharmony_ci    ///
10992f3ab15Sopenharmony_ci    /// Curves can also be generated using prime field parameters or a binary field.
11092f3ab15Sopenharmony_ci    ///
11192f3ab15Sopenharmony_ci    /// Prime fields use the formula `y^2 mod p = x^3 + ax + b mod p`.  Binary
11292f3ab15Sopenharmony_ci    /// fields use the formula `y^2 + xy = x^3 + ax^2 + b`.  Named curves have
11392f3ab15Sopenharmony_ci    /// assured security.  To prevent accidental vulnerabilities, they should
11492f3ab15Sopenharmony_ci    /// be preferred.
11592f3ab15Sopenharmony_ci    ///
11692f3ab15Sopenharmony_ci    /// [wiki]: https://wiki.openssl.org/index.php/Command_Line_Elliptic_Curve_Operations
11792f3ab15Sopenharmony_ci    /// [`Nid`]: ../nid/index.html
11892f3ab15Sopenharmony_ci    pub struct EcGroup;
11992f3ab15Sopenharmony_ci    /// Reference to [`EcGroup`]
12092f3ab15Sopenharmony_ci    ///
12192f3ab15Sopenharmony_ci    /// [`EcGroup`]: struct.EcGroup.html
12292f3ab15Sopenharmony_ci    pub struct EcGroupRef;
12392f3ab15Sopenharmony_ci}
12492f3ab15Sopenharmony_ci
12592f3ab15Sopenharmony_ciimpl EcGroup {
12692f3ab15Sopenharmony_ci    /// Returns the group of a standard named curve.
12792f3ab15Sopenharmony_ci    ///
12892f3ab15Sopenharmony_ci    /// # Examples
12992f3ab15Sopenharmony_ci    ///
13092f3ab15Sopenharmony_ci    /// ```
13192f3ab15Sopenharmony_ci    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
13292f3ab15Sopenharmony_ci    /// use openssl::nid::Nid;
13392f3ab15Sopenharmony_ci    /// use openssl::ec::{EcGroup, EcKey};
13492f3ab15Sopenharmony_ci    ///
13592f3ab15Sopenharmony_ci    /// let nid = Nid::X9_62_PRIME256V1; // NIST P-256 curve
13692f3ab15Sopenharmony_ci    /// let group = EcGroup::from_curve_name(nid)?;
13792f3ab15Sopenharmony_ci    /// let key = EcKey::generate(&group)?;
13892f3ab15Sopenharmony_ci    /// # Ok(()) }
13992f3ab15Sopenharmony_ci    /// ```
14092f3ab15Sopenharmony_ci    #[corresponds(EC_GROUP_new_by_curve_name)]
14192f3ab15Sopenharmony_ci    pub fn from_curve_name(nid: Nid) -> Result<EcGroup, ErrorStack> {
14292f3ab15Sopenharmony_ci        unsafe {
14392f3ab15Sopenharmony_ci            init();
14492f3ab15Sopenharmony_ci            cvt_p(ffi::EC_GROUP_new_by_curve_name(nid.as_raw())).map(EcGroup)
14592f3ab15Sopenharmony_ci        }
14692f3ab15Sopenharmony_ci    }
14792f3ab15Sopenharmony_ci
14892f3ab15Sopenharmony_ci    /// Returns the group for given parameters
14992f3ab15Sopenharmony_ci    #[corresponds(EC_GROUP_new_curve_GFp)]
15092f3ab15Sopenharmony_ci    pub fn from_components(
15192f3ab15Sopenharmony_ci        p: BigNum,
15292f3ab15Sopenharmony_ci        a: BigNum,
15392f3ab15Sopenharmony_ci        b: BigNum,
15492f3ab15Sopenharmony_ci        ctx: &mut BigNumContextRef,
15592f3ab15Sopenharmony_ci    ) -> Result<EcGroup, ErrorStack> {
15692f3ab15Sopenharmony_ci        unsafe {
15792f3ab15Sopenharmony_ci            cvt_p(ffi::EC_GROUP_new_curve_GFp(
15892f3ab15Sopenharmony_ci                p.as_ptr(),
15992f3ab15Sopenharmony_ci                a.as_ptr(),
16092f3ab15Sopenharmony_ci                b.as_ptr(),
16192f3ab15Sopenharmony_ci                ctx.as_ptr(),
16292f3ab15Sopenharmony_ci            ))
16392f3ab15Sopenharmony_ci            .map(EcGroup)
16492f3ab15Sopenharmony_ci        }
16592f3ab15Sopenharmony_ci    }
16692f3ab15Sopenharmony_ci}
16792f3ab15Sopenharmony_ci
16892f3ab15Sopenharmony_ciimpl EcGroupRef {
16992f3ab15Sopenharmony_ci    /// Places the components of a curve over a prime field in the provided `BigNum`s.
17092f3ab15Sopenharmony_ci    /// The components make up the formula `y^2 mod p = x^3 + ax + b mod p`.
17192f3ab15Sopenharmony_ci    #[corresponds(EC_GROUP_get_curve_GFp)]
17292f3ab15Sopenharmony_ci    pub fn components_gfp(
17392f3ab15Sopenharmony_ci        &self,
17492f3ab15Sopenharmony_ci        p: &mut BigNumRef,
17592f3ab15Sopenharmony_ci        a: &mut BigNumRef,
17692f3ab15Sopenharmony_ci        b: &mut BigNumRef,
17792f3ab15Sopenharmony_ci        ctx: &mut BigNumContextRef,
17892f3ab15Sopenharmony_ci    ) -> Result<(), ErrorStack> {
17992f3ab15Sopenharmony_ci        unsafe {
18092f3ab15Sopenharmony_ci            cvt(ffi::EC_GROUP_get_curve_GFp(
18192f3ab15Sopenharmony_ci                self.as_ptr(),
18292f3ab15Sopenharmony_ci                p.as_ptr(),
18392f3ab15Sopenharmony_ci                a.as_ptr(),
18492f3ab15Sopenharmony_ci                b.as_ptr(),
18592f3ab15Sopenharmony_ci                ctx.as_ptr(),
18692f3ab15Sopenharmony_ci            ))
18792f3ab15Sopenharmony_ci            .map(|_| ())
18892f3ab15Sopenharmony_ci        }
18992f3ab15Sopenharmony_ci    }
19092f3ab15Sopenharmony_ci
19192f3ab15Sopenharmony_ci    /// Places the components of a curve over a binary field in the provided `BigNum`s.
19292f3ab15Sopenharmony_ci    /// The components make up the formula `y^2 + xy = x^3 + ax^2 + b`.
19392f3ab15Sopenharmony_ci    ///
19492f3ab15Sopenharmony_ci    /// In this form `p` relates to the irreducible polynomial.  Each bit represents
19592f3ab15Sopenharmony_ci    /// a term in the polynomial.  It will be set to 3 `1`s or 5 `1`s depending on
19692f3ab15Sopenharmony_ci    /// using a trinomial or pentanomial.
19792f3ab15Sopenharmony_ci    #[corresponds(EC_GROUP_get_curve_GF2m)]
19892f3ab15Sopenharmony_ci    #[cfg(not(any(boringssl, osslconf = "OPENSSL_NO_EC2M")))]
19992f3ab15Sopenharmony_ci    pub fn components_gf2m(
20092f3ab15Sopenharmony_ci        &self,
20192f3ab15Sopenharmony_ci        p: &mut BigNumRef,
20292f3ab15Sopenharmony_ci        a: &mut BigNumRef,
20392f3ab15Sopenharmony_ci        b: &mut BigNumRef,
20492f3ab15Sopenharmony_ci        ctx: &mut BigNumContextRef,
20592f3ab15Sopenharmony_ci    ) -> Result<(), ErrorStack> {
20692f3ab15Sopenharmony_ci        unsafe {
20792f3ab15Sopenharmony_ci            cvt(ffi::EC_GROUP_get_curve_GF2m(
20892f3ab15Sopenharmony_ci                self.as_ptr(),
20992f3ab15Sopenharmony_ci                p.as_ptr(),
21092f3ab15Sopenharmony_ci                a.as_ptr(),
21192f3ab15Sopenharmony_ci                b.as_ptr(),
21292f3ab15Sopenharmony_ci                ctx.as_ptr(),
21392f3ab15Sopenharmony_ci            ))
21492f3ab15Sopenharmony_ci            .map(|_| ())
21592f3ab15Sopenharmony_ci        }
21692f3ab15Sopenharmony_ci    }
21792f3ab15Sopenharmony_ci
21892f3ab15Sopenharmony_ci    /// Places the cofactor of the group in the provided `BigNum`.
21992f3ab15Sopenharmony_ci    #[corresponds(EC_GROUP_get_cofactor)]
22092f3ab15Sopenharmony_ci    pub fn cofactor(
22192f3ab15Sopenharmony_ci        &self,
22292f3ab15Sopenharmony_ci        cofactor: &mut BigNumRef,
22392f3ab15Sopenharmony_ci        ctx: &mut BigNumContextRef,
22492f3ab15Sopenharmony_ci    ) -> Result<(), ErrorStack> {
22592f3ab15Sopenharmony_ci        unsafe {
22692f3ab15Sopenharmony_ci            cvt(ffi::EC_GROUP_get_cofactor(
22792f3ab15Sopenharmony_ci                self.as_ptr(),
22892f3ab15Sopenharmony_ci                cofactor.as_ptr(),
22992f3ab15Sopenharmony_ci                ctx.as_ptr(),
23092f3ab15Sopenharmony_ci            ))
23192f3ab15Sopenharmony_ci            .map(|_| ())
23292f3ab15Sopenharmony_ci        }
23392f3ab15Sopenharmony_ci    }
23492f3ab15Sopenharmony_ci
23592f3ab15Sopenharmony_ci    /// Returns the degree of the curve.
23692f3ab15Sopenharmony_ci    #[corresponds(EC_GROUP_get_degree)]
23792f3ab15Sopenharmony_ci    pub fn degree(&self) -> u32 {
23892f3ab15Sopenharmony_ci        unsafe { ffi::EC_GROUP_get_degree(self.as_ptr()) as u32 }
23992f3ab15Sopenharmony_ci    }
24092f3ab15Sopenharmony_ci
24192f3ab15Sopenharmony_ci    /// Returns the number of bits in the group order.
24292f3ab15Sopenharmony_ci    #[corresponds(EC_GROUP_order_bits)]
24392f3ab15Sopenharmony_ci    #[cfg(ossl110)]
24492f3ab15Sopenharmony_ci    pub fn order_bits(&self) -> u32 {
24592f3ab15Sopenharmony_ci        unsafe { ffi::EC_GROUP_order_bits(self.as_ptr()) as u32 }
24692f3ab15Sopenharmony_ci    }
24792f3ab15Sopenharmony_ci
24892f3ab15Sopenharmony_ci    /// Returns the generator for the given curve as an [`EcPoint`].
24992f3ab15Sopenharmony_ci    #[corresponds(EC_GROUP_get0_generator)]
25092f3ab15Sopenharmony_ci    pub fn generator(&self) -> &EcPointRef {
25192f3ab15Sopenharmony_ci        unsafe {
25292f3ab15Sopenharmony_ci            let ptr = ffi::EC_GROUP_get0_generator(self.as_ptr());
25392f3ab15Sopenharmony_ci            EcPointRef::from_const_ptr(ptr)
25492f3ab15Sopenharmony_ci        }
25592f3ab15Sopenharmony_ci    }
25692f3ab15Sopenharmony_ci
25792f3ab15Sopenharmony_ci    /// Sets the generator point for the given curve
25892f3ab15Sopenharmony_ci    #[corresponds(EC_GROUP_set_generator)]
25992f3ab15Sopenharmony_ci    pub fn set_generator(
26092f3ab15Sopenharmony_ci        &mut self,
26192f3ab15Sopenharmony_ci        generator: EcPoint,
26292f3ab15Sopenharmony_ci        order: BigNum,
26392f3ab15Sopenharmony_ci        cofactor: BigNum,
26492f3ab15Sopenharmony_ci    ) -> Result<(), ErrorStack> {
26592f3ab15Sopenharmony_ci        unsafe {
26692f3ab15Sopenharmony_ci            cvt(ffi::EC_GROUP_set_generator(
26792f3ab15Sopenharmony_ci                self.as_ptr(),
26892f3ab15Sopenharmony_ci                generator.as_ptr(),
26992f3ab15Sopenharmony_ci                order.as_ptr(),
27092f3ab15Sopenharmony_ci                cofactor.as_ptr(),
27192f3ab15Sopenharmony_ci            ))
27292f3ab15Sopenharmony_ci            .map(|_| ())
27392f3ab15Sopenharmony_ci        }
27492f3ab15Sopenharmony_ci    }
27592f3ab15Sopenharmony_ci
27692f3ab15Sopenharmony_ci    /// Places the order of the curve in the provided `BigNum`.
27792f3ab15Sopenharmony_ci    #[corresponds(EC_GROUP_get_order)]
27892f3ab15Sopenharmony_ci    pub fn order(
27992f3ab15Sopenharmony_ci        &self,
28092f3ab15Sopenharmony_ci        order: &mut BigNumRef,
28192f3ab15Sopenharmony_ci        ctx: &mut BigNumContextRef,
28292f3ab15Sopenharmony_ci    ) -> Result<(), ErrorStack> {
28392f3ab15Sopenharmony_ci        unsafe {
28492f3ab15Sopenharmony_ci            cvt(ffi::EC_GROUP_get_order(
28592f3ab15Sopenharmony_ci                self.as_ptr(),
28692f3ab15Sopenharmony_ci                order.as_ptr(),
28792f3ab15Sopenharmony_ci                ctx.as_ptr(),
28892f3ab15Sopenharmony_ci            ))
28992f3ab15Sopenharmony_ci            .map(|_| ())
29092f3ab15Sopenharmony_ci        }
29192f3ab15Sopenharmony_ci    }
29292f3ab15Sopenharmony_ci
29392f3ab15Sopenharmony_ci    /// Sets the flag determining if the group corresponds to a named curve or must be explicitly
29492f3ab15Sopenharmony_ci    /// parameterized.
29592f3ab15Sopenharmony_ci    ///
29692f3ab15Sopenharmony_ci    /// This defaults to `EXPLICIT_CURVE` in OpenSSL 1.0.1 and 1.0.2, but `NAMED_CURVE` in OpenSSL
29792f3ab15Sopenharmony_ci    /// 1.1.0.
29892f3ab15Sopenharmony_ci    #[corresponds(EC_GROUP_set_asn1_flag)]
29992f3ab15Sopenharmony_ci    pub fn set_asn1_flag(&mut self, flag: Asn1Flag) {
30092f3ab15Sopenharmony_ci        unsafe {
30192f3ab15Sopenharmony_ci            ffi::EC_GROUP_set_asn1_flag(self.as_ptr(), flag.0);
30292f3ab15Sopenharmony_ci        }
30392f3ab15Sopenharmony_ci    }
30492f3ab15Sopenharmony_ci
30592f3ab15Sopenharmony_ci    /// Gets the flag determining if the group corresponds to a named curve.
30692f3ab15Sopenharmony_ci    #[corresponds(EC_GROUP_get_asn1_flag)]
30792f3ab15Sopenharmony_ci    pub fn asn1_flag(&self) -> Asn1Flag {
30892f3ab15Sopenharmony_ci        unsafe { Asn1Flag(ffi::EC_GROUP_get_asn1_flag(self.as_ptr())) }
30992f3ab15Sopenharmony_ci    }
31092f3ab15Sopenharmony_ci
31192f3ab15Sopenharmony_ci    /// Returns the name of the curve, if a name is associated.
31292f3ab15Sopenharmony_ci    #[corresponds(EC_GROUP_get_curve_name)]
31392f3ab15Sopenharmony_ci    pub fn curve_name(&self) -> Option<Nid> {
31492f3ab15Sopenharmony_ci        let nid = unsafe { ffi::EC_GROUP_get_curve_name(self.as_ptr()) };
31592f3ab15Sopenharmony_ci        if nid > 0 {
31692f3ab15Sopenharmony_ci            Some(Nid::from_raw(nid))
31792f3ab15Sopenharmony_ci        } else {
31892f3ab15Sopenharmony_ci            None
31992f3ab15Sopenharmony_ci        }
32092f3ab15Sopenharmony_ci    }
32192f3ab15Sopenharmony_ci}
32292f3ab15Sopenharmony_ci
32392f3ab15Sopenharmony_ciforeign_type_and_impl_send_sync! {
32492f3ab15Sopenharmony_ci    type CType = ffi::EC_POINT;
32592f3ab15Sopenharmony_ci    fn drop = ffi::EC_POINT_free;
32692f3ab15Sopenharmony_ci
32792f3ab15Sopenharmony_ci    /// Represents a point on the curve
32892f3ab15Sopenharmony_ci    pub struct EcPoint;
32992f3ab15Sopenharmony_ci    /// A reference a borrowed [`EcPoint`].
33092f3ab15Sopenharmony_ci    pub struct EcPointRef;
33192f3ab15Sopenharmony_ci}
33292f3ab15Sopenharmony_ci
33392f3ab15Sopenharmony_ciimpl EcPointRef {
33492f3ab15Sopenharmony_ci    /// Computes `a + b`, storing the result in `self`.
33592f3ab15Sopenharmony_ci    #[corresponds(EC_POINT_add)]
33692f3ab15Sopenharmony_ci    pub fn add(
33792f3ab15Sopenharmony_ci        &mut self,
33892f3ab15Sopenharmony_ci        group: &EcGroupRef,
33992f3ab15Sopenharmony_ci        a: &EcPointRef,
34092f3ab15Sopenharmony_ci        b: &EcPointRef,
34192f3ab15Sopenharmony_ci        ctx: &mut BigNumContextRef,
34292f3ab15Sopenharmony_ci    ) -> Result<(), ErrorStack> {
34392f3ab15Sopenharmony_ci        unsafe {
34492f3ab15Sopenharmony_ci            cvt(ffi::EC_POINT_add(
34592f3ab15Sopenharmony_ci                group.as_ptr(),
34692f3ab15Sopenharmony_ci                self.as_ptr(),
34792f3ab15Sopenharmony_ci                a.as_ptr(),
34892f3ab15Sopenharmony_ci                b.as_ptr(),
34992f3ab15Sopenharmony_ci                ctx.as_ptr(),
35092f3ab15Sopenharmony_ci            ))
35192f3ab15Sopenharmony_ci            .map(|_| ())
35292f3ab15Sopenharmony_ci        }
35392f3ab15Sopenharmony_ci    }
35492f3ab15Sopenharmony_ci
35592f3ab15Sopenharmony_ci    /// Computes `q * m`, storing the result in `self`.
35692f3ab15Sopenharmony_ci    #[corresponds(EC_POINT_mul)]
35792f3ab15Sopenharmony_ci    pub fn mul(
35892f3ab15Sopenharmony_ci        &mut self,
35992f3ab15Sopenharmony_ci        group: &EcGroupRef,
36092f3ab15Sopenharmony_ci        q: &EcPointRef,
36192f3ab15Sopenharmony_ci        m: &BigNumRef,
36292f3ab15Sopenharmony_ci        // FIXME should be &mut
36392f3ab15Sopenharmony_ci        ctx: &BigNumContextRef,
36492f3ab15Sopenharmony_ci    ) -> Result<(), ErrorStack> {
36592f3ab15Sopenharmony_ci        unsafe {
36692f3ab15Sopenharmony_ci            cvt(ffi::EC_POINT_mul(
36792f3ab15Sopenharmony_ci                group.as_ptr(),
36892f3ab15Sopenharmony_ci                self.as_ptr(),
36992f3ab15Sopenharmony_ci                ptr::null(),
37092f3ab15Sopenharmony_ci                q.as_ptr(),
37192f3ab15Sopenharmony_ci                m.as_ptr(),
37292f3ab15Sopenharmony_ci                ctx.as_ptr(),
37392f3ab15Sopenharmony_ci            ))
37492f3ab15Sopenharmony_ci            .map(|_| ())
37592f3ab15Sopenharmony_ci        }
37692f3ab15Sopenharmony_ci    }
37792f3ab15Sopenharmony_ci
37892f3ab15Sopenharmony_ci    /// Computes `generator * n`, storing the result in `self`.
37992f3ab15Sopenharmony_ci    #[corresponds(EC_POINT_mul)]
38092f3ab15Sopenharmony_ci    pub fn mul_generator(
38192f3ab15Sopenharmony_ci        &mut self,
38292f3ab15Sopenharmony_ci        group: &EcGroupRef,
38392f3ab15Sopenharmony_ci        n: &BigNumRef,
38492f3ab15Sopenharmony_ci        // FIXME should be &mut
38592f3ab15Sopenharmony_ci        ctx: &BigNumContextRef,
38692f3ab15Sopenharmony_ci    ) -> Result<(), ErrorStack> {
38792f3ab15Sopenharmony_ci        unsafe {
38892f3ab15Sopenharmony_ci            cvt(ffi::EC_POINT_mul(
38992f3ab15Sopenharmony_ci                group.as_ptr(),
39092f3ab15Sopenharmony_ci                self.as_ptr(),
39192f3ab15Sopenharmony_ci                n.as_ptr(),
39292f3ab15Sopenharmony_ci                ptr::null(),
39392f3ab15Sopenharmony_ci                ptr::null(),
39492f3ab15Sopenharmony_ci                ctx.as_ptr(),
39592f3ab15Sopenharmony_ci            ))
39692f3ab15Sopenharmony_ci            .map(|_| ())
39792f3ab15Sopenharmony_ci        }
39892f3ab15Sopenharmony_ci    }
39992f3ab15Sopenharmony_ci
40092f3ab15Sopenharmony_ci    /// Computes `generator * n + q * m`, storing the result in `self`.
40192f3ab15Sopenharmony_ci    #[corresponds(EC_POINT_mul)]
40292f3ab15Sopenharmony_ci    pub fn mul_full(
40392f3ab15Sopenharmony_ci        &mut self,
40492f3ab15Sopenharmony_ci        group: &EcGroupRef,
40592f3ab15Sopenharmony_ci        n: &BigNumRef,
40692f3ab15Sopenharmony_ci        q: &EcPointRef,
40792f3ab15Sopenharmony_ci        m: &BigNumRef,
40892f3ab15Sopenharmony_ci        ctx: &mut BigNumContextRef,
40992f3ab15Sopenharmony_ci    ) -> Result<(), ErrorStack> {
41092f3ab15Sopenharmony_ci        unsafe {
41192f3ab15Sopenharmony_ci            cvt(ffi::EC_POINT_mul(
41292f3ab15Sopenharmony_ci                group.as_ptr(),
41392f3ab15Sopenharmony_ci                self.as_ptr(),
41492f3ab15Sopenharmony_ci                n.as_ptr(),
41592f3ab15Sopenharmony_ci                q.as_ptr(),
41692f3ab15Sopenharmony_ci                m.as_ptr(),
41792f3ab15Sopenharmony_ci                ctx.as_ptr(),
41892f3ab15Sopenharmony_ci            ))
41992f3ab15Sopenharmony_ci            .map(|_| ())
42092f3ab15Sopenharmony_ci        }
42192f3ab15Sopenharmony_ci    }
42292f3ab15Sopenharmony_ci
42392f3ab15Sopenharmony_ci    /// Inverts `self`.
42492f3ab15Sopenharmony_ci    #[corresponds(EC_POINT_invert)]
42592f3ab15Sopenharmony_ci    // FIXME should be mutable
42692f3ab15Sopenharmony_ci    pub fn invert(&mut self, group: &EcGroupRef, ctx: &BigNumContextRef) -> Result<(), ErrorStack> {
42792f3ab15Sopenharmony_ci        unsafe {
42892f3ab15Sopenharmony_ci            cvt(ffi::EC_POINT_invert(
42992f3ab15Sopenharmony_ci                group.as_ptr(),
43092f3ab15Sopenharmony_ci                self.as_ptr(),
43192f3ab15Sopenharmony_ci                ctx.as_ptr(),
43292f3ab15Sopenharmony_ci            ))
43392f3ab15Sopenharmony_ci            .map(|_| ())
43492f3ab15Sopenharmony_ci        }
43592f3ab15Sopenharmony_ci    }
43692f3ab15Sopenharmony_ci
43792f3ab15Sopenharmony_ci    /// Serializes the point to a binary representation.
43892f3ab15Sopenharmony_ci    #[corresponds(EC_POINT_point2oct)]
43992f3ab15Sopenharmony_ci    pub fn to_bytes(
44092f3ab15Sopenharmony_ci        &self,
44192f3ab15Sopenharmony_ci        group: &EcGroupRef,
44292f3ab15Sopenharmony_ci        form: PointConversionForm,
44392f3ab15Sopenharmony_ci        ctx: &mut BigNumContextRef,
44492f3ab15Sopenharmony_ci    ) -> Result<Vec<u8>, ErrorStack> {
44592f3ab15Sopenharmony_ci        unsafe {
44692f3ab15Sopenharmony_ci            let len = ffi::EC_POINT_point2oct(
44792f3ab15Sopenharmony_ci                group.as_ptr(),
44892f3ab15Sopenharmony_ci                self.as_ptr(),
44992f3ab15Sopenharmony_ci                form.0,
45092f3ab15Sopenharmony_ci                ptr::null_mut(),
45192f3ab15Sopenharmony_ci                0,
45292f3ab15Sopenharmony_ci                ctx.as_ptr(),
45392f3ab15Sopenharmony_ci            );
45492f3ab15Sopenharmony_ci            if len == 0 {
45592f3ab15Sopenharmony_ci                return Err(ErrorStack::get());
45692f3ab15Sopenharmony_ci            }
45792f3ab15Sopenharmony_ci            let mut buf = vec![0; len];
45892f3ab15Sopenharmony_ci            let len = ffi::EC_POINT_point2oct(
45992f3ab15Sopenharmony_ci                group.as_ptr(),
46092f3ab15Sopenharmony_ci                self.as_ptr(),
46192f3ab15Sopenharmony_ci                form.0,
46292f3ab15Sopenharmony_ci                buf.as_mut_ptr(),
46392f3ab15Sopenharmony_ci                len,
46492f3ab15Sopenharmony_ci                ctx.as_ptr(),
46592f3ab15Sopenharmony_ci            );
46692f3ab15Sopenharmony_ci            if len == 0 {
46792f3ab15Sopenharmony_ci                Err(ErrorStack::get())
46892f3ab15Sopenharmony_ci            } else {
46992f3ab15Sopenharmony_ci                Ok(buf)
47092f3ab15Sopenharmony_ci            }
47192f3ab15Sopenharmony_ci        }
47292f3ab15Sopenharmony_ci    }
47392f3ab15Sopenharmony_ci
47492f3ab15Sopenharmony_ci    /// Serializes the point to a hexadecimal string representation.
47592f3ab15Sopenharmony_ci    #[corresponds(EC_POINT_point2hex)]
47692f3ab15Sopenharmony_ci    #[cfg(not(boringssl))]
47792f3ab15Sopenharmony_ci    pub fn to_hex_str(
47892f3ab15Sopenharmony_ci        &self,
47992f3ab15Sopenharmony_ci        group: &EcGroupRef,
48092f3ab15Sopenharmony_ci        form: PointConversionForm,
48192f3ab15Sopenharmony_ci        ctx: &mut BigNumContextRef,
48292f3ab15Sopenharmony_ci    ) -> Result<OpensslString, ErrorStack> {
48392f3ab15Sopenharmony_ci        unsafe {
48492f3ab15Sopenharmony_ci            let buf = cvt_p(ffi::EC_POINT_point2hex(
48592f3ab15Sopenharmony_ci                group.as_ptr(),
48692f3ab15Sopenharmony_ci                self.as_ptr(),
48792f3ab15Sopenharmony_ci                form.0,
48892f3ab15Sopenharmony_ci                ctx.as_ptr(),
48992f3ab15Sopenharmony_ci            ))?;
49092f3ab15Sopenharmony_ci            Ok(OpensslString::from_ptr(buf))
49192f3ab15Sopenharmony_ci        }
49292f3ab15Sopenharmony_ci    }
49392f3ab15Sopenharmony_ci
49492f3ab15Sopenharmony_ci    /// Creates a new point on the specified curve with the same value.
49592f3ab15Sopenharmony_ci    #[corresponds(EC_POINT_dup)]
49692f3ab15Sopenharmony_ci    pub fn to_owned(&self, group: &EcGroupRef) -> Result<EcPoint, ErrorStack> {
49792f3ab15Sopenharmony_ci        unsafe { cvt_p(ffi::EC_POINT_dup(self.as_ptr(), group.as_ptr())).map(EcPoint) }
49892f3ab15Sopenharmony_ci    }
49992f3ab15Sopenharmony_ci
50092f3ab15Sopenharmony_ci    /// Determines if this point is equal to another.
50192f3ab15Sopenharmony_ci    #[corresponds(EC_POINT_cmp)]
50292f3ab15Sopenharmony_ci    pub fn eq(
50392f3ab15Sopenharmony_ci        &self,
50492f3ab15Sopenharmony_ci        group: &EcGroupRef,
50592f3ab15Sopenharmony_ci        other: &EcPointRef,
50692f3ab15Sopenharmony_ci        ctx: &mut BigNumContextRef,
50792f3ab15Sopenharmony_ci    ) -> Result<bool, ErrorStack> {
50892f3ab15Sopenharmony_ci        unsafe {
50992f3ab15Sopenharmony_ci            let res = cvt_n(ffi::EC_POINT_cmp(
51092f3ab15Sopenharmony_ci                group.as_ptr(),
51192f3ab15Sopenharmony_ci                self.as_ptr(),
51292f3ab15Sopenharmony_ci                other.as_ptr(),
51392f3ab15Sopenharmony_ci                ctx.as_ptr(),
51492f3ab15Sopenharmony_ci            ))?;
51592f3ab15Sopenharmony_ci            Ok(res == 0)
51692f3ab15Sopenharmony_ci        }
51792f3ab15Sopenharmony_ci    }
51892f3ab15Sopenharmony_ci
51992f3ab15Sopenharmony_ci    /// Places affine coordinates of a curve over a prime field in the provided
52092f3ab15Sopenharmony_ci    /// `x` and `y` `BigNum`s.
52192f3ab15Sopenharmony_ci    #[corresponds(EC_POINT_get_affine_coordinates)]
52292f3ab15Sopenharmony_ci    #[cfg(any(ossl111, boringssl, libressl350))]
52392f3ab15Sopenharmony_ci    pub fn affine_coordinates(
52492f3ab15Sopenharmony_ci        &self,
52592f3ab15Sopenharmony_ci        group: &EcGroupRef,
52692f3ab15Sopenharmony_ci        x: &mut BigNumRef,
52792f3ab15Sopenharmony_ci        y: &mut BigNumRef,
52892f3ab15Sopenharmony_ci        ctx: &mut BigNumContextRef,
52992f3ab15Sopenharmony_ci    ) -> Result<(), ErrorStack> {
53092f3ab15Sopenharmony_ci        unsafe {
53192f3ab15Sopenharmony_ci            cvt(ffi::EC_POINT_get_affine_coordinates(
53292f3ab15Sopenharmony_ci                group.as_ptr(),
53392f3ab15Sopenharmony_ci                self.as_ptr(),
53492f3ab15Sopenharmony_ci                x.as_ptr(),
53592f3ab15Sopenharmony_ci                y.as_ptr(),
53692f3ab15Sopenharmony_ci                ctx.as_ptr(),
53792f3ab15Sopenharmony_ci            ))
53892f3ab15Sopenharmony_ci            .map(|_| ())
53992f3ab15Sopenharmony_ci        }
54092f3ab15Sopenharmony_ci    }
54192f3ab15Sopenharmony_ci
54292f3ab15Sopenharmony_ci    /// Places affine coordinates of a curve over a prime field in the provided
54392f3ab15Sopenharmony_ci    /// `x` and `y` `BigNum`s
54492f3ab15Sopenharmony_ci    #[corresponds(EC_POINT_get_affine_coordinates_GFp)]
54592f3ab15Sopenharmony_ci    pub fn affine_coordinates_gfp(
54692f3ab15Sopenharmony_ci        &self,
54792f3ab15Sopenharmony_ci        group: &EcGroupRef,
54892f3ab15Sopenharmony_ci        x: &mut BigNumRef,
54992f3ab15Sopenharmony_ci        y: &mut BigNumRef,
55092f3ab15Sopenharmony_ci        ctx: &mut BigNumContextRef,
55192f3ab15Sopenharmony_ci    ) -> Result<(), ErrorStack> {
55292f3ab15Sopenharmony_ci        unsafe {
55392f3ab15Sopenharmony_ci            cvt(ffi::EC_POINT_get_affine_coordinates_GFp(
55492f3ab15Sopenharmony_ci                group.as_ptr(),
55592f3ab15Sopenharmony_ci                self.as_ptr(),
55692f3ab15Sopenharmony_ci                x.as_ptr(),
55792f3ab15Sopenharmony_ci                y.as_ptr(),
55892f3ab15Sopenharmony_ci                ctx.as_ptr(),
55992f3ab15Sopenharmony_ci            ))
56092f3ab15Sopenharmony_ci            .map(|_| ())
56192f3ab15Sopenharmony_ci        }
56292f3ab15Sopenharmony_ci    }
56392f3ab15Sopenharmony_ci
56492f3ab15Sopenharmony_ci    /// Sets affine coordinates of a curve over a prime field using the provided
56592f3ab15Sopenharmony_ci    /// `x` and `y` `BigNum`s
56692f3ab15Sopenharmony_ci    #[corresponds(EC_POINT_set_affine_coordinates_GFp)]
56792f3ab15Sopenharmony_ci    pub fn set_affine_coordinates_gfp(
56892f3ab15Sopenharmony_ci        &mut self,
56992f3ab15Sopenharmony_ci        group: &EcGroupRef,
57092f3ab15Sopenharmony_ci        x: &BigNumRef,
57192f3ab15Sopenharmony_ci        y: &BigNumRef,
57292f3ab15Sopenharmony_ci        ctx: &mut BigNumContextRef,
57392f3ab15Sopenharmony_ci    ) -> Result<(), ErrorStack> {
57492f3ab15Sopenharmony_ci        unsafe {
57592f3ab15Sopenharmony_ci            cvt(ffi::EC_POINT_set_affine_coordinates_GFp(
57692f3ab15Sopenharmony_ci                group.as_ptr(),
57792f3ab15Sopenharmony_ci                self.as_ptr(),
57892f3ab15Sopenharmony_ci                x.as_ptr(),
57992f3ab15Sopenharmony_ci                y.as_ptr(),
58092f3ab15Sopenharmony_ci                ctx.as_ptr(),
58192f3ab15Sopenharmony_ci            ))
58292f3ab15Sopenharmony_ci            .map(|_| ())
58392f3ab15Sopenharmony_ci        }
58492f3ab15Sopenharmony_ci    }
58592f3ab15Sopenharmony_ci
58692f3ab15Sopenharmony_ci    /// Places affine coordinates of a curve over a binary field in the provided
58792f3ab15Sopenharmony_ci    /// `x` and `y` `BigNum`s
58892f3ab15Sopenharmony_ci    #[corresponds(EC_POINT_get_affine_coordinates_GF2m)]
58992f3ab15Sopenharmony_ci    #[cfg(not(any(boringssl, osslconf = "OPENSSL_NO_EC2M")))]
59092f3ab15Sopenharmony_ci    pub fn affine_coordinates_gf2m(
59192f3ab15Sopenharmony_ci        &self,
59292f3ab15Sopenharmony_ci        group: &EcGroupRef,
59392f3ab15Sopenharmony_ci        x: &mut BigNumRef,
59492f3ab15Sopenharmony_ci        y: &mut BigNumRef,
59592f3ab15Sopenharmony_ci        ctx: &mut BigNumContextRef,
59692f3ab15Sopenharmony_ci    ) -> Result<(), ErrorStack> {
59792f3ab15Sopenharmony_ci        unsafe {
59892f3ab15Sopenharmony_ci            cvt(ffi::EC_POINT_get_affine_coordinates_GF2m(
59992f3ab15Sopenharmony_ci                group.as_ptr(),
60092f3ab15Sopenharmony_ci                self.as_ptr(),
60192f3ab15Sopenharmony_ci                x.as_ptr(),
60292f3ab15Sopenharmony_ci                y.as_ptr(),
60392f3ab15Sopenharmony_ci                ctx.as_ptr(),
60492f3ab15Sopenharmony_ci            ))
60592f3ab15Sopenharmony_ci            .map(|_| ())
60692f3ab15Sopenharmony_ci        }
60792f3ab15Sopenharmony_ci    }
60892f3ab15Sopenharmony_ci
60992f3ab15Sopenharmony_ci    /// Checks if point is infinity
61092f3ab15Sopenharmony_ci    #[corresponds(EC_POINT_is_at_infinity)]
61192f3ab15Sopenharmony_ci    pub fn is_infinity(&self, group: &EcGroupRef) -> bool {
61292f3ab15Sopenharmony_ci        unsafe {
61392f3ab15Sopenharmony_ci            let res = ffi::EC_POINT_is_at_infinity(group.as_ptr(), self.as_ptr());
61492f3ab15Sopenharmony_ci            res == 1
61592f3ab15Sopenharmony_ci        }
61692f3ab15Sopenharmony_ci    }
61792f3ab15Sopenharmony_ci
61892f3ab15Sopenharmony_ci    /// Checks if point is on a given curve
61992f3ab15Sopenharmony_ci    #[corresponds(EC_POINT_is_on_curve)]
62092f3ab15Sopenharmony_ci    pub fn is_on_curve(
62192f3ab15Sopenharmony_ci        &self,
62292f3ab15Sopenharmony_ci        group: &EcGroupRef,
62392f3ab15Sopenharmony_ci        ctx: &mut BigNumContextRef,
62492f3ab15Sopenharmony_ci    ) -> Result<bool, ErrorStack> {
62592f3ab15Sopenharmony_ci        unsafe {
62692f3ab15Sopenharmony_ci            let res = cvt_n(ffi::EC_POINT_is_on_curve(
62792f3ab15Sopenharmony_ci                group.as_ptr(),
62892f3ab15Sopenharmony_ci                self.as_ptr(),
62992f3ab15Sopenharmony_ci                ctx.as_ptr(),
63092f3ab15Sopenharmony_ci            ))?;
63192f3ab15Sopenharmony_ci            Ok(res == 1)
63292f3ab15Sopenharmony_ci        }
63392f3ab15Sopenharmony_ci    }
63492f3ab15Sopenharmony_ci}
63592f3ab15Sopenharmony_ci
63692f3ab15Sopenharmony_ciimpl EcPoint {
63792f3ab15Sopenharmony_ci    /// Creates a new point on the specified curve.
63892f3ab15Sopenharmony_ci    #[corresponds(EC_POINT_new)]
63992f3ab15Sopenharmony_ci    pub fn new(group: &EcGroupRef) -> Result<EcPoint, ErrorStack> {
64092f3ab15Sopenharmony_ci        unsafe { cvt_p(ffi::EC_POINT_new(group.as_ptr())).map(EcPoint) }
64192f3ab15Sopenharmony_ci    }
64292f3ab15Sopenharmony_ci
64392f3ab15Sopenharmony_ci    /// Creates point from a binary representation
64492f3ab15Sopenharmony_ci    #[corresponds(EC_POINT_oct2point)]
64592f3ab15Sopenharmony_ci    pub fn from_bytes(
64692f3ab15Sopenharmony_ci        group: &EcGroupRef,
64792f3ab15Sopenharmony_ci        buf: &[u8],
64892f3ab15Sopenharmony_ci        ctx: &mut BigNumContextRef,
64992f3ab15Sopenharmony_ci    ) -> Result<EcPoint, ErrorStack> {
65092f3ab15Sopenharmony_ci        let point = EcPoint::new(group)?;
65192f3ab15Sopenharmony_ci        unsafe {
65292f3ab15Sopenharmony_ci            cvt(ffi::EC_POINT_oct2point(
65392f3ab15Sopenharmony_ci                group.as_ptr(),
65492f3ab15Sopenharmony_ci                point.as_ptr(),
65592f3ab15Sopenharmony_ci                buf.as_ptr(),
65692f3ab15Sopenharmony_ci                buf.len(),
65792f3ab15Sopenharmony_ci                ctx.as_ptr(),
65892f3ab15Sopenharmony_ci            ))?;
65992f3ab15Sopenharmony_ci        }
66092f3ab15Sopenharmony_ci        Ok(point)
66192f3ab15Sopenharmony_ci    }
66292f3ab15Sopenharmony_ci
66392f3ab15Sopenharmony_ci    /// Creates point from a hexadecimal string representation
66492f3ab15Sopenharmony_ci    #[corresponds(EC_POINT_hex2point)]
66592f3ab15Sopenharmony_ci    #[cfg(not(boringssl))]
66692f3ab15Sopenharmony_ci    pub fn from_hex_str(
66792f3ab15Sopenharmony_ci        group: &EcGroupRef,
66892f3ab15Sopenharmony_ci        s: &str,
66992f3ab15Sopenharmony_ci        ctx: &mut BigNumContextRef,
67092f3ab15Sopenharmony_ci    ) -> Result<EcPoint, ErrorStack> {
67192f3ab15Sopenharmony_ci        let point = EcPoint::new(group)?;
67292f3ab15Sopenharmony_ci        unsafe {
67392f3ab15Sopenharmony_ci            let c_str = CString::new(s.as_bytes()).unwrap();
67492f3ab15Sopenharmony_ci            cvt_p(ffi::EC_POINT_hex2point(
67592f3ab15Sopenharmony_ci                group.as_ptr(),
67692f3ab15Sopenharmony_ci                c_str.as_ptr() as *const _,
67792f3ab15Sopenharmony_ci                point.as_ptr(),
67892f3ab15Sopenharmony_ci                ctx.as_ptr(),
67992f3ab15Sopenharmony_ci            ))?;
68092f3ab15Sopenharmony_ci        }
68192f3ab15Sopenharmony_ci        Ok(point)
68292f3ab15Sopenharmony_ci    }
68392f3ab15Sopenharmony_ci}
68492f3ab15Sopenharmony_ci
68592f3ab15Sopenharmony_cigeneric_foreign_type_and_impl_send_sync! {
68692f3ab15Sopenharmony_ci    type CType = ffi::EC_KEY;
68792f3ab15Sopenharmony_ci    fn drop = ffi::EC_KEY_free;
68892f3ab15Sopenharmony_ci
68992f3ab15Sopenharmony_ci    /// Public and optional private key on the given curve.
69092f3ab15Sopenharmony_ci    pub struct EcKey<T>;
69192f3ab15Sopenharmony_ci    /// A reference to an [`EcKey`].
69292f3ab15Sopenharmony_ci    pub struct EcKeyRef<T>;
69392f3ab15Sopenharmony_ci}
69492f3ab15Sopenharmony_ci
69592f3ab15Sopenharmony_ciimpl<T> EcKeyRef<T>
69692f3ab15Sopenharmony_ciwhere
69792f3ab15Sopenharmony_ci    T: HasPrivate,
69892f3ab15Sopenharmony_ci{
69992f3ab15Sopenharmony_ci    private_key_to_pem! {
70092f3ab15Sopenharmony_ci        /// Serializes the private key to a PEM-encoded ECPrivateKey structure.
70192f3ab15Sopenharmony_ci        ///
70292f3ab15Sopenharmony_ci        /// The output will have a header of `-----BEGIN EC PRIVATE KEY-----`.
70392f3ab15Sopenharmony_ci        #[corresponds(PEM_write_bio_ECPrivateKey)]
70492f3ab15Sopenharmony_ci        private_key_to_pem,
70592f3ab15Sopenharmony_ci        /// Serializes the private key to a PEM-encoded encrypted ECPrivateKey structure.
70692f3ab15Sopenharmony_ci        ///
70792f3ab15Sopenharmony_ci        /// The output will have a header of `-----BEGIN EC PRIVATE KEY-----`.
70892f3ab15Sopenharmony_ci        #[corresponds(PEM_write_bio_ECPrivateKey)]
70992f3ab15Sopenharmony_ci        private_key_to_pem_passphrase,
71092f3ab15Sopenharmony_ci        ffi::PEM_write_bio_ECPrivateKey
71192f3ab15Sopenharmony_ci    }
71292f3ab15Sopenharmony_ci
71392f3ab15Sopenharmony_ci    to_der! {
71492f3ab15Sopenharmony_ci        /// Serializes the private key into a DER-encoded ECPrivateKey structure.
71592f3ab15Sopenharmony_ci        #[corresponds(i2d_ECPrivateKey)]
71692f3ab15Sopenharmony_ci        private_key_to_der,
71792f3ab15Sopenharmony_ci        ffi::i2d_ECPrivateKey
71892f3ab15Sopenharmony_ci    }
71992f3ab15Sopenharmony_ci
72092f3ab15Sopenharmony_ci    /// Returns the private key value.
72192f3ab15Sopenharmony_ci    #[corresponds(EC_KEY_get0_private_key)]
72292f3ab15Sopenharmony_ci    pub fn private_key(&self) -> &BigNumRef {
72392f3ab15Sopenharmony_ci        unsafe {
72492f3ab15Sopenharmony_ci            let ptr = ffi::EC_KEY_get0_private_key(self.as_ptr());
72592f3ab15Sopenharmony_ci            BigNumRef::from_const_ptr(ptr)
72692f3ab15Sopenharmony_ci        }
72792f3ab15Sopenharmony_ci    }
72892f3ab15Sopenharmony_ci}
72992f3ab15Sopenharmony_ci
73092f3ab15Sopenharmony_ciimpl<T> EcKeyRef<T>
73192f3ab15Sopenharmony_ciwhere
73292f3ab15Sopenharmony_ci    T: HasPublic,
73392f3ab15Sopenharmony_ci{
73492f3ab15Sopenharmony_ci    /// Returns the public key.
73592f3ab15Sopenharmony_ci    #[corresponds(EC_KEY_get0_public_key)]
73692f3ab15Sopenharmony_ci    pub fn public_key(&self) -> &EcPointRef {
73792f3ab15Sopenharmony_ci        unsafe {
73892f3ab15Sopenharmony_ci            let ptr = ffi::EC_KEY_get0_public_key(self.as_ptr());
73992f3ab15Sopenharmony_ci            EcPointRef::from_const_ptr(ptr)
74092f3ab15Sopenharmony_ci        }
74192f3ab15Sopenharmony_ci    }
74292f3ab15Sopenharmony_ci
74392f3ab15Sopenharmony_ci    to_pem! {
74492f3ab15Sopenharmony_ci        /// Serializes the public key into a PEM-encoded SubjectPublicKeyInfo structure.
74592f3ab15Sopenharmony_ci        ///
74692f3ab15Sopenharmony_ci        /// The output will have a header of `-----BEGIN PUBLIC KEY-----`.
74792f3ab15Sopenharmony_ci        #[corresponds(PEM_write_bio_EC_PUBKEY)]
74892f3ab15Sopenharmony_ci        public_key_to_pem,
74992f3ab15Sopenharmony_ci        ffi::PEM_write_bio_EC_PUBKEY
75092f3ab15Sopenharmony_ci    }
75192f3ab15Sopenharmony_ci
75292f3ab15Sopenharmony_ci    to_der! {
75392f3ab15Sopenharmony_ci        /// Serializes the public key into a DER-encoded SubjectPublicKeyInfo structure.
75492f3ab15Sopenharmony_ci        #[corresponds(i2d_EC_PUBKEY)]
75592f3ab15Sopenharmony_ci        public_key_to_der,
75692f3ab15Sopenharmony_ci        ffi::i2d_EC_PUBKEY
75792f3ab15Sopenharmony_ci    }
75892f3ab15Sopenharmony_ci}
75992f3ab15Sopenharmony_ci
76092f3ab15Sopenharmony_ciimpl<T> EcKeyRef<T>
76192f3ab15Sopenharmony_ciwhere
76292f3ab15Sopenharmony_ci    T: HasParams,
76392f3ab15Sopenharmony_ci{
76492f3ab15Sopenharmony_ci    /// Returns the key's group.
76592f3ab15Sopenharmony_ci    #[corresponds(EC_KEY_get0_group)]
76692f3ab15Sopenharmony_ci    pub fn group(&self) -> &EcGroupRef {
76792f3ab15Sopenharmony_ci        unsafe {
76892f3ab15Sopenharmony_ci            let ptr = ffi::EC_KEY_get0_group(self.as_ptr());
76992f3ab15Sopenharmony_ci            EcGroupRef::from_const_ptr(ptr)
77092f3ab15Sopenharmony_ci        }
77192f3ab15Sopenharmony_ci    }
77292f3ab15Sopenharmony_ci
77392f3ab15Sopenharmony_ci    /// Checks the key for validity.
77492f3ab15Sopenharmony_ci    #[corresponds(EC_KEY_check_key)]
77592f3ab15Sopenharmony_ci    pub fn check_key(&self) -> Result<(), ErrorStack> {
77692f3ab15Sopenharmony_ci        unsafe { cvt(ffi::EC_KEY_check_key(self.as_ptr())).map(|_| ()) }
77792f3ab15Sopenharmony_ci    }
77892f3ab15Sopenharmony_ci}
77992f3ab15Sopenharmony_ci
78092f3ab15Sopenharmony_ciimpl<T> ToOwned for EcKeyRef<T> {
78192f3ab15Sopenharmony_ci    type Owned = EcKey<T>;
78292f3ab15Sopenharmony_ci
78392f3ab15Sopenharmony_ci    fn to_owned(&self) -> EcKey<T> {
78492f3ab15Sopenharmony_ci        unsafe {
78592f3ab15Sopenharmony_ci            let r = ffi::EC_KEY_up_ref(self.as_ptr());
78692f3ab15Sopenharmony_ci            assert!(r == 1);
78792f3ab15Sopenharmony_ci            EcKey::from_ptr(self.as_ptr())
78892f3ab15Sopenharmony_ci        }
78992f3ab15Sopenharmony_ci    }
79092f3ab15Sopenharmony_ci}
79192f3ab15Sopenharmony_ci
79292f3ab15Sopenharmony_ciimpl EcKey<Params> {
79392f3ab15Sopenharmony_ci    /// Constructs an `EcKey` corresponding to a known curve.
79492f3ab15Sopenharmony_ci    ///
79592f3ab15Sopenharmony_ci    /// It will not have an associated public or private key. This kind of key is primarily useful
79692f3ab15Sopenharmony_ci    /// to be provided to the `set_tmp_ecdh` methods on `Ssl` and `SslContextBuilder`.
79792f3ab15Sopenharmony_ci    #[corresponds(EC_KEY_new_by_curve_name)]
79892f3ab15Sopenharmony_ci    pub fn from_curve_name(nid: Nid) -> Result<EcKey<Params>, ErrorStack> {
79992f3ab15Sopenharmony_ci        unsafe {
80092f3ab15Sopenharmony_ci            init();
80192f3ab15Sopenharmony_ci            cvt_p(ffi::EC_KEY_new_by_curve_name(nid.as_raw())).map(|p| EcKey::from_ptr(p))
80292f3ab15Sopenharmony_ci        }
80392f3ab15Sopenharmony_ci    }
80492f3ab15Sopenharmony_ci
80592f3ab15Sopenharmony_ci    /// Constructs an `EcKey` corresponding to a curve.
80692f3ab15Sopenharmony_ci    #[corresponds(EC_KEY_set_group)]
80792f3ab15Sopenharmony_ci    pub fn from_group(group: &EcGroupRef) -> Result<EcKey<Params>, ErrorStack> {
80892f3ab15Sopenharmony_ci        unsafe {
80992f3ab15Sopenharmony_ci            cvt_p(ffi::EC_KEY_new())
81092f3ab15Sopenharmony_ci                .map(|p| EcKey::from_ptr(p))
81192f3ab15Sopenharmony_ci                .and_then(|key| {
81292f3ab15Sopenharmony_ci                    cvt(ffi::EC_KEY_set_group(key.as_ptr(), group.as_ptr())).map(|_| key)
81392f3ab15Sopenharmony_ci                })
81492f3ab15Sopenharmony_ci        }
81592f3ab15Sopenharmony_ci    }
81692f3ab15Sopenharmony_ci}
81792f3ab15Sopenharmony_ci
81892f3ab15Sopenharmony_ciimpl EcKey<Public> {
81992f3ab15Sopenharmony_ci    /// Constructs an `EcKey` from the specified group with the associated [`EcPoint`]: `public_key`.
82092f3ab15Sopenharmony_ci    ///
82192f3ab15Sopenharmony_ci    /// This will only have the associated `public_key`.
82292f3ab15Sopenharmony_ci    ///
82392f3ab15Sopenharmony_ci    /// # Example
82492f3ab15Sopenharmony_ci    ///
82592f3ab15Sopenharmony_ci    /// ```
82692f3ab15Sopenharmony_ci    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
82792f3ab15Sopenharmony_ci    /// use openssl::bn::BigNumContext;
82892f3ab15Sopenharmony_ci    /// use openssl::ec::*;
82992f3ab15Sopenharmony_ci    /// use openssl::nid::Nid;
83092f3ab15Sopenharmony_ci    /// use openssl::pkey::PKey;
83192f3ab15Sopenharmony_ci    ///
83292f3ab15Sopenharmony_ci    /// let group = EcGroup::from_curve_name(Nid::SECP384R1)?;
83392f3ab15Sopenharmony_ci    /// let mut ctx = BigNumContext::new()?;
83492f3ab15Sopenharmony_ci    ///
83592f3ab15Sopenharmony_ci    /// // get bytes from somewhere
83692f3ab15Sopenharmony_ci    /// let public_key = // ...
83792f3ab15Sopenharmony_ci    /// # EcKey::generate(&group)?.public_key().to_bytes(&group,
83892f3ab15Sopenharmony_ci    /// # PointConversionForm::COMPRESSED, &mut ctx)?;
83992f3ab15Sopenharmony_ci    ///
84092f3ab15Sopenharmony_ci    /// // create an EcKey from the binary form of a EcPoint
84192f3ab15Sopenharmony_ci    /// let point = EcPoint::from_bytes(&group, &public_key, &mut ctx)?;
84292f3ab15Sopenharmony_ci    /// let key = EcKey::from_public_key(&group, &point)?;
84392f3ab15Sopenharmony_ci    /// key.check_key()?;
84492f3ab15Sopenharmony_ci    /// # Ok(()) }
84592f3ab15Sopenharmony_ci    /// ```
84692f3ab15Sopenharmony_ci    #[corresponds(EC_KEY_set_public_key)]
84792f3ab15Sopenharmony_ci    pub fn from_public_key(
84892f3ab15Sopenharmony_ci        group: &EcGroupRef,
84992f3ab15Sopenharmony_ci        public_key: &EcPointRef,
85092f3ab15Sopenharmony_ci    ) -> Result<EcKey<Public>, ErrorStack> {
85192f3ab15Sopenharmony_ci        unsafe {
85292f3ab15Sopenharmony_ci            cvt_p(ffi::EC_KEY_new())
85392f3ab15Sopenharmony_ci                .map(|p| EcKey::from_ptr(p))
85492f3ab15Sopenharmony_ci                .and_then(|key| {
85592f3ab15Sopenharmony_ci                    cvt(ffi::EC_KEY_set_group(key.as_ptr(), group.as_ptr())).map(|_| key)
85692f3ab15Sopenharmony_ci                })
85792f3ab15Sopenharmony_ci                .and_then(|key| {
85892f3ab15Sopenharmony_ci                    cvt(ffi::EC_KEY_set_public_key(
85992f3ab15Sopenharmony_ci                        key.as_ptr(),
86092f3ab15Sopenharmony_ci                        public_key.as_ptr(),
86192f3ab15Sopenharmony_ci                    ))
86292f3ab15Sopenharmony_ci                    .map(|_| key)
86392f3ab15Sopenharmony_ci                })
86492f3ab15Sopenharmony_ci        }
86592f3ab15Sopenharmony_ci    }
86692f3ab15Sopenharmony_ci
86792f3ab15Sopenharmony_ci    /// Constructs a public key from its affine coordinates.
86892f3ab15Sopenharmony_ci    #[corresponds(EC_KEY_set_public_key_affine_coordinates)]
86992f3ab15Sopenharmony_ci    pub fn from_public_key_affine_coordinates(
87092f3ab15Sopenharmony_ci        group: &EcGroupRef,
87192f3ab15Sopenharmony_ci        x: &BigNumRef,
87292f3ab15Sopenharmony_ci        y: &BigNumRef,
87392f3ab15Sopenharmony_ci    ) -> Result<EcKey<Public>, ErrorStack> {
87492f3ab15Sopenharmony_ci        unsafe {
87592f3ab15Sopenharmony_ci            cvt_p(ffi::EC_KEY_new())
87692f3ab15Sopenharmony_ci                .map(|p| EcKey::from_ptr(p))
87792f3ab15Sopenharmony_ci                .and_then(|key| {
87892f3ab15Sopenharmony_ci                    cvt(ffi::EC_KEY_set_group(key.as_ptr(), group.as_ptr())).map(|_| key)
87992f3ab15Sopenharmony_ci                })
88092f3ab15Sopenharmony_ci                .and_then(|key| {
88192f3ab15Sopenharmony_ci                    cvt(ffi::EC_KEY_set_public_key_affine_coordinates(
88292f3ab15Sopenharmony_ci                        key.as_ptr(),
88392f3ab15Sopenharmony_ci                        x.as_ptr(),
88492f3ab15Sopenharmony_ci                        y.as_ptr(),
88592f3ab15Sopenharmony_ci                    ))
88692f3ab15Sopenharmony_ci                    .map(|_| key)
88792f3ab15Sopenharmony_ci                })
88892f3ab15Sopenharmony_ci        }
88992f3ab15Sopenharmony_ci    }
89092f3ab15Sopenharmony_ci
89192f3ab15Sopenharmony_ci    from_pem! {
89292f3ab15Sopenharmony_ci        /// Decodes a PEM-encoded SubjectPublicKeyInfo structure containing a EC key.
89392f3ab15Sopenharmony_ci        ///
89492f3ab15Sopenharmony_ci        /// The input should have a header of `-----BEGIN PUBLIC KEY-----`.
89592f3ab15Sopenharmony_ci        #[corresponds(PEM_read_bio_EC_PUBKEY)]
89692f3ab15Sopenharmony_ci        public_key_from_pem,
89792f3ab15Sopenharmony_ci        EcKey<Public>,
89892f3ab15Sopenharmony_ci        ffi::PEM_read_bio_EC_PUBKEY
89992f3ab15Sopenharmony_ci    }
90092f3ab15Sopenharmony_ci
90192f3ab15Sopenharmony_ci    from_der! {
90292f3ab15Sopenharmony_ci        /// Decodes a DER-encoded SubjectPublicKeyInfo structure containing a EC key.
90392f3ab15Sopenharmony_ci        #[corresponds(d2i_EC_PUBKEY)]
90492f3ab15Sopenharmony_ci        public_key_from_der,
90592f3ab15Sopenharmony_ci        EcKey<Public>,
90692f3ab15Sopenharmony_ci        ffi::d2i_EC_PUBKEY
90792f3ab15Sopenharmony_ci    }
90892f3ab15Sopenharmony_ci}
90992f3ab15Sopenharmony_ci
91092f3ab15Sopenharmony_ciimpl EcKey<Private> {
91192f3ab15Sopenharmony_ci    /// Generates a new public/private key pair on the specified curve.
91292f3ab15Sopenharmony_ci    ///
91392f3ab15Sopenharmony_ci    /// # Examples
91492f3ab15Sopenharmony_ci    ///
91592f3ab15Sopenharmony_ci    /// ```
91692f3ab15Sopenharmony_ci    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
91792f3ab15Sopenharmony_ci    /// use openssl::bn::BigNumContext;
91892f3ab15Sopenharmony_ci    /// use openssl::nid::Nid;
91992f3ab15Sopenharmony_ci    /// use openssl::ec::{EcGroup, EcKey, PointConversionForm};
92092f3ab15Sopenharmony_ci    ///
92192f3ab15Sopenharmony_ci    /// let nid = Nid::X9_62_PRIME256V1; // NIST P-256 curve
92292f3ab15Sopenharmony_ci    /// let group = EcGroup::from_curve_name(nid)?;
92392f3ab15Sopenharmony_ci    /// let key = EcKey::generate(&group)?;
92492f3ab15Sopenharmony_ci    ///
92592f3ab15Sopenharmony_ci    /// let mut ctx = BigNumContext::new()?;
92692f3ab15Sopenharmony_ci    ///
92792f3ab15Sopenharmony_ci    /// let public_key = &key.public_key().to_bytes(
92892f3ab15Sopenharmony_ci    ///     &group,
92992f3ab15Sopenharmony_ci    ///     PointConversionForm::COMPRESSED,
93092f3ab15Sopenharmony_ci    ///     &mut ctx,
93192f3ab15Sopenharmony_ci    /// )?;
93292f3ab15Sopenharmony_ci    /// assert_eq!(public_key.len(), 33);
93392f3ab15Sopenharmony_ci    /// assert_ne!(public_key[0], 0x04);
93492f3ab15Sopenharmony_ci    ///
93592f3ab15Sopenharmony_ci    /// let private_key = key.private_key().to_vec();
93692f3ab15Sopenharmony_ci    /// assert!(private_key.len() >= 31);
93792f3ab15Sopenharmony_ci    /// # Ok(()) }
93892f3ab15Sopenharmony_ci    /// ```
93992f3ab15Sopenharmony_ci    #[corresponds(EC_KEY_generate_key)]
94092f3ab15Sopenharmony_ci    pub fn generate(group: &EcGroupRef) -> Result<EcKey<Private>, ErrorStack> {
94192f3ab15Sopenharmony_ci        unsafe {
94292f3ab15Sopenharmony_ci            cvt_p(ffi::EC_KEY_new())
94392f3ab15Sopenharmony_ci                .map(|p| EcKey::from_ptr(p))
94492f3ab15Sopenharmony_ci                .and_then(|key| {
94592f3ab15Sopenharmony_ci                    cvt(ffi::EC_KEY_set_group(key.as_ptr(), group.as_ptr())).map(|_| key)
94692f3ab15Sopenharmony_ci                })
94792f3ab15Sopenharmony_ci                .and_then(|key| cvt(ffi::EC_KEY_generate_key(key.as_ptr())).map(|_| key))
94892f3ab15Sopenharmony_ci        }
94992f3ab15Sopenharmony_ci    }
95092f3ab15Sopenharmony_ci
95192f3ab15Sopenharmony_ci    /// Constructs an public/private key pair given a curve, a private key and a public key point.
95292f3ab15Sopenharmony_ci    #[corresponds(EC_KEY_set_private_key)]
95392f3ab15Sopenharmony_ci    pub fn from_private_components(
95492f3ab15Sopenharmony_ci        group: &EcGroupRef,
95592f3ab15Sopenharmony_ci        private_number: &BigNumRef,
95692f3ab15Sopenharmony_ci        public_key: &EcPointRef,
95792f3ab15Sopenharmony_ci    ) -> Result<EcKey<Private>, ErrorStack> {
95892f3ab15Sopenharmony_ci        unsafe {
95992f3ab15Sopenharmony_ci            cvt_p(ffi::EC_KEY_new())
96092f3ab15Sopenharmony_ci                .map(|p| EcKey::from_ptr(p))
96192f3ab15Sopenharmony_ci                .and_then(|key| {
96292f3ab15Sopenharmony_ci                    cvt(ffi::EC_KEY_set_group(key.as_ptr(), group.as_ptr())).map(|_| key)
96392f3ab15Sopenharmony_ci                })
96492f3ab15Sopenharmony_ci                .and_then(|key| {
96592f3ab15Sopenharmony_ci                    cvt(ffi::EC_KEY_set_private_key(
96692f3ab15Sopenharmony_ci                        key.as_ptr(),
96792f3ab15Sopenharmony_ci                        private_number.as_ptr(),
96892f3ab15Sopenharmony_ci                    ))
96992f3ab15Sopenharmony_ci                    .map(|_| key)
97092f3ab15Sopenharmony_ci                })
97192f3ab15Sopenharmony_ci                .and_then(|key| {
97292f3ab15Sopenharmony_ci                    cvt(ffi::EC_KEY_set_public_key(
97392f3ab15Sopenharmony_ci                        key.as_ptr(),
97492f3ab15Sopenharmony_ci                        public_key.as_ptr(),
97592f3ab15Sopenharmony_ci                    ))
97692f3ab15Sopenharmony_ci                    .map(|_| key)
97792f3ab15Sopenharmony_ci                })
97892f3ab15Sopenharmony_ci        }
97992f3ab15Sopenharmony_ci    }
98092f3ab15Sopenharmony_ci
98192f3ab15Sopenharmony_ci    private_key_from_pem! {
98292f3ab15Sopenharmony_ci        /// Deserializes a private key from a PEM-encoded ECPrivateKey structure.
98392f3ab15Sopenharmony_ci        ///
98492f3ab15Sopenharmony_ci        /// The input should have a header of `-----BEGIN EC PRIVATE KEY-----`.
98592f3ab15Sopenharmony_ci        #[corresponds(PEM_read_bio_ECPrivateKey)]
98692f3ab15Sopenharmony_ci        private_key_from_pem,
98792f3ab15Sopenharmony_ci
98892f3ab15Sopenharmony_ci        /// Deserializes a private key from a PEM-encoded encrypted ECPrivateKey structure.
98992f3ab15Sopenharmony_ci        ///
99092f3ab15Sopenharmony_ci        /// The input should have a header of `-----BEGIN EC PRIVATE KEY-----`.
99192f3ab15Sopenharmony_ci        #[corresponds(PEM_read_bio_ECPrivateKey)]
99292f3ab15Sopenharmony_ci        private_key_from_pem_passphrase,
99392f3ab15Sopenharmony_ci
99492f3ab15Sopenharmony_ci        /// Deserializes a private key from a PEM-encoded encrypted ECPrivateKey structure.
99592f3ab15Sopenharmony_ci        ///
99692f3ab15Sopenharmony_ci        /// The callback should fill the password into the provided buffer and return its length.
99792f3ab15Sopenharmony_ci        ///
99892f3ab15Sopenharmony_ci        /// The input should have a header of `-----BEGIN EC PRIVATE KEY-----`.
99992f3ab15Sopenharmony_ci        #[corresponds(PEM_read_bio_ECPrivateKey)]
100092f3ab15Sopenharmony_ci        private_key_from_pem_callback,
100192f3ab15Sopenharmony_ci        EcKey<Private>,
100292f3ab15Sopenharmony_ci        ffi::PEM_read_bio_ECPrivateKey
100392f3ab15Sopenharmony_ci    }
100492f3ab15Sopenharmony_ci
100592f3ab15Sopenharmony_ci    from_der! {
100692f3ab15Sopenharmony_ci        /// Decodes a DER-encoded elliptic curve private key structure.
100792f3ab15Sopenharmony_ci        #[corresponds(d2i_ECPrivateKey)]
100892f3ab15Sopenharmony_ci        private_key_from_der,
100992f3ab15Sopenharmony_ci        EcKey<Private>,
101092f3ab15Sopenharmony_ci        ffi::d2i_ECPrivateKey
101192f3ab15Sopenharmony_ci    }
101292f3ab15Sopenharmony_ci}
101392f3ab15Sopenharmony_ci
101492f3ab15Sopenharmony_ciimpl<T> Clone for EcKey<T> {
101592f3ab15Sopenharmony_ci    fn clone(&self) -> EcKey<T> {
101692f3ab15Sopenharmony_ci        (**self).to_owned()
101792f3ab15Sopenharmony_ci    }
101892f3ab15Sopenharmony_ci}
101992f3ab15Sopenharmony_ci
102092f3ab15Sopenharmony_ciimpl<T> fmt::Debug for EcKey<T> {
102192f3ab15Sopenharmony_ci    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
102292f3ab15Sopenharmony_ci        write!(f, "EcKey")
102392f3ab15Sopenharmony_ci    }
102492f3ab15Sopenharmony_ci}
102592f3ab15Sopenharmony_ci
102692f3ab15Sopenharmony_ci#[cfg(test)]
102792f3ab15Sopenharmony_cimod test {
102892f3ab15Sopenharmony_ci    use hex::FromHex;
102992f3ab15Sopenharmony_ci
103092f3ab15Sopenharmony_ci    use super::*;
103192f3ab15Sopenharmony_ci    use crate::bn::{BigNum, BigNumContext};
103292f3ab15Sopenharmony_ci    use crate::nid::Nid;
103392f3ab15Sopenharmony_ci
103492f3ab15Sopenharmony_ci    #[test]
103592f3ab15Sopenharmony_ci    fn key_new_by_curve_name() {
103692f3ab15Sopenharmony_ci        EcKey::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
103792f3ab15Sopenharmony_ci    }
103892f3ab15Sopenharmony_ci
103992f3ab15Sopenharmony_ci    #[test]
104092f3ab15Sopenharmony_ci    fn generate() {
104192f3ab15Sopenharmony_ci        let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
104292f3ab15Sopenharmony_ci        EcKey::generate(&group).unwrap();
104392f3ab15Sopenharmony_ci    }
104492f3ab15Sopenharmony_ci
104592f3ab15Sopenharmony_ci    #[test]
104692f3ab15Sopenharmony_ci    fn ec_group_from_components() {
104792f3ab15Sopenharmony_ci        // parameters are from secp256r1
104892f3ab15Sopenharmony_ci        let p = BigNum::from_hex_str(
104992f3ab15Sopenharmony_ci            "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF",
105092f3ab15Sopenharmony_ci        )
105192f3ab15Sopenharmony_ci        .unwrap();
105292f3ab15Sopenharmony_ci        let a = BigNum::from_hex_str(
105392f3ab15Sopenharmony_ci            "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC",
105492f3ab15Sopenharmony_ci        )
105592f3ab15Sopenharmony_ci        .unwrap();
105692f3ab15Sopenharmony_ci        let b = BigNum::from_hex_str(
105792f3ab15Sopenharmony_ci            "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B",
105892f3ab15Sopenharmony_ci        )
105992f3ab15Sopenharmony_ci        .unwrap();
106092f3ab15Sopenharmony_ci        let mut ctx = BigNumContext::new().unwrap();
106192f3ab15Sopenharmony_ci
106292f3ab15Sopenharmony_ci        let _curve = EcGroup::from_components(p, a, b, &mut ctx).unwrap();
106392f3ab15Sopenharmony_ci    }
106492f3ab15Sopenharmony_ci
106592f3ab15Sopenharmony_ci    #[test]
106692f3ab15Sopenharmony_ci    fn ec_point_set_affine() {
106792f3ab15Sopenharmony_ci        // parameters are from secp256r1
106892f3ab15Sopenharmony_ci        let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
106992f3ab15Sopenharmony_ci        let mut ctx = BigNumContext::new().unwrap();
107092f3ab15Sopenharmony_ci        let mut gen_point = EcPoint::new(&group).unwrap();
107192f3ab15Sopenharmony_ci        let gen_x = BigNum::from_hex_str(
107292f3ab15Sopenharmony_ci            "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296",
107392f3ab15Sopenharmony_ci        )
107492f3ab15Sopenharmony_ci        .unwrap();
107592f3ab15Sopenharmony_ci        let gen_y = BigNum::from_hex_str(
107692f3ab15Sopenharmony_ci            "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5",
107792f3ab15Sopenharmony_ci        )
107892f3ab15Sopenharmony_ci        .unwrap();
107992f3ab15Sopenharmony_ci        gen_point
108092f3ab15Sopenharmony_ci            .set_affine_coordinates_gfp(&group, &gen_x, &gen_y, &mut ctx)
108192f3ab15Sopenharmony_ci            .unwrap();
108292f3ab15Sopenharmony_ci        assert!(gen_point.is_on_curve(&group, &mut ctx).unwrap());
108392f3ab15Sopenharmony_ci    }
108492f3ab15Sopenharmony_ci
108592f3ab15Sopenharmony_ci    #[test]
108692f3ab15Sopenharmony_ci    fn ec_group_set_generator() {
108792f3ab15Sopenharmony_ci        // parameters are from secp256r1
108892f3ab15Sopenharmony_ci        let mut ctx = BigNumContext::new().unwrap();
108992f3ab15Sopenharmony_ci        let p = BigNum::from_hex_str(
109092f3ab15Sopenharmony_ci            "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF",
109192f3ab15Sopenharmony_ci        )
109292f3ab15Sopenharmony_ci        .unwrap();
109392f3ab15Sopenharmony_ci        let a = BigNum::from_hex_str(
109492f3ab15Sopenharmony_ci            "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC",
109592f3ab15Sopenharmony_ci        )
109692f3ab15Sopenharmony_ci        .unwrap();
109792f3ab15Sopenharmony_ci        let b = BigNum::from_hex_str(
109892f3ab15Sopenharmony_ci            "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B",
109992f3ab15Sopenharmony_ci        )
110092f3ab15Sopenharmony_ci        .unwrap();
110192f3ab15Sopenharmony_ci
110292f3ab15Sopenharmony_ci        let mut group = EcGroup::from_components(p, a, b, &mut ctx).unwrap();
110392f3ab15Sopenharmony_ci
110492f3ab15Sopenharmony_ci        let mut gen_point = EcPoint::new(&group).unwrap();
110592f3ab15Sopenharmony_ci        let gen_x = BigNum::from_hex_str(
110692f3ab15Sopenharmony_ci            "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296",
110792f3ab15Sopenharmony_ci        )
110892f3ab15Sopenharmony_ci        .unwrap();
110992f3ab15Sopenharmony_ci        let gen_y = BigNum::from_hex_str(
111092f3ab15Sopenharmony_ci            "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5",
111192f3ab15Sopenharmony_ci        )
111292f3ab15Sopenharmony_ci        .unwrap();
111392f3ab15Sopenharmony_ci        gen_point
111492f3ab15Sopenharmony_ci            .set_affine_coordinates_gfp(&group, &gen_x, &gen_y, &mut ctx)
111592f3ab15Sopenharmony_ci            .unwrap();
111692f3ab15Sopenharmony_ci
111792f3ab15Sopenharmony_ci        let order = BigNum::from_hex_str(
111892f3ab15Sopenharmony_ci            "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551",
111992f3ab15Sopenharmony_ci        )
112092f3ab15Sopenharmony_ci        .unwrap();
112192f3ab15Sopenharmony_ci        let cofactor = BigNum::from_hex_str("01").unwrap();
112292f3ab15Sopenharmony_ci        group.set_generator(gen_point, order, cofactor).unwrap();
112392f3ab15Sopenharmony_ci        let mut constructed_order = BigNum::new().unwrap();
112492f3ab15Sopenharmony_ci        group.order(&mut constructed_order, &mut ctx).unwrap();
112592f3ab15Sopenharmony_ci
112692f3ab15Sopenharmony_ci        let named_group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
112792f3ab15Sopenharmony_ci        let mut named_order = BigNum::new().unwrap();
112892f3ab15Sopenharmony_ci        named_group.order(&mut named_order, &mut ctx).unwrap();
112992f3ab15Sopenharmony_ci
113092f3ab15Sopenharmony_ci        assert_eq!(
113192f3ab15Sopenharmony_ci            constructed_order.ucmp(&named_order),
113292f3ab15Sopenharmony_ci            std::cmp::Ordering::Equal
113392f3ab15Sopenharmony_ci        );
113492f3ab15Sopenharmony_ci    }
113592f3ab15Sopenharmony_ci
113692f3ab15Sopenharmony_ci    #[test]
113792f3ab15Sopenharmony_ci    fn cofactor() {
113892f3ab15Sopenharmony_ci        let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
113992f3ab15Sopenharmony_ci        let mut ctx = BigNumContext::new().unwrap();
114092f3ab15Sopenharmony_ci        let mut cofactor = BigNum::new().unwrap();
114192f3ab15Sopenharmony_ci        group.cofactor(&mut cofactor, &mut ctx).unwrap();
114292f3ab15Sopenharmony_ci        let one = BigNum::from_u32(1).unwrap();
114392f3ab15Sopenharmony_ci        assert_eq!(cofactor, one);
114492f3ab15Sopenharmony_ci    }
114592f3ab15Sopenharmony_ci
114692f3ab15Sopenharmony_ci    #[test]
114792f3ab15Sopenharmony_ci    #[allow(clippy::redundant_clone)]
114892f3ab15Sopenharmony_ci    fn dup() {
114992f3ab15Sopenharmony_ci        let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
115092f3ab15Sopenharmony_ci        let key = EcKey::generate(&group).unwrap();
115192f3ab15Sopenharmony_ci        drop(key.clone());
115292f3ab15Sopenharmony_ci    }
115392f3ab15Sopenharmony_ci
115492f3ab15Sopenharmony_ci    #[test]
115592f3ab15Sopenharmony_ci    fn point_new() {
115692f3ab15Sopenharmony_ci        let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
115792f3ab15Sopenharmony_ci        EcPoint::new(&group).unwrap();
115892f3ab15Sopenharmony_ci    }
115992f3ab15Sopenharmony_ci
116092f3ab15Sopenharmony_ci    #[test]
116192f3ab15Sopenharmony_ci    fn point_bytes() {
116292f3ab15Sopenharmony_ci        let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
116392f3ab15Sopenharmony_ci        let key = EcKey::generate(&group).unwrap();
116492f3ab15Sopenharmony_ci        let point = key.public_key();
116592f3ab15Sopenharmony_ci        let mut ctx = BigNumContext::new().unwrap();
116692f3ab15Sopenharmony_ci        let bytes = point
116792f3ab15Sopenharmony_ci            .to_bytes(&group, PointConversionForm::COMPRESSED, &mut ctx)
116892f3ab15Sopenharmony_ci            .unwrap();
116992f3ab15Sopenharmony_ci        let point2 = EcPoint::from_bytes(&group, &bytes, &mut ctx).unwrap();
117092f3ab15Sopenharmony_ci        assert!(point.eq(&group, &point2, &mut ctx).unwrap());
117192f3ab15Sopenharmony_ci    }
117292f3ab15Sopenharmony_ci
117392f3ab15Sopenharmony_ci    #[test]
117492f3ab15Sopenharmony_ci    #[cfg(not(boringssl))]
117592f3ab15Sopenharmony_ci    fn point_hex_str() {
117692f3ab15Sopenharmony_ci        let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
117792f3ab15Sopenharmony_ci        let key = EcKey::generate(&group).unwrap();
117892f3ab15Sopenharmony_ci        let point = key.public_key();
117992f3ab15Sopenharmony_ci        let mut ctx = BigNumContext::new().unwrap();
118092f3ab15Sopenharmony_ci        let hex = point
118192f3ab15Sopenharmony_ci            .to_hex_str(&group, PointConversionForm::COMPRESSED, &mut ctx)
118292f3ab15Sopenharmony_ci            .unwrap();
118392f3ab15Sopenharmony_ci        let point2 = EcPoint::from_hex_str(&group, &hex, &mut ctx).unwrap();
118492f3ab15Sopenharmony_ci        assert!(point.eq(&group, &point2, &mut ctx).unwrap());
118592f3ab15Sopenharmony_ci    }
118692f3ab15Sopenharmony_ci
118792f3ab15Sopenharmony_ci    #[test]
118892f3ab15Sopenharmony_ci    fn point_owned() {
118992f3ab15Sopenharmony_ci        let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
119092f3ab15Sopenharmony_ci        let key = EcKey::generate(&group).unwrap();
119192f3ab15Sopenharmony_ci        let point = key.public_key();
119292f3ab15Sopenharmony_ci        let owned = point.to_owned(&group).unwrap();
119392f3ab15Sopenharmony_ci        let mut ctx = BigNumContext::new().unwrap();
119492f3ab15Sopenharmony_ci        assert!(owned.eq(&group, point, &mut ctx).unwrap());
119592f3ab15Sopenharmony_ci    }
119692f3ab15Sopenharmony_ci
119792f3ab15Sopenharmony_ci    #[test]
119892f3ab15Sopenharmony_ci    fn mul_generator() {
119992f3ab15Sopenharmony_ci        let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
120092f3ab15Sopenharmony_ci        let key = EcKey::generate(&group).unwrap();
120192f3ab15Sopenharmony_ci        let mut ctx = BigNumContext::new().unwrap();
120292f3ab15Sopenharmony_ci        let mut public_key = EcPoint::new(&group).unwrap();
120392f3ab15Sopenharmony_ci        public_key
120492f3ab15Sopenharmony_ci            .mul_generator(&group, key.private_key(), &ctx)
120592f3ab15Sopenharmony_ci            .unwrap();
120692f3ab15Sopenharmony_ci        assert!(public_key.eq(&group, key.public_key(), &mut ctx).unwrap());
120792f3ab15Sopenharmony_ci    }
120892f3ab15Sopenharmony_ci
120992f3ab15Sopenharmony_ci    #[test]
121092f3ab15Sopenharmony_ci    fn generator() {
121192f3ab15Sopenharmony_ci        let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
121292f3ab15Sopenharmony_ci        let gen = group.generator();
121392f3ab15Sopenharmony_ci        let one = BigNum::from_u32(1).unwrap();
121492f3ab15Sopenharmony_ci        let mut ctx = BigNumContext::new().unwrap();
121592f3ab15Sopenharmony_ci        let mut ecp = EcPoint::new(&group).unwrap();
121692f3ab15Sopenharmony_ci        ecp.mul_generator(&group, &one, &ctx).unwrap();
121792f3ab15Sopenharmony_ci        assert!(ecp.eq(&group, gen, &mut ctx).unwrap());
121892f3ab15Sopenharmony_ci    }
121992f3ab15Sopenharmony_ci
122092f3ab15Sopenharmony_ci    #[test]
122192f3ab15Sopenharmony_ci    fn key_from_public_key() {
122292f3ab15Sopenharmony_ci        let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
122392f3ab15Sopenharmony_ci        let key = EcKey::generate(&group).unwrap();
122492f3ab15Sopenharmony_ci        let mut ctx = BigNumContext::new().unwrap();
122592f3ab15Sopenharmony_ci        let bytes = key
122692f3ab15Sopenharmony_ci            .public_key()
122792f3ab15Sopenharmony_ci            .to_bytes(&group, PointConversionForm::COMPRESSED, &mut ctx)
122892f3ab15Sopenharmony_ci            .unwrap();
122992f3ab15Sopenharmony_ci
123092f3ab15Sopenharmony_ci        drop(key);
123192f3ab15Sopenharmony_ci        let public_key = EcPoint::from_bytes(&group, &bytes, &mut ctx).unwrap();
123292f3ab15Sopenharmony_ci        let ec_key = EcKey::from_public_key(&group, &public_key).unwrap();
123392f3ab15Sopenharmony_ci        assert!(ec_key.check_key().is_ok());
123492f3ab15Sopenharmony_ci    }
123592f3ab15Sopenharmony_ci
123692f3ab15Sopenharmony_ci    #[test]
123792f3ab15Sopenharmony_ci    fn key_from_private_components() {
123892f3ab15Sopenharmony_ci        let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
123992f3ab15Sopenharmony_ci        let key = EcKey::generate(&group).unwrap();
124092f3ab15Sopenharmony_ci
124192f3ab15Sopenharmony_ci        let dup_key =
124292f3ab15Sopenharmony_ci            EcKey::from_private_components(&group, key.private_key(), key.public_key()).unwrap();
124392f3ab15Sopenharmony_ci        dup_key.check_key().unwrap();
124492f3ab15Sopenharmony_ci
124592f3ab15Sopenharmony_ci        assert!(key.private_key() == dup_key.private_key());
124692f3ab15Sopenharmony_ci    }
124792f3ab15Sopenharmony_ci
124892f3ab15Sopenharmony_ci    #[test]
124992f3ab15Sopenharmony_ci    fn key_from_affine_coordinates() {
125092f3ab15Sopenharmony_ci        let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
125192f3ab15Sopenharmony_ci        let x = Vec::from_hex("30a0424cd21c2944838a2d75c92b37e76ea20d9f00893a3b4eee8a3c0aafec3e")
125292f3ab15Sopenharmony_ci            .unwrap();
125392f3ab15Sopenharmony_ci        let y = Vec::from_hex("e04b65e92456d9888b52b379bdfbd51ee869ef1f0fc65b6659695b6cce081723")
125492f3ab15Sopenharmony_ci            .unwrap();
125592f3ab15Sopenharmony_ci
125692f3ab15Sopenharmony_ci        let xbn = BigNum::from_slice(&x).unwrap();
125792f3ab15Sopenharmony_ci        let ybn = BigNum::from_slice(&y).unwrap();
125892f3ab15Sopenharmony_ci
125992f3ab15Sopenharmony_ci        let ec_key = EcKey::from_public_key_affine_coordinates(&group, &xbn, &ybn).unwrap();
126092f3ab15Sopenharmony_ci        assert!(ec_key.check_key().is_ok());
126192f3ab15Sopenharmony_ci    }
126292f3ab15Sopenharmony_ci
126392f3ab15Sopenharmony_ci    #[cfg(any(ossl111, boringssl, libressl350))]
126492f3ab15Sopenharmony_ci    #[test]
126592f3ab15Sopenharmony_ci    fn get_affine_coordinates() {
126692f3ab15Sopenharmony_ci        let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
126792f3ab15Sopenharmony_ci        let x = Vec::from_hex("30a0424cd21c2944838a2d75c92b37e76ea20d9f00893a3b4eee8a3c0aafec3e")
126892f3ab15Sopenharmony_ci            .unwrap();
126992f3ab15Sopenharmony_ci        let y = Vec::from_hex("e04b65e92456d9888b52b379bdfbd51ee869ef1f0fc65b6659695b6cce081723")
127092f3ab15Sopenharmony_ci            .unwrap();
127192f3ab15Sopenharmony_ci
127292f3ab15Sopenharmony_ci        let xbn = BigNum::from_slice(&x).unwrap();
127392f3ab15Sopenharmony_ci        let ybn = BigNum::from_slice(&y).unwrap();
127492f3ab15Sopenharmony_ci
127592f3ab15Sopenharmony_ci        let ec_key = EcKey::from_public_key_affine_coordinates(&group, &xbn, &ybn).unwrap();
127692f3ab15Sopenharmony_ci
127792f3ab15Sopenharmony_ci        let mut xbn2 = BigNum::new().unwrap();
127892f3ab15Sopenharmony_ci        let mut ybn2 = BigNum::new().unwrap();
127992f3ab15Sopenharmony_ci        let mut ctx = BigNumContext::new().unwrap();
128092f3ab15Sopenharmony_ci        let ec_key_pk = ec_key.public_key();
128192f3ab15Sopenharmony_ci        ec_key_pk
128292f3ab15Sopenharmony_ci            .affine_coordinates(&group, &mut xbn2, &mut ybn2, &mut ctx)
128392f3ab15Sopenharmony_ci            .unwrap();
128492f3ab15Sopenharmony_ci        assert_eq!(xbn2, xbn);
128592f3ab15Sopenharmony_ci        assert_eq!(ybn2, ybn);
128692f3ab15Sopenharmony_ci    }
128792f3ab15Sopenharmony_ci
128892f3ab15Sopenharmony_ci    #[test]
128992f3ab15Sopenharmony_ci    fn get_affine_coordinates_gfp() {
129092f3ab15Sopenharmony_ci        let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
129192f3ab15Sopenharmony_ci        let x = Vec::from_hex("30a0424cd21c2944838a2d75c92b37e76ea20d9f00893a3b4eee8a3c0aafec3e")
129292f3ab15Sopenharmony_ci            .unwrap();
129392f3ab15Sopenharmony_ci        let y = Vec::from_hex("e04b65e92456d9888b52b379bdfbd51ee869ef1f0fc65b6659695b6cce081723")
129492f3ab15Sopenharmony_ci            .unwrap();
129592f3ab15Sopenharmony_ci
129692f3ab15Sopenharmony_ci        let xbn = BigNum::from_slice(&x).unwrap();
129792f3ab15Sopenharmony_ci        let ybn = BigNum::from_slice(&y).unwrap();
129892f3ab15Sopenharmony_ci
129992f3ab15Sopenharmony_ci        let ec_key = EcKey::from_public_key_affine_coordinates(&group, &xbn, &ybn).unwrap();
130092f3ab15Sopenharmony_ci
130192f3ab15Sopenharmony_ci        let mut xbn2 = BigNum::new().unwrap();
130292f3ab15Sopenharmony_ci        let mut ybn2 = BigNum::new().unwrap();
130392f3ab15Sopenharmony_ci        let mut ctx = BigNumContext::new().unwrap();
130492f3ab15Sopenharmony_ci        let ec_key_pk = ec_key.public_key();
130592f3ab15Sopenharmony_ci        ec_key_pk
130692f3ab15Sopenharmony_ci            .affine_coordinates_gfp(&group, &mut xbn2, &mut ybn2, &mut ctx)
130792f3ab15Sopenharmony_ci            .unwrap();
130892f3ab15Sopenharmony_ci        assert_eq!(xbn2, xbn);
130992f3ab15Sopenharmony_ci        assert_eq!(ybn2, ybn);
131092f3ab15Sopenharmony_ci    }
131192f3ab15Sopenharmony_ci
131292f3ab15Sopenharmony_ci    #[test]
131392f3ab15Sopenharmony_ci    fn is_infinity() {
131492f3ab15Sopenharmony_ci        let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
131592f3ab15Sopenharmony_ci        let mut ctx = BigNumContext::new().unwrap();
131692f3ab15Sopenharmony_ci        let g = group.generator();
131792f3ab15Sopenharmony_ci        assert!(!g.is_infinity(&group));
131892f3ab15Sopenharmony_ci
131992f3ab15Sopenharmony_ci        let mut order = BigNum::new().unwrap();
132092f3ab15Sopenharmony_ci        group.order(&mut order, &mut ctx).unwrap();
132192f3ab15Sopenharmony_ci        let mut inf = EcPoint::new(&group).unwrap();
132292f3ab15Sopenharmony_ci        inf.mul_generator(&group, &order, &ctx).unwrap();
132392f3ab15Sopenharmony_ci        assert!(inf.is_infinity(&group));
132492f3ab15Sopenharmony_ci    }
132592f3ab15Sopenharmony_ci
132692f3ab15Sopenharmony_ci    #[test]
132792f3ab15Sopenharmony_ci    #[cfg(not(any(boringssl, osslconf = "OPENSSL_NO_EC2M")))]
132892f3ab15Sopenharmony_ci    fn is_on_curve() {
132992f3ab15Sopenharmony_ci        let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
133092f3ab15Sopenharmony_ci        let mut ctx = BigNumContext::new().unwrap();
133192f3ab15Sopenharmony_ci        let g = group.generator();
133292f3ab15Sopenharmony_ci        assert!(g.is_on_curve(&group, &mut ctx).unwrap());
133392f3ab15Sopenharmony_ci
133492f3ab15Sopenharmony_ci        let group2 = EcGroup::from_curve_name(Nid::X9_62_PRIME239V3).unwrap();
133592f3ab15Sopenharmony_ci        assert!(!g.is_on_curve(&group2, &mut ctx).unwrap());
133692f3ab15Sopenharmony_ci    }
133792f3ab15Sopenharmony_ci
133892f3ab15Sopenharmony_ci    #[test]
133992f3ab15Sopenharmony_ci    #[cfg(any(boringssl, ossl111, libressl350))]
134092f3ab15Sopenharmony_ci    fn asn1_flag() {
134192f3ab15Sopenharmony_ci        let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
134292f3ab15Sopenharmony_ci        let flag = group.asn1_flag();
134392f3ab15Sopenharmony_ci        assert_eq!(flag, Asn1Flag::NAMED_CURVE);
134492f3ab15Sopenharmony_ci    }
134592f3ab15Sopenharmony_ci}
1346