Skip to main content

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