diff --git a/doc/dox_comments/header_files/curve25519.h b/doc/dox_comments/header_files/curve25519.h index 1c12300bc..25eaf068c 100644 --- a/doc/dox_comments/header_files/curve25519.h +++ b/doc/dox_comments/header_files/curve25519.h @@ -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 diff --git a/wrapper/rust/include.am b/wrapper/rust/include.am index 2e97bac60..b1afb7808 100644 --- a/wrapper/rust/include.am +++ b/wrapper/rust/include.am @@ -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 diff --git a/wrapper/rust/wolfssl-wolfcrypt/build.rs b/wrapper/rust/wolfssl-wolfcrypt/build.rs index bd37c1990..6bcf08a70 100644 --- a/wrapper/rust/wolfssl-wolfcrypt/build.rs +++ b/wrapper/rust/wolfssl-wolfcrypt/build.rs @@ -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"); diff --git a/wrapper/rust/wolfssl-wolfcrypt/src/curve25519.rs b/wrapper/rust/wolfssl-wolfcrypt/src/curve25519.rs new file mode 100644 index 000000000..b42954bcd --- /dev/null +++ b/wrapper/rust/wolfssl-wolfcrypt/src/curve25519.rs @@ -0,0 +1,664 @@ +/* + * 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 { + let mut wc_key: MaybeUninit = MaybeUninit::uninit(); + let rc = unsafe { + sys::wc_curve25519_init(wc_key.as_mut_ptr()) + }; + if rc != 0 { + return Err(rc); + } + let mut wc_key = unsafe { wc_key.assume_init() }; + let rc = unsafe { + sys::wc_curve25519_make_key(&mut rng.wc_rng, Self::KEYSIZE as i32, &mut wc_key) + }; + if rc != 0 { + return Err(rc); + } + let curve25519key = Curve25519Key { wc_key }; + 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 { + let mut wc_key: MaybeUninit = MaybeUninit::uninit(); + let rc = unsafe { + sys::wc_curve25519_init(wc_key.as_mut_ptr()) + }; + if rc != 0 { + return Err(rc); + } + let mut wc_key = unsafe { wc_key.assume_init() }; + let private_size = private.len() as u32; + let rc = unsafe { + sys::wc_curve25519_import_private(private.as_ptr(), private_size, &mut wc_key) + }; + if rc != 0 { + return Err(rc); + } + let curve25519key = Curve25519Key { wc_key }; + 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 { + let mut wc_key: MaybeUninit = MaybeUninit::uninit(); + let rc = unsafe { + sys::wc_curve25519_init(wc_key.as_mut_ptr()) + }; + if rc != 0 { + return Err(rc); + } + let mut wc_key = unsafe { wc_key.assume_init() }; + 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 wc_key, endian as i32) + }; + if rc != 0 { + return Err(rc); + } + let curve25519key = Curve25519Key { wc_key }; + 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 { + let mut wc_key: MaybeUninit = MaybeUninit::uninit(); + let rc = unsafe { + sys::wc_curve25519_init(wc_key.as_mut_ptr()) + }; + if rc != 0 { + return Err(rc); + } + let mut wc_key = unsafe { wc_key.assume_init() }; + 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 wc_key) + }; + if rc != 0 { + return Err(rc); + } + let curve25519key = Curve25519Key { wc_key }; + 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 { + let mut wc_key: MaybeUninit = MaybeUninit::uninit(); + let rc = unsafe { + sys::wc_curve25519_init(wc_key.as_mut_ptr()) + }; + if rc != 0 { + return Err(rc); + } + let mut wc_key = unsafe { wc_key.assume_init() }; + 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 wc_key, + endian as i32) + }; + if rc != 0 { + return Err(rc); + } + let curve25519key = Curve25519Key { wc_key }; + 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 { + let mut wc_key: MaybeUninit = MaybeUninit::uninit(); + let rc = unsafe { + sys::wc_curve25519_init(wc_key.as_mut_ptr()) + }; + if rc != 0 { + return Err(rc); + } + let mut wc_key = unsafe { wc_key.assume_init() }; + let public_size = public.len() as u32; + let rc = unsafe { + sys::wc_curve25519_import_public(public.as_ptr(), public_size, &mut wc_key) + }; + if rc != 0 { + return Err(rc); + } + let curve25519key = Curve25519Key { wc_key }; + 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 { + let mut wc_key: MaybeUninit = MaybeUninit::uninit(); + let rc = unsafe { + sys::wc_curve25519_init(wc_key.as_mut_ptr()) + }; + if rc != 0 { + return Err(rc); + } + let mut wc_key = unsafe { wc_key.assume_init() }; + 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 wc_key, endian as i32) + }; + if rc != 0 { + return Err(rc); + } + let curve25519key = Curve25519Key { wc_key }; + 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 { + 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 { + 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 { + 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 { + 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 { + 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 { + 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); } + } +} diff --git a/wrapper/rust/wolfssl-wolfcrypt/src/lib.rs b/wrapper/rust/wolfssl-wolfcrypt/src/lib.rs index 02523f573..14f14ee35 100644 --- a/wrapper/rust/wolfssl-wolfcrypt/src/lib.rs +++ b/wrapper/rust/wolfssl-wolfcrypt/src/lib.rs @@ -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; diff --git a/wrapper/rust/wolfssl-wolfcrypt/tests/test_curve25519.rs b/wrapper/rust/wolfssl-wolfcrypt/tests/test_curve25519.rs new file mode 100644 index 000000000..ce1e3cc39 --- /dev/null +++ b/wrapper/rust/wolfssl-wolfcrypt/tests/test_curve25519.rs @@ -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); +}