use ::nettle_sys::{
ecc_point,
ecc_scalar,
nettle_ecc_scalar_get,
nettle_ecc_scalar_set,
nettle_ecc_scalar_init,
nettle_ecc_scalar_clear,
nettle_ecc_point_init,
nettle_ecc_point_get,
nettle_ecc_point_set,
nettle_ecc_point_clear,
__gmpz_init,
__gmpz_clear,
};
use std::mem::zeroed;
use helper;
use errors::Error;
use {Curve, Result};
pub struct Scalar {
pub(crate) scalar: ecc_scalar,
}
impl Scalar {
pub fn new<C: Curve>(num: &[u8]) -> Result<Scalar> {
unsafe {
let mut scalar: ecc_scalar = zeroed();
nettle_ecc_scalar_init(&mut scalar as *mut _, C::get_curve());
let mut mpz = helper::convert_buffer_to_gmpz(num);
if nettle_ecc_scalar_set(&mut scalar as *mut _, &mut mpz) == 1 {
__gmpz_clear(&mut mpz as *mut _);
Ok(Scalar{ scalar: scalar })
} else {
__gmpz_clear(&mut mpz as *mut _);
Err(Error::InvalidArgument{ argument_name: "num" }.into())
}
}
}
pub fn as_bytes(&self) -> Box<[u8]> {
unsafe {
let mut mpz = zeroed();
__gmpz_init(&mut mpz as *mut _);
nettle_ecc_scalar_get(&self.scalar as *const _, &mut mpz);
let ret = helper::convert_gmpz_to_buffer(mpz);
__gmpz_clear(&mut mpz);
ret
}
}
}
impl Clone for Scalar {
fn clone(&self) -> Self {
unsafe {
let buf = self.as_bytes();
let mut mpz = helper::convert_buffer_to_gmpz(&*buf);
let mut ret: ecc_scalar = zeroed();
nettle_ecc_scalar_init(&mut ret, self.scalar.ecc);
assert_eq!(nettle_ecc_scalar_set(&mut ret, &mut mpz), 1);
__gmpz_clear(&mut mpz);
Scalar{ scalar: ret }
}
}
}
impl Drop for Scalar {
fn drop(&mut self) {
unsafe {
nettle_ecc_scalar_clear(&mut self.scalar as *mut _);
}
}
}
pub struct Point {
pub(crate) point: ecc_point,
}
impl Point {
pub fn new<C: Curve>(x: &[u8], y: &[u8]) -> Result<Point> {
unsafe {
let mut point: ecc_point = zeroed();
nettle_ecc_point_init(&mut point as *mut _, C::get_curve());
let mut x_mpz = helper::convert_buffer_to_gmpz(x);
let mut y_mpz = helper::convert_buffer_to_gmpz(y);
if nettle_ecc_point_set(&mut point as *mut _, &mut x_mpz, &mut y_mpz) == 1 {
__gmpz_clear(&mut x_mpz as *mut _);
__gmpz_clear(&mut y_mpz as *mut _);
Ok(Point{ point: point })
} else {
__gmpz_clear(&mut x_mpz as *mut _);
__gmpz_clear(&mut y_mpz as *mut _);
Err(Error::InvalidArgument{ argument_name: "x or y" }.into())
}
}
}
pub fn as_bytes(&self) -> (Box<[u8]>,Box<[u8]>) {
unsafe {
let mut x_mpz = zeroed();
let mut y_mpz = zeroed();
__gmpz_init(&mut x_mpz as *mut _);
__gmpz_init(&mut y_mpz as *mut _);
nettle_ecc_point_get(&self.point as *const _, &mut x_mpz, &mut y_mpz);
let x_ret = helper::convert_gmpz_to_buffer(x_mpz);
let y_ret = helper::convert_gmpz_to_buffer(y_mpz);
__gmpz_clear(&mut x_mpz as *mut _);
__gmpz_clear(&mut y_mpz as *mut _);
(x_ret,y_ret)
}
}
}
impl Clone for Point {
fn clone(&self) -> Self {
unsafe {
let (buf_x,buf_y) = self.as_bytes();
let mut mpz_x = helper::convert_buffer_to_gmpz(&*buf_x);
let mut mpz_y = helper::convert_buffer_to_gmpz(&*buf_y);
let mut ret: ecc_point = zeroed();
nettle_ecc_point_init(&mut ret, self.point.ecc);
assert_eq!(nettle_ecc_point_set(&mut ret, &mut mpz_x,&mut mpz_y), 1);
__gmpz_clear(&mut mpz_x);
__gmpz_clear(&mut mpz_y);
Point{ point: ret }
}
}
}
impl Drop for Point {
fn drop(&mut self) {
unsafe {
nettle_ecc_point_clear(&mut self.point as *mut _);
}
}
}