Commit 35f11d55 authored by Steven Fackler's avatar Steven Fackler
Browse files

More functionality

parent 1a526495
Loading
Loading
Loading
Loading
+17 −0
Original line number Diff line number Diff line
@@ -60,6 +60,14 @@ pub enum BN_BLINDING {}
pub enum DSA_METHOD {}
pub enum EVP_PKEY_ASN1_METHOD {}

#[repr(C)]
#[derive(Copy, Clone)]
pub enum point_conversion_form_t {
    POINT_CONVERSION_COMPRESSED = 2,
    POINT_CONVERSION_UNCOMPRESSED = 4,
    POINT_CONVERSION_HYBRID = 6,
}

#[repr(C)]
pub struct GENERAL_NAME {
    pub type_: c_int,
@@ -1400,8 +1408,17 @@ extern {
    pub fn EC_GROUP_new_by_curve_name(nid: c_int) -> *mut EC_GROUP;
    pub fn EC_GROUP_get_curve_GFp(group: *const EC_GROUP, p: *mut BIGNUM, a: *mut BIGNUM, b: *mut BIGNUM, ctx: *mut BN_CTX) -> c_int;
    pub fn EC_GROUP_get_curve_GF2m(group: *const EC_GROUP, p: *mut BIGNUM, a: *mut BIGNUM, b: *mut BIGNUM, ctx: *mut BN_CTX) -> c_int;
    pub fn EC_GROUP_get_degree(group: *const EC_GROUP) -> c_int;
    pub fn EC_GROUP_get_order(group: *const EC_GROUP, order: *mut BIGNUM, ctx: *mut BN_CTX) -> c_int;

    pub fn EC_GROUP_free(group: *mut EC_GROUP);

    pub fn EC_POINT_new(group: *const EC_GROUP) -> *mut EC_POINT;
    pub fn EC_POINT_add(group: *const EC_GROUP, r: *mut EC_POINT, a: *const EC_POINT, b: *const EC_POINT, ctx: *mut BN_CTX) -> c_int;
    pub fn EC_POINT_mul(group: *const EC_GROUP, r: *mut EC_POINT, n: *const BIGNUM, q: *const EC_POINT, m: *const BIGNUM, ctx: *mut BN_CTX) -> c_int;
    pub fn EC_POINT_point2oct(group: *const EC_GROUP, p: *const EC_POINT, form: point_conversion_form_t, buf: *mut c_uchar, len: size_t, ctx: *mut BN_CTX) -> size_t;
    pub fn EC_POINT_oct2point(group: *const EC_GROUP, p: *mut EC_POINT, buf: *const c_uchar, len: size_t, ctx: *mut BN_CTX) -> c_int;
    pub fn EC_POINT_cmp(group: *const EC_GROUP, a: *const EC_POINT, b: *const EC_POINT, ctx: *mut BN_CTX) -> c_int;
    pub fn EC_POINT_free(point: *mut EC_POINT);

    pub fn ERR_get_error() -> c_ulong;
+155 −2
Original line number Diff line number Diff line
use ffi;
use std::ptr;

use {cvt, cvt_p, init};
use {cvt, cvt_n, cvt_p, init};
use bn::{BigNumRef, BigNumContextRef};
use error::ErrorStack;
use nid::Nid;
use types::OpenSslTypeRef;

pub const POINT_CONVERSION_COMPRESSED: PointConversionForm =
    PointConversionForm(ffi::point_conversion_form_t::POINT_CONVERSION_COMPRESSED);

pub const POINT_CONVERSION_UNCOMPRESSED: PointConversionForm =
    PointConversionForm(ffi::point_conversion_form_t::POINT_CONVERSION_UNCOMPRESSED);

pub const POINT_CONVERSION_HYBRID: PointConversionForm =
    PointConversionForm(ffi::point_conversion_form_t::POINT_CONVERSION_HYBRID);

#[derive(Copy, Clone)]
pub struct PointConversionForm(ffi::point_conversion_form_t);

type_!(EcGroup, EcGroupRef, ffi::EC_GROUP, ffi::EC_GROUP_free);

impl EcGroup {
@@ -75,10 +87,133 @@ impl EcGroup {
                .map(|_| ())
        }
    }

    /// Returns the degree of the curve.
    pub fn degree(&self) -> u32 {
        unsafe { ffi::EC_GROUP_get_degree(self.as_ptr()) as u32 }
    }

    /// Places the order of the curve in the provided `BigNum`.
    pub fn order(&self,
                 order: &mut BigNumRef,
                 ctx: &mut BigNumContextRef)
                 -> Result<(), ErrorStack> {
        unsafe {
            cvt(ffi::EC_GROUP_get_order(self.as_ptr(), order.as_ptr(), ctx.as_ptr())).map(|_| ())
        }
    }
}

type_!(EcPoint, EcPointRef, ffi::EC_POINT, ffi::EC_POINT_free);

impl EcPointRef {
    /// Computes `a + b`, storing the result in `self`.
    pub fn add(&mut self,
               group: &EcGroupRef,
               a: &EcPointRef,
               b: &EcPointRef,
               ctx: &mut BigNumContextRef)
               -> Result<(), ErrorStack> {
        unsafe {
            cvt(ffi::EC_POINT_add(group.as_ptr(),
                                  self.as_ptr(),
                                  a.as_ptr(),
                                  b.as_ptr(),
                                  ctx.as_ptr()))
                .map(|_| ())
        }
    }

