• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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(boringssl),
25     doc = r#"\
26 Generate a CMAC key
27 
28 ```
29 use openssl::pkey_ctx::PkeyCtx;
30 use openssl::pkey::Id;
31 use openssl::cipher::Cipher;
32 
33 let mut ctx = PkeyCtx::new_id(Id::CMAC).unwrap();
34 ctx.keygen_init().unwrap();
35 ctx.set_keygen_cipher(Cipher::aes_128_cbc()).unwrap();
36 ctx.set_keygen_mac_key(b"0123456789abcdef").unwrap();
37 let 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(boringssl))]
68 use crate::cipher::CipherRef;
69 use crate::error::ErrorStack;
70 use crate::md::MdRef;
71 use crate::pkey::{HasPrivate, HasPublic, Id, PKey, PKeyRef, Private};
72 use crate::rsa::Padding;
73 use crate::{cvt, cvt_n, cvt_p};
74 use foreign_types::{ForeignType, ForeignTypeRef};
75 #[cfg(not(boringssl))]
76 use libc::c_int;
77 use openssl_macros::corresponds;
78 use std::convert::TryFrom;
79 use std::ptr;
80 
81 /// HKDF modes of operation.
82 #[cfg(ossl111)]
83 pub struct HkdfMode(c_int);
84 
85 #[cfg(ossl111)]
86 impl HkdfMode {
87     /// This is the default mode. Calling [`derive`][PkeyCtxRef::derive] on a [`PkeyCtxRef`] set up
88     /// for HKDF will perform an extract followed by an expand operation in one go. The derived key
89     /// returned will be the result after the expand operation. The intermediate fixed-length
90     /// pseudorandom key K is not returned.
91     pub const EXTRACT_THEN_EXPAND: Self = HkdfMode(ffi::EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND);
92 
93     /// In this mode calling [`derive`][PkeyCtxRef::derive] will just perform the extract operation.
94     /// The value returned will be the intermediate fixed-length pseudorandom key K.
95     ///
96     /// The digest, key and salt values must be set before a key is derived or an error occurs.
97     pub const EXTRACT_ONLY: Self = HkdfMode(ffi::EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY);
98 
99     /// In this mode calling [`derive`][PkeyCtxRef::derive] will just perform the expand operation.
100     /// The input key should be set to the intermediate fixed-length pseudorandom key K returned
101     /// from a previous extract operation.
102     ///
103     /// The digest, key and info values must be set before a key is derived or an error occurs.
104     pub const EXPAND_ONLY: Self = HkdfMode(ffi::EVP_PKEY_HKDEF_MODE_EXPAND_ONLY);
105 }
106 
107 generic_foreign_type_and_impl_send_sync! {
108     type CType = ffi::EVP_PKEY_CTX;
109     fn drop = ffi::EVP_PKEY_CTX_free;
110 
111     /// A context object which can perform asymmetric cryptography operations.
112     pub struct PkeyCtx<T>;
113     /// A reference to a [`PkeyCtx`].
114     pub struct PkeyCtxRef<T>;
115 }
116 
117 impl<T> PkeyCtx<T> {
118     /// Creates a new pkey context using the provided key.
119     #[corresponds(EVP_PKEY_CTX_new)]
120     #[inline]
new(pkey: &PKeyRef<T>) -> Result<Self, ErrorStack>121     pub fn new(pkey: &PKeyRef<T>) -> Result<Self, ErrorStack> {
122         unsafe {
123             let ptr = cvt_p(ffi::EVP_PKEY_CTX_new(pkey.as_ptr(), ptr::null_mut()))?;
124             Ok(PkeyCtx::from_ptr(ptr))
125         }
126     }
127 }
128 
129 impl PkeyCtx<()> {
130     /// Creates a new pkey context for the specified algorithm ID.
131     #[corresponds(EVP_PKEY_new_id)]
132     #[inline]
new_id(id: Id) -> Result<Self, ErrorStack>133     pub fn new_id(id: Id) -> Result<Self, ErrorStack> {
134         unsafe {
135             let ptr = cvt_p(ffi::EVP_PKEY_CTX_new_id(id.as_raw(), ptr::null_mut()))?;
136             Ok(PkeyCtx::from_ptr(ptr))
137         }
138     }
139 }
140 
141 impl<T> PkeyCtxRef<T>
142 where
143     T: HasPublic,
144 {
145     /// Prepares the context for encryption using the public key.
146     #[corresponds(EVP_PKEY_encrypt_init)]
147     #[inline]
encrypt_init(&mut self) -> Result<(), ErrorStack>148     pub fn encrypt_init(&mut self) -> Result<(), ErrorStack> {
149         unsafe {
150             cvt(ffi::EVP_PKEY_encrypt_init(self.as_ptr()))?;
151         }
152 
153         Ok(())
154     }
155 
156     /// Prepares the context for signature verification using the public key.
157     #[corresponds(EVP_PKEY_verify_init)]
158     #[inline]
verify_init(&mut self) -> Result<(), ErrorStack>159     pub fn verify_init(&mut self) -> Result<(), ErrorStack> {
160         unsafe {
161             cvt(ffi::EVP_PKEY_verify_init(self.as_ptr()))?;
162         }
163 
164         Ok(())
165     }
166 
167     /// Encrypts data using the public key.
168     ///
169     /// If `to` is set to `None`, an upper bound on the number of bytes required for the output buffer will be
170     /// returned.
171     #[corresponds(EVP_PKEY_encrypt)]
172     #[inline]
encrypt(&mut self, from: &[u8], to: Option<&mut [u8]>) -> Result<usize, ErrorStack>173     pub fn encrypt(&mut self, from: &[u8], to: Option<&mut [u8]>) -> Result<usize, ErrorStack> {
174         let mut written = to.as_ref().map_or(0, |b| b.len());
175         unsafe {
176             cvt(ffi::EVP_PKEY_encrypt(
177                 self.as_ptr(),
178                 to.map_or(ptr::null_mut(), |b| b.as_mut_ptr()),
179                 &mut written,
180                 from.as_ptr(),
181                 from.len(),
182             ))?;
183         }
184 
185         Ok(written)
186     }
187 
188     /// Like [`Self::encrypt`] but appends ciphertext to a [`Vec`].
encrypt_to_vec(&mut self, from: &[u8], out: &mut Vec<u8>) -> Result<usize, ErrorStack>189     pub fn encrypt_to_vec(&mut self, from: &[u8], out: &mut Vec<u8>) -> Result<usize, ErrorStack> {
190         let base = out.len();
191         let len = self.encrypt(from, None)?;
192         out.resize(base + len, 0);
193         let len = self.encrypt(from, Some(&mut out[base..]))?;
194         out.truncate(base + len);
195         Ok(len)
196     }
197 
198     /// Verifies the signature of data using the public key.
199     ///
200     /// Returns `Ok(true)` if the signature is valid, `Ok(false)` if the signature is invalid, and `Err` if an error
201     /// occurred.
202     ///
203     /// # Note
204     ///
205     /// This verifies the signature of the *raw* data. It is more common to compute and verify the signature of the
206     /// cryptographic hash of an arbitrary amount of data. The [`MdCtx`](crate::md_ctx::MdCtx) type can be used to do
207     /// that.
208     #[corresponds(EVP_PKEY_verify)]
209     #[inline]
verify(&mut self, data: &[u8], sig: &[u8]) -> Result<bool, ErrorStack>210     pub fn verify(&mut self, data: &[u8], sig: &[u8]) -> Result<bool, ErrorStack> {
211         unsafe {
212             let r = cvt_n(ffi::EVP_PKEY_verify(
213                 self.as_ptr(),
214                 sig.as_ptr(),
215                 sig.len(),
216                 data.as_ptr(),
217                 data.len(),
218             ))?;
219             Ok(r == 1)
220         }
221     }
222 }
223 
224 impl<T> PkeyCtxRef<T>
225 where
226     T: HasPrivate,
227 {
228     /// Prepares the context for decryption using the private key.
229     #[corresponds(EVP_PKEY_decrypt_init)]
230     #[inline]
decrypt_init(&mut self) -> Result<(), ErrorStack>231     pub fn decrypt_init(&mut self) -> Result<(), ErrorStack> {
232         unsafe {
233             cvt(ffi::EVP_PKEY_decrypt_init(self.as_ptr()))?;
234         }
235 
236         Ok(())
237     }
238 
239     /// Prepares the context for signing using the private key.
240     #[corresponds(EVP_PKEY_sign_init)]
241     #[inline]
sign_init(&mut self) -> Result<(), ErrorStack>242     pub fn sign_init(&mut self) -> Result<(), ErrorStack> {
243         unsafe {
244             cvt(ffi::EVP_PKEY_sign_init(self.as_ptr()))?;
245         }
246 
247         Ok(())
248     }
249 
250     /// Sets the peer key used for secret derivation.
251     #[corresponds(EVP_PKEY_derive_set_peer)]
derive_set_peer<U>(&mut self, key: &PKeyRef<U>) -> Result<(), ErrorStack> where U: HasPublic,252     pub fn derive_set_peer<U>(&mut self, key: &PKeyRef<U>) -> Result<(), ErrorStack>
253     where
254         U: HasPublic,
255     {
256         unsafe {
257             cvt(ffi::EVP_PKEY_derive_set_peer(self.as_ptr(), key.as_ptr()))?;
258         }
259 
260         Ok(())
261     }
262 
263     /// Decrypts data using the private key.
264     ///
265     /// If `to` is set to `None`, an upper bound on the number of bytes required for the output buffer will be
266     /// returned.
267     #[corresponds(EVP_PKEY_decrypt)]
268     #[inline]
decrypt(&mut self, from: &[u8], to: Option<&mut [u8]>) -> Result<usize, ErrorStack>269     pub fn decrypt(&mut self, from: &[u8], to: Option<&mut [u8]>) -> Result<usize, ErrorStack> {
270         let mut written = to.as_ref().map_or(0, |b| b.len());
271         unsafe {
272             cvt(ffi::EVP_PKEY_decrypt(
273                 self.as_ptr(),
274                 to.map_or(ptr::null_mut(), |b| b.as_mut_ptr()),
275                 &mut written,
276                 from.as_ptr(),
277                 from.len(),
278             ))?;
279         }
280 
281         Ok(written)
282     }
283 
284     /// Like [`Self::decrypt`] but appends plaintext to a [`Vec`].
decrypt_to_vec(&mut self, from: &[u8], out: &mut Vec<u8>) -> Result<usize, ErrorStack>285     pub fn decrypt_to_vec(&mut self, from: &[u8], out: &mut Vec<u8>) -> Result<usize, ErrorStack> {
286         let base = out.len();
287         let len = self.decrypt(from, None)?;
288         out.resize(base + len, 0);
289         let len = self.decrypt(from, Some(&mut out[base..]))?;
290         out.truncate(base + len);
291         Ok(len)
292     }
293 
294     /// Signs the contents of `data`.
295     ///
296     /// If `sig` is set to `None`, an upper bound on the number of bytes required for the output buffer will be
297     /// returned.
298     ///
299     /// # Note
300     ///
301     /// This computes the signature of the *raw* bytes of `data`. It is more common to sign the cryptographic hash of
302     /// an arbitrary amount of data. The [`MdCtx`](crate::md_ctx::MdCtx) type can be used to do that.
303     #[corresponds(EVP_PKEY_sign)]
304     #[inline]
sign(&mut self, data: &[u8], sig: Option<&mut [u8]>) -> Result<usize, ErrorStack>305     pub fn sign(&mut self, data: &[u8], sig: Option<&mut [u8]>) -> Result<usize, ErrorStack> {
306         let mut written = sig.as_ref().map_or(0, |b| b.len());
307         unsafe {
308             cvt(ffi::EVP_PKEY_sign(
309                 self.as_ptr(),
310                 sig.map_or(ptr::null_mut(), |b| b.as_mut_ptr()),
311                 &mut written,
312                 data.as_ptr(),
313                 data.len(),
314             ))?;
315         }
316 
317         Ok(written)
318     }
319 
320     /// Like [`Self::sign`] but appends the signature to a [`Vec`].
sign_to_vec(&mut self, data: &[u8], sig: &mut Vec<u8>) -> Result<usize, ErrorStack>321     pub fn sign_to_vec(&mut self, data: &[u8], sig: &mut Vec<u8>) -> Result<usize, ErrorStack> {
322         let base = sig.len();
323         let len = self.sign(data, None)?;
324         sig.resize(base + len, 0);
325         let len = self.sign(data, Some(&mut sig[base..]))?;
326         sig.truncate(base + len);
327         Ok(len)
328     }
329 }
330 
331 impl<T> PkeyCtxRef<T> {
332     /// Prepares the context for shared secret derivation.
333     #[corresponds(EVP_PKEY_derive_init)]
334     #[inline]
derive_init(&mut self) -> Result<(), ErrorStack>335     pub fn derive_init(&mut self) -> Result<(), ErrorStack> {
336         unsafe {
337             cvt(ffi::EVP_PKEY_derive_init(self.as_ptr()))?;
338         }
339 
340         Ok(())
341     }
342 
343     /// Prepares the context for key generation.
344     #[corresponds(EVP_PKEY_keygen_init)]
345     #[inline]
keygen_init(&mut self) -> Result<(), ErrorStack>346     pub fn keygen_init(&mut self) -> Result<(), ErrorStack> {
347         unsafe {
348             cvt(ffi::EVP_PKEY_keygen_init(self.as_ptr()))?;
349         }
350 
351         Ok(())
352     }
353 
354     /// Returns the RSA padding mode in use.
355     ///
356     /// This is only useful for RSA keys.
357     #[corresponds(EVP_PKEY_CTX_get_rsa_padding)]
358     #[inline]
rsa_padding(&self) -> Result<Padding, ErrorStack>359     pub fn rsa_padding(&self) -> Result<Padding, ErrorStack> {
360         let mut pad = 0;
361         unsafe {
362             cvt(ffi::EVP_PKEY_CTX_get_rsa_padding(self.as_ptr(), &mut pad))?;
363         }
364 
365         Ok(Padding::from_raw(pad))
366     }
367 
368     /// Sets the RSA padding mode.
369     ///
370     /// This is only useful for RSA keys.
371     #[corresponds(EVP_PKEY_CTX_set_rsa_padding)]
372     #[inline]
set_rsa_padding(&mut self, padding: Padding) -> Result<(), ErrorStack>373     pub fn set_rsa_padding(&mut self, padding: Padding) -> Result<(), ErrorStack> {
374         unsafe {
375             cvt(ffi::EVP_PKEY_CTX_set_rsa_padding(
376                 self.as_ptr(),
377                 padding.as_raw(),
378             ))?;
379         }
380 
381         Ok(())
382     }
383 
384     /// Sets the RSA MGF1 algorithm.
385     ///
386     /// This is only useful for RSA keys.
387     #[corresponds(EVP_PKEY_CTX_set_rsa_mgf1_md)]
388     #[inline]
set_rsa_mgf1_md(&mut self, md: &MdRef) -> Result<(), ErrorStack>389     pub fn set_rsa_mgf1_md(&mut self, md: &MdRef) -> Result<(), ErrorStack> {
390         unsafe {
391             cvt(ffi::EVP_PKEY_CTX_set_rsa_mgf1_md(
392                 self.as_ptr(),
393                 md.as_ptr(),
394             ))?;
395         }
396 
397         Ok(())
398     }
399 
400     /// Sets the RSA OAEP algorithm.
401     ///
402     /// This is only useful for RSA keys.
403     #[corresponds(EVP_PKEY_CTX_set_rsa_oaep_md)]
404     #[cfg(any(ossl102, libressl310))]
405     #[inline]
set_rsa_oaep_md(&mut self, md: &MdRef) -> Result<(), ErrorStack>406     pub fn set_rsa_oaep_md(&mut self, md: &MdRef) -> Result<(), ErrorStack> {
407         unsafe {
408             cvt(ffi::EVP_PKEY_CTX_set_rsa_oaep_md(
409                 self.as_ptr(),
410                 md.as_ptr() as *mut _,
411             ))?;
412         }
413 
414         Ok(())
415     }
416 
417     /// Sets the RSA OAEP label.
418     ///
419     /// This is only useful for RSA keys.
420     #[corresponds(EVP_PKEY_CTX_set0_rsa_oaep_label)]
421     #[cfg(any(ossl102, libressl310, boringssl))]
set_rsa_oaep_label(&mut self, label: &[u8]) -> Result<(), ErrorStack>422     pub fn set_rsa_oaep_label(&mut self, label: &[u8]) -> Result<(), ErrorStack> {
423         use crate::LenType;
424         let len = LenType::try_from(label.len()).unwrap();
425 
426         unsafe {
427             let p = ffi::OPENSSL_malloc(label.len() as _);
428             ptr::copy_nonoverlapping(label.as_ptr(), p as *mut _, label.len());
429 
430             let r = cvt(ffi::EVP_PKEY_CTX_set0_rsa_oaep_label(
431                 self.as_ptr(),
432                 p as *mut _,
433                 len,
434             ));
435             if r.is_err() {
436                 ffi::OPENSSL_free(p);
437             }
438             r?;
439         }
440 
441         Ok(())
442     }
443 
444     /// Sets the cipher used during key generation.
445     #[cfg(not(boringssl))]
446     #[corresponds(EVP_PKEY_CTX_ctrl)]
447     #[inline]
set_keygen_cipher(&mut self, cipher: &CipherRef) -> Result<(), ErrorStack>448     pub fn set_keygen_cipher(&mut self, cipher: &CipherRef) -> Result<(), ErrorStack> {
449         unsafe {
450             cvt(ffi::EVP_PKEY_CTX_ctrl(
451                 self.as_ptr(),
452                 -1,
453                 ffi::EVP_PKEY_OP_KEYGEN,
454                 ffi::EVP_PKEY_CTRL_CIPHER,
455                 0,
456                 cipher.as_ptr() as *mut _,
457             ))?;
458         }
459 
460         Ok(())
461     }
462 
463     /// Sets the key MAC key used during key generation.
464     #[cfg(not(boringssl))]
465     #[corresponds(EVP_PKEY_CTX_ctrl)]
466     #[inline]
set_keygen_mac_key(&mut self, key: &[u8]) -> Result<(), ErrorStack>467     pub fn set_keygen_mac_key(&mut self, key: &[u8]) -> Result<(), ErrorStack> {
468         let len = c_int::try_from(key.len()).unwrap();
469 
470         unsafe {
471             cvt(ffi::EVP_PKEY_CTX_ctrl(
472                 self.as_ptr(),
473                 -1,
474                 ffi::EVP_PKEY_OP_KEYGEN,
475                 ffi::EVP_PKEY_CTRL_SET_MAC_KEY,
476                 len,
477                 key.as_ptr() as *mut _,
478             ))?;
479         }
480 
481         Ok(())
482     }
483 
484     /// Sets the digest used for HKDF derivation.
485     ///
486     /// Requires OpenSSL 1.1.0 or newer.
487     #[corresponds(EVP_PKEY_CTX_set_hkdf_md)]
488     #[cfg(ossl110)]
489     #[inline]
set_hkdf_md(&mut self, digest: &MdRef) -> Result<(), ErrorStack>490     pub fn set_hkdf_md(&mut self, digest: &MdRef) -> Result<(), ErrorStack> {
491         unsafe {
492             cvt(ffi::EVP_PKEY_CTX_set_hkdf_md(
493                 self.as_ptr(),
494                 digest.as_ptr(),
495             ))?;
496         }
497 
498         Ok(())
499     }
500 
501     /// Sets the HKDF mode of operation.
502     ///
503     /// Defaults to [`HkdfMode::EXTRACT_THEN_EXPAND`].
504     ///
505     /// WARNING: Although this API calls it a "mode", HKDF-Extract and HKDF-Expand are distinct
506     /// operations with distinct inputs and distinct kinds of keys. Callers should not pass input
507     /// secrets for one operation into the other.
508     ///
509     /// Requires OpenSSL 1.1.1 or newer.
510     #[corresponds(EVP_PKEY_CTX_set_hkdf_mode)]
511     #[cfg(ossl111)]
512     #[inline]
set_hkdf_mode(&mut self, mode: HkdfMode) -> Result<(), ErrorStack>513     pub fn set_hkdf_mode(&mut self, mode: HkdfMode) -> Result<(), ErrorStack> {
514         unsafe {
515             cvt(ffi::EVP_PKEY_CTX_set_hkdf_mode(self.as_ptr(), mode.0))?;
516         }
517 
518         Ok(())
519     }
520 
521     /// Sets the input material for HKDF generation as the "key".
522     ///
523     /// Which input is the key depends on the "mode" (see [`set_hkdf_mode`][Self::set_hkdf_mode]).
524     /// If [`HkdfMode::EXTRACT_THEN_EXPAND`] or [`HkdfMode::EXTRACT_ONLY`], this function specifies
525     /// the input keying material (IKM) for HKDF-Extract. If [`HkdfMode::EXPAND_ONLY`], it instead
526     /// specifies the pseudorandom key (PRK) for HKDF-Expand.
527     ///
528     /// Requires OpenSSL 1.1.0 or newer.
529     #[corresponds(EVP_PKEY_CTX_set1_hkdf_key)]
530     #[cfg(ossl110)]
531     #[inline]
set_hkdf_key(&mut self, key: &[u8]) -> Result<(), ErrorStack>532     pub fn set_hkdf_key(&mut self, key: &[u8]) -> Result<(), ErrorStack> {
533         let len = c_int::try_from(key.len()).unwrap();
534 
535         unsafe {
536             cvt(ffi::EVP_PKEY_CTX_set1_hkdf_key(
537                 self.as_ptr(),
538                 key.as_ptr(),
539                 len,
540             ))?;
541         }
542 
543         Ok(())
544     }
545 
546     /// Sets the salt value for HKDF generation.
547     ///
548     /// If performing HKDF-Expand only, this parameter is ignored.
549     ///
550     /// Requires OpenSSL 1.1.0 or newer.
551     #[corresponds(EVP_PKEY_CTX_set1_hkdf_salt)]
552     #[cfg(ossl110)]
553     #[inline]
set_hkdf_salt(&mut self, salt: &[u8]) -> Result<(), ErrorStack>554     pub fn set_hkdf_salt(&mut self, salt: &[u8]) -> Result<(), ErrorStack> {
555         let len = c_int::try_from(salt.len()).unwrap();
556 
557         unsafe {
558             cvt(ffi::EVP_PKEY_CTX_set1_hkdf_salt(
559                 self.as_ptr(),
560                 salt.as_ptr(),
561                 len,
562             ))?;
563         }
564 
565         Ok(())
566     }
567 
568     /// Appends info bytes for HKDF generation.
569     ///
570     /// If performing HKDF-Extract only, this parameter is ignored.
571     ///
572     /// Requires OpenSSL 1.1.0 or newer.
573     #[corresponds(EVP_PKEY_CTX_add1_hkdf_info)]
574     #[cfg(ossl110)]
575     #[inline]
add_hkdf_info(&mut self, info: &[u8]) -> Result<(), ErrorStack>576     pub fn add_hkdf_info(&mut self, info: &[u8]) -> Result<(), ErrorStack> {
577         let len = c_int::try_from(info.len()).unwrap();
578 
579         unsafe {
580             cvt(ffi::EVP_PKEY_CTX_add1_hkdf_info(
581                 self.as_ptr(),
582                 info.as_ptr(),
583                 len,
584             ))?;
585         }
586 
587         Ok(())
588     }
589 
590     /// Derives a shared secret between two keys.
591     ///
592     /// If `buf` is set to `None`, an upper bound on the number of bytes required for the buffer will be returned.
593     #[corresponds(EVP_PKEY_derive)]
derive(&mut self, buf: Option<&mut [u8]>) -> Result<usize, ErrorStack>594     pub fn derive(&mut self, buf: Option<&mut [u8]>) -> Result<usize, ErrorStack> {
595         let mut len = buf.as_ref().map_or(0, |b| b.len());
596         unsafe {
597             cvt(ffi::EVP_PKEY_derive(
598                 self.as_ptr(),
599                 buf.map_or(ptr::null_mut(), |b| b.as_mut_ptr()),
600                 &mut len,
601             ))?;
602         }
603 
604         Ok(len)
605     }
606 
607     /// Like [`Self::derive`] but appends the secret to a [`Vec`].
derive_to_vec(&mut self, buf: &mut Vec<u8>) -> Result<usize, ErrorStack>608     pub fn derive_to_vec(&mut self, buf: &mut Vec<u8>) -> Result<usize, ErrorStack> {
609         let base = buf.len();
610         let len = self.derive(None)?;
611         buf.resize(base + len, 0);
612         let len = self.derive(Some(&mut buf[base..]))?;
613         buf.truncate(base + len);
614         Ok(len)
615     }
616 
617     /// Generates a new public/private keypair.
618     #[corresponds(EVP_PKEY_keygen)]
619     #[inline]
keygen(&mut self) -> Result<PKey<Private>, ErrorStack>620     pub fn keygen(&mut self) -> Result<PKey<Private>, ErrorStack> {
621         unsafe {
622             let mut key = ptr::null_mut();
623             cvt(ffi::EVP_PKEY_keygen(self.as_ptr(), &mut key))?;
624             Ok(PKey::from_ptr(key))
625         }
626     }
627 }
628 
629 #[cfg(test)]
630 mod test {
631     use super::*;
632     #[cfg(not(boringssl))]
633     use crate::cipher::Cipher;
634     use crate::ec::{EcGroup, EcKey};
635     #[cfg(any(ossl102, libressl310))]
636     use crate::md::Md;
637     use crate::nid::Nid;
638     use crate::pkey::PKey;
639     use crate::rsa::Rsa;
640 
641     #[test]
rsa()642     fn rsa() {
643         let key = include_bytes!("../test/rsa.pem");
644         let rsa = Rsa::private_key_from_pem(key).unwrap();
645         let pkey = PKey::from_rsa(rsa).unwrap();
646 
647         let mut ctx = PkeyCtx::new(&pkey).unwrap();
648         ctx.encrypt_init().unwrap();
649         ctx.set_rsa_padding(Padding::PKCS1).unwrap();
650 
651         let pt = "hello world".as_bytes();
652         let mut ct = vec![];
653         ctx.encrypt_to_vec(pt, &mut ct).unwrap();
654 
655         ctx.decrypt_init().unwrap();
656         ctx.set_rsa_padding(Padding::PKCS1).unwrap();
657 
658         let mut out = vec![];
659         ctx.decrypt_to_vec(&ct, &mut out).unwrap();
660 
661         assert_eq!(pt, out);
662     }
663 
664     #[test]
665     #[cfg(any(ossl102, libressl310))]
rsa_oaep()666     fn rsa_oaep() {
667         let key = include_bytes!("../test/rsa.pem");
668         let rsa = Rsa::private_key_from_pem(key).unwrap();
669         let pkey = PKey::from_rsa(rsa).unwrap();
670 
671         let mut ctx = PkeyCtx::new(&pkey).unwrap();
672         ctx.encrypt_init().unwrap();
673         ctx.set_rsa_padding(Padding::PKCS1_OAEP).unwrap();
674         ctx.set_rsa_oaep_md(Md::sha256()).unwrap();
675         ctx.set_rsa_mgf1_md(Md::sha256()).unwrap();
676 
677         let pt = "hello world".as_bytes();
678         let mut ct = vec![];
679         ctx.encrypt_to_vec(pt, &mut ct).unwrap();
680 
681         ctx.decrypt_init().unwrap();
682         ctx.set_rsa_padding(Padding::PKCS1_OAEP).unwrap();
683         ctx.set_rsa_oaep_md(Md::sha256()).unwrap();
684         ctx.set_rsa_mgf1_md(Md::sha256()).unwrap();
685 
686         let mut out = vec![];
687         ctx.decrypt_to_vec(&ct, &mut out).unwrap();
688 
689         assert_eq!(pt, out);
690     }
691 
692     #[test]
derive()693     fn derive() {
694         let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
695         let key1 = EcKey::generate(&group).unwrap();
696         let key1 = PKey::from_ec_key(key1).unwrap();
697         let key2 = EcKey::generate(&group).unwrap();
698         let key2 = PKey::from_ec_key(key2).unwrap();
699 
700         let mut ctx = PkeyCtx::new(&key1).unwrap();
701         ctx.derive_init().unwrap();
702         ctx.derive_set_peer(&key2).unwrap();
703 
704         let mut buf = vec![];
705         ctx.derive_to_vec(&mut buf).unwrap();
706     }
707 
708     #[test]
709     #[cfg(not(boringssl))]
cmac_keygen()710     fn cmac_keygen() {
711         let mut ctx = PkeyCtx::new_id(Id::CMAC).unwrap();
712         ctx.keygen_init().unwrap();
713         ctx.set_keygen_cipher(Cipher::aes_128_cbc()).unwrap();
714         ctx.set_keygen_mac_key(&hex::decode("9294727a3638bb1c13f48ef8158bfc9d").unwrap())
715             .unwrap();
716         ctx.keygen().unwrap();
717     }
718 
719     #[test]
720     #[cfg(ossl110)]
hkdf()721     fn hkdf() {
722         let mut ctx = PkeyCtx::new_id(Id::HKDF).unwrap();
723         ctx.derive_init().unwrap();
724         ctx.set_hkdf_md(Md::sha256()).unwrap();
725         ctx.set_hkdf_key(&hex::decode("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b").unwrap())
726             .unwrap();
727         ctx.set_hkdf_salt(&hex::decode("000102030405060708090a0b0c").unwrap())
728             .unwrap();
729         ctx.add_hkdf_info(&hex::decode("f0f1f2f3f4f5f6f7f8f9").unwrap())
730             .unwrap();
731         let mut out = [0; 42];
732         ctx.derive(Some(&mut out)).unwrap();
733 
734         assert_eq!(
735             &out[..],
736             hex::decode("3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865")
737                 .unwrap()
738         );
739     }
740 
741     #[test]
742     #[cfg(ossl111)]
hkdf_expand()743     fn hkdf_expand() {
744         let mut ctx = PkeyCtx::new_id(Id::HKDF).unwrap();
745         ctx.derive_init().unwrap();
746         ctx.set_hkdf_mode(HkdfMode::EXPAND_ONLY).unwrap();
747         ctx.set_hkdf_md(Md::sha256()).unwrap();
748         ctx.set_hkdf_key(
749             &hex::decode("077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5")
750                 .unwrap(),
751         )
752         .unwrap();
753         ctx.add_hkdf_info(&hex::decode("f0f1f2f3f4f5f6f7f8f9").unwrap())
754             .unwrap();
755         let mut out = [0; 42];
756         ctx.derive(Some(&mut out)).unwrap();
757 
758         assert_eq!(
759             &out[..],
760             hex::decode("3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865")
761                 .unwrap()
762         );
763     }
764 
765     #[test]
766     #[cfg(ossl111)]
hkdf_extract()767     fn hkdf_extract() {
768         let mut ctx = PkeyCtx::new_id(Id::HKDF).unwrap();
769         ctx.derive_init().unwrap();
770         ctx.set_hkdf_mode(HkdfMode::EXTRACT_ONLY).unwrap();
771         ctx.set_hkdf_md(Md::sha256()).unwrap();
772         ctx.set_hkdf_key(&hex::decode("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b").unwrap())
773             .unwrap();
774         ctx.set_hkdf_salt(&hex::decode("000102030405060708090a0b0c").unwrap())
775             .unwrap();
776         let mut out = vec![];
777         ctx.derive_to_vec(&mut out).unwrap();
778 
779         assert_eq!(
780             &out[..],
781             hex::decode("077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5")
782                 .unwrap()
783         );
784     }
785 
786     #[test]
verify_fail()787     fn verify_fail() {
788         let key1 = Rsa::generate(4096).unwrap();
789         let key1 = PKey::from_rsa(key1).unwrap();
790 
791         let data = b"Some Crypto Text";
792 
793         let mut ctx = PkeyCtx::new(&key1).unwrap();
794         ctx.sign_init().unwrap();
795         let mut signature = vec![];
796         ctx.sign_to_vec(data, &mut signature).unwrap();
797 
798         let bad_data = b"Some Crypto text";
799 
800         ctx.verify_init().unwrap();
801         let valid = ctx.verify(bad_data, &signature).unwrap();
802         assert!(!valid);
803     }
804 }
805