aboutsummaryrefslogtreecommitdiff
path: root/openssl/src/ec.rs
diff options
context:
space:
mode:
authorSteven Fackler <[email protected]>2017-12-31 10:21:23 -0800
committerGitHub <[email protected]>2017-12-31 10:21:23 -0800
commitd3fff74ae8ab092a77050ba210b942e86c3bd9ff (patch)
treef5646108131916584291141407696ef894f2ff1e /openssl/src/ec.rs
parentMerge pull request #809 from sfackler/issuer-name (diff)
parentParameterize keys over what they contain (diff)
downloadrust-openssl-d3fff74ae8ab092a77050ba210b942e86c3bd9ff.tar.xz
rust-openssl-d3fff74ae8ab092a77050ba210b942e86c3bd9ff.zip
Merge pull request #810 from sfackler/key-tag
Parameterize keys over what they contain
Diffstat (limited to 'openssl/src/ec.rs')
-rw-r--r--openssl/src/ec.rs286
1 files changed, 118 insertions, 168 deletions
diff --git a/openssl/src/ec.rs b/openssl/src/ec.rs
index 524de79d..b85eb7f7 100644
--- a/openssl/src/ec.rs
+++ b/openssl/src/ec.rs
@@ -34,13 +34,13 @@
use ffi;
use foreign_types::{ForeignType, ForeignTypeRef};
use std::ptr;
-use std::mem;
use libc::c_int;
use {cvt, cvt_n, cvt_p, init};
use bn::{BigNumContextRef, BigNumRef};
use error::ErrorStack;
use nid::Nid;
+use pkey::{HasParams, HasPrivate, HasPublic, Params, Private, Public};
/// Compressed or Uncompressed conversion
///
@@ -501,7 +501,7 @@ impl EcPoint {
}
}
-foreign_type_and_impl_send_sync! {
+generic_foreign_type_and_impl_send_sync! {
type CType = ffi::EC_KEY;
fn drop = ffi::EC_KEY_free;
@@ -510,62 +510,64 @@ foreign_type_and_impl_send_sync! {
/// OpenSSL documentation at [`EC_KEY_new`]
///
/// [`EC_KEY_new`]: https://www.openssl.org/docs/man1.1.0/crypto/EC_KEY_new.html
- pub struct EcKey;
+ pub struct EcKey<T>;
+
/// Reference to [`EcKey`]
///
/// [`EcKey`]: struct.EcKey.html
- pub struct EcKeyRef;
+ pub struct EcKeyRef<T>;
}
-impl EcKeyRef {
+impl<T> EcKeyRef<T>
+where
+ T: HasPrivate,
+{
private_key_to_pem!(ffi::PEM_write_bio_ECPrivateKey);
private_key_to_der!(ffi::i2d_ECPrivateKey);
- /// Return [`EcGroup`] of the `EcKey`
+ /// Return [`EcPoint`] associated with the private key
///
- /// OpenSSL documentation at [`EC_KEY_get0_group`]
+ /// OpenSSL documentation at [`EC_KEY_get0_private_key`]
///
- /// [`EC_KEY_get0_group`]: https://www.openssl.org/docs/man1.1.0/crypto/EC_KEY_get0_group.html
- pub fn group(&self) -> Option<&EcGroupRef> {
+ /// [`EC_KEY_get0_private_key`]: https://www.openssl.org/docs/man1.1.0/crypto/EC_KEY_get0_private_key.html
+ pub fn private_key(&self) -> &BigNumRef {
unsafe {
- let ptr = ffi::EC_KEY_get0_group(self.as_ptr());
- if ptr.is_null() {
- None
- } else {
- Some(EcGroupRef::from_ptr(ptr as *mut _))
- }
+ let ptr = ffi::EC_KEY_get0_private_key(self.as_ptr());
+ BigNumRef::from_ptr(ptr as *mut _)
}
}
+}
- /// Return [`EcPoint`] associated with the public key
+impl<T> EcKeyRef<T>
+where
+ T: HasPublic,
+{
+ /// Returns the public key.
///
/// OpenSSL documentation at [`EC_KEY_get0_pubic_key`]
///
/// [`EC_KEY_get0_pubic_key`]: https://www.openssl.org/docs/man1.1.0/crypto/EC_KEY_get0_public_key.html
- pub fn public_key(&self) -> Option<&EcPointRef> {
+ pub fn public_key(&self) -> &EcPointRef {
unsafe {
let ptr = ffi::EC_KEY_get0_public_key(self.as_ptr());
- if ptr.is_null() {
- None
- } else {
- Some(EcPointRef::from_ptr(ptr as *mut _))
- }
+ EcPointRef::from_ptr(ptr as *mut _)
}
}
+}
- /// Return [`EcPoint`] associated with the private key
+impl<T> EcKeyRef<T>
+where
+ T: HasParams,
+{
+ /// Return [`EcGroup`] of the `EcKey`
///
- /// OpenSSL documentation at [`EC_KEY_get0_private_key`]
+ /// OpenSSL documentation at [`EC_KEY_get0_group`]
///
- /// [`EC_KEY_get0_private_key`]: https://www.openssl.org/docs/man1.1.0/crypto/EC_KEY_get0_private_key.html
- pub fn private_key(&self) -> Option<&BigNumRef> {
+ /// [`EC_KEY_get0_group`]: https://www.openssl.org/docs/man1.1.0/crypto/EC_KEY_get0_group.html
+ pub fn group(&self) -> &EcGroupRef {
unsafe {
- let ptr = ffi::EC_KEY_get0_private_key(self.as_ptr());
- if ptr.is_null() {
- None
- } else {
- Some(BigNumRef::from_ptr(ptr as *mut _))
- }
+ let ptr = ffi::EC_KEY_get0_group(self.as_ptr());
+ EcGroupRef::from_ptr(ptr as *mut _)
}
}
@@ -577,14 +579,21 @@ impl EcKeyRef {
pub fn check_key(&self) -> Result<(), ErrorStack> {
unsafe { cvt(ffi::EC_KEY_check_key(self.as_ptr())).map(|_| ()) }
}
+}
+
+impl<T> ToOwned for EcKeyRef<T> {
+ type Owned = EcKey<T>;
- /// Create a copy of the `EcKey` to allow modification
- pub fn to_owned(&self) -> Result<EcKey, ErrorStack> {
- unsafe { cvt_p(ffi::EC_KEY_dup(self.as_ptr())).map(EcKey) }
+ fn to_owned(&self) -> EcKey<T> {
+ unsafe {
+ let r = ffi::EC_KEY_up_ref(self.as_ptr());
+ assert!(r == 1);
+ EcKey::from_ptr(self.as_ptr())
+ }
}
}
-impl EcKey {
+impl EcKey<Params> {
/// Constructs an `EcKey` corresponding to a known curve.
///
/// It will not have an associated public or private key. This kind of key is primarily useful
@@ -593,13 +602,30 @@ impl EcKey {
/// OpenSSL documenation at [`EC_KEY_new_by_curve_name`]
///
/// [`EC_KEY_new_by_curve_name`]: https://www.openssl.org/docs/man1.1.0/crypto/EC_KEY_new_by_curve_name.html
- pub fn from_curve_name(nid: Nid) -> Result<EcKey, ErrorStack> {
+ pub fn from_curve_name(nid: Nid) -> Result<EcKey<Params>, ErrorStack> {
unsafe {
init();
- cvt_p(ffi::EC_KEY_new_by_curve_name(nid.as_raw())).map(EcKey)
+ cvt_p(ffi::EC_KEY_new_by_curve_name(nid.as_raw())).map(|p| EcKey::from_ptr(p))
+ }
+ }
+
+ /// Constructs an `EcKey` corresponding to a curve.
+ ///
+ /// This corresponds to [`EC_KEY_set_group`].
+ ///
+ /// [`EC_KEY_set_group`]: https://www.openssl.org/docs/man1.1.0/crypto/EC_KEY_new.html
+ pub fn from_group(group: &EcGroupRef) -> Result<EcKey<Params>, ErrorStack> {
+ unsafe {
+ cvt_p(ffi::EC_KEY_new())
+ .map(|p| EcKey::from_ptr(p))
+ .and_then(|key| {
+ cvt(ffi::EC_KEY_set_group(key.as_ptr(), group.as_ptr())).map(|_| key)
+ })
}
}
+}
+impl EcKey<Public> {
/// Constructs an `EcKey` from the specified group with the associated `EcPoint`, public_key.
///
/// This will only have the associated public_key.
@@ -624,104 +650,67 @@ impl EcKey {
pub fn from_public_key(
group: &EcGroupRef,
public_key: &EcPointRef,
- ) -> Result<EcKey, ErrorStack> {
- let mut builder = EcKeyBuilder::new()?;
- builder.set_group(group)?;
- builder.set_public_key(public_key)?;
- Ok(builder.build())
- }
-
- /// Generates a new public/private key pair on the specified curve.
- pub fn generate(group: &EcGroupRef) -> Result<EcKey, ErrorStack> {
- let mut builder = EcKeyBuilder::new()?;
- builder.set_group(group)?;
- builder.generate_key()?;
- Ok(builder.build())
- }
-
- private_key_from_pem!(EcKey, ffi::PEM_read_bio_ECPrivateKey);
- private_key_from_der!(EcKey, ffi::d2i_ECPrivateKey);
-}
-
-foreign_type_and_impl_send_sync! {
- type CType = ffi::EC_KEY;
- fn drop = ffi::EC_KEY_free;
-
- /// Builder pattern for key generation
- ///
- /// Returns a `EcKeyBuilder` to be consumed by `build`
- pub struct EcKeyBuilder;
- /// Reference to [`EcKeyBuilder`]
- ///
- /// [`EcKeyBuilder`]: struct.EcKeyBuilder.html
- pub struct EcKeyBuilderRef;
-}
-
-impl EcKeyBuilder {
- /// Creates an empty `EcKeyBuilder` to be chained with additonal methods
- pub fn new() -> Result<EcKeyBuilder, ErrorStack> {
+ ) -> Result<EcKey<Public>, ErrorStack> {
unsafe {
- init();
- cvt_p(ffi::EC_KEY_new()).map(EcKeyBuilder)
+ cvt_p(ffi::EC_KEY_new())
+ .map(|p| EcKey::from_ptr(p))
+ .and_then(|key| {
+ cvt(ffi::EC_KEY_set_group(key.as_ptr(), group.as_ptr())).map(|_| key)
+ })
+ .and_then(|key| {
+ cvt(ffi::EC_KEY_set_public_key(
+ key.as_ptr(),
+ public_key.as_ptr(),
+ )).map(|_| key)
+ })
}
}
- /// Consume the `EcKeyBuilder` and return [`EcKey`]
- ///
- /// [`EcKey`]: struct.EcKey.html
- pub fn build(self) -> EcKey {
+ /// Constructs a public key from its affine coordinates.
+ pub fn from_public_key_affine_coordinates(
+ group: &EcGroupRef,
+ x: &BigNumRef,
+ y: &BigNumRef,
+ ) -> Result<EcKey<Public>, ErrorStack> {
unsafe {
- let key = EcKey::from_ptr(self.as_ptr());
- mem::forget(self);
- key
+ cvt_p(ffi::EC_KEY_new())
+ .map(|p| EcKey::from_ptr(p))
+ .and_then(|key| {
+ cvt(ffi::EC_KEY_set_group(key.as_ptr(), group.as_ptr())).map(|_| key)
+ })
+ .and_then(|key| {
+ cvt(ffi::EC_KEY_set_public_key_affine_coordinates(
+ key.as_ptr(),
+ x.as_ptr(),
+ y.as_ptr(),
+ )).map(|_| key)
+ })
}
}
}
-impl EcKeyBuilderRef {
- /// Set the [`EcGroup`] explicitly
- ///
- /// [`EcGroup`]: struct.EcGroup.html
- pub fn set_group(&mut self, group: &EcGroupRef) -> Result<&mut EcKeyBuilderRef, ErrorStack> {
- unsafe { cvt(ffi::EC_KEY_set_group(self.as_ptr(), group.as_ptr())).map(|_| self) }
- }
-
- /// Set public key to given `EcPoint`
- pub fn set_public_key(
- &mut self,
- public_key: &EcPointRef,
- ) -> Result<&mut EcKeyBuilderRef, ErrorStack> {
+impl EcKey<Private> {
+ /// Generates a new public/private key pair on the specified curve.
+ pub fn generate(group: &EcGroupRef) -> Result<EcKey<Private>, ErrorStack> {
unsafe {
- cvt(ffi::EC_KEY_set_public_key(
- self.as_ptr(),
- public_key.as_ptr(),
- )).map(|_| self)
+ cvt_p(ffi::EC_KEY_new())
+ .map(|p| EcKey::from_ptr(p))
+ .and_then(|key| {
+ cvt(ffi::EC_KEY_set_group(key.as_ptr(), group.as_ptr())).map(|_| key)
+ })
+ .and_then(|key| {
+ cvt(ffi::EC_KEY_generate_key(key.as_ptr())).map(|_| key)
+ })
}
}
- /// Generate public and private keys.
- pub fn generate_key(&mut self) -> Result<&mut EcKeyBuilderRef, ErrorStack> {
- unsafe { cvt(ffi::EC_KEY_generate_key(self.as_ptr())).map(|_| self) }
- }
-
- /// Sets the public key based on affine coordinates.
- pub fn set_public_key_affine_coordinates(
- &mut self,
- x: &BigNumRef,
- y: &BigNumRef,
- ) -> Result<&mut EcKeyBuilderRef, ErrorStack> {
- unsafe {
- cvt(ffi::EC_KEY_set_public_key_affine_coordinates(
- self.as_ptr(),
- x.as_ptr(),
- y.as_ptr(),
- )).map(|_| self)
- }
- }
+ private_key_from_pem!(EcKey<Private>, ffi::PEM_read_bio_ECPrivateKey);
+ private_key_from_der!(EcKey<Private>, ffi::d2i_ECPrivateKey);
+}
- /// Sets the private key.
- pub fn set_private_key(&mut self, key: &BigNumRef) -> Result<&mut EcKeyBuilderRef, ErrorStack> {
- unsafe { cvt(ffi::EC_KEY_set_private_key(self.as_ptr(), key.as_ptr())).map(|_| self) }
+impl<T> Clone for EcKey<T> {
+ fn clone(&self) -> EcKey<T> {
+ (**self).to_owned()
}
}
@@ -741,15 +730,13 @@ mod test {
fn generate() {
let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
let key = EcKey::generate(&group).unwrap();
- key.public_key().unwrap();
- key.private_key().unwrap();
}
#[test]
fn dup() {
let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
let key = EcKey::generate(&group).unwrap();
- key.to_owned().unwrap();
+ key.clone();
}
#[test]
@@ -762,7 +749,7 @@ mod test {
fn point_bytes() {
let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
let key = EcKey::generate(&group).unwrap();
- let point = key.public_key().unwrap();
+ let point = key.public_key();
let mut ctx = BigNumContext::new().unwrap();
let bytes = point
.to_bytes(&group, PointConversionForm::COMPRESSED, &mut ctx)
@@ -778,13 +765,9 @@ mod test {
let mut ctx = BigNumContext::new().unwrap();
let mut public_key = EcPoint::new(&group).unwrap();
public_key
- .mul_generator(&group, key.private_key().unwrap(), &mut ctx)
+ .mul_generator(&group, key.private_key(), &mut ctx)
.unwrap();
- assert!(
- public_key
- .eq(&group, key.public_key().unwrap(), &mut ctx)
- .unwrap()
- );
+ assert!(public_key.eq(&group, key.public_key(), &mut ctx).unwrap());
}
#[test]
@@ -793,7 +776,6 @@ mod test {
let key = EcKey::generate(&group).unwrap();
let mut ctx = BigNumContext::new().unwrap();
let bytes = key.public_key()
- .unwrap()
.to_bytes(&group, PointConversionForm::COMPRESSED, &mut ctx)
.unwrap();
@@ -801,8 +783,6 @@ mod test {
let public_key = EcPoint::from_bytes(&group, &bytes, &mut ctx).unwrap();
let ec_key = EcKey::from_public_key(&group, &public_key).unwrap();
assert!(ec_key.check_key().is_ok());
- assert!(ec_key.public_key().is_some());
- assert!(ec_key.private_key().is_none());
}
#[test]
@@ -818,32 +798,8 @@ mod test {
let xbn = BigNum::from_slice(&x).unwrap();
let ybn = BigNum::from_slice(&y).unwrap();
- let mut builder = EcKeyBuilder::new().unwrap();
- builder.set_group(&group).unwrap();
- builder
- .set_public_key_affine_coordinates(&xbn, &ybn)
- .unwrap();
-
- let ec_key = builder.build();
+ let ec_key = EcKey::from_public_key_affine_coordinates(&group, &xbn, &ybn).unwrap();
assert!(ec_key.check_key().is_ok());
- assert!(ec_key.public_key().is_some());
- }
-
- #[test]
- fn set_private_key() {
- let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
- let d = BASE64URL_NOPAD
- .decode("870MB6gfuTJ4HtUnUvYMyJpr5eUZNP4Bk43bVdj3eAE".as_bytes())
- .unwrap();
-
- let dbn = BigNum::from_slice(&d).unwrap();
-
- let mut builder = EcKeyBuilder::new().unwrap();
- builder.set_group(&group).unwrap();
- builder.set_private_key(&dbn).unwrap();
-
- let ec_key = builder.build();
- assert!(ec_key.private_key().is_some());
}
#[test]
@@ -859,18 +815,12 @@ mod test {
let xbn = BigNum::from_slice(&x).unwrap();
let ybn = BigNum::from_slice(&y).unwrap();
- let mut builder = EcKeyBuilder::new().unwrap();
- builder.set_group(&group).unwrap();
- builder
- .set_public_key_affine_coordinates(&xbn, &ybn)
- .unwrap();
-
- let ec_key = builder.build();
+ let ec_key = EcKey::from_public_key_affine_coordinates(&group, &xbn, &ybn).unwrap();
let mut xbn2 = BigNum::new().unwrap();
let mut ybn2 = BigNum::new().unwrap();
let mut ctx = BigNumContext::new().unwrap();
- let ec_key_pk = ec_key.public_key().unwrap();
+ let ec_key_pk = ec_key.public_key();
ec_key_pk
.affine_coordinates_gfp(&group, &mut xbn2, &mut ybn2, &mut ctx)
.unwrap();