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