Files
wolfssl/wrapper/rust/wolfssl-wolfcrypt/src/ed25519.rs
T
Josh Holtrop 54cb1d8d38 Rust wrapper: ensure memory safety for C RNG struct
- store pointer to WC_RNG instead of full struct
- enforce RNG is not dropped before consumer structs

The C library stores a pointer via the set_rng() methods on a few
structs (e.g. RSA). This change holds a reference (or instance) of RNG
within the consumer structs to ensure it is kept alive if set_rng (or
now set_shared_rng) is used.
2026-05-18 12:27:44 -07:00

1566 lines
56 KiB
Rust

/*
* 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 EdDSA Curve
25519 (Ed25519) functionality.
*/
#![cfg(ed25519)]
use crate::sys;
use crate::random::RNG;
use core::mem::MaybeUninit;
/// The `Ed25519` struct manages the lifecycle of a wolfSSL `ed25519_key`
/// object.
///
/// It ensures proper initialization and deallocation.
///
/// An instance can be created with `generate()` or `new()`.
pub struct Ed25519 {
ws_key: sys::ed25519_key,
}
impl Ed25519 {
/** Size of private key only. */
pub const KEY_SIZE: usize = sys::ED25519_KEY_SIZE as usize;
/** Size of signature. */
pub const SIG_SIZE: usize = sys::ED25519_SIG_SIZE as usize;
/** Compressed public key size. */
pub const PUB_KEY_SIZE: usize = sys::ED25519_PUB_KEY_SIZE as usize;
/** Size of both private and public key. */
pub const PRV_KEY_SIZE: usize = sys::ED25519_PRV_KEY_SIZE as usize;
pub const ED25519: u8 = sys::Ed25519 as u8;
pub const ED25519CTX: u8 = sys::Ed25519ctx as u8;
pub const ED25519PH: u8 = sys::Ed25519ph as u8;
/// Generate a new Ed25519 key.
///
/// # Parameters
///
/// * `rng`: `RNG` instance to use for random number generation.
///
/// # Returns
///
/// Returns either Ok(ed25519) containing the Ed25519 struct instance or
/// Err(e) containing the wolfSSL library error code value.
///
/// # Example
///
/// ```rust
/// use wolfssl_wolfcrypt::random::RNG;
/// use wolfssl_wolfcrypt::ed25519::Ed25519;
/// let mut rng = RNG::new().expect("Error creating RNG");
/// let ed = Ed25519::generate(&mut rng).expect("Error with generate()");
/// ```
pub fn generate(rng: &RNG) -> Result<Self, i32> {
Self::generate_ex(rng, None, None)
}
/// Generate a new Ed25519 key with optional heap and device ID.
///
/// # Parameters
///
/// * `rng`: `RNG` instance to use for random number generation.
/// * `heap`: Optional heap hint.
/// * `dev_id` Optional device ID to use with crypto callbacks or async hardware.
///
/// # Returns
///
/// Returns either Ok(ed25519) containing the Ed25519 struct instance or
/// Err(e) containing the wolfSSL library error code value.
///
/// # Example
///
/// ```rust
/// use wolfssl_wolfcrypt::random::RNG;
/// use wolfssl_wolfcrypt::ed25519::Ed25519;
/// let mut rng = RNG::new().expect("Error creating RNG");
/// let ed = Ed25519::generate_ex(&mut rng, None, None).expect("Error with generate_ex()");
/// ```
pub fn generate_ex(rng: &RNG, heap: Option<*mut core::ffi::c_void>, dev_id: Option<i32>) -> Result<Self, i32> {
let mut ws_key: MaybeUninit<sys::ed25519_key> = 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_ed25519_init_ex(ws_key.as_mut_ptr(), heap, dev_id) };
if rc != 0 {
return Err(rc);
}
let ws_key = unsafe { ws_key.assume_init() };
let mut ed25519 = Ed25519 { ws_key };
let rc = unsafe {
sys::wc_ed25519_make_key(rng.wc_rng,
sys::ED25519_KEY_SIZE as i32, &mut ed25519.ws_key)
};
if rc != 0 {
return Err(rc);
}
Ok(ed25519)
}
/// Create and initialize a new Ed25519 instance.
///
/// A key will not be present but can be imported with one of the import
/// functions.
///
/// # Returns
///
/// Returns either Ok(ed25519) containing the Ed25519 struct instance or
/// Err(e) containing the wolfSSL library error code value.
///
/// # Example
///
/// ```rust
/// use wolfssl_wolfcrypt::ed25519::Ed25519;
/// let ed = Ed25519::new().expect("Error with new()");
/// ```
pub fn new() -> Result<Self, i32> {
Self::new_ex(None, None)
}
/// Create and initialize a new Ed25519 instance with optional heap and
/// device ID.
///
/// A key will not be present but can be imported with one of the import
/// functions.
///
/// # Parameters
///
/// * `heap`: Optional heap hint.
/// * `dev_id` Optional device ID to use with crypto callbacks or async hardware.
///
/// # Returns
///
/// Returns either Ok(ed25519) containing the Ed25519 struct instance or
/// Err(e) containing the wolfSSL library error code value.
///
/// # Example
///
/// ```rust
/// use wolfssl_wolfcrypt::ed25519::Ed25519;
/// let ed = Ed25519::new_ex(None, None).expect("Error with new()");
/// ```
pub fn new_ex(heap: Option<*mut core::ffi::c_void>, dev_id: Option<i32>) -> Result<Self, i32> {
let mut ws_key: MaybeUninit<sys::ed25519_key> = 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_ed25519_init_ex(ws_key.as_mut_ptr(), heap, dev_id) };
if rc != 0 {
return Err(rc);
}
let ws_key = unsafe { ws_key.assume_init() };
let ed25519 = Ed25519 { ws_key };
Ok(ed25519)
}
/// Check the public key is valid.
///
/// When a private key is present, check that the calculated public key
/// matches it. When a private key is not present, check that Y is in range
/// and an X is able to be calculated.
///
/// # Returns
///
/// Returns either Ok(()) on success or Err(e) containing the wolfSSL
/// library error code value.
///
/// # Example
///
/// ```rust
/// use wolfssl_wolfcrypt::random::RNG;
/// use wolfssl_wolfcrypt::ed25519::Ed25519;
/// let mut rng = RNG::new().expect("Error creating RNG");
/// let mut ed = Ed25519::generate(&mut rng).expect("Error with generate()");
/// ed.check_key().expect("Error with check_key()");
/// ```
pub fn check_key(&mut self) -> Result<(), i32> {
let rc = unsafe { sys::wc_ed25519_check_key(&mut self.ws_key) };
if rc != 0 {
return Err(rc);
}
Ok(())
}
/// Export private and public key to separate buffers.
///
/// # Parameters
///
/// * `private`: Output buffer in which to store the public/private key
/// pair. The length should be PRV_KEY_SIZE.
/// * `public`: Output buffer in which to store the public key. The length
/// should be PUB_KEY_SIZE.
///
/// # Returns
///
/// Returns either Ok(()) on success or Err(e) containing the wolfSSL
/// library error code value.
///
/// # Example
///
/// ```rust
/// #[cfg(ed25519_export)]
/// {
/// use wolfssl_wolfcrypt::random::RNG;
/// use wolfssl_wolfcrypt::ed25519::Ed25519;
/// let mut rng = RNG::new().expect("Error creating RNG");
/// let mut ed = Ed25519::generate(&mut rng).expect("Error with generate()");
/// let mut private = [0u8; Ed25519::PRV_KEY_SIZE];
/// let mut public = [0u8; Ed25519::PUB_KEY_SIZE];
/// ed.export_key(&mut private, &mut public).expect("Error with export_key()");
/// }
/// ```
#[cfg(ed25519_export)]
pub fn export_key(&self, private: &mut [u8], public: &mut [u8]) -> Result<(), i32> {
let mut private_size = crate::buffer_len_to_u32(private.len())?;
let mut public_size = crate::buffer_len_to_u32(public.len())?;
let rc = unsafe {
sys::wc_ed25519_export_key(&self.ws_key,
private.as_mut_ptr(), &mut private_size,
public.as_mut_ptr(), &mut public_size)
};
if rc != 0 {
return Err(rc);
}
Ok(())
}
/// Export public key to buffer.
///
/// # Parameters
///
/// * `public`: Output buffer in which to store the public key. The length
/// should be PUB_KEY_SIZE.
///
/// # Returns
///
/// Returns either Ok(size) containing the number of bytes written to
/// `public` on success or Err(e) containing the wolfSSL library error
/// code value.
///
/// # Example
///
/// ```rust
/// #[cfg(ed25519_export)]
/// {
/// use wolfssl_wolfcrypt::random::RNG;
/// use wolfssl_wolfcrypt::ed25519::Ed25519;
/// let mut rng = RNG::new().expect("Error creating RNG");
/// let mut ed = Ed25519::generate(&mut rng).expect("Error with generate()");
/// let mut public = [0u8; Ed25519::PUB_KEY_SIZE];
/// ed.export_public(&mut public).expect("Error with export_public()");
/// }
/// ```
#[cfg(ed25519_export)]
pub fn export_public(&self, public: &mut [u8]) -> Result<(), i32> {
let mut public_size = crate::buffer_len_to_u32(public.len())?;
let rc = unsafe {
sys::wc_ed25519_export_public(&self.ws_key, public.as_mut_ptr(),
&mut public_size)
};
if rc != 0 {
return Err(rc);
}
Ok(())
}
/// Export public/private key pair to buffer.
///
/// # Parameters
///
/// * `keyout`: Output buffer in which to store the key pair. The length
/// should be PRV_KEY_SIZE.
///
/// # Returns
///
/// Returns either Ok(size) containing the number of bytes written to
/// `keyout` on success or Err(e) containing the wolfSSL library error
/// code value.
///
/// # Example
///
/// ```rust
/// #[cfg(ed25519_export)]
/// {
/// use wolfssl_wolfcrypt::random::RNG;
/// use wolfssl_wolfcrypt::ed25519::Ed25519;
/// let mut rng = RNG::new().expect("Error creating RNG");
/// let mut ed = Ed25519::generate(&mut rng).expect("Error with generate()");
/// let mut private = [0u8; Ed25519::PRV_KEY_SIZE];
/// ed.export_private(&mut private).expect("Error with export_private()");
/// }
/// ```
#[cfg(ed25519_export)]
pub fn export_private(&self, keyout: &mut [u8]) -> Result<(), i32> {
let mut keyout_size = crate::buffer_len_to_u32(keyout.len())?;
let rc = unsafe {
sys::wc_ed25519_export_private(&self.ws_key, keyout.as_mut_ptr(),
&mut keyout_size)
};
if rc != 0 {
return Err(rc);
}
Ok(())
}
/// Export private key only to buffer.
///
/// # Parameters
///
/// * `private`: Output buffer in which to store the private key. The
/// length should be KEY_SIZE.
///
/// # Returns
///
/// Returns either Ok(size) containing the number of bytes written to
/// `private` on success or Err(e) containing the wolfSSL library error
/// code value.
///
/// # Example
///
/// ```rust
/// #[cfg(ed25519_export)]
/// {
/// use wolfssl_wolfcrypt::random::RNG;
/// use wolfssl_wolfcrypt::ed25519::Ed25519;
/// let mut rng = RNG::new().expect("Error creating RNG");
/// let mut ed = Ed25519::generate(&mut rng).expect("Error with generate()");
/// let mut private_only = [0u8; Ed25519::KEY_SIZE];
/// ed.export_private_only(&mut private_only).expect("Error with export_private_only()");
/// }
/// ```
#[cfg(ed25519_export)]
pub fn export_private_only(&self, private: &mut [u8]) -> Result<(), i32> {
let mut private_size = crate::buffer_len_to_u32(private.len())?;
let rc = unsafe {
sys::wc_ed25519_export_private_only(&self.ws_key,
private.as_mut_ptr(), &mut private_size)
};
if rc != 0 {
return Err(rc);
}
Ok(())
}
/// Import a public Ed25519 key from buffer.
///
/// This function handles either compressed or uncompressed keys.
/// The public key is checked that it matches the private key if one is
/// already present.
///
/// # Parameters
///
/// * `public`: Input buffer containing public key.
///
/// # Returns
///
/// Returns either Ok(()) on success or Err(e) containing the wolfSSL
/// library error code value.
///
/// # Example
///
/// ```rust
/// #[cfg(ed25519_import)]
/// {
/// use wolfssl_wolfcrypt::random::RNG;
/// use wolfssl_wolfcrypt::ed25519::Ed25519;
/// let mut rng = RNG::new().expect("Error creating RNG");
/// let mut ed = Ed25519::generate(&mut rng).expect("Error with generate()");
/// let mut private = [0u8; Ed25519::PRV_KEY_SIZE];
/// let mut public = [0u8; Ed25519::PUB_KEY_SIZE];
/// ed.export_key(&mut private, &mut public).expect("Error with export_key()");
/// let mut ed = Ed25519::new().expect("Error with new()");
/// ed.import_public(&public).expect("Error with import_public()");
/// }
/// ```
#[cfg(ed25519_import)]
pub fn import_public(&mut self, public: &[u8]) -> Result<(), i32> {
let public_size = crate::buffer_len_to_u32(public.len())?;
let rc = unsafe {
sys::wc_ed25519_import_public(public.as_ptr(), public_size, &mut self.ws_key)
};
if rc != 0 {
return Err(rc);
}
Ok(())
}
/// Import a public Ed25519 key from buffer with trusted flag.
///
/// This function handles either compressed or uncompressed keys.
/// The public key is checked that it matches the private key if one is
/// already present and trusted is false.
///
/// # Parameters
///
/// * `public`: Input buffer containing public key.
/// * `trusted`: Whether the public key buffer is trusted.
///
/// # Returns
///
/// Returns either Ok(()) on success or Err(e) containing the wolfSSL
/// library error code value.
///
/// # Example
///
/// ```rust
/// #[cfg(ed25519_import)]
/// {
/// use wolfssl_wolfcrypt::random::RNG;
/// use wolfssl_wolfcrypt::ed25519::Ed25519;
/// let mut rng = RNG::new().expect("Error creating RNG");
/// let mut ed = Ed25519::generate(&mut rng).expect("Error with generate()");
/// let mut private = [0u8; Ed25519::PRV_KEY_SIZE];
/// let mut public = [0u8; Ed25519::PUB_KEY_SIZE];
/// ed.export_key(&mut private, &mut public).expect("Error with export_key()");
/// let mut ed = Ed25519::new().expect("Error with new()");
/// ed.import_public_ex(&public, false).expect("Error with import_public_ex()");
/// }
/// ```
#[cfg(ed25519_import)]
pub fn import_public_ex(&mut self, public: &[u8], trusted: bool) -> Result<(), i32> {
let public_size = crate::buffer_len_to_u32(public.len())?;
let rc = unsafe {
sys::wc_ed25519_import_public_ex(public.as_ptr(), public_size,
&mut self.ws_key, if trusted {1} else {0})
};
if rc != 0 {
return Err(rc);
}
Ok(())
}
/// Import private Ed25519 key only from buffer.
///
/// # Parameters
///
/// * `private`: Input buffer containing private key.
///
/// # Returns
///
/// Returns either Ok(()) on success or Err(e) containing the wolfSSL
/// library error code value.
///
/// # Example
///
/// ```rust
/// #[cfg(ed25519_import)]
/// {
/// use wolfssl_wolfcrypt::random::RNG;
/// use wolfssl_wolfcrypt::ed25519::Ed25519;
/// let mut rng = RNG::new().expect("Error creating RNG");
/// let mut ed = Ed25519::generate(&mut rng).expect("Error with generate()");
/// let mut private_only = [0u8; Ed25519::KEY_SIZE];
/// ed.export_private_only(&mut private_only).expect("Error with export_private_only()");
/// let mut ed = Ed25519::new().expect("Error with new()");
/// ed.import_private_only(&private_only).expect("Error with import_private_only()");
/// }
/// ```
#[cfg(ed25519_import)]
pub fn import_private_only(&mut self, private: &[u8]) -> Result<(), i32> {
let private_size = crate::buffer_len_to_u32(private.len())?;
let rc = unsafe {
sys::wc_ed25519_import_private_only(private.as_ptr(), private_size,
&mut self.ws_key)
};
if rc != 0 {
return Err(rc);
}
Ok(())
}
/// Import public/private Ed25519 key pair from buffers.
///
/// This functions handles either compressed or uncompressed keys.
/// The public key is assumed to be untrusted and is checked against the
/// private key.
///
/// # Parameters
///
/// * `private`: Input buffer containing private key.
/// * `public`: Optional input buffer containing public key.
///
/// # Returns
///
/// Returns either Ok(()) on success or Err(e) containing the wolfSSL
/// library error code value.
///
/// # Example
///
/// ```rust
/// #[cfg(ed25519_import)]
/// {
/// use wolfssl_wolfcrypt::random::RNG;
/// use wolfssl_wolfcrypt::ed25519::Ed25519;
/// let mut rng = RNG::new().expect("Error creating RNG");
/// let mut ed = Ed25519::generate(&mut rng).expect("Error with generate()");
/// let mut private = [0u8; Ed25519::PRV_KEY_SIZE];
/// let mut public = [0u8; Ed25519::PUB_KEY_SIZE];
/// ed.export_key(&mut private, &mut public).expect("Error with export_key()");
/// let mut ed = Ed25519::new().expect("Error with new()");
/// ed.import_private_key(&private, Some(&public)).expect("Error with import_private_key()");
/// }
/// ```
#[cfg(ed25519_import)]
pub fn import_private_key(&mut self, private: &[u8], public: Option<&[u8]>) -> Result<(), i32> {
let private_size = crate::buffer_len_to_u32(private.len())?;
let mut public_ptr: *const u8 = core::ptr::null();
let mut public_size = 0u32;
if let Some(public) = public {
public_ptr = public.as_ptr();
public_size = crate::buffer_len_to_u32(public.len())?;
}
let rc = unsafe {
sys::wc_ed25519_import_private_key(private.as_ptr(), private_size,
public_ptr, public_size, &mut self.ws_key)
};
if rc != 0 {
return Err(rc);
}
Ok(())
}
/// Import public/private Ed25519 key pair from buffers with trusted flag.
///
/// This functions handles either compressed or uncompressed keys.
/// The public is checked against private key if not trusted.
///
/// # Parameters
///
/// * `private`: Input buffer containing private key.
/// * `public`: Optional input buffer containing private key.
/// * `trusted`: Whether the public key buffer is trusted.
///
/// # Returns
///
/// Returns either Ok(()) on success or Err(e) containing the wolfSSL
/// library error code value.
///
/// # Example
///
/// ```rust
/// #[cfg(ed25519_import)]
/// {
/// use wolfssl_wolfcrypt::random::RNG;
/// use wolfssl_wolfcrypt::ed25519::Ed25519;
/// let mut rng = RNG::new().expect("Error creating RNG");
/// let mut ed = Ed25519::generate(&mut rng).expect("Error with generate()");
/// let mut private = [0u8; Ed25519::PRV_KEY_SIZE];
/// let mut public = [0u8; Ed25519::PUB_KEY_SIZE];
/// ed.export_key(&mut private, &mut public).expect("Error with export_key()");
/// let mut ed = Ed25519::new().expect("Error with new()");
/// ed.import_private_key_ex(&private, Some(&public), false).expect("Error with import_private_key_ex()");
/// }
/// ```
#[cfg(ed25519_import)]
pub fn import_private_key_ex(&mut self, private: &[u8], public: Option<&[u8]>, trusted: bool) -> Result<(), i32> {
let private_size = crate::buffer_len_to_u32(private.len())?;
let mut public_ptr: *const u8 = core::ptr::null();
let mut public_size = 0u32;
if let Some(public) = public {
public_ptr = public.as_ptr();
public_size = crate::buffer_len_to_u32(public.len())?;
}
let rc = unsafe {
sys::wc_ed25519_import_private_key_ex(private.as_ptr(), private_size,
public_ptr, public_size, &mut self.ws_key, if trusted {1} else {0})
};
if rc != 0 {
return Err(rc);
}
Ok(())
}
/// Generate the Ed25519 public key from the private key stored in the
/// Ed25519 object.
///
/// The public key is written to the pubkey output buffer.
///
/// # Parameters
///
/// * `pubkey`: Output buffer in which to store the public key.
///
/// # Returns
///
/// Returns either Ok(()) on success or Err(e) containing the wolfSSL
/// library error code value.
///
/// # Example
///
/// ```rust
/// use wolfssl_wolfcrypt::random::RNG;
/// use wolfssl_wolfcrypt::ed25519::Ed25519;
/// let mut rng = RNG::new().expect("Error creating RNG");
/// let ed = Ed25519::generate(&mut rng).expect("Error with generate()");
/// let mut private = [0u8; Ed25519::KEY_SIZE];
/// ed.export_private_only(&mut private).expect("Error with export_private_only()");
/// let mut ed = Ed25519::new().expect("Error with new()");
/// ed.import_private_only(&private).expect("Error with import_private_only()");
/// let mut public = [0u8; Ed25519::KEY_SIZE];
/// ed.make_public(&mut public).expect("Error with make_public()");
/// ```
pub fn make_public(&mut self, pubkey: &mut [u8]) -> Result<(), i32> {
let pubkey_size = crate::buffer_len_to_u32(pubkey.len())?;
let rc = unsafe {
sys::wc_ed25519_make_public(&mut self.ws_key,
pubkey.as_mut_ptr(), pubkey_size)
};
if rc != 0 {
return Err(rc);
}
Ok(())
}
/// Sign a message using Ed25519 key.
///
/// # Parameters
///
/// * `message`: Message to sign.
/// * `signature`: Output buffer to hold signature.
///
/// # Returns
///
/// Returns either Ok(size) containing the number of bytes written to
/// signature on success or Err(e) containing the wolfSSL library error
/// code value.
///
/// # Example
///
/// ```rust
/// #[cfg(ed25519_sign)]
/// {
/// use wolfssl_wolfcrypt::random::RNG;
/// use wolfssl_wolfcrypt::ed25519::Ed25519;
/// let mut rng = RNG::new().expect("Error creating RNG");
/// let mut ed = Ed25519::generate(&mut rng).expect("Error with generate()");
/// let message = [0x42u8, 33, 55, 66];
/// let mut signature = [0u8; Ed25519::SIG_SIZE];
/// ed.sign_msg(&message, &mut signature).expect("Error with sign_msg()");
/// }
/// ```
#[cfg(ed25519_sign)]
pub fn sign_msg(&mut self, message: &[u8], signature: &mut [u8]) -> Result<usize, i32> {
let message_size = crate::buffer_len_to_u32(message.len())?;
let mut signature_size = crate::buffer_len_to_u32(signature.len())?;
let rc = unsafe {
sys::wc_ed25519_sign_msg(message.as_ptr(), message_size,
signature.as_mut_ptr(), &mut signature_size, &mut self.ws_key)
};
if rc != 0 {
return Err(rc);
}
Ok(signature_size as usize)
}
/// Sign a message with context using Ed25519 key.
///
/// The context is part of the data signed.
///
/// # Parameters
///
/// * `message`: Message to sign.
/// * `context`: Buffer containing context for which message is being signed.
/// * `signature`: Output buffer to hold signature.
///
/// # Returns
///
/// Returns either Ok(size) containing the number of bytes written to
/// signature on success or Err(e) containing the wolfSSL library error
/// code value.
///
/// # Example
///
/// ```rust
/// #[cfg(ed25519_sign)]
/// {
/// use wolfssl_wolfcrypt::random::RNG;
/// use wolfssl_wolfcrypt::ed25519::Ed25519;
/// let mut rng = RNG::new().expect("Error creating RNG");
/// let mut ed = Ed25519::generate(&mut rng).expect("Error with generate()");
/// let message = [0x42u8, 33, 55, 66];
/// let context = b"context";
/// let mut signature = [0u8; Ed25519::SIG_SIZE];
/// ed.sign_msg_ctx(&message, context, &mut signature).expect("Error with sign_msg_ctx()");
/// }
/// ```
#[cfg(ed25519_sign)]
pub fn sign_msg_ctx(&mut self, message: &[u8], context: &[u8], signature: &mut [u8]) -> Result<usize, i32> {
let message_size = crate::buffer_len_to_u32(message.len())?;
if context.len() > 255 {
return Err(sys::wolfCrypt_ErrorCodes_BAD_FUNC_ARG);
}
let context_size = context.len() as u8;
let mut signature_size = crate::buffer_len_to_u32(signature.len())?;
let rc = unsafe {
sys::wc_ed25519ctx_sign_msg(message.as_ptr(), message_size,
signature.as_mut_ptr(), &mut signature_size, &mut self.ws_key,
context.as_ptr(), context_size)
};
if rc != 0 {
return Err(rc);
}
Ok(signature_size as usize)
}
/// Sign a message digest with context using Ed25519 key.
///
/// The context is part of the data signed.
/// The message is pre-hashed before signature calculation.
///
/// # Parameters
///
/// * `hash`: Message digest to sign.
/// * `context`: Optional buffer containing context for which hash is being signed.
/// * `signature`: Output buffer to hold signature.
///
/// # Returns
///
/// Returns either Ok(size) containing the number of bytes written to
/// signature on success or Err(e) containing the wolfSSL library error
/// code value.
///
/// # Example
///
/// ```rust
/// #[cfg(ed25519_sign)]
/// {
/// use wolfssl_wolfcrypt::random::RNG;
/// use wolfssl_wolfcrypt::ed25519::Ed25519;
/// let mut rng = RNG::new().expect("Error creating RNG");
/// let mut ed = Ed25519::generate(&mut rng).expect("Error with generate()");
/// let hash = [
/// 0xddu8,0xaf,0x35,0xa1,0x93,0x61,0x7a,0xba,
/// 0xcc,0x41,0x73,0x49,0xae,0x20,0x41,0x31,
/// 0x12,0xe6,0xfa,0x4e,0x89,0xa9,0x7e,0xa2,
/// 0x0a,0x9e,0xee,0xe6,0x4b,0x55,0xd3,0x9a,
/// 0x21,0x92,0x99,0x2a,0x27,0x4f,0xc1,0xa8,
/// 0x36,0xba,0x3c,0x23,0xa3,0xfe,0xeb,0xbd,
/// 0x45,0x4d,0x44,0x23,0x64,0x3c,0xe8,0x0e,
/// 0x2a,0x9a,0xc9,0x4f,0xa5,0x4c,0xa4,0x9f
/// ];
/// let context = b"context";
/// let mut signature = [0u8; Ed25519::SIG_SIZE];
/// ed.sign_hash_ph(&hash, Some(context), &mut signature).expect("Error with sign_hash_ph()");
/// }
/// ```
#[cfg(ed25519_sign)]
pub fn sign_hash_ph(&mut self, hash: &[u8], context: Option<&[u8]>, signature: &mut [u8]) -> Result<usize, i32> {
let hash_size = crate::buffer_len_to_u32(hash.len())?;
let mut context_ptr: *const u8 = core::ptr::null();
let mut context_size = 0u8;
if let Some(context) = context {
context_ptr = context.as_ptr();
if context.len() > 255 {
return Err(sys::wolfCrypt_ErrorCodes_BAD_FUNC_ARG);
}
context_size = context.len() as u8;
}
let mut signature_size = crate::buffer_len_to_u32(signature.len())?;
let rc = unsafe {
sys::wc_ed25519ph_sign_hash(hash.as_ptr(), hash_size,
signature.as_mut_ptr(), &mut signature_size, &mut self.ws_key,
context_ptr, context_size)
};
if rc != 0 {
return Err(rc);
}
Ok(signature_size as usize)
}
/// Sign a message with context using Ed25519 key.
///
/// The context is part of the data signed.
/// The message is pre-hashed before signature calculation.
///
/// # Parameters
///
/// * `message`: Message digest to sign.
/// * `context`: Optional buffer containing context for which message is being signed.
/// * `signature`: Output buffer to hold signature.
///
/// # Returns
///
/// Returns either Ok(size) containing the number of bytes written to
/// signature on success or Err(e) containing the wolfSSL library error
/// code value.
///
/// # Example
///
/// ```rust
/// #[cfg(ed25519_sign)]
/// {
/// use wolfssl_wolfcrypt::random::RNG;
/// use wolfssl_wolfcrypt::ed25519::Ed25519;
/// let mut rng = RNG::new().expect("Error creating RNG");
/// let mut ed = Ed25519::generate(&mut rng).expect("Error with generate()");
/// let message = [0x42u8, 33, 55, 66];
/// let context = b"context";
/// let mut signature = [0u8; Ed25519::SIG_SIZE];
/// ed.sign_msg_ph(&message, Some(context), &mut signature).expect("Error with sign_msg_ph()");
/// }
/// ```
#[cfg(ed25519_sign)]
pub fn sign_msg_ph(&mut self, message: &[u8], context: Option<&[u8]>, signature: &mut [u8]) -> Result<usize, i32> {
let message_size = crate::buffer_len_to_u32(message.len())?;
let mut context_ptr: *const u8 = core::ptr::null();
let mut context_size = 0u8;
if let Some(context) = context {
context_ptr = context.as_ptr();
if context.len() > 255 {
return Err(sys::wolfCrypt_ErrorCodes_BAD_FUNC_ARG);
}
context_size = context.len() as u8;
}
let mut signature_size = crate::buffer_len_to_u32(signature.len())?;
let rc = unsafe {
sys::wc_ed25519ph_sign_msg(message.as_ptr(), message_size,
signature.as_mut_ptr(), &mut signature_size, &mut self.ws_key,
context_ptr, context_size)
};
if rc != 0 {
return Err(rc);
}
Ok(signature_size as usize)
}
/// Sign input data with optional context using Ed25519 key.
///
/// If provided, the context is part of the data signed.
///
/// # Parameters
///
/// * `din`: Data to sign.
/// * `context`: Optional buffer containing context for which `din` is being signed.
/// * `typ`: One of `Ed25519::ED25519`, `Ed25519::ED25519CTX`, or `Ed25519::ED25519PH`.
/// * `signature`: Output buffer to hold signature.
///
/// # Returns
///
/// Returns either Ok(size) containing the number of bytes written to
/// signature on success or Err(e) containing the wolfSSL library error
/// code value.
///
/// # Example
///
/// ```rust
/// #[cfg(ed25519_sign)]
/// {
/// use wolfssl_wolfcrypt::random::RNG;
/// use wolfssl_wolfcrypt::ed25519::Ed25519;
/// let mut rng = RNG::new().expect("Error creating RNG");
/// let mut ed = Ed25519::generate(&mut rng).expect("Error with generate()");
/// let message = [0x42u8, 33, 55, 66];
/// let context = b"context";
/// let mut signature = [0u8; Ed25519::SIG_SIZE];
/// ed.sign_msg_ex(&message, Some(context), Ed25519::ED25519, &mut signature).expect("Error with sign_msg_ex()");
/// }
/// ```
#[cfg(ed25519_sign)]
pub fn sign_msg_ex(&mut self, din: &[u8], context: Option<&[u8]>, typ: u8, signature: &mut [u8]) -> Result<usize, i32> {
let din_size = crate::buffer_len_to_u32(din.len())?;
let mut context_ptr: *const u8 = core::ptr::null();
let mut context_size = 0u8;
if let Some(context) = context {
context_ptr = context.as_ptr();
if context.len() > 255 {
return Err(sys::wolfCrypt_ErrorCodes_BAD_FUNC_ARG);
}
context_size = context.len() as u8;
}
let mut signature_size = crate::buffer_len_to_u32(signature.len())?;
let rc = unsafe {
sys::wc_ed25519_sign_msg_ex(din.as_ptr(), din_size,
signature.as_mut_ptr(), &mut signature_size, &mut self.ws_key,
typ, context_ptr, context_size)
};
if rc != 0 {
return Err(rc);
}
Ok(signature_size as usize)
}
/// Verify the Ed25519 signature of a message to ensure authenticity.
///
/// # Parameters
///
/// * `signature`: Signature to verify.
/// * `message`: Message to verify the signature of.
///
/// # Returns
///
/// Returns either Ok(valid) containing whether the signature is valid or
/// Err(e) containing the wolfSSL library error code value.
///
/// # Example
///
/// ```rust
/// #[cfg(ed25519_verify)]
/// {
/// use wolfssl_wolfcrypt::random::RNG;
/// use wolfssl_wolfcrypt::ed25519::Ed25519;
/// let mut rng = RNG::new().expect("Error creating RNG");
/// let mut ed = Ed25519::generate(&mut rng).expect("Error with generate()");
/// let message = [0x42u8, 33, 55, 66];
/// let mut signature = [0u8; Ed25519::SIG_SIZE];
/// ed.sign_msg(&message, &mut signature).expect("Error with sign_msg()");
/// let signature_valid = ed.verify_msg(&signature, &message).expect("Error with verify_msg()");
/// assert!(signature_valid);
/// }
/// ```
#[cfg(ed25519_verify)]
pub fn verify_msg(&mut self, signature: &[u8], message: &[u8]) -> Result<bool, i32> {
let signature_size = crate::buffer_len_to_u32(signature.len())?;
let message_size = crate::buffer_len_to_u32(message.len())?;
let mut res = 0i32;
let rc = unsafe {
sys::wc_ed25519_verify_msg(signature.as_ptr(), signature_size,
message.as_ptr(), message_size, &mut res, &mut self.ws_key)
};
if rc != 0 {
return Err(rc);
}
Ok(res == 1)
}
/// Verify the Ed25519 signature of a message and context to ensure authenticity.
///
/// The context is included as part of the data verified.
///
/// # Parameters
///
/// * `signature`: Signature to verify.
/// * `message`: Message to verify the signature of.
/// * `context`: Buffer containing context for which the message was signed.
///
/// # Returns
///
/// Returns either Ok(valid) containing whether the signature is valid or
/// Err(e) containing the wolfSSL library error code value.
///
/// # Example
///
/// ```rust
/// #[cfg(ed25519_verify)]
/// {
/// use wolfssl_wolfcrypt::random::RNG;
/// use wolfssl_wolfcrypt::ed25519::Ed25519;
/// let mut rng = RNG::new().expect("Error creating RNG");
/// let mut ed = Ed25519::generate(&mut rng).expect("Error with generate()");
/// let message = b"Hello!";
/// let context = b"context";
/// let mut signature = [0u8; Ed25519::SIG_SIZE];
/// ed.sign_msg_ctx(message, context, &mut signature).expect("Error with sign_msg()");
/// let signature_valid = ed.verify_msg_ctx(&signature, message, context).expect("Error with verify_msg_ctx()");
/// assert!(signature_valid);
/// }
/// ```
#[cfg(ed25519_verify)]
pub fn verify_msg_ctx(&mut self, signature: &[u8], message: &[u8], context: &[u8]) -> Result<bool, i32> {
let signature_size = crate::buffer_len_to_u32(signature.len())?;
let message_size = crate::buffer_len_to_u32(message.len())?;
if context.len() > 255 {
return Err(sys::wolfCrypt_ErrorCodes_BAD_FUNC_ARG);
}
let context_size = context.len() as u8;
let mut res = 0i32;
let rc = unsafe {
sys::wc_ed25519ctx_verify_msg(signature.as_ptr(), signature_size,
message.as_ptr(), message_size, &mut res, &mut self.ws_key,
context.as_ptr(), context_size)
};
if rc != 0 {
return Err(rc);
}
Ok(res == 1)
}
/// Verify the Ed25519 signature of a message digest and context to ensure authenticity.
///
/// The context is included as part of the data verified.
/// The hash algorithm used to create message digest must be SHA-512.
/// The message is pre-hashed before verification.
///
/// # Parameters
///
/// * `signature`: Signature to verify.
/// * `hash`: Message to verify the signature of.
/// * `context`: Optional buffer containing context for which the hash was signed.
///
/// # Returns
///
/// Returns either Ok(valid) containing whether the signature is valid or
/// Err(e) containing the wolfSSL library error code value.
///
/// # Example
///
/// ```rust
/// #[cfg(ed25519_verify)]
/// {
/// use wolfssl_wolfcrypt::random::RNG;
/// use wolfssl_wolfcrypt::ed25519::Ed25519;
/// let mut rng = RNG::new().expect("Error creating RNG");
/// let mut ed = Ed25519::generate(&mut rng).expect("Error with generate()");
/// let hash = [
/// 0xddu8,0xaf,0x35,0xa1,0x93,0x61,0x7a,0xba,
/// 0xcc,0x41,0x73,0x49,0xae,0x20,0x41,0x31,
/// 0x12,0xe6,0xfa,0x4e,0x89,0xa9,0x7e,0xa2,
/// 0x0a,0x9e,0xee,0xe6,0x4b,0x55,0xd3,0x9a,
/// 0x21,0x92,0x99,0x2a,0x27,0x4f,0xc1,0xa8,
/// 0x36,0xba,0x3c,0x23,0xa3,0xfe,0xeb,0xbd,
/// 0x45,0x4d,0x44,0x23,0x64,0x3c,0xe8,0x0e,
/// 0x2a,0x9a,0xc9,0x4f,0xa5,0x4c,0xa4,0x9f
/// ];
/// let context = b"context";
/// let mut signature = [0u8; Ed25519::SIG_SIZE];
/// ed.sign_hash_ph(&hash, Some(context), &mut signature).expect("Error with sign_hash_ph()");
/// let signature_valid = ed.verify_hash_ph(&signature, &hash, Some(context)).expect("Error with verify_hash_ph()");
/// assert!(signature_valid);
/// }
/// ```
#[cfg(ed25519_verify)]
pub fn verify_hash_ph(&mut self, signature: &[u8], hash: &[u8], context: Option<&[u8]>) -> Result<bool, i32> {
let signature_size = crate::buffer_len_to_u32(signature.len())?;
let hash_size = crate::buffer_len_to_u32(hash.len())?;
let mut context_ptr: *const u8 = core::ptr::null();
let mut context_size = 0u8;
if let Some(context) = context {
context_ptr = context.as_ptr();
if context.len() > 255 {
return Err(sys::wolfCrypt_ErrorCodes_BAD_FUNC_ARG);
}
context_size = context.len() as u8;
}
let mut res = 0i32;
let rc = unsafe {
sys::wc_ed25519ph_verify_hash(signature.as_ptr(), signature_size,
hash.as_ptr(), hash_size, &mut res, &mut self.ws_key,
context_ptr, context_size)
};
if rc != 0 {
return Err(rc);
}
Ok(res == 1)
}
/// Verify the Ed25519 signature of a message and context to ensure authenticity.
///
/// The context is included as part of the data verified.
/// The message is pre-hashed before verification.
///
/// # Parameters
///
/// * `signature`: Signature to verify.
/// * `message`: Message to verify the signature of.
/// * `context`: Option buffer containing context for which the message was signed.
///
/// # Returns
///
/// Returns either Ok(valid) containing whether the signature is valid or
/// Err(e) containing the wolfSSL library error code value.
///
/// # Example
///
/// ```rust
/// #[cfg(ed25519_verify)]
/// {
/// use wolfssl_wolfcrypt::random::RNG;
/// use wolfssl_wolfcrypt::ed25519::Ed25519;
/// let mut rng = RNG::new().expect("Error creating RNG");
/// let mut ed = Ed25519::generate(&mut rng).expect("Error with generate()");
/// let message = [0x42u8, 33, 55, 66];
/// let context = b"context";
/// let mut signature = [0u8; Ed25519::SIG_SIZE];
/// ed.sign_msg_ph(&message, Some(context), &mut signature).expect("Error with sign_msg_ph()");
/// let signature_valid = ed.verify_msg_ph(&signature, &message, Some(context)).expect("Error with verify_msg_ph()");
/// assert!(signature_valid);
/// }
/// ```
#[cfg(ed25519_verify)]
pub fn verify_msg_ph(&mut self, signature: &[u8], message: &[u8], context: Option<&[u8]>) -> Result<bool, i32> {
let signature_size = crate::buffer_len_to_u32(signature.len())?;
let message_size = crate::buffer_len_to_u32(message.len())?;
let mut context_ptr: *const u8 = core::ptr::null();
let mut context_size = 0u8;
if let Some(context) = context {
context_ptr = context.as_ptr();
if context.len() > 255 {
return Err(sys::wolfCrypt_ErrorCodes_BAD_FUNC_ARG);
}
context_size = context.len() as u8;
}
let mut res = 0i32;
let rc = unsafe {
sys::wc_ed25519ph_verify_msg(signature.as_ptr(), signature_size,
message.as_ptr(), message_size, &mut res, &mut self.ws_key,
context_ptr, context_size)
};
if rc != 0 {
return Err(rc);
}
Ok(res == 1)
}
/// Verify the Ed25519 signature of a message and context to ensure authenticity.
///
/// The context is included as part of the data verified.
///
/// # Parameters
///
/// * `signature`: Signature to verify.
/// * `din`: Message to verify the signature of.
/// * `context`: Optional buffer containing context for which the input data was signed.
/// * `typ`: One of `Ed25519::ED25519`, `Ed25519::ED25519CTX`, or `Ed25519::ED25519PH`.
///
/// # Returns
///
/// Returns either Ok(valid) containing whether the signature is valid or
/// Err(e) containing the wolfSSL library error code value.
///
/// # Example
///
/// ```rust
/// #[cfg(ed25519_verify)]
/// {
/// use wolfssl_wolfcrypt::random::RNG;
/// use wolfssl_wolfcrypt::ed25519::Ed25519;
/// let mut rng = RNG::new().expect("Error creating RNG");
/// let mut ed = Ed25519::generate(&mut rng).expect("Error with generate()");
/// let message = [0x42u8, 33, 55, 66];
/// let context = b"context";
/// let mut signature = [0u8; Ed25519::SIG_SIZE];
/// ed.sign_msg_ex(&message, Some(context), Ed25519::ED25519, &mut signature).expect("Error with sign_msg_ex()");
/// let signature_valid = ed.verify_msg_ex(&signature, &message, Some(context), Ed25519::ED25519).expect("Error with verify_msg_ex()");
/// assert!(signature_valid);
/// }
/// ```
#[cfg(ed25519_verify)]
pub fn verify_msg_ex(&mut self, signature: &[u8], din: &[u8], context: Option<&[u8]>, typ: u8) -> Result<bool, i32> {
let signature_size = crate::buffer_len_to_u32(signature.len())?;
let din_size = crate::buffer_len_to_u32(din.len())?;
let mut context_ptr: *const u8 = core::ptr::null();
let mut context_size = 0u8;
if let Some(context) = context {
context_ptr = context.as_ptr();
if context.len() > 255 {
return Err(sys::wolfCrypt_ErrorCodes_BAD_FUNC_ARG);
}
context_size = context.len() as u8;
}
let mut res = 0i32;
let rc = unsafe {
sys::wc_ed25519_verify_msg_ex(signature.as_ptr(), signature_size,
din.as_ptr(), din_size, &mut res, &mut self.ws_key, typ,
context_ptr, context_size)
};
if rc != 0 {
return Err(rc);
}
Ok(res == 1)
}
/// Initialize Ed25519 key to perform streaming verification.
///
/// # Parameters
///
/// * `signature`: Signature to verify.
/// * `context`: Optional buffer containing context for which the input data was signed.
/// * `typ`: One of `Ed25519::ED25519`, `Ed25519::ED25519CTX`, or `Ed25519::ED25519PH`.
///
/// # Returns
///
/// Returns either Ok(()) on success or Err(e) containing the wolfSSL
/// library error code value.
///
/// # Example
///
/// ```rust
/// #[cfg(ed25519_streaming_verify)]
/// {
/// use wolfssl_wolfcrypt::random::RNG;
/// use wolfssl_wolfcrypt::ed25519::Ed25519;
/// let mut rng = RNG::new().expect("Error creating RNG");
/// let mut ed = Ed25519::generate(&mut rng).expect("Error with generate()");
/// let message = [0x42u8, 33, 55, 66];
/// let mut signature = [0u8; Ed25519::SIG_SIZE];
/// ed.sign_msg(&message, &mut signature).expect("Error with sign_msg()");
/// ed.verify_msg_init(&signature, None, Ed25519::ED25519).expect("Error with verify_msg_init()");
/// ed.verify_msg_update(&message[0..2]).expect("Error with verify_msg_update()");
/// ed.verify_msg_update(&message[2..4]).expect("Error with verify_msg_update()");
/// let signature_valid = ed.verify_msg_final(&signature).expect("Error with verify_msg_final()");
/// assert!(signature_valid);
/// }
/// ```
#[cfg(ed25519_streaming_verify)]
pub fn verify_msg_init(&mut self, signature: &[u8], context: Option<&[u8]>, typ: u8) -> Result<(), i32> {
let signature_size = crate::buffer_len_to_u32(signature.len())?;
let mut context_ptr: *const u8 = core::ptr::null();
let mut context_size = 0u8;
if let Some(context) = context {
context_ptr = context.as_ptr();
if context.len() > 255 {
return Err(sys::wolfCrypt_ErrorCodes_BAD_FUNC_ARG);
}
context_size = context.len() as u8;
}
let rc = unsafe {
sys::wc_ed25519_verify_msg_init(signature.as_ptr(), signature_size,
&mut self.ws_key, typ, context_ptr, context_size)
};
if rc != 0 {
return Err(rc);
}
Ok(())
}
/// Add input data to Ed25519 streaming verification.
///
/// # Parameters
///
/// * `din`: Segment of message to verify the signature of.
///
/// # Returns
///
/// Returns either Ok(()) on success or Err(e) containing the wolfSSL
/// library error code value.
///
/// # Example
///
/// ```rust
/// #[cfg(ed25519_streaming_verify)]
/// {
/// use wolfssl_wolfcrypt::random::RNG;
/// use wolfssl_wolfcrypt::ed25519::Ed25519;
/// let mut rng = RNG::new().expect("Error creating RNG");
/// let mut ed = Ed25519::generate(&mut rng).expect("Error with generate()");
/// let message = [0x42u8, 33, 55, 66];
/// let mut signature = [0u8; Ed25519::SIG_SIZE];
/// ed.sign_msg(&message, &mut signature).expect("Error with sign_msg()");
/// ed.verify_msg_init(&signature, None, Ed25519::ED25519).expect("Error with verify_msg_init()");
/// ed.verify_msg_update(&message[0..2]).expect("Error with verify_msg_update()");
/// ed.verify_msg_update(&message[2..4]).expect("Error with verify_msg_update()");
/// let signature_valid = ed.verify_msg_final(&signature).expect("Error with verify_msg_final()");
/// assert!(signature_valid);
/// }
/// ```
#[cfg(ed25519_streaming_verify)]
pub fn verify_msg_update(&mut self, din: &[u8]) -> Result<(), i32> {
let din_size = crate::buffer_len_to_u32(din.len())?;
let rc = unsafe {
sys::wc_ed25519_verify_msg_update(din.as_ptr(), din_size,
&mut self.ws_key)
};
if rc != 0 {
return Err(rc);
}
Ok(())
}
/// Finalize Ed25519 streaming verification.
///
/// # Parameters
///
/// * `signature`: Signature to verify.
///
/// # Returns
///
/// Returns either Ok(valid) containing whether the signature is valid or
/// Err(e) containing the wolfSSL library error code value.
///
/// # Example
///
/// ```rust
/// #[cfg(ed25519_streaming_verify)]
/// {
/// use wolfssl_wolfcrypt::random::RNG;
/// use wolfssl_wolfcrypt::ed25519::Ed25519;
/// let mut rng = RNG::new().expect("Error creating RNG");
/// let mut ed = Ed25519::generate(&mut rng).expect("Error with generate()");
/// let message = [0x42u8, 33, 55, 66];
/// let mut signature = [0u8; Ed25519::SIG_SIZE];
/// ed.sign_msg(&message, &mut signature).expect("Error with sign_msg()");
/// ed.verify_msg_init(&signature, None, Ed25519::ED25519).expect("Error with verify_msg_init()");
/// ed.verify_msg_update(&message[0..2]).expect("Error with verify_msg_update()");
/// ed.verify_msg_update(&message[2..4]).expect("Error with verify_msg_update()");
/// let signature_valid = ed.verify_msg_final(&signature).expect("Error with verify_msg_final()");
/// assert!(signature_valid);
/// }
/// ```
#[cfg(ed25519_streaming_verify)]
pub fn verify_msg_final(&mut self, signature: &[u8]) -> Result<bool, i32> {
let signature_size = crate::buffer_len_to_u32(signature.len())?;
let mut res = 0i32;
let rc = unsafe {
sys::wc_ed25519_verify_msg_final(signature.as_ptr(), signature_size,
&mut res, &mut self.ws_key)
};
if rc != 0 {
return Err(rc);
}
Ok(res == 1)
}
/// Get the size of an Ed25519 key (32 bytes).
///
/// # Returns
///
/// Returns either Ok(size) containing the key size or Err(e)
/// containing the wolfSSL library error code value.
///
/// # Example
///
/// ```rust
/// use wolfssl_wolfcrypt::random::RNG;
/// use wolfssl_wolfcrypt::ed25519::Ed25519;
/// let mut rng = RNG::new().expect("Error creating RNG");
/// let ed = Ed25519::generate(&mut rng).expect("Error with generate()");
/// let key_size = ed.size().expect("Error with size()");
/// assert_eq!(key_size, Ed25519::KEY_SIZE);
/// ```
pub fn size(&self) -> Result<usize, i32> {
let rc = unsafe { sys::wc_ed25519_size(&self.ws_key) };
if rc < 0 {
return Err(rc);
}
Ok(rc as usize)
}
/// Get the size of a private (including public) Ed25519 key (64 bytes).
///
/// # Returns
///
/// Returns either Ok(size) containing the key size or Err(e)
/// containing the wolfSSL library error code value.
///
/// # Example
///
/// ```rust
/// use wolfssl_wolfcrypt::random::RNG;
/// use wolfssl_wolfcrypt::ed25519::Ed25519;
/// let mut rng = RNG::new().expect("Error creating RNG");
/// let ed = Ed25519::generate(&mut rng).expect("Error with generate()");
/// let priv_size = ed.priv_size().expect("Error with priv_size()");
/// assert_eq!(priv_size, Ed25519::PRV_KEY_SIZE);
/// ```
pub fn priv_size(&self) -> Result<usize, i32> {
let rc = unsafe { sys::wc_ed25519_priv_size(&self.ws_key) };
if rc < 0 {
return Err(rc);
}
Ok(rc as usize)
}
/// Get the size of a public Ed25519 key (32 bytes).
///
/// # Returns
///
/// Returns either Ok(size) containing the key size or Err(e)
/// containing the wolfSSL library error code value.
///
/// # Example
///
/// ```rust
/// use wolfssl_wolfcrypt::random::RNG;
/// use wolfssl_wolfcrypt::ed25519::Ed25519;
/// let mut rng = RNG::new().expect("Error creating RNG");
/// let ed = Ed25519::generate(&mut rng).expect("Error with generate()");
/// let pub_size = ed.pub_size().expect("Error with pub_size()");
/// assert_eq!(pub_size, Ed25519::PUB_KEY_SIZE);
/// ```
pub fn pub_size(&self) -> Result<usize, i32> {
let rc = unsafe { sys::wc_ed25519_pub_size(&self.ws_key) };
if rc < 0 {
return Err(rc);
}
Ok(rc as usize)
}
/// Get the size of a Ed25519 signature (64 bytes).
///
/// # Returns
///
/// Returns either Ok(size) containing the key size or Err(e)
/// containing the wolfSSL library error code value.
///
/// # Example
///
/// ```rust
/// use wolfssl_wolfcrypt::random::RNG;
/// use wolfssl_wolfcrypt::ed25519::Ed25519;
/// let mut rng = RNG::new().expect("Error creating RNG");
/// let ed = Ed25519::generate(&mut rng).expect("Error with generate()");
/// let sig_size = ed.sig_size().expect("Error with sig_size()");
/// assert_eq!(sig_size, Ed25519::SIG_SIZE);
/// ```
pub fn sig_size(&self) -> Result<usize, i32> {
let rc = unsafe { sys::wc_ed25519_sig_size(&self.ws_key) };
if rc < 0 {
return Err(rc);
}
Ok(rc as usize)
}
}
impl Ed25519 {
fn zeroize(&mut self) {
unsafe { crate::zeroize_raw(&mut self.ws_key); }
}
}
impl Drop for Ed25519 {
/// Safely free the wolfSSL resources.
fn drop(&mut self) {
unsafe { sys::wc_ed25519_free(&mut self.ws_key); }
self.zeroize();
}
}
/// RustCrypto `signature` crate trait implementations.
///
/// Provides a fixed-size [`Signature`] and a [`VerifyingKey`] type so that
/// [`Ed25519`] can be used wherever the `signature` crate's
/// [`signature::SignerMut`], [`signature::Keypair`], and
/// [`signature::Verifier`] traits are accepted.
#[cfg(feature = "signature")]
mod signature_impl {
use super::Ed25519;
use signature::Error;
/// Ed25519 signature in its standard 64-byte encoded form.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct Signature([u8; Ed25519::SIG_SIZE]);
impl Signature {
/// Construct a signature from its raw bytes.
pub const fn from_bytes(bytes: [u8; Ed25519::SIG_SIZE]) -> Self {
Self(bytes)
}
/// Return the raw signature bytes.
pub const fn to_bytes(&self) -> [u8; Ed25519::SIG_SIZE] {
self.0
}
}
impl AsRef<[u8]> for Signature {
fn as_ref(&self) -> &[u8] {
&self.0
}
}
impl TryFrom<&[u8]> for Signature {
type Error = Error;
fn try_from(bytes: &[u8]) -> Result<Self, Error> {
let arr: [u8; Ed25519::SIG_SIZE] = bytes.try_into().map_err(|_| Error::new())?;
Ok(Self(arr))
}
}
impl From<Signature> for [u8; Ed25519::SIG_SIZE] {
fn from(sig: Signature) -> Self {
sig.0
}
}
impl signature::SignatureEncoding for Signature {
type Repr = [u8; Ed25519::SIG_SIZE];
}
/// Ed25519 verifying (public) key.
///
/// Owns a copy of the 32-byte compressed public key and instantiates a
/// short-lived wolfCrypt `ed25519_key` on each verification.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct VerifyingKey([u8; Ed25519::PUB_KEY_SIZE]);
impl VerifyingKey {
/// Construct a verifying key from its raw public key bytes.
pub const fn from_bytes(bytes: [u8; Ed25519::PUB_KEY_SIZE]) -> Self {
Self(bytes)
}
/// Return the raw public key bytes.
pub const fn to_bytes(&self) -> [u8; Ed25519::PUB_KEY_SIZE] {
self.0
}
}
impl AsRef<[u8]> for VerifyingKey {
fn as_ref(&self) -> &[u8] {
&self.0
}
}
impl TryFrom<&[u8]> for VerifyingKey {
type Error = Error;
fn try_from(bytes: &[u8]) -> Result<Self, Error> {
let arr: [u8; Ed25519::PUB_KEY_SIZE] =
bytes.try_into().map_err(|_| Error::new())?;
Ok(Self(arr))
}
}
#[cfg(all(ed25519_sign, ed25519_export))]
impl signature::Keypair for Ed25519 {
type VerifyingKey = VerifyingKey;
fn verifying_key(&self) -> Self::VerifyingKey {
let mut pub_key = [0u8; Ed25519::PUB_KEY_SIZE];
self.export_public(&mut pub_key).expect("ed25519 export_public failed");
VerifyingKey(pub_key)
}
}
#[cfg(ed25519_sign)]
impl signature::SignerMut<Signature> for Ed25519 {
fn try_sign(&mut self, msg: &[u8]) -> Result<Signature, Error> {
let mut sig = [0u8; Ed25519::SIG_SIZE];
self.sign_msg(msg, &mut sig).map_err(|_| Error::new())?;
Ok(Signature(sig))
}
}
#[cfg(all(ed25519_import, ed25519_verify))]
impl signature::Verifier<Signature> for VerifyingKey {
fn verify(&self, msg: &[u8], signature: &Signature) -> Result<(), Error> {
let mut key = Ed25519::new().map_err(|_| Error::new())?;
key.import_public(&self.0).map_err(|_| Error::new())?;
let valid = key
.verify_msg(&signature.0, msg)
.map_err(|_| Error::new())?;
if valid { Ok(()) } else { Err(Error::new()) }
}
}
}
#[cfg(feature = "signature")]
pub use signature_impl::{Signature, VerifyingKey};