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