From 7cbcd0b00d64d8da05c0bb77b0b8038c621729a1 Mon Sep 17 00:00:00 2001 From: Josh Holtrop Date: Tue, 28 Oct 2025 17:20:12 -0400 Subject: [PATCH] Rust wrapper: add wolfssl::wolfcrypt::ed25519 module --- doc/dox_comments/header_files/ed25519.h | 32 +- wolfcrypt/src/asn.c | 6 +- wolfcrypt/src/ed25519.c | 16 +- wolfssl/wolfcrypt/asn_public.h | 6 +- wolfssl/wolfcrypt/ed25519.h | 16 +- wrapper/rust/include.am | 2 + wrapper/rust/wolfssl/src/wolfcrypt.rs | 1 + wrapper/rust/wolfssl/src/wolfcrypt/ed25519.rs | 1237 +++++++++++++++++ wrapper/rust/wolfssl/tests/test_ed25519.rs | 214 +++ 9 files changed, 1493 insertions(+), 37 deletions(-) create mode 100644 wrapper/rust/wolfssl/src/wolfcrypt/ed25519.rs create mode 100644 wrapper/rust/wolfssl/tests/test_ed25519.rs diff --git a/doc/dox_comments/header_files/ed25519.h b/doc/dox_comments/header_files/ed25519.h index a1d0064db..d165da255 100644 --- a/doc/dox_comments/header_files/ed25519.h +++ b/doc/dox_comments/header_files/ed25519.h @@ -440,8 +440,8 @@ int wc_ed25519ctx_verify_msg(const byte* sig, word32 siglen, const byte* msg, byte hash[] = { initialize with SHA-512 hash of message }; byte context[] = { initialize with context of signature }; // initialize key with received public key - ret = wc_ed25519ph_verify_hash(sig, sizeof(sig), msg, sizeof(msg), - &verified, &key, ); + ret = wc_ed25519ph_verify_hash(sig, sizeof(sig), hash, sizeof(hash), + &verified, &key, context, sizeof(context)); if (ret < 0) { // error performing verification } else if (verified == 0) @@ -496,8 +496,8 @@ int wc_ed25519ph_verify_hash(const byte* sig, word32 siglen, const byte* hash, byte msg[] = { initialize with message }; byte context[] = { initialize with context of signature }; // initialize key with received public key - ret = wc_ed25519ctx_verify_msg(sig, sizeof(sig), msg, sizeof(msg), - &verified, &key, ); + ret = wc_ed25519ph_verify_msg(sig, sizeof(sig), msg, sizeof(msg), + &verified, &key, context, sizeof(context)); if (ret < 0) { // error performing verification } else if (verified == 0) @@ -506,8 +506,8 @@ int wc_ed25519ph_verify_hash(const byte* sig, word32 siglen, const byte* hash, \endcode \sa wc_ed25519_verify_msg + \sa wc_ed25519ctx_verify_msg \sa wc_ed25519ph_verify_hash - \sa wc_ed25519ph_verify_msg \sa wc_ed25519_sign_msg */ @@ -747,7 +747,7 @@ int wc_ed25519_import_private_key(const byte* priv, word32 privSz, ed25519_key key; wc_ed25519_init_key(&key); - ret = wc_ed25519_import_private_key(priv, sizeof(priv), pub, sizeof(pub), + ret = wc_ed25519_import_private_key_ex(priv, sizeof(priv), pub, sizeof(pub), &key, 1); if (ret != 0) { // error importing key @@ -774,7 +774,7 @@ int wc_ed25519_import_private_key_ex(const byte* priv, word32 privSz, \return 0 Returned upon successfully exporting the public key. \return BAD_FUNC_ARG Returned if any of the input values evaluate to NULL. \return BUFFER_E Returned if the buffer provided is not large enough to - store the private key. Upon returning this error, the function sets the + store the public key. Upon returning this error, the function sets the size required in outLen. \param [in] key Pointer to an ed25519_key structure from which to export the @@ -801,10 +801,11 @@ int wc_ed25519_import_private_key_ex(const byte* priv, word32 privSz, \sa wc_ed25519_import_public \sa wc_ed25519_import_public_ex + \sa wc_ed25519_export_private \sa wc_ed25519_export_private_only */ -int wc_ed25519_export_public(ed25519_key* key, byte* out, word32* outLen); +int wc_ed25519_export_public(const ed25519_key* key, byte* out, word32* outLen); /*! \ingroup ED25519 @@ -840,11 +841,12 @@ int wc_ed25519_export_public(ed25519_key* key, byte* out, word32* outLen); \endcode \sa wc_ed25519_export_public + \sa wc_ed25519_export_private \sa wc_ed25519_import_private_key \sa wc_ed25519_import_private_key_ex */ -int wc_ed25519_export_private_only(ed25519_key* key, byte* out, word32* outLen); +int wc_ed25519_export_private_only(const ed25519_key* key, byte* out, word32* outLen); /*! \ingroup ED25519 @@ -888,7 +890,7 @@ int wc_ed25519_export_private_only(ed25519_key* key, byte* out, word32* outLen); \sa wc_ed25519_export_private_only */ -int wc_ed25519_export_private(ed25519_key* key, byte* out, word32* outLen); +int wc_ed25519_export_private(const ed25519_key* key, byte* out, word32* outLen); /*! \ingroup ED25519 @@ -935,7 +937,7 @@ int wc_ed25519_export_private(ed25519_key* key, byte* out, word32* outLen); \sa wc_ed25519_export_public */ -int wc_ed25519_export_key(ed25519_key* key, +int wc_ed25519_export_key(const ed25519_key* key, byte* priv, word32 *privSz, byte* pub, word32 *pubSz); @@ -999,7 +1001,7 @@ int wc_ed25519_check_key(ed25519_key* key); \sa wc_ed25519_make_key */ -int wc_ed25519_size(ed25519_key* key); +int wc_ed25519_size(const ed25519_key* key); /*! \ingroup ED25519 @@ -1028,7 +1030,7 @@ int wc_ed25519_size(ed25519_key* key); \sa wc_ed25519_pub_size */ -int wc_ed25519_priv_size(ed25519_key* key); +int wc_ed25519_priv_size(const ed25519_key* key); /*! \ingroup ED25519 @@ -1056,7 +1058,7 @@ int wc_ed25519_priv_size(ed25519_key* key); \sa wc_ed25519_priv_size */ -int wc_ed25519_pub_size(ed25519_key* key); +int wc_ed25519_pub_size(const ed25519_key* key); /*! \ingroup ED25519 @@ -1084,4 +1086,4 @@ int wc_ed25519_pub_size(ed25519_key* key); \sa wc_ed25519_sign_msg */ -int wc_ed25519_sig_size(ed25519_key* key); +int wc_ed25519_sig_size(const ed25519_key* key); diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 0edc7f556..436980083 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -13499,7 +13499,7 @@ int SetAsymKeyDerPublic(const byte* pubKey, word32 pubKeyLen, * @return BAD_FUNC_ARG when key is NULL. * @return MEMORY_E when dynamic memory allocation failed. */ -int wc_Ed25519PublicKeyToDer(ed25519_key* key, byte* output, word32 inLen, +int wc_Ed25519PublicKeyToDer(const ed25519_key* key, byte* output, word32 inLen, int withAlg) { int ret; @@ -37770,7 +37770,7 @@ int SetAsymKeyDer(const byte* privKey, word32 privKeyLen, #if defined(HAVE_ED25519) && defined(HAVE_ED25519_KEY_EXPORT) /* Write a Private ED25519 key, including public to DER format, * length on success else < 0 */ -int wc_Ed25519KeyToDer(ed25519_key* key, byte* output, word32 inLen) +int wc_Ed25519KeyToDer(const ed25519_key* key, byte* output, word32 inLen) { if (key == NULL) { return BAD_FUNC_ARG; @@ -37781,7 +37781,7 @@ int wc_Ed25519KeyToDer(ed25519_key* key, byte* output, word32 inLen) /* Write only private ED25519 key to DER format, * length on success else < 0 */ -int wc_Ed25519PrivateKeyToDer(ed25519_key* key, byte* output, word32 inLen) +int wc_Ed25519PrivateKeyToDer(const ed25519_key* key, byte* output, word32 inLen) { if (key == NULL) { return BAD_FUNC_ARG; diff --git a/wolfcrypt/src/ed25519.c b/wolfcrypt/src/ed25519.c index 7cc029b08..69c7a1b30 100644 --- a/wolfcrypt/src/ed25519.c +++ b/wolfcrypt/src/ed25519.c @@ -1117,7 +1117,7 @@ void wc_ed25519_free(ed25519_key* key) to the final output length. returns 0 on success */ -int wc_ed25519_export_public(ed25519_key* key, byte* out, word32* outLen) +int wc_ed25519_export_public(const ed25519_key* key, byte* out, word32* outLen) { /* sanity check on arguments */ if (key == NULL || out == NULL || outLen == NULL) @@ -1343,7 +1343,7 @@ int wc_ed25519_import_private_key(const byte* priv, word32 privSz, to the final output length. returns 0 on success */ -int wc_ed25519_export_private_only(ed25519_key* key, byte* out, word32* outLen) +int wc_ed25519_export_private_only(const ed25519_key* key, byte* out, word32* outLen) { /* sanity checks on arguments */ if (key == NULL || out == NULL || outLen == NULL) @@ -1366,7 +1366,7 @@ int wc_ed25519_export_private_only(ed25519_key* key, byte* out, word32* outLen) to the final output length. returns 0 on success */ -int wc_ed25519_export_private(ed25519_key* key, byte* out, word32* outLen) +int wc_ed25519_export_private(const ed25519_key* key, byte* out, word32* outLen) { /* sanity checks on arguments */ if (key == NULL || out == NULL || outLen == NULL) @@ -1386,7 +1386,7 @@ int wc_ed25519_export_private(ed25519_key* key, byte* out, word32* outLen) /* export full private key and public key return 0 on success */ -int wc_ed25519_export_key(ed25519_key* key, +int wc_ed25519_export_key(const ed25519_key* key, byte* priv, word32 *privSz, byte* pub, word32 *pubSz) { @@ -1487,7 +1487,7 @@ int wc_ed25519_check_key(ed25519_key* key) } /* returns the private key size (secret only) in bytes */ -int wc_ed25519_size(ed25519_key* key) +int wc_ed25519_size(const ed25519_key* key) { if (key == NULL) return BAD_FUNC_ARG; @@ -1496,7 +1496,7 @@ int wc_ed25519_size(ed25519_key* key) } /* returns the private key size (secret + public) in bytes */ -int wc_ed25519_priv_size(ed25519_key* key) +int wc_ed25519_priv_size(const ed25519_key* key) { if (key == NULL) return BAD_FUNC_ARG; @@ -1505,7 +1505,7 @@ int wc_ed25519_priv_size(ed25519_key* key) } /* returns the compressed key size in bytes (public key) */ -int wc_ed25519_pub_size(ed25519_key* key) +int wc_ed25519_pub_size(const ed25519_key* key) { if (key == NULL) return BAD_FUNC_ARG; @@ -1514,7 +1514,7 @@ int wc_ed25519_pub_size(ed25519_key* key) } /* returns the size of signature in bytes */ -int wc_ed25519_sig_size(ed25519_key* key) +int wc_ed25519_sig_size(const ed25519_key* key) { if (key == NULL) return BAD_FUNC_ARG; diff --git a/wolfssl/wolfcrypt/asn_public.h b/wolfssl/wolfcrypt/asn_public.h index 3bf071dd5..685f80699 100644 --- a/wolfssl/wolfcrypt/asn_public.h +++ b/wolfssl/wolfcrypt/asn_public.h @@ -728,11 +728,11 @@ WOLFSSL_API int wc_Ed25519PublicKeyDecode(const byte* input, word32* inOutIdx, ed25519_key* key, word32 inSz); #endif #ifdef HAVE_ED25519_KEY_EXPORT -WOLFSSL_API int wc_Ed25519KeyToDer(ed25519_key* key, byte* output, +WOLFSSL_API int wc_Ed25519KeyToDer(const ed25519_key* key, byte* output, word32 inLen); -WOLFSSL_API int wc_Ed25519PrivateKeyToDer(ed25519_key* key, byte* output, +WOLFSSL_API int wc_Ed25519PrivateKeyToDer(const ed25519_key* key, byte* output, word32 inLen); -WOLFSSL_API int wc_Ed25519PublicKeyToDer(ed25519_key* key, byte* output, +WOLFSSL_API int wc_Ed25519PublicKeyToDer(const ed25519_key* key, byte* output, word32 inLen, int withAlg); #endif #endif /* HAVE_ED25519 */ diff --git a/wolfssl/wolfcrypt/ed25519.h b/wolfssl/wolfcrypt/ed25519.h index 1abba3a31..06a22cdf7 100644 --- a/wolfssl/wolfcrypt/ed25519.h +++ b/wolfssl/wolfcrypt/ed25519.h @@ -207,13 +207,13 @@ int wc_ed25519_import_private_key_ex(const byte* priv, word32 privSz, #ifdef HAVE_ED25519_KEY_EXPORT WOLFSSL_API -int wc_ed25519_export_public(ed25519_key* key, byte* out, word32* outLen); +int wc_ed25519_export_public(const ed25519_key* key, byte* out, word32* outLen); WOLFSSL_API -int wc_ed25519_export_private_only(ed25519_key* key, byte* out, word32* outLen); +int wc_ed25519_export_private_only(const ed25519_key* key, byte* out, word32* outLen); WOLFSSL_API -int wc_ed25519_export_private(ed25519_key* key, byte* out, word32* outLen); +int wc_ed25519_export_private(const ed25519_key* key, byte* out, word32* outLen); WOLFSSL_API -int wc_ed25519_export_key(ed25519_key* key, +int wc_ed25519_export_key(const ed25519_key* key, byte* priv, word32 *privSz, byte* pub, word32 *pubSz); #endif /* HAVE_ED25519_KEY_EXPORT */ @@ -223,13 +223,13 @@ int wc_ed25519_check_key(ed25519_key* key); /* size helper */ WOLFSSL_API -int wc_ed25519_size(ed25519_key* key); +int wc_ed25519_size(const ed25519_key* key); WOLFSSL_API -int wc_ed25519_priv_size(ed25519_key* key); +int wc_ed25519_priv_size(const ed25519_key* key); WOLFSSL_API -int wc_ed25519_pub_size(ed25519_key* key); +int wc_ed25519_pub_size(const ed25519_key* key); WOLFSSL_API -int wc_ed25519_sig_size(ed25519_key* key); +int wc_ed25519_sig_size(const ed25519_key* key); #ifdef __cplusplus } /* extern "C" */ diff --git a/wrapper/rust/include.am b/wrapper/rust/include.am index 2b8ca9c46..dc1e46284 100644 --- a/wrapper/rust/include.am +++ b/wrapper/rust/include.am @@ -20,6 +20,7 @@ EXTRA_DIST += wrapper/rust/wolfssl/src/wolfcrypt/aes.rs 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/hkdf.rs EXTRA_DIST += wrapper/rust/wolfssl/src/wolfcrypt/hmac.rs EXTRA_DIST += wrapper/rust/wolfssl/src/wolfcrypt/kdf.rs @@ -31,6 +32,7 @@ EXTRA_DIST += wrapper/rust/wolfssl/tests/test_aes.rs 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_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 5e02b45d4..c5a0f3b49 100644 --- a/wrapper/rust/wolfssl/src/wolfcrypt.rs +++ b/wrapper/rust/wolfssl/src/wolfcrypt.rs @@ -22,6 +22,7 @@ pub mod aes; pub mod cmac; pub mod dh; pub mod ecc; +pub mod ed25519; 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 new file mode 100644 index 000000000..e65cc73fa --- /dev/null +++ b/wrapper/rust/wolfssl/src/wolfcrypt/ed25519.rs @@ -0,0 +1,1237 @@ +/* + * 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 +25519 (Ed25519) 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 `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: ws::ed25519_key, +} + +impl Ed25519 { + /** Size of private key only. */ + pub const KEY_SIZE: usize = ws::ED25519_KEY_SIZE as usize; + /** Size of signature. */ + pub const SIG_SIZE: usize = ws::ED25519_SIG_SIZE as usize; + /** Compressed public key size. */ + pub const PUB_KEY_SIZE: usize = ws::ED25519_PUB_KEY_SIZE as usize; + /** Size of both private and public key. */ + pub const PRV_KEY_SIZE: usize = ws::ED25519_PRV_KEY_SIZE as usize; + + pub const ED25519: u8 = ws::Ed25519 as u8; + pub const ED25519CTX: u8 = ws::Ed25519ctx as u8; + pub const ED25519PH: u8 = ws::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: &mut RNG) -> Result { + let mut ws_key: MaybeUninit = MaybeUninit::uninit(); + let rc = unsafe { ws::wc_ed25519_init(ws_key.as_mut_ptr()) }; + if rc != 0 { + return Err(rc); + } + let ws_key = unsafe { ws_key.assume_init() }; + let mut ed25519 = Ed25519 { ws_key }; + let rc = unsafe { + ws::wc_ed25519_make_key(&mut rng.wc_rng, + ws::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 { + let mut ws_key: MaybeUninit = MaybeUninit::uninit(); + let rc = unsafe { ws::wc_ed25519_init(ws_key.as_mut_ptr()) }; + 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 { ws::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 + /// 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()"); + /// ``` + 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_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 + /// 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()"); + /// ``` + pub fn export_public(&self, public: &mut [u8]) -> Result<(), i32> { + let mut public_size = public.len() as u32; + let rc = unsafe { + ws::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 + /// 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()"); + /// ``` + pub fn export_private(&self, keyout: &mut [u8]) -> Result<(), i32> { + let mut keyout_size = keyout.len() as u32; + let rc = unsafe { + ws::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 + /// 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()"); + /// ``` + pub fn export_private_only(&self, private: &mut [u8]) -> Result<(), i32> { + let mut private_size = private.len() as u32; + let rc = unsafe { + ws::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 + /// 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()"); + /// ``` + pub fn import_public(&mut self, public: &[u8]) -> Result<(), i32> { + let public_size = public.len() as u32; + let rc = unsafe { + ws::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 + /// 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()"); + /// ``` + 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_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 + /// 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()"); + /// ``` + pub fn import_private_only(&mut self, private: &[u8]) -> Result<(), i32> { + let private_size = private.len() as u32; + let rc = unsafe { + ws::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 + /// 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()"); + /// ``` + 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_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 + /// 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()"); + /// ``` + 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_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 = pubkey.len() as u32; + let rc = unsafe { + ws::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 + /// 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()"); + /// ``` + pub fn sign_msg(&mut self, message: &[u8], signature: &mut [u8]) -> Result { + let message_size = message.len() as u32; + let mut signature_size = signature.len() as u32; + let rc = unsafe { + ws::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 + /// 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()"); + /// ``` + pub fn sign_msg_ctx(&mut self, message: &[u8], context: &[u8], signature: &mut [u8]) -> Result { + let message_size = message.len() as u32; + let context_size = context.len() as u8; + let mut signature_size = signature.len() as u32; + let rc = unsafe { + ws::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`: 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::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, context, &mut signature).expect("Error with sign_hash_ph()"); + /// ``` + pub fn sign_hash_ph(&mut self, hash: &[u8], context: &[u8], signature: &mut [u8]) -> Result { + let hash_size = hash.len() as u32; + let 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) + }; + 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`: 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::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, context, &mut signature).expect("Error with sign_msg_ph()"); + /// ``` + pub fn sign_msg_ph(&mut self, message: &[u8], context: &[u8], signature: &mut [u8]) -> Result { + let message_size = message.len() as u32; + let 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) + }; + 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 + /// 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()"); + /// ``` + 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_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 + /// 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); + /// ``` + pub fn verify_msg(&mut self, signature: &[u8], message: &[u8]) -> Result { + let signature_size = signature.len() as u32; + let message_size = message.len() as u32; + let mut res = 0i32; + let rc = unsafe { + ws::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 + /// 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); + /// ``` + pub fn verify_msg_ctx(&mut self, signature: &[u8], message: &[u8], context: &[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 res = 0i32; + let rc = unsafe { + ws::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`: 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::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, 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()"); + /// assert!(signature_valid); + /// ``` + pub fn verify_hash_ph(&mut self, signature: &[u8], hash: &[u8], context: &[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 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) + }; + 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`: 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::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, 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()"); + /// assert!(signature_valid); + /// ``` + pub fn verify_msg_ph(&mut self, signature: &[u8], message: &[u8], context: &[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 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) + }; + 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 + /// 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); + /// ``` + 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_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 + /// 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); + /// ``` + 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_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 + /// 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); + /// ``` + pub fn verify_msg_update(&mut self, din: &[u8]) -> Result<(), i32> { + let din_size = din.len() as u32; + let rc = unsafe { + ws::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 + /// 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); + /// ``` + 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_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 { + let rc = unsafe { ws::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 { + let rc = unsafe { ws::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 { + let rc = unsafe { ws::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 { + let rc = unsafe { ws::wc_ed25519_sig_size(&self.ws_key) }; + if rc < 0 { + return Err(rc); + } + Ok(rc as usize) + } +} + +impl Drop for Ed25519 { + /// Safely free the wolfSSL resources. + fn drop(&mut self) { + unsafe { ws::wc_ed25519_free(&mut self.ws_key); } + } +} diff --git a/wrapper/rust/wolfssl/tests/test_ed25519.rs b/wrapper/rust/wolfssl/tests/test_ed25519.rs new file mode 100644 index 000000000..39a7c41aa --- /dev/null +++ b/wrapper/rust/wolfssl/tests/test_ed25519.rs @@ -0,0 +1,214 @@ +use wolfssl::wolfcrypt::random::RNG; +use wolfssl::wolfcrypt::ed25519::*; + +#[test] +fn test_make_public() { + 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()"); +} + +#[test] +fn test_check_key() { + 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()"); +} + +#[test] +fn test_sign_verify() { + let private_key = [ + 0xc5u8,0xaa,0x8d,0xf4,0x3f,0x9f,0x83,0x7b, + 0xed,0xb7,0x44,0x2f,0x31,0xdc,0xb7,0xb1, + 0x66,0xd3,0x85,0x35,0x07,0x6f,0x09,0x4b, + 0x85,0xce,0x3a,0x2e,0x0b,0x44,0x58,0xf7 + ]; + let public_key = [ + 0xfcu8,0x51,0xcd,0x8e,0x62,0x18,0xa1,0xa3, + 0x8d,0xa4,0x7e,0xd0,0x02,0x30,0xf0,0x58, + 0x08,0x16,0xed,0x13,0xba,0x33,0x03,0xac, + 0x5d,0xeb,0x91,0x15,0x48,0x90,0x80,0x25 + ]; + let message = [0xAFu8, 0x82]; + let expected_signature = [ + 0x62u8,0x91,0xd6,0x57,0xde,0xec,0x24,0x02, + 0x48,0x27,0xe6,0x9c,0x3a,0xbe,0x01,0xa3, + 0x0c,0xe5,0x48,0xa2,0x84,0x74,0x3a,0x44, + 0x5e,0x36,0x80,0xd7,0xdb,0x5a,0xc3,0xac, + 0x18,0xff,0x9b,0x53,0x8d,0x16,0xf2,0x90, + 0xae,0x67,0xf7,0x60,0x98,0x4d,0xc6,0x59, + 0x4a,0x7c,0x15,0xe9,0x71,0x6e,0xd2,0x8d, + 0xc0,0x27,0xbe,0xce,0xea,0x1e,0xc4,0x0a + ]; + + let mut ed = Ed25519::new().expect("Error with new()"); + 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(&message, &mut signature).expect("Error with sign_msg()"); + assert_eq!(signature, expected_signature); + + let signature_valid = ed.verify_msg(&signature, &message).expect("Error with verify_msg()"); + 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()"); + assert_eq!(signature, expected_signature); + + let signature_valid = ed.verify_msg_ex(&signature, &message, None, Ed25519::ED25519).expect("Error with verify_msg()"); + assert!(signature_valid); + + ed.verify_msg_init(&signature, None, Ed25519::ED25519).expect("Error with verify_msg_init()"); + ed.verify_msg_update(&message[0..1]).expect("Error with verify_msg_update()"); + ed.verify_msg_update(&message[1..2]).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_ctx_sign_verify() { + let private_key = [ + 0x03u8,0x05,0x33,0x4e,0x38,0x1a,0xf7,0x8f, + 0x14,0x1c,0xb6,0x66,0xf6,0x19,0x9f,0x57, + 0xbc,0x34,0x95,0x33,0x5a,0x25,0x6a,0x95, + 0xbd,0x2a,0x55,0xbf,0x54,0x66,0x63,0xf6 + ]; + let public_key = [ + 0xdfu8,0xc9,0x42,0x5e,0x4f,0x96,0x8f,0x7f, + 0x0c,0x29,0xf0,0x25,0x9c,0xf5,0xf9,0xae, + 0xd6,0x85,0x1c,0x2b,0xb4,0xad,0x8b,0xfb, + 0x86,0x0c,0xfe,0xe0,0xab,0x24,0x82,0x92 + ]; + let message = [ + 0xf7u8,0x26,0x93,0x6d,0x19,0xc8,0x00,0x49, + 0x4e,0x3f,0xda,0xff,0x20,0xb2,0x76,0xa8 + ]; + let context = [0x66u8,0x6f,0x6f]; + let expected_signature = [ + 0x55u8,0xa4,0xcc,0x2f,0x70,0xa5,0x4e,0x04, + 0x28,0x8c,0x5f,0x4c,0xd1,0xe4,0x5a,0x7b, + 0xb5,0x20,0xb3,0x62,0x92,0x91,0x18,0x76, + 0xca,0xda,0x73,0x23,0x19,0x8d,0xd8,0x7a, + 0x8b,0x36,0x95,0x0b,0x95,0x13,0x00,0x22, + 0x90,0x7a,0x7f,0xb7,0xc4,0xe9,0xb2,0xd5, + 0xf6,0xcc,0xa6,0x85,0xa5,0x87,0xb4,0xb2, + 0x1f,0x4b,0x88,0x8e,0x4e,0x7e,0xdb,0x0d + ]; + + let mut ed = Ed25519::new().expect("Error with new()"); + 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_ctx(&message, &context, &mut signature).expect("Error with sign_msg_ctx()"); + assert_eq!(signature, expected_signature); + + let signature_valid = ed.verify_msg_ctx(&signature, &message, &context).expect("Error with verify_msg_ctx()"); + 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 + ]; + let public_key = [ + 0xecu8,0x17,0x2b,0x93,0xad,0x5e,0x56,0x3b, + 0xf4,0x93,0x2c,0x70,0xe1,0x24,0x50,0x34, + 0xc3,0x54,0x67,0xef,0x2e,0xfd,0x4d,0x64, + 0xeb,0xf8,0x19,0x68,0x34,0x67,0xe2,0xbf + ]; + let message = [0x61u8,0x62,0x63]; + let context = [0x66u8,0x6f,0x6f]; + 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 expected_signature = [ + 0xe0u8,0x39,0x70,0x2b,0x4c,0x25,0x95,0xa6, + 0xa5,0x41,0xac,0x85,0x09,0x23,0x6e,0x29, + 0x90,0x47,0x47,0x95,0x33,0x0c,0x9b,0x34, + 0xa7,0x5f,0x58,0xa6,0x60,0x12,0x9e,0x08, + 0xfd,0x73,0x69,0x43,0xfb,0x19,0x43,0xa5, + 0x57,0x20,0xb9,0xe0,0x95,0x7b,0x1e,0xd6, + 0x73,0x48,0x16,0x61,0x9f,0x13,0x88,0xf4, + 0x3f,0x73,0xe6,0xe3,0xba,0xa8,0x1c,0x0e + ]; + + let mut ed = Ed25519::new().expect("Error with new()"); + 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()"); + assert_eq!(signature, expected_signature); + + let signature_valid = ed.verify_msg_ph(&signature, &message, &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()"); + assert_eq!(signature, expected_signature); + + let signature_valid = ed.verify_hash_ph(&signature, &hash, &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 = 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 public2 = [0u8; Ed25519::PUB_KEY_SIZE]; + ed.export_public(&mut public2).expect("Error with export_public()"); + assert_eq!(public2, public); + + let mut private2 = [0u8; Ed25519::PRV_KEY_SIZE]; + ed.export_private(&mut private2).expect("Error with export_private()"); + assert_eq!(private2, private); + + 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_key_ex(&private, Some(&public), false).expect("Error with import_private_key_ex()"); + + let mut ed = Ed25519::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 = Ed25519::generate(&mut rng).expect("Error with generate()"); + + let size = ed.size().expect("Error with size()"); + assert_eq!(size, Ed25519::KEY_SIZE); + + let size = ed.priv_size().expect("Error with priv_size()"); + assert_eq!(size, Ed25519::PRV_KEY_SIZE); + + let size = ed.pub_size().expect("Error with pub_size()"); + assert_eq!(size, Ed25519::PUB_KEY_SIZE); + + let size = ed.sig_size().expect("Error with sig_size()"); + assert_eq!(size, Ed25519::SIG_SIZE); +}