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
983#[cfg(test)]
984mod test {
985    use super::*;
986    use crate::bn::BigNum;
987    #[cfg(not(any(boringssl, awslc)))]
988    use crate::cipher::Cipher;
989    use crate::ec::{EcGroup, EcKey};
990    use crate::hash::{hash, MessageDigest};
991    use crate::md::Md;
992    use crate::nid::Nid;
993    use crate::pkey::PKey;
994    use crate::rsa::Rsa;
995    use crate::sign::Verifier;
996    #[cfg(not(boringssl))]
997    use cfg_if::cfg_if;
998
999    #[test]
1000    fn rsa() {
1001        let key = include_bytes!("../test/rsa.pem");
1002        let rsa = Rsa::private_key_from_pem(key).unwrap();
1003        let pkey = PKey::from_rsa(rsa).unwrap();
1004
1005        let mut ctx = PkeyCtx::new(&pkey).unwrap();
1006        ctx.encrypt_init().unwrap();
1007        ctx.set_rsa_padding(Padding::PKCS1).unwrap();
1008
1009        let pt = "hello world".as_bytes();
1010        let mut ct = vec![];
1011        ctx.encrypt_to_vec(pt, &mut ct).unwrap();
1012
1013        ctx.decrypt_init().unwrap();
1014        ctx.set_rsa_padding(Padding::PKCS1).unwrap();
1015
1016        let mut out = vec![];
1017        ctx.decrypt_to_vec(&ct, &mut out).unwrap();
1018
1019        assert_eq!(pt, out);
1020    }
1021
1022    #[test]
1023    fn rsa_oaep() {
1024        let key = include_bytes!("../test/rsa.pem");
1025        let rsa = Rsa::private_key_from_pem(key).unwrap();
1026        let pkey = PKey::from_rsa(rsa).unwrap();
1027
1028        let mut ctx = PkeyCtx::new(&pkey).unwrap();
1029        ctx.encrypt_init().unwrap();
1030        ctx.set_rsa_padding(Padding::PKCS1_OAEP).unwrap();
1031        ctx.set_rsa_oaep_md(Md::sha256()).unwrap();
1032        ctx.set_rsa_mgf1_md(Md::sha256()).unwrap();
1033
1034        let pt = "hello world".as_bytes();
1035        let mut ct = vec![];
1036        ctx.encrypt_to_vec(pt, &mut ct).unwrap();
1037
1038        ctx.decrypt_init().unwrap();
1039        ctx.set_rsa_padding(Padding::PKCS1_OAEP).unwrap();
1040        ctx.set_rsa_oaep_md(Md::sha256()).unwrap();
1041        ctx.set_rsa_mgf1_md(Md::sha256()).unwrap();
1042
1043        let mut out = vec![];
1044        ctx.decrypt_to_vec(&ct, &mut out).unwrap();
1045
1046        assert_eq!(pt, out);
1047    }
1048
1049    #[test]
1050    fn rsa_sign() {
1051        let key = include_bytes!("../test/rsa.pem");
1052        let rsa = Rsa::private_key_from_pem(key).unwrap();
1053        let pkey = PKey::from_rsa(rsa).unwrap();
1054
1055        let mut ctx = PkeyCtx::new(&pkey).unwrap();
1056        ctx.sign_init().unwrap();
1057        ctx.set_rsa_padding(Padding::PKCS1).unwrap();
1058        ctx.set_signature_md(Md::sha384()).unwrap();
1059
1060        let msg = b"hello world";
1061        let digest = hash(MessageDigest::sha384(), msg).unwrap();
1062        let mut signature = vec![];
1063        ctx.sign_to_vec(&digest, &mut signature).unwrap();
1064
1065        let mut verifier = Verifier::new(MessageDigest::sha384(), &pkey).unwrap();
1066        verifier.update(msg).unwrap();
1067        assert!(matches!(verifier.verify(&signature), Ok(true)));
1068    }
1069
1070    #[test]
1071    fn rsa_sign_pss() {
1072        let key = include_bytes!("../test/rsa.pem");
1073        let rsa = Rsa::private_key_from_pem(key).unwrap();
1074        let pkey = PKey::from_rsa(rsa).unwrap();
1075
1076        let mut ctx = PkeyCtx::new(&pkey).unwrap();
1077        ctx.sign_init().unwrap();
1078        ctx.set_rsa_padding(Padding::PKCS1_PSS).unwrap();
1079        ctx.set_signature_md(Md::sha384()).unwrap();
1080        ctx.set_rsa_pss_saltlen(RsaPssSaltlen::custom(14)).unwrap();
1081
1082        let msg = b"hello world";
1083        let digest = hash(MessageDigest::sha384(), msg).unwrap();
1084        let mut signature = vec![];
1085        ctx.sign_to_vec(&digest, &mut signature).unwrap();
1086
1087        let mut verifier = Verifier::new(MessageDigest::sha384(), &pkey).unwrap();
1088        verifier.set_rsa_padding(Padding::PKCS1_PSS).unwrap();
1089        verifier
1090            .set_rsa_pss_saltlen(RsaPssSaltlen::custom(14))
1091            .unwrap();
1092        verifier.update(msg).unwrap();
1093        assert!(matches!(verifier.verify(&signature), Ok(true)));
1094    }
1095
1096    #[test]
1097    fn derive() {
1098        let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
1099        let key1 = EcKey::generate(&group).unwrap();
1100        let key1 = PKey::from_ec_key(key1).unwrap();
1101        let key2 = EcKey::generate(&group).unwrap();
1102        let key2 = PKey::from_ec_key(key2).unwrap();
1103
1104        let mut ctx = PkeyCtx::new(&key1).unwrap();
1105        ctx.derive_init().unwrap();
1106        ctx.derive_set_peer(&key2).unwrap();
1107
1108        let mut buf = vec![];
1109        ctx.derive_to_vec(&mut buf).unwrap();
1110    }
1111
1112    #[test]
1113    #[cfg(any(ossl111, libressl370))]
1114    fn derive_undersized_buffer() {
1115        // Without the temp-buffer fallback in this crate, X25519 on 1.1.x
1116        // would OOB into a 4-byte buffer because it ignores *keylen.
1117        // On 1.1.x / LibreSSL the fallback kicks in and we return the
1118        // truncated prefix. On 3.0+ the provider rejects undersized
1119        // buffers before any write happens, so the call errors out.
1120        let key1 = PKey::generate_x25519().unwrap();
1121        let key2 = PKey::generate_x25519().unwrap();
1122
1123        let mut ctx = PkeyCtx::new(&key1).unwrap();
1124        ctx.derive_init().unwrap();
1125        ctx.derive_set_peer(&key2).unwrap();
1126
1127        let mut buf = [0u8; 4];
1128        let result = ctx.derive(Some(&mut buf));
1129        #[cfg(any(all(ossl110, not(ossl300)), libressl))]
1130        assert_eq!(result.unwrap(), 4);
1131        #[cfg(all(ossl300, not(libressl)))]
1132        assert!(result.is_err());
1133    }
1134
1135    #[test]
1136    #[cfg(not(any(boringssl, awslc)))]
1137    fn cmac_keygen() {
1138        let mut ctx = PkeyCtx::new_id(Id::CMAC).unwrap();
1139        ctx.keygen_init().unwrap();
1140        ctx.set_keygen_cipher(Cipher::aes_128_cbc()).unwrap();
1141        ctx.set_keygen_mac_key(&hex::decode("9294727a3638bb1c13f48ef8158bfc9d").unwrap())
1142            .unwrap();
1143        ctx.keygen().unwrap();
1144    }
1145
1146    #[test]
1147    #[cfg(not(any(boringssl, awslc_fips)))]
1148    fn dh_paramgen() {
1149        let mut ctx = PkeyCtx::new_id(Id::DH).unwrap();
1150        ctx.paramgen_init().unwrap();
1151        ctx.set_dh_paramgen_prime_len(512).unwrap();
1152        ctx.set_dh_paramgen_generator(2).unwrap();
1153        let params = ctx.paramgen().unwrap();
1154
1155        assert_eq!(params.size(), 64);
1156    }
1157
1158    #[test]
1159    #[cfg(not(boringssl))]
1160    fn dsa_paramgen() {
1161        let mut ctx = PkeyCtx::new_id(Id::DSA).unwrap();
1162        ctx.paramgen_init().unwrap();
1163        ctx.set_dsa_paramgen_bits(2048).unwrap();
1164        let params = ctx.paramgen().unwrap();
1165
1166        let size = {
1167            cfg_if! {
1168                if #[cfg(awslc)] {
1169                    72
1170                } else if #[cfg(libressl)] {
1171                    48
1172                } else {
1173                    64
1174                }
1175            }
1176        };
1177        assert_eq!(params.size(), size);
1178    }
1179
1180    #[test]
1181    fn ec_keygen() {
1182        let mut ctx = PkeyCtx::new_id(Id::EC).unwrap();
1183        ctx.paramgen_init().unwrap();
1184        ctx.set_ec_paramgen_curve_nid(Nid::X9_62_PRIME256V1)
1185            .unwrap();
1186        let params = ctx.paramgen().unwrap();
1187
1188        assert_eq!(params.size(), 72);
1189    }
1190
1191    #[test]
1192    fn rsa_keygen() {
1193        let pubexp = BigNum::from_u32(65537).unwrap();
1194        let mut ctx = PkeyCtx::new_id(Id::RSA).unwrap();
1195        ctx.keygen_init().unwrap();
1196        ctx.set_rsa_keygen_pubexp(&pubexp).unwrap();
1197        ctx.set_rsa_keygen_bits(2048).unwrap();
1198        let key = ctx.keygen().unwrap();
1199
1200        assert_eq!(key.bits(), 2048);
1201    }
1202
1203    #[test]
1204    #[cfg(any(ossl110, boringssl, libressl360, awslc))]
1205    fn hkdf() {
1206        let mut ctx = PkeyCtx::new_id(Id::HKDF).unwrap();
1207        ctx.derive_init().unwrap();
1208        ctx.set_hkdf_md(Md::sha256()).unwrap();
1209        ctx.set_hkdf_key(&hex::decode("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b").unwrap())
1210            .unwrap();
1211        ctx.set_hkdf_salt(&hex::decode("000102030405060708090a0b0c").unwrap())
1212            .unwrap();
1213        ctx.add_hkdf_info(&hex::decode("f0f1f2f3f4f5f6f7f8f9").unwrap())
1214            .unwrap();
1215        let mut out = [0; 42];
1216        ctx.derive(Some(&mut out)).unwrap();
1217
1218        assert_eq!(
1219            &out[..],
1220            hex::decode("3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865")
1221                .unwrap()
1222        );
1223    }
1224
1225    #[test]
1226    #[cfg(any(ossl111, libressl360))]
1227    fn hkdf_expand() {
1228        let mut ctx = PkeyCtx::new_id(Id::HKDF).unwrap();
1229        ctx.derive_init().unwrap();
1230        ctx.set_hkdf_mode(HkdfMode::EXPAND_ONLY).unwrap();
1231        ctx.set_hkdf_md(Md::sha256()).unwrap();
1232        ctx.set_hkdf_key(
1233            &hex::decode("077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5")
1234                .unwrap(),
1235        )
1236        .unwrap();
1237        ctx.add_hkdf_info(&hex::decode("f0f1f2f3f4f5f6f7f8f9").unwrap())
1238            .unwrap();
1239        let mut out = [0; 42];
1240        ctx.derive(Some(&mut out)).unwrap();
1241
1242        assert_eq!(
1243            &out[..],
1244            hex::decode("3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865")
1245                .unwrap()
1246        );
1247    }
1248
1249    #[test]
1250    #[cfg(any(ossl111, libressl360))]
1251    fn hkdf_extract() {
1252        let mut ctx = PkeyCtx::new_id(Id::HKDF).unwrap();
1253        ctx.derive_init().unwrap();
1254        ctx.set_hkdf_mode(HkdfMode::EXTRACT_ONLY).unwrap();
1255        ctx.set_hkdf_md(Md::sha256()).unwrap();
1256        ctx.set_hkdf_key(&hex::decode("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b").unwrap())
1257            .unwrap();
1258        ctx.set_hkdf_salt(&hex::decode("000102030405060708090a0b0c").unwrap())
1259            .unwrap();
1260        let mut out = vec![];
1261        ctx.derive_to_vec(&mut out).unwrap();
1262
1263        assert_eq!(
1264            &out[..],
1265            hex::decode("077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5")
1266                .unwrap()
1267        );
1268    }
1269
1270    #[test]
1271    fn verify_fail() {
1272        let key1 = Rsa::generate(4096).unwrap();
1273        let key1 = PKey::from_rsa(key1).unwrap();
1274
1275        let data = b"Some Crypto Text";
1276
1277        let mut ctx = PkeyCtx::new(&key1).unwrap();
1278        ctx.sign_init().unwrap();
1279        let mut signature = vec![];
1280        ctx.sign_to_vec(data, &mut signature).unwrap();
1281
1282        let bad_data = b"Some Crypto text";
1283
1284        ctx.verify_init().unwrap();
1285        let valid = ctx.verify(bad_data, &signature);
1286        assert!(matches!(valid, Ok(false) | Err(_)));
1287        assert!(ErrorStack::get().errors().is_empty());
1288    }
1289
1290    #[test]
1291    fn verify_fail_ec() {
1292        let key1 =
1293            EcKey::generate(&EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap()).unwrap();
1294        let key1 = PKey::from_ec_key(key1).unwrap();
1295
1296        let data = b"Some Crypto Text";
1297        let mut ctx = PkeyCtx::new(&key1).unwrap();
1298        ctx.verify_init().unwrap();
1299        assert!(matches!(ctx.verify(data, &[0; 64]), Ok(false) | Err(_)));
1300        assert!(ErrorStack::get().errors().is_empty());
1301    }
1302
1303    #[test]
1304    fn test_verify_recover() {
1305        let key = Rsa::generate(2048).unwrap();
1306        let key = PKey::from_rsa(key).unwrap();
1307
1308        let digest = [
1309            0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
1310            24, 25, 26, 27, 28, 29, 30, 31,
1311        ];
1312
1313        let mut ctx = PkeyCtx::new(&key).unwrap();
1314        ctx.sign_init().unwrap();
1315        ctx.set_rsa_padding(Padding::PKCS1).unwrap();
1316        ctx.set_signature_md(Md::sha256()).unwrap();
1317        let mut signature = vec![];
1318        ctx.sign_to_vec(&digest, &mut signature).unwrap();
1319
1320        // Attempt recovery of just the digest.
1321        let mut ctx = PkeyCtx::new(&key).unwrap();
1322        ctx.verify_recover_init().unwrap();
1323        ctx.set_rsa_padding(Padding::PKCS1).unwrap();
1324        ctx.set_signature_md(Md::sha256()).unwrap();
1325        let length = ctx.verify_recover(&signature, None).unwrap();
1326        let mut result_buf = vec![0; length];
1327        let length = ctx
1328            .verify_recover(&signature, Some(&mut result_buf))
1329            .unwrap();
1330        assert_eq!(length, digest.len());
1331        // result_buf contains the digest
1332        assert_eq!(result_buf[..length], digest);
1333
1334        // Attempt recovery of the entire DigestInfo
1335        let mut ctx = PkeyCtx::new(&key).unwrap();
1336        ctx.verify_recover_init().unwrap();
1337        ctx.set_rsa_padding(Padding::PKCS1).unwrap();
1338        let length = ctx.verify_recover(&signature, None).unwrap();
1339        let mut result_buf = vec![0; length];
1340        let length = ctx
1341            .verify_recover(&signature, Some(&mut result_buf))
1342            .unwrap();
1343        // 32-bytes of SHA256 digest + the ASN.1 DigestInfo structure == 51 bytes
1344        assert_eq!(length, 51);
1345        // The digest is the end of the DigestInfo structure.
1346        assert_eq!(result_buf[length - digest.len()..length], digest);
1347    }
1348
1349    #[test]
1350    #[cfg(ossl320)]
1351    fn set_nonce_type() {
1352        let key1 =
1353            EcKey::generate(&EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap()).unwrap();
1354        let key1 = PKey::from_ec_key(key1).unwrap();
1355
1356        let mut ctx = PkeyCtx::new(&key1).unwrap();
1357        ctx.sign_init().unwrap();
1358        ctx.set_nonce_type(NonceType::DETERMINISTIC_K).unwrap();
1359        let nonce_type = ctx.nonce_type().unwrap();
1360        assert_eq!(nonce_type, NonceType::DETERMINISTIC_K);
1361        assert!(ErrorStack::get().errors().is_empty());
1362    }
1363
1364    // Test vector from
1365    // https://github.com/openssl/openssl/blob/openssl-3.2.0/test/recipes/30-test_evp_data/evppkey_ecdsa_rfc6979.txt
1366    #[test]
1367    #[cfg(ossl320)]
1368    fn ecdsa_deterministic_signature() {
1369        let private_key_pem = "-----BEGIN PRIVATE KEY-----
1370MEECAQAwEwYHKoZIzj0CAQYIKoZIzj0DAQcEJzAlAgEBBCDJr6nYRbp1FmtcIVdnsdaTTlDD2zbo
1371mxJ7imIrEg9nIQ==
1372-----END PRIVATE KEY-----";
1373
1374        let key1 = EcKey::private_key_from_pem(private_key_pem.as_bytes()).unwrap();
1375        let key1 = PKey::from_ec_key(key1).unwrap();
1376        let input = "sample";
1377        let expected_output = hex::decode("3046022100EFD48B2AACB6A8FD1140DD9CD45E81D69D2C877B56AAF991C34D0EA84EAF3716022100F7CB1C942D657C41D436C7A1B6E29F65F3E900DBB9AFF4064DC4AB2F843ACDA8").unwrap();
1378
1379        let hashed_input = hash(MessageDigest::sha256(), input.as_bytes()).unwrap();
1380        let mut ctx = PkeyCtx::new(&key1).unwrap();
1381        ctx.sign_init().unwrap();
1382        ctx.set_signature_md(Md::sha256()).unwrap();
1383        ctx.set_nonce_type(NonceType::DETERMINISTIC_K).unwrap();
1384
1385        let mut output = vec![];
1386        ctx.sign_to_vec(&hashed_input, &mut output).unwrap();
1387        assert_eq!(output, expected_output);
1388        assert!(ErrorStack::get().errors().is_empty());
1389    }
1390}