    /// Computes `generator * n + q * m`, storing the result in `self`.
    ///
    /// If `n` is `None`, `q * m` will be computed instead.
    pub fn mul(&mut self,
               group: &EcGroupRef,
               n: Option<&BigNumRef>,
               q: &EcPointRef,
               m: &BigNumRef,
               ctx: &mut BigNumContextRef)
               -> Result<(), ErrorStack> {
        unsafe {
            cvt(ffi::EC_POINT_mul(group.as_ptr(),
                                  self.as_ptr(),
                                  n.map_or(ptr::null(), |n| n.as_ptr()),
                                  q.as_ptr(),
                                  m.as_ptr(),
                                  ctx.as_ptr()))
                .map(|_| ())
        }
    }

    /// Serializes the point to a binary representation.
    pub fn to_bytes(&self,
                    group: &EcGroupRef,
                    form: PointConversionForm,
                    ctx: &mut BigNumContextRef)
                    -> Result<Vec<u8>, ErrorStack> {
        unsafe {
            let len = ffi::EC_POINT_point2oct(group.as_ptr(),
                                              self.as_ptr(),
                                              form.0,
                                              ptr::null_mut(),
                                              0,
                                              ctx.as_ptr());
            if len == 0 {
                return Err(ErrorStack::get());
            }
            let mut buf = vec![0; len];
            let len = ffi::EC_POINT_point2oct(group.as_ptr(),
                                              self.as_ptr(),
                                              form.0,
                                              buf.as_mut_ptr(),
                                              len,
                                              ctx.as_ptr());
            if len == 0 {
                Err(ErrorStack::get())
            } else {
                Ok(buf)
            }
        }
    }

    /// Determines if this point is equal to another.
    pub fn eq(&self,
              group: &EcGroupRef,
              other: &EcPointRef,
              ctx: &mut BigNumContextRef)
              -> Result<bool, ErrorStack> {
        unsafe {
            let res = try!(cvt_n(ffi::EC_POINT_cmp(group.as_ptr(),
                                                   self.as_ptr(),
                                                   other.as_ptr(),
                                                   ctx.as_ptr())));
            Ok(res == 0)
        }
    }
}

impl EcPoint {
    /// Creates a new point on the specified curve.
    pub fn new(group: &EcGroupRef) -> Result<EcPoint, ErrorStack> {
        unsafe { cvt_p(ffi::EC_POINT_new(group.as_ptr())).map(EcPoint) }
    }

    pub fn from_bytes(group: &EcGroupRef,
                      buf: &[u8],
                      ctx: &mut BigNumContextRef)
                      -> Result<EcPoint, ErrorStack> {
        let point = try!(EcPoint::new(group));
        unsafe {
            try!(cvt(ffi::EC_POINT_oct2point(group.as_ptr(),
                                             point.as_ptr(),
                                             buf.as_ptr(),
                                             buf.len(),
                                             ctx.as_ptr())));
        }
        Ok(point)
    }
}

type_!(EcKey, EcKeyRef, ffi::EC_KEY, ffi::EC_KEY_free);

impl EcKeyRef {
@@ -119,7 +254,8 @@ impl EcKeyRef {
impl EcKey {
    /// Constructs an `EcKey` corresponding to a known curve.
    ///
    /// It will not have an associated public or private key.
    /// It will not have an associated public or private key. This kind of key is primarily useful
    /// to be provided to the `set_tmp_ecdh` methods on `Ssl` and `SslContextBuilder`.
    pub fn from_curve_name(nid: Nid) -> Result<EcKey, ErrorStack> {
        unsafe {
            init();
@@ -175,4 +311,21 @@ mod test {
        key.public_key().unwrap();
        key.private_key().unwrap();
    }

    #[test]
    fn point_new() {
        let group = EcGroup::from_curve_name(nid::X9_62_PRIME256V1).unwrap();
        EcPoint::new(&group).unwrap();
    }

    #[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 mut ctx = BigNumContext::new().unwrap();
        let bytes = point.to_bytes(&group, POINT_CONVERSION_COMPRESSED, &mut ctx).unwrap();
        let point2 = EcPoint::from_bytes(&group, &bytes, &mut ctx).unwrap();
        assert!(point.eq(&group, &point2, &mut ctx).unwrap());
    }
}
+1 −1
Original line number Diff line number Diff line
@@ -52,7 +52,7 @@ fn main() {
            format!("bio_info_cb*")
        } else if s == "_STACK" {
            format!("struct stack_st")
        } else if is_struct && s.chars().next().unwrap().is_lowercase() {
        } else if is_struct && s != "point_conversion_form_t" && s.chars().next().unwrap().is_lowercase() {
            format!("struct {}", s)
        } else {
            format!("{}", s)