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