diff --git a/wolfcrypt/src/ed448.c b/wolfcrypt/src/ed448.c index 59b411005a..263e5ad4b1 100644 --- a/wolfcrypt/src/ed448.c +++ b/wolfcrypt/src/ed448.c @@ -969,7 +969,7 @@ void wc_ed448_free(ed448_key* key) * ECC_BAD_ARG_E when outLen is less than ED448_PUB_KEY_SIZE, * 0 otherwise. */ -int wc_ed448_export_public(ed448_key* key, byte* out, word32* outLen) +int wc_ed448_export_public(const ed448_key* key, byte* out, word32* outLen) { int ret = 0; @@ -1212,7 +1212,7 @@ int wc_ed448_import_private_key(const byte* priv, word32 privSz, * ECC_BAD_ARG_E when outLen is less than ED448_KEY_SIZE, * 0 otherwise. */ -int wc_ed448_export_private_only(ed448_key* key, byte* out, word32* outLen) +int wc_ed448_export_private_only(const ed448_key* key, byte* out, word32* outLen) { int ret = 0; @@ -1244,7 +1244,7 @@ int wc_ed448_export_private_only(ed448_key* key, byte* out, word32* outLen) * BUFFER_E when outLen is less than ED448_PRV_KEY_SIZE, * 0 otherwise. */ -int wc_ed448_export_private(ed448_key* key, byte* out, word32* outLen) +int wc_ed448_export_private(const ed448_key* key, byte* out, word32* outLen) { int ret = 0; @@ -1279,7 +1279,7 @@ int wc_ed448_export_private(ed448_key* key, byte* out, word32* outLen) * than ED448_PUB_KEY_SIZE, * 0 otherwise. */ -int wc_ed448_export_key(ed448_key* key, byte* priv, word32 *privSz, +int wc_ed448_export_key(const ed448_key* key, byte* priv, word32 *privSz, byte* pub, word32 *pubSz) { int ret = 0; @@ -1392,7 +1392,7 @@ int wc_ed448_check_key(ed448_key* key) * returns BAD_FUNC_ARG when key is NULL, * ED448_KEY_SIZE otherwise. */ -int wc_ed448_size(ed448_key* key) +int wc_ed448_size(const ed448_key* key) { int ret = ED448_KEY_SIZE; @@ -1409,7 +1409,7 @@ int wc_ed448_size(ed448_key* key) * returns BAD_FUNC_ARG when key is NULL, * ED448_PRV_KEY_SIZE otherwise. */ -int wc_ed448_priv_size(ed448_key* key) +int wc_ed448_priv_size(const ed448_key* key) { int ret = ED448_PRV_KEY_SIZE; @@ -1426,7 +1426,7 @@ int wc_ed448_priv_size(ed448_key* key) * returns BAD_FUNC_ARG when key is NULL, * ED448_PUB_KEY_SIZE otherwise. */ -int wc_ed448_pub_size(ed448_key* key) +int wc_ed448_pub_size(const ed448_key* key) { int ret = ED448_PUB_KEY_SIZE; @@ -1443,7 +1443,7 @@ int wc_ed448_pub_size(ed448_key* key) * returns BAD_FUNC_ARG when key is NULL, * ED448_SIG_SIZE otherwise. */ -int wc_ed448_sig_size(ed448_key* key) +int wc_ed448_sig_size(const ed448_key* key) { int ret = ED448_SIG_SIZE; diff --git a/wolfssl/wolfcrypt/ed448.h b/wolfssl/wolfcrypt/ed448.h index d56ac4a252..162bcbc124 100644 --- a/wolfssl/wolfcrypt/ed448.h +++ b/wolfssl/wolfcrypt/ed448.h @@ -183,13 +183,13 @@ int wc_ed448_import_private_key_ex(const byte* priv, word32 privSz, #ifdef HAVE_ED448_KEY_EXPORT WOLFSSL_API -int wc_ed448_export_public(ed448_key* key, byte* out, word32* outLen); +int wc_ed448_export_public(const ed448_key* key, byte* out, word32* outLen); WOLFSSL_API -int wc_ed448_export_private_only(ed448_key* key, byte* out, word32* outLen); +int wc_ed448_export_private_only(const ed448_key* key, byte* out, word32* outLen); WOLFSSL_API -int wc_ed448_export_private(ed448_key* key, byte* out, word32* outLen); +int wc_ed448_export_private(const ed448_key* key, byte* out, word32* outLen); WOLFSSL_API -int wc_ed448_export_key(ed448_key* key, byte* priv, word32 *privSz, +int wc_ed448_export_key(const ed448_key* key, byte* priv, word32 *privSz, byte* pub, word32 *pubSz); #endif /* HAVE_ED448_KEY_EXPORT */ @@ -198,13 +198,13 @@ int wc_ed448_check_key(ed448_key* key); /* size helper */ WOLFSSL_API -int wc_ed448_size(ed448_key* key); +int wc_ed448_size(const ed448_key* key); WOLFSSL_API -int wc_ed448_priv_size(ed448_key* key); +int wc_ed448_priv_size(const ed448_key* key); WOLFSSL_API -int wc_ed448_pub_size(ed448_key* key); +int wc_ed448_pub_size(const ed448_key* key); WOLFSSL_API -int wc_ed448_sig_size(ed448_key* key); +int wc_ed448_sig_size(const ed448_key* key); #ifdef __cplusplus } /* extern "C" */ diff --git a/wrapper/rust/include.am b/wrapper/rust/include.am index dc1e46284c..a91452f40f 100644 --- a/wrapper/rust/include.am +++ b/wrapper/rust/include.am @@ -21,6 +21,7 @@ EXTRA_DIST += wrapper/rust/wolfssl/src/wolfcrypt/cmac.rs EXTRA_DIST += wrapper/rust/wolfssl/src/wolfcrypt/dh.rs EXTRA_DIST += wrapper/rust/wolfssl/src/wolfcrypt/ecc.rs EXTRA_DIST += wrapper/rust/wolfssl/src/wolfcrypt/ed25519.rs +EXTRA_DIST += wrapper/rust/wolfssl/src/wolfcrypt/ed448.rs EXTRA_DIST += wrapper/rust/wolfssl/src/wolfcrypt/hkdf.rs EXTRA_DIST += wrapper/rust/wolfssl/src/wolfcrypt/hmac.rs EXTRA_DIST += wrapper/rust/wolfssl/src/wolfcrypt/kdf.rs @@ -33,6 +34,7 @@ EXTRA_DIST += wrapper/rust/wolfssl/tests/test_cmac.rs EXTRA_DIST += wrapper/rust/wolfssl/tests/test_dh.rs EXTRA_DIST += wrapper/rust/wolfssl/tests/test_ecc.rs EXTRA_DIST += wrapper/rust/wolfssl/tests/test_ed25519.rs +EXTRA_DIST += wrapper/rust/wolfssl/tests/test_ed448.rs EXTRA_DIST += wrapper/rust/wolfssl/tests/test_hkdf.rs EXTRA_DIST += wrapper/rust/wolfssl/tests/test_hmac.rs EXTRA_DIST += wrapper/rust/wolfssl/tests/test_kdf.rs diff --git a/wrapper/rust/wolfssl/src/wolfcrypt.rs b/wrapper/rust/wolfssl/src/wolfcrypt.rs index c5a0f3b49e..597a311ae9 100644 --- a/wrapper/rust/wolfssl/src/wolfcrypt.rs +++ b/wrapper/rust/wolfssl/src/wolfcrypt.rs @@ -23,6 +23,7 @@ pub mod cmac; pub mod dh; pub mod ecc; pub mod ed25519; +pub mod ed448; pub mod hkdf; pub mod hmac; pub mod kdf; diff --git a/wrapper/rust/wolfssl/src/wolfcrypt/ed25519.rs b/wrapper/rust/wolfssl/src/wolfcrypt/ed25519.rs index e65cc73fad..c32adca849 100644 --- a/wrapper/rust/wolfssl/src/wolfcrypt/ed25519.rs +++ b/wrapper/rust/wolfssl/src/wolfcrypt/ed25519.rs @@ -627,7 +627,7 @@ impl Ed25519 { /// # Parameters /// /// * `hash`: Message digest to sign. - /// * `context`: Buffer containing context for which hash is being signed. + /// * `context`: Optional buffer containing context for which hash is being signed. /// * `signature`: Output buffer to hold signature. /// /// # Returns @@ -655,16 +655,21 @@ impl Ed25519 { /// ]; /// let context = b"context"; /// let mut signature = [0u8; Ed25519::SIG_SIZE]; - /// ed.sign_hash_ph(&hash, context, &mut signature).expect("Error with sign_hash_ph()"); + /// ed.sign_hash_ph(&hash, Some(context), &mut signature).expect("Error with sign_hash_ph()"); /// ``` - pub fn sign_hash_ph(&mut self, hash: &[u8], context: &[u8], signature: &mut [u8]) -> Result { + pub fn sign_hash_ph(&mut self, hash: &[u8], context: Option<&[u8]>, signature: &mut [u8]) -> Result { let hash_size = hash.len() as u32; - let context_size = context.len() as u8; + let mut context_ptr: *const u8 = core::ptr::null(); + let mut context_size = 0u8; + if let Some(context) = context { + context_ptr = context.as_ptr(); + context_size = context.len() as u8; + } let mut signature_size = signature.len() as u32; let rc = unsafe { ws::wc_ed25519ph_sign_hash(hash.as_ptr(), hash_size, signature.as_mut_ptr(), &mut signature_size, &mut self.ws_key, - context.as_ptr(), context_size) + context_ptr, context_size) }; if rc != 0 { return Err(rc); @@ -680,7 +685,7 @@ impl Ed25519 { /// # Parameters /// /// * `message`: Message digest to sign. - /// * `context`: Buffer containing context for which message is being signed. + /// * `context`: Optional buffer containing context for which message is being signed. /// * `signature`: Output buffer to hold signature. /// /// # Returns @@ -699,16 +704,21 @@ impl Ed25519 { /// let message = [0x42u8, 33, 55, 66]; /// let context = b"context"; /// let mut signature = [0u8; Ed25519::SIG_SIZE]; - /// ed.sign_msg_ph(&message, context, &mut signature).expect("Error with sign_msg_ph()"); + /// ed.sign_msg_ph(&message, Some(context), &mut signature).expect("Error with sign_msg_ph()"); /// ``` - pub fn sign_msg_ph(&mut self, message: &[u8], context: &[u8], signature: &mut [u8]) -> Result { + pub fn sign_msg_ph(&mut self, message: &[u8], context: Option<&[u8]>, signature: &mut [u8]) -> Result { let message_size = message.len() as u32; - let context_size = context.len() as u8; + let mut context_ptr: *const u8 = core::ptr::null(); + let mut context_size = 0u8; + if let Some(context) = context { + context_ptr = context.as_ptr(); + context_size = context.len() as u8; + } let mut signature_size = signature.len() as u32; let rc = unsafe { ws::wc_ed25519ph_sign_msg(message.as_ptr(), message_size, signature.as_mut_ptr(), &mut signature_size, &mut self.ws_key, - context.as_ptr(), context_size) + context_ptr, context_size) }; if rc != 0 { return Err(rc); @@ -859,7 +869,7 @@ impl Ed25519 { /// /// * `signature`: Signature to verify. /// * `hash`: Message to verify the signature of. - /// * `context`: Buffer containing context for which the hash was signed. + /// * `context`: Optional buffer containing context for which the hash was signed. /// /// # Returns /// @@ -885,19 +895,24 @@ impl Ed25519 { /// ]; /// let context = b"context"; /// let mut signature = [0u8; Ed25519::SIG_SIZE]; - /// ed.sign_hash_ph(&hash, context, &mut signature).expect("Error with sign_hash_ph()"); - /// let signature_valid = ed.verify_hash_ph(&signature, &hash, context).expect("Error with verify_hash_ph()"); + /// 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); /// ``` - pub fn verify_hash_ph(&mut self, signature: &[u8], hash: &[u8], context: &[u8]) -> Result { + pub fn verify_hash_ph(&mut self, signature: &[u8], hash: &[u8], context: Option<&[u8]>) -> Result { let signature_size = signature.len() as u32; let hash_size = hash.len() as u32; - let context_size = context.len() as u8; + let mut context_ptr: *const u8 = core::ptr::null(); + let mut context_size = 0u8; + if let Some(context) = context { + context_ptr = context.as_ptr(); + context_size = context.len() as u8; + } let mut res = 0i32; let rc = unsafe { ws::wc_ed25519ph_verify_hash(signature.as_ptr(), signature_size, hash.as_ptr(), hash_size, &mut res, &mut self.ws_key, - context.as_ptr(), context_size) + context_ptr, context_size) }; if rc != 0 { return Err(rc); @@ -914,7 +929,7 @@ impl Ed25519 { /// /// * `signature`: Signature to verify. /// * `message`: Message to verify the signature of. - /// * `context`: Buffer containing context for which the message was signed. + /// * `context`: Option buffer containing context for which the message was signed. /// /// # Returns /// @@ -931,19 +946,24 @@ impl Ed25519 { /// let message = [0x42u8, 33, 55, 66]; /// let context = b"context"; /// let mut signature = [0u8; Ed25519::SIG_SIZE]; - /// ed.sign_msg_ph(&message, context, &mut signature).expect("Error with sign_msg_ph()"); - /// let signature_valid = ed.verify_msg_ph(&signature, &message, context).expect("Error with verify_msg_ph()"); + /// 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); /// ``` - pub fn verify_msg_ph(&mut self, signature: &[u8], message: &[u8], context: &[u8]) -> Result { + pub fn verify_msg_ph(&mut self, signature: &[u8], message: &[u8], context: Option<&[u8]>) -> Result { let signature_size = signature.len() as u32; let message_size = message.len() as u32; - let context_size = context.len() as u8; + let mut context_ptr: *const u8 = core::ptr::null(); + let mut context_size = 0u8; + if let Some(context) = context { + context_ptr = context.as_ptr(); + context_size = context.len() as u8; + } let mut res = 0i32; let rc = unsafe { ws::wc_ed25519ph_verify_msg(signature.as_ptr(), signature_size, message.as_ptr(), message_size, &mut res, &mut self.ws_key, - context.as_ptr(), context_size) + context_ptr, context_size) }; if rc != 0 { return Err(rc); diff --git a/wrapper/rust/wolfssl/src/wolfcrypt/ed448.rs b/wrapper/rust/wolfssl/src/wolfcrypt/ed448.rs new file mode 100644 index 0000000000..677d9c59c7 --- /dev/null +++ b/wrapper/rust/wolfssl/src/wolfcrypt/ed448.rs @@ -0,0 +1,1190 @@ +/* + * Copyright (C) 2025 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +/*! +This module provides a Rust wrapper for the wolfCrypt library's EdDSA Curve +448 (Ed448) functionality. + +It leverages the `wolfssl-sys` crate for low-level FFI bindings, encapsulating +the raw C functions in a memory-safe and easy-to-use Rust API. +*/ + +use crate::wolfcrypt::random::RNG; +use std::mem::MaybeUninit; +use wolfssl_sys as ws; + +/// The `Ed448` struct manages the lifecycle of a wolfSSL `ed448_key` +/// object. +/// +/// It ensures proper initialization and deallocation. +/// +/// An instance can be created with `generate()` or `new()`. +pub struct Ed448 { + ws_key: ws::ed448_key, +} + +impl Ed448 { + /** Size of private key only. */ + pub const KEY_SIZE: usize = ws::ED448_KEY_SIZE as usize; + /** Size of signature. */ + pub const SIG_SIZE: usize = ws::ED448_SIG_SIZE as usize; + /** Compressed public key size. */ + pub const PUB_KEY_SIZE: usize = ws::ED448_PUB_KEY_SIZE as usize; + /** Size of both private and public key. */ + pub const PRV_KEY_SIZE: usize = ws::ED448_PRV_KEY_SIZE as usize; + + pub const ED448: u8 = ws::Ed448 as u8; + pub const ED448PH: u8 = ws::Ed448ph as u8; + + /// Generate a new Ed448 key. + /// + /// # Parameters + /// + /// * `rng`: `RNG` instance to use for random number generation. + /// + /// # Returns + /// + /// Returns either Ok(ed448) containing the Ed448 struct instance or + /// Err(e) containing the wolfSSL library error code value. + /// + /// # Example + /// + /// ```rust + /// use wolfssl::wolfcrypt::random::RNG; + /// use wolfssl::wolfcrypt::ed448::Ed448; + /// let mut rng = RNG::new().expect("Error creating RNG"); + /// let ed = Ed448::generate(&mut rng).expect("Error with generate()"); + /// ``` + pub fn generate(rng: &mut RNG) -> Result { + let mut ws_key: MaybeUninit = MaybeUninit::uninit(); + let rc = unsafe { ws::wc_ed448_init(ws_key.as_mut_ptr()) }; + if rc != 0 { + return Err(rc); + } + let ws_key = unsafe { ws_key.assume_init() }; + let mut ed448 = Ed448 { ws_key }; + let rc = unsafe { + ws::wc_ed448_make_key(&mut rng.wc_rng, + ws::ED448_KEY_SIZE as i32, &mut ed448.ws_key) + }; + if rc != 0 { + return Err(rc); + } + Ok(ed448) + } + + /// Create and initialize a new Ed448 instance. + /// + /// A key will not be present but can be imported with one of the import + /// functions. + /// + /// # Returns + /// + /// Returns either Ok(ed448) containing the Ed448 struct instance or + /// Err(e) containing the wolfSSL library error code value. + /// + /// # Example + /// + /// ```rust + /// use wolfssl::wolfcrypt::ed448::Ed448; + /// let ed = Ed448::new().expect("Error with new()"); + /// ``` + pub fn new() -> Result { + let mut ws_key: MaybeUninit = MaybeUninit::uninit(); + let rc = unsafe { ws::wc_ed448_init(ws_key.as_mut_ptr()) }; + if rc != 0 { + return Err(rc); + } + let ws_key = unsafe { ws_key.assume_init() }; + let ed448 = Ed448 { ws_key }; + Ok(ed448) + } + + /// 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::ed448::Ed448; + /// let mut rng = RNG::new().expect("Error creating RNG"); + /// let mut ed = Ed448::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 { ws::wc_ed448_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 + /// use wolfssl::wolfcrypt::random::RNG; + /// use wolfssl::wolfcrypt::ed448::Ed448; + /// let mut rng = RNG::new().expect("Error creating RNG"); + /// let mut ed = Ed448::generate(&mut rng).expect("Error with generate()"); + /// let mut private = [0u8; Ed448::PRV_KEY_SIZE]; + /// let mut public = [0u8; Ed448::PUB_KEY_SIZE]; + /// ed.export_key(&mut private, &mut public).expect("Error with export_key()"); + /// ``` + pub fn export_key(&self, private: &mut [u8], public: &mut [u8]) -> Result<(), i32> { + let mut private_size = private.len() as u32; + let mut public_size = public.len() as u32; + let rc = unsafe { + ws::wc_ed448_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(()) on success or Err(e) containing the wolfSSL + /// library error code value. + /// + /// # Example + /// + /// ```rust + /// use wolfssl::wolfcrypt::random::RNG; + /// use wolfssl::wolfcrypt::ed448::Ed448; + /// let mut rng = RNG::new().expect("Error creating RNG"); + /// let mut ed = Ed448::generate(&mut rng).expect("Error with generate()"); + /// let mut public = [0u8; Ed448::PUB_KEY_SIZE]; + /// ed.export_public(&mut public).expect("Error with export_public()"); + /// ``` + pub fn export_public(&self, public: &mut [u8]) -> Result<(), i32> { + let mut public_size = public.len() as u32; + let rc = unsafe { + ws::wc_ed448_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(()) on success or Err(e) containing the wolfSSL + /// library error code value. + /// + /// # Example + /// + /// ```rust + /// use wolfssl::wolfcrypt::random::RNG; + /// use wolfssl::wolfcrypt::ed448::Ed448; + /// let mut rng = RNG::new().expect("Error creating RNG"); + /// let mut ed = Ed448::generate(&mut rng).expect("Error with generate()"); + /// let mut private = [0u8; Ed448::PRV_KEY_SIZE]; + /// ed.export_private(&mut private).expect("Error with export_private()"); + /// ``` + pub fn export_private(&self, keyout: &mut [u8]) -> Result<(), i32> { + let mut keyout_size = keyout.len() as u32; + let rc = unsafe { + ws::wc_ed448_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(()) on success or Err(e) containing the wolfSSL + /// library error code value. + /// + /// # Example + /// + /// ```rust + /// use wolfssl::wolfcrypt::random::RNG; + /// use wolfssl::wolfcrypt::ed448::Ed448; + /// let mut rng = RNG::new().expect("Error creating RNG"); + /// let mut ed = Ed448::generate(&mut rng).expect("Error with generate()"); + /// let mut private_only = [0u8; Ed448::KEY_SIZE]; + /// ed.export_private_only(&mut private_only).expect("Error with export_private_only()"); + /// ``` + pub fn export_private_only(&self, private: &mut [u8]) -> Result<(), i32> { + let mut private_size = private.len() as u32; + let rc = unsafe { + ws::wc_ed448_export_private_only(&self.ws_key, + private.as_mut_ptr(), &mut private_size) + }; + if rc != 0 { + return Err(rc); + } + Ok(()) + } + + /// Import a public Ed448 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 + /// use wolfssl::wolfcrypt::random::RNG; + /// use wolfssl::wolfcrypt::ed448::Ed448; + /// let mut rng = RNG::new().expect("Error creating RNG"); + /// let mut ed = Ed448::generate(&mut rng).expect("Error with generate()"); + /// let mut private = [0u8; Ed448::PRV_KEY_SIZE]; + /// let mut public = [0u8; Ed448::PUB_KEY_SIZE]; + /// ed.export_key(&mut private, &mut public).expect("Error with export_key()"); + /// let mut ed = Ed448::new().expect("Error with new()"); + /// ed.import_public(&public).expect("Error with import_public()"); + /// ``` + pub fn import_public(&mut self, public: &[u8]) -> Result<(), i32> { + let public_size = public.len() as u32; + let rc = unsafe { + ws::wc_ed448_import_public(public.as_ptr(), public_size, &mut self.ws_key) + }; + if rc != 0 { + return Err(rc); + } + Ok(()) + } + + /// Import a public Ed448 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 + /// use wolfssl::wolfcrypt::random::RNG; + /// use wolfssl::wolfcrypt::ed448::Ed448; + /// let mut rng = RNG::new().expect("Error creating RNG"); + /// let mut ed = Ed448::generate(&mut rng).expect("Error with generate()"); + /// let mut private = [0u8; Ed448::PRV_KEY_SIZE]; + /// let mut public = [0u8; Ed448::PUB_KEY_SIZE]; + /// ed.export_key(&mut private, &mut public).expect("Error with export_key()"); + /// let mut ed = Ed448::new().expect("Error with new()"); + /// ed.import_public_ex(&public, false).expect("Error with import_public_ex()"); + /// ``` + pub fn import_public_ex(&mut self, public: &[u8], trusted: bool) -> Result<(), i32> { + let public_size = public.len() as u32; + let rc = unsafe { + ws::wc_ed448_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 Ed448 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 + /// use wolfssl::wolfcrypt::random::RNG; + /// use wolfssl::wolfcrypt::ed448::Ed448; + /// let mut rng = RNG::new().expect("Error creating RNG"); + /// let mut ed = Ed448::generate(&mut rng).expect("Error with generate()"); + /// let mut private_only = [0u8; Ed448::KEY_SIZE]; + /// ed.export_private_only(&mut private_only).expect("Error with export_private_only()"); + /// let mut ed = Ed448::new().expect("Error with new()"); + /// ed.import_private_only(&private_only).expect("Error with import_private_only()"); + /// ``` + pub fn import_private_only(&mut self, private: &[u8]) -> Result<(), i32> { + let private_size = private.len() as u32; + let rc = unsafe { + ws::wc_ed448_import_private_only(private.as_ptr(), private_size, + &mut self.ws_key) + }; + if rc != 0 { + return Err(rc); + } + Ok(()) + } + + /// Import public/private Ed448 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 + /// use wolfssl::wolfcrypt::random::RNG; + /// use wolfssl::wolfcrypt::ed448::Ed448; + /// let mut rng = RNG::new().expect("Error creating RNG"); + /// let mut ed = Ed448::generate(&mut rng).expect("Error with generate()"); + /// let mut private = [0u8; Ed448::PRV_KEY_SIZE]; + /// let mut public = [0u8; Ed448::PUB_KEY_SIZE]; + /// ed.export_key(&mut private, &mut public).expect("Error with export_key()"); + /// let mut ed = Ed448::new().expect("Error with new()"); + /// ed.import_private_key(&private, Some(&public)).expect("Error with import_private_key()"); + /// ``` + pub fn import_private_key(&mut self, private: &[u8], public: Option<&[u8]>) -> Result<(), i32> { + let private_size = private.len() as u32; + 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 = public.len() as u32; + } + let rc = unsafe { + ws::wc_ed448_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 Ed448 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 + /// use wolfssl::wolfcrypt::random::RNG; + /// use wolfssl::wolfcrypt::ed448::Ed448; + /// let mut rng = RNG::new().expect("Error creating RNG"); + /// let mut ed = Ed448::generate(&mut rng).expect("Error with generate()"); + /// let mut private = [0u8; Ed448::PRV_KEY_SIZE]; + /// let mut public = [0u8; Ed448::PUB_KEY_SIZE]; + /// ed.export_key(&mut private, &mut public).expect("Error with export_key()"); + /// let mut ed = Ed448::new().expect("Error with new()"); + /// ed.import_private_key_ex(&private, Some(&public), false).expect("Error with import_private_key_ex()"); + /// ``` + pub fn import_private_key_ex(&mut self, private: &[u8], public: Option<&[u8]>, trusted: bool) -> Result<(), i32> { + let private_size = private.len() as u32; + 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 = public.len() as u32; + } + let rc = unsafe { + ws::wc_ed448_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 Ed448 public key from the private key stored in the + /// Ed448 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::ed448::Ed448; + /// let mut rng = RNG::new().expect("Error creating RNG"); + /// let ed = Ed448::generate(&mut rng).expect("Error with generate()"); + /// let mut private = [0u8; Ed448::KEY_SIZE]; + /// ed.export_private_only(&mut private).expect("Error with export_private_only()"); + /// let mut ed = Ed448::new().expect("Error with new()"); + /// ed.import_private_only(&private).expect("Error with import_private_only()"); + /// let mut public = [0u8; Ed448::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 = pubkey.len() as u32; + let rc = unsafe { + ws::wc_ed448_make_public(&mut self.ws_key, + pubkey.as_mut_ptr(), pubkey_size) + }; + if rc != 0 { + return Err(rc); + } + Ok(()) + } + + /// Sign a message with optional context using Ed448 key. + /// + /// The context is part of the data signed. + /// + /// # Parameters + /// + /// * `message`: Message 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 + /// use wolfssl::wolfcrypt::random::RNG; + /// use wolfssl::wolfcrypt::ed448::Ed448; + /// let mut rng = RNG::new().expect("Error creating RNG"); + /// let mut ed = Ed448::generate(&mut rng).expect("Error with generate()"); + /// let message = [0x42u8, 33, 55, 66]; + /// let context = b"context"; + /// let mut signature = [0u8; Ed448::SIG_SIZE]; + /// ed.sign_msg(&message, Some(context), &mut signature).expect("Error with sign_msg()"); + /// ``` + pub fn sign_msg(&mut self, message: &[u8], context: Option<&[u8]>, signature: &mut [u8]) -> Result { + let message_size = message.len() as u32; + let mut context_ptr: *const u8 = core::ptr::null(); + let mut context_size = 0u8; + if let Some(context) = context { + context_ptr = context.as_ptr(); + context_size = context.len() as u8; + } + let mut signature_size = signature.len() as u32; + let rc = unsafe { + ws::wc_ed448_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 a message digest with optional context using Ed448 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 + /// use wolfssl::wolfcrypt::random::RNG; + /// use wolfssl::wolfcrypt::ed448::Ed448; + /// let mut rng = RNG::new().expect("Error creating RNG"); + /// let mut ed = Ed448::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; Ed448::SIG_SIZE]; + /// ed.sign_hash_ph(&hash, Some(context), &mut signature).expect("Error with sign_hash_ph()"); + /// ``` + pub fn sign_hash_ph(&mut self, hash: &[u8], context: Option<&[u8]>, signature: &mut [u8]) -> Result { + let hash_size = hash.len() as u32; + let mut context_ptr: *const u8 = core::ptr::null(); + let mut context_size = 0u8; + if let Some(context) = context { + context_ptr = context.as_ptr(); + context_size = context.len() as u8; + } + let mut signature_size = signature.len() as u32; + let rc = unsafe { + ws::wc_ed448ph_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 optional context using Ed448 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 + /// use wolfssl::wolfcrypt::random::RNG; + /// use wolfssl::wolfcrypt::ed448::Ed448; + /// let mut rng = RNG::new().expect("Error creating RNG"); + /// let mut ed = Ed448::generate(&mut rng).expect("Error with generate()"); + /// let message = [0x42u8, 33, 55, 66]; + /// let context = b"context"; + /// let mut signature = [0u8; Ed448::SIG_SIZE]; + /// ed.sign_msg_ph(&message, Some(context), &mut signature).expect("Error with sign_msg_ph()"); + /// ``` + pub fn sign_msg_ph(&mut self, message: &[u8], context: Option<&[u8]>, signature: &mut [u8]) -> Result { + let message_size = message.len() as u32; + let mut context_ptr: *const u8 = core::ptr::null(); + let mut context_size = 0u8; + if let Some(context) = context { + context_ptr = context.as_ptr(); + context_size = context.len() as u8; + } + let mut signature_size = signature.len() as u32; + let rc = unsafe { + ws::wc_ed448ph_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 Ed448 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 `Ed448::ED448` or `Ed448::ED448PH`. + /// * `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 + /// use wolfssl::wolfcrypt::random::RNG; + /// use wolfssl::wolfcrypt::ed448::Ed448; + /// let mut rng = RNG::new().expect("Error creating RNG"); + /// let mut ed = Ed448::generate(&mut rng).expect("Error with generate()"); + /// let message = [0x42u8, 33, 55, 66]; + /// let context = b"context"; + /// let mut signature = [0u8; Ed448::SIG_SIZE]; + /// ed.sign_msg_ex(&message, Some(context), Ed448::ED448, &mut signature).expect("Error with sign_msg_ex()"); + /// ``` + pub fn sign_msg_ex(&mut self, din: &[u8], context: Option<&[u8]>, typ: u8, signature: &mut [u8]) -> Result { + let din_size = din.len() as u32; + let mut context_ptr: *const u8 = core::ptr::null(); + let mut context_size = 0u8; + if let Some(context) = context { + context_ptr = context.as_ptr(); + context_size = context.len() as u8; + } + let mut signature_size = signature.len() as u32; + let rc = unsafe { + ws::wc_ed448_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 Ed448 signature of a message and optional 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`: Optional 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 + /// use wolfssl::wolfcrypt::random::RNG; + /// use wolfssl::wolfcrypt::ed448::Ed448; + /// let mut rng = RNG::new().expect("Error creating RNG"); + /// let mut ed = Ed448::generate(&mut rng).expect("Error with generate()"); + /// let message = b"Hello!"; + /// let context = b"context"; + /// let mut signature = [0u8; Ed448::SIG_SIZE]; + /// ed.sign_msg(message, Some(context), &mut signature).expect("Error with sign_msg()"); + /// let signature_valid = ed.verify_msg(&signature, message, Some(context)).expect("Error with verify_msg()"); + /// assert!(signature_valid); + /// ``` + pub fn verify_msg(&mut self, signature: &[u8], message: &[u8], context: Option<&[u8]>) -> Result { + let signature_size = signature.len() as u32; + let message_size = message.len() as u32; + let mut context_ptr: *const u8 = core::ptr::null(); + let mut context_size = 0u8; + if let Some(context) = context { + context_ptr = context.as_ptr(); + context_size = context.len() as u8; + } + let mut res = 0i32; + let rc = unsafe { + ws::wc_ed448_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 Ed448 signature of a message digest and optional 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 + /// use wolfssl::wolfcrypt::random::RNG; + /// use wolfssl::wolfcrypt::ed448::Ed448; + /// let mut rng = RNG::new().expect("Error creating RNG"); + /// let mut ed = Ed448::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; Ed448::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); + /// ``` + pub fn verify_hash_ph(&mut self, signature: &[u8], hash: &[u8], context: Option<&[u8]>) -> Result { + let signature_size = signature.len() as u32; + let hash_size = hash.len() as u32; + let mut context_ptr: *const u8 = core::ptr::null(); + let mut context_size = 0u8; + if let Some(context) = context { + context_ptr = context.as_ptr(); + context_size = context.len() as u8; + } + let mut res = 0i32; + let rc = unsafe { + ws::wc_ed448ph_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 Ed448 signature of a message and optional 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`: Optional 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 + /// use wolfssl::wolfcrypt::random::RNG; + /// use wolfssl::wolfcrypt::ed448::Ed448; + /// let mut rng = RNG::new().expect("Error creating RNG"); + /// let mut ed = Ed448::generate(&mut rng).expect("Error with generate()"); + /// let message = [0x42u8, 33, 55, 66]; + /// let context = b"context"; + /// let mut signature = [0u8; Ed448::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); + /// ``` + pub fn verify_msg_ph(&mut self, signature: &[u8], message: &[u8], context: Option<&[u8]>) -> Result { + let signature_size = signature.len() as u32; + let message_size = message.len() as u32; + let mut context_ptr: *const u8 = core::ptr::null(); + let mut context_size = 0u8; + if let Some(context) = context { + context_ptr = context.as_ptr(); + context_size = context.len() as u8; + } + let mut res = 0i32; + let rc = unsafe { + ws::wc_ed448ph_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 Ed448 signature of a message and optional 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 `Ed448::ED448` or `Ed448::ED448PH`. + /// + /// # Returns + /// + /// Returns either Ok(valid) containing whether the signature is valid or + /// Err(e) containing the wolfSSL library error code value. + /// + /// # Example + /// + /// ```rust + /// use wolfssl::wolfcrypt::random::RNG; + /// use wolfssl::wolfcrypt::ed448::Ed448; + /// let mut rng = RNG::new().expect("Error creating RNG"); + /// let mut ed = Ed448::generate(&mut rng).expect("Error with generate()"); + /// let message = [0x42u8, 33, 55, 66]; + /// let context = b"context"; + /// let mut signature = [0u8; Ed448::SIG_SIZE]; + /// ed.sign_msg_ex(&message, Some(context), Ed448::ED448, &mut signature).expect("Error with sign_msg_ex()"); + /// let signature_valid = ed.verify_msg_ex(&signature, &message, Some(context), Ed448::ED448).expect("Error with verify_msg_ex()"); + /// assert!(signature_valid); + /// ``` + pub fn verify_msg_ex(&mut self, signature: &[u8], din: &[u8], context: Option<&[u8]>, typ: u8) -> Result { + let signature_size = signature.len() as u32; + let din_size = din.len() as u32; + let mut context_ptr: *const u8 = core::ptr::null(); + let mut context_size = 0u8; + if let Some(context) = context { + context_ptr = context.as_ptr(); + context_size = context.len() as u8; + } + let mut res = 0i32; + let rc = unsafe { + ws::wc_ed448_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 Ed448 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 `Ed448::ED448` or `Ed448::ED448PH`. + /// + /// # 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::ed448::Ed448; + /// let mut rng = RNG::new().expect("Error creating RNG"); + /// let mut ed = Ed448::generate(&mut rng).expect("Error with generate()"); + /// let message = [0x42u8, 33, 55, 66]; + /// let context = [0x42u8, 1, 2, 3]; + /// let mut signature = [0u8; Ed448::SIG_SIZE]; + /// ed.sign_msg(&message, Some(&context), &mut signature).expect("Error with sign_msg()"); + /// ed.verify_msg_init(&signature, Some(&context), Ed448::ED448).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); + /// ``` + pub fn verify_msg_init(&mut self, signature: &[u8], context: Option<&[u8]>, typ: u8) -> Result<(), i32> { + let signature_size = signature.len() as u32; + let mut context_ptr: *const u8 = core::ptr::null(); + let mut context_size = 0u8; + if let Some(context) = context { + context_ptr = context.as_ptr(); + context_size = context.len() as u8; + } + let rc = unsafe { + ws::wc_ed448_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 Ed448 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 + /// use wolfssl::wolfcrypt::random::RNG; + /// use wolfssl::wolfcrypt::ed448::Ed448; + /// let mut rng = RNG::new().expect("Error creating RNG"); + /// let mut ed = Ed448::generate(&mut rng).expect("Error with generate()"); + /// let message = [0x42u8, 33, 55, 66]; + /// let context = [0x42u8, 1, 2, 3]; + /// let mut signature = [0u8; Ed448::SIG_SIZE]; + /// ed.sign_msg(&message, Some(&context), &mut signature).expect("Error with sign_msg()"); + /// ed.verify_msg_init(&signature, Some(&context), Ed448::ED448).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); + /// ``` + pub fn verify_msg_update(&mut self, din: &[u8]) -> Result<(), i32> { + let din_size = din.len() as u32; + let rc = unsafe { + ws::wc_ed448_verify_msg_update(din.as_ptr(), din_size, + &mut self.ws_key) + }; + if rc != 0 { + return Err(rc); + } + Ok(()) + } + + /// Finalize Ed448 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 + /// use wolfssl::wolfcrypt::random::RNG; + /// use wolfssl::wolfcrypt::ed448::Ed448; + /// let mut rng = RNG::new().expect("Error creating RNG"); + /// let mut ed = Ed448::generate(&mut rng).expect("Error with generate()"); + /// let message = [0x42u8, 33, 55, 66]; + /// let context = [0x42u8, 1, 2, 3]; + /// let mut signature = [0u8; Ed448::SIG_SIZE]; + /// ed.sign_msg(&message, Some(&context), &mut signature).expect("Error with sign_msg()"); + /// ed.verify_msg_init(&signature, Some(&context), Ed448::ED448).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); + /// ``` + pub fn verify_msg_final(&mut self, signature: &[u8]) -> Result { + let signature_size = signature.len() as u32; + let mut res = 0i32; + let rc = unsafe { + ws::wc_ed448_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 Ed448 key (57 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::ed448::Ed448; + /// let mut rng = RNG::new().expect("Error creating RNG"); + /// let ed = Ed448::generate(&mut rng).expect("Error with generate()"); + /// let key_size = ed.size().expect("Error with size()"); + /// assert_eq!(key_size, Ed448::KEY_SIZE); + /// ``` + pub fn size(&self) -> Result { + let rc = unsafe { ws::wc_ed448_size(&self.ws_key) }; + if rc < 0 { + return Err(rc); + } + Ok(rc as usize) + } + + /// Get the size of a private (including public) Ed448 key (114 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::ed448::Ed448; + /// let mut rng = RNG::new().expect("Error creating RNG"); + /// let ed = Ed448::generate(&mut rng).expect("Error with generate()"); + /// let priv_size = ed.priv_size().expect("Error with priv_size()"); + /// assert_eq!(priv_size, Ed448::PRV_KEY_SIZE); + /// ``` + pub fn priv_size(&self) -> Result { + let rc = unsafe { ws::wc_ed448_priv_size(&self.ws_key) }; + if rc < 0 { + return Err(rc); + } + Ok(rc as usize) + } + + /// Get the size of a public Ed448 key (57 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::ed448::Ed448; + /// let mut rng = RNG::new().expect("Error creating RNG"); + /// let ed = Ed448::generate(&mut rng).expect("Error with generate()"); + /// let pub_size = ed.pub_size().expect("Error with pub_size()"); + /// assert_eq!(pub_size, Ed448::PUB_KEY_SIZE); + /// ``` + pub fn pub_size(&self) -> Result { + let rc = unsafe { ws::wc_ed448_pub_size(&self.ws_key) }; + if rc < 0 { + return Err(rc); + } + Ok(rc as usize) + } + + /// Get the size of a Ed448 signature (114 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::ed448::Ed448; + /// let mut rng = RNG::new().expect("Error creating RNG"); + /// let ed = Ed448::generate(&mut rng).expect("Error with generate()"); + /// let sig_size = ed.sig_size().expect("Error with sig_size()"); + /// assert_eq!(sig_size, Ed448::SIG_SIZE); + /// ``` + pub fn sig_size(&self) -> Result { + let rc = unsafe { ws::wc_ed448_sig_size(&self.ws_key) }; + if rc < 0 { + return Err(rc); + } + Ok(rc as usize) + } +} + +impl Drop for Ed448 { + /// Safely free the wolfSSL resources. + fn drop(&mut self) { + unsafe { ws::wc_ed448_free(&mut self.ws_key); } + } +} diff --git a/wrapper/rust/wolfssl/tests/test_ed25519.rs b/wrapper/rust/wolfssl/tests/test_ed25519.rs index 39a7c41aa2..fd4beaf002 100644 --- a/wrapper/rust/wolfssl/tests/test_ed25519.rs +++ b/wrapper/rust/wolfssl/tests/test_ed25519.rs @@ -57,10 +57,10 @@ fn test_sign_verify() { assert!(signature_valid); let mut signature = [0u8; Ed25519::SIG_SIZE]; - ed.sign_msg_ex(&message, None, Ed25519::ED25519, &mut signature).expect("Error with sign_msg()"); + ed.sign_msg_ex(&message, None, Ed25519::ED25519, &mut signature).expect("Error with sign_msg_ex()"); assert_eq!(signature, expected_signature); - let signature_valid = ed.verify_msg_ex(&signature, &message, None, Ed25519::ED25519).expect("Error with verify_msg()"); + let signature_valid = ed.verify_msg_ex(&signature, &message, None, Ed25519::ED25519).expect("Error with verify_msg_ex()"); assert!(signature_valid); ed.verify_msg_init(&signature, None, Ed25519::ED25519).expect("Error with verify_msg_init()"); @@ -152,17 +152,17 @@ fn test_ph_sign_verify() { ed.import_private_key(&private_key, Some(&public_key)).expect("Error with import_private_key()"); let mut signature = [0u8; Ed25519::SIG_SIZE]; - ed.sign_msg_ph(&message, &context, &mut signature).expect("Error with sign_msg_ph()"); + ed.sign_msg_ph(&message, Some(&context), &mut signature).expect("Error with sign_msg_ph()"); assert_eq!(signature, expected_signature); - let signature_valid = ed.verify_msg_ph(&signature, &message, &context).expect("Error with verify_msg_ph()"); + let signature_valid = ed.verify_msg_ph(&signature, &message, Some(&context)).expect("Error with verify_msg_ph()"); assert!(signature_valid); let mut signature = [0u8; Ed25519::SIG_SIZE]; - ed.sign_hash_ph(&hash, &context, &mut signature).expect("Error with sign_hash_ph()"); + ed.sign_hash_ph(&hash, Some(&context), &mut signature).expect("Error with sign_hash_ph()"); assert_eq!(signature, expected_signature); - let signature_valid = ed.verify_hash_ph(&signature, &hash, &context).expect("Error with verify_hash_ph()"); + let signature_valid = ed.verify_hash_ph(&signature, &hash, Some(&context)).expect("Error with verify_hash_ph()"); assert!(signature_valid); } diff --git a/wrapper/rust/wolfssl/tests/test_ed448.rs b/wrapper/rust/wolfssl/tests/test_ed448.rs new file mode 100644 index 0000000000..08e5506a82 --- /dev/null +++ b/wrapper/rust/wolfssl/tests/test_ed448.rs @@ -0,0 +1,203 @@ +use wolfssl::wolfcrypt::random::RNG; +use wolfssl::wolfcrypt::ed448::*; + +#[test] +fn test_make_public() { + let mut rng = RNG::new().expect("Error creating RNG"); + let ed = Ed448::generate(&mut rng).expect("Error with generate()"); + let mut private = [0u8; Ed448::KEY_SIZE]; + ed.export_private_only(&mut private).expect("Error with export_private_only()"); + let mut ed = Ed448::new().expect("Error with new()"); + ed.import_private_only(&private).expect("Error with import_private_only()"); + let mut public = [0u8; Ed448::KEY_SIZE]; + ed.make_public(&mut public).expect("Error with make_public()"); +} + +#[test] +fn test_check_key() { + let mut rng = RNG::new().expect("Error creating RNG"); + let mut ed = Ed448::generate(&mut rng).expect("Error with generate()"); + ed.check_key().expect("Error with check_key()"); +} + +#[test] +fn test_sign_verify() { + let private_key = [ + 0xc4u8, 0xea, 0xb0, 0x5d, 0x35, 0x70, 0x07, 0xc6, + 0x32, 0xf3, 0xdb, 0xb4, 0x84, 0x89, 0x92, 0x4d, + 0x55, 0x2b, 0x08, 0xfe, 0x0c, 0x35, 0x3a, 0x0d, + 0x4a, 0x1f, 0x00, 0xac, 0xda, 0x2c, 0x46, 0x3a, + 0xfb, 0xea, 0x67, 0xc5, 0xe8, 0xd2, 0x87, 0x7c, + 0x5e, 0x3b, 0xc3, 0x97, 0xa6, 0x59, 0x94, 0x9e, + 0xf8, 0x02, 0x1e, 0x95, 0x4e, 0x0a, 0x12, 0x27, + 0x4e + ]; + let public_key = [ + 0x43u8, 0xba, 0x28, 0xf4, 0x30, 0xcd, 0xff, 0x45, + 0x6a, 0xe5, 0x31, 0x54, 0x5f, 0x7e, 0xcd, 0x0a, + 0xc8, 0x34, 0xa5, 0x5d, 0x93, 0x58, 0xc0, 0x37, + 0x2b, 0xfa, 0x0c, 0x6c, 0x67, 0x98, 0xc0, 0x86, + 0x6a, 0xea, 0x01, 0xeb, 0x00, 0x74, 0x28, 0x02, + 0xb8, 0x43, 0x8e, 0xa4, 0xcb, 0x82, 0x16, 0x9c, + 0x23, 0x51, 0x60, 0x62, 0x7b, 0x4c, 0x3a, 0x94, + 0x80 + ]; + let message = [0x03u8]; + let context = [0x66u8,0x6f,0x6f]; + let expected_signature = [ + 0xd4u8, 0xf8, 0xf6, 0x13, 0x17, 0x70, 0xdd, 0x46, + 0xf4, 0x08, 0x67, 0xd6, 0xfd, 0x5d, 0x50, 0x55, + 0xde, 0x43, 0x54, 0x1f, 0x8c, 0x5e, 0x35, 0xab, + 0xbc, 0xd0, 0x01, 0xb3, 0x2a, 0x89, 0xf7, 0xd2, + 0x15, 0x1f, 0x76, 0x47, 0xf1, 0x1d, 0x8c, 0xa2, + 0xae, 0x27, 0x9f, 0xb8, 0x42, 0xd6, 0x07, 0x21, + 0x7f, 0xce, 0x6e, 0x04, 0x2f, 0x68, 0x15, 0xea, + 0x00, 0x0c, 0x85, 0x74, 0x1d, 0xe5, 0xc8, 0xda, + 0x11, 0x44, 0xa6, 0xa1, 0xab, 0xa7, 0xf9, 0x6d, + 0xe4, 0x25, 0x05, 0xd7, 0xa7, 0x29, 0x85, 0x24, + 0xfd, 0xa5, 0x38, 0xfc, 0xcb, 0xbb, 0x75, 0x4f, + 0x57, 0x8c, 0x1c, 0xad, 0x10, 0xd5, 0x4d, 0x0d, + 0x54, 0x28, 0x40, 0x7e, 0x85, 0xdc, 0xbc, 0x98, + 0xa4, 0x91, 0x55, 0xc1, 0x37, 0x64, 0xe6, 0x6c, + 0x3c, 0x00 + ]; + + let mut ed = Ed448::new().expect("Error with new()"); + ed.import_private_key(&private_key, Some(&public_key)).expect("Error with import_private_key()"); + + let mut signature = [0u8; Ed448::SIG_SIZE]; + ed.sign_msg(&message, Some(&context), &mut signature).expect("Error with sign_msg()"); + assert_eq!(signature, expected_signature); + + let signature_valid = ed.verify_msg(&signature, &message, Some(&context)).expect("Error with verify_msg()"); + assert!(signature_valid); + + let mut signature = [0u8; Ed448::SIG_SIZE]; + ed.sign_msg_ex(&message, Some(&context), Ed448::ED448, &mut signature).expect("Error with sign_msg_ex()"); + assert_eq!(signature, expected_signature); + + let signature_valid = ed.verify_msg_ex(&signature, &message, Some(&context), Ed448::ED448).expect("Error with verify_msg_ex()"); + assert!(signature_valid); + + ed.verify_msg_init(&signature, Some(&context), Ed448::ED448).expect("Error with verify_msg_init()"); + ed.verify_msg_update(&message).expect("Error with verify_msg_update()"); + let signature_valid = ed.verify_msg_final(&signature).expect("Error with verify_msg_final()"); + assert!(signature_valid); +} + +#[test] +fn test_ph_sign_verify() { + let private_key = [ + 0x83u8, 0x3f, 0xe6, 0x24, 0x09, 0x23, 0x7b, 0x9d, + 0x62, 0xec, 0x77, 0x58, 0x75, 0x20, 0x91, 0x1e, + 0x9a, 0x75, 0x9c, 0xec, 0x1d, 0x19, 0x75, 0x5b, + 0x7d, 0xa9, 0x01, 0xb9, 0x6d, 0xca, 0x3d, 0x42, + 0xef, 0x78, 0x22, 0xe0, 0xd5, 0x10, 0x41, 0x27, + 0xdc, 0x05, 0xd6, 0xdb, 0xef, 0xde, 0x69, 0xe3, + 0xab, 0x2c, 0xec, 0x7c, 0x86, 0x7c, 0x6e, 0x2c, + 0x49 + ]; + let public_key = [ + 0x25u8, 0x9b, 0x71, 0xc1, 0x9f, 0x83, 0xef, 0x77, + 0xa7, 0xab, 0xd2, 0x65, 0x24, 0xcb, 0xdb, 0x31, + 0x61, 0xb5, 0x90, 0xa4, 0x8f, 0x7d, 0x17, 0xde, + 0x3e, 0xe0, 0xba, 0x9c, 0x52, 0xbe, 0xb7, 0x43, + 0xc0, 0x94, 0x28, 0xa1, 0x31, 0xd6, 0xb1, 0xb5, + 0x73, 0x03, 0xd9, 0x0d, 0x81, 0x32, 0xc2, 0x76, + 0xd5, 0xed, 0x3d, 0x5d, 0x01, 0xc0, 0xf5, 0x38, + 0x80 + ]; + let message = [0x61u8,0x62,0x63]; + let context = [0x66u8,0x6f,0x6f]; + let hash = [ + 0x48u8, 0x33, 0x66, 0x60, 0x13, 0x60, 0xa8, 0x77, + 0x1c, 0x68, 0x63, 0x08, 0x0c, 0xc4, 0x11, 0x4d, + 0x8d, 0xb4, 0x45, 0x30, 0xf8, 0xf1, 0xe1, 0xee, + 0x4f, 0x94, 0xea, 0x37, 0xe7, 0x8b, 0x57, 0x39, + 0xd5, 0xa1, 0x5b, 0xef, 0x18, 0x6a, 0x53, 0x86, + 0xc7, 0x57, 0x44, 0xc0, 0x52, 0x7e, 0x1f, 0xaa, + 0x9f, 0x87, 0x26, 0xe4, 0x62, 0xa1, 0x2a, 0x4f, + 0xeb, 0x06, 0xbd, 0x88, 0x01, 0xe7, 0x51, 0xe4 + ]; + let expected_signature = [ + 0xc3u8, 0x22, 0x99, 0xd4, 0x6e, 0xc8, 0xff, 0x02, + 0xb5, 0x45, 0x40, 0x98, 0x28, 0x14, 0xdc, 0xe9, + 0xa0, 0x58, 0x12, 0xf8, 0x19, 0x62, 0xb6, 0x49, + 0xd5, 0x28, 0x09, 0x59, 0x16, 0xa2, 0xaa, 0x48, + 0x10, 0x65, 0xb1, 0x58, 0x04, 0x23, 0xef, 0x92, + 0x7e, 0xcf, 0x0a, 0xf5, 0x88, 0x8f, 0x90, 0xda, + 0x0f, 0x6a, 0x9a, 0x85, 0xad, 0x5d, 0xc3, 0xf2, + 0x80, 0xd9, 0x12, 0x24, 0xba, 0x99, 0x11, 0xa3, + 0x65, 0x3d, 0x00, 0xe4, 0x84, 0xe2, 0xce, 0x23, + 0x25, 0x21, 0x48, 0x1c, 0x86, 0x58, 0xdf, 0x30, + 0x4b, 0xb7, 0x74, 0x5a, 0x73, 0x51, 0x4c, 0xdb, + 0x9b, 0xf3, 0xe1, 0x57, 0x84, 0xab, 0x71, 0x28, + 0x4f, 0x8d, 0x07, 0x04, 0xa6, 0x08, 0xc5, 0x4a, + 0x6b, 0x62, 0xd9, 0x7b, 0xeb, 0x51, 0x1d, 0x13, + 0x21, 0x00 + ]; + + let mut ed = Ed448::new().expect("Error with new()"); + ed.import_private_key(&private_key, Some(&public_key)).expect("Error with import_private_key()"); + + let mut signature = [0u8; Ed448::SIG_SIZE]; + ed.sign_msg_ph(&message, Some(&context), &mut signature).expect("Error with sign_msg_ph()"); + assert_eq!(signature, expected_signature); + + let signature_valid = ed.verify_msg_ph(&signature, &message, Some(&context)).expect("Error with verify_msg_ph()"); + assert!(signature_valid); + + let mut signature = [0u8; Ed448::SIG_SIZE]; + ed.sign_hash_ph(&hash, Some(&context), &mut signature).expect("Error with sign_hash_ph()"); + assert_eq!(signature, expected_signature); + + let signature_valid = ed.verify_hash_ph(&signature, &hash, Some(&context)).expect("Error with verify_hash_ph()"); + assert!(signature_valid); +} + +#[test] +fn test_import_export() { + let mut rng = RNG::new().expect("Error creating RNG"); + let ed = Ed448::generate(&mut rng).expect("Error with generate()"); + + let mut private = [0u8; Ed448::PRV_KEY_SIZE]; + let mut public = [0u8; Ed448::PUB_KEY_SIZE]; + ed.export_key(&mut private, &mut public).expect("Error with export_key()"); + + let mut public2 = [0u8; Ed448::PUB_KEY_SIZE]; + ed.export_public(&mut public2).expect("Error with export_public()"); + assert_eq!(public2, public); + + let mut private2 = [0u8; Ed448::PRV_KEY_SIZE]; + ed.export_private(&mut private2).expect("Error with export_private()"); + assert_eq!(private2, private); + + let mut private_only = [0u8; Ed448::KEY_SIZE]; + ed.export_private_only(&mut private_only).expect("Error with export_private_only()"); + + let mut ed = Ed448::new().expect("Error with new()"); + ed.import_private_key_ex(&private, Some(&public), false).expect("Error with import_private_key_ex()"); + + let mut ed = Ed448::new().expect("Error with new()"); + ed.import_private_only(&private_only).expect("Error with import_private_only()"); + ed.import_public(&public).expect("Error with import_public()"); + ed.import_public_ex(&public, false).expect("Error with import_public_ex()"); +} + +#[test] +fn test_sizes() { + let mut rng = RNG::new().expect("Error creating RNG"); + let ed = Ed448::generate(&mut rng).expect("Error with generate()"); + + let size = ed.size().expect("Error with size()"); + assert_eq!(size, Ed448::KEY_SIZE); + + let size = ed.priv_size().expect("Error with priv_size()"); + assert_eq!(size, Ed448::PRV_KEY_SIZE); + + let size = ed.pub_size().expect("Error with pub_size()"); + assert_eq!(size, Ed448::PUB_KEY_SIZE); + + let size = ed.sig_size().expect("Error with sig_size()"); + assert_eq!(size, Ed448::SIG_SIZE); +}