/* * Copyright (C) 2006-2026 wolfSSL Inc. * * This file is part of wolfSSL. * * wolfSSL is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * wolfSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ /*! This module provides a Rust wrapper for the wolfCrypt library's RSA functionality. The primary component is the `RSA` struct, which manages the lifecycle of a wolfSSL `RsaKey` object. It ensures proper initialization and deallocation. # Examples ```rust # extern crate std; #[cfg(random)] { use std::fs; use wolfssl_wolfcrypt::random::RNG; use wolfssl_wolfcrypt::rsa::RSA; let mut rng = RNG::new().expect("Error creating RNG"); let key_path = "../../../certs/client-keyPub.der"; let der: Vec = fs::read(key_path).expect("Error reading key file"); let mut rsa = RSA::new_public_from_der(&der).expect("Error with new_public_from_der()"); rsa.set_rng(&mut rng).expect("Error with set_rng()"); let plain: &[u8] = b"Test message"; let mut enc: [u8; 512] = [0; 512]; let enc_len = rsa.public_encrypt(plain, &mut enc, &mut rng).expect("Error with public_encrypt()"); assert!(enc_len > 0 && enc_len <= 512); let key_path = "../../../certs/client-key.der"; let der: Vec = fs::read(key_path).expect("Error reading key file"); let mut rsa = RSA::new_from_der(&der).expect("Error with new_from_der()"); rsa.set_rng(&mut rng).expect("Error with set_rng()"); let mut plain_out: [u8; 512] = [0; 512]; let dec_len = rsa.private_decrypt(&enc[0..enc_len], &mut plain_out).expect("Error with private_decrypt()"); assert!(dec_len as usize == plain.len()); assert_eq!(plain_out[0..dec_len], *plain); } ``` */ #![cfg(rsa)] use crate::sys; #[cfg(random)] use crate::random::RNG; use core::mem::{MaybeUninit}; /// The `RSA` struct manages the lifecycle of a wolfSSL `RsaKey` object. /// /// It ensures proper initialization and deallocation. /// /// An instance can be created with `new_from_der()`, `new_public_from_der()`, /// or `generate()`. pub struct RSA { pub(crate) wc_rsakey: sys::RsaKey, } impl RSA { // Hash type constants used for PSS sign and verify methods. pub const HASH_TYPE_NONE : u32 = sys::wc_HashType_WC_HASH_TYPE_NONE; pub const HASH_TYPE_MD2 : u32 = sys::wc_HashType_WC_HASH_TYPE_MD2; pub const HASH_TYPE_MD4 : u32 = sys::wc_HashType_WC_HASH_TYPE_MD4; pub const HASH_TYPE_MD5 : u32 = sys::wc_HashType_WC_HASH_TYPE_MD5; #[cfg(sha)] pub const HASH_TYPE_SHA : u32 = sys::wc_HashType_WC_HASH_TYPE_SHA; #[cfg(sha256)] pub const HASH_TYPE_SHA224 : u32 = sys::wc_HashType_WC_HASH_TYPE_SHA224; #[cfg(sha256)] pub const HASH_TYPE_SHA256 : u32 = sys::wc_HashType_WC_HASH_TYPE_SHA256; #[cfg(sha512)] pub const HASH_TYPE_SHA384 : u32 = sys::wc_HashType_WC_HASH_TYPE_SHA384; #[cfg(sha512)] pub const HASH_TYPE_SHA512 : u32 = sys::wc_HashType_WC_HASH_TYPE_SHA512; pub const HASH_TYPE_MD5_SHA : u32 = sys::wc_HashType_WC_HASH_TYPE_MD5_SHA; #[cfg(sha3)] pub const HASH_TYPE_SHA3_224 : u32 = sys::wc_HashType_WC_HASH_TYPE_SHA3_224; #[cfg(sha3)] pub const HASH_TYPE_SHA3_256 : u32 = sys::wc_HashType_WC_HASH_TYPE_SHA3_256; #[cfg(sha3)] pub const HASH_TYPE_SHA3_384 : u32 = sys::wc_HashType_WC_HASH_TYPE_SHA3_384; #[cfg(sha3)] pub const HASH_TYPE_SHA3_512 : u32 = sys::wc_HashType_WC_HASH_TYPE_SHA3_512; pub const HASH_TYPE_BLAKE2B : u32 = sys::wc_HashType_WC_HASH_TYPE_BLAKE2B; pub const HASH_TYPE_BLAKE2S : u32 = sys::wc_HashType_WC_HASH_TYPE_BLAKE2S; #[cfg(sha512_224)] pub const HASH_TYPE_SHA512_224 : u32 = sys::wc_HashType_WC_HASH_TYPE_SHA512_224; #[cfg(sha512_256)] pub const HASH_TYPE_SHA512_256 : u32 = sys::wc_HashType_WC_HASH_TYPE_SHA512_256; #[cfg(shake128)] pub const HASH_TYPE_SHAKE128 : u32 = sys::wc_HashType_WC_HASH_TYPE_SHAKE128; #[cfg(shake256)] pub const HASH_TYPE_SHAKE256 : u32 = sys::wc_HashType_WC_HASH_TYPE_SHAKE256; // Mask generation function (MGF) constants used for PSS sign and verify methods. pub const MGF1NONE : i32 = sys::WC_MGF1NONE as i32; pub const MGF1SHA1 : i32 = sys::WC_MGF1SHA1 as i32; pub const MGF1SHA224 : i32 = sys::WC_MGF1SHA224 as i32; pub const MGF1SHA256 : i32 = sys::WC_MGF1SHA256 as i32; pub const MGF1SHA384 : i32 = sys::WC_MGF1SHA384 as i32; pub const MGF1SHA512 : i32 = sys::WC_MGF1SHA512 as i32; #[cfg(rsa_mgf1sha512_224)] pub const MGF1SHA512_224 : i32 = sys::WC_MGF1SHA512_224 as i32; #[cfg(rsa_mgf1sha512_256)] pub const MGF1SHA512_256 : i32 = sys::WC_MGF1SHA512_256 as i32; // Type constants used for `rsa_direct()`. pub const PUBLIC_ENCRYPT : i32 = sys::RSA_PUBLIC_ENCRYPT; pub const PUBLIC_DECRYPT : i32 = sys::RSA_PUBLIC_DECRYPT; pub const PRIVATE_ENCRYPT : i32 = sys::RSA_PRIVATE_ENCRYPT; pub const PRIVATE_DECRYPT : i32 = sys::RSA_PRIVATE_DECRYPT; /// Load a public and private RSA keypair from DER-encoded buffer. /// /// # Parameters /// /// * `der`: DER-encoded input buffer. /// /// # Returns /// /// Returns either Ok(RSA) containing the RSA struct instance or Err(e) /// containing the wolfSSL library error code value. /// /// # Example /// /// ```rust /// # extern crate std; /// #[cfg(random)] /// { /// use std::fs; /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::rsa::RSA; /// /// let mut rng = RNG::new().expect("Error creating RNG"); /// let key_path = "../../../certs/client-keyPub.der"; /// let der: Vec = fs::read(key_path).expect("Error reading key file"); /// let mut rsa = RSA::new_public_from_der(&der).expect("Error with new_public_from_der()"); /// rsa.set_rng(&mut rng).expect("Error with set_rng()"); /// let plain: &[u8] = b"Test message"; /// let mut enc: [u8; 512] = [0; 512]; /// let enc_len = rsa.public_encrypt(plain, &mut enc, &mut rng).expect("Error with public_encrypt()"); /// assert!(enc_len > 0 && enc_len <= 512); /// /// let key_path = "../../../certs/client-key.der"; /// let der: Vec = fs::read(key_path).expect("Error reading key file"); /// let mut rsa = RSA::new_from_der(&der).expect("Error with new_from_der()"); /// rsa.set_rng(&mut rng).expect("Error with set_rng()"); /// let mut plain_out: [u8; 512] = [0; 512]; /// let dec_len = rsa.private_decrypt(&enc[0..enc_len], &mut plain_out).expect("Error with private_decrypt()"); /// assert!(dec_len as usize == plain.len()); /// assert_eq!(plain_out[0..dec_len], *plain); /// } /// ``` pub fn new_from_der(der: &[u8]) -> Result { Self::new_from_der_ex(der, None, None) } /// Load a public and private RSA keypair from DER-encoded buffer with /// optional heap and device ID. /// /// # Parameters /// /// * `der`: DER-encoded input buffer. /// * `heap`: Optional heap hint. /// * `dev_id` Optional device ID to use with crypto callbacks or async hardware. /// /// # Returns /// /// Returns either Ok(RSA) containing the RSA struct instance or Err(e) /// containing the wolfSSL library error code value. /// /// # Example /// /// ```rust /// # extern crate std; /// #[cfg(random)] /// { /// use std::fs; /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::rsa::RSA; /// /// let mut rng = RNG::new().expect("Error creating RNG"); /// let key_path = "../../../certs/client-keyPub.der"; /// let der: Vec = fs::read(key_path).expect("Error reading key file"); /// let mut rsa = RSA::new_public_from_der(&der).expect("Error with new_public_from_der()"); /// rsa.set_rng(&mut rng).expect("Error with set_rng()"); /// let plain: &[u8] = b"Test message"; /// let mut enc: [u8; 512] = [0; 512]; /// let enc_len = rsa.public_encrypt(plain, &mut enc, &mut rng).expect("Error with public_encrypt()"); /// assert!(enc_len > 0 && enc_len <= 512); /// /// let key_path = "../../../certs/client-key.der"; /// let der: Vec = fs::read(key_path).expect("Error reading key file"); /// let mut rsa = RSA::new_from_der_ex(&der, None, None).expect("Error with new_from_der_ex()"); /// rsa.set_rng(&mut rng).expect("Error with set_rng()"); /// let mut plain_out: [u8; 512] = [0; 512]; /// let dec_len = rsa.private_decrypt(&enc[0..enc_len], &mut plain_out).expect("Error with private_decrypt()"); /// assert!(dec_len as usize == plain.len()); /// assert_eq!(plain_out[0..dec_len], *plain); /// } /// ``` pub fn new_from_der_ex(der: &[u8], heap: Option<*mut core::ffi::c_void>, dev_id: Option) -> Result { let der_size = crate::buffer_len_to_u32(der.len())?; let mut wc_rsakey: MaybeUninit = MaybeUninit::uninit(); let heap = match heap { Some(heap) => heap, None => core::ptr::null_mut(), }; let dev_id = match dev_id { Some(dev_id) => dev_id, None => sys::INVALID_DEVID, }; let rc = unsafe { sys::wc_InitRsaKey_ex(wc_rsakey.as_mut_ptr(), heap, dev_id) }; if rc != 0 { return Err(rc); } let mut wc_rsakey = unsafe { wc_rsakey.assume_init() }; let mut idx: u32 = 0; let rc = unsafe { sys::wc_RsaPrivateKeyDecode(der.as_ptr(), &mut idx, &mut wc_rsakey, der_size) }; if rc != 0 { unsafe { sys::wc_FreeRsaKey(&mut wc_rsakey); } return Err(rc); } let rsa = RSA { wc_rsakey }; Ok(rsa) } /// Load a public RSA key from DER-encoded buffer. /// /// # Parameters /// /// * `der`: DER-encoded input buffer. /// /// # Returns /// /// Returns either Ok(RSA) containing the RSA struct instance or Err(e) /// containing the wolfSSL library error code value. /// /// # Example /// /// ```rust /// # extern crate std; /// #[cfg(random)] /// { /// use std::fs; /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::rsa::RSA; /// /// let mut rng = RNG::new().expect("Error creating RNG"); /// let key_path = "../../../certs/client-keyPub.der"; /// let der: Vec = fs::read(key_path).expect("Error reading key file"); /// let mut rsa = RSA::new_public_from_der(&der).expect("Error with new_public_from_der()"); /// rsa.set_rng(&mut rng).expect("Error with set_rng()"); /// let plain: &[u8] = b"Test message"; /// let mut enc: [u8; 512] = [0; 512]; /// let enc_len = rsa.public_encrypt(plain, &mut enc, &mut rng).expect("Error with public_encrypt()"); /// assert!(enc_len > 0 && enc_len <= 512); /// /// let key_path = "../../../certs/client-key.der"; /// let der: Vec = fs::read(key_path).expect("Error reading key file"); /// let mut rsa = RSA::new_from_der(&der).expect("Error with new_from_der()"); /// rsa.set_rng(&mut rng).expect("Error with set_rng()"); /// let mut plain_out: [u8; 512] = [0; 512]; /// let dec_len = rsa.private_decrypt(&enc[0..enc_len], &mut plain_out).expect("Error with private_decrypt()"); /// assert!(dec_len as usize == plain.len()); /// assert_eq!(plain_out[0..dec_len], *plain); /// } /// ``` pub fn new_public_from_der(der: &[u8]) -> Result { Self::new_public_from_der_ex(der, None, None) } /// Load a public RSA key from DER-encoded buffer with optional heap and /// device ID. /// /// # Parameters /// /// * `der`: DER-encoded input buffer. /// * `heap`: Optional heap hint. /// * `dev_id` Optional device ID to use with crypto callbacks or async hardware. /// /// # Returns /// /// Returns either Ok(RSA) containing the RSA struct instance or Err(e) /// containing the wolfSSL library error code value. /// /// # Example /// /// ```rust /// # extern crate std; /// #[cfg(random)] /// { /// use std::fs; /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::rsa::RSA; /// /// let mut rng = RNG::new().expect("Error creating RNG"); /// let key_path = "../../../certs/client-keyPub.der"; /// let der: Vec = fs::read(key_path).expect("Error reading key file"); /// let mut rsa = RSA::new_public_from_der_ex(&der, None, None).expect("Error with new_public_from_der_ex()"); /// rsa.set_rng(&mut rng).expect("Error with set_rng()"); /// let plain: &[u8] = b"Test message"; /// let mut enc: [u8; 512] = [0; 512]; /// let enc_len = rsa.public_encrypt(plain, &mut enc, &mut rng).expect("Error with public_encrypt()"); /// assert!(enc_len > 0 && enc_len <= 512); /// /// let key_path = "../../../certs/client-key.der"; /// let der: Vec = fs::read(key_path).expect("Error reading key file"); /// let mut rsa = RSA::new_from_der(&der).expect("Error with new_from_der()"); /// rsa.set_rng(&mut rng).expect("Error with set_rng()"); /// let mut plain_out: [u8; 512] = [0; 512]; /// let dec_len = rsa.private_decrypt(&enc[0..enc_len], &mut plain_out).expect("Error with private_decrypt()"); /// assert!(dec_len as usize == plain.len()); /// assert_eq!(plain_out[0..dec_len], *plain); /// } /// ``` pub fn new_public_from_der_ex(der: &[u8], heap: Option<*mut core::ffi::c_void>, dev_id: Option) -> Result { let der_size = crate::buffer_len_to_u32(der.len())?; let mut wc_rsakey: MaybeUninit = MaybeUninit::uninit(); let heap = match heap { Some(heap) => heap, None => core::ptr::null_mut(), }; let dev_id = match dev_id { Some(dev_id) => dev_id, None => sys::INVALID_DEVID, }; let rc = unsafe { sys::wc_InitRsaKey_ex(wc_rsakey.as_mut_ptr(), heap, dev_id) }; if rc != 0 { return Err(rc); } let mut wc_rsakey = unsafe { wc_rsakey.assume_init() }; let mut idx: u32 = 0; let rc = unsafe { sys::wc_RsaPublicKeyDecode(der.as_ptr(), &mut idx, &mut wc_rsakey, der_size) }; if rc != 0 { unsafe { sys::wc_FreeRsaKey(&mut wc_rsakey); } return Err(rc); } let rsa = RSA { wc_rsakey }; Ok(rsa) } /// Create a new RSA public key from raw modulus (`n`) and public /// exponent (`e`) bytes in big-endian form. /// /// # Parameters /// /// * `n`: Big-endian modulus bytes. /// * `e`: Big-endian public exponent bytes. /// /// # Returns /// /// Returns either Ok(RSA) containing the RSA struct instance or Err(e) /// containing the wolfSSL library error code value. pub fn new_public_from_raw(n: &[u8], e: &[u8]) -> Result { Self::new_public_from_raw_ex(n, e, None, None) } /// Create a new RSA public key from raw modulus (`n`) and public /// exponent (`e`) bytes with optional heap and device ID. pub fn new_public_from_raw_ex( n: &[u8], e: &[u8], heap: Option<*mut core::ffi::c_void>, dev_id: Option, ) -> Result { let n_size = crate::buffer_len_to_u32(n.len())?; let e_size = crate::buffer_len_to_u32(e.len())?; let mut wc_rsakey: MaybeUninit = MaybeUninit::uninit(); let heap = match heap { Some(heap) => heap, None => core::ptr::null_mut(), }; let dev_id = match dev_id { Some(dev_id) => dev_id, None => sys::INVALID_DEVID, }; let rc = unsafe { sys::wc_InitRsaKey_ex(wc_rsakey.as_mut_ptr(), heap, dev_id) }; if rc != 0 { return Err(rc); } let mut wc_rsakey = unsafe { wc_rsakey.assume_init() }; let rc = unsafe { sys::wc_RsaPublicKeyDecodeRaw( n.as_ptr(), n_size, e.as_ptr(), e_size, &mut wc_rsakey, ) }; if rc != 0 { unsafe { sys::wc_FreeRsaKey(&mut wc_rsakey); } return Err(rc); } Ok(RSA { wc_rsakey }) } /// Generate a new RSA key using the given size and exponent. /// /// This function generates an RSA private key of length size (in bits) and /// given exponent (e). It then returns the RSA structure instance so that /// it may be used for encryption or signing operations. A secure number to /// use for e is 65537. size is required to be greater than or equal to /// RSA_MIN_SIZE and less than or equal to RSA_MAX_SIZE. For this function /// to be available, the option WOLFSSL_KEY_GEN must be enabled at compile /// time. This can be accomplished with --enable-keygen if using /// `./configure`. /// /// # Parameters /// /// * `size`: Desired key length in bits. /// * `e`: Exponent parameter to use for generating the key. A secure /// choice is 65537. /// * `rng`: Reference to a `RNG` struct to use for random number /// generation while making the key. /// /// # Returns /// /// Returns either Ok(RSA) containing the RSA struct instance or Err(e) /// containing the wolfSSL library error code value. /// /// # Example /// /// ```rust /// #[cfg(rsa_keygen)] /// { /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::rsa::RSA; /// /// let mut rng = RNG::new().expect("Error creating RNG"); /// let mut rsa = RSA::generate(2048, 65537, &mut rng).expect("Error with generate()"); /// rsa.check().expect("Error with check()"); /// let encrypt_size = rsa.get_encrypt_size().expect("Error with get_encrypt_size()"); /// assert_eq!(encrypt_size, 256); /// } /// ``` #[cfg(all(random, rsa_keygen))] pub fn generate(size: i32, e: i32, rng: &mut RNG) -> Result { Self::generate_ex(size, e, rng, None, None) } /// Generate a new RSA key using the given size and exponent with optional /// heap and device ID. /// /// This function generates an RSA private key of length size (in bits) and /// given exponent (e). It then returns the RSA structure instance so that /// it may be used for encryption or signing operations. A secure number to /// use for e is 65537. size is required to be greater than or equal to /// RSA_MIN_SIZE and less than or equal to RSA_MAX_SIZE. For this function /// to be available, the option WOLFSSL_KEY_GEN must be enabled at compile /// time. This can be accomplished with --enable-keygen if using /// `./configure`. /// /// # Parameters /// /// * `size`: Desired key length in bits. /// * `e`: Exponent parameter to use for generating the key. A secure /// choice is 65537. /// * `rng`: Reference to a `RNG` struct to use for random number /// generation while making the key. /// * `heap`: Optional heap hint. /// * `dev_id` Optional device ID to use with crypto callbacks or async hardware. /// /// # Returns /// /// Returns either Ok(RSA) containing the RSA struct instance or Err(e) /// containing the wolfSSL library error code value. /// /// # Example /// /// ```rust /// #[cfg(rsa_keygen)] /// { /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::rsa::RSA; /// /// let mut rng = RNG::new().expect("Error creating RNG"); /// let mut rsa = RSA::generate_ex(2048, 65537, &mut rng, None, None).expect("Error with generate_ex()"); /// rsa.check().expect("Error with check()"); /// let encrypt_size = rsa.get_encrypt_size().expect("Error with get_encrypt_size()"); /// assert_eq!(encrypt_size, 256); /// } /// ``` #[cfg(all(random, rsa_keygen))] pub fn generate_ex(size: i32, e: i32, rng: &mut RNG, heap: Option<*mut core::ffi::c_void>, dev_id: Option) -> Result { let mut wc_rsakey: MaybeUninit = MaybeUninit::uninit(); let heap = match heap { Some(heap) => heap, None => core::ptr::null_mut(), }; let dev_id = match dev_id { Some(dev_id) => dev_id, None => sys::INVALID_DEVID, }; let rc = unsafe { sys::wc_InitRsaKey_ex(wc_rsakey.as_mut_ptr(), heap, dev_id) }; if rc != 0 { return Err(rc); } let mut wc_rsakey = unsafe { wc_rsakey.assume_init() }; let e = e as core::ffi::c_long; let rc = unsafe { sys::wc_MakeRsaKey(&mut wc_rsakey, size, e, &mut rng.wc_rng) }; if rc != 0 { unsafe { sys::wc_FreeRsaKey(&mut wc_rsakey); } return Err(rc); } let rsa = RSA { wc_rsakey }; Ok(rsa) } /// Export public and private RSA parameters from an RSA key. /// /// # Parameters /// /// * `e`: Slice in which to hold `e` key parameter. /// * `e_size`: Output holding the number of bytes written to `e`. /// * `n`: Slice in which to hold `n` key parameter. /// * `n_size`: Output holding the number of bytes written to `n`. /// * `d`: Slice in which to hold `d` key parameter. /// * `d_size`: Output holding the number of bytes written to `d`. /// * `p`: Slice in which to hold `p` key parameter. /// * `p_size`: Output holding the number of bytes written to `p`. /// * `q`: Slice in which to hold `q` key parameter. /// * `q_size`: Output holding the number of bytes written to `q`. /// /// # Returns /// /// Returns Ok(()) on success or Err(e) containing the wolfSSL library /// error code value. /// /// # Example /// /// ```rust /// #[cfg(rsa_keygen)] /// { /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::rsa::RSA; /// /// let mut rng = RNG::new().expect("Error creating RNG"); /// let mut rsa = RSA::generate(2048, 65537, &mut rng).expect("Error with generate()"); /// let mut e: [u8; 256] = [0; 256]; /// let mut e_size: u32 = 0; /// let mut n: [u8; 256] = [0; 256]; /// let mut n_size: u32 = 0; /// let mut d: [u8; 256] = [0; 256]; /// let mut d_size: u32 = 0; /// let mut p: [u8; 256] = [0; 256]; /// let mut p_size: u32 = 0; /// let mut q: [u8; 256] = [0; 256]; /// let mut q_size: u32 = 0; /// rsa.export_key(&mut e, &mut e_size, &mut n, &mut n_size, /// &mut d, &mut d_size, &mut p, &mut p_size, &mut q, &mut q_size).expect("Error with export_key()"); /// } /// ``` #[allow(clippy::too_many_arguments)] pub fn export_key(&mut self, e: &mut [u8], e_size: &mut u32, n: &mut [u8], n_size: &mut u32, d: &mut [u8], d_size: &mut u32, p: &mut [u8], p_size: &mut u32, q: &mut [u8], q_size: &mut u32) -> Result<(), i32> { *e_size = crate::buffer_len_to_u32(e.len())?; *n_size = crate::buffer_len_to_u32(n.len())?; *d_size = crate::buffer_len_to_u32(d.len())?; *p_size = crate::buffer_len_to_u32(p.len())?; *q_size = crate::buffer_len_to_u32(q.len())?; #[cfg(rsa_const_api)] let key_ptr = &self.wc_rsakey; #[cfg(not(rsa_const_api))] let key_ptr = &mut self.wc_rsakey; let rc = unsafe { sys::wc_RsaExportKey(key_ptr, e.as_mut_ptr(), e_size, n.as_mut_ptr(), n_size, d.as_mut_ptr(), d_size, p.as_mut_ptr(), p_size, q.as_mut_ptr(), q_size) }; if rc != 0 { return Err(rc); } Ok(()) } /// Export public RSA parameters from an RSA key. /// /// # Parameters /// /// * `e`: Slice in which to hold `e` key parameter. /// * `e_size`: Output holding the number of bytes written to `e`. /// * `n`: Slice in which to hold `n` key parameter. /// * `n_size`: Output holding the number of bytes written to `n`. /// /// # Returns /// /// Returns Ok(()) on success or Err(e) containing the wolfSSL library /// error code value. /// /// # Example /// /// ```rust /// #[cfg(rsa_keygen)] /// { /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::rsa::RSA; /// /// let mut rng = RNG::new().expect("Error creating RNG"); /// let mut rsa = RSA::generate(2048, 65537, &mut rng).expect("Error with generate()"); /// let mut e: [u8; 256] = [0; 256]; /// let mut e_size: u32 = 0; /// let mut n: [u8; 256] = [0; 256]; /// let mut n_size: u32 = 0; /// rsa.export_public_key(&mut e, &mut e_size, &mut n, &mut n_size).expect("Error with export_public_key()"); /// } /// ``` pub fn export_public_key(&mut self, e: &mut [u8], e_size: &mut u32, n: &mut [u8], n_size: &mut u32) -> Result<(), i32> { *e_size = crate::buffer_len_to_u32(e.len())?; *n_size = crate::buffer_len_to_u32(n.len())?; #[cfg(rsa_const_api)] let key = &self.wc_rsakey; #[cfg(not(rsa_const_api))] let key = &mut self.wc_rsakey; let rc = unsafe { sys::wc_RsaFlattenPublicKey(key, e.as_mut_ptr(), e_size, n.as_mut_ptr(), n_size) }; if rc != 0 { return Err(rc); } Ok(()) } /// Get the encryption size for the RSA key. /// /// # Returns /// /// Returns Ok(size) on success or Err(e) containing the wolfSSL library /// error code value. /// /// # Example /// /// ```rust /// #[cfg(rsa_keygen)] /// { /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::rsa::RSA; /// /// let mut rng = RNG::new().expect("Error creating RNG"); /// let mut rsa = RSA::generate(2048, 65537, &mut rng).expect("Error with generate()"); /// let encrypt_size = rsa.get_encrypt_size().expect("Error with get_encrypt_size()"); /// assert_eq!(encrypt_size, 256); /// } /// ``` pub fn get_encrypt_size(&self) -> Result { let rc = unsafe { sys::wc_RsaEncryptSize(&self.wc_rsakey) }; if rc < 0 { return Err(rc); } Ok(rc as usize) } /// Check the RSA key. /// /// # Returns /// /// Returns Ok(()) on success or Err(e) containing the wolfSSL library /// error code value. /// /// # Example /// /// ```rust /// #[cfg(rsa_keygen)] /// { /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::rsa::RSA; /// /// let mut rng = RNG::new().expect("Error creating RNG"); /// let mut rsa = RSA::generate(2048, 65537, &mut rng).expect("Error with generate()"); /// rsa.check().expect("Error with check()"); /// } /// ``` pub fn check(&mut self) -> Result<(), i32> { let rc = unsafe { sys::wc_CheckRsaKey(&mut self.wc_rsakey) }; if rc != 0 { return Err(rc); } Ok(()) } /// Encrypt data using an RSA public key. /// /// # Parameters /// /// * `din`: Data to encrypt. /// * `dout`: Buffer in which to store encrypted data. /// * `rng`: Reference to a `RNG` struct to use for random number /// generation while encrypting. /// /// # Returns /// /// Returns Ok(size) on success or Err(e) containing the wolfSSL library /// error code value. /// The size returned specifies the number of bytes written to the `dout` /// buffer. /// /// # Example /// /// ```rust /// # extern crate std; /// #[cfg(random)] /// { /// use std::fs; /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::rsa::RSA; /// /// let mut rng = RNG::new().expect("Error creating RNG"); /// let key_path = "../../../certs/client-keyPub.der"; /// let der: Vec = fs::read(key_path).expect("Error reading key file"); /// let mut rsa = RSA::new_public_from_der(&der).expect("Error with new_public_from_der()"); /// rsa.set_rng(&mut rng).expect("Error with set_rng()"); /// let plain: &[u8] = b"Test message"; /// let mut enc: [u8; 512] = [0; 512]; /// let enc_len = rsa.public_encrypt(plain, &mut enc, &mut rng).expect("Error with public_encrypt()"); /// assert!(enc_len > 0 && enc_len <= 512); /// /// let key_path = "../../../certs/client-key.der"; /// let der: Vec = fs::read(key_path).expect("Error reading key file"); /// let mut rsa = RSA::new_from_der(&der).expect("Error with new_from_der()"); /// rsa.set_rng(&mut rng).expect("Error with set_rng()"); /// let mut plain_out: [u8; 512] = [0; 512]; /// let dec_len = rsa.private_decrypt(&enc[0..enc_len], &mut plain_out).expect("Error with private_decrypt()"); /// assert!(dec_len as usize == plain.len()); /// assert_eq!(plain_out[0..dec_len], *plain); /// } /// ``` #[cfg(random)] pub fn public_encrypt(&mut self, din: &[u8], dout: &mut [u8], rng: &mut RNG) -> Result { let din_size = crate::buffer_len_to_u32(din.len())?; let dout_size = crate::buffer_len_to_u32(dout.len())?; let rc = unsafe { sys::wc_RsaPublicEncrypt(din.as_ptr(), din_size, dout.as_mut_ptr(), dout_size, &mut self.wc_rsakey, &mut rng.wc_rng) }; if rc < 0 { return Err(rc); } Ok(rc as usize) } /// Decrypt data using an RSA private key. /// /// # Parameters /// /// * `din`: Data to decrypt. /// * `dout`: Buffer in which to store decrypted data. /// /// # Returns /// /// Returns Ok(size) on success or Err(e) containing the wolfSSL library /// error code value. /// The size returned specifies the number of bytes written to the `dout` /// buffer. /// /// # Example /// /// ```rust /// # extern crate std; /// #[cfg(random)] /// { /// use std::fs; /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::rsa::RSA; /// /// let mut rng = RNG::new().expect("Error creating RNG"); /// let key_path = "../../../certs/client-keyPub.der"; /// let der: Vec = fs::read(key_path).expect("Error reading key file"); /// let mut rsa = RSA::new_public_from_der(&der).expect("Error with new_public_from_der()"); /// rsa.set_rng(&mut rng).expect("Error with set_rng()"); /// let plain: &[u8] = b"Test message"; /// let mut enc: [u8; 512] = [0; 512]; /// let enc_len = rsa.public_encrypt(plain, &mut enc, &mut rng).expect("Error with public_encrypt()"); /// assert!(enc_len > 0 && enc_len <= 512); /// /// let key_path = "../../../certs/client-key.der"; /// let der: Vec = fs::read(key_path).expect("Error reading key file"); /// let mut rsa = RSA::new_from_der(&der).expect("Error with new_from_der()"); /// rsa.set_rng(&mut rng).expect("Error with set_rng()"); /// let mut plain_out: [u8; 512] = [0; 512]; /// let dec_len = rsa.private_decrypt(&enc[0..enc_len], &mut plain_out).expect("Error with private_decrypt()"); /// assert!(dec_len as usize == plain.len()); /// assert_eq!(plain_out[0..dec_len], *plain); /// } /// ``` pub fn private_decrypt(&mut self, din: &[u8], dout: &mut [u8]) -> Result { let din_size = crate::buffer_len_to_u32(din.len())?; let dout_size = crate::buffer_len_to_u32(dout.len())?; let rc = unsafe { sys::wc_RsaPrivateDecrypt(din.as_ptr(), din_size, dout.as_mut_ptr(), dout_size, &mut self.wc_rsakey) }; if rc < 0 { return Err(rc); } Ok(rc as usize) } /// Sign the provided data with the private key using RSA-PSS signature /// scheme. /// /// # Parameters /// /// * `din`: Data to sign. /// * `dout`: Buffer in which to store output signature. /// * `hash_algo`: Hash algorithm type to use, one of RSA::HASH_TYPE_*. /// * `mgf`: Mask generation function to use, one of RSA::MGF*. /// * `rng`: Reference to a `RNG` struct to use for random number /// generation while signing. /// /// # Returns /// /// Returns Ok(size) on success or Err(e) containing the wolfSSL library /// error code value. /// The size returned specifies the number of bytes written to the `dout` /// buffer. /// /// # Example /// /// ```rust /// #[cfg(all(random, rsa_pss))] /// { /// use std::fs; /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::rsa::RSA; /// /// let mut rng = RNG::new().expect("Error creating RNG"); /// /// let key_path = "../../../certs/client-key.der"; /// let der: Vec = fs::read(key_path).expect("Error reading key file"); /// let mut rsa = RSA::new_from_der(&der).expect("Error with new_from_der()"); /// let msg: &[u8] = b"This is the string to be signed!"; /// let mut signature: [u8; 512] = [0; 512]; /// let sig_len = rsa.pss_sign(msg, &mut signature, RSA::HASH_TYPE_SHA256, RSA::MGF1SHA256, &mut rng).expect("Error with pss_sign()"); /// assert!(sig_len > 0 && sig_len <= 512); /// /// let key_path = "../../../certs/client-keyPub.der"; /// let der: Vec = fs::read(key_path).expect("Error reading key file"); /// let mut rsa = RSA::new_public_from_der(&der).expect("Error with new_public_from_der()"); /// rsa.set_rng(&mut rng).expect("Error with set_rng()"); /// let signature = &signature[0..sig_len]; /// let mut verify_out: [u8; 512] = [0; 512]; /// let verify_out_size = rsa.pss_verify(signature, &mut verify_out, RSA::HASH_TYPE_SHA256, RSA::MGF1SHA256).expect("Error with pss_verify()"); /// let verify_out = &verify_out[0..verify_out_size]; /// rsa.pss_check_padding(msg, verify_out, RSA::HASH_TYPE_SHA256).expect("Error with pss_check_padding()"); /// /// let mut verify_out: [u8; 512] = [0; 512]; /// rsa.pss_verify_check(signature, &mut verify_out, msg, RSA::HASH_TYPE_SHA256, RSA::MGF1SHA256).expect("Error with pss_verify_check()"); /// } /// ``` #[cfg(all(random, rsa_pss))] pub fn pss_sign(&mut self, din: &[u8], dout: &mut [u8], hash_algo: u32, mgf: i32, rng: &mut RNG) -> Result { let din_size = crate::buffer_len_to_u32(din.len())?; let dout_size = crate::buffer_len_to_u32(dout.len())?; let rc = unsafe { sys::wc_RsaPSS_Sign(din.as_ptr(), din_size, dout.as_mut_ptr(), dout_size, hash_algo, mgf, &mut self.wc_rsakey, &mut rng.wc_rng) }; if rc < 0 { return Err(rc); } Ok(rc as usize) } /// Check the PSS data to ensure the signature matches. /// /// `set_rng()` must be called previously when wolfSSL is built with /// WC_RSA_BLINDING option enabled. /// /// # Parameters /// /// * `din`: Hash of data being verified. /// * `sig`: Buffer holding PSS data (output from `pss_verify()`). /// * `hash_algo`: Hash algorithm type to use, one of RSA::HASH_TYPE_*. /// /// # Returns /// /// Returns Ok(()) on success or Err(e) containing the wolfSSL library /// error code value. /// /// # Example /// /// ```rust /// #[cfg(all(random, rsa_pss, rsa_const_api))] /// { /// use std::fs; /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::rsa::RSA; /// /// let mut rng = RNG::new().expect("Error creating RNG"); /// /// let key_path = "../../../certs/client-key.der"; /// let der: Vec = fs::read(key_path).expect("Error reading key file"); /// let mut rsa = RSA::new_from_der(&der).expect("Error with new_from_der()"); /// let msg: &[u8] = b"This is the string to be signed!"; /// let mut signature: [u8; 512] = [0; 512]; /// let sig_len = rsa.pss_sign(msg, &mut signature, RSA::HASH_TYPE_SHA256, RSA::MGF1SHA256, &mut rng).expect("Error with pss_sign()"); /// assert!(sig_len > 0 && sig_len <= 512); /// /// let key_path = "../../../certs/client-keyPub.der"; /// let der: Vec = fs::read(key_path).expect("Error reading key file"); /// let mut rsa = RSA::new_public_from_der(&der).expect("Error with new_public_from_der()"); /// rsa.set_rng(&mut rng).expect("Error with set_rng()"); /// let signature = &signature[0..sig_len]; /// let mut verify_out: [u8; 512] = [0; 512]; /// let verify_out_size = rsa.pss_verify(signature, &mut verify_out, RSA::HASH_TYPE_SHA256, RSA::MGF1SHA256).expect("Error with pss_verify()"); /// let verify_out = &verify_out[0..verify_out_size]; /// rsa.pss_check_padding(msg, verify_out, RSA::HASH_TYPE_SHA256).expect("Error with pss_check_padding()"); /// /// let mut verify_out: [u8; 512] = [0; 512]; /// rsa.pss_verify_check(signature, &mut verify_out, msg, RSA::HASH_TYPE_SHA256, RSA::MGF1SHA256).expect("Error with pss_verify_check()"); /// } /// ``` #[cfg(all(rsa_pss, rsa_const_api))] pub fn pss_check_padding(&mut self, din: &[u8], sig: &[u8], hash_algo: u32) -> Result<(), i32> { let din_size = crate::buffer_len_to_u32(din.len())?; let sig_size = crate::buffer_len_to_u32(sig.len())?; let rc = unsafe { sys::wc_RsaPSS_CheckPadding(din.as_ptr(), din_size, sig.as_ptr(), sig_size, hash_algo) }; if rc != 0 { return Err(rc); } Ok(()) } /// Decrypt input signature to verify that the message was signed by key. /// /// `set_rng()` must be called previously when wolfSSL is built with /// WC_RSA_BLINDING option enabled. /// /// # Parameters /// /// * `din`: Input data to decrypt. /// * `dout`: Buffer in which to store decrypted data. /// * `hash_algo`: Hash algorithm type to use, one of RSA::HASH_TYPE_*. /// * `mgf`: Mask generation function to use, one of RSA::MGF*. /// /// # Returns /// /// Returns Ok(size) on success or Err(e) containing the wolfSSL library /// error code value. /// The size returned specifies the number of bytes written to the `dout` /// buffer. /// /// # Example /// /// ```rust /// #[cfg(all(random, rsa_pss, rsa_const_api))] /// { /// use std::fs; /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::rsa::RSA; /// /// let mut rng = RNG::new().expect("Error creating RNG"); /// /// let key_path = "../../../certs/client-key.der"; /// let der: Vec = fs::read(key_path).expect("Error reading key file"); /// let mut rsa = RSA::new_from_der(&der).expect("Error with new_from_der()"); /// let msg: &[u8] = b"This is the string to be signed!"; /// let mut signature: [u8; 512] = [0; 512]; /// let sig_len = rsa.pss_sign(msg, &mut signature, RSA::HASH_TYPE_SHA256, RSA::MGF1SHA256, &mut rng).expect("Error with pss_sign()"); /// assert!(sig_len > 0 && sig_len <= 512); /// /// let key_path = "../../../certs/client-keyPub.der"; /// let der: Vec = fs::read(key_path).expect("Error reading key file"); /// let mut rsa = RSA::new_public_from_der(&der).expect("Error with new_public_from_der()"); /// rsa.set_rng(&mut rng).expect("Error with set_rng()"); /// let signature = &signature[0..sig_len]; /// let mut verify_out: [u8; 512] = [0; 512]; /// let verify_out_size = rsa.pss_verify(signature, &mut verify_out, RSA::HASH_TYPE_SHA256, RSA::MGF1SHA256).expect("Error with pss_verify()"); /// let verify_out = &verify_out[0..verify_out_size]; /// rsa.pss_check_padding(msg, verify_out, RSA::HASH_TYPE_SHA256).expect("Error with pss_check_padding()"); /// /// let mut verify_out: [u8; 512] = [0; 512]; /// rsa.pss_verify_check(signature, &mut verify_out, msg, RSA::HASH_TYPE_SHA256, RSA::MGF1SHA256).expect("Error with pss_verify_check()"); /// } /// ``` #[cfg(all(rsa_pss, rsa_const_api))] pub fn pss_verify(&mut self, din: &[u8], dout: &mut [u8], hash_algo: u32, mgf: i32) -> Result { let din_size = crate::buffer_len_to_u32(din.len())?; let dout_size = crate::buffer_len_to_u32(dout.len())?; let rc = unsafe { sys::wc_RsaPSS_Verify(din.as_ptr(), din_size, dout.as_mut_ptr(), dout_size, hash_algo, mgf, &mut self.wc_rsakey) }; if rc < 0 { return Err(rc); } Ok(rc as usize) } /// Verify the message signed with RSA-PSS. /// /// This method combines the functionality of `pss_verify()` and /// `pss_check_padding()`. /// /// `set_rng()` must be called previously when wolfSSL is built with /// WC_RSA_BLINDING option enabled. /// /// # Parameters /// /// * `din`: Input data to decrypt. /// * `dout`: Buffer in which to store decrypted data. /// * `digest`: Hash of data being verified. /// * `hash_algo`: Hash algorithm type to use, one of RSA::HASH_TYPE_*. /// * `mgf`: Mask generation function to use, one of RSA::MGF*. /// /// # Returns /// /// Returns Ok(size) on success or Err(e) containing the wolfSSL library /// error code value. /// The size returned specifies the number of bytes written to the `dout` /// buffer. /// /// # Example /// /// ```rust /// #[cfg(all(random, rsa_pss, rsa_const_api))] /// { /// use std::fs; /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::rsa::RSA; /// /// let mut rng = RNG::new().expect("Error creating RNG"); /// /// let key_path = "../../../certs/client-key.der"; /// let der: Vec = fs::read(key_path).expect("Error reading key file"); /// let mut rsa = RSA::new_from_der(&der).expect("Error with new_from_der()"); /// let msg: &[u8] = b"This is the string to be signed!"; /// let mut signature: [u8; 512] = [0; 512]; /// let sig_len = rsa.pss_sign(msg, &mut signature, RSA::HASH_TYPE_SHA256, RSA::MGF1SHA256, &mut rng).expect("Error with pss_sign()"); /// assert!(sig_len > 0 && sig_len <= 512); /// /// let key_path = "../../../certs/client-keyPub.der"; /// let der: Vec = fs::read(key_path).expect("Error reading key file"); /// let mut rsa = RSA::new_public_from_der(&der).expect("Error with new_public_from_der()"); /// rsa.set_rng(&mut rng).expect("Error with set_rng()"); /// let signature = &signature[0..sig_len]; /// let mut verify_out: [u8; 512] = [0; 512]; /// let verify_out_size = rsa.pss_verify(signature, &mut verify_out, RSA::HASH_TYPE_SHA256, RSA::MGF1SHA256).expect("Error with pss_verify()"); /// let verify_out = &verify_out[0..verify_out_size]; /// rsa.pss_check_padding(msg, verify_out, RSA::HASH_TYPE_SHA256).expect("Error with pss_check_padding()"); /// /// let mut verify_out: [u8; 512] = [0; 512]; /// rsa.pss_verify_check(signature, &mut verify_out, msg, RSA::HASH_TYPE_SHA256, RSA::MGF1SHA256).expect("Error with pss_verify_check()"); /// } /// ``` #[cfg(all(rsa_pss, rsa_const_api))] pub fn pss_verify_check(&mut self, din: &[u8], dout: &mut [u8], digest: &[u8], hash_algo: u32, mgf: i32) -> Result { let din_size = crate::buffer_len_to_u32(din.len())?; let dout_size = crate::buffer_len_to_u32(dout.len())?; let digest_size = crate::buffer_len_to_u32(digest.len())?; let rc = unsafe { sys::wc_RsaPSS_VerifyCheck(din.as_ptr(), din_size, dout.as_mut_ptr(), dout_size, digest.as_ptr(), digest_size, hash_algo, mgf, &mut self.wc_rsakey) }; if rc < 0 { return Err(rc); } Ok(rc as usize) } /// Perform the RSA operation directly with no padding. /// /// The input size must match key size. Typically this is used when padding /// is already done on the RSA input. /// /// # Parameters /// /// * `din`: Input data to encrypt/decrypt. /// * `dout`: Buffer in which to store output. /// * `typ`: Operation type, one of `RSA::PUBLIC_ENCRYPT`, /// `RSA::PUBLIC_DECRYPT`, `RSA::PRIVATE_ENCRYPT`, `RSA::PRIVATE_DECRYPT`. /// * `rng`: Reference to a `RNG` struct to use for random number /// generation while signing. /// /// # Returns /// /// Returns Ok(size) on success or Err(e) containing the wolfSSL library /// error code value. /// The size returned specifies the number of bytes written to the `dout` /// buffer. /// /// # Example /// /// ```rust /// #[cfg(all(rsa_direct, rsa_const_api))] /// { /// use std::fs; /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::rsa::RSA; /// /// let mut rng = RNG::new().expect("Error creating RNG"); /// /// let key_path = "../../../certs/client-key.der"; /// let der: Vec = fs::read(key_path).expect("Error reading key file"); /// let mut rsa = RSA::new_from_der(&der).expect("Error with new_from_der()"); /// let msg = b"A rsa_direct() test input string"; /// let mut plain = [0u8; 256]; /// plain[..msg.len()].copy_from_slice(msg); /// let mut enc = [0u8; 256]; /// let enc_len = rsa.rsa_direct(&plain, &mut enc, RSA::PRIVATE_ENCRYPT, &mut rng).expect("Error with rsa_direct()"); /// assert_eq!(enc_len, 256); /// let mut plain_out = [0u8; 256]; /// let dec_len = rsa.rsa_direct(&enc, &mut plain_out, RSA::PUBLIC_DECRYPT, &mut rng).expect("Error with rsa_direct()"); /// assert_eq!(dec_len, 256); /// assert_eq!(plain_out, plain); /// } /// ``` #[cfg(all(rsa_direct, rsa_const_api))] pub fn rsa_direct(&mut self, din: &[u8], dout: &mut [u8], typ: i32, rng: &mut RNG) -> Result { let din_size = crate::buffer_len_to_u32(din.len())?; let mut dout_size = crate::buffer_len_to_u32(dout.len())?; let rc = unsafe { sys::wc_RsaDirect(din.as_ptr(), din_size, dout.as_mut_ptr(), &mut dout_size, &mut self.wc_rsakey, typ, &mut rng.wc_rng) }; if rc < 0 { return Err(rc); } Ok(dout_size as usize) } /// Associates a `RNG` instance with this `RSA` instance. /// /// This is necessary when wolfSSL is built with the `WC_RSA_BLINDING` /// build option enabled. /// /// # Parameters /// /// * `rng`: The `RNG` struct instance to associate with this `RSA` /// instance. The `RNG` struct should not be moved in memory after /// calling this method. /// /// # Returns /// /// Returns Ok(()) on success or Err(e) containing the wolfSSL library /// error code value. /// /// # Example /// /// ```rust /// # extern crate std; /// #[cfg(random)] /// { /// use std::fs; /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::rsa::RSA; /// /// let mut rng = RNG::new().expect("Error creating RNG"); /// let key_path = "../../../certs/client-keyPub.der"; /// let der: Vec = fs::read(key_path).expect("Error reading key file"); /// let mut rsa = RSA::new_public_from_der(&der).expect("Error with new_public_from_der()"); /// rsa.set_rng(&mut rng).expect("Error with set_rng()"); /// let plain: &[u8] = b"Test message"; /// let mut enc: [u8; 512] = [0; 512]; /// let enc_len = rsa.public_encrypt(plain, &mut enc, &mut rng).expect("Error with public_encrypt()"); /// assert!(enc_len > 0 && enc_len <= 512); /// let key_path = "../../../certs/client-key.der"; /// let der: Vec = fs::read(key_path).expect("Error reading key file"); /// let mut rsa = RSA::new_from_der(&der).expect("Error with new_from_der()"); /// rsa.set_rng(&mut rng).expect("Error with set_rng()"); /// let mut plain_out: [u8; 512] = [0; 512]; /// let dec_len = rsa.private_decrypt(&enc[0..enc_len], &mut plain_out).expect("Error with private_decrypt()"); /// assert!(dec_len as usize == plain.len()); /// assert_eq!(plain_out[0..dec_len], *plain); /// } /// ``` #[cfg(random)] pub fn set_rng(&mut self, rng: &mut RNG) -> Result<(), i32> { let rc = unsafe { sys::wc_RsaSetRNG(&mut self.wc_rsakey, &mut rng.wc_rng) }; if rc != 0 { return Err(rc); } Ok(()) } /// Sign the provided data with the private key. /// /// # Parameters /// /// * `din`: Data to sign. /// * `dout`: Buffer in which to store output signature. /// * `rng`: Reference to a `RNG` struct to use for random number /// generation while signing. /// /// # Returns /// /// Returns Ok(size) on success or Err(e) containing the wolfSSL library /// error code value. /// The size returned specifies the number of bytes written to the `dout` /// buffer. /// /// # Example /// /// ```rust /// # extern crate std; /// #[cfg(random)] /// { /// use std::fs; /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::rsa::RSA; /// /// let mut rng = RNG::new().expect("Error creating RNG"); /// /// let key_path = "../../../certs/client-key.der"; /// let der: Vec = fs::read(key_path).expect("Error reading key file"); /// let mut rsa = RSA::new_from_der(&der).expect("Error with new_from_der()"); /// let msg: &[u8] = b"This is the string to be signed!"; /// let mut signature: [u8; 512] = [0; 512]; /// let sig_len = rsa.ssl_sign(msg, &mut signature, &mut rng).expect("Error with ssl_sign()"); /// assert!(sig_len > 0 && sig_len <= 512); /// /// let key_path = "../../../certs/client-keyPub.der"; /// let der: Vec = fs::read(key_path).expect("Error reading key file"); /// let mut rsa = RSA::new_public_from_der(&der).expect("Error with new_public_from_der()"); /// rsa.set_rng(&mut rng).expect("Error with set_rng()"); /// let signature = &signature[0..sig_len]; /// let mut verify_out: [u8; 512] = [0; 512]; /// let verify_out_size = rsa.ssl_verify(signature, &mut verify_out).expect("Error with ssl_verify()"); /// assert!(verify_out_size > 0 && verify_out_size <= 512); /// } /// ``` #[cfg(random)] pub fn ssl_sign(&mut self, din: &[u8], dout: &mut [u8], rng: &mut RNG) -> Result { let din_size = crate::buffer_len_to_u32(din.len())?; let dout_size = crate::buffer_len_to_u32(dout.len())?; let rc = unsafe { sys::wc_RsaSSL_Sign(din.as_ptr(), din_size, dout.as_mut_ptr(), dout_size, &mut self.wc_rsakey, &mut rng.wc_rng) }; if rc < 0 { return Err(rc); } Ok(rc as usize) } /// Decrypt input signature to verify that the message was signed by key. /// /// `set_rng()` must be called previously when wolfSSL is built with /// WC_RSA_BLINDING option enabled. /// /// # Parameters /// /// * `din`: Input data to decrypt. /// * `dout`: Buffer in which to store decrypted data. /// /// # Returns /// /// Returns Ok(size) on success or Err(e) containing the wolfSSL library /// error code value. /// The size returned specifies the number of bytes written to the `dout` /// buffer. /// /// # Example /// /// ```rust /// # extern crate std; /// #[cfg(random)] /// { /// use std::fs; /// use wolfssl_wolfcrypt::random::RNG; /// use wolfssl_wolfcrypt::rsa::RSA; /// /// let mut rng = RNG::new().expect("Error creating RNG"); /// /// let key_path = "../../../certs/client-key.der"; /// let der: Vec = fs::read(key_path).expect("Error reading key file"); /// let mut rsa = RSA::new_from_der(&der).expect("Error with new_from_der()"); /// let msg: &[u8] = b"This is the string to be signed!"; /// let mut signature: [u8; 512] = [0; 512]; /// let sig_len = rsa.ssl_sign(msg, &mut signature, &mut rng).expect("Error with ssl_sign()"); /// assert!(sig_len > 0 && sig_len <= 512); /// /// let key_path = "../../../certs/client-keyPub.der"; /// let der: Vec = fs::read(key_path).expect("Error reading key file"); /// let mut rsa = RSA::new_public_from_der(&der).expect("Error with new_public_from_der()"); /// rsa.set_rng(&mut rng).expect("Error with set_rng()"); /// let signature = &signature[0..sig_len]; /// let mut verify_out: [u8; 512] = [0; 512]; /// let verify_out_size = rsa.ssl_verify(signature, &mut verify_out).expect("Error with ssl_verify()"); /// assert!(verify_out_size > 0 && verify_out_size <= 512); /// } /// ``` pub fn ssl_verify(&mut self, din: &[u8], dout: &mut [u8]) -> Result { let din_size = crate::buffer_len_to_u32(din.len())?; let dout_size = crate::buffer_len_to_u32(dout.len())?; let rc = unsafe { sys::wc_RsaSSL_Verify(din.as_ptr(), din_size, dout.as_mut_ptr(), dout_size, &mut self.wc_rsakey) }; if rc < 0 { return Err(rc); } Ok(rc as usize) } } impl RSA { fn zeroize(&mut self) { unsafe { crate::zeroize_raw(&mut self.wc_rsakey); } } } impl Drop for RSA { /// Safely free the underlying wolfSSL RSA context. /// /// This calls the `wc_FreeRsaKey` wolfssl library function. /// /// The Rust Drop trait guarantees that this method is called when the RSA /// struct goes out of scope, automatically cleaning up resources and /// preventing memory leaks. fn drop(&mut self) { unsafe { sys::wc_FreeRsaKey(&mut self.wc_rsakey); } self.zeroize(); } }