192f3ab15Sopenharmony_ci//! The asymmetric encryption context. 292f3ab15Sopenharmony_ci//! 392f3ab15Sopenharmony_ci//! # Examples 492f3ab15Sopenharmony_ci//! 592f3ab15Sopenharmony_ci//! Encrypt data with RSA 692f3ab15Sopenharmony_ci//! 792f3ab15Sopenharmony_ci//! ``` 892f3ab15Sopenharmony_ci//! use openssl::rsa::Rsa; 992f3ab15Sopenharmony_ci//! use openssl::pkey::PKey; 1092f3ab15Sopenharmony_ci//! use openssl::pkey_ctx::PkeyCtx; 1192f3ab15Sopenharmony_ci//! 1292f3ab15Sopenharmony_ci//! let key = Rsa::generate(4096).unwrap(); 1392f3ab15Sopenharmony_ci//! let key = PKey::from_rsa(key).unwrap(); 1492f3ab15Sopenharmony_ci//! 1592f3ab15Sopenharmony_ci//! let mut ctx = PkeyCtx::new(&key).unwrap(); 1692f3ab15Sopenharmony_ci//! ctx.encrypt_init().unwrap(); 1792f3ab15Sopenharmony_ci//! 1892f3ab15Sopenharmony_ci//! let data = b"Some Crypto Text"; 1992f3ab15Sopenharmony_ci//! let mut ciphertext = vec![]; 2092f3ab15Sopenharmony_ci//! ctx.encrypt_to_vec(data, &mut ciphertext).unwrap(); 2192f3ab15Sopenharmony_ci//! ``` 2292f3ab15Sopenharmony_ci 2392f3ab15Sopenharmony_ci#![cfg_attr( 2492f3ab15Sopenharmony_ci not(boringssl), 2592f3ab15Sopenharmony_ci doc = r#"\ 2692f3ab15Sopenharmony_ciGenerate a CMAC key 2792f3ab15Sopenharmony_ci 2892f3ab15Sopenharmony_ci``` 2992f3ab15Sopenharmony_ciuse openssl::pkey_ctx::PkeyCtx; 3092f3ab15Sopenharmony_ciuse openssl::pkey::Id; 3192f3ab15Sopenharmony_ciuse openssl::cipher::Cipher; 3292f3ab15Sopenharmony_ci 3392f3ab15Sopenharmony_cilet mut ctx = PkeyCtx::new_id(Id::CMAC).unwrap(); 3492f3ab15Sopenharmony_cictx.keygen_init().unwrap(); 3592f3ab15Sopenharmony_cictx.set_keygen_cipher(Cipher::aes_128_cbc()).unwrap(); 3692f3ab15Sopenharmony_cictx.set_keygen_mac_key(b"0123456789abcdef").unwrap(); 3792f3ab15Sopenharmony_cilet cmac_key = ctx.keygen().unwrap(); 3892f3ab15Sopenharmony_ci```"# 3992f3ab15Sopenharmony_ci)] 4092f3ab15Sopenharmony_ci 4192f3ab15Sopenharmony_ci//! 4292f3ab15Sopenharmony_ci//! Sign and verify data with RSA 4392f3ab15Sopenharmony_ci//! 4492f3ab15Sopenharmony_ci//! ``` 4592f3ab15Sopenharmony_ci//! use openssl::pkey_ctx::PkeyCtx; 4692f3ab15Sopenharmony_ci//! use openssl::pkey::PKey; 4792f3ab15Sopenharmony_ci//! use openssl::rsa::Rsa; 4892f3ab15Sopenharmony_ci//! 4992f3ab15Sopenharmony_ci//! // Generate a random RSA key. 5092f3ab15Sopenharmony_ci//! let key = Rsa::generate(4096).unwrap(); 5192f3ab15Sopenharmony_ci//! let key = PKey::from_rsa(key).unwrap(); 5292f3ab15Sopenharmony_ci//! 5392f3ab15Sopenharmony_ci//! let text = b"Some Crypto Text"; 5492f3ab15Sopenharmony_ci//! 5592f3ab15Sopenharmony_ci//! // Create the signature. 5692f3ab15Sopenharmony_ci//! let mut ctx = PkeyCtx::new(&key).unwrap(); 5792f3ab15Sopenharmony_ci//! ctx.sign_init().unwrap(); 5892f3ab15Sopenharmony_ci//! let mut signature = vec![]; 5992f3ab15Sopenharmony_ci//! ctx.sign_to_vec(text, &mut signature).unwrap(); 6092f3ab15Sopenharmony_ci//! 6192f3ab15Sopenharmony_ci//! // Verify the signature. 6292f3ab15Sopenharmony_ci//! let mut ctx = PkeyCtx::new(&key).unwrap(); 6392f3ab15Sopenharmony_ci//! ctx.verify_init().unwrap(); 6492f3ab15Sopenharmony_ci//! let valid = ctx.verify(text, &signature).unwrap(); 6592f3ab15Sopenharmony_ci//! assert!(valid); 6692f3ab15Sopenharmony_ci//! ``` 6792f3ab15Sopenharmony_ci#[cfg(not(boringssl))] 6892f3ab15Sopenharmony_ciuse crate::cipher::CipherRef; 6992f3ab15Sopenharmony_ciuse crate::error::ErrorStack; 7092f3ab15Sopenharmony_ciuse crate::md::MdRef; 7192f3ab15Sopenharmony_ciuse crate::pkey::{HasPrivate, HasPublic, Id, PKey, PKeyRef, Private}; 7292f3ab15Sopenharmony_ciuse crate::rsa::Padding; 7392f3ab15Sopenharmony_ciuse crate::sign::RsaPssSaltlen; 7492f3ab15Sopenharmony_ciuse crate::{cvt, cvt_p}; 7592f3ab15Sopenharmony_ciuse foreign_types::{ForeignType, ForeignTypeRef}; 7692f3ab15Sopenharmony_ci#[cfg(not(boringssl))] 7792f3ab15Sopenharmony_ciuse libc::c_int; 7892f3ab15Sopenharmony_ciuse openssl_macros::corresponds; 7992f3ab15Sopenharmony_ciuse std::convert::TryFrom; 8092f3ab15Sopenharmony_ciuse std::ptr; 8192f3ab15Sopenharmony_ci 8292f3ab15Sopenharmony_ci/// HKDF modes of operation. 8392f3ab15Sopenharmony_ci#[cfg(ossl111)] 8492f3ab15Sopenharmony_cipub struct HkdfMode(c_int); 8592f3ab15Sopenharmony_ci 8692f3ab15Sopenharmony_ci#[cfg(ossl111)] 8792f3ab15Sopenharmony_ciimpl HkdfMode { 8892f3ab15Sopenharmony_ci /// This is the default mode. Calling [`derive`][PkeyCtxRef::derive] on a [`PkeyCtxRef`] set up 8992f3ab15Sopenharmony_ci /// for HKDF will perform an extract followed by an expand operation in one go. The derived key 9092f3ab15Sopenharmony_ci /// returned will be the result after the expand operation. The intermediate fixed-length 9192f3ab15Sopenharmony_ci /// pseudorandom key K is not returned. 9292f3ab15Sopenharmony_ci pub const EXTRACT_THEN_EXPAND: Self = HkdfMode(ffi::EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND); 9392f3ab15Sopenharmony_ci 9492f3ab15Sopenharmony_ci /// In this mode calling [`derive`][PkeyCtxRef::derive] will just perform the extract operation. 9592f3ab15Sopenharmony_ci /// The value returned will be the intermediate fixed-length pseudorandom key K. 9692f3ab15Sopenharmony_ci /// 9792f3ab15Sopenharmony_ci /// The digest, key and salt values must be set before a key is derived or an error occurs. 9892f3ab15Sopenharmony_ci pub const EXTRACT_ONLY: Self = HkdfMode(ffi::EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY); 9992f3ab15Sopenharmony_ci 10092f3ab15Sopenharmony_ci /// In this mode calling [`derive`][PkeyCtxRef::derive] will just perform the expand operation. 10192f3ab15Sopenharmony_ci /// The input key should be set to the intermediate fixed-length pseudorandom key K returned 10292f3ab15Sopenharmony_ci /// from a previous extract operation. 10392f3ab15Sopenharmony_ci /// 10492f3ab15Sopenharmony_ci /// The digest, key and info values must be set before a key is derived or an error occurs. 10592f3ab15Sopenharmony_ci pub const EXPAND_ONLY: Self = HkdfMode(ffi::EVP_PKEY_HKDEF_MODE_EXPAND_ONLY); 10692f3ab15Sopenharmony_ci} 10792f3ab15Sopenharmony_ci 10892f3ab15Sopenharmony_cigeneric_foreign_type_and_impl_send_sync! { 10992f3ab15Sopenharmony_ci type CType = ffi::EVP_PKEY_CTX; 11092f3ab15Sopenharmony_ci fn drop = ffi::EVP_PKEY_CTX_free; 11192f3ab15Sopenharmony_ci 11292f3ab15Sopenharmony_ci /// A context object which can perform asymmetric cryptography operations. 11392f3ab15Sopenharmony_ci pub struct PkeyCtx<T>; 11492f3ab15Sopenharmony_ci /// A reference to a [`PkeyCtx`]. 11592f3ab15Sopenharmony_ci pub struct PkeyCtxRef<T>; 11692f3ab15Sopenharmony_ci} 11792f3ab15Sopenharmony_ci 11892f3ab15Sopenharmony_ciimpl<T> PkeyCtx<T> { 11992f3ab15Sopenharmony_ci /// Creates a new pkey context using the provided key. 12092f3ab15Sopenharmony_ci #[corresponds(EVP_PKEY_CTX_new)] 12192f3ab15Sopenharmony_ci #[inline] 12292f3ab15Sopenharmony_ci pub fn new(pkey: &PKeyRef<T>) -> Result<Self, ErrorStack> { 12392f3ab15Sopenharmony_ci unsafe { 12492f3ab15Sopenharmony_ci let ptr = cvt_p(ffi::EVP_PKEY_CTX_new(pkey.as_ptr(), ptr::null_mut()))?; 12592f3ab15Sopenharmony_ci Ok(PkeyCtx::from_ptr(ptr)) 12692f3ab15Sopenharmony_ci } 12792f3ab15Sopenharmony_ci } 12892f3ab15Sopenharmony_ci} 12992f3ab15Sopenharmony_ci 13092f3ab15Sopenharmony_ciimpl PkeyCtx<()> { 13192f3ab15Sopenharmony_ci /// Creates a new pkey context for the specified algorithm ID. 13292f3ab15Sopenharmony_ci #[corresponds(EVP_PKEY_new_id)] 13392f3ab15Sopenharmony_ci #[inline] 13492f3ab15Sopenharmony_ci pub fn new_id(id: Id) -> Result<Self, ErrorStack> { 13592f3ab15Sopenharmony_ci unsafe { 13692f3ab15Sopenharmony_ci let ptr = cvt_p(ffi::EVP_PKEY_CTX_new_id(id.as_raw(), ptr::null_mut()))?; 13792f3ab15Sopenharmony_ci Ok(PkeyCtx::from_ptr(ptr)) 13892f3ab15Sopenharmony_ci } 13992f3ab15Sopenharmony_ci } 14092f3ab15Sopenharmony_ci} 14192f3ab15Sopenharmony_ci 14292f3ab15Sopenharmony_ciimpl<T> PkeyCtxRef<T> 14392f3ab15Sopenharmony_ciwhere 14492f3ab15Sopenharmony_ci T: HasPublic, 14592f3ab15Sopenharmony_ci{ 14692f3ab15Sopenharmony_ci /// Prepares the context for encryption using the public key. 14792f3ab15Sopenharmony_ci #[corresponds(EVP_PKEY_encrypt_init)] 14892f3ab15Sopenharmony_ci #[inline] 14992f3ab15Sopenharmony_ci pub fn encrypt_init(&mut self) -> Result<(), ErrorStack> { 15092f3ab15Sopenharmony_ci unsafe { 15192f3ab15Sopenharmony_ci cvt(ffi::EVP_PKEY_encrypt_init(self.as_ptr()))?; 15292f3ab15Sopenharmony_ci } 15392f3ab15Sopenharmony_ci 15492f3ab15Sopenharmony_ci Ok(()) 15592f3ab15Sopenharmony_ci } 15692f3ab15Sopenharmony_ci 15792f3ab15Sopenharmony_ci /// Prepares the context for signature verification using the public key. 15892f3ab15Sopenharmony_ci #[corresponds(EVP_PKEY_verify_init)] 15992f3ab15Sopenharmony_ci #[inline] 16092f3ab15Sopenharmony_ci pub fn verify_init(&mut self) -> Result<(), ErrorStack> { 16192f3ab15Sopenharmony_ci unsafe { 16292f3ab15Sopenharmony_ci cvt(ffi::EVP_PKEY_verify_init(self.as_ptr()))?; 16392f3ab15Sopenharmony_ci } 16492f3ab15Sopenharmony_ci 16592f3ab15Sopenharmony_ci Ok(()) 16692f3ab15Sopenharmony_ci } 16792f3ab15Sopenharmony_ci 16892f3ab15Sopenharmony_ci /// Prepares the context for signature recovery using the public key. 16992f3ab15Sopenharmony_ci #[corresponds(EVP_PKEY_verify_recover_init)] 17092f3ab15Sopenharmony_ci #[inline] 17192f3ab15Sopenharmony_ci pub fn verify_recover_init(&mut self) -> Result<(), ErrorStack> { 17292f3ab15Sopenharmony_ci unsafe { 17392f3ab15Sopenharmony_ci cvt(ffi::EVP_PKEY_verify_recover_init(self.as_ptr()))?; 17492f3ab15Sopenharmony_ci } 17592f3ab15Sopenharmony_ci 17692f3ab15Sopenharmony_ci Ok(()) 17792f3ab15Sopenharmony_ci } 17892f3ab15Sopenharmony_ci 17992f3ab15Sopenharmony_ci /// Encrypts data using the public key. 18092f3ab15Sopenharmony_ci /// 18192f3ab15Sopenharmony_ci /// If `to` is set to `None`, an upper bound on the number of bytes required for the output buffer will be 18292f3ab15Sopenharmony_ci /// returned. 18392f3ab15Sopenharmony_ci #[corresponds(EVP_PKEY_encrypt)] 18492f3ab15Sopenharmony_ci #[inline] 18592f3ab15Sopenharmony_ci pub fn encrypt(&mut self, from: &[u8], to: Option<&mut [u8]>) -> Result<usize, ErrorStack> { 18692f3ab15Sopenharmony_ci let mut written = to.as_ref().map_or(0, |b| b.len()); 18792f3ab15Sopenharmony_ci unsafe { 18892f3ab15Sopenharmony_ci cvt(ffi::EVP_PKEY_encrypt( 18992f3ab15Sopenharmony_ci self.as_ptr(), 19092f3ab15Sopenharmony_ci to.map_or(ptr::null_mut(), |b| b.as_mut_ptr()), 19192f3ab15Sopenharmony_ci &mut written, 19292f3ab15Sopenharmony_ci from.as_ptr(), 19392f3ab15Sopenharmony_ci from.len(), 19492f3ab15Sopenharmony_ci ))?; 19592f3ab15Sopenharmony_ci } 19692f3ab15Sopenharmony_ci 19792f3ab15Sopenharmony_ci Ok(written) 19892f3ab15Sopenharmony_ci } 19992f3ab15Sopenharmony_ci 20092f3ab15Sopenharmony_ci /// Like [`Self::encrypt`] but appends ciphertext to a [`Vec`]. 20192f3ab15Sopenharmony_ci pub fn encrypt_to_vec(&mut self, from: &[u8], out: &mut Vec<u8>) -> Result<usize, ErrorStack> { 20292f3ab15Sopenharmony_ci let base = out.len(); 20392f3ab15Sopenharmony_ci let len = self.encrypt(from, None)?; 20492f3ab15Sopenharmony_ci out.resize(base + len, 0); 20592f3ab15Sopenharmony_ci let len = self.encrypt(from, Some(&mut out[base..]))?; 20692f3ab15Sopenharmony_ci out.truncate(base + len); 20792f3ab15Sopenharmony_ci Ok(len) 20892f3ab15Sopenharmony_ci } 20992f3ab15Sopenharmony_ci 21092f3ab15Sopenharmony_ci /// Verifies the signature of data using the public key. 21192f3ab15Sopenharmony_ci /// 21292f3ab15Sopenharmony_ci /// Returns `Ok(true)` if the signature is valid, `Ok(false)` if the signature is invalid, and `Err` if an error 21392f3ab15Sopenharmony_ci /// occurred. 21492f3ab15Sopenharmony_ci /// 21592f3ab15Sopenharmony_ci /// # Note 21692f3ab15Sopenharmony_ci /// 21792f3ab15Sopenharmony_ci /// This verifies the signature of the *raw* data. It is more common to compute and verify the signature of the 21892f3ab15Sopenharmony_ci /// cryptographic hash of an arbitrary amount of data. The [`MdCtx`](crate::md_ctx::MdCtx) type can be used to do 21992f3ab15Sopenharmony_ci /// that. 22092f3ab15Sopenharmony_ci #[corresponds(EVP_PKEY_verify)] 22192f3ab15Sopenharmony_ci #[inline] 22292f3ab15Sopenharmony_ci pub fn verify(&mut self, data: &[u8], sig: &[u8]) -> Result<bool, ErrorStack> { 22392f3ab15Sopenharmony_ci unsafe { 22492f3ab15Sopenharmony_ci let r = ffi::EVP_PKEY_verify( 22592f3ab15Sopenharmony_ci self.as_ptr(), 22692f3ab15Sopenharmony_ci sig.as_ptr(), 22792f3ab15Sopenharmony_ci sig.len(), 22892f3ab15Sopenharmony_ci data.as_ptr(), 22992f3ab15Sopenharmony_ci data.len(), 23092f3ab15Sopenharmony_ci ); 23192f3ab15Sopenharmony_ci // `EVP_PKEY_verify` is not terribly consistent about how it, 23292f3ab15Sopenharmony_ci // reports errors. It does not clearly distinguish between 0 and 23392f3ab15Sopenharmony_ci // -1, and may put errors on the stack in both cases. If there's 23492f3ab15Sopenharmony_ci // errors on the stack, we return `Err()`, else we return 23592f3ab15Sopenharmony_ci // `Ok(false)`. 23692f3ab15Sopenharmony_ci if r <= 0 { 23792f3ab15Sopenharmony_ci let errors = ErrorStack::get(); 23892f3ab15Sopenharmony_ci if !errors.errors().is_empty() { 23992f3ab15Sopenharmony_ci return Err(errors); 24092f3ab15Sopenharmony_ci } 24192f3ab15Sopenharmony_ci } 24292f3ab15Sopenharmony_ci 24392f3ab15Sopenharmony_ci Ok(r == 1) 24492f3ab15Sopenharmony_ci } 24592f3ab15Sopenharmony_ci } 24692f3ab15Sopenharmony_ci 24792f3ab15Sopenharmony_ci /// Recovers the original data signed by the private key. You almost 24892f3ab15Sopenharmony_ci /// always want `verify` instead. 24992f3ab15Sopenharmony_ci /// 25092f3ab15Sopenharmony_ci /// Returns the number of bytes written to `to`, or the number of bytes 25192f3ab15Sopenharmony_ci /// that would be written, if `to` is `None. 25292f3ab15Sopenharmony_ci #[corresponds(EVP_PKEY_verify_recover)] 25392f3ab15Sopenharmony_ci #[inline] 25492f3ab15Sopenharmony_ci pub fn verify_recover( 25592f3ab15Sopenharmony_ci &mut self, 25692f3ab15Sopenharmony_ci sig: &[u8], 25792f3ab15Sopenharmony_ci to: Option<&mut [u8]>, 25892f3ab15Sopenharmony_ci ) -> Result<usize, ErrorStack> { 25992f3ab15Sopenharmony_ci let mut written = to.as_ref().map_or(0, |b| b.len()); 26092f3ab15Sopenharmony_ci unsafe { 26192f3ab15Sopenharmony_ci cvt(ffi::EVP_PKEY_verify_recover( 26292f3ab15Sopenharmony_ci self.as_ptr(), 26392f3ab15Sopenharmony_ci to.map_or(ptr::null_mut(), |b| b.as_mut_ptr()), 26492f3ab15Sopenharmony_ci &mut written, 26592f3ab15Sopenharmony_ci sig.as_ptr(), 26692f3ab15Sopenharmony_ci sig.len(), 26792f3ab15Sopenharmony_ci ))?; 26892f3ab15Sopenharmony_ci } 26992f3ab15Sopenharmony_ci 27092f3ab15Sopenharmony_ci Ok(written) 27192f3ab15Sopenharmony_ci } 27292f3ab15Sopenharmony_ci} 27392f3ab15Sopenharmony_ci 27492f3ab15Sopenharmony_ciimpl<T> PkeyCtxRef<T> 27592f3ab15Sopenharmony_ciwhere 27692f3ab15Sopenharmony_ci T: HasPrivate, 27792f3ab15Sopenharmony_ci{ 27892f3ab15Sopenharmony_ci /// Prepares the context for decryption using the private key. 27992f3ab15Sopenharmony_ci #[corresponds(EVP_PKEY_decrypt_init)] 28092f3ab15Sopenharmony_ci #[inline] 28192f3ab15Sopenharmony_ci pub fn decrypt_init(&mut self) -> Result<(), ErrorStack> { 28292f3ab15Sopenharmony_ci unsafe { 28392f3ab15Sopenharmony_ci cvt(ffi::EVP_PKEY_decrypt_init(self.as_ptr()))?; 28492f3ab15Sopenharmony_ci } 28592f3ab15Sopenharmony_ci 28692f3ab15Sopenharmony_ci Ok(()) 28792f3ab15Sopenharmony_ci } 28892f3ab15Sopenharmony_ci 28992f3ab15Sopenharmony_ci /// Prepares the context for signing using the private key. 29092f3ab15Sopenharmony_ci #[corresponds(EVP_PKEY_sign_init)] 29192f3ab15Sopenharmony_ci #[inline] 29292f3ab15Sopenharmony_ci pub fn sign_init(&mut self) -> Result<(), ErrorStack> { 29392f3ab15Sopenharmony_ci unsafe { 29492f3ab15Sopenharmony_ci cvt(ffi::EVP_PKEY_sign_init(self.as_ptr()))?; 29592f3ab15Sopenharmony_ci } 29692f3ab15Sopenharmony_ci 29792f3ab15Sopenharmony_ci Ok(()) 29892f3ab15Sopenharmony_ci } 29992f3ab15Sopenharmony_ci 30092f3ab15Sopenharmony_ci /// Sets the peer key used for secret derivation. 30192f3ab15Sopenharmony_ci #[corresponds(EVP_PKEY_derive_set_peer)] 30292f3ab15Sopenharmony_ci pub fn derive_set_peer<U>(&mut self, key: &PKeyRef<U>) -> Result<(), ErrorStack> 30392f3ab15Sopenharmony_ci where 30492f3ab15Sopenharmony_ci U: HasPublic, 30592f3ab15Sopenharmony_ci { 30692f3ab15Sopenharmony_ci unsafe { 30792f3ab15Sopenharmony_ci cvt(ffi::EVP_PKEY_derive_set_peer(self.as_ptr(), key.as_ptr()))?; 30892f3ab15Sopenharmony_ci } 30992f3ab15Sopenharmony_ci 31092f3ab15Sopenharmony_ci Ok(()) 31192f3ab15Sopenharmony_ci } 31292f3ab15Sopenharmony_ci 31392f3ab15Sopenharmony_ci /// Decrypts data using the private key. 31492f3ab15Sopenharmony_ci /// 31592f3ab15Sopenharmony_ci /// If `to` is set to `None`, an upper bound on the number of bytes required for the output buffer will be 31692f3ab15Sopenharmony_ci /// returned. 31792f3ab15Sopenharmony_ci #[corresponds(EVP_PKEY_decrypt)] 31892f3ab15Sopenharmony_ci #[inline] 31992f3ab15Sopenharmony_ci pub fn decrypt(&mut self, from: &[u8], to: Option<&mut [u8]>) -> Result<usize, ErrorStack> { 32092f3ab15Sopenharmony_ci let mut written = to.as_ref().map_or(0, |b| b.len()); 32192f3ab15Sopenharmony_ci unsafe { 32292f3ab15Sopenharmony_ci cvt(ffi::EVP_PKEY_decrypt( 32392f3ab15Sopenharmony_ci self.as_ptr(), 32492f3ab15Sopenharmony_ci to.map_or(ptr::null_mut(), |b| b.as_mut_ptr()), 32592f3ab15Sopenharmony_ci &mut written, 32692f3ab15Sopenharmony_ci from.as_ptr(), 32792f3ab15Sopenharmony_ci from.len(), 32892f3ab15Sopenharmony_ci ))?; 32992f3ab15Sopenharmony_ci } 33092f3ab15Sopenharmony_ci 33192f3ab15Sopenharmony_ci Ok(written) 33292f3ab15Sopenharmony_ci } 33392f3ab15Sopenharmony_ci 33492f3ab15Sopenharmony_ci /// Like [`Self::decrypt`] but appends plaintext to a [`Vec`]. 33592f3ab15Sopenharmony_ci pub fn decrypt_to_vec(&mut self, from: &[u8], out: &mut Vec<u8>) -> Result<usize, ErrorStack> { 33692f3ab15Sopenharmony_ci let base = out.len(); 33792f3ab15Sopenharmony_ci let len = self.decrypt(from, None)?; 33892f3ab15Sopenharmony_ci out.resize(base + len, 0); 33992f3ab15Sopenharmony_ci let len = self.decrypt(from, Some(&mut out[base..]))?; 34092f3ab15Sopenharmony_ci out.truncate(base + len); 34192f3ab15Sopenharmony_ci Ok(len) 34292f3ab15Sopenharmony_ci } 34392f3ab15Sopenharmony_ci 34492f3ab15Sopenharmony_ci /// Signs the contents of `data`. 34592f3ab15Sopenharmony_ci /// 34692f3ab15Sopenharmony_ci /// If `sig` is set to `None`, an upper bound on the number of bytes required for the output buffer will be 34792f3ab15Sopenharmony_ci /// returned. 34892f3ab15Sopenharmony_ci /// 34992f3ab15Sopenharmony_ci /// # Note 35092f3ab15Sopenharmony_ci /// 35192f3ab15Sopenharmony_ci /// This computes the signature of the *raw* bytes of `data`. It is more common to sign the cryptographic hash of 35292f3ab15Sopenharmony_ci /// an arbitrary amount of data. The [`MdCtx`](crate::md_ctx::MdCtx) type can be used to do that. 35392f3ab15Sopenharmony_ci #[corresponds(EVP_PKEY_sign)] 35492f3ab15Sopenharmony_ci #[inline] 35592f3ab15Sopenharmony_ci pub fn sign(&mut self, data: &[u8], sig: Option<&mut [u8]>) -> Result<usize, ErrorStack> { 35692f3ab15Sopenharmony_ci let mut written = sig.as_ref().map_or(0, |b| b.len()); 35792f3ab15Sopenharmony_ci unsafe { 35892f3ab15Sopenharmony_ci cvt(ffi::EVP_PKEY_sign( 35992f3ab15Sopenharmony_ci self.as_ptr(), 36092f3ab15Sopenharmony_ci sig.map_or(ptr::null_mut(), |b| b.as_mut_ptr()), 36192f3ab15Sopenharmony_ci &mut written, 36292f3ab15Sopenharmony_ci data.as_ptr(), 36392f3ab15Sopenharmony_ci data.len(), 36492f3ab15Sopenharmony_ci ))?; 36592f3ab15Sopenharmony_ci } 36692f3ab15Sopenharmony_ci 36792f3ab15Sopenharmony_ci Ok(written) 36892f3ab15Sopenharmony_ci } 36992f3ab15Sopenharmony_ci 37092f3ab15Sopenharmony_ci /// Like [`Self::sign`] but appends the signature to a [`Vec`]. 37192f3ab15Sopenharmony_ci pub fn sign_to_vec(&mut self, data: &[u8], sig: &mut Vec<u8>) -> Result<usize, ErrorStack> { 37292f3ab15Sopenharmony_ci let base = sig.len(); 37392f3ab15Sopenharmony_ci let len = self.sign(data, None)?; 37492f3ab15Sopenharmony_ci sig.resize(base + len, 0); 37592f3ab15Sopenharmony_ci let len = self.sign(data, Some(&mut sig[base..]))?; 37692f3ab15Sopenharmony_ci sig.truncate(base + len); 37792f3ab15Sopenharmony_ci Ok(len) 37892f3ab15Sopenharmony_ci } 37992f3ab15Sopenharmony_ci} 38092f3ab15Sopenharmony_ci 38192f3ab15Sopenharmony_ciimpl<T> PkeyCtxRef<T> { 38292f3ab15Sopenharmony_ci /// Prepares the context for shared secret derivation. 38392f3ab15Sopenharmony_ci #[corresponds(EVP_PKEY_derive_init)] 38492f3ab15Sopenharmony_ci #[inline] 38592f3ab15Sopenharmony_ci pub fn derive_init(&mut self) -> Result<(), ErrorStack> { 38692f3ab15Sopenharmony_ci unsafe { 38792f3ab15Sopenharmony_ci cvt(ffi::EVP_PKEY_derive_init(self.as_ptr()))?; 38892f3ab15Sopenharmony_ci } 38992f3ab15Sopenharmony_ci 39092f3ab15Sopenharmony_ci Ok(()) 39192f3ab15Sopenharmony_ci } 39292f3ab15Sopenharmony_ci 39392f3ab15Sopenharmony_ci /// Prepares the context for key generation. 39492f3ab15Sopenharmony_ci #[corresponds(EVP_PKEY_keygen_init)] 39592f3ab15Sopenharmony_ci #[inline] 39692f3ab15Sopenharmony_ci pub fn keygen_init(&mut self) -> Result<(), ErrorStack> { 39792f3ab15Sopenharmony_ci unsafe { 39892f3ab15Sopenharmony_ci cvt(ffi::EVP_PKEY_keygen_init(self.as_ptr()))?; 39992f3ab15Sopenharmony_ci } 40092f3ab15Sopenharmony_ci 40192f3ab15Sopenharmony_ci Ok(()) 40292f3ab15Sopenharmony_ci } 40392f3ab15Sopenharmony_ci 40492f3ab15Sopenharmony_ci /// Sets which algorithm was used to compute the digest used in a 40592f3ab15Sopenharmony_ci /// signature. With RSA signatures this causes the signature to be wrapped 40692f3ab15Sopenharmony_ci /// in a `DigestInfo` structure. This is almost always what you want with 40792f3ab15Sopenharmony_ci /// RSA signatures. 40892f3ab15Sopenharmony_ci #[corresponds(EVP_PKEY_CTX_set_signature_md)] 40992f3ab15Sopenharmony_ci #[inline] 41092f3ab15Sopenharmony_ci pub fn set_signature_md(&self, md: &MdRef) -> Result<(), ErrorStack> { 41192f3ab15Sopenharmony_ci unsafe { 41292f3ab15Sopenharmony_ci cvt(ffi::EVP_PKEY_CTX_set_signature_md( 41392f3ab15Sopenharmony_ci self.as_ptr(), 41492f3ab15Sopenharmony_ci md.as_ptr(), 41592f3ab15Sopenharmony_ci ))?; 41692f3ab15Sopenharmony_ci } 41792f3ab15Sopenharmony_ci Ok(()) 41892f3ab15Sopenharmony_ci } 41992f3ab15Sopenharmony_ci 42092f3ab15Sopenharmony_ci /// Returns the RSA padding mode in use. 42192f3ab15Sopenharmony_ci /// 42292f3ab15Sopenharmony_ci /// This is only useful for RSA keys. 42392f3ab15Sopenharmony_ci #[corresponds(EVP_PKEY_CTX_get_rsa_padding)] 42492f3ab15Sopenharmony_ci #[inline] 42592f3ab15Sopenharmony_ci pub fn rsa_padding(&self) -> Result<Padding, ErrorStack> { 42692f3ab15Sopenharmony_ci let mut pad = 0; 42792f3ab15Sopenharmony_ci unsafe { 42892f3ab15Sopenharmony_ci cvt(ffi::EVP_PKEY_CTX_get_rsa_padding(self.as_ptr(), &mut pad))?; 42992f3ab15Sopenharmony_ci } 43092f3ab15Sopenharmony_ci 43192f3ab15Sopenharmony_ci Ok(Padding::from_raw(pad)) 43292f3ab15Sopenharmony_ci } 43392f3ab15Sopenharmony_ci 43492f3ab15Sopenharmony_ci /// Sets the RSA padding mode. 43592f3ab15Sopenharmony_ci /// 43692f3ab15Sopenharmony_ci /// This is only useful for RSA keys. 43792f3ab15Sopenharmony_ci #[corresponds(EVP_PKEY_CTX_set_rsa_padding)] 43892f3ab15Sopenharmony_ci #[inline] 43992f3ab15Sopenharmony_ci pub fn set_rsa_padding(&mut self, padding: Padding) -> Result<(), ErrorStack> { 44092f3ab15Sopenharmony_ci unsafe { 44192f3ab15Sopenharmony_ci cvt(ffi::EVP_PKEY_CTX_set_rsa_padding( 44292f3ab15Sopenharmony_ci self.as_ptr(), 44392f3ab15Sopenharmony_ci padding.as_raw(), 44492f3ab15Sopenharmony_ci ))?; 44592f3ab15Sopenharmony_ci } 44692f3ab15Sopenharmony_ci 44792f3ab15Sopenharmony_ci Ok(()) 44892f3ab15Sopenharmony_ci } 44992f3ab15Sopenharmony_ci 45092f3ab15Sopenharmony_ci /// Sets the RSA PSS salt length. 45192f3ab15Sopenharmony_ci /// 45292f3ab15Sopenharmony_ci /// This is only useful for RSA keys. 45392f3ab15Sopenharmony_ci #[corresponds(EVP_PKEY_CTX_set_rsa_pss_saltlen)] 45492f3ab15Sopenharmony_ci #[inline] 45592f3ab15Sopenharmony_ci pub fn set_rsa_pss_saltlen(&mut self, len: RsaPssSaltlen) -> Result<(), ErrorStack> { 45692f3ab15Sopenharmony_ci unsafe { 45792f3ab15Sopenharmony_ci cvt(ffi::EVP_PKEY_CTX_set_rsa_pss_saltlen( 45892f3ab15Sopenharmony_ci self.as_ptr(), 45992f3ab15Sopenharmony_ci len.as_raw(), 46092f3ab15Sopenharmony_ci )) 46192f3ab15Sopenharmony_ci .map(|_| ()) 46292f3ab15Sopenharmony_ci } 46392f3ab15Sopenharmony_ci } 46492f3ab15Sopenharmony_ci 46592f3ab15Sopenharmony_ci /// Sets the RSA MGF1 algorithm. 46692f3ab15Sopenharmony_ci /// 46792f3ab15Sopenharmony_ci /// This is only useful for RSA keys. 46892f3ab15Sopenharmony_ci #[corresponds(EVP_PKEY_CTX_set_rsa_mgf1_md)] 46992f3ab15Sopenharmony_ci #[inline] 47092f3ab15Sopenharmony_ci pub fn set_rsa_mgf1_md(&mut self, md: &MdRef) -> Result<(), ErrorStack> { 47192f3ab15Sopenharmony_ci unsafe { 47292f3ab15Sopenharmony_ci cvt(ffi::EVP_PKEY_CTX_set_rsa_mgf1_md( 47392f3ab15Sopenharmony_ci self.as_ptr(), 47492f3ab15Sopenharmony_ci md.as_ptr(), 47592f3ab15Sopenharmony_ci ))?; 47692f3ab15Sopenharmony_ci } 47792f3ab15Sopenharmony_ci 47892f3ab15Sopenharmony_ci Ok(()) 47992f3ab15Sopenharmony_ci } 48092f3ab15Sopenharmony_ci 48192f3ab15Sopenharmony_ci /// Sets the RSA OAEP algorithm. 48292f3ab15Sopenharmony_ci /// 48392f3ab15Sopenharmony_ci /// This is only useful for RSA keys. 48492f3ab15Sopenharmony_ci #[corresponds(EVP_PKEY_CTX_set_rsa_oaep_md)] 48592f3ab15Sopenharmony_ci #[cfg(any(ossl102, libressl310, boringssl))] 48692f3ab15Sopenharmony_ci #[inline] 48792f3ab15Sopenharmony_ci pub fn set_rsa_oaep_md(&mut self, md: &MdRef) -> Result<(), ErrorStack> { 48892f3ab15Sopenharmony_ci unsafe { 48992f3ab15Sopenharmony_ci cvt(ffi::EVP_PKEY_CTX_set_rsa_oaep_md( 49092f3ab15Sopenharmony_ci self.as_ptr(), 49192f3ab15Sopenharmony_ci md.as_ptr() as *mut _, 49292f3ab15Sopenharmony_ci ))?; 49392f3ab15Sopenharmony_ci } 49492f3ab15Sopenharmony_ci 49592f3ab15Sopenharmony_ci Ok(()) 49692f3ab15Sopenharmony_ci } 49792f3ab15Sopenharmony_ci 49892f3ab15Sopenharmony_ci /// Sets the RSA OAEP label. 49992f3ab15Sopenharmony_ci /// 50092f3ab15Sopenharmony_ci /// This is only useful for RSA keys. 50192f3ab15Sopenharmony_ci #[corresponds(EVP_PKEY_CTX_set0_rsa_oaep_label)] 50292f3ab15Sopenharmony_ci #[cfg(any(ossl102, libressl310, boringssl))] 50392f3ab15Sopenharmony_ci pub fn set_rsa_oaep_label(&mut self, label: &[u8]) -> Result<(), ErrorStack> { 50492f3ab15Sopenharmony_ci use crate::LenType; 50592f3ab15Sopenharmony_ci let len = LenType::try_from(label.len()).unwrap(); 50692f3ab15Sopenharmony_ci 50792f3ab15Sopenharmony_ci unsafe { 50892f3ab15Sopenharmony_ci let p = ffi::OPENSSL_malloc(label.len() as _); 50992f3ab15Sopenharmony_ci ptr::copy_nonoverlapping(label.as_ptr(), p as *mut _, label.len()); 51092f3ab15Sopenharmony_ci 51192f3ab15Sopenharmony_ci let r = cvt(ffi::EVP_PKEY_CTX_set0_rsa_oaep_label( 51292f3ab15Sopenharmony_ci self.as_ptr(), 51392f3ab15Sopenharmony_ci p as *mut _, 51492f3ab15Sopenharmony_ci len, 51592f3ab15Sopenharmony_ci )); 51692f3ab15Sopenharmony_ci if r.is_err() { 51792f3ab15Sopenharmony_ci ffi::OPENSSL_free(p); 51892f3ab15Sopenharmony_ci } 51992f3ab15Sopenharmony_ci r?; 52092f3ab15Sopenharmony_ci } 52192f3ab15Sopenharmony_ci 52292f3ab15Sopenharmony_ci Ok(()) 52392f3ab15Sopenharmony_ci } 52492f3ab15Sopenharmony_ci 52592f3ab15Sopenharmony_ci /// Sets the cipher used during key generation. 52692f3ab15Sopenharmony_ci #[cfg(not(boringssl))] 52792f3ab15Sopenharmony_ci #[corresponds(EVP_PKEY_CTX_ctrl)] 52892f3ab15Sopenharmony_ci #[inline] 52992f3ab15Sopenharmony_ci pub fn set_keygen_cipher(&mut self, cipher: &CipherRef) -> Result<(), ErrorStack> { 53092f3ab15Sopenharmony_ci unsafe { 53192f3ab15Sopenharmony_ci cvt(ffi::EVP_PKEY_CTX_ctrl( 53292f3ab15Sopenharmony_ci self.as_ptr(), 53392f3ab15Sopenharmony_ci -1, 53492f3ab15Sopenharmony_ci ffi::EVP_PKEY_OP_KEYGEN, 53592f3ab15Sopenharmony_ci ffi::EVP_PKEY_CTRL_CIPHER, 53692f3ab15Sopenharmony_ci 0, 53792f3ab15Sopenharmony_ci cipher.as_ptr() as *mut _, 53892f3ab15Sopenharmony_ci ))?; 53992f3ab15Sopenharmony_ci } 54092f3ab15Sopenharmony_ci 54192f3ab15Sopenharmony_ci Ok(()) 54292f3ab15Sopenharmony_ci } 54392f3ab15Sopenharmony_ci 54492f3ab15Sopenharmony_ci /// Sets the key MAC key used during key generation. 54592f3ab15Sopenharmony_ci #[cfg(not(boringssl))] 54692f3ab15Sopenharmony_ci #[corresponds(EVP_PKEY_CTX_ctrl)] 54792f3ab15Sopenharmony_ci #[inline] 54892f3ab15Sopenharmony_ci pub fn set_keygen_mac_key(&mut self, key: &[u8]) -> Result<(), ErrorStack> { 54992f3ab15Sopenharmony_ci let len = c_int::try_from(key.len()).unwrap(); 55092f3ab15Sopenharmony_ci 55192f3ab15Sopenharmony_ci unsafe { 55292f3ab15Sopenharmony_ci cvt(ffi::EVP_PKEY_CTX_ctrl( 55392f3ab15Sopenharmony_ci self.as_ptr(), 55492f3ab15Sopenharmony_ci -1, 55592f3ab15Sopenharmony_ci ffi::EVP_PKEY_OP_KEYGEN, 55692f3ab15Sopenharmony_ci ffi::EVP_PKEY_CTRL_SET_MAC_KEY, 55792f3ab15Sopenharmony_ci len, 55892f3ab15Sopenharmony_ci key.as_ptr() as *mut _, 55992f3ab15Sopenharmony_ci ))?; 56092f3ab15Sopenharmony_ci } 56192f3ab15Sopenharmony_ci 56292f3ab15Sopenharmony_ci Ok(()) 56392f3ab15Sopenharmony_ci } 56492f3ab15Sopenharmony_ci 56592f3ab15Sopenharmony_ci /// Sets the digest used for HKDF derivation. 56692f3ab15Sopenharmony_ci /// 56792f3ab15Sopenharmony_ci /// Requires OpenSSL 1.1.0 or newer. 56892f3ab15Sopenharmony_ci #[corresponds(EVP_PKEY_CTX_set_hkdf_md)] 56992f3ab15Sopenharmony_ci #[cfg(any(ossl110, boringssl))] 57092f3ab15Sopenharmony_ci #[inline] 57192f3ab15Sopenharmony_ci pub fn set_hkdf_md(&mut self, digest: &MdRef) -> Result<(), ErrorStack> { 57292f3ab15Sopenharmony_ci unsafe { 57392f3ab15Sopenharmony_ci cvt(ffi::EVP_PKEY_CTX_set_hkdf_md( 57492f3ab15Sopenharmony_ci self.as_ptr(), 57592f3ab15Sopenharmony_ci digest.as_ptr(), 57692f3ab15Sopenharmony_ci ))?; 57792f3ab15Sopenharmony_ci } 57892f3ab15Sopenharmony_ci 57992f3ab15Sopenharmony_ci Ok(()) 58092f3ab15Sopenharmony_ci } 58192f3ab15Sopenharmony_ci 58292f3ab15Sopenharmony_ci /// Sets the HKDF mode of operation. 58392f3ab15Sopenharmony_ci /// 58492f3ab15Sopenharmony_ci /// Defaults to [`HkdfMode::EXTRACT_THEN_EXPAND`]. 58592f3ab15Sopenharmony_ci /// 58692f3ab15Sopenharmony_ci /// WARNING: Although this API calls it a "mode", HKDF-Extract and HKDF-Expand are distinct 58792f3ab15Sopenharmony_ci /// operations with distinct inputs and distinct kinds of keys. Callers should not pass input 58892f3ab15Sopenharmony_ci /// secrets for one operation into the other. 58992f3ab15Sopenharmony_ci /// 59092f3ab15Sopenharmony_ci /// Requires OpenSSL 1.1.1 or newer. 59192f3ab15Sopenharmony_ci #[corresponds(EVP_PKEY_CTX_set_hkdf_mode)] 59292f3ab15Sopenharmony_ci #[cfg(ossl111)] 59392f3ab15Sopenharmony_ci #[inline] 59492f3ab15Sopenharmony_ci pub fn set_hkdf_mode(&mut self, mode: HkdfMode) -> Result<(), ErrorStack> { 59592f3ab15Sopenharmony_ci unsafe { 59692f3ab15Sopenharmony_ci cvt(ffi::EVP_PKEY_CTX_set_hkdf_mode(self.as_ptr(), mode.0))?; 59792f3ab15Sopenharmony_ci } 59892f3ab15Sopenharmony_ci 59992f3ab15Sopenharmony_ci Ok(()) 60092f3ab15Sopenharmony_ci } 60192f3ab15Sopenharmony_ci 60292f3ab15Sopenharmony_ci /// Sets the input material for HKDF generation as the "key". 60392f3ab15Sopenharmony_ci /// 60492f3ab15Sopenharmony_ci /// Which input is the key depends on the "mode" (see [`set_hkdf_mode`][Self::set_hkdf_mode]). 60592f3ab15Sopenharmony_ci /// If [`HkdfMode::EXTRACT_THEN_EXPAND`] or [`HkdfMode::EXTRACT_ONLY`], this function specifies 60692f3ab15Sopenharmony_ci /// the input keying material (IKM) for HKDF-Extract. If [`HkdfMode::EXPAND_ONLY`], it instead 60792f3ab15Sopenharmony_ci /// specifies the pseudorandom key (PRK) for HKDF-Expand. 60892f3ab15Sopenharmony_ci /// 60992f3ab15Sopenharmony_ci /// Requires OpenSSL 1.1.0 or newer. 61092f3ab15Sopenharmony_ci #[corresponds(EVP_PKEY_CTX_set1_hkdf_key)] 61192f3ab15Sopenharmony_ci #[cfg(any(ossl110, boringssl))] 61292f3ab15Sopenharmony_ci #[inline] 61392f3ab15Sopenharmony_ci pub fn set_hkdf_key(&mut self, key: &[u8]) -> Result<(), ErrorStack> { 61492f3ab15Sopenharmony_ci #[cfg(not(boringssl))] 61592f3ab15Sopenharmony_ci let len = c_int::try_from(key.len()).unwrap(); 61692f3ab15Sopenharmony_ci #[cfg(boringssl)] 61792f3ab15Sopenharmony_ci let len = key.len(); 61892f3ab15Sopenharmony_ci 61992f3ab15Sopenharmony_ci unsafe { 62092f3ab15Sopenharmony_ci cvt(ffi::EVP_PKEY_CTX_set1_hkdf_key( 62192f3ab15Sopenharmony_ci self.as_ptr(), 62292f3ab15Sopenharmony_ci key.as_ptr(), 62392f3ab15Sopenharmony_ci len, 62492f3ab15Sopenharmony_ci ))?; 62592f3ab15Sopenharmony_ci } 62692f3ab15Sopenharmony_ci 62792f3ab15Sopenharmony_ci Ok(()) 62892f3ab15Sopenharmony_ci } 62992f3ab15Sopenharmony_ci 63092f3ab15Sopenharmony_ci /// Sets the salt value for HKDF generation. 63192f3ab15Sopenharmony_ci /// 63292f3ab15Sopenharmony_ci /// If performing HKDF-Expand only, this parameter is ignored. 63392f3ab15Sopenharmony_ci /// 63492f3ab15Sopenharmony_ci /// Requires OpenSSL 1.1.0 or newer. 63592f3ab15Sopenharmony_ci #[corresponds(EVP_PKEY_CTX_set1_hkdf_salt)] 63692f3ab15Sopenharmony_ci #[cfg(any(ossl110, boringssl))] 63792f3ab15Sopenharmony_ci #[inline] 63892f3ab15Sopenharmony_ci pub fn set_hkdf_salt(&mut self, salt: &[u8]) -> Result<(), ErrorStack> { 63992f3ab15Sopenharmony_ci #[cfg(not(boringssl))] 64092f3ab15Sopenharmony_ci let len = c_int::try_from(salt.len()).unwrap(); 64192f3ab15Sopenharmony_ci #[cfg(boringssl)] 64292f3ab15Sopenharmony_ci let len = salt.len(); 64392f3ab15Sopenharmony_ci 64492f3ab15Sopenharmony_ci unsafe { 64592f3ab15Sopenharmony_ci cvt(ffi::EVP_PKEY_CTX_set1_hkdf_salt( 64692f3ab15Sopenharmony_ci self.as_ptr(), 64792f3ab15Sopenharmony_ci salt.as_ptr(), 64892f3ab15Sopenharmony_ci len, 64992f3ab15Sopenharmony_ci ))?; 65092f3ab15Sopenharmony_ci } 65192f3ab15Sopenharmony_ci 65292f3ab15Sopenharmony_ci Ok(()) 65392f3ab15Sopenharmony_ci } 65492f3ab15Sopenharmony_ci 65592f3ab15Sopenharmony_ci /// Appends info bytes for HKDF generation. 65692f3ab15Sopenharmony_ci /// 65792f3ab15Sopenharmony_ci /// If performing HKDF-Extract only, this parameter is ignored. 65892f3ab15Sopenharmony_ci /// 65992f3ab15Sopenharmony_ci /// Requires OpenSSL 1.1.0 or newer. 66092f3ab15Sopenharmony_ci #[corresponds(EVP_PKEY_CTX_add1_hkdf_info)] 66192f3ab15Sopenharmony_ci #[cfg(any(ossl110, boringssl))] 66292f3ab15Sopenharmony_ci #[inline] 66392f3ab15Sopenharmony_ci pub fn add_hkdf_info(&mut self, info: &[u8]) -> Result<(), ErrorStack> { 66492f3ab15Sopenharmony_ci #[cfg(not(boringssl))] 66592f3ab15Sopenharmony_ci let len = c_int::try_from(info.len()).unwrap(); 66692f3ab15Sopenharmony_ci #[cfg(boringssl)] 66792f3ab15Sopenharmony_ci let len = info.len(); 66892f3ab15Sopenharmony_ci 66992f3ab15Sopenharmony_ci unsafe { 67092f3ab15Sopenharmony_ci cvt(ffi::EVP_PKEY_CTX_add1_hkdf_info( 67192f3ab15Sopenharmony_ci self.as_ptr(), 67292f3ab15Sopenharmony_ci info.as_ptr(), 67392f3ab15Sopenharmony_ci len, 67492f3ab15Sopenharmony_ci ))?; 67592f3ab15Sopenharmony_ci } 67692f3ab15Sopenharmony_ci 67792f3ab15Sopenharmony_ci Ok(()) 67892f3ab15Sopenharmony_ci } 67992f3ab15Sopenharmony_ci 68092f3ab15Sopenharmony_ci /// Derives a shared secret between two keys. 68192f3ab15Sopenharmony_ci /// 68292f3ab15Sopenharmony_ci /// If `buf` is set to `None`, an upper bound on the number of bytes required for the buffer will be returned. 68392f3ab15Sopenharmony_ci #[corresponds(EVP_PKEY_derive)] 68492f3ab15Sopenharmony_ci pub fn derive(&mut self, buf: Option<&mut [u8]>) -> Result<usize, ErrorStack> { 68592f3ab15Sopenharmony_ci let mut len = buf.as_ref().map_or(0, |b| b.len()); 68692f3ab15Sopenharmony_ci unsafe { 68792f3ab15Sopenharmony_ci cvt(ffi::EVP_PKEY_derive( 68892f3ab15Sopenharmony_ci self.as_ptr(), 68992f3ab15Sopenharmony_ci buf.map_or(ptr::null_mut(), |b| b.as_mut_ptr()), 69092f3ab15Sopenharmony_ci &mut len, 69192f3ab15Sopenharmony_ci ))?; 69292f3ab15Sopenharmony_ci } 69392f3ab15Sopenharmony_ci 69492f3ab15Sopenharmony_ci Ok(len) 69592f3ab15Sopenharmony_ci } 69692f3ab15Sopenharmony_ci 69792f3ab15Sopenharmony_ci /// Like [`Self::derive`] but appends the secret to a [`Vec`]. 69892f3ab15Sopenharmony_ci pub fn derive_to_vec(&mut self, buf: &mut Vec<u8>) -> Result<usize, ErrorStack> { 69992f3ab15Sopenharmony_ci let base = buf.len(); 70092f3ab15Sopenharmony_ci let len = self.derive(None)?; 70192f3ab15Sopenharmony_ci buf.resize(base + len, 0); 70292f3ab15Sopenharmony_ci let len = self.derive(Some(&mut buf[base..]))?; 70392f3ab15Sopenharmony_ci buf.truncate(base + len); 70492f3ab15Sopenharmony_ci Ok(len) 70592f3ab15Sopenharmony_ci } 70692f3ab15Sopenharmony_ci 70792f3ab15Sopenharmony_ci /// Generates a new public/private keypair. 70892f3ab15Sopenharmony_ci #[corresponds(EVP_PKEY_keygen)] 70992f3ab15Sopenharmony_ci #[inline] 71092f3ab15Sopenharmony_ci pub fn keygen(&mut self) -> Result<PKey<Private>, ErrorStack> { 71192f3ab15Sopenharmony_ci unsafe { 71292f3ab15Sopenharmony_ci let mut key = ptr::null_mut(); 71392f3ab15Sopenharmony_ci cvt(ffi::EVP_PKEY_keygen(self.as_ptr(), &mut key))?; 71492f3ab15Sopenharmony_ci Ok(PKey::from_ptr(key)) 71592f3ab15Sopenharmony_ci } 71692f3ab15Sopenharmony_ci } 71792f3ab15Sopenharmony_ci} 71892f3ab15Sopenharmony_ci 71992f3ab15Sopenharmony_ci#[cfg(test)] 72092f3ab15Sopenharmony_cimod test { 72192f3ab15Sopenharmony_ci use super::*; 72292f3ab15Sopenharmony_ci #[cfg(not(boringssl))] 72392f3ab15Sopenharmony_ci use crate::cipher::Cipher; 72492f3ab15Sopenharmony_ci use crate::ec::{EcGroup, EcKey}; 72592f3ab15Sopenharmony_ci use crate::hash::{hash, MessageDigest}; 72692f3ab15Sopenharmony_ci use crate::md::Md; 72792f3ab15Sopenharmony_ci use crate::nid::Nid; 72892f3ab15Sopenharmony_ci use crate::pkey::PKey; 72992f3ab15Sopenharmony_ci use crate::rsa::Rsa; 73092f3ab15Sopenharmony_ci use crate::sign::Verifier; 73192f3ab15Sopenharmony_ci 73292f3ab15Sopenharmony_ci #[test] 73392f3ab15Sopenharmony_ci fn rsa() { 73492f3ab15Sopenharmony_ci let key = include_bytes!("../test/rsa.pem"); 73592f3ab15Sopenharmony_ci let rsa = Rsa::private_key_from_pem(key).unwrap(); 73692f3ab15Sopenharmony_ci let pkey = PKey::from_rsa(rsa).unwrap(); 73792f3ab15Sopenharmony_ci 73892f3ab15Sopenharmony_ci let mut ctx = PkeyCtx::new(&pkey).unwrap(); 73992f3ab15Sopenharmony_ci ctx.encrypt_init().unwrap(); 74092f3ab15Sopenharmony_ci ctx.set_rsa_padding(Padding::PKCS1).unwrap(); 74192f3ab15Sopenharmony_ci 74292f3ab15Sopenharmony_ci let pt = "hello world".as_bytes(); 74392f3ab15Sopenharmony_ci let mut ct = vec![]; 74492f3ab15Sopenharmony_ci ctx.encrypt_to_vec(pt, &mut ct).unwrap(); 74592f3ab15Sopenharmony_ci 74692f3ab15Sopenharmony_ci ctx.decrypt_init().unwrap(); 74792f3ab15Sopenharmony_ci ctx.set_rsa_padding(Padding::PKCS1).unwrap(); 74892f3ab15Sopenharmony_ci 74992f3ab15Sopenharmony_ci let mut out = vec![]; 75092f3ab15Sopenharmony_ci ctx.decrypt_to_vec(&ct, &mut out).unwrap(); 75192f3ab15Sopenharmony_ci 75292f3ab15Sopenharmony_ci assert_eq!(pt, out); 75392f3ab15Sopenharmony_ci } 75492f3ab15Sopenharmony_ci 75592f3ab15Sopenharmony_ci #[test] 75692f3ab15Sopenharmony_ci #[cfg(any(ossl102, libressl310, boringssl))] 75792f3ab15Sopenharmony_ci fn rsa_oaep() { 75892f3ab15Sopenharmony_ci let key = include_bytes!("../test/rsa.pem"); 75992f3ab15Sopenharmony_ci let rsa = Rsa::private_key_from_pem(key).unwrap(); 76092f3ab15Sopenharmony_ci let pkey = PKey::from_rsa(rsa).unwrap(); 76192f3ab15Sopenharmony_ci 76292f3ab15Sopenharmony_ci let mut ctx = PkeyCtx::new(&pkey).unwrap(); 76392f3ab15Sopenharmony_ci ctx.encrypt_init().unwrap(); 76492f3ab15Sopenharmony_ci ctx.set_rsa_padding(Padding::PKCS1_OAEP).unwrap(); 76592f3ab15Sopenharmony_ci ctx.set_rsa_oaep_md(Md::sha256()).unwrap(); 76692f3ab15Sopenharmony_ci ctx.set_rsa_mgf1_md(Md::sha256()).unwrap(); 76792f3ab15Sopenharmony_ci 76892f3ab15Sopenharmony_ci let pt = "hello world".as_bytes(); 76992f3ab15Sopenharmony_ci let mut ct = vec![]; 77092f3ab15Sopenharmony_ci ctx.encrypt_to_vec(pt, &mut ct).unwrap(); 77192f3ab15Sopenharmony_ci 77292f3ab15Sopenharmony_ci ctx.decrypt_init().unwrap(); 77392f3ab15Sopenharmony_ci ctx.set_rsa_padding(Padding::PKCS1_OAEP).unwrap(); 77492f3ab15Sopenharmony_ci ctx.set_rsa_oaep_md(Md::sha256()).unwrap(); 77592f3ab15Sopenharmony_ci ctx.set_rsa_mgf1_md(Md::sha256()).unwrap(); 77692f3ab15Sopenharmony_ci 77792f3ab15Sopenharmony_ci let mut out = vec![]; 77892f3ab15Sopenharmony_ci ctx.decrypt_to_vec(&ct, &mut out).unwrap(); 77992f3ab15Sopenharmony_ci 78092f3ab15Sopenharmony_ci assert_eq!(pt, out); 78192f3ab15Sopenharmony_ci } 78292f3ab15Sopenharmony_ci 78392f3ab15Sopenharmony_ci #[test] 78492f3ab15Sopenharmony_ci fn rsa_sign() { 78592f3ab15Sopenharmony_ci let key = include_bytes!("../test/rsa.pem"); 78692f3ab15Sopenharmony_ci let rsa = Rsa::private_key_from_pem(key).unwrap(); 78792f3ab15Sopenharmony_ci let pkey = PKey::from_rsa(rsa).unwrap(); 78892f3ab15Sopenharmony_ci 78992f3ab15Sopenharmony_ci let mut ctx = PkeyCtx::new(&pkey).unwrap(); 79092f3ab15Sopenharmony_ci ctx.sign_init().unwrap(); 79192f3ab15Sopenharmony_ci ctx.set_rsa_padding(Padding::PKCS1).unwrap(); 79292f3ab15Sopenharmony_ci ctx.set_signature_md(Md::sha384()).unwrap(); 79392f3ab15Sopenharmony_ci 79492f3ab15Sopenharmony_ci let msg = b"hello world"; 79592f3ab15Sopenharmony_ci let digest = hash(MessageDigest::sha384(), msg).unwrap(); 79692f3ab15Sopenharmony_ci let mut signature = vec![]; 79792f3ab15Sopenharmony_ci ctx.sign_to_vec(&digest, &mut signature).unwrap(); 79892f3ab15Sopenharmony_ci 79992f3ab15Sopenharmony_ci let mut verifier = Verifier::new(MessageDigest::sha384(), &pkey).unwrap(); 80092f3ab15Sopenharmony_ci verifier.update(msg).unwrap(); 80192f3ab15Sopenharmony_ci assert!(matches!(verifier.verify(&signature), Ok(true))); 80292f3ab15Sopenharmony_ci } 80392f3ab15Sopenharmony_ci 80492f3ab15Sopenharmony_ci #[test] 80592f3ab15Sopenharmony_ci fn rsa_sign_pss() { 80692f3ab15Sopenharmony_ci let key = include_bytes!("../test/rsa.pem"); 80792f3ab15Sopenharmony_ci let rsa = Rsa::private_key_from_pem(key).unwrap(); 80892f3ab15Sopenharmony_ci let pkey = PKey::from_rsa(rsa).unwrap(); 80992f3ab15Sopenharmony_ci 81092f3ab15Sopenharmony_ci let mut ctx = PkeyCtx::new(&pkey).unwrap(); 81192f3ab15Sopenharmony_ci ctx.sign_init().unwrap(); 81292f3ab15Sopenharmony_ci ctx.set_rsa_padding(Padding::PKCS1_PSS).unwrap(); 81392f3ab15Sopenharmony_ci ctx.set_signature_md(Md::sha384()).unwrap(); 81492f3ab15Sopenharmony_ci ctx.set_rsa_pss_saltlen(RsaPssSaltlen::custom(14)).unwrap(); 81592f3ab15Sopenharmony_ci 81692f3ab15Sopenharmony_ci let msg = b"hello world"; 81792f3ab15Sopenharmony_ci let digest = hash(MessageDigest::sha384(), msg).unwrap(); 81892f3ab15Sopenharmony_ci let mut signature = vec![]; 81992f3ab15Sopenharmony_ci ctx.sign_to_vec(&digest, &mut signature).unwrap(); 82092f3ab15Sopenharmony_ci 82192f3ab15Sopenharmony_ci let mut verifier = Verifier::new(MessageDigest::sha384(), &pkey).unwrap(); 82292f3ab15Sopenharmony_ci verifier.set_rsa_padding(Padding::PKCS1_PSS).unwrap(); 82392f3ab15Sopenharmony_ci verifier 82492f3ab15Sopenharmony_ci .set_rsa_pss_saltlen(RsaPssSaltlen::custom(14)) 82592f3ab15Sopenharmony_ci .unwrap(); 82692f3ab15Sopenharmony_ci verifier.update(msg).unwrap(); 82792f3ab15Sopenharmony_ci assert!(matches!(verifier.verify(&signature), Ok(true))); 82892f3ab15Sopenharmony_ci } 82992f3ab15Sopenharmony_ci 83092f3ab15Sopenharmony_ci #[test] 83192f3ab15Sopenharmony_ci fn derive() { 83292f3ab15Sopenharmony_ci let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap(); 83392f3ab15Sopenharmony_ci let key1 = EcKey::generate(&group).unwrap(); 83492f3ab15Sopenharmony_ci let key1 = PKey::from_ec_key(key1).unwrap(); 83592f3ab15Sopenharmony_ci let key2 = EcKey::generate(&group).unwrap(); 83692f3ab15Sopenharmony_ci let key2 = PKey::from_ec_key(key2).unwrap(); 83792f3ab15Sopenharmony_ci 83892f3ab15Sopenharmony_ci let mut ctx = PkeyCtx::new(&key1).unwrap(); 83992f3ab15Sopenharmony_ci ctx.derive_init().unwrap(); 84092f3ab15Sopenharmony_ci ctx.derive_set_peer(&key2).unwrap(); 84192f3ab15Sopenharmony_ci 84292f3ab15Sopenharmony_ci let mut buf = vec![]; 84392f3ab15Sopenharmony_ci ctx.derive_to_vec(&mut buf).unwrap(); 84492f3ab15Sopenharmony_ci } 84592f3ab15Sopenharmony_ci 84692f3ab15Sopenharmony_ci #[test] 84792f3ab15Sopenharmony_ci #[cfg(not(boringssl))] 84892f3ab15Sopenharmony_ci fn cmac_keygen() { 84992f3ab15Sopenharmony_ci let mut ctx = PkeyCtx::new_id(Id::CMAC).unwrap(); 85092f3ab15Sopenharmony_ci ctx.keygen_init().unwrap(); 85192f3ab15Sopenharmony_ci ctx.set_keygen_cipher(Cipher::aes_128_cbc()).unwrap(); 85292f3ab15Sopenharmony_ci ctx.set_keygen_mac_key(&hex::decode("9294727a3638bb1c13f48ef8158bfc9d").unwrap()) 85392f3ab15Sopenharmony_ci .unwrap(); 85492f3ab15Sopenharmony_ci ctx.keygen().unwrap(); 85592f3ab15Sopenharmony_ci } 85692f3ab15Sopenharmony_ci 85792f3ab15Sopenharmony_ci #[test] 85892f3ab15Sopenharmony_ci #[cfg(any(ossl110, boringssl))] 85992f3ab15Sopenharmony_ci fn hkdf() { 86092f3ab15Sopenharmony_ci let mut ctx = PkeyCtx::new_id(Id::HKDF).unwrap(); 86192f3ab15Sopenharmony_ci ctx.derive_init().unwrap(); 86292f3ab15Sopenharmony_ci ctx.set_hkdf_md(Md::sha256()).unwrap(); 86392f3ab15Sopenharmony_ci ctx.set_hkdf_key(&hex::decode("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b").unwrap()) 86492f3ab15Sopenharmony_ci .unwrap(); 86592f3ab15Sopenharmony_ci ctx.set_hkdf_salt(&hex::decode("000102030405060708090a0b0c").unwrap()) 86692f3ab15Sopenharmony_ci .unwrap(); 86792f3ab15Sopenharmony_ci ctx.add_hkdf_info(&hex::decode("f0f1f2f3f4f5f6f7f8f9").unwrap()) 86892f3ab15Sopenharmony_ci .unwrap(); 86992f3ab15Sopenharmony_ci let mut out = [0; 42]; 87092f3ab15Sopenharmony_ci ctx.derive(Some(&mut out)).unwrap(); 87192f3ab15Sopenharmony_ci 87292f3ab15Sopenharmony_ci assert_eq!( 87392f3ab15Sopenharmony_ci &out[..], 87492f3ab15Sopenharmony_ci hex::decode("3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865") 87592f3ab15Sopenharmony_ci .unwrap() 87692f3ab15Sopenharmony_ci ); 87792f3ab15Sopenharmony_ci } 87892f3ab15Sopenharmony_ci 87992f3ab15Sopenharmony_ci #[test] 88092f3ab15Sopenharmony_ci #[cfg(ossl111)] 88192f3ab15Sopenharmony_ci fn hkdf_expand() { 88292f3ab15Sopenharmony_ci let mut ctx = PkeyCtx::new_id(Id::HKDF).unwrap(); 88392f3ab15Sopenharmony_ci ctx.derive_init().unwrap(); 88492f3ab15Sopenharmony_ci ctx.set_hkdf_mode(HkdfMode::EXPAND_ONLY).unwrap(); 88592f3ab15Sopenharmony_ci ctx.set_hkdf_md(Md::sha256()).unwrap(); 88692f3ab15Sopenharmony_ci ctx.set_hkdf_key( 88792f3ab15Sopenharmony_ci &hex::decode("077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5") 88892f3ab15Sopenharmony_ci .unwrap(), 88992f3ab15Sopenharmony_ci ) 89092f3ab15Sopenharmony_ci .unwrap(); 89192f3ab15Sopenharmony_ci ctx.add_hkdf_info(&hex::decode("f0f1f2f3f4f5f6f7f8f9").unwrap()) 89292f3ab15Sopenharmony_ci .unwrap(); 89392f3ab15Sopenharmony_ci let mut out = [0; 42]; 89492f3ab15Sopenharmony_ci ctx.derive(Some(&mut out)).unwrap(); 89592f3ab15Sopenharmony_ci 89692f3ab15Sopenharmony_ci assert_eq!( 89792f3ab15Sopenharmony_ci &out[..], 89892f3ab15Sopenharmony_ci hex::decode("3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865") 89992f3ab15Sopenharmony_ci .unwrap() 90092f3ab15Sopenharmony_ci ); 90192f3ab15Sopenharmony_ci } 90292f3ab15Sopenharmony_ci 90392f3ab15Sopenharmony_ci #[test] 90492f3ab15Sopenharmony_ci #[cfg(ossl111)] 90592f3ab15Sopenharmony_ci fn hkdf_extract() { 90692f3ab15Sopenharmony_ci let mut ctx = PkeyCtx::new_id(Id::HKDF).unwrap(); 90792f3ab15Sopenharmony_ci ctx.derive_init().unwrap(); 90892f3ab15Sopenharmony_ci ctx.set_hkdf_mode(HkdfMode::EXTRACT_ONLY).unwrap(); 90992f3ab15Sopenharmony_ci ctx.set_hkdf_md(Md::sha256()).unwrap(); 91092f3ab15Sopenharmony_ci ctx.set_hkdf_key(&hex::decode("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b").unwrap()) 91192f3ab15Sopenharmony_ci .unwrap(); 91292f3ab15Sopenharmony_ci ctx.set_hkdf_salt(&hex::decode("000102030405060708090a0b0c").unwrap()) 91392f3ab15Sopenharmony_ci .unwrap(); 91492f3ab15Sopenharmony_ci let mut out = vec![]; 91592f3ab15Sopenharmony_ci ctx.derive_to_vec(&mut out).unwrap(); 91692f3ab15Sopenharmony_ci 91792f3ab15Sopenharmony_ci assert_eq!( 91892f3ab15Sopenharmony_ci &out[..], 91992f3ab15Sopenharmony_ci hex::decode("077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5") 92092f3ab15Sopenharmony_ci .unwrap() 92192f3ab15Sopenharmony_ci ); 92292f3ab15Sopenharmony_ci } 92392f3ab15Sopenharmony_ci 92492f3ab15Sopenharmony_ci #[test] 92592f3ab15Sopenharmony_ci fn verify_fail() { 92692f3ab15Sopenharmony_ci let key1 = Rsa::generate(4096).unwrap(); 92792f3ab15Sopenharmony_ci let key1 = PKey::from_rsa(key1).unwrap(); 92892f3ab15Sopenharmony_ci 92992f3ab15Sopenharmony_ci let data = b"Some Crypto Text"; 93092f3ab15Sopenharmony_ci 93192f3ab15Sopenharmony_ci let mut ctx = PkeyCtx::new(&key1).unwrap(); 93292f3ab15Sopenharmony_ci ctx.sign_init().unwrap(); 93392f3ab15Sopenharmony_ci let mut signature = vec![]; 93492f3ab15Sopenharmony_ci ctx.sign_to_vec(data, &mut signature).unwrap(); 93592f3ab15Sopenharmony_ci 93692f3ab15Sopenharmony_ci let bad_data = b"Some Crypto text"; 93792f3ab15Sopenharmony_ci 93892f3ab15Sopenharmony_ci ctx.verify_init().unwrap(); 93992f3ab15Sopenharmony_ci let valid = ctx.verify(bad_data, &signature); 94092f3ab15Sopenharmony_ci assert!(matches!(valid, Ok(false) | Err(_))); 94192f3ab15Sopenharmony_ci assert!(ErrorStack::get().errors().is_empty()); 94292f3ab15Sopenharmony_ci } 94392f3ab15Sopenharmony_ci 94492f3ab15Sopenharmony_ci #[test] 94592f3ab15Sopenharmony_ci fn verify_fail_ec() { 94692f3ab15Sopenharmony_ci let key1 = 94792f3ab15Sopenharmony_ci EcKey::generate(&EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap()).unwrap(); 94892f3ab15Sopenharmony_ci let key1 = PKey::from_ec_key(key1).unwrap(); 94992f3ab15Sopenharmony_ci 95092f3ab15Sopenharmony_ci let data = b"Some Crypto Text"; 95192f3ab15Sopenharmony_ci let mut ctx = PkeyCtx::new(&key1).unwrap(); 95292f3ab15Sopenharmony_ci ctx.verify_init().unwrap(); 95392f3ab15Sopenharmony_ci assert!(matches!(ctx.verify(data, &[0; 64]), Ok(false) | Err(_))); 95492f3ab15Sopenharmony_ci assert!(ErrorStack::get().errors().is_empty()); 95592f3ab15Sopenharmony_ci } 95692f3ab15Sopenharmony_ci 95792f3ab15Sopenharmony_ci #[test] 95892f3ab15Sopenharmony_ci fn test_verify_recover() { 95992f3ab15Sopenharmony_ci let key = Rsa::generate(2048).unwrap(); 96092f3ab15Sopenharmony_ci let key = PKey::from_rsa(key).unwrap(); 96192f3ab15Sopenharmony_ci 96292f3ab15Sopenharmony_ci let digest = [ 96392f3ab15Sopenharmony_ci 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 96492f3ab15Sopenharmony_ci 24, 25, 26, 27, 28, 29, 30, 31, 96592f3ab15Sopenharmony_ci ]; 96692f3ab15Sopenharmony_ci 96792f3ab15Sopenharmony_ci let mut ctx = PkeyCtx::new(&key).unwrap(); 96892f3ab15Sopenharmony_ci ctx.sign_init().unwrap(); 96992f3ab15Sopenharmony_ci ctx.set_rsa_padding(Padding::PKCS1).unwrap(); 97092f3ab15Sopenharmony_ci ctx.set_signature_md(Md::sha256()).unwrap(); 97192f3ab15Sopenharmony_ci let mut signature = vec![]; 97292f3ab15Sopenharmony_ci ctx.sign_to_vec(&digest, &mut signature).unwrap(); 97392f3ab15Sopenharmony_ci 97492f3ab15Sopenharmony_ci // Attempt recovery of just the digest. 97592f3ab15Sopenharmony_ci let mut ctx = PkeyCtx::new(&key).unwrap(); 97692f3ab15Sopenharmony_ci ctx.verify_recover_init().unwrap(); 97792f3ab15Sopenharmony_ci ctx.set_rsa_padding(Padding::PKCS1).unwrap(); 97892f3ab15Sopenharmony_ci ctx.set_signature_md(Md::sha256()).unwrap(); 97992f3ab15Sopenharmony_ci let length = ctx.verify_recover(&signature, None).unwrap(); 98092f3ab15Sopenharmony_ci let mut result_buf = vec![0; length]; 98192f3ab15Sopenharmony_ci let length = ctx 98292f3ab15Sopenharmony_ci .verify_recover(&signature, Some(&mut result_buf)) 98392f3ab15Sopenharmony_ci .unwrap(); 98492f3ab15Sopenharmony_ci assert_eq!(length, digest.len()); 98592f3ab15Sopenharmony_ci // result_buf contains the digest 98692f3ab15Sopenharmony_ci assert_eq!(result_buf[..length], digest); 98792f3ab15Sopenharmony_ci 98892f3ab15Sopenharmony_ci // Attempt recovery of teh entire DigestInfo 98992f3ab15Sopenharmony_ci let mut ctx = PkeyCtx::new(&key).unwrap(); 99092f3ab15Sopenharmony_ci ctx.verify_recover_init().unwrap(); 99192f3ab15Sopenharmony_ci ctx.set_rsa_padding(Padding::PKCS1).unwrap(); 99292f3ab15Sopenharmony_ci let length = ctx.verify_recover(&signature, None).unwrap(); 99392f3ab15Sopenharmony_ci let mut result_buf = vec![0; length]; 99492f3ab15Sopenharmony_ci let length = ctx 99592f3ab15Sopenharmony_ci .verify_recover(&signature, Some(&mut result_buf)) 99692f3ab15Sopenharmony_ci .unwrap(); 99792f3ab15Sopenharmony_ci // 32-bytes of SHA256 digest + the ASN.1 DigestInfo structure == 51 bytes 99892f3ab15Sopenharmony_ci assert_eq!(length, 51); 99992f3ab15Sopenharmony_ci // The digest is the end of the DigestInfo structure. 100092f3ab15Sopenharmony_ci assert_eq!(result_buf[length - digest.len()..length], digest); 100192f3ab15Sopenharmony_ci } 100292f3ab15Sopenharmony_ci} 1003