Skip to main content

openssl/
pkey_ctx.rs

1//! The asymmetric encryption context.
2//!
3//! # Examples
4//!
5//! Encrypt data with RSA
6//!
7//! ```
8//! use openssl::rsa::Rsa;
9//! use openssl::pkey::PKey;
10//! use openssl::pkey_ctx::PkeyCtx;
11//!
12//! let key = Rsa::generate(4096).unwrap();
13//! let key = PKey::from_rsa(key).unwrap();
14//!
15//! let mut ctx = PkeyCtx::new(&key).unwrap();
16//! ctx.encrypt_init().unwrap();
17//!
18//! let data = b"Some Crypto Text";
19//! let mut ciphertext = vec![];
20//! ctx.encrypt_to_vec(data, &mut ciphertext).unwrap();
21//! ```
22
23#![cfg_attr(
24    not(any(boringssl, awslc)),
25    doc = r#"\
26Generate a CMAC key
27
28```
29use openssl::pkey_ctx::PkeyCtx;
30use openssl::pkey::Id;
31use openssl::cipher::Cipher;
32
33let mut ctx = PkeyCtx::new_id(Id::CMAC).unwrap();
34ctx.keygen_init().unwrap();
35ctx.set_keygen_cipher(Cipher::aes_128_cbc()).unwrap();
36ctx.set_keygen_mac_key(b"0123456789abcdef").unwrap();
37let cmac_key = ctx.keygen().unwrap();
38```"#
39)]
40
41//!
42//! Sign and verify data with RSA
43//!
44//! ```
45//! use openssl::pkey_ctx::PkeyCtx;
46//! use openssl::pkey::PKey;
47//! use openssl::rsa::Rsa;
48//!
49//! // Generate a random RSA key.
50//! let key = Rsa::generate(4096).unwrap();
51//! let key = PKey::from_rsa(key).unwrap();
52//!
53//! let text = b"Some Crypto Text";
54//!
55//! // Create the signature.
56//! let mut ctx = PkeyCtx::new(&key).unwrap();
57//! ctx.sign_init().unwrap();
58//! let mut signature = vec![];
59//! ctx.sign_to_vec(text, &mut signature).unwrap();
60//!
61//! // Verify the signature.
62//! let mut ctx = PkeyCtx::new(&key).unwrap();
63//! ctx.verify_init().unwrap();
64//! let valid = ctx.verify(text, &signature).unwrap();
65//! assert!(valid);
66//! ```
67use crate::bn::BigNumRef;
68#[cfg(not(any(boringssl, awslc)))]
69use crate::cipher::CipherRef;
70use crate::error::ErrorStack;
71use crate::md::MdRef;
72use crate::nid::Nid;
73use crate::pkey::{HasPrivate, HasPublic, Id, PKey, PKeyRef, Params, Private};
74use crate::rsa::Padding;
75use crate::sign::RsaPssSaltlen;
76use crate::{cvt, cvt_p};
77use cfg_if::cfg_if;
78use foreign_types::{ForeignType, ForeignTypeRef};
79#[cfg(not(any(boringssl, awslc)))]
80use libc::c_int;
81#[cfg(ossl320)]
82use libc::c_uint;
83use openssl_macros::corresponds;
84use std::convert::TryFrom;
85use std::ptr;
86
87/// HKDF modes of operation.
88#[cfg(any(ossl111, libressl360))]
89pub struct HkdfMode(c_int);
90
91#[cfg(any(ossl111, libressl360))]
92impl HkdfMode {
93    /// This is the default mode. Calling [`derive`][PkeyCtxRef::derive] on a [`PkeyCtxRef`] set up
94    /// for HKDF will perform an extract followed by an expand operation in one go. The derived key
95    /// returned will be the result after the expand operation. The intermediate fixed-length
96    /// pseudorandom key K is not returned.
97    pub const EXTRACT_THEN_EXPAND: Self = HkdfMode(ffi::EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND);
98
99    /// In this mode calling [`derive`][PkeyCtxRef::derive] will just perform the extract operation.
100    /// The value returned will be the intermediate fixed-length pseudorandom key K.
101    ///
102    /// The digest, key and salt values must be set before a key is derived or an error occurs.
103    pub const EXTRACT_ONLY: Self = HkdfMode(ffi::EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY);
104
105    /// In this mode calling [`derive`][PkeyCtxRef::derive] will just perform the expand operation.
106    /// The input key should be set to the intermediate fixed-length pseudorandom key K returned
107    /// from a previous extract operation.
108    ///
109    /// The digest, key and info values must be set before a key is derived or an error occurs.
110    pub const EXPAND_ONLY: Self = HkdfMode(ffi::EVP_PKEY_HKDEF_MODE_EXPAND_ONLY);
111}
112
113/// Nonce type for ECDSA and DSA.
114#[cfg(ossl320)]
115#[derive(Debug, PartialEq)]
116pub struct NonceType(c_uint);
117
118#[cfg(ossl320)]
119impl NonceType {
120    /// This is the default mode. It uses a random value for the nonce k as defined in FIPS 186-4 Section 6.3
121    /// “Secret Number Generation”.
122    pub const RANDOM_K: Self = NonceType(0);
123
124    /// Uses a deterministic value for the nonce k as defined in RFC #6979 (See Section 3.2 “Generation of k”).
125    pub const DETERMINISTIC_K: Self = NonceType(1);
126}
127
128generic_foreign_type_and_impl_send_sync! {
129    type CType = ffi::EVP_PKEY_CTX;
130    fn drop = ffi::EVP_PKEY_CTX_free;
131
132    /// A context object which can perform asymmetric cryptography operations.
133    pub struct PkeyCtx<T>;
134    /// A reference to a [`PkeyCtx`].
135    pub struct PkeyCtxRef<T>;
136}
137
138impl<T> PkeyCtx<T> {
139    /// Creates a new pkey context using the provided key.
140    #[corresponds(EVP_PKEY_CTX_new)]
141    #[inline]
142    pub fn new(pkey: &PKeyRef<T>) -> Result<Self, ErrorStack> {
143        unsafe {
144            let ptr = cvt_p(ffi::EVP_PKEY_CTX_new(pkey.as_ptr(), ptr::null_mut()))?;
145            Ok(PkeyCtx::from_ptr(ptr))
146        }
147    }
148}
149
150impl PkeyCtx<()> {
151    /// Creates a new pkey context for the specified algorithm ID.
152    #[corresponds(EVP_PKEY_CTX_new_id)]
153    #[inline]
154    pub fn new_id(id: Id) -> Result<Self, ErrorStack> {
155        unsafe {
156            let ptr = cvt_p(ffi::EVP_PKEY_CTX_new_id(id.as_raw(), ptr::null_mut()))?;
157            Ok(PkeyCtx::from_ptr(ptr))
158        }
159    }
160}
161
162impl<T> PkeyCtxRef<T>
163where
164    T: HasPublic,
165{
166    /// Prepares the context for encryption using the public key.
167    #[corresponds(EVP_PKEY_encrypt_init)]
168    #[inline]
169    pub fn encrypt_init(&mut self) -> Result<(), ErrorStack> {
170        unsafe {
171            cvt(ffi::EVP_PKEY_encrypt_init(self.as_ptr()))?;
172        }
173
174        Ok(())
175    }
176
177    /// Prepares the context for signature verification using the public key.
178    #[corresponds(EVP_PKEY_verify_init)]
179    #[inline]
180    pub fn verify_init(&mut self) -> Result<(), ErrorStack> {
181        unsafe {
182            cvt(ffi::EVP_PKEY_verify_init(self.as_ptr()))?;
183        }
184
185        Ok(())
186    }
187
188    /// Prepares the context for signature recovery using the public key.
189    #[corresponds(EVP_PKEY_verify_recover_init)]
190    #[inline]
191    pub fn verify_recover_init(&mut self) -> Result<(), ErrorStack> {
192        unsafe {
193            cvt(ffi::EVP_PKEY_verify_recover_init(self.as_ptr()))?;
194        }
195
196        Ok(())
197    }
198
199    /// Encrypts data using the public key.
200    ///
201    /// If `to` is set to `None`, an upper bound on the number of bytes required for the output buffer will be
202    /// returned.
203    #[corresponds(EVP_PKEY_encrypt)]
204    #[inline]
205    pub fn encrypt(&mut self, from: &[u8], to: Option<&mut [u8]>) -> Result<usize, ErrorStack> {
206        let mut written = to.as_ref().map_or(0, |b| b.len());
207        unsafe {
208            cvt(ffi::EVP_PKEY_encrypt(
209                self.as_ptr(),
210                to.map_or(ptr::null_mut(), |b| b.as_mut_ptr()),
211                &mut written,
212                from.as_ptr(),
213                from.len(),
214            ))?;
215        }
216
217        Ok(written)
218    }
219
220    /// Like [`Self::encrypt`] but appends ciphertext to a [`Vec`].
221    pub fn encrypt_to_vec(&mut self, from: &[u8], out: &mut Vec<u8>) -> Result<usize, ErrorStack> {
222        let base = out.len();
223        let len = self.encrypt(from, None)?;
224        out.resize(base + len, 0);
225        let len = self.encrypt(from, Some(&mut out[base..]))?;
226        out.truncate(base + len);
227        Ok(len)
228    }
229
230    /// Verifies the signature of data using the public key.
231    ///
232    /// Returns `Ok(true)` if the signature is valid, `Ok(false)` if the signature is invalid, and `Err` if an error
233    /// occurred.
234    ///
235    /// # Note
236    ///
237    /// This verifies the signature of the *raw* data. It is more common to compute and verify the signature of the
238    /// cryptographic hash of an arbitrary amount of data. The [`MdCtx`](crate::md_ctx::MdCtx) type can be used to do
239    /// that.
240    #[corresponds(EVP_PKEY_verify)]
241    #[inline]
242    pub fn verify(&mut self, data: &[u8], sig: &[u8]) -> Result<bool, ErrorStack> {
243        unsafe {
244            let r = ffi::EVP_PKEY_verify(
245                self.as_ptr(),
246                sig.as_ptr(),
247                sig.len(),
248                data.as_ptr(),
249                data.len(),
250            );
251            // `EVP_PKEY_verify` is not terribly consistent about how it,
252            // reports errors. It does not clearly distinguish between 0 and
253            // -1, and may put errors on the stack in both cases. If there's
254            // errors on the stack, we return `Err()`, else we return
255            // `Ok(false)`.
256            if r <= 0 {
257                let errors = ErrorStack::get();
258                if !errors.errors().is_empty() {
259                    return Err(errors);
260                }
261            }
262
263            Ok(r == 1)
264        }
265    }
266
267    /// Recovers the original data signed by the private key. You almost
268    /// always want `verify` instead.
269    ///
270    /// Returns the number of bytes written to `to`, or the number of bytes
271    /// that would be written, if `to` is `None.
272    ///
273    /// Returns an error if `to` is shorter than the length returned when `to`
274    /// is `None`.
275    #[corresponds(EVP_PKEY_verify_recover)]
276    #[inline]
277    pub fn verify_recover(
278        &mut self,
279        sig: &[u8],
280        to: Option<&mut [u8]>,
281    ) -> Result<usize, ErrorStack> {
282        // OpenSSL does not treat the output length as a bound for all key
283        // types (RSA writes up to the modulus size), so check it here.
284        if let Some(buf) = &to {
285            if buf.len() < self.verify_recover(sig, None)? {
286                return Err(ErrorStack::internal_error(
287                    "verify_recover output buffer is too small",
288                ));
289            }
290        }
291
292        let mut written = to.as_ref().map_or(0, |b| b.len());
293        unsafe {
294            cvt(ffi::EVP_PKEY_verify_recover(
295                self.as_ptr(),
296                to.map_or(ptr::null_mut(), |b| b.as_mut_ptr()),
297                &mut written,
298                sig.as_ptr(),
299                sig.len(),
300            ))?;
301        }
302
303        Ok(written)
304    }
305}
306
307impl<T> PkeyCtxRef<T>
308where
309    T: HasPrivate,
310{
311    /// Prepares the context for decryption using the private key.
312    #[corresponds(EVP_PKEY_decrypt_init)]
313    #[inline]
314    pub fn decrypt_init(&mut self) -> Result<(), ErrorStack> {
315        unsafe {
316            cvt(ffi::EVP_PKEY_decrypt_init(self.as_ptr()))?;
317        }
318
319        Ok(())
320    }
321
322    /// Prepares the context for signing using the private key.
323    #[corresponds(EVP_PKEY_sign_init)]
324    #[inline]
325    pub fn sign_init(&mut self) -> Result<(), ErrorStack> {
326        unsafe {
327            cvt(ffi::EVP_PKEY_sign_init(self.as_ptr()))?;
328        }
329
330        Ok(())
331    }
332
333    /// Sets the peer key used for secret derivation.
334    #[corresponds(EVP_PKEY_derive_set_peer)]
335    pub fn derive_set_peer<U>(&mut self, key: &PKeyRef<U>) -> Result<(), ErrorStack>
336    where
337        U: HasPublic,
338    {
339        unsafe {
340            cvt(ffi::EVP_PKEY_derive_set_peer(self.as_ptr(), key.as_ptr()))?;
341        }
342
343        Ok(())
344    }
345
346    /// Decrypts data using the private key.
347    ///
348    /// If `to` is set to `None`, an upper bound on the number of bytes required for the output buffer will be
349    /// returned.
350    #[corresponds(EVP_PKEY_decrypt)]
351    #[inline]
352    pub fn decrypt(&mut self, from: &[u8], to: Option<&mut [u8]>) -> Result<usize, ErrorStack> {
353        let mut written = to.as_ref().map_or(0, |b| b.len());
354        unsafe {
355            cvt(ffi::EVP_PKEY_decrypt(
356                self.as_ptr(),
357                to.map_or(ptr::null_mut(), |b| b.as_mut_ptr()),
358                &mut written,
359                from.as_ptr(),
360                from.len(),
361            ))?;
362        }
363
364        Ok(written)
365    }
366
367    /// Like [`Self::decrypt`] but appends plaintext to a [`Vec`].
368    pub fn decrypt_to_vec(&mut self, from: &[u8], out: &mut Vec<u8>) -> Result<usize, ErrorStack> {
369        let base = out.len();
370        let len = self.decrypt(from, None)?;
371        out.resize(base + len, 0);
372        let len = self.decrypt(from, Some(&mut out[base..]))?;
373        out.truncate(base + len);
374        Ok(len)
375    }
376
377    /// Signs the contents of `data`.
378    ///
379    /// If `sig` is set to `None`, an upper bound on the number of bytes required for the output buffer will be
380    /// returned.
381    ///
382    /// # Note
383    ///
384    /// This computes the signature of the *raw* bytes of `data`. It is more common to sign the cryptographic hash of
385    /// an arbitrary amount of data. The [`MdCtx`](crate::md_ctx::MdCtx) type can be used to do that.
386    #[corresponds(EVP_PKEY_sign)]
387    #[inline]
388    pub fn sign(&mut self, data: &[u8], sig: Option<&mut [u8]>) -> Result<usize, ErrorStack> {
389        let mut written = sig.as_ref().map_or(0, |b| b.len());
390        unsafe {
391            cvt(ffi::EVP_PKEY_sign(
392                self.as_ptr(),
393                sig.map_or(ptr::null_mut(), |b| b.as_mut_ptr()),
394                &mut written,
395                data.as_ptr(),
396                data.len(),
397            ))?;
398        }
399
400        Ok(written)
401    }
402
403    /// Like [`Self::sign`] but appends the signature to a [`Vec`].
404    pub fn sign_to_vec(&mut self, data: &[u8], sig: &mut Vec<u8>) -> Result<usize, ErrorStack> {
405        let base = sig.len();
406        let len = self.sign(data, None)?;
407        sig.resize(base + len, 0);
408        let len = self.sign(data, Some(&mut sig[base..]))?;
409        sig.truncate(base + len);
410        Ok(len)
411    }
412}
413
414impl<T> PkeyCtxRef<T> {
415    /// Prepares the context for shared secret derivation.
416    #[corresponds(EVP_PKEY_derive_init)]
417    #[inline]
418    pub fn derive_init(&mut self) -> Result<(), ErrorStack> {
419        unsafe {
420            cvt(ffi::EVP_PKEY_derive_init(self.as_ptr()))?;
421        }
422
423        Ok(())
424    }
425
426    /// Prepares the context for key generation.
427    #[corresponds(EVP_PKEY_keygen_init)]
428    #[inline]
429    pub fn keygen_init(&mut self) -> Result<(), ErrorStack> {
430        unsafe {
431            cvt(ffi::EVP_PKEY_keygen_init(self.as_ptr()))?;
432        }
433
434        Ok(())
435    }
436
437    /// Prepares the context for key parameter generation.
438    #[corresponds(EVP_PKEY_paramgen_init)]
439    #[inline]
440    pub fn paramgen_init(&mut self) -> Result<(), ErrorStack> {
441        unsafe {
442            cvt(ffi::EVP_PKEY_paramgen_init(self.as_ptr()))?;
443        }
444
445        Ok(())
446    }
447
448    /// Sets which algorithm was used to compute the digest used in a
449    /// signature. With RSA signatures this causes the signature to be wrapped
450    /// in a `DigestInfo` structure. This is almost always what you want with
451    /// RSA signatures.
452    #[corresponds(EVP_PKEY_CTX_set_signature_md)]
453    #[inline]
454    pub fn set_signature_md(&self, md: &MdRef) -> Result<(), ErrorStack> {
455        unsafe {
456            cvt(ffi::EVP_PKEY_CTX_set_signature_md(
457                self.as_ptr(),
458                md.as_ptr(),
459            ))?;
460        }
461        Ok(())
462    }
463
464    /// Sets the DH paramgen prime length.
465    ///
466    /// This is only useful for DH keys.
467    #[corresponds(EVP_PKEY_CTX_set_dh_paramgen_prime_len)]
468    #[cfg(not(boringssl))]
469    #[inline]
470    pub fn set_dh_paramgen_prime_len(&mut self, bits: u32) -> Result<(), ErrorStack> {
471        unsafe {
472            cvt(ffi::EVP_PKEY_CTX_set_dh_paramgen_prime_len(
473                self.as_ptr(),
474                bits as i32,
475            ))?;
476        }
477
478        Ok(())
479    }
480
481    /// Sets the DH paramgen generator.
482    ///
483    /// This is only useful for DH keys.
484    #[corresponds(EVP_PKEY_CTX_set_dh_paramgen_generator)]
485    #[cfg(not(boringssl))]
486    #[inline]
487    pub fn set_dh_paramgen_generator(&mut self, bits: u32) -> Result<(), ErrorStack> {
488        unsafe {
489            cvt(ffi::EVP_PKEY_CTX_set_dh_paramgen_generator(
490                self.as_ptr(),
491                bits as i32,
492            ))?;
493        }
494
495        Ok(())
496    }
497
498    /// Sets the DSA paramgen bits.
499    ///
500    /// This is only useful for DSA keys.
501    #[corresponds(EVP_PKEY_CTX_set_dsa_paramgen_bits)]
502    #[inline]
503    pub fn set_dsa_paramgen_bits(&mut self, bits: u32) -> Result<(), ErrorStack> {
504        unsafe {
505            cvt(ffi::EVP_PKEY_CTX_set_dsa_paramgen_bits(
506                self.as_ptr(),
507                bits as i32,
508            ))?;
509        }
510
511        Ok(())
512    }
513
514    /// Sets the EC paramgen curve NID.
515    ///
516    /// This is only useful for EC keys.
517    #[corresponds(EVP_PKEY_CTX_set_ec_paramgen_curve_nid)]
518    #[inline]
519    pub fn set_ec_paramgen_curve_nid(&mut self, nid: Nid) -> Result<(), ErrorStack> {
520        unsafe {
521            cvt(ffi::EVP_PKEY_CTX_set_ec_paramgen_curve_nid(
522                self.as_ptr(),
523                nid.as_raw(),
524            ))?;
525        }
526
527        Ok(())
528    }
529
530    /// Returns the RSA padding mode in use.
531    ///
532    /// This is only useful for RSA keys.
533    #[corresponds(EVP_PKEY_CTX_get_rsa_padding)]
534    #[inline]
535    pub fn rsa_padding(&self) -> Result<Padding, ErrorStack> {
536        let mut pad = 0;
537        unsafe {
538            cvt(ffi::EVP_PKEY_CTX_get_rsa_padding(self.as_ptr(), &mut pad))?;
539        }
540
541        Ok(Padding::from_raw(pad))
542    }
543
544    /// Sets the RSA padding mode.
545    ///
546    /// This is only useful for RSA keys.
547    #[corresponds(EVP_PKEY_CTX_set_rsa_padding)]
548    #[inline]
549    pub fn set_rsa_padding(&mut self, padding: Padding) -> Result<(), ErrorStack> {
550        unsafe {
551            cvt(ffi::EVP_PKEY_CTX_set_rsa_padding(
552                self.as_ptr(),
553                padding.as_raw(),
554            ))?;
555        }
556
557        Ok(())
558    }
559
560    /// Sets the RSA keygen bits.
561    ///
562    /// This is only useful for RSA keys.
563    #[corresponds(EVP_PKEY_CTX_set_rsa_keygen_bits)]
564    #[inline]
565    pub fn set_rsa_keygen_bits(&mut self, bits: u32) -> Result<(), ErrorStack> {
566        unsafe {
567            cvt(ffi::EVP_PKEY_CTX_set_rsa_keygen_bits(
568                self.as_ptr(),
569                bits as i32,
570            ))?;
571        }
572
573        Ok(())
574    }
575
576    /// Sets the RSA keygen public exponent.
577    ///
578    /// This is only useful for RSA keys.
579    #[corresponds(EVP_PKEY_CTX_set1_rsa_keygen_pubexp)]
580    #[inline]
581    pub fn set_rsa_keygen_pubexp(&mut self, pubexp: &BigNumRef) -> Result<(), ErrorStack> {
582        unsafe {
583            cfg_if! {
584                if #[cfg(ossl300)] {
585                    cvt(ffi::EVP_PKEY_CTX_set1_rsa_keygen_pubexp(
586                        self.as_ptr(),
587                        pubexp.as_ptr(),
588                    ))?;
589                } else {
590                    cvt(ffi::EVP_PKEY_CTX_set_rsa_keygen_pubexp(
591                        self.as_ptr(),
592                        // Dupe the BN because the EVP_PKEY_CTX takes ownership of it and will free it.
593                        cvt_p(ffi::BN_dup(pubexp.as_ptr()))?,
594                    ))?;
595                }
596            }
597        }
598
599        Ok(())
600    }
601
602    /// Sets the RSA PSS salt length.
603    ///
604    /// This is only useful for RSA keys.
605    #[corresponds(EVP_PKEY_CTX_set_rsa_pss_saltlen)]
606    #[inline]
607    pub fn set_rsa_pss_saltlen(&mut self, len: RsaPssSaltlen) -> Result<(), ErrorStack> {
608        unsafe {
609            cvt(ffi::EVP_PKEY_CTX_set_rsa_pss_saltlen(
610                self.as_ptr(),
611                len.as_raw(),
612            ))
613            .map(|_| ())
614        }
615    }
616
617    /// Sets the RSA MGF1 algorithm.
618    ///
619    /// This is only useful for RSA keys.
620    #[corresponds(EVP_PKEY_CTX_set_rsa_mgf1_md)]
621    #[inline]
622    pub fn set_rsa_mgf1_md(&mut self, md: &MdRef) -> Result<(), ErrorStack> {
623        unsafe {
624            cvt(ffi::EVP_PKEY_CTX_set_rsa_mgf1_md(
625                self.as_ptr(),
626                md.as_ptr(),
627            ))?;
628        }
629
630        Ok(())
631    }
632
633    /// Sets the RSA OAEP algorithm.
634    ///
635    /// This is only useful for RSA keys.
636    #[corresponds(EVP_PKEY_CTX_set_rsa_oaep_md)]
637    #[inline]
638    pub fn set_rsa_oaep_md(&mut self, md: &MdRef) -> Result<(), ErrorStack> {
639        unsafe {
640            cvt(ffi::EVP_PKEY_CTX_set_rsa_oaep_md(
641                self.as_ptr(),
642                md.as_ptr() as *mut _,
643            ))?;
644        }
645
646        Ok(())
647    }
648
649    /// Sets the RSA OAEP label.
650    ///
651    /// This is only useful for RSA keys.
652    #[corresponds(EVP_PKEY_CTX_set0_rsa_oaep_label)]
653    pub fn set_rsa_oaep_label(&mut self, label: &[u8]) -> Result<(), ErrorStack> {
654        use crate::LenType;
655        let len = LenType::try_from(label.len()).unwrap();
656
657        unsafe {
658            let p = cvt_p(ffi::OPENSSL_malloc(label.len() as _))?;
659            ptr::copy_nonoverlapping(label.as_ptr(), p as *mut _, label.len());
660
661            let r = cvt(ffi::EVP_PKEY_CTX_set0_rsa_oaep_label(
662                self.as_ptr(),
663                p as *mut _,
664                len,
665            ));
666            if r.is_err() {
667                ffi::OPENSSL_free(p);
668            }
669            r?;
670        }
671
672        Ok(())
673    }
674
675    /// Sets the cipher used during key generation.
676    #[cfg(not(any(boringssl, awslc)))]
677    #[corresponds(EVP_PKEY_CTX_ctrl)]
678    #[inline]
679    pub fn set_keygen_cipher(&mut self, cipher: &CipherRef) -> Result<(), ErrorStack> {
680        unsafe {
681            cvt(ffi::EVP_PKEY_CTX_ctrl(
682                self.as_ptr(),
683                -1,
684                ffi::EVP_PKEY_OP_KEYGEN,
685                ffi::EVP_PKEY_CTRL_CIPHER,
686                0,
687                cipher.as_ptr() as *mut _,
688            ))?;
689        }
690
691        Ok(())
692    }
693
694    /// Sets the key MAC key used during key generation.
695    #[cfg(not(any(boringssl, awslc)))]
696    #[corresponds(EVP_PKEY_CTX_ctrl)]
697    #[inline]
698    pub fn set_keygen_mac_key(&mut self, key: &[u8]) -> Result<(), ErrorStack> {
699        let len = c_int::try_from(key.len()).unwrap();
700
701        unsafe {
702            cvt(ffi::EVP_PKEY_CTX_ctrl(
703                self.as_ptr(),
704                -1,
705                ffi::EVP_PKEY_OP_KEYGEN,
706                ffi::EVP_PKEY_CTRL_SET_MAC_KEY,
707                len,
708                key.as_ptr() as *mut _,
709            ))?;
710        }
711
712        Ok(())
713    }
714
715    /// Sets the digest used for HKDF derivation.
716    ///
717    /// Requires OpenSSL 1.1.0 or newer.
718    #[corresponds(EVP_PKEY_CTX_set_hkdf_md)]
719    #[cfg(any(ossl110, boringssl, libressl360, awslc))]
720    #[inline]
721    pub fn set_hkdf_md(&mut self, digest: &MdRef) -> Result<(), ErrorStack> {
722        unsafe {
723            cvt(ffi::EVP_PKEY_CTX_set_hkdf_md(
724                self.as_ptr(),
725                digest.as_ptr(),
726            ))?;
727        }
728
729        Ok(())
730    }
731
732    /// Sets the HKDF mode of operation.
733    ///
734    /// Defaults to [`HkdfMode::EXTRACT_THEN_EXPAND`].
735    ///
736    /// WARNING: Although this API calls it a "mode", HKDF-Extract and HKDF-Expand are distinct
737    /// operations with distinct inputs and distinct kinds of keys. Callers should not pass input
738    /// secrets for one operation into the other.
739    ///
740    /// Requires OpenSSL 1.1.1 or newer.
741    #[corresponds(EVP_PKEY_CTX_set_hkdf_mode)]
742    #[cfg(any(ossl111, libressl360))]
743    #[inline]
744    pub fn set_hkdf_mode(&mut self, mode: HkdfMode) -> Result<(), ErrorStack> {
745        unsafe {
746            cvt(ffi::EVP_PKEY_CTX_set_hkdf_mode(self.as_ptr(), mode.0))?;
747        }
748
749        Ok(())
750    }
751
752    /// Sets the input material for HKDF generation as the "key".
753    ///
754    /// Which input is the key depends on the "mode" (see [`set_hkdf_mode`][Self::set_hkdf_mode]).
755    /// If [`HkdfMode::EXTRACT_THEN_EXPAND`] or [`HkdfMode::EXTRACT_ONLY`], this function specifies
756    /// the input keying material (IKM) for HKDF-Extract. If [`HkdfMode::EXPAND_ONLY`], it instead
757    /// specifies the pseudorandom key (PRK) for HKDF-Expand.
758    ///
759    /// Requires OpenSSL 1.1.0 or newer.
760    #[corresponds(EVP_PKEY_CTX_set1_hkdf_key)]
761    #[cfg(any(ossl110, boringssl, libressl360, awslc))]
762    #[inline]
763    pub fn set_hkdf_key(&mut self, key: &[u8]) -> Result<(), ErrorStack> {
764        #[cfg(not(any(boringssl, awslc)))]
765        let len = c_int::try_from(key.len()).unwrap();
766        #[cfg(any(boringssl, awslc))]
767        let len = key.len();
768
769        unsafe {
770            cvt(ffi::EVP_PKEY_CTX_set1_hkdf_key(
771                self.as_ptr(),
772                key.as_ptr(),
773                len,
774            ))?;
775        }
776
777        Ok(())
778    }
779
780    /// Sets the salt value for HKDF generation.
781    ///
782    /// If performing HKDF-Expand only, this parameter is ignored.
783    ///
784    /// Requires OpenSSL 1.1.0 or newer.
785    #[corresponds(EVP_PKEY_CTX_set1_hkdf_salt)]
786    #[cfg(any(ossl110, boringssl, libressl360, awslc))]
787    #[inline]
788    pub fn set_hkdf_salt(&mut self, salt: &[u8]) -> Result<(), ErrorStack> {
789        #[cfg(not(any(boringssl, awslc)))]
790        let len = c_int::try_from(salt.len()).unwrap();
791        #[cfg(any(boringssl, awslc))]
792        let len = salt.len();
793
794        unsafe {
795            cvt(ffi::EVP_PKEY_CTX_set1_hkdf_salt(
796                self.as_ptr(),
797                salt.as_ptr(),
798                len,
799            ))?;
800        }
801
802        Ok(())
803    }
804
805    /// Appends info bytes for HKDF generation.
806    ///
807    /// If performing HKDF-Extract only, this parameter is ignored.
808    ///
809    /// Requires OpenSSL 1.1.0 or newer.
810    #[corresponds(EVP_PKEY_CTX_add1_hkdf_info)]
811    #[cfg(any(ossl110, boringssl, libressl360, awslc))]
812    #[inline]
813    pub fn add_hkdf_info(&mut self, info: &[u8]) -> Result<(), ErrorStack> {
814        #[cfg(not(any(boringssl, awslc)))]
815        let len = c_int::try_from(info.len()).unwrap();
816        #[cfg(any(boringssl, awslc))]
817        let len = info.len();
818
819        unsafe {
820            cvt(ffi::EVP_PKEY_CTX_add1_hkdf_info(
821                self.as_ptr(),
822                info.as_ptr(),
823                len,
824            ))?;
825        }
826
827        Ok(())
828    }
829
830    /// Derives a shared secret between two keys.
831    ///
832    /// If `buf` is set to `None`, an upper bound on the number of bytes required for the buffer will be returned.
833    #[corresponds(EVP_PKEY_derive)]
834    #[allow(unused_mut)]
835    pub fn derive(&mut self, mut buf: Option<&mut [u8]>) -> Result<usize, ErrorStack> {
836        // On OpenSSL 1.1.x some pmeths ignore *keylen and unconditionally
837        // write the full natural output size (X25519, X448, HKDF-extract),
838        // which can overflow a shorter caller-provided buffer. Others honor
839        // *keylen by truncating the output (notably the default ECDH
840        // EVP_PKEY_EC pmeth, where the OpenSSL source explicitly documents
841        // that *keylen below the natural size "is not an error, the result
842        // is truncated").
843        //
844        // We can't distinguish those two groups from the probe alone, so
845        // when the probe reports a natural size larger than the caller's
846        // buffer, derive into a temporary buffer of the probed size and
847        // copy the leading bytes out. This prevents the OOB write for the
848        // ignore-*keylen group and produces the same bytes for the
849        // honor-*keylen group (ECDH_compute_key copies leading bytes of
850        // the shared secret either way).
851        //
852        // Some pmeths (HKDF extract-and-expand and expand-only on 1.1.x)
853        // don't support the NULL-out probe and fail it with an empty error
854        // stack; those honor *keylen during derivation, so clear the
855        // errors and proceed with the direct path. usize::MAX is a
856        // sentinel some pmeths use when *keylen is caller-chosen.
857        //
858        // 3.0+ providers check the buffer size themselves, so this whole
859        // dance is cfg-gated to 1.1.x and LibreSSL.
860        #[cfg(any(all(ossl110, not(ossl300)), libressl))]
861        {
862            if let Some(b) = buf.as_deref_mut() {
863                let mut required = 0;
864                let probe_ok = unsafe {
865                    ffi::EVP_PKEY_derive(self.as_ptr(), ptr::null_mut(), &mut required) == 1
866                };
867                if !probe_ok {
868                    let _ = ErrorStack::get();
869                } else if required != usize::MAX && b.len() < required {
870                    let mut temp = vec![0u8; required];
871                    let mut len = required;
872                    unsafe {
873                        cvt(ffi::EVP_PKEY_derive(
874                            self.as_ptr(),
875                            temp.as_mut_ptr(),
876                            &mut len,
877                        ))?;
878                    }
879                    let copy_len = b.len().min(len);
880                    b[..copy_len].copy_from_slice(&temp[..copy_len]);
881                    return Ok(copy_len);
882                }
883            }
884        }
885        let mut len = buf.as_ref().map_or(0, |b| b.len());
886        unsafe {
887            cvt(ffi::EVP_PKEY_derive(
888                self.as_ptr(),
889                buf.map_or(ptr::null_mut(), |b| b.as_mut_ptr()),
890                &mut len,
891            ))?;
892        }
893
894        Ok(len)
895    }
896
897    /// Like [`Self::derive`] but appends the secret to a [`Vec`].
898    pub fn derive_to_vec(&mut self, buf: &mut Vec<u8>) -> Result<usize, ErrorStack> {
899        let base = buf.len();
900        let len = self.derive(None)?;
901        buf.resize(base + len, 0);
902        let len = self.derive(Some(&mut buf[base..]))?;
903        buf.truncate(base + len);
904        Ok(len)
905    }
906
907    /// Generates a new public/private keypair.
908    #[corresponds(EVP_PKEY_keygen)]
909    #[inline]
910    pub fn keygen(&mut self) -> Result<PKey<Private>, ErrorStack> {
911        unsafe {
912            let mut key = ptr::null_mut();
913            cvt(ffi::EVP_PKEY_keygen(self.as_ptr(), &mut key))?;
914            Ok(PKey::from_ptr(key))
915        }
916    }
917
918    /// Generates a new set of key parameters.
919    #[corresponds(EVP_PKEY_paramgen)]
920    #[inline]
921    pub fn paramgen(&mut self) -> Result<PKey<Params>, ErrorStack> {
922        unsafe {
923            let mut key = ptr::null_mut();
924            cvt(ffi::EVP_PKEY_paramgen(self.as_ptr(), &mut key))?;
925            Ok(PKey::from_ptr(key))
926        }
927    }
928
929    /// Sets the nonce type for a private key context.
930    ///
931    /// The nonce for DSA and ECDSA can be either random (the default) or deterministic (as defined by RFC 6979).
932    ///
933    /// This is only useful for DSA and ECDSA.
934    /// Requires OpenSSL 3.2.0 or newer.
935    #[cfg(ossl320)]
936    #[corresponds(EVP_PKEY_CTX_set_params)]
937    pub fn set_nonce_type(&mut self, nonce_type: NonceType) -> Result<(), ErrorStack> {
938        let nonce_field_name = c"nonce-type";
939        let mut nonce_type = nonce_type.0;
940        unsafe {
941            let param_nonce =
942                ffi::OSSL_PARAM_construct_uint(nonce_field_name.as_ptr(), &mut nonce_type);
943            let param_end = ffi::OSSL_PARAM_construct_end();
944
945            let params = [param_nonce, param_end];
946            cvt(ffi::EVP_PKEY_CTX_set_params(self.as_ptr(), params.as_ptr()))?;
947        }
948        Ok(())
949    }
950
951    /// Gets the nonce type for a private key context.
952    ///
953    /// The nonce for DSA and ECDSA can be either random (the default) or deterministic (as defined by RFC 6979).
954    ///
955    /// This is only useful for DSA and ECDSA.
956    /// Requires OpenSSL 3.2.0 or newer.
957    #[cfg(ossl320)]
958    #[corresponds(EVP_PKEY_CTX_get_params)]
959    pub fn nonce_type(&mut self) -> Result<NonceType, ErrorStack> {
960        let nonce_field_name = c"nonce-type";
961        let mut nonce_type: c_uint = 0;
962        unsafe {
963            let param_nonce =
964                ffi::OSSL_PARAM_construct_uint(nonce_field_name.as_ptr(), &mut nonce_type);
965            let param_end = ffi::OSSL_PARAM_construct_end();
966
967            let mut params = [param_nonce, param_end];
968            cvt(ffi::EVP_PKEY_CTX_get_params(
969                self.as_ptr(),
970                params.as_mut_ptr(),
971            ))?;
972        }
973        Ok(NonceType(nonce_type))
974    }
975
976    /// Sets the context string for an ML-DSA signing or verification
977    /// operation, as defined in FIPS 204 §5.
978    ///
979    /// Requires OpenSSL 3.5.0 or newer.
980    #[cfg(ossl350)]
981    #[corresponds(EVP_PKEY_CTX_set_params)]
982    pub fn set_context_string(&mut self, context: &[u8]) -> Result<(), ErrorStack> {
983        let mut builder = crate::ossl_param::OsslParamBuilder::new()?;
984        builder.add_octet_string(c"context-string", context)?;
985        let params = builder.to_param()?;
986        unsafe {
987            cvt(ffi::EVP_PKEY_CTX_set_params(self.as_ptr(), params.as_ptr()))?;
988        }
989        Ok(())
990    }
991}
992
993#[cfg(test)]
994mod test {
995    use super::*;
996    use crate::bn::BigNum;
997    #[cfg(not(any(boringssl, awslc)))]
998    use crate::cipher::Cipher;
999    use crate::ec::{EcGroup, EcKey};
1000    use crate::hash::{hash, MessageDigest};
1001    use crate::md::Md;
1002    #[cfg(ossl350)]
1003    use crate::md_ctx::MdCtx;
1004    use crate::nid::Nid;
1005    #[cfg(ossl350)]
1006    use crate::pkey::KeyType;
1007    use crate::pkey::PKey;
1008    use crate::rsa::Rsa;
1009    use crate::sign::Verifier;
1010    #[cfg(not(boringssl))]
1011    use cfg_if::cfg_if;
1012
1013    #[test]
1014    fn rsa() {
1015        let key = include_bytes!("../test/rsa.pem");
1016        let rsa = Rsa::private_key_from_pem(key).unwrap();
1017        let pkey = PKey::from_rsa(rsa).unwrap();
1018
1019        let mut ctx = PkeyCtx::new(&pkey).unwrap();
1020        ctx.encrypt_init().unwrap();
1021        ctx.set_rsa_padding(Padding::PKCS1).unwrap();
1022
1023        let pt = "hello world".as_bytes();
1024        let mut ct = vec![];
1025        ctx.encrypt_to_vec(pt, &mut ct).unwrap();
1026
1027        ctx.decrypt_init().unwrap();
1028        ctx.set_rsa_padding(Padding::PKCS1).unwrap();
1029
1030        let mut out = vec![];
1031        ctx.decrypt_to_vec(&ct, &mut out).unwrap();
1032
1033        assert_eq!(pt, out);
1034    }
1035
1036    #[test]
1037    fn rsa_oaep() {
1038        let key = include_bytes!("../test/rsa.pem");
1039        let rsa = Rsa::private_key_from_pem(key).unwrap();
1040        let pkey = PKey::from_rsa(rsa).unwrap();
1041
1042        let mut ctx = PkeyCtx::new(&pkey).unwrap();
1043        ctx.encrypt_init().unwrap();
1044        ctx.set_rsa_padding(Padding::PKCS1_OAEP).unwrap();
1045        ctx.set_rsa_oaep_md(Md::sha256()).unwrap();
1046        ctx.set_rsa_mgf1_md(Md::sha256()).unwrap();
1047
1048        let pt = "hello world".as_bytes();
1049        let mut ct = vec![];
1050        ctx.encrypt_to_vec(pt, &mut ct).unwrap();
1051
1052        ctx.decrypt_init().unwrap();
1053        ctx.set_rsa_padding(Padding::PKCS1_OAEP).unwrap();
1054        ctx.set_rsa_oaep_md(Md::sha256()).unwrap();
1055        ctx.set_rsa_mgf1_md(Md::sha256()).unwrap();
1056
1057        let mut out = vec![];
1058        ctx.decrypt_to_vec(&ct, &mut out).unwrap();
1059
1060        assert_eq!(pt, out);
1061    }
1062
1063    #[test]
1064    fn rsa_sign() {
1065        let key = include_bytes!("../test/rsa.pem");
1066        let rsa = Rsa::private_key_from_pem(key).unwrap();
1067        let pkey = PKey::from_rsa(rsa).unwrap();
1068
1069        let mut ctx = PkeyCtx::new(&pkey).unwrap();
1070        ctx.sign_init().unwrap();
1071        ctx.set_rsa_padding(Padding::PKCS1).unwrap();
1072        ctx.set_signature_md(Md::sha384()).unwrap();
1073
1074        let msg = b"hello world";
1075        let digest = hash(MessageDigest::sha384(), msg).unwrap();
1076        let mut signature = vec![];
1077        ctx.sign_to_vec(&digest, &mut signature).unwrap();
1078
1079        let mut verifier = Verifier::new(MessageDigest::sha384(), &pkey).unwrap();
1080        verifier.update(msg).unwrap();
1081        assert!(matches!(verifier.verify(&signature), Ok(true)));
1082    }
1083
1084    #[test]
1085    fn rsa_sign_pss() {
1086        let key = include_bytes!("../test/rsa.pem");
1087        let rsa = Rsa::private_key_from_pem(key).unwrap();
1088        let pkey = PKey::from_rsa(rsa).unwrap();
1089
1090        let mut ctx = PkeyCtx::new(&pkey).unwrap();
1091        ctx.sign_init().unwrap();
1092        ctx.set_rsa_padding(Padding::PKCS1_PSS).unwrap();
1093        ctx.set_signature_md(Md::sha384()).unwrap();
1094        ctx.set_rsa_pss_saltlen(RsaPssSaltlen::custom(14)).unwrap();
1095
1096        let msg = b"hello world";
1097        let digest = hash(MessageDigest::sha384(), msg).unwrap();
1098        let mut signature = vec![];
1099        ctx.sign_to_vec(&digest, &mut signature).unwrap();
1100
1101        let mut verifier = Verifier::new(MessageDigest::sha384(), &pkey).unwrap();
1102        verifier.set_rsa_padding(Padding::PKCS1_PSS).unwrap();
1103        verifier
1104            .set_rsa_pss_saltlen(RsaPssSaltlen::custom(14))
1105            .unwrap();
1106        verifier.update(msg).unwrap();
1107        assert!(matches!(verifier.verify(&signature), Ok(true)));
1108    }
1109
1110    #[test]
1111    fn derive() {
1112        let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
1113        let key1 = EcKey::generate(&group).unwrap();
1114        let key1 = PKey::from_ec_key(key1).unwrap();
1115        let key2 = EcKey::generate(&group).unwrap();
1116        let key2 = PKey::from_ec_key(key2).unwrap();
1117
1118        let mut ctx = PkeyCtx::new(&key1).unwrap();
1119        ctx.derive_init().unwrap();
1120        ctx.derive_set_peer(&key2).unwrap();
1121
1122        let mut buf = vec![];
1123        ctx.derive_to_vec(&mut buf).unwrap();
1124    }
1125
1126    #[test]
1127    #[cfg(any(ossl111, libressl370))]
1128    fn derive_undersized_buffer() {
1129        // Without the temp-buffer fallback in this crate, X25519 on 1.1.x
1130        // would OOB into a 4-byte buffer because it ignores *keylen.
1131        // On 1.1.x / LibreSSL the fallback kicks in and we return the
1132        // truncated prefix. On 3.0+ the provider rejects undersized
1133        // buffers before any write happens, so the call errors out.
1134        let key1 = PKey::generate_x25519().unwrap();
1135        let key2 = PKey::generate_x25519().unwrap();
1136
1137        let mut ctx = PkeyCtx::new(&key1).unwrap();
1138        ctx.derive_init().unwrap();
1139        ctx.derive_set_peer(&key2).unwrap();
1140
1141        let mut buf = [0u8; 4];
1142        let result = ctx.derive(Some(&mut buf));
1143        #[cfg(any(all(ossl110, not(ossl300)), libressl))]
1144        assert_eq!(result.unwrap(), 4);
1145        #[cfg(all(ossl300, not(libressl)))]
1146        assert!(result.is_err());
1147    }
1148
1149    #[test]
1150    #[cfg(not(any(boringssl, awslc)))]
1151    fn cmac_keygen() {
1152        let mut ctx = PkeyCtx::new_id(Id::CMAC).unwrap();
1153        ctx.keygen_init().unwrap();
1154        ctx.set_keygen_cipher(Cipher::aes_128_cbc()).unwrap();
1155        ctx.set_keygen_mac_key(&hex::decode("9294727a3638bb1c13f48ef8158bfc9d").unwrap())
1156            .unwrap();
1157        ctx.keygen().unwrap();
1158    }
1159
1160    #[test]
1161    #[cfg(not(boringssl))]
1162    fn dh_paramgen() {
1163        let mut ctx = PkeyCtx::new_id(Id::DH).unwrap();
1164        ctx.paramgen_init().unwrap();
1165        ctx.set_dh_paramgen_prime_len(512).unwrap();
1166        ctx.set_dh_paramgen_generator(2).unwrap();
1167        let params = ctx.paramgen().unwrap();
1168
1169        assert_eq!(params.size(), 64);
1170    }
1171
1172    #[test]
1173    #[cfg(not(boringssl))]
1174    fn dsa_paramgen() {
1175        let mut ctx = PkeyCtx::new_id(Id::DSA).unwrap();
1176        ctx.paramgen_init().unwrap();
1177        ctx.set_dsa_paramgen_bits(2048).unwrap();
1178        let params = ctx.paramgen().unwrap();
1179
1180        let size = {
1181            cfg_if! {
1182                if #[cfg(awslc)] {
1183                    72
1184                } else if #[cfg(libressl)] {
1185                    48
1186                } else {
1187                    64
1188                }
1189            }
1190        };
1191        assert_eq!(params.size(), size);
1192    }
1193
1194    #[test]
1195    fn ec_keygen() {
1196        let mut ctx = PkeyCtx::new_id(Id::EC).unwrap();
1197        ctx.paramgen_init().unwrap();
1198        ctx.set_ec_paramgen_curve_nid(Nid::X9_62_PRIME256V1)
1199            .unwrap();
1200        let params = ctx.paramgen().unwrap();
1201
1202        assert_eq!(params.size(), 72);
1203    }
1204
1205    #[test]
1206    fn rsa_keygen() {
1207        let pubexp = BigNum::from_u32(65537).unwrap();
1208        let mut ctx = PkeyCtx::new_id(Id::RSA).unwrap();
1209        ctx.keygen_init().unwrap();
1210        ctx.set_rsa_keygen_pubexp(&pubexp).unwrap();
1211        ctx.set_rsa_keygen_bits(2048).unwrap();
1212        let key = ctx.keygen().unwrap();
1213
1214        assert_eq!(key.bits(), 2048);
1215    }
1216
1217    #[test]
1218    #[cfg(any(ossl110, boringssl, libressl360, awslc))]
1219    fn hkdf() {
1220        let mut ctx = PkeyCtx::new_id(Id::HKDF).unwrap();
1221        ctx.derive_init().unwrap();
1222        ctx.set_hkdf_md(Md::sha256()).unwrap();
1223        ctx.set_hkdf_key(&hex::decode("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b").unwrap())
1224            .unwrap();
1225        ctx.set_hkdf_salt(&hex::decode("000102030405060708090a0b0c").unwrap())
1226            .unwrap();
1227        ctx.add_hkdf_info(&hex::decode("f0f1f2f3f4f5f6f7f8f9").unwrap())
1228            .unwrap();
1229        let mut out = [0; 42];
1230        ctx.derive(Some(&mut out)).unwrap();
1231
1232        assert_eq!(
1233            &out[..],
1234            hex::decode("3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865")
1235                .unwrap()
1236        );
1237    }
1238
1239    #[test]
1240    #[cfg(any(ossl111, libressl360))]
1241    fn hkdf_expand() {
1242        let mut ctx = PkeyCtx::new_id(Id::HKDF).unwrap();
1243        ctx.derive_init().unwrap();
1244        ctx.set_hkdf_mode(HkdfMode::EXPAND_ONLY).unwrap();
1245        ctx.set_hkdf_md(Md::sha256()).unwrap();
1246        ctx.set_hkdf_key(
1247            &hex::decode("077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5")
1248                .unwrap(),
1249        )
1250        .unwrap();
1251        ctx.add_hkdf_info(&hex::decode("f0f1f2f3f4f5f6f7f8f9").unwrap())
1252            .unwrap();
1253        let mut out = [0; 42];
1254        ctx.derive(Some(&mut out)).unwrap();
1255
1256        assert_eq!(
1257            &out[..],
1258            hex::decode("3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865")
1259                .unwrap()
1260        );
1261    }
1262
1263    #[test]
1264    #[cfg(any(ossl111, libressl360))]
1265    fn hkdf_extract() {
1266        let mut ctx = PkeyCtx::new_id(Id::HKDF).unwrap();
1267        ctx.derive_init().unwrap();
1268        ctx.set_hkdf_mode(HkdfMode::EXTRACT_ONLY).unwrap();
1269        ctx.set_hkdf_md(Md::sha256()).unwrap();
1270        ctx.set_hkdf_key(&hex::decode("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b").unwrap())
1271            .unwrap();
1272        ctx.set_hkdf_salt(&hex::decode("000102030405060708090a0b0c").unwrap())
1273            .unwrap();
1274        let mut out = vec![];
1275        ctx.derive_to_vec(&mut out).unwrap();
1276
1277        assert_eq!(
1278            &out[..],
1279            hex::decode("077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5")
1280                .unwrap()
1281        );
1282    }
1283
1284    #[test]
1285    fn verify_fail() {
1286        let key1 = Rsa::generate(4096).unwrap();
1287        let key1 = PKey::from_rsa(key1).unwrap();
1288
1289        let data = b"Some Crypto Text";
1290
1291        let mut ctx = PkeyCtx::new(&key1).unwrap();
1292        ctx.sign_init().unwrap();
1293        let mut signature = vec![];
1294        ctx.sign_to_vec(data, &mut signature).unwrap();
1295
1296        let bad_data = b"Some Crypto text";
1297
1298        ctx.verify_init().unwrap();
1299        let valid = ctx.verify(bad_data, &signature);
1300        assert!(matches!(valid, Ok(false) | Err(_)));
1301        assert!(ErrorStack::get().errors().is_empty());
1302    }
1303
1304    #[test]
1305    fn verify_fail_ec() {
1306        let key1 =
1307            EcKey::generate(&EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap()).unwrap();
1308        let key1 = PKey::from_ec_key(key1).unwrap();
1309
1310        let data = b"Some Crypto Text";
1311        let mut ctx = PkeyCtx::new(&key1).unwrap();
1312        ctx.verify_init().unwrap();
1313        assert!(matches!(ctx.verify(data, &[0; 64]), Ok(false) | Err(_)));
1314        assert!(ErrorStack::get().errors().is_empty());
1315    }
1316
1317    #[test]
1318    fn test_verify_recover() {
1319        let key = Rsa::generate(2048).unwrap();
1320        let key = PKey::from_rsa(key).unwrap();
1321
1322        let digest = [
1323            0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
1324            24, 25, 26, 27, 28, 29, 30, 31,
1325        ];
1326
1327        let mut ctx = PkeyCtx::new(&key).unwrap();
1328        ctx.sign_init().unwrap();
1329        ctx.set_rsa_padding(Padding::PKCS1).unwrap();
1330        ctx.set_signature_md(Md::sha256()).unwrap();
1331        let mut signature = vec![];
1332        ctx.sign_to_vec(&digest, &mut signature).unwrap();
1333
1334        // Attempt recovery of just the digest.
1335        let mut ctx = PkeyCtx::new(&key).unwrap();
1336        ctx.verify_recover_init().unwrap();
1337        ctx.set_rsa_padding(Padding::PKCS1).unwrap();
1338        ctx.set_signature_md(Md::sha256()).unwrap();
1339        let length = ctx.verify_recover(&signature, None).unwrap();
1340        let mut result_buf = vec![0; length];
1341        let length = ctx
1342            .verify_recover(&signature, Some(&mut result_buf))
1343            .unwrap();
1344        assert_eq!(length, digest.len());
1345        // result_buf contains the digest
1346        assert_eq!(result_buf[..length], digest);
1347
1348        // Attempt recovery of the entire DigestInfo
1349        let mut ctx = PkeyCtx::new(&key).unwrap();
1350        ctx.verify_recover_init().unwrap();
1351        ctx.set_rsa_padding(Padding::PKCS1).unwrap();
1352        let length = ctx.verify_recover(&signature, None).unwrap();
1353        let mut result_buf = vec![0; length];
1354        let length = ctx
1355            .verify_recover(&signature, Some(&mut result_buf))
1356            .unwrap();
1357        // 32-bytes of SHA256 digest + the ASN.1 DigestInfo structure == 51 bytes
1358        assert_eq!(length, 51);
1359        // The digest is the end of the DigestInfo structure.
1360        assert_eq!(result_buf[length - digest.len()..length], digest);
1361
1362        // A buffer shorter than the reported length is rejected instead of
1363        // being written past.
1364        let mut short_buf = vec![0; 8];
1365        assert!(ctx
1366            .verify_recover(&signature, Some(&mut short_buf))
1367            .is_err());
1368        assert_eq!(short_buf, [0; 8]);
1369    }
1370
1371    #[test]
1372    #[cfg(ossl320)]
1373    fn set_nonce_type() {
1374        let key1 =
1375            EcKey::generate(&EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap()).unwrap();
1376        let key1 = PKey::from_ec_key(key1).unwrap();
1377
1378        let mut ctx = PkeyCtx::new(&key1).unwrap();
1379        ctx.sign_init().unwrap();
1380        ctx.set_nonce_type(NonceType::DETERMINISTIC_K).unwrap();
1381        let nonce_type = ctx.nonce_type().unwrap();
1382        assert_eq!(nonce_type, NonceType::DETERMINISTIC_K);
1383        assert!(ErrorStack::get().errors().is_empty());
1384    }
1385
1386    // Test vector from
1387    // https://github.com/openssl/openssl/blob/openssl-3.2.0/test/recipes/30-test_evp_data/evppkey_ecdsa_rfc6979.txt
1388    #[test]
1389    #[cfg(ossl320)]
1390    fn ecdsa_deterministic_signature() {
1391        let private_key_pem = "-----BEGIN PRIVATE KEY-----
1392MEECAQAwEwYHKoZIzj0CAQYIKoZIzj0DAQcEJzAlAgEBBCDJr6nYRbp1FmtcIVdnsdaTTlDD2zbo
1393mxJ7imIrEg9nIQ==
1394-----END PRIVATE KEY-----";
1395
1396        let key1 = EcKey::private_key_from_pem(private_key_pem.as_bytes()).unwrap();
1397        let key1 = PKey::from_ec_key(key1).unwrap();
1398        let input = "sample";
1399        let expected_output = hex::decode("3046022100EFD48B2AACB6A8FD1140DD9CD45E81D69D2C877B56AAF991C34D0EA84EAF3716022100F7CB1C942D657C41D436C7A1B6E29F65F3E900DBB9AFF4064DC4AB2F843ACDA8").unwrap();
1400
1401        let hashed_input = hash(MessageDigest::sha256(), input.as_bytes()).unwrap();
1402        let mut ctx = PkeyCtx::new(&key1).unwrap();
1403        ctx.sign_init().unwrap();
1404        ctx.set_signature_md(Md::sha256()).unwrap();
1405        ctx.set_nonce_type(NonceType::DETERMINISTIC_K).unwrap();
1406
1407        let mut output = vec![];
1408        ctx.sign_to_vec(&hashed_input, &mut output).unwrap();
1409        assert_eq!(output, expected_output);
1410        assert!(ErrorStack::get().errors().is_empty());
1411    }
1412
1413    #[test]
1414    #[cfg(ossl350)]
1415    fn set_context_string_mldsa() {
1416        // ML-DSA-65 KAT vector 0 from
1417        // https://github.com/post-quantum-cryptography/KAT/blob/main/MLDSA/kat_MLDSA_65_det_pure.rsp
1418        let xi = hex::decode("f696484048ec21f96cf50a56d0759c448f3779752f0383d37449690694cf7a68")
1419            .unwrap();
1420        let msg = hex::decode("6dbbc4375136df3b07f7c70e639e223e").unwrap();
1421        let ctx = hex::decode("480c658c0cb3e040bde084345cef0df7").unwrap();
1422        let expected_sig = hex::decode("0e9e903efe9d51ef5356b9794e52cf55cbfde58596f7e81faafe2921928279aab3ec9ba9a072c2c68adc72f0c2946fd4f5adb4c722a2f0e55676f1c79cbdc1d8afd19cf86156b5f7f8d012cd8245fb03fe30c62ea63110a722782367983030afadd16391b345f00d9c6d9750ae4b7099d5fcb66b944a213cf4881fa0f806e293554e869205e3e8e9abe67d0749d8c72fb882d3f3d1512f3077845787050527bde82da3cfc8ae9d0ab7827281a14f2bf6131cb79d27f4c781d0e8e42da9fdecb5be1979c9ccde17f1cc5b94f2f8e0a93d3e085ec72e221ca7d6bdad712a2c649b7bfdd0ad02306dd49cbdc298d4b23e73db05aa6a8b1514396e3032fe512d8cf58c5b61a546e1de56d98ad98c6d6a81db9865566a7cad4d533cb1d7770f2807819bb436e89045f8ac363aa6af27b5b7488d2303b10ba6e80e61ec0b8ae5850c96edeaf97ed2ebe64f77df8708c31bc6f6d4598dfc7c7ddb12b16b85adac7d8f1c2d961983ca2db804e3062c8e94d37c97181abfa111529adf15ed04dc403e9758d545cee70e868c222ed724d0f9483d7d2c5c44ad28662382ec40b7949ce08a6acb69d05a90d52ce487ce8fb6b5e5b91a2187d021ece47700f2f8eb5d2eb8e86000f14b978a051009c54ab1f1b90daa1d0d6711249d766d91a5f8c8604568bfc2f52822c52d625f451c194a5cfa4151b4fda81873e5f444144344eb75410033e2ba3d77850cae4b34495943a3880e273bb8842295ad853d1c7055a290e5ca084ba993c18810a85392ba042b7efe1e002c923723a43cc7b2dedca6123beebc4968ce42bb10d19111b3f77f519c19e9fc8111616dfd53b01eee401af9530568ffe98164e2d2e220a66422efb00bc90b07e48804c67db44f79e0595ad4a31e9b760c01e9fc239fabf55837316d7a13fd069f86563936e7b61ccb7d0dee4bd93e6b129c7da92a4516b7fa263cb6bf5940228312973b442f305dcfc40f843be2da8d693450f9ecf339bc9419f543a2fa0d4dc7793aced11d8e50d68003c2bd0212a7af1a5cfd7e8e54f14d8c627b3cd9558fbab33bf6209e485e59a9c9feecc54caa2dfece838b97b313c169cf27404cfc6dc5174856300208e10244183b2fcd28d34d67228eb9611b8f739a112178dc143fda2b8e64417e0f4c18f875eff34ec80a0fe04b5016473385a3e9c7b863b49ca05ebc3a34724a99488eba3dd49608da335a2acda60a91f3b8fb04ca30de481c0e1f17af2f13227b183345250b523257e08b58e15eb7b22a82ce581e63310a35cffb159ec276ecf3fac1ccefc23389de6c29b7e4454987611b315fb7684c72376ba448161cd82bc6a924095097c897b414750df37d34bbd2844979fbbdf68110afc3e14cce7cf963c375c92dcf65e4d633093bb8094052f8e9e6c4f3f650e9082f7346867794474a89f74e543714a5ad03ba003ffc1c716d56fb6078798e68ad4072d7db5099d0eb2c7ffdf21bcb4308965c13e0e1bd36bfab7c4267fa0c02ac393e70883b734027b9b087dabcd2c9bb65d9f769eae934c2b0415b2a5f2d7933e259ba51b2bd82fc08aa496e5fd3c4c0668e432dda489b4b9626006a2a958c0758624544279336421e92c477b09b968137686b68c5fbee84629b2c6b5506ad42198eefe6dfed5273fd74387faec972120aeaf85bec1491293362ebb2bda24eb7b3632c0950cf16f793fb333ca0025f57ce51b141cdc34456bfce530b417b00b574cbd4d13be8ef48fd3326948f7adc5b1f0398fcf0281e040407b3f9b7f79e4f1e89fb5eca34c9b387b0db3a5e98e253b999cd4c1616fd7e3fd26aa896c2118fe1e92499ddf5ff1125377a59987e84e03181262f7ad843b61b6450d92372cbcac16ba5b9b8d8deee7781f841672d91f336ce220fbfff7e32d61c98f5249e67bfef35edc3d9c3630b4f956c44c4a3e93f851c7775b64d759f2632b5ee38f0f3fff016a1fd3999b50c4f1de82cec0f11c34e494d51ad34df7bd812899daec5dfbd1b8405baf261e1da7898ba1dc1ced8afa4c23d662859d8a68205b62b6f908e2411d3a125e71442f74fc08b02e65195a63f198e1cb6c408e6a1b157d2a4b85a792cac2a07ddaea79c5858ce0ebdcdeab199483e2367f9b4785344447dca9251eb3df906cf4934228c4c028495f00e130722e175243791680bf540ca60e4c17c910637f6db35c1670d5c6d7e8264fa97fa540c870c87d1aa441599ee6fe6c22eabf8fc49c824b3bfac6491a2349ea33c4cb6cb19c0facb7d0cdb62db2ba56a5c337f9fe7b4ab5936275f98fe487b6c4805be709f67456caebd3043737a5974b0ca932b19c435bed01010c4617d350d803ff22dbbb3442189d9f81a0e5b47edfa4ea0a832fb14d27b19be226b42910ed10ac2d404abd96262bde3c391b238fa9bcfd3734275dacfc411811e01b1178750c745fe9462740c3f91f130535a7feb6be25b34a3314666ebaef01f5ec8b656add9b87e59c5bae71153e91be21505f27246035ec6c2569d7f165723a169cda18aaadb1481d84976da019a149b02f5b1f9b8c090a8115ecb3be65423aa1461e35c804a411b1cb191a8734233ca7a42acaee8eb4f451aa3089b9542a3c65e92a3a74b14443d1a8d72846fa7846098ec3233d2553ed4ab542c8c425cbabb94bb2fdb5223acb999ba31a19a0ff9b646fc4297832d36722e0af0c03899c8ce17c79303b091512f0106b4285e6e8faf09325f0bc3d8d724575c9556931a4dc34c93d81a79f25199ed712a97309630b5635ae067edd4e17be9d4e194905f8d3c7c6ad93bd219beac7c389f62f8adec30a72bcbc15e8586b9e2b057140eb95fadd960389230edb3925dd9a7deb86f72502ffcebbe9a65a99e6cecf61823f9cd326f298b9430a0f476e57093895e26b0375c327b29c3e37f14474af815dd90cfbc8e61fc2f0b528b3db0e5a5407db99c3c5c2862e3b68084305e93c79f1b962a6a5d28c76969e1d5d1e82ad831ee1b6238208890db7006b395771e34c1a0d25ebf651273ba3d495417033163b46f6a176b79c446c92ebbed4bc84f0e1effc0b38d3e269cd39f392472f1634acd1bd178a8ea5a54e045c45e19d54bc286e9fb0e324c30e00593529aa28f7b66288144ba6db9ff9f368565944bf776e93e27741fd7ded89144bad8a3c1287498973d7cd8d883fe3012db6af76e9ee1dfc189e1e7f97f1e23b288c5776de731b286a80fa349b09db359a5cfafc83c46de3b43cfe9e96270e18749a3af460d1312c4eb058935f13eaa29e8836877a88734356a816b319178776310086551003227f0b191aa6058cf8209de79cf106d57c4b769f142054ccc16b0348bf620f1a28dca8ff02e11fdae7cd155383b59e4acdfc53795786b759b5a03abb1b25adccf711e30ce1b783dbf75421d6ca5e146c6deca0da3078575c936063131c14f57ec4eef5fa5047f3e3be6fe2d3940878f905ee5c7e46cfa43575b64b6a5f71eb715e2cf1aa514df138234317b401d57f1a61ff08a0eedaa6b4370e61003532fffabfbe368eb465230b7f25c80bf73ae239b9deb8ce54b64bfc06820c01507aa2d9a8a6a9f5ed2d8912b4e1b43192baee1e10df1c15c88f7fb4381cac124848b55549239e2f1acc7a4352c4aeb56307d670ea52217b272345effaba37c04dccf9f4d8a9c89e2d51ee3cfd8a53e369256800af40e230d2c554114e99db275e8f8dc34ad6f2ecca886e018bce9822041a9196d4efe9ec952ae2ff4fc8256084923075295a82034909942c87b64e5bb941eae7de6cba2540c594b3f1f4a24d6fc25d1182a88b9e6dc4616a3a76d03523e8c34c71684d8c5e5be134402df6153e9230f6e013ec6131e5af35a4b8c5aa227b2452cc8232bbc904d4b822eeddf96c89b16af80856afe9d5a66f914b81b2d52efc451e6f3d92cfba8070a9b3957e74db749c1b94dc5acd950b6a553909229fd916a1cfd56701f57a0971224070eb24d3718a665dda9b4ca9171ffbdfea55ef194f91ecc61d04cf5068cb3b7e481073b9396e8ec349e5257db91f0f00d9df9d3b465ca93c15c9efefb9aed057343eb169b206aa0db60db319801899a2b6527e1f97263444599b555dab700dffc302d6767385f982c78b4932ca12a16d575752b915b034dd69f3473c52097fc6078dd7ef6462b820bee65980510367235191d900033f13b7e2bd43cd423fbed47aa54377f67be5583c1c385c659449bf202032502d2db40101cdb5543ddfcea652c5b3c711d932c2c22ec67256b194e5bcab3ae054d02b22e7193c7c32aa3a958822cd5917117f53569ad42a5b30a64781355d22ff3bb70b76430b7e8e538df4c5411a09e6fecc4086d86aebfe497315056d11660165b47383302d6461a7f0f2d0c6e894c33c71c1c4eaa715d55ec369bbf7d86623a7b2b76bed3b1356ed80f8a1ee77229ab6cddd96eaa724fa740b480ae6fb1768c67adc5ce85dcf0f46026fdcdb4f346c60c2478f6da4b33fc06a0645fb5629b80e96d6f78aa4ae1c5cefefb24912de843f509e9609fc969be9a66c28d5608d6bcdc6bc0e6ca5752142e196679935fc745f1a84fed03d47276e29ffefa61b4232b737583c1c2e93752a7acbac2f747698b9b023a4000122a706c758fd300000000000000000000000000000000000000000000000000080f13161a1e").unwrap();
1423
1424        let key = PKey::private_key_from_seed(None, KeyType::ML_DSA_65, None, &xi).unwrap();
1425
1426        // Verify the KAT signature against the matching context string.
1427        let mut md_ctx = MdCtx::new().unwrap();
1428        let pkey_ctx = md_ctx.digest_verify_init(None, &key).unwrap();
1429        pkey_ctx.set_context_string(&ctx).unwrap();
1430        assert!(md_ctx.digest_verify(&msg, &expected_sig).unwrap());
1431
1432        // Sign and verify roundtrip with the same context string.
1433        let mut md_ctx = MdCtx::new().unwrap();
1434        let pkey_ctx = md_ctx.digest_sign_init(None, &key).unwrap();
1435        pkey_ctx.set_context_string(&ctx).unwrap();
1436        let mut sig = vec![];
1437        md_ctx.digest_sign_to_vec(&msg, &mut sig).unwrap();
1438
1439        let mut md_ctx = MdCtx::new().unwrap();
1440        let pkey_ctx = md_ctx.digest_verify_init(None, &key).unwrap();
1441        pkey_ctx.set_context_string(&ctx).unwrap();
1442        assert!(md_ctx.digest_verify(&msg, &sig).unwrap());
1443
1444        assert!(ErrorStack::get().errors().is_empty());
1445    }
1446}