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