Merge pull request #9594 from holtrop-wolfssl/rust-curve25519

Rust wrapper: add wolfssl_wolfcrypt::curve25519 module
This commit is contained in:
David Garske
2025-12-31 12:45:43 -08:00
committed by GitHub
7 changed files with 832 additions and 9 deletions

View File

@@ -46,7 +46,7 @@ int wc_curve25519_make_key(WC_RNG* rng, int keysize, curve25519_key* key);
\brief This function computes a shared secret key given a secret private
key and a received public key. It stores the generated secret key in the
buffer out and assigns the variable of the secret key to outlen. Only
buffer out and assigns the length of the secret key to outlen. Only
supports big endian.
\return 0 Returned on successfully computing a shared secret key.
@@ -93,7 +93,7 @@ int wc_curve25519_shared_secret(curve25519_key* private_key,
\brief This function computes a shared secret key given a secret private
key and a received public key. It stores the generated secret key in the
buffer out and assigns the variable of the secret key to outlen. Supports
buffer out and assigns the length of the secret key to outlen. Supports
both big and little endian.
\return 0 Returned on successfully computing a shared secret key.
@@ -361,7 +361,7 @@ int wc_curve25519_import_private_raw_ex(const byte* priv, word32 privSz,
\return 0 Returned on successfully exporting the private key from the
curve25519_key structure.
\return BAD_FUNC_ARG Returned if any input parameters are NULL.
\return ECC_BAD_ARG_E Returned if wc_curve25519_size() is not equal to key.
\return ECC_BAD_ARG_E Returned if *outLen is less than wc_curve25519_size().
\param [in] key Pointer to the structure from which to export the key.
\param [out] out Pointer to the buffer in which to store the exported key.
@@ -372,7 +372,7 @@ int wc_curve25519_import_private_raw_ex(const byte* priv, word32 privSz,
\code
int ret;
byte priv[32];
int privSz;
word32 privSz;
curve25519_key key;
// initialize and make key
@@ -402,7 +402,7 @@ int wc_curve25519_export_private_raw(curve25519_key* key, byte* out,
\return 0 Returned on successfully exporting the private key from the
curve25519_key structure.
\return BAD_FUNC_ARG Returned if any input parameters are NULL.
\return ECC_BAD_ARG_E Returned if wc_curve25519_size() is not equal to key.
\return ECC_BAD_ARG_E Returned if *outLen is less than wc_curve25519_size().
\param [in] key Pointer to the structure from which to export the key.
\param [out] out Pointer to the buffer in which to store the exported key.
@@ -416,7 +416,7 @@ int wc_curve25519_export_private_raw(curve25519_key* key, byte* out,
int ret;
byte priv[32];
int privSz;
word32 privSz;
curve25519_key key;
// initialize and make key
ret = wc_curve25519_export_private_raw_ex(&key, priv, &privSz,
@@ -656,7 +656,7 @@ int wc_curve25519_export_public_ex(curve25519_key* key, byte* out,
\return ECC_BAD_ARG_E Returned if privSz is less than CURVE25519_KEY_SIZE or
pubSz is less than CURVE25519_PUB_KEY_SIZE.
\param [in] key Pointer to the curve448_key structure in from which to
\param [in] key Pointer to the curve25519_key structure in from which to
export the key pair.
\param [out] priv Pointer to the buffer in which to store the private key.
\param [in,out] privSz On in, is the size of the priv buffer in bytes.
@@ -702,7 +702,7 @@ int wc_curve25519_export_key_raw(curve25519_key* key,
\return ECC_BAD_ARG_E Returned if privSz is less than CURVE25519_KEY_SIZE or
pubSz is less than CURVE25519_PUB_KEY_SIZE.
\param [in] key Pointer to the curve448_key structure in from which to
\param [in] key Pointer to the curve25519_key structure in from which to
export the key pair.
\param [out] priv Pointer to the buffer in which to store the private key.
\param [in,out] privSz On in, is the size of the priv buffer in bytes.
@@ -725,7 +725,7 @@ int wc_curve25519_export_key_raw(curve25519_key* key,
curve25519_key key;
// initialize and make key
ret = wc_curve25519_export_key_raw_ex(&key,priv, &privSz, pub, &pubSz,
ret = wc_curve25519_export_key_raw_ex(&key, priv, &privSz, pub, &pubSz,
EC25519_BIG_ENDIAN);
if (ret != 0) {
// error exporting key

View File

@@ -14,6 +14,7 @@ EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/headers.h
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/src/aes.rs
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/src/blake2.rs
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/src/cmac.rs
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/src/curve25519.rs
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/src/dh.rs
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/src/ecc.rs
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/src/ed25519.rs
@@ -30,6 +31,7 @@ EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/src/sys.rs
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/tests/test_aes.rs
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/tests/test_blake2.rs
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/tests/test_cmac.rs
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/tests/test_curve25519.rs
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/tests/test_dh.rs
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/tests/test_ecc.rs
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/tests/test_ed25519.rs

View File

@@ -133,6 +133,10 @@ fn scan_cfg() -> Result<()> {
/* cmac */
check_cfg(&binding, "wc_InitCmac", "cmac");
/* curve25519 */
check_cfg(&binding, "wc_curve25519_make_pub", "curve25519");
check_cfg(&binding, "wc_curve25519_make_pub_blind", "curve25519_blinding");
/* dh */
check_cfg(&binding, "wc_InitDhKey", "dh");
check_cfg(&binding, "wc_DhGenerateParams", "dh_keygen");

View File

@@ -23,6 +23,8 @@ This module provides a Rust wrapper for the wolfCrypt library's BLAKE2
functionality.
*/
#![cfg(any(blake2b, blake2s))]
use crate::sys;
use std::mem::MaybeUninit;

View File

@@ -0,0 +1,668 @@
/*
* Copyright (C) 2025 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
/*!
This module provides a Rust wrapper for the wolfCrypt library's Curve25519
functionality.
*/
#![cfg(curve25519)]
#[cfg(random)]
use crate::random::RNG;
use crate::sys;
use std::mem::MaybeUninit;
pub struct Curve25519Key {
wc_key: sys::curve25519_key,
}
impl Curve25519Key {
/// Curve 25519 key size (32 bytes).
pub const KEYSIZE: usize = sys::CURVE25519_KEYSIZE as usize;
/// Check that a public key buffer holds a valid Curve25519 key value
/// given the endian ordering.
///
/// # Parameters
///
/// * `big_endian`: True for big-endian, false for little-endian.
///
/// # Returns
///
/// Returns either Ok(()) on success or Err(e) containing the wolfSSL
/// library error code value.
pub fn check_public(public: &[u8], big_endian: bool) -> Result<(), i32> {
let public_size = public.len() as u32;
let endian = if big_endian {sys::EC25519_BIG_ENDIAN} else {sys::EC25519_LITTLE_ENDIAN};
let rc = unsafe {
sys::wc_curve25519_check_public(public.as_ptr(), public_size,
endian as i32)
};
if rc != 0 {
return Err(rc);
}
Ok(())
}
/// Generate a new private key.
///
/// # Parameters
///
/// * `rng`: Random number generator struct to use for blinding operation.
///
/// # Returns
///
/// Returns either Ok(curve25519key) on success or Err(e) containing the
/// wolfSSL library error code value.
#[cfg(random)]
pub fn generate(rng: &mut RNG) -> Result<Self, i32> {
let mut wc_key: MaybeUninit<sys::curve25519_key> = MaybeUninit::uninit();
let rc = unsafe {
sys::wc_curve25519_init(wc_key.as_mut_ptr())
};
if rc != 0 {
return Err(rc);
}
let wc_key = unsafe { wc_key.assume_init() };
let mut curve25519key = Curve25519Key { wc_key };
let rc = unsafe {
sys::wc_curve25519_make_key(&mut rng.wc_rng, Self::KEYSIZE as i32,
&mut curve25519key.wc_key)
};
if rc != 0 {
return Err(rc);
}
Ok(curve25519key)
}
/// Generate a new private key as a bare vector.
///
/// # Parameters
///
/// * `rng`: Random number generator struct to use for blinding operation.
///
/// # Returns
///
/// Returns either Ok(()) on success or Err(e) containing the wolfSSL
/// library error code value.
#[cfg(random)]
pub fn generate_priv(rng: &mut RNG, out: &mut [u8]) -> Result<(), i32> {
if out.len() != Self::KEYSIZE {
return Err(sys::wolfCrypt_ErrorCodes_BUFFER_E);
}
let rc = unsafe {
sys::wc_curve25519_make_priv(&mut rng.wc_rng, Self::KEYSIZE as i32, out.as_mut_ptr())
};
if rc != 0 {
return Err(rc);
}
Ok(())
}
/// Import a Curve25519 private key only (big-endian only).
///
/// # Parameters
///
/// * `private`: Buffer containing the Curve25519 private key.
///
/// # Returns
///
/// Returns either Ok(curve25519key) on success or Err(e) containing the
/// wolfSSL library error code value.
pub fn import_private(private: &[u8]) -> Result<Self, i32> {
let mut wc_key: MaybeUninit<sys::curve25519_key> = MaybeUninit::uninit();
let rc = unsafe {
sys::wc_curve25519_init(wc_key.as_mut_ptr())
};
if rc != 0 {
return Err(rc);
}
let wc_key = unsafe { wc_key.assume_init() };
let mut curve25519key = Curve25519Key { wc_key };
let private_size = private.len() as u32;
let rc = unsafe {
sys::wc_curve25519_import_private(private.as_ptr(), private_size,
&mut curve25519key.wc_key)
};
if rc != 0 {
return Err(rc);
}
Ok(curve25519key)
}
/// Import a Curve25519 private key only (big or little endian).
///
/// # Parameters
///
/// * `private`: Buffer containing the Curve25519 private key.
/// * `big_endian`: True for big-endian, false for little-endian.
///
/// # Returns
///
/// Returns either Ok(curve25519key) on success or Err(e) containing the
/// wolfSSL library error code value.
pub fn import_private_ex(private: &[u8], big_endian: bool) -> Result<Self, i32> {
let mut wc_key: MaybeUninit<sys::curve25519_key> = MaybeUninit::uninit();
let rc = unsafe {
sys::wc_curve25519_init(wc_key.as_mut_ptr())
};
if rc != 0 {
return Err(rc);
}
let wc_key = unsafe { wc_key.assume_init() };
let mut curve25519key = Curve25519Key { wc_key };
let private_size = private.len() as u32;
let endian = if big_endian {sys::EC25519_BIG_ENDIAN} else {sys::EC25519_LITTLE_ENDIAN};
let rc = unsafe {
sys::wc_curve25519_import_private_ex(private.as_ptr(),
private_size, &mut curve25519key.wc_key, endian as i32)
};
if rc != 0 {
return Err(rc);
}
Ok(curve25519key)
}
/// Import a Curve25519 public/private key pair (big-endian only).
///
/// # Parameters
///
/// * `private`: Buffer containing the Curve25519 private key.
/// * `public`: Buffer containing the Curve25519 public key.
///
/// # Returns
///
/// Returns either Ok(curve25519key) on success or Err(e) containing the
/// wolfSSL library error code value.
pub fn import_private_raw(private: &[u8], public: &[u8]) -> Result<Self, i32> {
let mut wc_key: MaybeUninit<sys::curve25519_key> = MaybeUninit::uninit();
let rc = unsafe {
sys::wc_curve25519_init(wc_key.as_mut_ptr())
};
if rc != 0 {
return Err(rc);
}
let wc_key = unsafe { wc_key.assume_init() };
let mut curve25519key = Curve25519Key { wc_key };
let private_size = private.len() as u32;
let public_size = public.len() as u32;
let rc = unsafe {
sys::wc_curve25519_import_private_raw(private.as_ptr(),
private_size, public.as_ptr(), public_size,
&mut curve25519key.wc_key)
};
if rc != 0 {
return Err(rc);
}
Ok(curve25519key)
}
/// Import a Curve25519 public/private key pair (big or little endian).
///
/// # Parameters
///
/// * `private`: Buffer containing the Curve25519 private key.
/// * `public`: Buffer containing the Curve25519 public key.
/// * `big_endian`: True for big-endian, false for little-endian.
///
/// # Returns
///
/// Returns either Ok(curve25519key) on success or Err(e) containing the
/// wolfSSL library error code value.
pub fn import_private_raw_ex(private: &[u8], public: &[u8], big_endian: bool) -> Result<Self, i32> {
let mut wc_key: MaybeUninit<sys::curve25519_key> = MaybeUninit::uninit();
let rc = unsafe {
sys::wc_curve25519_init(wc_key.as_mut_ptr())
};
if rc != 0 {
return Err(rc);
}
let wc_key = unsafe { wc_key.assume_init() };
let mut curve25519key = Curve25519Key { wc_key };
let private_size = private.len() as u32;
let public_size = public.len() as u32;
let endian = if big_endian {sys::EC25519_BIG_ENDIAN} else {sys::EC25519_LITTLE_ENDIAN};
let rc = unsafe {
sys::wc_curve25519_import_private_raw_ex(private.as_ptr(),
private_size, public.as_ptr(), public_size,
&mut curve25519key.wc_key, endian as i32)
};
if rc != 0 {
return Err(rc);
}
Ok(curve25519key)
}
/// Import a Curve25519 public key (big-endian only).
///
/// # Parameters
///
/// * `public`: Buffer containing the Curve25519 public key.
///
/// # Returns
///
/// Returns either Ok(curve25519key) on success or Err(e) containing the
/// wolfSSL library error code value.
pub fn import_public(public: &[u8]) -> Result<Self, i32> {
let mut wc_key: MaybeUninit<sys::curve25519_key> = MaybeUninit::uninit();
let rc = unsafe {
sys::wc_curve25519_init(wc_key.as_mut_ptr())
};
if rc != 0 {
return Err(rc);
}
let wc_key = unsafe { wc_key.assume_init() };
let mut curve25519key = Curve25519Key { wc_key };
let public_size = public.len() as u32;
let rc = unsafe {
sys::wc_curve25519_import_public(public.as_ptr(), public_size,
&mut curve25519key.wc_key)
};
if rc != 0 {
return Err(rc);
}
Ok(curve25519key)
}
/// Import a Curve25519 public key (big or little endian).
///
/// # Parameters
///
/// * `public`: Buffer containing the Curve25519 public key.
/// * `big_endian`: True for big-endian, false for little-endian.
///
/// # Returns
///
/// Returns either Ok(curve25519key) on success or Err(e) containing the
/// wolfSSL library error code value.
pub fn import_public_ex(public: &[u8], big_endian: bool) -> Result<Self, i32> {
let mut wc_key: MaybeUninit<sys::curve25519_key> = MaybeUninit::uninit();
let rc = unsafe {
sys::wc_curve25519_init(wc_key.as_mut_ptr())
};
if rc != 0 {
return Err(rc);
}
let wc_key = unsafe { wc_key.assume_init() };
let mut curve25519key = Curve25519Key { wc_key };
let public_size = public.len() as u32;
let endian = if big_endian {sys::EC25519_BIG_ENDIAN} else {sys::EC25519_LITTLE_ENDIAN};
let rc = unsafe {
sys::wc_curve25519_import_public_ex(public.as_ptr(), public_size,
&mut curve25519key.wc_key, endian as i32)
};
if rc != 0 {
return Err(rc);
}
Ok(curve25519key)
}
/// Compute the public key from an existing private key using bare vectors.
///
/// # Parameters
///
/// * `private`: Private key (input).
/// * `public`: Buffer in which to store the computed public key.
///
/// # Returns
///
/// Returns either Ok(()) on success or Err(e) containing the wolfSSL
/// library error code value.
pub fn make_pub(private: &[u8], public: &mut [u8]) -> Result<(), i32> {
let private_size = private.len() as i32;
let public_size = public.len() as i32;
let rc = unsafe {
sys::wc_curve25519_make_pub(public_size, public.as_mut_ptr(),
private_size, private.as_ptr())
};
if rc != 0 {
return Err(rc);
}
Ok(())
}
/// Compute the public key from an existing private key using bare vectors
/// with blinding.
///
/// # Parameters
///
/// * `private`: Private key (input).
/// * `public`: Buffer in which to store the computed public key.
/// * `rng`: Random number generator struct to use for blinding operation.
///
/// # Returns
///
/// Returns either Ok(()) on success or Err(e) containing the wolfSSL
/// library error code value.
#[cfg(all(curve25519_blinding, random))]
pub fn make_pub_blind(private: &[u8], public: &mut [u8], rng: &mut RNG) -> Result<(), i32> {
let private_size = private.len() as i32;
let public_size = public.len() as i32;
let rc = unsafe {
sys::wc_curve25519_make_pub_blind(public_size, public.as_mut_ptr(),
private_size, private.as_ptr(), &mut rng.wc_rng)
};
if rc != 0 {
return Err(rc);
}
Ok(())
}
/// Compute the public key from an existing private key with supplied
/// basepoint, using bare vectors.
///
/// # Parameters
///
/// * `private`: Private key (input).
/// * `public`: Buffer in which to store the computed public key.
/// * `basepoint`: Basepoint value to use.
///
/// # Returns
///
/// Returns either Ok(()) on success or Err(e) containing the wolfSSL
/// library error code value.
pub fn make_pub_generic(private: &[u8], public: &mut [u8], basepoint: &[u8]) -> Result<(), i32> {
let private_size = private.len() as i32;
let public_size = public.len() as i32;
let basepoint_size = basepoint.len() as i32;
let rc = unsafe {
sys::wc_curve25519_generic(public_size, public.as_mut_ptr(),
private_size, private.as_ptr(), basepoint_size, basepoint.as_ptr())
};
if rc != 0 {
return Err(rc);
}
Ok(())
}
/// Compute the public key from an existing private key with supplied
/// basepoint, using bare vectors.
///
/// # Parameters
///
/// * `private`: Private key (input).
/// * `public`: Buffer in which to store the computed public key.
/// * `basepoint`: Basepoint value to use.
/// * `rng`: Random number generator struct to use for blinding operation.
///
/// # Returns
///
/// Returns either Ok(()) on success or Err(e) containing the wolfSSL
/// library error code value.
#[cfg(all(curve25519_blinding, random))]
pub fn make_pub_generic_blind(private: &[u8], public: &mut [u8], basepoint: &[u8], rng: &mut RNG) -> Result<(), i32> {
let private_size = private.len() as i32;
let public_size = public.len() as i32;
let basepoint_size = basepoint.len() as i32;
let rc = unsafe {
sys::wc_curve25519_generic_blind(public_size, public.as_mut_ptr(),
private_size, private.as_ptr(), basepoint_size, basepoint.as_ptr(),
&mut rng.wc_rng)
};
if rc != 0 {
return Err(rc);
}
Ok(())
}
/// Compute a shared secret key given a secret private key and a received
/// public key. It stores the generated secret key in the buffer out and
/// returns the generated key size. Only supports big endian.
///
/// # Parameters
///
/// * `private_key`: Curve25519Key struct holding the user's private key.
/// * `public_key`: Curve25519Key struct holding the received public key.
/// * `out`: Output buffer in which to store the generated secret key.
///
/// # Returns
///
/// Returns either Ok(size) containing the number of bytes written to `out`
/// on success or Err(e) containing the wolfSSL library error code value.
pub fn shared_secret(private_key: &mut Curve25519Key, public_key: &mut Curve25519Key, out: &mut [u8]) -> Result<usize, i32> {
let mut outlen = out.len() as u32;
let rc = unsafe {
sys::wc_curve25519_shared_secret(&mut private_key.wc_key,
&mut public_key.wc_key, out.as_mut_ptr(), &mut outlen)
};
if rc != 0 {
return Err(rc);
}
Ok(outlen as usize)
}
/// Associates a `RNG` instance with this `Curve25519Key` instance.
///
/// This is necessary when generating a shared secret if wolfSSL is built
/// with the `WOLFSSL_CURVE25519_BLINDING` build option enabled.
///
/// # Parameters
///
/// * `rng`: The `RNG` struct instance to associate with this
/// `Curve25519Key` instance. The `RNG` struct should not be moved in
/// memory after calling this method.
///
/// # Returns
///
/// Returns Ok(()) on success or Err(e) containing the wolfSSL library
/// error code value.
#[cfg(all(curve25519_blinding, random))]
pub fn set_rng(&mut self, rng: &mut RNG) -> Result<(), i32> {
let rc = unsafe {
sys::wc_curve25519_set_rng(&mut self.wc_key, &mut rng.wc_rng)
};
if rc != 0 {
return Err(rc);
}
Ok(())
}
/// Compute a shared secret key given a secret private key and a received
/// public key. It stores the generated secret key in the buffer out and
/// returns the generated key size. Supports big or little endian.
///
/// # Parameters
///
/// * `private_key`: Curve25519Key struct holding the user's private key.
/// * `public_key`: Curve25519Key struct holding the received public key.
/// * `out`: Output buffer in which to store the generated secret key.
/// * `big_endian`: True for big-endian, false for little-endian.
///
/// # Returns
///
/// Returns either Ok(size) containing the number of bytes written to `out`
/// on success or Err(e) containing the wolfSSL library error code value.
pub fn shared_secret_ex(private_key: &mut Curve25519Key, public_key: &mut Curve25519Key, out: &mut [u8], big_endian: bool) -> Result<usize, i32> {
let mut outlen = out.len() as u32;
let endian = if big_endian {sys::EC25519_BIG_ENDIAN} else {sys::EC25519_LITTLE_ENDIAN};
let rc = unsafe {
sys::wc_curve25519_shared_secret_ex(&mut private_key.wc_key,
&mut public_key.wc_key, out.as_mut_ptr(), &mut outlen, endian as i32)
};
if rc != 0 {
return Err(rc);
}
Ok(outlen as usize)
}
/// Export public and private keys from Curve25519Key struct to raw buffers
/// (big-endian only).
///
/// # Parameters
///
/// * `private`: Buffer in which to store the raw private key.
/// * `public`: Buffer in which to store the raw public key.
///
/// # Returns
///
/// Returns either Ok(()) on success or Err(e) containing the wolfSSL
/// library error code value.
pub fn export_key_raw(&mut self, private: &mut [u8], public: &mut [u8]) -> Result<(), i32> {
let mut private_size = private.len() as u32;
let mut public_size = public.len() as u32;
let rc = unsafe {
sys::wc_curve25519_export_key_raw(&mut self.wc_key,
private.as_mut_ptr(), &mut private_size,
public.as_mut_ptr(), &mut public_size)
};
if rc != 0 {
return Err(rc);
}
Ok(())
}
/// Export public and private keys from Curve25519Key struct to raw buffers
/// (big or little endian).
///
/// # Parameters
///
/// * `private`: Buffer in which to store the raw private key.
/// * `public`: Buffer in which to store the raw public key.
/// * `big_endian`: True for big-endian, false for little-endian.
///
/// # Returns
///
/// Returns either Ok(()) on success or Err(e) containing the wolfSSL
/// library error code value.
pub fn export_key_raw_ex(&mut self, private: &mut [u8], public: &mut [u8], big_endian: bool) -> Result<(), i32> {
let mut private_size = private.len() as u32;
let mut public_size = public.len() as u32;
let endian = if big_endian {sys::EC25519_BIG_ENDIAN} else {sys::EC25519_LITTLE_ENDIAN};
let rc = unsafe {
sys::wc_curve25519_export_key_raw_ex(&mut self.wc_key,
private.as_mut_ptr(), &mut private_size,
public.as_mut_ptr(), &mut public_size, endian as i32)
};
if rc != 0 {
return Err(rc);
}
Ok(())
}
/// Export private key from Curve25519Key struct to a raw buffer
/// (big-endian only).
///
/// # Parameters
///
/// * `out`: Buffer in which to store the raw private key.
///
/// # Returns
///
/// Returns either Ok(size) containing the number of bytes written to `out`
/// on success or Err(e) containing the wolfSSL library error code value.
pub fn export_private_raw(&mut self, out: &mut [u8]) -> Result<usize, i32> {
let mut outlen = out.len() as u32;
let rc = unsafe {
sys::wc_curve25519_export_private_raw(&mut self.wc_key,
out.as_mut_ptr(), &mut outlen)
};
if rc != 0 {
return Err(rc);
}
Ok(outlen as usize)
}
/// Export private key from Curve25519Key struct to a raw buffer
/// (big or little endian).
///
/// # Parameters
///
/// * `out`: Buffer in which to store the raw private key.
/// * `big_endian`: True for big-endian, false for little-endian.
///
/// # Returns
///
/// Returns either Ok(size) containing the number of bytes written to `out`
/// on success or Err(e) containing the wolfSSL library error code value.
pub fn export_private_raw_ex(&mut self, out: &mut [u8], big_endian: bool) -> Result<usize, i32> {
let mut outlen = out.len() as u32;
let endian = if big_endian {sys::EC25519_BIG_ENDIAN} else {sys::EC25519_LITTLE_ENDIAN};
let rc = unsafe {
sys::wc_curve25519_export_private_raw_ex(&mut self.wc_key,
out.as_mut_ptr(), &mut outlen, endian as i32)
};
if rc != 0 {
return Err(rc);
}
Ok(outlen as usize)
}
/// Export public key from Curve25519Key struct to a raw buffer
/// (big-endian only).
///
/// # Parameters
///
/// * `out`: Buffer in which to store the raw public key.
///
/// # Returns
///
/// Returns either Ok(size) containing the number of bytes written to `out`
/// on success or Err(e) containing the wolfSSL library error code value.
pub fn export_public(&mut self, out: &mut [u8]) -> Result<usize, i32> {
let mut outlen = out.len() as u32;
let rc = unsafe {
sys::wc_curve25519_export_public(&mut self.wc_key,
out.as_mut_ptr(), &mut outlen)
};
if rc != 0 {
return Err(rc);
}
Ok(outlen as usize)
}
/// Export public key from Curve25519Key struct to a raw buffer
/// (big or little endian).
///
/// # Parameters
///
/// * `out`: Buffer in which to store the raw public key.
/// * `big_endian`: True for big-endian, false for little-endian.
///
/// # Returns
///
/// Returns either Ok(size) containing the number of bytes written to `out`
/// on success or Err(e) containing the wolfSSL library error code value.
pub fn export_public_ex(&mut self, out: &mut [u8], big_endian: bool) -> Result<usize, i32> {
let mut outlen = out.len() as u32;
let endian = if big_endian {sys::EC25519_BIG_ENDIAN} else {sys::EC25519_LITTLE_ENDIAN};
let rc = unsafe {
sys::wc_curve25519_export_public_ex(&mut self.wc_key,
out.as_mut_ptr(), &mut outlen, endian as i32)
};
if rc != 0 {
return Err(rc);
}
Ok(outlen as usize)
}
}
impl Drop for Curve25519Key {
/// Safely free the underlying wolfSSL Curve25519Key context.
///
/// This calls the `wc_curve25519_free` wolfssl library function.
///
/// The Rust Drop trait guarantees that this method is called when the
/// struct goes out of scope, automatically cleaning up resources and
/// preventing memory leaks.
fn drop(&mut self) {
unsafe { sys::wc_curve25519_free(&mut self.wc_key); }
}
}

View File

@@ -24,6 +24,7 @@ pub mod sys;
pub mod aes;
pub mod blake2;
pub mod cmac;
pub mod curve25519;
pub mod dh;
pub mod ecc;
pub mod ed25519;

View File

@@ -0,0 +1,146 @@
#![cfg(all(curve25519, random))]
use wolfssl_wolfcrypt::curve25519::*;
use wolfssl_wolfcrypt::random::RNG;
#[test]
fn test_check_pub() {
let mut rng = RNG::new().expect("Error with new()");
let mut private_buffer = [0u8; Curve25519Key::KEYSIZE];
Curve25519Key::generate_priv(&mut rng, &mut private_buffer).expect("Error with generate_priv()");
let mut public_buffer = [0u8; Curve25519Key::KEYSIZE];
Curve25519Key::make_pub(&private_buffer, &mut public_buffer).expect("Error with make_pub()");
Curve25519Key::check_public(&public_buffer, false).expect("Error with check_public()");
}
#[test]
fn test_generate_priv() {
let mut rng = RNG::new().expect("Error with new()");
let mut private_buffer = [0u8; Curve25519Key::KEYSIZE];
Curve25519Key::generate_priv(&mut rng, &mut private_buffer).expect("Error with generate_priv()");
}
#[test]
fn test_import_export_private() {
let mut rng = RNG::new().expect("Error with new()");
let mut curve25519key = Curve25519Key::generate(&mut rng).expect("Error with generate()");
let mut private_buffer = [0u8; Curve25519Key::KEYSIZE];
curve25519key.export_private_raw(&mut private_buffer).expect("Error with export_private_raw()");
Curve25519Key::import_private(&private_buffer).expect("Error with import_private()");
}
#[test]
fn test_import_export_private_ex() {
let mut rng = RNG::new().expect("Error with new()");
let mut curve25519key = Curve25519Key::generate(&mut rng).expect("Error with generate()");
let mut private_buffer = [0u8; Curve25519Key::KEYSIZE];
curve25519key.export_private_raw_ex(&mut private_buffer, false).expect("Error with export_private_raw_ex()");
Curve25519Key::import_private_ex(&private_buffer, false).expect("Error with import_private_ex()");
}
#[test]
fn test_import_export_raw() {
let mut rng = RNG::new().expect("Error with new()");
let mut curve25519key = Curve25519Key::generate(&mut rng).expect("Error with generate()");
let mut private_buffer = [0u8; Curve25519Key::KEYSIZE];
let mut public_buffer = [0u8; Curve25519Key::KEYSIZE];
curve25519key.export_key_raw(&mut private_buffer, &mut public_buffer).expect("Error with export_key_raw()");
Curve25519Key::import_private_raw(&private_buffer, &public_buffer).expect("Error with import_private_raw()");
}
#[test]
fn test_import_export_raw_ex() {
let mut rng = RNG::new().expect("Error with new()");
let mut curve25519key = Curve25519Key::generate(&mut rng).expect("Error with generate()");
let mut private_buffer = [0u8; Curve25519Key::KEYSIZE];
let mut public_buffer = [0u8; Curve25519Key::KEYSIZE];
curve25519key.export_key_raw_ex(&mut private_buffer, &mut public_buffer, false).expect("Error with export_key_raw_ex()");
Curve25519Key::import_private_raw_ex(&private_buffer, &public_buffer, false).expect("Error with import_private_raw_ex()");
}
#[test]
fn test_import_export_public() {
let mut rng = RNG::new().expect("Error with new()");
let mut curve25519key = Curve25519Key::generate(&mut rng).expect("Error with generate()");
let mut public_buffer = [0u8; Curve25519Key::KEYSIZE];
curve25519key.export_public(&mut public_buffer).expect("Error with export_public()");
Curve25519Key::import_public(&public_buffer).expect("Error with import_public()");
}
#[test]
fn test_import_export_public_ex() {
let mut rng = RNG::new().expect("Error with new()");
let mut curve25519key = Curve25519Key::generate(&mut rng).expect("Error with generate()");
let mut public_buffer = [0u8; Curve25519Key::KEYSIZE];
curve25519key.export_public_ex(&mut public_buffer, false).expect("Error with export_public_ex()");
Curve25519Key::import_public_ex(&public_buffer, false).expect("Error with import_public_ex()");
}
#[test]
fn test_make_pub() {
let mut rng = RNG::new().expect("Error with new()");
let mut private_buffer = [0u8; Curve25519Key::KEYSIZE];
Curve25519Key::generate_priv(&mut rng, &mut private_buffer).expect("Error with generate_priv()");
let mut public_buffer = [0u8; Curve25519Key::KEYSIZE];
Curve25519Key::make_pub(&private_buffer, &mut public_buffer).expect("Error with make_pub()");
}
#[test]
#[cfg(curve25519_blinding)]
fn test_make_pub_blind() {
let mut rng = RNG::new().expect("Error with new()");
let mut private_buffer = [0u8; Curve25519Key::KEYSIZE];
Curve25519Key::generate_priv(&mut rng, &mut private_buffer).expect("Error with generate_priv()");
let mut public_buffer = [0u8; Curve25519Key::KEYSIZE];
Curve25519Key::make_pub_blind(&private_buffer, &mut public_buffer, &mut rng).expect("Error with make_pub_blind()");
}
#[test]
fn test_shared_secret() {
let mut rng = RNG::new().expect("Error with new()");
let mut key1 = Curve25519Key::generate(&mut rng).expect("Error with generate()");
let mut key2 = Curve25519Key::generate(&mut rng).expect("Error with generate()");
#[cfg(curve25519_blinding)]
key1.set_rng(&mut rng).expect("Error with set_rng()");
#[cfg(curve25519_blinding)]
key2.set_rng(&mut rng).expect("Error with set_rng()");
let mut public_buffer = [0u8; Curve25519Key::KEYSIZE];
key1.export_public(&mut public_buffer).expect("Error with export_public()");
let mut key1public = Curve25519Key::import_public(&public_buffer).expect("Error with import_public()");
key2.export_public(&mut public_buffer).expect("Error with export_public()");
let mut key2public = Curve25519Key::import_public(&public_buffer).expect("Error with import_public()");
let mut ss1 = [0u8; Curve25519Key::KEYSIZE];
let mut ss2 = [0u8; Curve25519Key::KEYSIZE];
Curve25519Key::shared_secret(&mut key1, &mut key2public, &mut ss1).expect("Error with shared_secret()");
Curve25519Key::shared_secret(&mut key2, &mut key1public, &mut ss2).expect("Error with shared_secret()");
assert_eq!(ss1, ss2);
}
#[test]
fn test_shared_secret_ex() {
let mut rng = RNG::new().expect("Error with new()");
let mut key1 = Curve25519Key::generate(&mut rng).expect("Error with generate()");
let mut key2 = Curve25519Key::generate(&mut rng).expect("Error with generate()");
#[cfg(curve25519_blinding)]
key1.set_rng(&mut rng).expect("Error with set_rng()");
#[cfg(curve25519_blinding)]
key2.set_rng(&mut rng).expect("Error with set_rng()");
let mut public_buffer = [0u8; Curve25519Key::KEYSIZE];
key1.export_public(&mut public_buffer).expect("Error with export_public()");
let mut key1public = Curve25519Key::import_public(&public_buffer).expect("Error with import_public()");
key2.export_public(&mut public_buffer).expect("Error with export_public()");
let mut key2public = Curve25519Key::import_public(&public_buffer).expect("Error with import_public()");
let mut ss1 = [0u8; Curve25519Key::KEYSIZE];
let mut ss2 = [0u8; Curve25519Key::KEYSIZE];
Curve25519Key::shared_secret_ex(&mut key1, &mut key2public, &mut ss1, false).expect("Error with shared_secret()");
Curve25519Key::shared_secret_ex(&mut key2, &mut key1public, &mut ss2, false).expect("Error with shared_secret()");
assert_eq!(ss1, ss2);
}