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#"\
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(boringssl))]
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(boringssl))]
77use libc::c_int;
78use openssl_macros::corresponds;
79use std::convert::TryFrom;
80use std::ptr;
81
82/// HKDF modes of operation.
83#[cfg(any(ossl111, libressl360))]
84pub struct HkdfMode(c_int);
85
86#[cfg(any(ossl111, libressl360))]
87impl HkdfMode {
88 /// This is the default mode. Calling [`derive`][PkeyCtxRef::derive] on a [`PkeyCtxRef`] set up
89 /// for HKDF will perform an extract followed by an expand operation in one go. The derived key
90 /// returned will be the result after the expand operation. The intermediate fixed-length
91 /// pseudorandom key K is not returned.
92 pub const EXTRACT_THEN_EXPAND: Self = HkdfMode(ffi::EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND);
93
94 /// In this mode calling [`derive`][PkeyCtxRef::derive] will just perform the extract operation.
95 /// The value returned will be the intermediate fixed-length pseudorandom key K.
96 ///
97 /// The digest, key and salt values must be set before a key is derived or an error occurs.
98 pub const EXTRACT_ONLY: Self = HkdfMode(ffi::EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY);
99
100 /// In this mode calling [`derive`][PkeyCtxRef::derive] will just perform the expand operation.
101 /// The input key should be set to the intermediate fixed-length pseudorandom key K returned
102 /// from a previous extract operation.
103 ///
104 /// The digest, key and info values must be set before a key is derived or an error occurs.
105 pub const EXPAND_ONLY: Self = HkdfMode(ffi::EVP_PKEY_HKDEF_MODE_EXPAND_ONLY);
106}
107
108generic_foreign_type_and_impl_send_sync! {
109 type CType = ffi::EVP_PKEY_CTX;
110 fn drop = ffi::EVP_PKEY_CTX_free;
111
112 /// A context object which can perform asymmetric cryptography operations.
113 pub struct PkeyCtx<T>;
114 /// A reference to a [`PkeyCtx`].
115 pub struct PkeyCtxRef<T>;
116}
117
118impl<T> PkeyCtx<T> {
119 /// Creates a new pkey context using the provided key.
120 #[corresponds(EVP_PKEY_CTX_new)]
121 #[inline]
122 pub fn new(pkey: &PKeyRef<T>) -> Result<Self, ErrorStack> {
123 unsafe {
124 let ptr: *mut EVP_PKEY_CTX = cvt_p(ffi::EVP_PKEY_CTX_new(k:pkey.as_ptr(), e:ptr::null_mut()))?;
125 Ok(PkeyCtx::from_ptr(ptr))
126 }
127 }
128}
129
130impl PkeyCtx<()> {
131 /// Creates a new pkey context for the specified algorithm ID.
132 #[corresponds(EVP_PKEY_new_id)]
133 #[inline]
134 pub fn new_id(id: Id) -> Result<Self, ErrorStack> {
135 unsafe {
136 let ptr: *mut EVP_PKEY_CTX = cvt_p(ffi::EVP_PKEY_CTX_new_id(id:id.as_raw(), e:ptr::null_mut()))?;
137 Ok(PkeyCtx::from_ptr(ptr))
138 }
139 }
140}
141
142impl<T> PkeyCtxRef<T>
143where
144 T: HasPublic,
145{
146 /// Prepares the context for encryption using the public key.
147 #[corresponds(EVP_PKEY_encrypt_init)]
148 #[inline]
149 pub fn encrypt_init(&mut self) -> Result<(), ErrorStack> {
150 unsafe {
151 cvt(ffi::EVP_PKEY_encrypt_init(self.as_ptr()))?;
152 }
153
154 Ok(())
155 }
156
157 /// Prepares the context for signature verification using the public key.
158 #[corresponds(EVP_PKEY_verify_init)]
159 #[inline]
160 pub fn verify_init(&mut self) -> Result<(), ErrorStack> {
161 unsafe {
162 cvt(ffi::EVP_PKEY_verify_init(self.as_ptr()))?;
163 }
164
165 Ok(())
166 }
167
168 /// Prepares the context for signature recovery using the public key.
169 #[corresponds(EVP_PKEY_verify_recover_init)]
170 #[inline]
171 pub fn verify_recover_init(&mut self) -> Result<(), ErrorStack> {
172 unsafe {
173 cvt(ffi::EVP_PKEY_verify_recover_init(self.as_ptr()))?;
174 }
175
176 Ok(())
177 }
178
179 /// Encrypts data using the public key.
180 ///
181 /// If `to` is set to `None`, an upper bound on the number of bytes required for the output buffer will be
182 /// returned.
183 #[corresponds(EVP_PKEY_encrypt)]
184 #[inline]
185 pub fn encrypt(&mut self, from: &[u8], to: Option<&mut [u8]>) -> Result<usize, ErrorStack> {
186 let mut written = to.as_ref().map_or(0, |b| b.len());
187 unsafe {
188 cvt(ffi::EVP_PKEY_encrypt(
189 self.as_ptr(),
190 to.map_or(ptr::null_mut(), |b| b.as_mut_ptr()),
191 &mut written,
192 from.as_ptr(),
193 from.len(),
194 ))?;
195 }
196
197 Ok(written)
198 }
199
200 /// Like [`Self::encrypt`] but appends ciphertext to a [`Vec`].
201 pub fn encrypt_to_vec(&mut self, from: &[u8], out: &mut Vec<u8>) -> Result<usize, ErrorStack> {
202 let base = out.len();
203 let len = self.encrypt(from, None)?;
204 out.resize(base + len, 0);
205 let len = self.encrypt(from, Some(&mut out[base..]))?;
206 out.truncate(base + len);
207 Ok(len)
208 }
209
210 /// Verifies the signature of data using the public key.
211 ///
212 /// Returns `Ok(true)` if the signature is valid, `Ok(false)` if the signature is invalid, and `Err` if an error
213 /// occurred.
214 ///
215 /// # Note
216 ///
217 /// This verifies the signature of the *raw* data. It is more common to compute and verify the signature of the
218 /// cryptographic hash of an arbitrary amount of data. The [`MdCtx`](crate::md_ctx::MdCtx) type can be used to do
219 /// that.
220 #[corresponds(EVP_PKEY_verify)]
221 #[inline]
222 pub fn verify(&mut self, data: &[u8], sig: &[u8]) -> Result<bool, ErrorStack> {
223 unsafe {
224 let r = ffi::EVP_PKEY_verify(
225 self.as_ptr(),
226 sig.as_ptr(),
227 sig.len(),
228 data.as_ptr(),
229 data.len(),
230 );
231 // `EVP_PKEY_verify` is not terribly consistent about how it,
232 // reports errors. It does not clearly distinguish between 0 and
233 // -1, and may put errors on the stack in both cases. If there's
234 // errors on the stack, we return `Err()`, else we return
235 // `Ok(false)`.
236 if r <= 0 {
237 let errors = ErrorStack::get();
238 if !errors.errors().is_empty() {
239 return Err(errors);
240 }
241 }
242
243 Ok(r == 1)
244 }
245 }
246
247 /// Recovers the original data signed by the private key. You almost
248 /// always want `verify` instead.
249 ///
250 /// Returns the number of bytes written to `to`, or the number of bytes
251 /// that would be written, if `to` is `None.
252 #[corresponds(EVP_PKEY_verify_recover)]
253 #[inline]
254 pub fn verify_recover(
255 &mut self,
256 sig: &[u8],
257 to: Option<&mut [u8]>,
258 ) -> Result<usize, ErrorStack> {
259 let mut written = to.as_ref().map_or(0, |b| b.len());
260 unsafe {
261 cvt(ffi::EVP_PKEY_verify_recover(
262 self.as_ptr(),
263 to.map_or(ptr::null_mut(), |b| b.as_mut_ptr()),
264 &mut written,
265 sig.as_ptr(),
266 sig.len(),
267 ))?;
268 }
269
270 Ok(written)
271 }
272}
273
274impl<T> PkeyCtxRef<T>
275where
276 T: HasPrivate,
277{
278 /// Prepares the context for decryption using the private key.
279 #[corresponds(EVP_PKEY_decrypt_init)]
280 #[inline]
281 pub fn decrypt_init(&mut self) -> Result<(), ErrorStack> {
282 unsafe {
283 cvt(ffi::EVP_PKEY_decrypt_init(self.as_ptr()))?;
284 }
285
286 Ok(())
287 }
288
289 /// Prepares the context for signing using the private key.
290 #[corresponds(EVP_PKEY_sign_init)]
291 #[inline]
292 pub fn sign_init(&mut self) -> Result<(), ErrorStack> {
293 unsafe {
294 cvt(ffi::EVP_PKEY_sign_init(self.as_ptr()))?;
295 }
296
297 Ok(())
298 }
299
300 /// Sets the peer key used for secret derivation.
301 #[corresponds(EVP_PKEY_derive_set_peer)]
302 pub fn derive_set_peer<U>(&mut self, key: &PKeyRef<U>) -> Result<(), ErrorStack>
303 where
304 U: HasPublic,
305 {
306 unsafe {
307 cvt(ffi::EVP_PKEY_derive_set_peer(self.as_ptr(), key.as_ptr()))?;
308 }
309
310 Ok(())
311 }
312
313 /// Decrypts data using the private key.
314 ///
315 /// If `to` is set to `None`, an upper bound on the number of bytes required for the output buffer will be
316 /// returned.
317 #[corresponds(EVP_PKEY_decrypt)]
318 #[inline]
319 pub fn decrypt(&mut self, from: &[u8], to: Option<&mut [u8]>) -> Result<usize, ErrorStack> {
320 let mut written = to.as_ref().map_or(0, |b| b.len());
321 unsafe {
322 cvt(ffi::EVP_PKEY_decrypt(
323 self.as_ptr(),
324 to.map_or(ptr::null_mut(), |b| b.as_mut_ptr()),
325 &mut written,
326 from.as_ptr(),
327 from.len(),
328 ))?;
329 }
330
331 Ok(written)
332 }
333
334 /// Like [`Self::decrypt`] but appends plaintext to a [`Vec`].
335 pub fn decrypt_to_vec(&mut self, from: &[u8], out: &mut Vec<u8>) -> Result<usize, ErrorStack> {
336 let base = out.len();
337 let len = self.decrypt(from, None)?;
338 out.resize(base + len, 0);
339 let len = self.decrypt(from, Some(&mut out[base..]))?;
340 out.truncate(base + len);
341 Ok(len)
342 }
343
344 /// Signs the contents of `data`.
345 ///
346 /// If `sig` is set to `None`, an upper bound on the number of bytes required for the output buffer will be
347 /// returned.
348 ///
349 /// # Note
350 ///
351 /// This computes the signature of the *raw* bytes of `data`. It is more common to sign the cryptographic hash of
352 /// an arbitrary amount of data. The [`MdCtx`](crate::md_ctx::MdCtx) type can be used to do that.
353 #[corresponds(EVP_PKEY_sign)]
354 #[inline]
355 pub fn sign(&mut self, data: &[u8], sig: Option<&mut [u8]>) -> Result<usize, ErrorStack> {
356 let mut written = sig.as_ref().map_or(0, |b| b.len());
357 unsafe {
358 cvt(ffi::EVP_PKEY_sign(
359 self.as_ptr(),
360 sig.map_or(ptr::null_mut(), |b| b.as_mut_ptr()),
361 &mut written,
362 data.as_ptr(),
363 data.len(),
364 ))?;
365 }
366
367 Ok(written)
368 }
369
370 /// Like [`Self::sign`] but appends the signature to a [`Vec`].
371 pub fn sign_to_vec(&mut self, data: &[u8], sig: &mut Vec<u8>) -> Result<usize, ErrorStack> {
372 let base = sig.len();
373 let len = self.sign(data, None)?;
374 sig.resize(base + len, 0);
375 let len = self.sign(data, Some(&mut sig[base..]))?;
376 sig.truncate(base + len);
377 Ok(len)
378 }
379}
380
381impl<T> PkeyCtxRef<T> {
382 /// Prepares the context for shared secret derivation.
383 #[corresponds(EVP_PKEY_derive_init)]
384 #[inline]
385 pub fn derive_init(&mut self) -> Result<(), ErrorStack> {
386 unsafe {
387 cvt(ffi::EVP_PKEY_derive_init(self.as_ptr()))?;
388 }
389
390 Ok(())
391 }
392
393 /// Prepares the context for key generation.
394 #[corresponds(EVP_PKEY_keygen_init)]
395 #[inline]
396 pub fn keygen_init(&mut self) -> Result<(), ErrorStack> {
397 unsafe {
398 cvt(ffi::EVP_PKEY_keygen_init(self.as_ptr()))?;
399 }
400
401 Ok(())
402 }
403
404 /// Sets which algorithm was used to compute the digest used in a
405 /// signature. With RSA signatures this causes the signature to be wrapped
406 /// in a `DigestInfo` structure. This is almost always what you want with
407 /// RSA signatures.
408 #[corresponds(EVP_PKEY_CTX_set_signature_md)]
409 #[inline]
410 pub fn set_signature_md(&self, md: &MdRef) -> Result<(), ErrorStack> {
411 unsafe {
412 cvt(ffi::EVP_PKEY_CTX_set_signature_md(
413 self.as_ptr(),
414 md.as_ptr(),
415 ))?;
416 }
417 Ok(())
418 }
419
420 /// Returns the RSA padding mode in use.
421 ///
422 /// This is only useful for RSA keys.
423 #[corresponds(EVP_PKEY_CTX_get_rsa_padding)]
424 #[inline]
425 pub fn rsa_padding(&self) -> Result<Padding, ErrorStack> {
426 let mut pad = 0;
427 unsafe {
428 cvt(ffi::EVP_PKEY_CTX_get_rsa_padding(self.as_ptr(), &mut pad))?;
429 }
430
431 Ok(Padding::from_raw(pad))
432 }
433
434 /// Sets the RSA padding mode.
435 ///
436 /// This is only useful for RSA keys.
437 #[corresponds(EVP_PKEY_CTX_set_rsa_padding)]
438 #[inline]
439 pub fn set_rsa_padding(&mut self, padding: Padding) -> Result<(), ErrorStack> {
440 unsafe {
441 cvt(ffi::EVP_PKEY_CTX_set_rsa_padding(
442 self.as_ptr(),
443 padding.as_raw(),
444 ))?;
445 }
446
447 Ok(())
448 }
449
450 /// Sets the RSA PSS salt length.
451 ///
452 /// This is only useful for RSA keys.
453 #[corresponds(EVP_PKEY_CTX_set_rsa_pss_saltlen)]
454 #[inline]
455 pub fn set_rsa_pss_saltlen(&mut self, len: RsaPssSaltlen) -> Result<(), ErrorStack> {
456 unsafe {
457 cvt(ffi::EVP_PKEY_CTX_set_rsa_pss_saltlen(
458 self.as_ptr(),
459 len.as_raw(),
460 ))
461 .map(|_| ())
462 }
463 }
464
465 /// Sets the RSA MGF1 algorithm.
466 ///
467 /// This is only useful for RSA keys.
468 #[corresponds(EVP_PKEY_CTX_set_rsa_mgf1_md)]
469 #[inline]
470 pub fn set_rsa_mgf1_md(&mut self, md: &MdRef) -> Result<(), ErrorStack> {
471 unsafe {
472 cvt(ffi::EVP_PKEY_CTX_set_rsa_mgf1_md(
473 self.as_ptr(),
474 md.as_ptr(),
475 ))?;
476 }
477
478 Ok(())
479 }
480
481 /// Sets the RSA OAEP algorithm.
482 ///
483 /// This is only useful for RSA keys.
484 #[corresponds(EVP_PKEY_CTX_set_rsa_oaep_md)]
485 #[cfg(any(ossl102, libressl310, boringssl))]
486 #[inline]
487 pub fn set_rsa_oaep_md(&mut self, md: &MdRef) -> Result<(), ErrorStack> {
488 unsafe {
489 cvt(ffi::EVP_PKEY_CTX_set_rsa_oaep_md(
490 self.as_ptr(),
491 md.as_ptr() as *mut _,
492 ))?;
493 }
494
495 Ok(())
496 }
497
498 /// Sets the RSA OAEP label.
499 ///
500 /// This is only useful for RSA keys.
501 #[corresponds(EVP_PKEY_CTX_set0_rsa_oaep_label)]
502 #[cfg(any(ossl102, libressl310, boringssl))]
503 pub fn set_rsa_oaep_label(&mut self, label: &[u8]) -> Result<(), ErrorStack> {
504 use crate::LenType;
505 let len = LenType::try_from(label.len()).unwrap();
506
507 unsafe {
508 let p = ffi::OPENSSL_malloc(label.len() as _);
509 ptr::copy_nonoverlapping(label.as_ptr(), p as *mut _, label.len());
510
511 let r = cvt(ffi::EVP_PKEY_CTX_set0_rsa_oaep_label(
512 self.as_ptr(),
513 p as *mut _,
514 len,
515 ));
516 if r.is_err() {
517 ffi::OPENSSL_free(p);
518 }
519 r?;
520 }
521
522 Ok(())
523 }
524
525 /// Sets the cipher used during key generation.
526 #[cfg(not(boringssl))]
527 #[corresponds(EVP_PKEY_CTX_ctrl)]
528 #[inline]
529 pub fn set_keygen_cipher(&mut self, cipher: &CipherRef) -> Result<(), ErrorStack> {
530 unsafe {
531 cvt(ffi::EVP_PKEY_CTX_ctrl(
532 self.as_ptr(),
533 -1,
534 ffi::EVP_PKEY_OP_KEYGEN,
535 ffi::EVP_PKEY_CTRL_CIPHER,
536 0,
537 cipher.as_ptr() as *mut _,
538 ))?;
539 }
540
541 Ok(())
542 }
543
544 /// Sets the key MAC key used during key generation.
545 #[cfg(not(boringssl))]
546 #[corresponds(EVP_PKEY_CTX_ctrl)]
547 #[inline]
548 pub fn set_keygen_mac_key(&mut self, key: &[u8]) -> Result<(), ErrorStack> {
549 let len = c_int::try_from(key.len()).unwrap();
550
551 unsafe {
552 cvt(ffi::EVP_PKEY_CTX_ctrl(
553 self.as_ptr(),
554 -1,
555 ffi::EVP_PKEY_OP_KEYGEN,
556 ffi::EVP_PKEY_CTRL_SET_MAC_KEY,
557 len,
558 key.as_ptr() as *mut _,
559 ))?;
560 }
561
562 Ok(())
563 }
564
565 /// Sets the digest used for HKDF derivation.
566 ///
567 /// Requires OpenSSL 1.1.0 or newer.
568 #[corresponds(EVP_PKEY_CTX_set_hkdf_md)]
569 #[cfg(any(ossl110, boringssl, libressl360))]
570 #[inline]
571 pub fn set_hkdf_md(&mut self, digest: &MdRef) -> Result<(), ErrorStack> {
572 unsafe {
573 cvt(ffi::EVP_PKEY_CTX_set_hkdf_md(
574 self.as_ptr(),
575 digest.as_ptr(),
576 ))?;
577 }
578
579 Ok(())
580 }
581
582 /// Sets the HKDF mode of operation.
583 ///
584 /// Defaults to [`HkdfMode::EXTRACT_THEN_EXPAND`].
585 ///
586 /// WARNING: Although this API calls it a "mode", HKDF-Extract and HKDF-Expand are distinct
587 /// operations with distinct inputs and distinct kinds of keys. Callers should not pass input
588 /// secrets for one operation into the other.
589 ///
590 /// Requires OpenSSL 1.1.1 or newer.
591 #[corresponds(EVP_PKEY_CTX_set_hkdf_mode)]
592 #[cfg(any(ossl111, libressl360))]
593 #[inline]
594 pub fn set_hkdf_mode(&mut self, mode: HkdfMode) -> Result<(), ErrorStack> {
595 unsafe {
596 cvt(ffi::EVP_PKEY_CTX_set_hkdf_mode(self.as_ptr(), mode.0))?;
597 }
598
599 Ok(())
600 }
601
602 /// Sets the input material for HKDF generation as the "key".
603 ///
604 /// Which input is the key depends on the "mode" (see [`set_hkdf_mode`][Self::set_hkdf_mode]).
605 /// If [`HkdfMode::EXTRACT_THEN_EXPAND`] or [`HkdfMode::EXTRACT_ONLY`], this function specifies
606 /// the input keying material (IKM) for HKDF-Extract. If [`HkdfMode::EXPAND_ONLY`], it instead
607 /// specifies the pseudorandom key (PRK) for HKDF-Expand.
608 ///
609 /// Requires OpenSSL 1.1.0 or newer.
610 #[corresponds(EVP_PKEY_CTX_set1_hkdf_key)]
611 #[cfg(any(ossl110, boringssl, libressl360))]
612 #[inline]
613 pub fn set_hkdf_key(&mut self, key: &[u8]) -> Result<(), ErrorStack> {
614 #[cfg(not(boringssl))]
615 let len = c_int::try_from(key.len()).unwrap();
616 #[cfg(boringssl)]
617 let len = key.len();
618
619 unsafe {
620 cvt(ffi::EVP_PKEY_CTX_set1_hkdf_key(
621 self.as_ptr(),
622 key.as_ptr(),
623 len,
624 ))?;
625 }
626
627 Ok(())
628 }
629
630 /// Sets the salt value for HKDF generation.
631 ///
632 /// If performing HKDF-Expand only, this parameter is ignored.
633 ///
634 /// Requires OpenSSL 1.1.0 or newer.
635 #[corresponds(EVP_PKEY_CTX_set1_hkdf_salt)]
636 #[cfg(any(ossl110, boringssl, libressl360))]
637 #[inline]
638 pub fn set_hkdf_salt(&mut self, salt: &[u8]) -> Result<(), ErrorStack> {
639 #[cfg(not(boringssl))]
640 let len = c_int::try_from(salt.len()).unwrap();
641 #[cfg(boringssl)]
642 let len = salt.len();
643
644 unsafe {
645 cvt(ffi::EVP_PKEY_CTX_set1_hkdf_salt(
646 self.as_ptr(),
647 salt.as_ptr(),
648 len,
649 ))?;
650 }
651
652 Ok(())
653 }
654
655 /// Appends info bytes for HKDF generation.
656 ///
657 /// If performing HKDF-Extract only, this parameter is ignored.
658 ///
659 /// Requires OpenSSL 1.1.0 or newer.
660 #[corresponds(EVP_PKEY_CTX_add1_hkdf_info)]
661 #[cfg(any(ossl110, boringssl, libressl360))]
662 #[inline]
663 pub fn add_hkdf_info(&mut self, info: &[u8]) -> Result<(), ErrorStack> {
664 #[cfg(not(boringssl))]
665 let len = c_int::try_from(info.len()).unwrap();
666 #[cfg(boringssl)]
667 let len = info.len();
668
669 unsafe {
670 cvt(ffi::EVP_PKEY_CTX_add1_hkdf_info(
671 self.as_ptr(),
672 info.as_ptr(),
673 len,
674 ))?;
675 }
676
677 Ok(())
678 }
679
680 /// Derives a shared secret between two keys.
681 ///
682 /// If `buf` is set to `None`, an upper bound on the number of bytes required for the buffer will be returned.
683 #[corresponds(EVP_PKEY_derive)]
684 pub fn derive(&mut self, buf: Option<&mut [u8]>) -> Result<usize, ErrorStack> {
685 let mut len = buf.as_ref().map_or(0, |b| b.len());
686 unsafe {
687 cvt(ffi::EVP_PKEY_derive(
688 self.as_ptr(),
689 buf.map_or(ptr::null_mut(), |b| b.as_mut_ptr()),
690 &mut len,
691 ))?;
692 }
693
694 Ok(len)
695 }
696
697 /// Like [`Self::derive`] but appends the secret to a [`Vec`].
698 pub fn derive_to_vec(&mut self, buf: &mut Vec<u8>) -> Result<usize, ErrorStack> {
699 let base = buf.len();
700 let len = self.derive(None)?;
701 buf.resize(base + len, 0);
702 let len = self.derive(Some(&mut buf[base..]))?;
703 buf.truncate(base + len);
704 Ok(len)
705 }
706
707 /// Generates a new public/private keypair.
708 #[corresponds(EVP_PKEY_keygen)]
709 #[inline]
710 pub fn keygen(&mut self) -> Result<PKey<Private>, ErrorStack> {
711 unsafe {
712 let mut key = ptr::null_mut();
713 cvt(ffi::EVP_PKEY_keygen(self.as_ptr(), &mut key))?;
714 Ok(PKey::from_ptr(key))
715 }
716 }
717}
718
719#[cfg(test)]
720mod test {
721 use super::*;
722 #[cfg(not(boringssl))]
723 use crate::cipher::Cipher;
724 use crate::ec::{EcGroup, EcKey};
725 use crate::hash::{hash, MessageDigest};
726 use crate::md::Md;
727 use crate::nid::Nid;
728 use crate::pkey::PKey;
729 use crate::rsa::Rsa;
730 use crate::sign::Verifier;
731
732 #[test]
733 fn rsa() {
734 let key = include_bytes!("../test/rsa.pem");
735 let rsa = Rsa::private_key_from_pem(key).unwrap();
736 let pkey = PKey::from_rsa(rsa).unwrap();
737
738 let mut ctx = PkeyCtx::new(&pkey).unwrap();
739 ctx.encrypt_init().unwrap();
740 ctx.set_rsa_padding(Padding::PKCS1).unwrap();
741
742 let pt = "hello world".as_bytes();
743 let mut ct = vec![];
744 ctx.encrypt_to_vec(pt, &mut ct).unwrap();
745
746 ctx.decrypt_init().unwrap();
747 ctx.set_rsa_padding(Padding::PKCS1).unwrap();
748
749 let mut out = vec![];
750 ctx.decrypt_to_vec(&ct, &mut out).unwrap();
751
752 assert_eq!(pt, out);
753 }
754
755 #[test]
756 #[cfg(any(ossl102, libressl310, boringssl))]
757 fn rsa_oaep() {
758 let key = include_bytes!("../test/rsa.pem");
759 let rsa = Rsa::private_key_from_pem(key).unwrap();
760 let pkey = PKey::from_rsa(rsa).unwrap();
761
762 let mut ctx = PkeyCtx::new(&pkey).unwrap();
763 ctx.encrypt_init().unwrap();
764 ctx.set_rsa_padding(Padding::PKCS1_OAEP).unwrap();
765 ctx.set_rsa_oaep_md(Md::sha256()).unwrap();
766 ctx.set_rsa_mgf1_md(Md::sha256()).unwrap();
767
768 let pt = "hello world".as_bytes();
769 let mut ct = vec![];
770 ctx.encrypt_to_vec(pt, &mut ct).unwrap();
771
772 ctx.decrypt_init().unwrap();
773 ctx.set_rsa_padding(Padding::PKCS1_OAEP).unwrap();
774 ctx.set_rsa_oaep_md(Md::sha256()).unwrap();
775 ctx.set_rsa_mgf1_md(Md::sha256()).unwrap();
776
777 let mut out = vec![];
778 ctx.decrypt_to_vec(&ct, &mut out).unwrap();
779
780 assert_eq!(pt, out);
781 }
782
783 #[test]
784 fn rsa_sign() {
785 let key = include_bytes!("../test/rsa.pem");
786 let rsa = Rsa::private_key_from_pem(key).unwrap();
787 let pkey = PKey::from_rsa(rsa).unwrap();
788
789 let mut ctx = PkeyCtx::new(&pkey).unwrap();
790 ctx.sign_init().unwrap();
791 ctx.set_rsa_padding(Padding::PKCS1).unwrap();
792 ctx.set_signature_md(Md::sha384()).unwrap();
793
794 let msg = b"hello world";
795 let digest = hash(MessageDigest::sha384(), msg).unwrap();
796 let mut signature = vec![];
797 ctx.sign_to_vec(&digest, &mut signature).unwrap();
798
799 let mut verifier = Verifier::new(MessageDigest::sha384(), &pkey).unwrap();
800 verifier.update(msg).unwrap();
801 assert!(matches!(verifier.verify(&signature), Ok(true)));
802 }
803
804 #[test]
805 fn rsa_sign_pss() {
806 let key = include_bytes!("../test/rsa.pem");
807 let rsa = Rsa::private_key_from_pem(key).unwrap();
808 let pkey = PKey::from_rsa(rsa).unwrap();
809
810 let mut ctx = PkeyCtx::new(&pkey).unwrap();
811 ctx.sign_init().unwrap();
812 ctx.set_rsa_padding(Padding::PKCS1_PSS).unwrap();
813 ctx.set_signature_md(Md::sha384()).unwrap();
814 ctx.set_rsa_pss_saltlen(RsaPssSaltlen::custom(14)).unwrap();
815
816 let msg = b"hello world";
817 let digest = hash(MessageDigest::sha384(), msg).unwrap();
818 let mut signature = vec![];
819 ctx.sign_to_vec(&digest, &mut signature).unwrap();
820
821 let mut verifier = Verifier::new(MessageDigest::sha384(), &pkey).unwrap();
822 verifier.set_rsa_padding(Padding::PKCS1_PSS).unwrap();
823 verifier
824 .set_rsa_pss_saltlen(RsaPssSaltlen::custom(14))
825 .unwrap();
826 verifier.update(msg).unwrap();
827 assert!(matches!(verifier.verify(&signature), Ok(true)));
828 }
829
830 #[test]
831 fn derive() {
832 let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
833 let key1 = EcKey::generate(&group).unwrap();
834 let key1 = PKey::from_ec_key(key1).unwrap();
835 let key2 = EcKey::generate(&group).unwrap();
836 let key2 = PKey::from_ec_key(key2).unwrap();
837
838 let mut ctx = PkeyCtx::new(&key1).unwrap();
839 ctx.derive_init().unwrap();
840 ctx.derive_set_peer(&key2).unwrap();
841
842 let mut buf = vec![];
843 ctx.derive_to_vec(&mut buf).unwrap();
844 }
845
846 #[test]
847 #[cfg(not(boringssl))]
848 fn cmac_keygen() {
849 let mut ctx = PkeyCtx::new_id(Id::CMAC).unwrap();
850 ctx.keygen_init().unwrap();
851 ctx.set_keygen_cipher(Cipher::aes_128_cbc()).unwrap();
852 ctx.set_keygen_mac_key(&hex::decode("9294727a3638bb1c13f48ef8158bfc9d").unwrap())
853 .unwrap();
854 ctx.keygen().unwrap();
855 }
856
857 #[test]
858 #[cfg(any(ossl110, boringssl, libressl360))]
859 fn hkdf() {
860 let mut ctx = PkeyCtx::new_id(Id::HKDF).unwrap();
861 ctx.derive_init().unwrap();
862 ctx.set_hkdf_md(Md::sha256()).unwrap();
863 ctx.set_hkdf_key(&hex::decode("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b").unwrap())
864 .unwrap();
865 ctx.set_hkdf_salt(&hex::decode("000102030405060708090a0b0c").unwrap())
866 .unwrap();
867 ctx.add_hkdf_info(&hex::decode("f0f1f2f3f4f5f6f7f8f9").unwrap())
868 .unwrap();
869 let mut out = [0; 42];
870 ctx.derive(Some(&mut out)).unwrap();
871
872 assert_eq!(
873 &out[..],
874 hex::decode("3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865")
875 .unwrap()
876 );
877 }
878
879 #[test]
880 #[cfg(any(ossl111, libressl360))]
881 fn hkdf_expand() {
882 let mut ctx = PkeyCtx::new_id(Id::HKDF).unwrap();
883 ctx.derive_init().unwrap();
884 ctx.set_hkdf_mode(HkdfMode::EXPAND_ONLY).unwrap();
885 ctx.set_hkdf_md(Md::sha256()).unwrap();
886 ctx.set_hkdf_key(
887 &hex::decode("077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5")
888 .unwrap(),
889 )
890 .unwrap();
891 ctx.add_hkdf_info(&hex::decode("f0f1f2f3f4f5f6f7f8f9").unwrap())
892 .unwrap();
893 let mut out = [0; 42];
894 ctx.derive(Some(&mut out)).unwrap();
895
896 assert_eq!(
897 &out[..],
898 hex::decode("3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865")
899 .unwrap()
900 );
901 }
902
903 #[test]
904 #[cfg(any(ossl111, libressl360))]
905 fn hkdf_extract() {
906 let mut ctx = PkeyCtx::new_id(Id::HKDF).unwrap();
907 ctx.derive_init().unwrap();
908 ctx.set_hkdf_mode(HkdfMode::EXTRACT_ONLY).unwrap();
909 ctx.set_hkdf_md(Md::sha256()).unwrap();
910 ctx.set_hkdf_key(&hex::decode("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b").unwrap())
911 .unwrap();
912 ctx.set_hkdf_salt(&hex::decode("000102030405060708090a0b0c").unwrap())
913 .unwrap();
914 let mut out = vec![];
915 ctx.derive_to_vec(&mut out).unwrap();
916
917 assert_eq!(
918 &out[..],
919 hex::decode("077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5")
920 .unwrap()
921 );
922 }
923
924 #[test]
925 fn verify_fail() {
926 let key1 = Rsa::generate(4096).unwrap();
927 let key1 = PKey::from_rsa(key1).unwrap();
928
929 let data = b"Some Crypto Text";
930
931 let mut ctx = PkeyCtx::new(&key1).unwrap();
932 ctx.sign_init().unwrap();
933 let mut signature = vec![];
934 ctx.sign_to_vec(data, &mut signature).unwrap();
935
936 let bad_data = b"Some Crypto text";
937
938 ctx.verify_init().unwrap();
939 let valid = ctx.verify(bad_data, &signature);
940 assert!(matches!(valid, Ok(false) | Err(_)));
941 assert!(ErrorStack::get().errors().is_empty());
942 }
943
944 #[test]
945 fn verify_fail_ec() {
946 let key1 =
947 EcKey::generate(&EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap()).unwrap();
948 let key1 = PKey::from_ec_key(key1).unwrap();
949
950 let data = b"Some Crypto Text";
951 let mut ctx = PkeyCtx::new(&key1).unwrap();
952 ctx.verify_init().unwrap();
953 assert!(matches!(ctx.verify(data, &[0; 64]), Ok(false) | Err(_)));
954 assert!(ErrorStack::get().errors().is_empty());
955 }
956
957 #[test]
958 fn test_verify_recover() {
959 let key = Rsa::generate(2048).unwrap();
960 let key = PKey::from_rsa(key).unwrap();
961
962 let digest = [
963 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
964 24, 25, 26, 27, 28, 29, 30, 31,
965 ];
966
967 let mut ctx = PkeyCtx::new(&key).unwrap();
968 ctx.sign_init().unwrap();
969 ctx.set_rsa_padding(Padding::PKCS1).unwrap();
970 ctx.set_signature_md(Md::sha256()).unwrap();
971 let mut signature = vec![];
972 ctx.sign_to_vec(&digest, &mut signature).unwrap();
973
974 // Attempt recovery of just the digest.
975 let mut ctx = PkeyCtx::new(&key).unwrap();
976 ctx.verify_recover_init().unwrap();
977 ctx.set_rsa_padding(Padding::PKCS1).unwrap();
978 ctx.set_signature_md(Md::sha256()).unwrap();
979 let length = ctx.verify_recover(&signature, None).unwrap();
980 let mut result_buf = vec![0; length];
981 let length = ctx
982 .verify_recover(&signature, Some(&mut result_buf))
983 .unwrap();
984 assert_eq!(length, digest.len());
985 // result_buf contains the digest
986 assert_eq!(result_buf[..length], digest);
987
988 // Attempt recovery of teh entire DigestInfo
989 let mut ctx = PkeyCtx::new(&key).unwrap();
990 ctx.verify_recover_init().unwrap();
991 ctx.set_rsa_padding(Padding::PKCS1).unwrap();
992 let length = ctx.verify_recover(&signature, None).unwrap();
993 let mut result_buf = vec![0; length];
994 let length = ctx
995 .verify_recover(&signature, Some(&mut result_buf))
996 .unwrap();
997 // 32-bytes of SHA256 digest + the ASN.1 DigestInfo structure == 51 bytes
998 assert_eq!(length, 51);
999 // The digest is the end of the DigestInfo structure.
1000 assert_eq!(result_buf[length - digest.len()..length], digest);
1001 }
1002}
1003