/* * Copyright (C) 2006-2026 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 ECC functionality. The primary component is the `ECC` struct, which manages the lifecycle of a wolfSSL `ecc_key` object. It ensures proper initialization and deallocation. */ #![cfg(ecc)] use crate::sys; #[cfg(random)] use crate::random::RNG; use core::mem::{MaybeUninit}; /// Rust wrapper for wolfSSL `ecc_point` object. pub struct ECCPoint { wc_ecc_point: *mut sys::ecc_point, heap: *mut core::ffi::c_void, } impl ECCPoint { /// Import an ECCPoint from a DER-formatted buffer. /// /// # Parameters /// /// * `din`: DER-formatted buffer. /// * `curve_id`: Curve ID, e.g. ECC::SECP256R1. /// * `heap`: Optional heap hint. /// /// # Returns /// /// Returns either Ok(ECCPoint) containing the ECCPoint struct instance or /// Err(e) containing the wolfSSL library error code value. /// /// # Example /// /// ```rust /// #[cfg(all(ecc_import, random))] /// { /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::ecc::{ECC,ECCPoint}; /// let mut rng = RNG::new().expect("Failed to create RNG"); /// let curve_id = ECC::SECP256R1; /// let curve_size = ECC::get_curve_size_from_id(curve_id).expect("Error with get_curve_size_from_id()"); /// let mut ecc = ECC::generate_ex(curve_size, &mut rng, curve_id, None, None).expect("Error with generate()"); /// let ecc_point = ecc.make_pub_to_point(Some(&mut rng), None).expect("Error with make_pub_to_point()"); /// let mut der = [0u8; 128]; /// let size = ecc_point.export_der(&mut der, curve_id).expect("Error with export_der()"); /// ECCPoint::import_der(&der[0..size], curve_id, None).expect("Error with import_der()"); /// } /// ``` #[cfg(ecc_import)] pub fn import_der(din: &[u8], curve_id: i32, heap: Option<*mut core::ffi::c_void>) -> Result { let curve_idx = unsafe { sys::wc_ecc_get_curve_idx(curve_id) }; if curve_idx < 0 { return Err(curve_idx); } let heap = match heap { Some(heap) => heap, None => core::ptr::null_mut(), }; let wc_ecc_point = unsafe { sys::wc_ecc_new_point_h(heap) }; if wc_ecc_point.is_null() { return Err(sys::wolfCrypt_ErrorCodes_MEMORY_E); } let eccpoint = ECCPoint { wc_ecc_point, heap }; let din_size = crate::buffer_len_to_u32(din.len())?; let rc = unsafe { sys::wc_ecc_import_point_der(din.as_ptr(), din_size, curve_idx, eccpoint.wc_ecc_point) }; if rc != 0 { return Err(rc); } Ok(eccpoint) } /// Import an ECCPoint from a DER-formatted buffer. /// /// # Parameters /// /// * `din`: DER-formatted buffer. /// * `curve_id`: Curve ID, e.g. ECC::SECP256R1. /// * `short_key_size`: if shortKeySize != 0 then key size is always /// (din.len() - 1) / 2. /// * `heap`: Optional heap hint. /// /// # Returns /// /// Returns either Ok(ECCPoint) containing the ECCPoint struct instance or /// Err(e) containing the wolfSSL library error code value. /// /// # Example /// /// ```rust /// #[cfg(all(ecc_import, ecc_export, ecc_comp_key, random))] /// { /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::ecc::{ECC,ECCPoint}; /// let mut rng = RNG::new().expect("Failed to create RNG"); /// let curve_id = ECC::SECP256R1; /// let curve_size = ECC::get_curve_size_from_id(curve_id).expect("Error with get_curve_size_from_id()"); /// let mut ecc = ECC::generate_ex(curve_size, &mut rng, curve_id, None, None).expect("Error with generate()"); /// let ecc_point = ecc.make_pub_to_point(Some(&mut rng), None).expect("Error with make_pub_to_point()"); /// let mut der = [0u8; 128]; /// let size = ecc_point.export_der(&mut der, curve_id).expect("Error with export_der()"); /// ECCPoint::import_der_ex(&der[0..size], curve_id, 0, None).expect("Error with import_der_ex()"); /// } /// ``` #[cfg(ecc_import)] pub fn import_der_ex(din: &[u8], curve_id: i32, short_key_size: i32, heap: Option<*mut core::ffi::c_void>) -> Result { let curve_idx = unsafe { sys::wc_ecc_get_curve_idx(curve_id) }; if curve_idx < 0 { return Err(curve_idx); } let heap = match heap { Some(heap) => heap, None => core::ptr::null_mut(), }; let wc_ecc_point = unsafe { sys::wc_ecc_new_point_h(heap) }; if wc_ecc_point.is_null() { return Err(sys::wolfCrypt_ErrorCodes_MEMORY_E); } let eccpoint = ECCPoint { wc_ecc_point, heap }; let din_size = crate::buffer_len_to_u32(din.len())?; let rc = unsafe { sys::wc_ecc_import_point_der_ex(din.as_ptr(), din_size, curve_idx, wc_ecc_point, short_key_size) }; if rc != 0 { return Err(rc); } Ok(eccpoint) } /// Export an ECCPoint in DER format. /// /// # Parameters /// /// * `dout`: Output buffer. /// * `curve_id`: Curve ID, e.g. ECC::SECP256R1. /// /// # Returns /// /// Returns either Ok(size) containing the number of bytes written to /// `dout` or Err(e) containing the wolfSSL library error code value. /// /// # Example /// /// ```rust /// #[cfg(all(ecc_export, random))] /// { /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::ecc::{ECC,ECCPoint}; /// let mut rng = RNG::new().expect("Failed to create RNG"); /// let curve_id = ECC::SECP256R1; /// let curve_size = ECC::get_curve_size_from_id(curve_id).expect("Error with get_curve_size_from_id()"); /// let mut ecc = ECC::generate_ex(curve_size, &mut rng, curve_id, None, None).expect("Error with generate()"); /// let ecc_point = ecc.make_pub_to_point(Some(&mut rng), None).expect("Error with make_pub_to_point()"); /// let mut der = [0u8; 128]; /// let size = ecc_point.export_der(&mut der, curve_id).expect("Error with export_der()"); /// assert!(size > 0 && size <= der.len()); /// ECCPoint::import_der(&der[0..size], curve_id, None).expect("Error with import_der()"); /// } /// ``` #[cfg(ecc_export)] pub fn export_der(&self, dout: &mut [u8], curve_id: i32) -> Result { let curve_idx = unsafe { sys::wc_ecc_get_curve_idx(curve_id) }; if curve_idx < 0 { return Err(curve_idx); } let mut dout_size = crate::buffer_len_to_u32(dout.len())?; let rc = unsafe { sys::wc_ecc_export_point_der(curve_idx, self.wc_ecc_point, dout.as_mut_ptr(), &mut dout_size) }; if rc != 0 { return Err(rc); } Ok(dout_size as usize) } /// Export an ECCPoint in compressed DER format. /// /// # Parameters /// /// * `dout`: Output buffer. /// * `curve_id`: Curve ID, e.g. ECC::SECP256R1. /// /// # Returns /// /// Returns either Ok(size) containing the number of bytes written to /// `dout` or Err(e) containing the wolfSSL library error code value. /// /// # Example /// /// ```rust /// #[cfg(all(ecc_export, ecc_comp_key, random))] /// { /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::ecc::{ECC,ECCPoint}; /// let mut rng = RNG::new().expect("Failed to create RNG"); /// let curve_id = ECC::SECP256R1; /// let curve_size = ECC::get_curve_size_from_id(curve_id).expect("Error with get_curve_size_from_id()"); /// let mut ecc = ECC::generate_ex(curve_size, &mut rng, curve_id, None, None).expect("Error with generate()"); /// let ecc_point = ecc.make_pub_to_point(Some(&mut rng), None).expect("Error with make_pub_to_point()"); /// let mut der = [0u8; 128]; /// let size = ecc_point.export_der_compressed(&mut der, curve_id).expect("Error with export_der_compressed()"); /// } /// ``` #[cfg(all(ecc_export, ecc_comp_key))] pub fn export_der_compressed(&self, dout: &mut [u8], curve_id: i32) -> Result { let curve_idx = unsafe { sys::wc_ecc_get_curve_idx(curve_id) }; if curve_idx < 0 { return Err(curve_idx); } let mut dout_size = crate::buffer_len_to_u32(dout.len())?; let rc = unsafe { sys::wc_ecc_export_point_der_ex(curve_idx, self.wc_ecc_point, dout.as_mut_ptr(), &mut dout_size, 1) }; if rc != 0 { return Err(rc); } Ok(dout_size as usize) } /// Zeroize the ECCPoint. /// /// # Example /// /// ```rust /// # extern crate std; /// #[cfg(random)] /// { /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::ecc::ECC; /// let mut rng = RNG::new().expect("Failed to create RNG"); /// let mut ecc = ECC::generate(32, &mut rng, None, None).expect("Error with generate()"); /// let mut ecc_point = ecc.make_pub_to_point(Some(&mut rng), None).expect("Error with make_pub_to_point()"); /// ecc_point.forcezero(); /// } /// ``` pub fn forcezero(&mut self) { unsafe { sys::wc_ecc_forcezero_point(self.wc_ecc_point) }; } } impl ECCPoint { fn zeroize(&mut self) { self.wc_ecc_point = core::ptr::null_mut(); self.heap = core::ptr::null_mut(); } } impl Drop for ECCPoint { /// Safely free the underlying wolfSSL ecc_point context. /// /// This calls the `wc_ecc_del_point_h()` wolfssl library function. /// /// The Rust Drop trait guarantees that this method is called when the /// ECCPoint struct instance goes out of scope, automatically cleaning up /// resources and preventing memory leaks. fn drop(&mut self) { unsafe { sys::wc_ecc_del_point_h(self.wc_ecc_point, self.heap); } self.zeroize(); } } /// The `ECC` struct manages the lifecycle of a wolfSSL `ecc_key` object. /// /// It ensures proper initialization and deallocation. /// /// An instance can be created with `generate()`, `import_x963()`, /// `import_x963_ex()`, `import_private_key()`, `import_private_key_ex()`, /// `import_raw()`, or `import_raw_ex()`. pub struct ECC { pub(crate) wc_ecc_key: sys::ecc_key, } #[cfg(ecc_curve_ids)] impl ECC { pub const CURVE_INVALID: i32 = sys::ecc_curve_ids_ECC_CURVE_INVALID; pub const CURVE_DEF: i32 = sys::ecc_curve_ids_ECC_CURVE_DEF; pub const SECP192R1: i32 = sys::ecc_curve_ids_ECC_SECP192R1; pub const PRIME192V2: i32 = sys::ecc_curve_ids_ECC_PRIME192V2; pub const PRIME192V3: i32 = sys::ecc_curve_ids_ECC_PRIME192V3; pub const PRIME239V1: i32 = sys::ecc_curve_ids_ECC_PRIME239V1; pub const PRIME239V2: i32 = sys::ecc_curve_ids_ECC_PRIME239V2; pub const PRIME239V3: i32 = sys::ecc_curve_ids_ECC_PRIME239V3; pub const SECP256R1: i32 = sys::ecc_curve_ids_ECC_SECP256R1; pub const SECP112R1: i32 = sys::ecc_curve_ids_ECC_SECP112R1; pub const SECP112R2: i32 = sys::ecc_curve_ids_ECC_SECP112R2; pub const SECP128R1: i32 = sys::ecc_curve_ids_ECC_SECP128R1; pub const SECP128R2: i32 = sys::ecc_curve_ids_ECC_SECP128R2; pub const SECP160R1: i32 = sys::ecc_curve_ids_ECC_SECP160R1; pub const SECP160R2: i32 = sys::ecc_curve_ids_ECC_SECP160R2; pub const SECP224R1: i32 = sys::ecc_curve_ids_ECC_SECP224R1; pub const SECP384R1: i32 = sys::ecc_curve_ids_ECC_SECP384R1; pub const SECP521R1: i32 = sys::ecc_curve_ids_ECC_SECP521R1; pub const SECP160K1: i32 = sys::ecc_curve_ids_ECC_SECP160K1; pub const SECP192K1: i32 = sys::ecc_curve_ids_ECC_SECP192K1; pub const SECP224K1: i32 = sys::ecc_curve_ids_ECC_SECP224K1; pub const SECP256K1: i32 = sys::ecc_curve_ids_ECC_SECP256K1; pub const BRAINPOOLP160R1: i32 = sys::ecc_curve_ids_ECC_BRAINPOOLP160R1; pub const BRAINPOOLP192R1: i32 = sys::ecc_curve_ids_ECC_BRAINPOOLP192R1; pub const BRAINPOOLP224R1: i32 = sys::ecc_curve_ids_ECC_BRAINPOOLP224R1; pub const BRAINPOOLP256R1: i32 = sys::ecc_curve_ids_ECC_BRAINPOOLP256R1; pub const BRAINPOOLP320R1: i32 = sys::ecc_curve_ids_ECC_BRAINPOOLP320R1; pub const BRAINPOOLP384R1: i32 = sys::ecc_curve_ids_ECC_BRAINPOOLP384R1; pub const BRAINPOOLP512R1: i32 = sys::ecc_curve_ids_ECC_BRAINPOOLP512R1; #[cfg(ecc_curve_sm2p256v1)] pub const SM2P256V1: i32 = sys::ecc_curve_ids_ECC_SM2P256V1; #[cfg(ecc_curve_25519)] pub const X25519: i32 = sys::ecc_curve_ids_ECC_X25519; #[cfg(ecc_curve_448)] pub const X448: i32 = sys::ecc_curve_ids_ECC_X448; #[cfg(ecc_curve_sakke)] pub const SAKKE_1: i32 = sys::ecc_curve_ids_ECC_SAKKE_1; #[cfg(ecc_custom_curves)] pub const CURVE_CUSTOM: i32 = sys::ecc_curve_ids_ECC_CURVE_CUSTOM; pub const CURVE_MAX: i32 = sys::ecc_curve_ids_ECC_CURVE_MAX; } #[cfg(not(ecc_curve_ids))] impl ECC { pub const CURVE_INVALID: i32 = sys::ecc_curve_id_ECC_CURVE_INVALID; pub const CURVE_DEF: i32 = sys::ecc_curve_id_ECC_CURVE_DEF; pub const SECP192R1: i32 = sys::ecc_curve_id_ECC_SECP192R1; pub const PRIME192V2: i32 = sys::ecc_curve_id_ECC_PRIME192V2; pub const PRIME192V3: i32 = sys::ecc_curve_id_ECC_PRIME192V3; pub const PRIME239V1: i32 = sys::ecc_curve_id_ECC_PRIME239V1; pub const PRIME239V2: i32 = sys::ecc_curve_id_ECC_PRIME239V2; pub const PRIME239V3: i32 = sys::ecc_curve_id_ECC_PRIME239V3; pub const SECP256R1: i32 = sys::ecc_curve_id_ECC_SECP256R1; pub const SECP112R1: i32 = sys::ecc_curve_id_ECC_SECP112R1; pub const SECP112R2: i32 = sys::ecc_curve_id_ECC_SECP112R2; pub const SECP128R1: i32 = sys::ecc_curve_id_ECC_SECP128R1; pub const SECP128R2: i32 = sys::ecc_curve_id_ECC_SECP128R2; pub const SECP160R1: i32 = sys::ecc_curve_id_ECC_SECP160R1; pub const SECP160R2: i32 = sys::ecc_curve_id_ECC_SECP160R2; pub const SECP224R1: i32 = sys::ecc_curve_id_ECC_SECP224R1; pub const SECP384R1: i32 = sys::ecc_curve_id_ECC_SECP384R1; pub const SECP521R1: i32 = sys::ecc_curve_id_ECC_SECP521R1; pub const SECP160K1: i32 = sys::ecc_curve_id_ECC_SECP160K1; pub const SECP192K1: i32 = sys::ecc_curve_id_ECC_SECP192K1; pub const SECP224K1: i32 = sys::ecc_curve_id_ECC_SECP224K1; pub const SECP256K1: i32 = sys::ecc_curve_id_ECC_SECP256K1; pub const BRAINPOOLP160R1: i32 = sys::ecc_curve_id_ECC_BRAINPOOLP160R1; pub const BRAINPOOLP192R1: i32 = sys::ecc_curve_id_ECC_BRAINPOOLP192R1; pub const BRAINPOOLP224R1: i32 = sys::ecc_curve_id_ECC_BRAINPOOLP224R1; pub const BRAINPOOLP256R1: i32 = sys::ecc_curve_id_ECC_BRAINPOOLP256R1; pub const BRAINPOOLP320R1: i32 = sys::ecc_curve_id_ECC_BRAINPOOLP320R1; pub const BRAINPOOLP384R1: i32 = sys::ecc_curve_id_ECC_BRAINPOOLP384R1; pub const BRAINPOOLP512R1: i32 = sys::ecc_curve_id_ECC_BRAINPOOLP512R1; #[cfg(ecc_curve_sm2p256v1)] pub const SM2P256V1: i32 = sys::ecc_curve_id_ECC_SM2P256V1; #[cfg(ecc_curve_25519)] pub const X25519: i32 = sys::ecc_curve_id_ECC_X25519; #[cfg(ecc_curve_448)] pub const X448: i32 = sys::ecc_curve_id_ECC_X448; #[cfg(ecc_curve_sakke)] pub const SAKKE_1: i32 = sys::ecc_curve_id_ECC_SAKKE_1; #[cfg(ecc_custom_curves)] pub const CURVE_CUSTOM: i32 = sys::ecc_curve_id_ECC_CURVE_CUSTOM; pub const CURVE_MAX: i32 = sys::ecc_curve_id_ECC_CURVE_MAX; } impl ECC { pub const FLAG_NONE: i32 = sys::WC_ECC_FLAG_NONE as i32; pub const FLAG_COFACTOR: i32 = sys::WC_ECC_FLAG_COFACTOR as i32; pub const FLAG_DEC_SIGN: i32 = sys::WC_ECC_FLAG_DEC_SIGN as i32; /// Generate a new ECC key with the given size. /// /// # Parameters /// /// * `size`: Desired key length in bytes. /// * `rng`: Reference to a `RNG` struct to use for random number /// generation while making the key. /// * `heap`: Optional heap hint. /// * `dev_id` Optional device ID to use with crypto callbacks or async hardware. /// /// # Returns /// /// Returns either Ok(ECC) containing the ECC struct instance or Err(e) /// containing the wolfSSL library error code value. /// /// # Example /// /// ```rust /// # extern crate std; /// #[cfg(random)] /// { /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::ecc::ECC; /// let mut rng = RNG::new().expect("Failed to create RNG"); /// let mut ecc = ECC::generate(32, &mut rng, None, None).expect("Error with generate()"); /// ecc.check().expect("Error with check()"); /// } /// ``` #[cfg(random)] pub fn generate(size: i32, rng: &mut RNG, heap: Option<*mut core::ffi::c_void>, dev_id: Option) -> Result { let mut wc_ecc_key: MaybeUninit = MaybeUninit::uninit(); let heap = match heap { Some(heap) => heap, None => core::ptr::null_mut(), }; let dev_id = match dev_id { Some(dev_id) => dev_id, None => sys::INVALID_DEVID, }; let rc = unsafe { sys::wc_ecc_init_ex(wc_ecc_key.as_mut_ptr(), heap, dev_id) }; if rc != 0 { return Err(rc); } let wc_ecc_key = unsafe { wc_ecc_key.assume_init() }; let mut ecc = ECC { wc_ecc_key }; let rc = unsafe { sys::wc_ecc_make_key(&mut rng.wc_rng, size, &mut ecc.wc_ecc_key) }; if rc != 0 { return Err(rc); } Ok(ecc) } /// Generate a new ECC key with the given size and curve. /// /// # Parameters /// /// * `size`: Desired key length in bytes. /// * `rng`: Reference to a `RNG` struct to use for random number /// generation while making the key. /// * `curve_id`: Curve ID, e.g. ECC::SECP256R1. /// * `heap`: Optional heap hint. /// * `dev_id` Optional device ID to use with crypto callbacks or async hardware. /// /// # Returns /// /// Returns either Ok(ECC) containing the ECC struct instance or Err(e) /// containing the wolfSSL library error code value. /// /// # Example /// /// ```rust /// # extern crate std; /// #[cfg(random)] /// { /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::ecc::ECC; /// let mut rng = RNG::new().expect("Failed to create RNG"); /// let curve_id = ECC::SECP256R1; /// let curve_size = ECC::get_curve_size_from_id(curve_id).expect("Error with get_curve_size_from_id()"); /// let mut ecc = ECC::generate_ex(curve_size, &mut rng, curve_id, None, None).expect("Error with generate_ex()"); /// ecc.check().expect("Error with check()"); /// } /// ``` #[cfg(random)] pub fn generate_ex(size: i32, rng: &mut RNG, curve_id: i32, heap: Option<*mut core::ffi::c_void>, dev_id: Option) -> Result { let mut wc_ecc_key: MaybeUninit = MaybeUninit::uninit(); let heap = match heap { Some(heap) => heap, None => core::ptr::null_mut(), }; let dev_id = match dev_id { Some(dev_id) => dev_id, None => sys::INVALID_DEVID, }; let rc = unsafe { sys::wc_ecc_init_ex(wc_ecc_key.as_mut_ptr(), heap, dev_id) }; if rc != 0 { return Err(rc); } let wc_ecc_key = unsafe { wc_ecc_key.assume_init() }; let mut ecc = ECC { wc_ecc_key }; let rc = unsafe { sys::wc_ecc_make_key_ex(&mut rng.wc_rng, size, &mut ecc.wc_ecc_key, curve_id) }; if rc != 0 { return Err(rc); } Ok(ecc) } /// Generate a new ECC key with the given size, curve, and flags. /// /// # Parameters /// /// * `size`: Desired key length in bytes. /// * `rng`: Reference to a `RNG` struct to use for random number /// generation while making the key. /// * `curve_id`: Curve ID, e.g. ECC::SECP256R1. /// * `flags`: Flags for making the key. /// * `heap`: Optional heap hint. /// * `dev_id` Optional device ID to use with crypto callbacks or async hardware. /// /// # Returns /// /// Returns either Ok(ECC) containing the ECC struct instance or Err(e) /// containing the wolfSSL library error code value. /// /// # Example /// /// ```rust /// # extern crate std; /// #[cfg(random)] /// { /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::ecc::ECC; /// let mut rng = RNG::new().expect("Failed to create RNG"); /// let curve_id = ECC::SECP256R1; /// let curve_size = ECC::get_curve_size_from_id(curve_id).expect("Error with get_curve_size_from_id()"); /// let mut ecc = ECC::generate_ex2(curve_size, &mut rng, curve_id, ECC::FLAG_COFACTOR, None, None).expect("Error with generate_ex2()"); /// ecc.check().expect("Error with check()"); /// } /// ``` #[cfg(random)] pub fn generate_ex2(size: i32, rng: &mut RNG, curve_id: i32, flags: i32, heap: Option<*mut core::ffi::c_void>, dev_id: Option) -> Result { let mut wc_ecc_key: MaybeUninit = MaybeUninit::uninit(); let heap = match heap { Some(heap) => heap, None => core::ptr::null_mut(), }; let dev_id = match dev_id { Some(dev_id) => dev_id, None => sys::INVALID_DEVID, }; let rc = unsafe { sys::wc_ecc_init_ex(wc_ecc_key.as_mut_ptr(), heap, dev_id) }; if rc != 0 { return Err(rc); } let wc_ecc_key = unsafe { wc_ecc_key.assume_init() }; let mut ecc = ECC { wc_ecc_key }; let rc = unsafe { sys::wc_ecc_make_key_ex2(&mut rng.wc_rng, size, &mut ecc.wc_ecc_key, curve_id, flags) }; if rc != 0 { return Err(rc); } Ok(ecc) } /// Get the curve size corresponding to the given curve ID. /// /// # Parameters /// /// * `curve_id`: Curve ID, e.g. ECC::SECP256R1. /// /// # Returns /// /// Returns either Ok(size) containing the curve size or Err(e) /// containing the wolfSSL library error code value. /// /// # Example /// /// ```rust /// # extern crate std; /// #[cfg(random)] /// { /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::ecc::ECC; /// let mut rng = RNG::new().expect("Failed to create RNG"); /// let curve_id = ECC::SECP256R1; /// let curve_size = ECC::get_curve_size_from_id(curve_id).expect("Error with get_curve_size_from_id()"); /// let mut ecc = ECC::generate_ex(curve_size, &mut rng, curve_id, None, None).expect("Error with generate()"); /// ecc.check().expect("Error with check()"); /// } /// ``` pub fn get_curve_size_from_id(curve_id: i32) -> Result { let rc = unsafe { sys::wc_ecc_get_curve_size_from_id(curve_id) }; if rc < 0 { return Err(rc); } Ok(rc) } /// Import public and private ECC key pair from DER input buffer. /// /// # Parameters /// /// * `der`: DER buffer containing the ECC public and private key pair. /// * `heap`: Optional heap hint. /// * `dev_id` Optional device ID to use with crypto callbacks or async hardware. /// /// # Returns /// /// Returns either Ok(ECC) containing the ECC struct instance or Err(e) /// containing the wolfSSL library error code value. /// /// # Example /// /// ```rust /// # extern crate std; /// #[cfg(random)] /// { /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::ecc::ECC; /// use std::fs; /// let mut rng = RNG::new().expect("Failed to create RNG"); /// let key_path = "../../../certs/ecc-client-key.der"; /// let der: Vec = fs::read(key_path).expect("Error reading key file"); /// let mut ecc = ECC::import_der(&der, None, None).expect("Error with import_der()"); /// } /// ``` pub fn import_der(der: &[u8], heap: Option<*mut core::ffi::c_void>, dev_id: Option) -> Result { let mut wc_ecc_key: MaybeUninit = MaybeUninit::uninit(); let heap = match heap { Some(heap) => heap, None => core::ptr::null_mut(), }; let dev_id = match dev_id { Some(dev_id) => dev_id, None => sys::INVALID_DEVID, }; let rc = unsafe { sys::wc_ecc_init_ex(wc_ecc_key.as_mut_ptr(), heap, dev_id) }; if rc != 0 { return Err(rc); } let wc_ecc_key = unsafe { wc_ecc_key.assume_init() }; let mut ecc = ECC { wc_ecc_key }; let mut idx = 0u32; let der_size = crate::buffer_len_to_u32(der.len())?; let rc = unsafe { sys::wc_EccPrivateKeyDecode(der.as_ptr(), &mut idx, &mut ecc.wc_ecc_key, der_size) }; if rc != 0 { return Err(rc); } Ok(ecc) } /// Import public ECC key from DER input buffer. /// /// # Parameters /// /// * `der`: DER buffer containing the ECC public key. /// * `heap`: Optional heap hint. /// * `dev_id` Optional device ID to use with crypto callbacks or async hardware. /// /// # Returns /// /// Returns either Ok(ECC) containing the ECC struct instance or Err(e) /// containing the wolfSSL library error code value. /// /// # Example /// /// ```rust /// # extern crate std; /// #[cfg(random)] /// { /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::ecc::ECC; /// use std::fs; /// let mut rng = RNG::new().expect("Failed to create RNG"); /// let key_path = "../../../certs/ecc-client-key.der"; /// let der: Vec = fs::read(key_path).expect("Error reading key file"); /// let mut ecc = ECC::import_der(&der, None, None).expect("Error with import_der()"); /// let hash = [0x42u8; 32]; /// let mut signature = [0u8; 128]; /// let signature_length = ecc.sign_hash(&hash, &mut signature, &mut rng).expect("Error with sign_hash()"); /// assert!(signature_length > 0 && signature_length <= signature.len()); /// let signature = &mut signature[0..signature_length]; /// let key_path = "../../../certs/ecc-client-keyPub.der"; /// let der: Vec = fs::read(key_path).expect("Error reading key file"); /// let mut ecc = ECC::import_public_der(&der, None, None).expect("Error with import_public_der()"); /// } /// ``` pub fn import_public_der(der: &[u8], heap: Option<*mut core::ffi::c_void>, dev_id: Option) -> Result { let mut wc_ecc_key: MaybeUninit = MaybeUninit::uninit(); let heap = match heap { Some(heap) => heap, None => core::ptr::null_mut(), }; let dev_id = match dev_id { Some(dev_id) => dev_id, None => sys::INVALID_DEVID, }; let rc = unsafe { sys::wc_ecc_init_ex(wc_ecc_key.as_mut_ptr(), heap, dev_id) }; if rc != 0 { return Err(rc); } let wc_ecc_key = unsafe { wc_ecc_key.assume_init() }; let mut ecc = ECC { wc_ecc_key }; let mut idx = 0u32; let der_size = crate::buffer_len_to_u32(der.len())?; let rc = unsafe { sys::wc_EccPublicKeyDecode(der.as_ptr(), &mut idx, &mut ecc.wc_ecc_key, der_size) }; if rc != 0 { return Err(rc); } Ok(ecc) } /// Import a public/private ECC key pair from a buffer containing the raw /// private key and a second buffer containing the ANSI X9.63 formatted /// public key. This function handles both compressed and uncompressed /// keys as long as wolfSSL is built with the HAVE_COMP_KEY build option /// enabled. /// /// # Parameters /// /// * `priv_buf`: Buffer containing the raw private key. /// * `pub_buf`: Buffer containing the ANSI X9.63 formatted public key. /// * `heap`: Optional heap hint. /// * `dev_id` Optional device ID to use with crypto callbacks or async hardware. /// /// # Returns /// /// Returns either Ok(ECC) containing the ECC struct instance or Err(e) /// containing the wolfSSL library error code value. /// /// # Example /// /// ```rust /// #[cfg(all(ecc_import, random))] /// { /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::ecc::ECC; /// let mut rng = RNG::new().expect("Failed to create RNG"); /// let mut ecc = ECC::generate(32, &mut rng, None, None).expect("Error with generate()"); /// let hash = [0x42u8; 32]; /// let mut signature = [0u8; 128]; /// let signature_length = ecc.sign_hash(&hash, &mut signature, &mut rng).expect("Error with sign_hash()"); /// let signature = &signature[0..signature_length]; /// let mut d = [0u8; 32]; /// let d_size = ecc.export_private(&mut d).expect("Error with export_private()"); /// let mut x963 = [0u8; 128]; /// let x963_size = ecc.export_x963(&mut x963).expect("Error with export_x963()"); /// let x963 = &x963[0..x963_size]; /// let mut ecc2 = ECC::import_private_key(&d, x963, None, None).expect("Error with import_private_key()"); /// let valid = ecc2.verify_hash(&signature, &hash).expect("Error with verify_hash()"); /// assert_eq!(valid, true); /// } /// ``` #[cfg(ecc_import)] pub fn import_private_key(priv_buf: &[u8], pub_buf: &[u8], heap: Option<*mut core::ffi::c_void>, dev_id: Option) -> Result { let mut wc_ecc_key: MaybeUninit = MaybeUninit::uninit(); let heap = match heap { Some(heap) => heap, None => core::ptr::null_mut(), }; let dev_id = match dev_id { Some(dev_id) => dev_id, None => sys::INVALID_DEVID, }; let rc = unsafe { sys::wc_ecc_init_ex(wc_ecc_key.as_mut_ptr(), heap, dev_id) }; if rc != 0 { return Err(rc); } let wc_ecc_key = unsafe { wc_ecc_key.assume_init() }; let mut ecc = ECC { wc_ecc_key }; let priv_size = crate::buffer_len_to_u32(priv_buf.len())?; let pub_ptr = if pub_buf.is_empty() {core::ptr::null()} else {pub_buf.as_ptr()}; let pub_size = crate::buffer_len_to_u32(pub_buf.len())?; let rc = unsafe { sys::wc_ecc_import_private_key(priv_buf.as_ptr(), priv_size, pub_ptr, pub_size, &mut ecc.wc_ecc_key) }; if rc != 0 { return Err(rc); } Ok(ecc) } /// Import a public/private ECC key pair from a buffer containing the raw /// private key and a second buffer containing the ANSI X9.63 formatted /// public key. This function handles both compressed and uncompressed /// keys as long as wolfSSL is built with the HAVE_COMP_KEY build option /// enabled. This function allows the curve ID to be explicitly specified. /// /// # Parameters /// /// * `priv_buf`: Buffer containing the raw private key. /// * `pub_buf`: Buffer containing the ANSI X9.63 formatted public key. /// * `curve_id`: Curve ID, e.g. ECC::SECP256R1. /// * `heap`: Optional heap hint. /// * `dev_id` Optional device ID to use with crypto callbacks or async hardware. /// /// # Returns /// /// Returns either Ok(ECC) containing the ECC struct instance or Err(e) /// containing the wolfSSL library error code value. /// /// # Example /// /// ```rust /// #[cfg(all(ecc_import, random))] /// { /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::ecc::ECC; /// let mut rng = RNG::new().expect("Failed to create RNG"); /// let curve_id = ECC::SECP256R1; /// let curve_size = ECC::get_curve_size_from_id(curve_id).expect("Error with get_curve_size_from_id()"); /// let mut ecc = ECC::generate_ex(curve_size, &mut rng, curve_id, None, None).expect("Error with generate_ex()"); /// let hash = [0x42u8; 32]; /// let mut signature = [0u8; 128]; /// let signature_length = ecc.sign_hash(&hash, &mut signature, &mut rng).expect("Error with sign_hash()"); /// let signature = &signature[0..signature_length]; /// let mut d = [0u8; 32]; /// let d_size = ecc.export_private(&mut d).expect("Error with export_private()"); /// let mut x963 = [0u8; 128]; /// let x963_size = ecc.export_x963(&mut x963).expect("Error with export_x963()"); /// let x963 = &x963[0..x963_size]; /// let mut ecc2 = ECC::import_private_key_ex(&d, x963, curve_id, None, None).expect("Error with import_private_key_ex()"); /// let valid = ecc2.verify_hash(&signature, &hash).expect("Error with verify_hash()"); /// assert_eq!(valid, true); /// } /// ``` #[cfg(ecc_import)] pub fn import_private_key_ex(priv_buf: &[u8], pub_buf: &[u8], curve_id: i32, heap: Option<*mut core::ffi::c_void>, dev_id: Option) -> Result { let mut wc_ecc_key: MaybeUninit = MaybeUninit::uninit(); let heap = match heap { Some(heap) => heap, None => core::ptr::null_mut(), }; let dev_id = match dev_id { Some(dev_id) => dev_id, None => sys::INVALID_DEVID, }; let rc = unsafe { sys::wc_ecc_init_ex(wc_ecc_key.as_mut_ptr(), heap, dev_id) }; if rc != 0 { return Err(rc); } let wc_ecc_key = unsafe { wc_ecc_key.assume_init() }; let mut ecc = ECC { wc_ecc_key }; let priv_size = crate::buffer_len_to_u32(priv_buf.len())?; let pub_ptr = if pub_buf.is_empty() {core::ptr::null()} else {pub_buf.as_ptr()}; let pub_size = crate::buffer_len_to_u32(pub_buf.len())?; let rc = unsafe { sys::wc_ecc_import_private_key_ex(priv_buf.as_ptr(), priv_size, pub_ptr, pub_size, &mut ecc.wc_ecc_key, curve_id) }; if rc != 0 { return Err(rc); } Ok(ecc) } /// Import raw ECC key from components in hexadecimal ASCII string format /// with curve name specified. /// /// # Parameters /// /// * `qx`: X component of public key as null terminated ASCII hex string. /// * `qy`: Y component of public key as null terminated ASCII hex string. /// * `d`: Private key as null terminated ASCII hex string. /// * `curve_name`: Null terminated ASCII string containing the curve name. /// * `heap`: Optional heap hint. /// * `dev_id` Optional device ID to use with crypto callbacks or async hardware. /// /// # Returns /// /// Returns either Ok(ECC) containing the ECC struct instance or Err(e) /// containing the wolfSSL library error code value. /// /// # Example /// /// ```rust /// #[cfg(ecc_import)] /// { /// use wolfssl_wolfcrypt::ecc::ECC; /// let qx = b"7a4e287890a1a47ad3457e52f2f76a83ce46cbc947616d0cbaa82323818a793d\0"; /// let qy = b"eec4084f5b29ebf29c44cce3b3059610922f8b30ea6e8811742ac7238fe87308\0"; /// let d = b"8c14b793cb19137e323a6d2e2a870bca2e7a493ec1153b3a95feb8a4873f8d08\0"; /// ECC::import_raw(qx, qy, d, b"SECP256R1\0", None, None).expect("Error with import_raw()"); /// } /// ``` #[cfg(ecc_import)] pub fn import_raw(qx: &[u8], qy: &[u8], d: &[u8], curve_name: &[u8], heap: Option<*mut core::ffi::c_void>, dev_id: Option) -> Result { let mut wc_ecc_key: MaybeUninit = MaybeUninit::uninit(); let heap = match heap { Some(heap) => heap, None => core::ptr::null_mut(), }; let dev_id = match dev_id { Some(dev_id) => dev_id, None => sys::INVALID_DEVID, }; let rc = unsafe { sys::wc_ecc_init_ex(wc_ecc_key.as_mut_ptr(), heap, dev_id) }; if rc != 0 { return Err(rc); } let wc_ecc_key = unsafe { wc_ecc_key.assume_init() }; let mut ecc = ECC { wc_ecc_key }; let qx_ptr = qx.as_ptr() as *const core::ffi::c_char; let qy_ptr = qy.as_ptr() as *const core::ffi::c_char; let d_ptr = d.as_ptr() as *const core::ffi::c_char; let curve_name_ptr = curve_name.as_ptr() as *const core::ffi::c_char; let rc = unsafe { sys::wc_ecc_import_raw(&mut ecc.wc_ecc_key, qx_ptr, qy_ptr, d_ptr, curve_name_ptr) }; if rc != 0 { return Err(rc); } Ok(ecc) } /// Import raw ECC key from components in hexadecimal ASCII string format /// with curve ID specified. /// /// # Parameters /// /// * `qx`: X component of public key as null terminated ASCII hex string. /// * `qy`: Y component of public key as null terminated ASCII hex string. /// * `d`: Private key as null terminated ASCII hex string. /// * `curve_id`: Curve ID, e.g. ECC::SECP256R1. /// * `heap`: Optional heap hint. /// * `dev_id` Optional device ID to use with crypto callbacks or async hardware. /// /// # Returns /// /// Returns either Ok(ECC) containing the ECC struct instance or Err(e) /// containing the wolfSSL library error code value. /// /// # Example /// /// ```rust /// #[cfg(ecc_import)] /// { /// use wolfssl_wolfcrypt::ecc::ECC; /// let qx = b"7a4e287890a1a47ad3457e52f2f76a83ce46cbc947616d0cbaa82323818a793d\0"; /// let qy = b"eec4084f5b29ebf29c44cce3b3059610922f8b30ea6e8811742ac7238fe87308\0"; /// let d = b"8c14b793cb19137e323a6d2e2a870bca2e7a493ec1153b3a95feb8a4873f8d08\0"; /// ECC::import_raw_ex(qx, qy, d, ECC::SECP256R1, None, None).expect("Error with import_raw_ex()"); /// } /// ``` #[cfg(ecc_import)] pub fn import_raw_ex(qx: &[u8], qy: &[u8], d: &[u8], curve_id: i32, heap: Option<*mut core::ffi::c_void>, dev_id: Option) -> Result { let mut wc_ecc_key: MaybeUninit = MaybeUninit::uninit(); let heap = match heap { Some(heap) => heap, None => core::ptr::null_mut(), }; let dev_id = match dev_id { Some(dev_id) => dev_id, None => sys::INVALID_DEVID, }; let rc = unsafe { sys::wc_ecc_init_ex(wc_ecc_key.as_mut_ptr(), heap, dev_id) }; if rc != 0 { return Err(rc); } let wc_ecc_key = unsafe { wc_ecc_key.assume_init() }; let mut ecc = ECC { wc_ecc_key }; let qx_ptr = qx.as_ptr() as *const core::ffi::c_char; let qy_ptr = qy.as_ptr() as *const core::ffi::c_char; let d_ptr = d.as_ptr() as *const core::ffi::c_char; let rc = unsafe { sys::wc_ecc_import_raw_ex(&mut ecc.wc_ecc_key, qx_ptr, qy_ptr, d_ptr, curve_id) }; if rc != 0 { return Err(rc); } Ok(ecc) } /// Import raw ECC key from components in binary unsigned integer format /// with curve ID specified. /// /// # Parameters /// /// * `qx`: X component of public key in binary unsigned integer format. /// * `qy`: Y component of public key in binary unsigned integer format. /// * `d`: Private key in binary unsigned integer format. /// * `curve_id`: Curve ID, e.g. ECC::SECP256R1. /// * `heap`: Optional heap hint. /// * `dev_id` Optional device ID to use with crypto callbacks or async hardware. /// /// # Returns /// /// Returns either Ok(ECC) containing the ECC struct instance or Err(e) /// containing the wolfSSL library error code value. /// /// # Example /// /// ```rust /// #[cfg(all(ecc_import, random))] /// { /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::ecc::ECC; /// let mut rng = RNG::new().expect("Failed to create RNG"); /// let curve_id = ECC::SECP256R1; /// let curve_size = ECC::get_curve_size_from_id(curve_id).expect("Error with get_curve_size_from_id()"); /// let mut ecc = ECC::generate_ex(curve_size, &mut rng, curve_id, None, None).expect("Error with generate()"); /// let mut qx = [0u8; 32]; /// let mut qx_len = 0u32; /// let mut qy = [0u8; 32]; /// let mut qy_len = 0u32; /// let mut d = [0u8; 32]; /// let mut d_len = 0u32; /// ecc.export_ex(&mut qx, &mut qx_len, &mut qy, &mut qy_len, &mut d, &mut d_len, false).expect("Error with export_ex()"); /// let mut ecc2 = ECC::import_unsigned(&qx, &qy, &d, curve_id, None, None).expect("Error with import_unsigned()"); /// } /// ``` #[cfg(ecc_import)] pub fn import_unsigned(qx: &[u8], qy: &[u8], d: &[u8], curve_id: i32, heap: Option<*mut core::ffi::c_void>, dev_id: Option) -> Result { let mut wc_ecc_key: MaybeUninit = MaybeUninit::uninit(); let heap = match heap { Some(heap) => heap, None => core::ptr::null_mut(), }; let dev_id = match dev_id { Some(dev_id) => dev_id, None => sys::INVALID_DEVID, }; let rc = unsafe { sys::wc_ecc_init_ex(wc_ecc_key.as_mut_ptr(), heap, dev_id) }; if rc != 0 { return Err(rc); } let wc_ecc_key = unsafe { wc_ecc_key.assume_init() }; let mut ecc = ECC { wc_ecc_key }; let rc = unsafe { sys::wc_ecc_import_unsigned(&mut ecc.wc_ecc_key, qx.as_ptr(), qy.as_ptr(), d.as_ptr(), curve_id) }; if rc != 0 { return Err(rc); } Ok(ecc) } /// Import a public ECC key from the given buffer containing the key stored /// in ANSI X9.63 format. This function handles both compressed and /// uncompressed keys, as long as compressed keys are enabled at compile /// time with the HAVE_COMP_KEY build option. /// /// # Parameters /// /// * `din`: Buffer containing the ECC key encoded in ANSI X9.63 format. /// * `heap`: Optional heap hint. /// * `dev_id` Optional device ID to use with crypto callbacks or async hardware. /// /// # Returns /// /// Returns either Ok(ECC) containing the ECC struct instance or Err(e) /// containing the wolfSSL library error code value. /// /// # Example /// /// ```rust /// #[cfg(all(ecc_import, random))] /// { /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::ecc::ECC; /// let mut rng = RNG::new().expect("Failed to create RNG"); /// let mut ecc = ECC::generate(32, &mut rng, None, None).expect("Error with generate()"); /// let mut x963 = [0u8; 128]; /// let x963_size = ecc.export_x963(&mut x963).expect("Error with export_x963()"); /// let x963 = &x963[0..x963_size]; /// let _ecc2 = ECC::import_x963(x963, None, None).expect("Error with import_x963()"); /// } /// ``` #[cfg(ecc_import)] pub fn import_x963(din: &[u8], heap: Option<*mut core::ffi::c_void>, dev_id: Option) -> Result { let din_size = crate::buffer_len_to_u32(din.len())?; let mut wc_ecc_key: MaybeUninit = MaybeUninit::uninit(); let heap = match heap { Some(heap) => heap, None => core::ptr::null_mut(), }; let dev_id = match dev_id { Some(dev_id) => dev_id, None => sys::INVALID_DEVID, }; let rc = unsafe { sys::wc_ecc_init_ex(wc_ecc_key.as_mut_ptr(), heap, dev_id) }; if rc != 0 { return Err(rc); } let wc_ecc_key = unsafe { wc_ecc_key.assume_init() }; let mut ecc = ECC { wc_ecc_key }; let rc = unsafe { sys::wc_ecc_import_x963(din.as_ptr(), din_size, &mut ecc.wc_ecc_key) }; if rc != 0 { return Err(rc); } Ok(ecc) } /// Import a public ECC key from the given buffer containing the key stored /// in ANSI X9.63 format. This function handles both compressed and /// uncompressed keys, as long as compressed keys are enabled at compile /// time with the HAVE_COMP_KEY build option. /// /// This function allows specifying the ECC curve ID to use. /// /// # Parameters /// /// * `din`: Buffer containing the ECC key encoded in ANSI X9.63 format. /// * `curve_id`: Curve ID, e.g. ECC::SECP256R1. /// * `heap`: Optional heap hint. /// * `dev_id` Optional device ID to use with crypto callbacks or async hardware. /// /// # Returns /// /// Returns either Ok(ECC) containing the ECC struct instance or Err(e) /// containing the wolfSSL library error code value. /// /// # Example /// /// ```rust /// #[cfg(all(ecc_import, random))] /// { /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::ecc::ECC; /// let mut rng = RNG::new().expect("Failed to create RNG"); /// let curve_id = ECC::SECP256R1; /// let curve_size = ECC::get_curve_size_from_id(curve_id).expect("Error with get_curve_size_from_id()"); /// let mut ecc = ECC::generate_ex(curve_size, &mut rng, curve_id, None, None).expect("Error with generate_ex()"); /// let mut x963 = [0u8; 128]; /// let x963_size = ecc.export_x963(&mut x963).expect("Error with export_x963()"); /// let x963 = &x963[0..x963_size]; /// let _ecc2 = ECC::import_x963_ex(x963, curve_id, None, None).expect("Error with import_x963_ex()"); /// } /// ``` #[cfg(ecc_import)] pub fn import_x963_ex(din: &[u8], curve_id: i32, heap: Option<*mut core::ffi::c_void>, dev_id: Option) -> Result { let din_size = crate::buffer_len_to_u32(din.len())?; let mut wc_ecc_key: MaybeUninit = MaybeUninit::uninit(); let heap = match heap { Some(heap) => heap, None => core::ptr::null_mut(), }; let dev_id = match dev_id { Some(dev_id) => dev_id, None => sys::INVALID_DEVID, }; let rc = unsafe { sys::wc_ecc_init_ex(wc_ecc_key.as_mut_ptr(), heap, dev_id) }; if rc != 0 { return Err(rc); } let wc_ecc_key = unsafe { wc_ecc_key.assume_init() }; let mut ecc = ECC { wc_ecc_key }; let rc = unsafe { sys::wc_ecc_import_x963_ex(din.as_ptr(), din_size, &mut ecc.wc_ecc_key, curve_id) }; if rc != 0 { return Err(rc); } Ok(ecc) } /// Convert the R and S portions (as hexadecimal ASCII strings) of an ECC /// signature into a DER-encoded ECDSA signature. /// /// # Parameters /// /// * `r`: R component of ECC signature as a null-terminated hexadecimal /// ASCII string. /// * `s`: S component of ECC signature as a null-terminated hexadecimal /// ASCII string. /// * `dout`: Buffer in which to store the output ECDSA signature. /// /// # Returns /// /// Returns either Ok(size) containing the number of bytes written to /// `dout` or Err(e) containing the wolfSSL library error code value. /// /// # Example /// /// ```rust /// # extern crate std; /// #[cfg(random)] /// { /// use std::fs; /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::ecc::ECC; /// fn bytes_to_asciiz_hex_string(bytes: &[u8]) -> String { /// let mut hex_string = String::with_capacity(bytes.len() * 2 + 1); /// for byte in bytes { /// hex_string.push_str(&format!("{:02X}", byte)); /// } /// hex_string.push('\0'); /// hex_string /// } /// let mut rng = RNG::new().expect("Failed to create RNG"); /// let key_path = "../../../certs/ecc-client-key.der"; /// let der: Vec = fs::read(key_path).expect("Error reading key file"); /// let mut ecc = ECC::import_der(&der, None, None).expect("Error with import_der()"); /// let hash = [0x42u8; 32]; /// let mut signature = [0u8; 128]; /// let signature_length = ecc.sign_hash(&hash, &mut signature, &mut rng).expect("Error with sign_hash()"); /// let signature = &mut signature[0..signature_length]; /// let mut r = [0u8; 32]; /// let mut r_size = 0u32; /// let mut s = [0u8; 32]; /// let mut s_size = 0u32; /// ECC::sig_to_rs(signature, &mut r, &mut r_size, &mut s, &mut s_size).expect("Error with sig_to_rs()"); /// let r = &r[0..r_size as usize]; /// let s = &s[0..s_size as usize]; /// let r_hex_string = bytes_to_asciiz_hex_string(r); /// let s_hex_string = bytes_to_asciiz_hex_string(s); /// let mut sig_out = [0u8; 128]; /// let sig_out_size = ECC::rs_hex_to_sig(&r_hex_string[0..r_hex_string.len()].as_bytes(), &s_hex_string[0..s_hex_string.len()].as_bytes(), &mut sig_out).expect("Error with rs_hex_to_sig()"); /// assert_eq!(*signature, *&sig_out[0..sig_out_size]); /// } /// ``` pub fn rs_hex_to_sig(r: &[u8], s: &[u8], dout: &mut [u8]) -> Result { if r.is_empty() || s.is_empty() || r[r.len() - 1] != 0 || s[s.len() - 1] != 0 { return Err(sys::wolfCrypt_ErrorCodes_BAD_FUNC_ARG); } let mut dout_size = crate::buffer_len_to_u32(dout.len())?; let r_ptr = r.as_ptr() as *const core::ffi::c_char; let s_ptr = s.as_ptr() as *const core::ffi::c_char; let rc = unsafe { sys::wc_ecc_rs_to_sig(r_ptr, s_ptr, dout.as_mut_ptr(), &mut dout_size) }; if rc != 0 { return Err(rc); } Ok(dout_size as usize) } /// Convert the R and S portions (as binary unsigned integers) of an ECC /// signature into a DER-encoded ECDSA signature. /// /// # Parameters /// /// * `r`: R component of ECC signature as a binary unsigned integer. /// * `s`: S component of ECC signature as a binary unsigned integer. /// * `dout`: Buffer in which to store the output ECDSA signature. /// /// # Returns /// /// Returns either Ok(size) containing the number of bytes written to /// `dout` or Err(e) containing the wolfSSL library error code value. /// /// # Example /// /// ```rust /// # extern crate std; /// #[cfg(random)] /// { /// use std::fs; /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::ecc::ECC; /// let mut rng = RNG::new().expect("Failed to create RNG"); /// let key_path = "../../../certs/ecc-client-key.der"; /// let der: Vec = fs::read(key_path).expect("Error reading key file"); /// let mut ecc = ECC::import_der(&der, None, None).expect("Error with import_der()"); /// let hash = [0x42u8; 32]; /// let mut signature = [0u8; 128]; /// let signature_length = ecc.sign_hash(&hash, &mut signature, &mut rng).expect("Error with sign_hash()"); /// let signature = &mut signature[0..signature_length]; /// let mut r = [0u8; 32]; /// let mut r_size = 0u32; /// let mut s = [0u8; 32]; /// let mut s_size = 0u32; /// ECC::sig_to_rs(signature, &mut r, &mut r_size, &mut s, &mut s_size).expect("Error with sig_to_rs()"); /// let r = &r[0..r_size as usize]; /// let s = &s[0..s_size as usize]; /// let mut sig_out = [0u8; 128]; /// let sig_out_size = ECC::rs_bin_to_sig(r, s, &mut sig_out).expect("Error with rs_bin_to_sig()"); /// assert_eq!(*signature, *&sig_out[0..sig_out_size]); /// } /// ``` pub fn rs_bin_to_sig(r: &[u8], s: &[u8], dout: &mut [u8]) -> Result { let r_size = crate::buffer_len_to_u32(r.len())?; let s_size = crate::buffer_len_to_u32(s.len())?; let mut dout_size = crate::buffer_len_to_u32(dout.len())?; let rc = unsafe { sys::wc_ecc_rs_raw_to_sig(r.as_ptr(), r_size, s.as_ptr(), s_size, dout.as_mut_ptr(), &mut dout_size) }; if rc != 0 { return Err(rc); } Ok(dout_size as usize) } /// Convert ECDSA signature to R and S components. /// /// # Parameters /// /// * `sig`: ECDSA signature. /// * `r`: Output buffer for R component. /// * `r_size`: Number of bytes written to `r` buffer. /// * `s`: Output buffer for S component. /// * `s_size`: Number of bytes written to `s` buffer. /// /// # Example /// /// ```rust /// # extern crate std; /// #[cfg(random)] /// { /// use std::fs; /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::ecc::ECC; /// let mut rng = RNG::new().expect("Failed to create RNG"); /// let key_path = "../../../certs/ecc-client-key.der"; /// let der: Vec = fs::read(key_path).expect("Error reading key file"); /// let mut ecc = ECC::import_der(&der, None, None).expect("Error with import_der()"); /// let hash = [0x42u8; 32]; /// let mut signature = [0u8; 128]; /// let signature_length = ecc.sign_hash(&hash, &mut signature, &mut rng).expect("Error with sign_hash()"); /// let signature = &mut signature[0..signature_length]; /// let mut r = [0u8; 32]; /// let mut r_size = 0u32; /// let mut s = [0u8; 32]; /// let mut s_size = 0u32; /// ECC::sig_to_rs(signature, &mut r, &mut r_size, &mut s, &mut s_size).expect("Error with sig_to_rs()"); /// let r = &r[0..r_size as usize]; /// let s = &s[0..s_size as usize]; /// let mut sig_out = [0u8; 128]; /// let sig_out_size = ECC::rs_bin_to_sig(r, s, &mut sig_out).expect("Error with rs_bin_to_sig()"); /// assert_eq!(*signature, *&sig_out[0..sig_out_size]); /// } /// ``` pub fn sig_to_rs(sig: &[u8], r: &mut [u8], r_size: &mut u32, s: &mut [u8], s_size: &mut u32) -> Result<(), i32> { let sig_len = crate::buffer_len_to_u32(sig.len())?; *r_size = crate::buffer_len_to_u32(r.len())?; *s_size = crate::buffer_len_to_u32(s.len())?; let rc = unsafe { sys::wc_ecc_sig_to_rs(sig.as_ptr(), sig_len, r.as_mut_ptr(), r_size, s.as_mut_ptr(), s_size) }; if rc != 0 { return Err(rc); } Ok(()) } /// Perform basic sanity checks on the ECC key. /// /// # Returns /// /// Returns either Ok(ECC) containing the ECC struct instance or Err(e) /// containing the wolfSSL library error code value. /// /// # Example /// /// ```rust /// # extern crate std; /// #[cfg(random)] /// { /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::ecc::ECC; /// let mut rng = RNG::new().expect("Failed to create RNG"); /// let mut ecc = ECC::generate(32, &mut rng, None, None).expect("Error with generate()"); /// ecc.check().expect("Error with check()"); /// } /// ``` pub fn check(&mut self) -> Result<(), i32> { let rc = unsafe { sys::wc_ecc_check_key(&mut self.wc_ecc_key) }; if rc != 0 { return Err(rc); } Ok(()) } /// Export ECC key components in binary unsigned integer format. /// /// # Parameters /// /// * `qx`: Buffer in which to store public X component. /// * `qx_len`: Output parameter storing number of bytes written to `qx`. /// * `qy`: Buffer in which to store public Y component. /// * `qy_len`: Output parameter storing number of bytes written to `qy`. /// * `d`: Buffer in which to store private component. /// * `d_len`: Output parameter storing number of bytes written to `d`. /// /// # Returns /// /// Returns either Ok(()) or Err(e) containing the wolfSSL library error /// code value. /// /// # Example /// /// ```rust /// #[cfg(all(ecc_import, random))] /// { /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::ecc::ECC; /// let mut rng = RNG::new().expect("Failed to create RNG"); /// let mut ecc = ECC::generate(32, &mut rng, None, None).expect("Error with generate()"); /// let mut qx = [0u8; 32]; /// let mut qx_len = 0u32; /// let mut qy = [0u8; 32]; /// let mut qy_len = 0u32; /// let mut d = [0u8; 32]; /// let mut d_len = 0u32; /// ecc.export(&mut qx, &mut qx_len, &mut qy, &mut qy_len, &mut d, &mut d_len).expect("Error with export()"); /// } /// ``` #[cfg(ecc_import)] pub fn export(&mut self, qx: &mut [u8], qx_len: &mut u32, qy: &mut [u8], qy_len: &mut u32, d: &mut [u8], d_len: &mut u32) -> Result<(), i32> { *qx_len = crate::buffer_len_to_u32(qx.len())?; *qy_len = crate::buffer_len_to_u32(qy.len())?; *d_len = crate::buffer_len_to_u32(d.len())?; let rc = unsafe { sys::wc_ecc_export_private_raw(&mut self.wc_ecc_key, qx.as_mut_ptr(), qx_len, qy.as_mut_ptr(), qy_len, d.as_mut_ptr(), d_len) }; if rc != 0 { return Err(rc); } Ok(()) } /// Export ECC key components as either ASCII hexadecimal strings or /// in binary unsigned integer format. /// /// # Parameters /// /// * `qx`: Buffer in which to store public X component. /// * `qx_len`: Output parameter storing number of bytes written to `qx`. /// * `qy`: Buffer in which to store public Y component. /// * `qy_len`: Output parameter storing number of bytes written to `qy`. /// * `d`: Buffer in which to store private component. /// * `d_len`: Output parameter storing number of bytes written to `d`. /// * `hex`: true to output in ASCII hexadecimal string, false to output /// as binary data. /// /// # Returns /// /// Returns either Ok(()) or Err(e) containing the wolfSSL library error /// code value. /// /// # Example /// /// ```rust /// #[cfg(all(ecc_import, random))] /// { /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::ecc::ECC; /// let mut rng = RNG::new().expect("Failed to create RNG"); /// let mut ecc = ECC::generate(32, &mut rng, None, None).expect("Error with generate()"); /// let mut qx = [0u8; 32]; /// let mut qx_len = 0u32; /// let mut qy = [0u8; 32]; /// let mut qy_len = 0u32; /// let mut d = [0u8; 32]; /// let mut d_len = 0u32; /// ecc.export_ex(&mut qx, &mut qx_len, &mut qy, &mut qy_len, &mut d, &mut d_len, false).expect("Error with export_ex()"); /// } /// ``` #[cfg(ecc_import)] #[allow(clippy::too_many_arguments)] pub fn export_ex(&mut self, qx: &mut [u8], qx_len: &mut u32, qy: &mut [u8], qy_len: &mut u32, d: &mut [u8], d_len: &mut u32, hex: bool) -> Result<(), i32> { *qx_len = crate::buffer_len_to_u32(qx.len())?; *qy_len = crate::buffer_len_to_u32(qy.len())?; *d_len = crate::buffer_len_to_u32(d.len())?; let enc_type = if hex { sys::WC_TYPE_HEX_STR as i32 } else { sys::WC_TYPE_UNSIGNED_BIN as i32 }; let rc = unsafe { sys::wc_ecc_export_ex(&mut self.wc_ecc_key, qx.as_mut_ptr(), qx_len, qy.as_mut_ptr(), qy_len, d.as_mut_ptr(), d_len, enc_type) }; if rc != 0 { return Err(rc); } Ok(()) } /// Export private component from ECC key in binary unsigned integer form. /// /// # Parameters /// /// * `d`: Buffer in which to store private component. /// /// # Returns /// /// Returns either Ok(size) containing the number of bytes written to `d` /// or Err(e) containing the wolfSSL library error code value. /// /// # Example /// /// ```rust /// #[cfg(all(ecc_export, random))] /// { /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::ecc::ECC; /// let mut rng = RNG::new().expect("Failed to create RNG"); /// let mut ecc = ECC::generate(32, &mut rng, None, None).expect("Error with generate()"); /// let mut d = [0u8; 32]; /// let d_size = ecc.export_private(&mut d).expect("Error with export_private()"); /// assert_eq!(d_size, 32); /// } /// ``` #[cfg(ecc_export)] pub fn export_private(&mut self, d: &mut [u8]) -> Result { let mut d_size = crate::buffer_len_to_u32(d.len())?; let rc = unsafe { sys::wc_ecc_export_private_only(&mut self.wc_ecc_key, d.as_mut_ptr(), &mut d_size) }; if rc != 0 { return Err(rc); } Ok(d_size as usize) } /// Export public ECC key components in binary unsigned integer format. /// /// # Parameters /// /// * `qx`: Buffer in which to store public X component. /// * `qx_len`: Output parameter storing number of bytes written to `qx`. /// * `qy`: Buffer in which to store public Y component. /// * `qy_len`: Output parameter storing number of bytes written to `qy`. /// /// # Returns /// /// Returns either Ok(()) or Err(e) containing the wolfSSL library error /// code value. /// /// # Example /// /// ```rust /// #[cfg(all(ecc_export, random))] /// { /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::ecc::ECC; /// let mut rng = RNG::new().expect("Failed to create RNG"); /// let mut ecc = ECC::generate(32, &mut rng, None, None).expect("Error with generate()"); /// let mut qx = [0u8; 32]; /// let mut qx_len = 0u32; /// let mut qy = [0u8; 32]; /// let mut qy_len = 0u32; /// ecc.export_public(&mut qx, &mut qx_len, &mut qy, &mut qy_len).expect("Error with export_public()"); /// } /// ``` #[cfg(ecc_export)] pub fn export_public(&mut self, qx: &mut [u8], qx_len: &mut u32, qy: &mut [u8], qy_len: &mut u32) -> Result<(), i32> { *qx_len = crate::buffer_len_to_u32(qx.len())?; *qy_len = crate::buffer_len_to_u32(qy.len())?; let rc = unsafe { sys::wc_ecc_export_public_raw(&mut self.wc_ecc_key, qx.as_mut_ptr(), qx_len, qy.as_mut_ptr(), qy_len) }; if rc != 0 { return Err(rc); } Ok(()) } /// Export public key in ANSI X9.63 format. /// /// # Parameters /// /// * `dout`: Buffer to contain the output. /// /// # Returns /// /// Returns either Ok(size) containing the number of bytes written to /// `dout` or Err(e) containing the wolfSSL library error code value. /// /// # Example /// /// ```rust /// #[cfg(all(ecc_export, random))] /// { /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::ecc::ECC; /// let mut rng = RNG::new().expect("Failed to create RNG"); /// let mut ecc = ECC::generate(32, &mut rng, None, None).expect("Error with generate()"); /// let mut x963 = [0u8; 128]; /// let _x963_size = ecc.export_x963(&mut x963).expect("Error with export_x963()"); /// } /// ``` #[cfg(ecc_export)] pub fn export_x963(&mut self, dout: &mut [u8]) -> Result { let mut out_len = crate::buffer_len_to_u32(dout.len())?; let rc = unsafe { sys::wc_ecc_export_x963(&mut self.wc_ecc_key, dout.as_mut_ptr(), &mut out_len) }; if rc != 0 { return Err(rc); } Ok(out_len as usize) } /// Export public key in ANSI X9.63 compressed format. /// /// # Parameters /// /// * `dout`: Buffer to contain the output. /// /// # Returns /// /// Returns either Ok(size) containing the number of bytes written to /// `dout` or Err(e) containing the wolfSSL library error code value. /// /// # Example /// /// ```rust /// #[cfg(all(ecc_export, ecc_comp_key, random))] /// { /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::ecc::ECC; /// let mut rng = RNG::new().expect("Failed to create RNG"); /// let mut ecc = ECC::generate(32, &mut rng, None, None).expect("Error with generate()"); /// let mut x963 = [0u8; 128]; /// let _x963_size = ecc.export_x963_compressed(&mut x963).expect("Error with export_x963_compressed()"); /// } /// ``` #[cfg(all(ecc_export, ecc_comp_key))] pub fn export_x963_compressed(&mut self, dout: &mut [u8]) -> Result { let mut out_len = crate::buffer_len_to_u32(dout.len())?; let rc = unsafe { sys::wc_ecc_export_x963_ex(&mut self.wc_ecc_key, dout.as_mut_ptr(), &mut out_len, 1) }; if rc != 0 { return Err(rc); } Ok(out_len as usize) } /// Compute the public component from this key private component. /// /// # Parameters /// /// * `rng`: RNG struct used to blind the private key value used in the /// computation. /// /// # Returns /// /// Returns either Ok(()) or Err(e) containing the wolfSSL library error /// code value. /// /// # Example /// /// ```rust /// # extern crate std; /// #[cfg(random)] /// { /// use std::fs; /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::ecc::ECC; /// let mut rng = RNG::new().expect("Failed to create RNG"); /// let key_path = "../../../certs/ecc-client-key.der"; /// let der: Vec = fs::read(key_path).expect("Error reading key file"); /// let mut ecc = ECC::import_der(&der, None, None).expect("Error with import_der()"); /// ecc.make_pub(Some(&mut rng)).expect("Error with make_pub()"); /// } /// ``` #[cfg(random)] pub fn make_pub(&mut self, rng: Option<&mut RNG>) -> Result<(), i32> { let rng_ptr = match rng { Some(rng) => &mut rng.wc_rng, None => core::ptr::null_mut(), }; let rc = unsafe { sys::wc_ecc_make_pub_ex(&mut self.wc_ecc_key, core::ptr::null_mut(), rng_ptr) }; if rc != 0 { return Err(rc); } Ok(()) } /// Compute the public component from this key private component. /// /// # Parameters /// /// * `rng`: RNG struct used to blind the private key value used in the /// computation. /// * `heap`: Optional heap hint. /// /// # Returns /// /// Returns either Ok(ECCPoint) containing the public component ECCPoint /// or Err(e) containing the wolfSSL library error code value. /// /// # Example /// /// ```rust /// # extern crate std; /// #[cfg(random)] /// { /// use std::fs; /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::ecc::ECC; /// let mut rng = RNG::new().expect("Failed to create RNG"); /// let key_path = "../../../certs/ecc-client-key.der"; /// let der: Vec = fs::read(key_path).expect("Error reading key file"); /// let mut ecc = ECC::import_der(&der, None, None).expect("Error with import_der()"); /// ecc.make_pub_to_point(Some(&mut rng), None).expect("Error with make_pub_to_point()"); /// } /// ``` #[cfg(random)] pub fn make_pub_to_point(&mut self, rng: Option<&mut RNG>, heap: Option<*mut core::ffi::c_void>) -> Result { let rng_ptr = match rng { Some(rng) => &mut rng.wc_rng, None => core::ptr::null_mut(), }; let heap = match heap { Some(heap) => heap, None => core::ptr::null_mut(), }; let wc_ecc_point = unsafe { sys::wc_ecc_new_point_h(heap) }; if wc_ecc_point.is_null() { return Err(sys::wolfCrypt_ErrorCodes_MEMORY_E); } let ecc_point = ECCPoint { wc_ecc_point, heap }; let rc = unsafe { sys::wc_ecc_make_pub_ex(&mut self.wc_ecc_key, wc_ecc_point, rng_ptr) }; if rc != 0 { return Err(rc); } Ok(ecc_point) } /// Associates a `RNG` instance with this `ECC` instance. /// /// This is necessary when wolfSSL is built with the `ECC_TIMING_RESISTANT` /// build option enabled. /// /// # Parameters /// /// * `rng`: The `RNG` struct instance to associate with this `ECC` /// 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. /// /// # Example /// /// ```rust /// # extern crate std; /// #[cfg(random)] /// { /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::ecc::ECC; /// let mut rng = RNG::new().expect("Failed to create RNG"); /// let mut ecc = ECC::generate(32, &mut rng, None, None).expect("Error with generate()"); /// ecc.set_rng(&mut rng).expect("Error with set_rng()"); /// } /// ``` #[cfg(random)] pub fn set_rng(&mut self, rng: &mut RNG) -> Result<(), i32> { let rc = unsafe { sys::wc_ecc_set_rng(&mut self.wc_ecc_key, &mut rng.wc_rng) }; if rc != 0 { return Err(rc); } Ok(()) } /// Compute the ECDH shared secret using this key's private component /// and the peer public key. /// /// # Parameters /// /// * `peer`: `ECC` public key. /// * `dout`: Buffer in which to store the computed secret value. /// /// # Returns /// /// Returns either Ok(size) containing the number of bytes written to /// `dout` or Err(e) containing the wolfSSL library error code value. /// /// # Example /// /// ```rust /// #[cfg(all(ecc_dh, random))] /// { /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::ecc::ECC; /// let mut rng = RNG::new().expect("Failed to create RNG"); /// let mut ecc0 = ECC::generate(32, &mut rng, None, None).expect("Error with generate()"); /// let mut ecc1 = ECC::generate(32, &mut rng, None, None).expect("Error with generate()"); /// let mut ss0 = [0u8; 128]; /// let mut ss1 = [0u8; 128]; /// ecc0.set_rng(&mut rng).expect("Error with set_rng()"); /// ecc1.set_rng(&mut rng).expect("Error with set_rng()"); /// let ss0_size = ecc0.shared_secret(&mut ecc1, &mut ss0).expect("Error with shared_secret()"); /// let ss1_size = ecc1.shared_secret(&mut ecc0, &mut ss1).expect("Error with shared_secret()"); /// assert_eq!(ss0_size, ss1_size); /// let ss0 = &ss0[0..ss0_size]; /// let ss1 = &ss1[0..ss1_size]; /// assert_eq!(*ss0, *ss1); /// } /// ``` #[cfg(ecc_dh)] pub fn shared_secret(&mut self, peer_key: &mut ECC, dout: &mut [u8]) -> Result { let mut out_len = crate::buffer_len_to_u32(dout.len())?; let rc = unsafe { sys::wc_ecc_shared_secret(&mut self.wc_ecc_key, &mut peer_key.wc_ecc_key, dout.as_mut_ptr(), &mut out_len) }; if rc != 0 { return Err(rc); } Ok(out_len as usize) } /// Compute the ECDH shared secret using this key's private component /// and the peer public point. /// /// # Parameters /// /// * `peer`: `ECCPoint` struct holding the public components of the peer /// ECC key. /// * `dout`: Buffer in which to store the computed secret value. /// /// # Returns /// /// Returns either Ok(size) containing the number of bytes written to /// `dout` or Err(e) containing the wolfSSL library error code value. /// /// # Example /// /// ```rust /// #[cfg(all(ecc_dh, random))] /// { /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::ecc::ECC; /// let mut rng = RNG::new().expect("Failed to create RNG"); /// let mut ecc0 = ECC::generate(32, &mut rng, None, None).expect("Error with generate()"); /// let mut ecc1 = ECC::generate(32, &mut rng, None, None).expect("Error with generate()"); /// let ecc1_point = ecc1.make_pub_to_point(None, None).expect("Error with make_pub_to_point()"); /// let mut ss0 = [0u8; 128]; /// let mut ss1 = [0u8; 128]; /// ecc0.set_rng(&mut rng).expect("Error with set_rng()"); /// ecc1.set_rng(&mut rng).expect("Error with set_rng()"); /// let ss0_size = ecc0.shared_secret_ex(&ecc1_point, &mut ss0).expect("Error with shared_secret_ex()"); /// let ss1_size = ecc1.shared_secret(&mut ecc0, &mut ss1).expect("Error with shared_secret()"); /// assert_eq!(ss0_size, ss1_size); /// let ss0 = &ss0[0..ss0_size]; /// let ss1 = &ss1[0..ss1_size]; /// assert_eq!(*ss0, *ss1); /// } /// ``` #[cfg(ecc_dh)] pub fn shared_secret_ex(&mut self, peer: &ECCPoint, dout: &mut [u8]) -> Result { let mut out_len = crate::buffer_len_to_u32(dout.len())?; let rc = unsafe { sys::wc_ecc_shared_secret_ex(&mut self.wc_ecc_key, peer.wc_ecc_point, dout.as_mut_ptr(), &mut out_len) }; if rc != 0 { return Err(rc); } Ok(out_len as usize) } /// Sign a message digest using the ECC key. /// /// # Parameters /// /// * `din`: Message digest to sign. /// * `dout`: Buffer in which to store the signature. /// * `rng`: RNG struct to use for random number generation during signing. /// /// # Returns /// /// Returns either Ok(size) containing the number of bytes written to /// `dout` or Err(e) containing the wolfSSL library error code value. /// /// # Example /// /// ```rust /// #[cfg(all(ecc_sign, random))] /// { /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::ecc::ECC; /// let mut rng = RNG::new().expect("Failed to create RNG"); /// let mut ecc = ECC::generate(32, &mut rng, None, None).expect("Error with generate()"); /// let hash = [0x42u8; 32]; /// let mut signature = [0u8; 128]; /// let signature_length = ecc.sign_hash(&hash, &mut signature, &mut rng).expect("Error with sign_hash()"); /// let signature = &mut signature[0..signature_length]; /// let valid = ecc.verify_hash(&signature, &hash).expect("Error with verify_hash()"); /// assert_eq!(valid, true); /// } /// ``` #[cfg(all(ecc_sign, random))] pub fn sign_hash(&mut self, din: &[u8], dout: &mut [u8], rng: &mut RNG) -> Result { let din_size = crate::buffer_len_to_u32(din.len())?; let mut dout_size = crate::buffer_len_to_u32(dout.len())?; let rc = unsafe { sys::wc_ecc_sign_hash(din.as_ptr(), din_size, dout.as_mut_ptr(), &mut dout_size, &mut rng.wc_rng, &mut self.wc_ecc_key) }; if rc != 0 { return Err(rc); } Ok(dout_size as usize) } /// Verify the ECC signature of a hash. /// /// # Parameters /// /// * `sig`: ECC signature. /// * `hash`: Message digest. /// /// # Returns /// /// Returns either Ok(valid) containing a flag for whether the signature is /// valid or Err(e) containing the wolfSSL library error code value. /// /// # Example /// /// ```rust /// #[cfg(all(ecc_verify, random))] /// { /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::ecc::ECC; /// let mut rng = RNG::new().expect("Failed to create RNG"); /// let mut ecc = ECC::generate(32, &mut rng, None, None).expect("Error with generate()"); /// let hash = [0x42u8; 32]; /// let mut signature = [0u8; 128]; /// let signature_length = ecc.sign_hash(&hash, &mut signature, &mut rng).expect("Error with sign_hash()"); /// let signature = &mut signature[0..signature_length]; /// let valid = ecc.verify_hash(&signature, &hash).expect("Error with verify_hash()"); /// assert_eq!(valid, true); /// } /// ``` #[cfg(ecc_verify)] pub fn verify_hash(&mut self, sig: &[u8], hash: &[u8]) -> Result { let mut res: i32 = 0; let sig_len = crate::buffer_len_to_u32(sig.len())?; let hash_len = crate::buffer_len_to_u32(hash.len())?; let rc = unsafe { sys::wc_ecc_verify_hash(sig.as_ptr(), sig_len, hash.as_ptr(), hash_len, &mut res, &mut self.wc_ecc_key) }; if rc != 0 { return Err(rc); } Ok(res == 1) } } impl ECC { fn zeroize(&mut self) { unsafe { crate::zeroize_raw(&mut self.wc_ecc_key); } } } impl Drop for ECC { /// Safely free the underlying wolfSSL ECC context. /// /// This calls the `wc_ecc_key_free()` wolfssl library function. /// /// The Rust Drop trait guarantees that this method is called when the ECC /// struct goes out of scope, automatically cleaning up resources and /// preventing memory leaks. fn drop(&mut self) { unsafe { sys::wc_ecc_free(&mut self.wc_ecc_key); } self.zeroize(); } }