/*
 * 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};
