openssl/
pkey_ctx.rs

1//! The asymmetric encryption context.
2//!
3//! # Examples
4//!
5//! Encrypt data with RSA
6//!
7//! ```
8//! use openssl::rsa::Rsa;
9//! use openssl::pkey::PKey;
10//! use openssl::pkey_ctx::PkeyCtx;
11//!
12//! let key = Rsa::generate(4096).unwrap();
13//! let key = PKey::from_rsa(key).unwrap();
14//!
15//! let mut ctx = PkeyCtx::new(&key).unwrap();
16//! ctx.encrypt_init().unwrap();
17//!
18//! let data = b"Some Crypto Text";
19//! let mut ciphertext = vec![];
20//! ctx.encrypt_to_vec(data, &mut ciphertext).unwrap();
21//! ```
22
23#![cfg_attr(
24    not(any(boringssl, awslc)),
25    doc = r#"\
26Generate a CMAC key
27
28```
29use openssl::pkey_ctx::PkeyCtx;
30use openssl::pkey::Id;
31use openssl::cipher::Cipher;
32
33let mut ctx = PkeyCtx::new_id(Id::CMAC).unwrap();
34ctx.keygen_init().unwrap();
35ctx.set_keygen_cipher(Cipher::aes_128_cbc()).unwrap();
36ctx.set_keygen_mac_key(b"0123456789abcdef").unwrap();
37let cmac_key = ctx.keygen().unwrap();
38```"#
39)]
40
41//!
42//! Sign and verify data with RSA
43//!
44//! ```
45//! use openssl::pkey_ctx::PkeyCtx;
46//! use openssl::pkey::PKey;
47//! use openssl::rsa::Rsa;
48//!
49//! // Generate a random RSA key.
50//! let key = Rsa::generate(4096).unwrap();
51//! let key = PKey::from_rsa(key).unwrap();
52//!
53//! let text = b"Some Crypto Text";
54//!
55//! // Create the signature.
56//! let mut ctx = PkeyCtx::new(&key).unwrap();
57//! ctx.sign_init().unwrap();
58//! let mut signature = vec![];
59//! ctx.sign_to_vec(text, &mut signature).unwrap();
60//!
61//! // Verify the signature.
62//! let mut ctx = PkeyCtx::new(&key).unwrap();
63//! ctx.verify_init().unwrap();
64//! let valid = ctx.verify(text, &signature).unwrap();
65//! assert!(valid);
66//! ```
67#[cfg(not(any(boringssl, awslc)))]
68use crate::cipher::CipherRef;
69use crate::error::ErrorStack;
70use crate::md::MdRef;
71use crate::pkey::{HasPrivate, HasPublic, Id, PKey, PKeyRef, Private};
72use crate::rsa::Padding;
73use crate::sign::RsaPssSaltlen;
74use crate::{cvt, cvt_p};
75use foreign_types::{ForeignType, ForeignTypeRef};
76#[cfg(not(any(boringssl, awslc)))]
77use libc::c_int;
78#[cfg(ossl320)]
79use libc::c_uint;
80use openssl_macros::corresponds;
81use std::convert::TryFrom;
82#[cfg(ossl320)]
83use std::ffi::CStr;
84use std::ptr;
85
86/// HKDF modes of operation.
87#[cfg(any(ossl111, libressl360))]
88pub struct HkdfMode(c_int);
89
90#[cfg(any(ossl111, libressl360))]
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    /// Sets which algorithm was used to compute the digest used in a
424    /// signature. With RSA signatures this causes the signature to be wrapped
425    /// in a `DigestInfo` structure. This is almost always what you want with
426    /// RSA signatures.
427    #[corresponds(EVP_PKEY_CTX_set_signature_md)]
428    #[inline]
429    pub fn set_signature_md(&self, md: &MdRef) -> Result<(), ErrorStack> {
430        unsafe {
431            cvt(ffi::EVP_PKEY_CTX_set_signature_md(
432                self.as_ptr(),
433                md.as_ptr(),
434            ))?;
435        }
436        Ok(())
437    }
438
439    /// Returns the RSA padding mode in use.
440    ///
441    /// This is only useful for RSA keys.
442    #[corresponds(EVP_PKEY_CTX_get_rsa_padding)]
443    #[inline]
444    pub fn rsa_padding(&self) -> Result<Padding, ErrorStack> {
445        let mut pad = 0;
446        unsafe {
447            cvt(ffi::EVP_PKEY_CTX_get_rsa_padding(self.as_ptr(), &mut pad))?;
448        }
449
450        Ok(Padding::from_raw(pad))
451    }
452
453    /// Sets the RSA padding mode.
454    ///
455    /// This is only useful for RSA keys.
456    #[corresponds(EVP_PKEY_CTX_set_rsa_padding)]
457    #[inline]
458    pub fn set_rsa_padding(&mut self, padding: Padding) -> Result<(), ErrorStack> {
459        unsafe {
460            cvt(ffi::EVP_PKEY_CTX_set_rsa_padding(
461                self.as_ptr(),
462                padding.as_raw(),
463            ))?;
464        }
465
466        Ok(())
467    }
468
469    /// Sets the RSA PSS salt length.
470    ///
471    /// This is only useful for RSA keys.
472    #[corresponds(EVP_PKEY_CTX_set_rsa_pss_saltlen)]
473    #[inline]
474    pub fn set_rsa_pss_saltlen(&mut self, len: RsaPssSaltlen) -> Result<(), ErrorStack> {
475        unsafe {
476            cvt(ffi::EVP_PKEY_CTX_set_rsa_pss_saltlen(
477                self.as_ptr(),
478                len.as_raw(),
479            ))
480            .map(|_| ())
481        }
482    }
483
484    /// Sets the RSA MGF1 algorithm.
485    ///
486    /// This is only useful for RSA keys.
487    #[corresponds(EVP_PKEY_CTX_set_rsa_mgf1_md)]
488    #[inline]
489    pub fn set_rsa_mgf1_md(&mut self, md: &MdRef) -> Result<(), ErrorStack> {
490        unsafe {
491            cvt(ffi::EVP_PKEY_CTX_set_rsa_mgf1_md(
492                self.as_ptr(),
493                md.as_ptr(),
494            ))?;
495        }
496
497        Ok(())
498    }
499
500    /// Sets the RSA OAEP algorithm.
501    ///
502    /// This is only useful for RSA keys.
503    #[corresponds(EVP_PKEY_CTX_set_rsa_oaep_md)]
504    #[cfg(any(ossl102, libressl310, boringssl, awslc))]
505    #[inline]
506    pub fn set_rsa_oaep_md(&mut self, md: &MdRef) -> Result<(), ErrorStack> {
507        unsafe {
508            cvt(ffi::EVP_PKEY_CTX_set_rsa_oaep_md(
509                self.as_ptr(),
510                md.as_ptr() as *mut _,
511            ))?;
512        }
513
514        Ok(())
515    }
516
517    /// Sets the RSA OAEP label.
518    ///
519    /// This is only useful for RSA keys.
520    #[corresponds(EVP_PKEY_CTX_set0_rsa_oaep_label)]
521    #[cfg(any(ossl102, libressl310, boringssl, awslc))]
522    pub fn set_rsa_oaep_label(&mut self, label: &[u8]) -> Result<(), ErrorStack> {
523        use crate::LenType;
524        let len = LenType::try_from(label.len()).unwrap();
525
526        unsafe {
527            let p = ffi::OPENSSL_malloc(label.len() as _);
528            ptr::copy_nonoverlapping(label.as_ptr(), p as *mut _, label.len());
529
530            let r = cvt(ffi::EVP_PKEY_CTX_set0_rsa_oaep_label(
531                self.as_ptr(),
532                p as *mut _,
533                len,
534            ));
535            if r.is_err() {
536                ffi::OPENSSL_free(p);
537            }
538            r?;
539        }
540
541        Ok(())
542    }
543
544    /// Sets the cipher used during key generation.
545    #[cfg(not(any(boringssl, awslc)))]
546    #[corresponds(EVP_PKEY_CTX_ctrl)]
547    #[inline]
548    pub fn set_keygen_cipher(&mut self, cipher: &CipherRef) -> Result<(), ErrorStack> {
549        unsafe {
550            cvt(ffi::EVP_PKEY_CTX_ctrl(
551                self.as_ptr(),
552                -1,
553                ffi::EVP_PKEY_OP_KEYGEN,
554                ffi::EVP_PKEY_CTRL_CIPHER,
555                0,
556                cipher.as_ptr() as *mut _,
557            ))?;
558        }
559
560        Ok(())
561    }
562
563    /// Sets the key MAC key used during key generation.
564    #[cfg(not(any(boringssl, awslc)))]
565    #[corresponds(EVP_PKEY_CTX_ctrl)]
566    #[inline]
567    pub fn set_keygen_mac_key(&mut self, key: &[u8]) -> Result<(), ErrorStack> {
568        let len = c_int::try_from(key.len()).unwrap();
569
570        unsafe {
571            cvt(ffi::EVP_PKEY_CTX_ctrl(
572                self.as_ptr(),
573                -1,
574                ffi::EVP_PKEY_OP_KEYGEN,
575                ffi::EVP_PKEY_CTRL_SET_MAC_KEY,
576                len,
577                key.as_ptr() as *mut _,
578            ))?;
579        }
580
581        Ok(())
582    }
583
584    /// Sets the digest used for HKDF derivation.
585    ///
586    /// Requires OpenSSL 1.1.0 or newer.
587    #[corresponds(EVP_PKEY_CTX_set_hkdf_md)]
588    #[cfg(any(ossl110, boringssl, libressl360, awslc))]
589    #[inline]
590    pub fn set_hkdf_md(&mut self, digest: &MdRef) -> Result<(), ErrorStack> {
591        unsafe {
592            cvt(ffi::EVP_PKEY_CTX_set_hkdf_md(
593                self.as_ptr(),
594                digest.as_ptr(),
595            ))?;
596        }
597
598        Ok(())
599    }
600
601    /// Sets the HKDF mode of operation.
602    ///
603    /// Defaults to [`HkdfMode::EXTRACT_THEN_EXPAND`].
604    ///
605    /// WARNING: Although this API calls it a "mode", HKDF-Extract and HKDF-Expand are distinct
606    /// operations with distinct inputs and distinct kinds of keys. Callers should not pass input
607    /// secrets for one operation into the other.
608    ///
609    /// Requires OpenSSL 1.1.1 or newer.
610    #[corresponds(EVP_PKEY_CTX_set_hkdf_mode)]
611    #[cfg(any(ossl111, libressl360))]
612    #[inline]
613    pub fn set_hkdf_mode(&mut self, mode: HkdfMode) -> Result<(), ErrorStack> {
614        unsafe {
615            cvt(ffi::EVP_PKEY_CTX_set_hkdf_mode(self.as_ptr(), mode.0))?;
616        }
617
618        Ok(())
619    }
620
621    /// Sets the input material for HKDF generation as the "key".
622    ///
623    /// Which input is the key depends on the "mode" (see [`set_hkdf_mode`][Self::set_hkdf_mode]).
624    /// If [`HkdfMode::EXTRACT_THEN_EXPAND`] or [`HkdfMode::EXTRACT_ONLY`], this function specifies
625    /// the input keying material (IKM) for HKDF-Extract. If [`HkdfMode::EXPAND_ONLY`], it instead
626    /// specifies the pseudorandom key (PRK) for HKDF-Expand.
627    ///
628    /// Requires OpenSSL 1.1.0 or newer.
629    #[corresponds(EVP_PKEY_CTX_set1_hkdf_key)]
630    #[cfg(any(ossl110, boringssl, libressl360, awslc))]
631    #[inline]
632    pub fn set_hkdf_key(&mut self, key: &[u8]) -> Result<(), ErrorStack> {
633        #[cfg(not(any(boringssl, awslc)))]
634        let len = c_int::try_from(key.len()).unwrap();
635        #[cfg(any(boringssl, awslc))]
636        let len = key.len();
637
638        unsafe {
639            cvt(ffi::EVP_PKEY_CTX_set1_hkdf_key(
640                self.as_ptr(),
641                key.as_ptr(),
642                len,
643            ))?;
644        }
645
646        Ok(())
647    }
648
649    /// Sets the salt value for HKDF generation.
650    ///
651    /// If performing HKDF-Expand only, this parameter is ignored.
652    ///
653    /// Requires OpenSSL 1.1.0 or newer.
654    #[corresponds(EVP_PKEY_CTX_set1_hkdf_salt)]
655    #[cfg(any(ossl110, boringssl, libressl360, awslc))]
656    #[inline]
657    pub fn set_hkdf_salt(&mut self, salt: &[u8]) -> Result<(), ErrorStack> {
658        #[cfg(not(any(boringssl, awslc)))]
659        let len = c_int::try_from(salt.len()).unwrap();
660        #[cfg(any(boringssl, awslc))]
661        let len = salt.len();
662
663        unsafe {
664            cvt(ffi::EVP_PKEY_CTX_set1_hkdf_salt(
665                self.as_ptr(),
666                salt.as_ptr(),
667                len,
668            ))?;
669        }
670
671        Ok(())
672    }
673
674    /// Appends info bytes for HKDF generation.
675    ///
676    /// If performing HKDF-Extract only, this parameter is ignored.
677    ///
678    /// Requires OpenSSL 1.1.0 or newer.
679    #[corresponds(EVP_PKEY_CTX_add1_hkdf_info)]
680    #[cfg(any(ossl110, boringssl, libressl360, awslc))]
681    #[inline]
682    pub fn add_hkdf_info(&mut self, info: &[u8]) -> Result<(), ErrorStack> {
683        #[cfg(not(any(boringssl, awslc)))]
684        let len = c_int::try_from(info.len()).unwrap();
685        #[cfg(any(boringssl, awslc))]
686        let len = info.len();
687
688        unsafe {
689            cvt(ffi::EVP_PKEY_CTX_add1_hkdf_info(
690                self.as_ptr(),
691                info.as_ptr(),
692                len,
693            ))?;
694        }
695
696        Ok(())
697    }
698
699    /// Derives a shared secret between two keys.
700    ///
701    /// If `buf` is set to `None`, an upper bound on the number of bytes required for the buffer will be returned.
702    #[corresponds(EVP_PKEY_derive)]
703    pub fn derive(&mut self, buf: Option<&mut [u8]>) -> Result<usize, ErrorStack> {
704        let mut len = buf.as_ref().map_or(0, |b| b.len());
705        unsafe {
706            cvt(ffi::EVP_PKEY_derive(
707                self.as_ptr(),
708                buf.map_or(ptr::null_mut(), |b| b.as_mut_ptr()),
709                &mut len,
710            ))?;
711        }
712
713        Ok(len)
714    }
715
716    /// Like [`Self::derive`] but appends the secret to a [`Vec`].
717    pub fn derive_to_vec(&mut self, buf: &mut Vec<u8>) -> Result<usize, ErrorStack> {
718        let base = buf.len();
719        let len = self.derive(None)?;
720        buf.resize(base + len, 0);
721        let len = self.derive(Some(&mut buf[base..]))?;
722        buf.truncate(base + len);
723        Ok(len)
724    }
725
726    /// Generates a new public/private keypair.
727    #[corresponds(EVP_PKEY_keygen)]
728    #[inline]
729    pub fn keygen(&mut self) -> Result<PKey<Private>, ErrorStack> {
730        unsafe {
731            let mut key = ptr::null_mut();
732            cvt(ffi::EVP_PKEY_keygen(self.as_ptr(), &mut key))?;
733            Ok(PKey::from_ptr(key))
734        }
735    }
736
737    /// Sets the nonce type for a private key context.
738    ///
739    /// The nonce for DSA and ECDSA can be either random (the default) or deterministic (as defined by RFC 6979).
740    ///
741    /// This is only useful for DSA and ECDSA.
742    /// Requires OpenSSL 3.2.0 or newer.
743    #[cfg(ossl320)]
744    #[corresponds(EVP_PKEY_CTX_set_params)]
745    pub fn set_nonce_type(&mut self, nonce_type: NonceType) -> Result<(), ErrorStack> {
746        let nonce_field_name = CStr::from_bytes_with_nul(b"nonce-type\0").unwrap();
747        let mut nonce_type = nonce_type.0;
748        unsafe {
749            let param_nonce =
750                ffi::OSSL_PARAM_construct_uint(nonce_field_name.as_ptr(), &mut nonce_type);
751            let param_end = ffi::OSSL_PARAM_construct_end();
752
753            let params = [param_nonce, param_end];
754            cvt(ffi::EVP_PKEY_CTX_set_params(self.as_ptr(), params.as_ptr()))?;
755        }
756        Ok(())
757    }
758
759    /// Gets the nonce type for a private key context.
760    ///
761    /// The nonce for DSA and ECDSA can be either random (the default) or deterministic (as defined by RFC 6979).
762    ///
763    /// This is only useful for DSA and ECDSA.
764    /// Requires OpenSSL 3.2.0 or newer.
765    #[cfg(ossl320)]
766    #[corresponds(EVP_PKEY_CTX_get_params)]
767    pub fn nonce_type(&mut self) -> Result<NonceType, ErrorStack> {
768        let nonce_field_name = CStr::from_bytes_with_nul(b"nonce-type\0").unwrap();
769        let mut nonce_type: c_uint = 0;
770        unsafe {
771            let param_nonce =
772                ffi::OSSL_PARAM_construct_uint(nonce_field_name.as_ptr(), &mut nonce_type);
773            let param_end = ffi::OSSL_PARAM_construct_end();
774
775            let mut params = [param_nonce, param_end];
776            cvt(ffi::EVP_PKEY_CTX_get_params(
777                self.as_ptr(),
778                params.as_mut_ptr(),
779            ))?;
780        }
781        Ok(NonceType(nonce_type))
782    }
783}
784
785#[cfg(test)]
786mod test {
787    use super::*;
788    #[cfg(not(any(boringssl, awslc)))]
789    use crate::cipher::Cipher;
790    use crate::ec::{EcGroup, EcKey};
791    use crate::hash::{hash, MessageDigest};
792    use crate::md::Md;
793    use crate::nid::Nid;
794    use crate::pkey::PKey;
795    use crate::rsa::Rsa;
796    use crate::sign::Verifier;
797
798    #[test]
799    fn rsa() {
800        let key = include_bytes!("../test/rsa.pem");
801        let rsa = Rsa::private_key_from_pem(key).unwrap();
802        let pkey = PKey::from_rsa(rsa).unwrap();
803
804        let mut ctx = PkeyCtx::new(&pkey).unwrap();
805        ctx.encrypt_init().unwrap();
806        ctx.set_rsa_padding(Padding::PKCS1).unwrap();
807
808        let pt = "hello world".as_bytes();
809        let mut ct = vec![];
810        ctx.encrypt_to_vec(pt, &mut ct).unwrap();
811
812        ctx.decrypt_init().unwrap();
813        ctx.set_rsa_padding(Padding::PKCS1).unwrap();
814
815        let mut out = vec![];
816        ctx.decrypt_to_vec(&ct, &mut out).unwrap();
817
818        assert_eq!(pt, out);
819    }
820
821    #[test]
822    #[cfg(any(ossl102, libressl310, boringssl, awslc))]
823    fn rsa_oaep() {
824        let key = include_bytes!("../test/rsa.pem");
825        let rsa = Rsa::private_key_from_pem(key).unwrap();
826        let pkey = PKey::from_rsa(rsa).unwrap();
827
828        let mut ctx = PkeyCtx::new(&pkey).unwrap();
829        ctx.encrypt_init().unwrap();
830        ctx.set_rsa_padding(Padding::PKCS1_OAEP).unwrap();
831        ctx.set_rsa_oaep_md(Md::sha256()).unwrap();
832        ctx.set_rsa_mgf1_md(Md::sha256()).unwrap();
833
834        let pt = "hello world".as_bytes();
835        let mut ct = vec![];
836        ctx.encrypt_to_vec(pt, &mut ct).unwrap();
837
838        ctx.decrypt_init().unwrap();
839        ctx.set_rsa_padding(Padding::PKCS1_OAEP).unwrap();
840        ctx.set_rsa_oaep_md(Md::sha256()).unwrap();
841        ctx.set_rsa_mgf1_md(Md::sha256()).unwrap();
842
843        let mut out = vec![];
844        ctx.decrypt_to_vec(&ct, &mut out).unwrap();
845
846        assert_eq!(pt, out);
847    }
848
849    #[test]
850    fn rsa_sign() {
851        let key = include_bytes!("../test/rsa.pem");
852        let rsa = Rsa::private_key_from_pem(key).unwrap();
853        let pkey = PKey::from_rsa(rsa).unwrap();
854
855        let mut ctx = PkeyCtx::new(&pkey).unwrap();
856        ctx.sign_init().unwrap();
857        ctx.set_rsa_padding(Padding::PKCS1).unwrap();
858        ctx.set_signature_md(Md::sha384()).unwrap();
859
860        let msg = b"hello world";
861        let digest = hash(MessageDigest::sha384(), msg).unwrap();
862        let mut signature = vec![];
863        ctx.sign_to_vec(&digest, &mut signature).unwrap();
864
865        let mut verifier = Verifier::new(MessageDigest::sha384(), &pkey).unwrap();
866        verifier.update(msg).unwrap();
867        assert!(matches!(verifier.verify(&signature), Ok(true)));
868    }
869
870    #[test]
871    fn rsa_sign_pss() {
872        let key = include_bytes!("../test/rsa.pem");
873        let rsa = Rsa::private_key_from_pem(key).unwrap();
874        let pkey = PKey::from_rsa(rsa).unwrap();
875
876        let mut ctx = PkeyCtx::new(&pkey).unwrap();
877        ctx.sign_init().unwrap();
878        ctx.set_rsa_padding(Padding::PKCS1_PSS).unwrap();
879        ctx.set_signature_md(Md::sha384()).unwrap();
880        ctx.set_rsa_pss_saltlen(RsaPssSaltlen::custom(14)).unwrap();
881
882        let msg = b"hello world";
883        let digest = hash(MessageDigest::sha384(), msg).unwrap();
884        let mut signature = vec![];
885        ctx.sign_to_vec(&digest, &mut signature).unwrap();
886
887        let mut verifier = Verifier::new(MessageDigest::sha384(), &pkey).unwrap();
888        verifier.set_rsa_padding(Padding::PKCS1_PSS).unwrap();
889        verifier
890            .set_rsa_pss_saltlen(RsaPssSaltlen::custom(14))
891            .unwrap();
892        verifier.update(msg).unwrap();
893        assert!(matches!(verifier.verify(&signature), Ok(true)));
894    }
895
896    #[test]
897    fn derive() {
898        let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
899        let key1 = EcKey::generate(&group).unwrap();
900        let key1 = PKey::from_ec_key(key1).unwrap();
901        let key2 = EcKey::generate(&group).unwrap();
902        let key2 = PKey::from_ec_key(key2).unwrap();
903
904        let mut ctx = PkeyCtx::new(&key1).unwrap();
905        ctx.derive_init().unwrap();
906        ctx.derive_set_peer(&key2).unwrap();
907
908        let mut buf = vec![];
909        ctx.derive_to_vec(&mut buf).unwrap();
910    }
911
912    #[test]
913    #[cfg(not(any(boringssl, awslc)))]
914    fn cmac_keygen() {
915        let mut ctx = PkeyCtx::new_id(Id::CMAC).unwrap();
916        ctx.keygen_init().unwrap();
917        ctx.set_keygen_cipher(Cipher::aes_128_cbc()).unwrap();
918        ctx.set_keygen_mac_key(&hex::decode("9294727a3638bb1c13f48ef8158bfc9d").unwrap())
919            .unwrap();
920        ctx.keygen().unwrap();
921    }
922
923    #[test]
924    #[cfg(any(ossl110, boringssl, libressl360, awslc))]
925    fn hkdf() {
926        let mut ctx = PkeyCtx::new_id(Id::HKDF).unwrap();
927        ctx.derive_init().unwrap();
928        ctx.set_hkdf_md(Md::sha256()).unwrap();
929        ctx.set_hkdf_key(&hex::decode("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b").unwrap())
930            .unwrap();
931        ctx.set_hkdf_salt(&hex::decode("000102030405060708090a0b0c").unwrap())
932            .unwrap();
933        ctx.add_hkdf_info(&hex::decode("f0f1f2f3f4f5f6f7f8f9").unwrap())
934            .unwrap();
935        let mut out = [0; 42];
936        ctx.derive(Some(&mut out)).unwrap();
937
938        assert_eq!(
939            &out[..],
940            hex::decode("3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865")
941                .unwrap()
942        );
943    }
944
945    #[test]
946    #[cfg(any(ossl111, libressl360))]
947    fn hkdf_expand() {
948        let mut ctx = PkeyCtx::new_id(Id::HKDF).unwrap();
949        ctx.derive_init().unwrap();
950        ctx.set_hkdf_mode(HkdfMode::EXPAND_ONLY).unwrap();
951        ctx.set_hkdf_md(Md::sha256()).unwrap();
952        ctx.set_hkdf_key(
953            &hex::decode("077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5")
954                .unwrap(),
955        )
956        .unwrap();
957        ctx.add_hkdf_info(&hex::decode("f0f1f2f3f4f5f6f7f8f9").unwrap())
958            .unwrap();
959        let mut out = [0; 42];
960        ctx.derive(Some(&mut out)).unwrap();
961
962        assert_eq!(
963            &out[..],
964            hex::decode("3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865")
965                .unwrap()
966        );
967    }
968
969    #[test]
970    #[cfg(any(ossl111, libressl360))]
971    fn hkdf_extract() {
972        let mut ctx = PkeyCtx::new_id(Id::HKDF).unwrap();
973        ctx.derive_init().unwrap();
974        ctx.set_hkdf_mode(HkdfMode::EXTRACT_ONLY).unwrap();
975        ctx.set_hkdf_md(Md::sha256()).unwrap();
976        ctx.set_hkdf_key(&hex::decode("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b").unwrap())
977            .unwrap();
978        ctx.set_hkdf_salt(&hex::decode("000102030405060708090a0b0c").unwrap())
979            .unwrap();
980        let mut out = vec![];
981        ctx.derive_to_vec(&mut out).unwrap();
982
983        assert_eq!(
984            &out[..],
985            hex::decode("077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5")
986                .unwrap()
987        );
988    }
989
990    #[test]
991    fn verify_fail() {
992        let key1 = Rsa::generate(4096).unwrap();
993        let key1 = PKey::from_rsa(key1).unwrap();
994
995        let data = b"Some Crypto Text";
996
997        let mut ctx = PkeyCtx::new(&key1).unwrap();
998        ctx.sign_init().unwrap();
999        let mut signature = vec![];
1000        ctx.sign_to_vec(data, &mut signature).unwrap();
1001
1002        let bad_data = b"Some Crypto text";
1003
1004        ctx.verify_init().unwrap();
1005        let valid = ctx.verify(bad_data, &signature);
1006        assert!(matches!(valid, Ok(false) | Err(_)));
1007        assert!(ErrorStack::get().errors().is_empty());
1008    }
1009
1010    #[test]
1011    fn verify_fail_ec() {
1012        let key1 =
1013            EcKey::generate(&EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap()).unwrap();
1014        let key1 = PKey::from_ec_key(key1).unwrap();
1015
1016        let data = b"Some Crypto Text";
1017        let mut ctx = PkeyCtx::new(&key1).unwrap();
1018        ctx.verify_init().unwrap();
1019        assert!(matches!(ctx.verify(data, &[0; 64]), Ok(false) | Err(_)));
1020        assert!(ErrorStack::get().errors().is_empty());
1021    }
1022
1023    #[test]
1024    fn test_verify_recover() {
1025        let key = Rsa::generate(2048).unwrap();
1026        let key = PKey::from_rsa(key).unwrap();
1027
1028        let digest = [
1029            0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
1030            24, 25, 26, 27, 28, 29, 30, 31,
1031        ];
1032
1033        let mut ctx = PkeyCtx::new(&key).unwrap();
1034        ctx.sign_init().unwrap();
1035        ctx.set_rsa_padding(Padding::PKCS1).unwrap();
1036        ctx.set_signature_md(Md::sha256()).unwrap();
1037        let mut signature = vec![];
1038        ctx.sign_to_vec(&digest, &mut signature).unwrap();
1039
1040        // Attempt recovery of just the digest.
1041        let mut ctx = PkeyCtx::new(&key).unwrap();
1042        ctx.verify_recover_init().unwrap();
1043        ctx.set_rsa_padding(Padding::PKCS1).unwrap();
1044        ctx.set_signature_md(Md::sha256()).unwrap();
1045        let length = ctx.verify_recover(&signature, None).unwrap();
1046        let mut result_buf = vec![0; length];
1047        let length = ctx
1048            .verify_recover(&signature, Some(&mut result_buf))
1049            .unwrap();
1050        assert_eq!(length, digest.len());
1051        // result_buf contains the digest
1052        assert_eq!(result_buf[..length], digest);
1053
1054        // Attempt recovery of teh entire DigestInfo
1055        let mut ctx = PkeyCtx::new(&key).unwrap();
1056        ctx.verify_recover_init().unwrap();
1057        ctx.set_rsa_padding(Padding::PKCS1).unwrap();
1058        let length = ctx.verify_recover(&signature, None).unwrap();
1059        let mut result_buf = vec![0; length];
1060        let length = ctx
1061            .verify_recover(&signature, Some(&mut result_buf))
1062            .unwrap();
1063        // 32-bytes of SHA256 digest + the ASN.1 DigestInfo structure == 51 bytes
1064        assert_eq!(length, 51);
1065        // The digest is the end of the DigestInfo structure.
1066        assert_eq!(result_buf[length - digest.len()..length], digest);
1067    }
1068
1069    #[test]
1070    #[cfg(ossl320)]
1071    fn set_nonce_type() {
1072        let key1 =
1073            EcKey::generate(&EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap()).unwrap();
1074        let key1 = PKey::from_ec_key(key1).unwrap();
1075
1076        let mut ctx = PkeyCtx::new(&key1).unwrap();
1077        ctx.sign_init().unwrap();
1078        ctx.set_nonce_type(NonceType::DETERMINISTIC_K).unwrap();
1079        let nonce_type = ctx.nonce_type().unwrap();
1080        assert_eq!(nonce_type, NonceType::DETERMINISTIC_K);
1081        assert!(ErrorStack::get().errors().is_empty());
1082    }
1083
1084    // Test vector from
1085    // https://github.com/openssl/openssl/blob/openssl-3.2.0/test/recipes/30-test_evp_data/evppkey_ecdsa_rfc6979.txt
1086    #[test]
1087    #[cfg(ossl320)]
1088    fn ecdsa_deterministic_signature() {
1089        let private_key_pem = "-----BEGIN PRIVATE KEY-----
1090MEECAQAwEwYHKoZIzj0CAQYIKoZIzj0DAQcEJzAlAgEBBCDJr6nYRbp1FmtcIVdnsdaTTlDD2zbo
1091mxJ7imIrEg9nIQ==
1092-----END PRIVATE KEY-----";
1093
1094        let key1 = EcKey::private_key_from_pem(private_key_pem.as_bytes()).unwrap();
1095        let key1 = PKey::from_ec_key(key1).unwrap();
1096        let input = "sample";
1097        let expected_output = hex::decode("3044022061340C88C3AAEBEB4F6D667F672CA9759A6CCAA9FA8811313039EE4A35471D3202206D7F147DAC089441BB2E2FE8F7A3FA264B9C475098FDCF6E00D7C996E1B8B7EB").unwrap();
1098
1099        let hashed_input = hash(MessageDigest::sha1(), input.as_bytes()).unwrap();
1100        let mut ctx = PkeyCtx::new(&key1).unwrap();
1101        ctx.sign_init().unwrap();
1102        ctx.set_signature_md(Md::sha1()).unwrap();
1103        ctx.set_nonce_type(NonceType::DETERMINISTIC_K).unwrap();
1104
1105        let mut output = vec![];
1106        ctx.sign_to_vec(&hashed_input, &mut output).unwrap();
1107        assert_eq!(output, expected_output);
1108        assert!(ErrorStack::get().errors().is_empty());
1109    }
1110}