Coverage Report

Created: 2025-08-28 06:06

/rust/registry/src/index.crates.io-6f17d22bba15001f/openssl-0.10.62/src/pkey_ctx.rs
Line
Count
Source (jump to first uncovered line)
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::sign::RsaPssSaltlen;
74
use crate::{cvt, cvt_p};
75
use foreign_types::{ForeignType, ForeignTypeRef};
76
#[cfg(not(boringssl))]
77
use libc::c_int;
78
use openssl_macros::corresponds;
79
use std::convert::TryFrom;
80
use std::ptr;
81
82
/// HKDF modes of operation.
83
#[cfg(any(ossl111, libressl360))]
84
pub struct HkdfMode(c_int);
85
86
#[cfg(any(ossl111, libressl360))]
87
impl 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
108
generic_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
118
impl<T> PkeyCtx<T> {
119
    /// Creates a new pkey context using the provided key.
120
    #[corresponds(EVP_PKEY_CTX_new)]
121
    #[inline]
122
0
    pub fn new(pkey: &PKeyRef<T>) -> Result<Self, ErrorStack> {
123
        unsafe {
124
0
            let ptr = cvt_p(ffi::EVP_PKEY_CTX_new(pkey.as_ptr(), ptr::null_mut()))?;
125
0
            Ok(PkeyCtx::from_ptr(ptr))
126
        }
127
0
    }
128
}
129
130
impl PkeyCtx<()> {
131
    /// Creates a new pkey context for the specified algorithm ID.
132
    #[corresponds(EVP_PKEY_new_id)]
133
    #[inline]
134
0
    pub fn new_id(id: Id) -> Result<Self, ErrorStack> {
135
        unsafe {
136
0
            let ptr = cvt_p(ffi::EVP_PKEY_CTX_new_id(id.as_raw(), ptr::null_mut()))?;
137
0
            Ok(PkeyCtx::from_ptr(ptr))
138
        }
139
0
    }
140
}
141
142
impl<T> PkeyCtxRef<T>
143
where
144
    T: HasPublic,
145
{
146
    /// Prepares the context for encryption using the public key.
147
    #[corresponds(EVP_PKEY_encrypt_init)]
148
    #[inline]
149
0
    pub fn encrypt_init(&mut self) -> Result<(), ErrorStack> {
150
0
        unsafe {
151
0
            cvt(ffi::EVP_PKEY_encrypt_init(self.as_ptr()))?;
152
        }
153
154
0
        Ok(())
155
0
    }
156
157
    /// Prepares the context for signature verification using the public key.
158
    #[corresponds(EVP_PKEY_verify_init)]
159
    #[inline]
160
0
    pub fn verify_init(&mut self) -> Result<(), ErrorStack> {
161
0
        unsafe {
162
0
            cvt(ffi::EVP_PKEY_verify_init(self.as_ptr()))?;
163
        }
164
165
0
        Ok(())
166
0
    }
167
168
    /// Prepares the context for signature recovery using the public key.
169
    #[corresponds(EVP_PKEY_verify_recover_init)]
170
    #[inline]
171
0
    pub fn verify_recover_init(&mut self) -> Result<(), ErrorStack> {
172
0
        unsafe {
173
0
            cvt(ffi::EVP_PKEY_verify_recover_init(self.as_ptr()))?;
174
        }
175
176
0
        Ok(())
177
0
    }
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
0
    pub fn encrypt(&mut self, from: &[u8], to: Option<&mut [u8]>) -> Result<usize, ErrorStack> {
186
0
        let mut written = to.as_ref().map_or(0, |b| b.len());
187
0
        unsafe {
188
0
            cvt(ffi::EVP_PKEY_encrypt(
189
0
                self.as_ptr(),
190
0
                to.map_or(ptr::null_mut(), |b| b.as_mut_ptr()),
191
0
                &mut written,
192
0
                from.as_ptr(),
193
0
                from.len(),
194
0
            ))?;
195
        }
196
197
0
        Ok(written)
198
0
    }
199
200
    /// Like [`Self::encrypt`] but appends ciphertext to a [`Vec`].
201
0
    pub fn encrypt_to_vec(&mut self, from: &[u8], out: &mut Vec<u8>) -> Result<usize, ErrorStack> {
202
0
        let base = out.len();
203
0
        let len = self.encrypt(from, None)?;
204
0
        out.resize(base + len, 0);
205
0
        let len = self.encrypt(from, Some(&mut out[base..]))?;
206
0
        out.truncate(base + len);
207
0
        Ok(len)
208
0
    }
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
0
    pub fn verify(&mut self, data: &[u8], sig: &[u8]) -> Result<bool, ErrorStack> {
223
0
        unsafe {
224
0
            let r = ffi::EVP_PKEY_verify(
225
0
                self.as_ptr(),
226
0
                sig.as_ptr(),
227
0
                sig.len(),
228
0
                data.as_ptr(),
229
0
                data.len(),
230
0
            );
231
0
            // `EVP_PKEY_verify` is not terribly consistent about how it,
232
0
            // reports errors. It does not clearly distinguish between 0 and
233
0
            // -1, and may put errors on the stack in both cases. If there's
234
0
            // errors on the stack, we return `Err()`, else we return
235
0
            // `Ok(false)`.
236
0
            if r <= 0 {
237
0
                let errors = ErrorStack::get();
238
0
                if !errors.errors().is_empty() {
239
0
                    return Err(errors);
240
0
                }
241
0
            }
242
243
0
            Ok(r == 1)
244
        }
245
0
    }
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
0
    pub fn verify_recover(
255
0
        &mut self,
256
0
        sig: &[u8],
257
0
        to: Option<&mut [u8]>,
258
0
    ) -> Result<usize, ErrorStack> {
259
0
        let mut written = to.as_ref().map_or(0, |b| b.len());
260
0
        unsafe {
261
0
            cvt(ffi::EVP_PKEY_verify_recover(
262
0
                self.as_ptr(),
263
0
                to.map_or(ptr::null_mut(), |b| b.as_mut_ptr()),
264
0
                &mut written,
265
0
                sig.as_ptr(),
266
0
                sig.len(),
267
0
            ))?;
268
        }
269
270
0
        Ok(written)
271
0
    }
272
}
273
274
impl<T> PkeyCtxRef<T>
275
where
276
    T: HasPrivate,
277
{
278
    /// Prepares the context for decryption using the private key.
279
    #[corresponds(EVP_PKEY_decrypt_init)]
280
    #[inline]
281
0
    pub fn decrypt_init(&mut self) -> Result<(), ErrorStack> {
282
0
        unsafe {
283
0
            cvt(ffi::EVP_PKEY_decrypt_init(self.as_ptr()))?;
284
        }
285
286
0
        Ok(())
287
0
    }
288
289
    /// Prepares the context for signing using the private key.
290
    #[corresponds(EVP_PKEY_sign_init)]
291
    #[inline]
292
0
    pub fn sign_init(&mut self) -> Result<(), ErrorStack> {
293
0
        unsafe {
294
0
            cvt(ffi::EVP_PKEY_sign_init(self.as_ptr()))?;
295
        }
296
297
0
        Ok(())
298
0
    }
299
300
    /// Sets the peer key used for secret derivation.
301
    #[corresponds(EVP_PKEY_derive_set_peer)]
302
0
    pub fn derive_set_peer<U>(&mut self, key: &PKeyRef<U>) -> Result<(), ErrorStack>
303
0
    where
304
0
        U: HasPublic,
305
0
    {
306
0
        unsafe {
307
0
            cvt(ffi::EVP_PKEY_derive_set_peer(self.as_ptr(), key.as_ptr()))?;
308
        }
309
310
0
        Ok(())
311
0
    }
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
0
    pub fn decrypt(&mut self, from: &[u8], to: Option<&mut [u8]>) -> Result<usize, ErrorStack> {
320
0
        let mut written = to.as_ref().map_or(0, |b| b.len());
321
0
        unsafe {
322
0
            cvt(ffi::EVP_PKEY_decrypt(
323
0
                self.as_ptr(),
324
0
                to.map_or(ptr::null_mut(), |b| b.as_mut_ptr()),
325
0
                &mut written,
326
0
                from.as_ptr(),
327
0
                from.len(),
328
0
            ))?;
329
        }
330
331
0
        Ok(written)
332
0
    }
333
334
    /// Like [`Self::decrypt`] but appends plaintext to a [`Vec`].
335
0
    pub fn decrypt_to_vec(&mut self, from: &[u8], out: &mut Vec<u8>) -> Result<usize, ErrorStack> {
336
0
        let base = out.len();
337
0
        let len = self.decrypt(from, None)?;
338
0
        out.resize(base + len, 0);
339
0
        let len = self.decrypt(from, Some(&mut out[base..]))?;
340
0
        out.truncate(base + len);
341
0
        Ok(len)
342
0
    }
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
0
    pub fn sign(&mut self, data: &[u8], sig: Option<&mut [u8]>) -> Result<usize, ErrorStack> {
356
0
        let mut written = sig.as_ref().map_or(0, |b| b.len());
357
0
        unsafe {
358
0
            cvt(ffi::EVP_PKEY_sign(
359
0
                self.as_ptr(),
360
0
                sig.map_or(ptr::null_mut(), |b| b.as_mut_ptr()),
361
0
                &mut written,
362
0
                data.as_ptr(),
363
0
                data.len(),
364
0
            ))?;
365
        }
366
367
0
        Ok(written)
368
0
    }
369
370
    /// Like [`Self::sign`] but appends the signature to a [`Vec`].
371
0
    pub fn sign_to_vec(&mut self, data: &[u8], sig: &mut Vec<u8>) -> Result<usize, ErrorStack> {
372
0
        let base = sig.len();
373
0
        let len = self.sign(data, None)?;
374
0
        sig.resize(base + len, 0);
375
0
        let len = self.sign(data, Some(&mut sig[base..]))?;
376
0
        sig.truncate(base + len);
377
0
        Ok(len)
378
0
    }
379
}
380
381
impl<T> PkeyCtxRef<T> {
382
    /// Prepares the context for shared secret derivation.
383
    #[corresponds(EVP_PKEY_derive_init)]
384
    #[inline]
385
0
    pub fn derive_init(&mut self) -> Result<(), ErrorStack> {
386
0
        unsafe {
387
0
            cvt(ffi::EVP_PKEY_derive_init(self.as_ptr()))?;
388
        }
389
390
0
        Ok(())
391
0
    }
392
393
    /// Prepares the context for key generation.
394
    #[corresponds(EVP_PKEY_keygen_init)]
395
    #[inline]
396
0
    pub fn keygen_init(&mut self) -> Result<(), ErrorStack> {
397
0
        unsafe {
398
0
            cvt(ffi::EVP_PKEY_keygen_init(self.as_ptr()))?;
399
        }
400
401
0
        Ok(())
402
0
    }
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
0
    pub fn set_signature_md(&self, md: &MdRef) -> Result<(), ErrorStack> {
411
0
        unsafe {
412
0
            cvt(ffi::EVP_PKEY_CTX_set_signature_md(
413
0
                self.as_ptr(),
414
0
                md.as_ptr(),
415
0
            ))?;
416
        }
417
0
        Ok(())
418
0
    }
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
0
    pub fn rsa_padding(&self) -> Result<Padding, ErrorStack> {
426
0
        let mut pad = 0;
427
0
        unsafe {
428
0
            cvt(ffi::EVP_PKEY_CTX_get_rsa_padding(self.as_ptr(), &mut pad))?;
429
        }
430
431
0
        Ok(Padding::from_raw(pad))
432
0
    }
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
0
    pub fn set_rsa_padding(&mut self, padding: Padding) -> Result<(), ErrorStack> {
440
0
        unsafe {
441
0
            cvt(ffi::EVP_PKEY_CTX_set_rsa_padding(
442
0
                self.as_ptr(),
443
0
                padding.as_raw(),
444
0
            ))?;
445
        }
446
447
0
        Ok(())
448
0
    }
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
0
    pub fn set_rsa_pss_saltlen(&mut self, len: RsaPssSaltlen) -> Result<(), ErrorStack> {
456
0
        unsafe {
457
0
            cvt(ffi::EVP_PKEY_CTX_set_rsa_pss_saltlen(
458
0
                self.as_ptr(),
459
0
                len.as_raw(),
460
0
            ))
461
0
            .map(|_| ())
462
0
        }
463
0
    }
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
0
    pub fn set_rsa_mgf1_md(&mut self, md: &MdRef) -> Result<(), ErrorStack> {
471
0
        unsafe {
472
0
            cvt(ffi::EVP_PKEY_CTX_set_rsa_mgf1_md(
473
0
                self.as_ptr(),
474
0
                md.as_ptr(),
475
0
            ))?;
476
        }
477
478
0
        Ok(())
479
0
    }
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
0
    pub fn set_rsa_oaep_md(&mut self, md: &MdRef) -> Result<(), ErrorStack> {
488
0
        unsafe {
489
0
            cvt(ffi::EVP_PKEY_CTX_set_rsa_oaep_md(
490
0
                self.as_ptr(),
491
0
                md.as_ptr() as *mut _,
492
0
            ))?;
493
        }
494
495
0
        Ok(())
496
0
    }
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
0
    pub fn set_rsa_oaep_label(&mut self, label: &[u8]) -> Result<(), ErrorStack> {
504
        use crate::LenType;
505
0
        let len = LenType::try_from(label.len()).unwrap();
506
0
507
0
        unsafe {
508
0
            let p = ffi::OPENSSL_malloc(label.len() as _);
509
0
            ptr::copy_nonoverlapping(label.as_ptr(), p as *mut _, label.len());
510
0
511
0
            let r = cvt(ffi::EVP_PKEY_CTX_set0_rsa_oaep_label(
512
0
                self.as_ptr(),
513
0
                p as *mut _,
514
0
                len,
515
0
            ));
516
0
            if r.is_err() {
517
0
                ffi::OPENSSL_free(p);
518
0
            }
519
0
            r?;
520
        }
521
522
0
        Ok(())
523
0
    }
524
525
    /// Sets the cipher used during key generation.
526
    #[cfg(not(boringssl))]
527
    #[corresponds(EVP_PKEY_CTX_ctrl)]
528
    #[inline]
529
0
    pub fn set_keygen_cipher(&mut self, cipher: &CipherRef) -> Result<(), ErrorStack> {
530
0
        unsafe {
531
0
            cvt(ffi::EVP_PKEY_CTX_ctrl(
532
0
                self.as_ptr(),
533
0
                -1,
534
0
                ffi::EVP_PKEY_OP_KEYGEN,
535
0
                ffi::EVP_PKEY_CTRL_CIPHER,
536
0
                0,
537
0
                cipher.as_ptr() as *mut _,
538
0
            ))?;
539
        }
540
541
0
        Ok(())
542
0
    }
543
544
    /// Sets the key MAC key used during key generation.
545
    #[cfg(not(boringssl))]
546
    #[corresponds(EVP_PKEY_CTX_ctrl)]
547
    #[inline]
548
0
    pub fn set_keygen_mac_key(&mut self, key: &[u8]) -> Result<(), ErrorStack> {
549
0
        let len = c_int::try_from(key.len()).unwrap();
550
0
551
0
        unsafe {
552
0
            cvt(ffi::EVP_PKEY_CTX_ctrl(
553
0
                self.as_ptr(),
554
0
                -1,
555
0
                ffi::EVP_PKEY_OP_KEYGEN,
556
0
                ffi::EVP_PKEY_CTRL_SET_MAC_KEY,
557
0
                len,
558
0
                key.as_ptr() as *mut _,
559
0
            ))?;
560
        }
561
562
0
        Ok(())
563
0
    }
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
0
    pub fn set_hkdf_md(&mut self, digest: &MdRef) -> Result<(), ErrorStack> {
572
0
        unsafe {
573
0
            cvt(ffi::EVP_PKEY_CTX_set_hkdf_md(
574
0
                self.as_ptr(),
575
0
                digest.as_ptr(),
576
0
            ))?;
577
        }
578
579
0
        Ok(())
580
0
    }
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
0
    pub fn set_hkdf_mode(&mut self, mode: HkdfMode) -> Result<(), ErrorStack> {
595
0
        unsafe {
596
0
            cvt(ffi::EVP_PKEY_CTX_set_hkdf_mode(self.as_ptr(), mode.0))?;
597
        }
598
599
0
        Ok(())
600
0
    }
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
0
    pub fn set_hkdf_key(&mut self, key: &[u8]) -> Result<(), ErrorStack> {
614
0
        #[cfg(not(boringssl))]
615
0
        let len = c_int::try_from(key.len()).unwrap();
616
0
        #[cfg(boringssl)]
617
0
        let len = key.len();
618
0
619
0
        unsafe {
620
0
            cvt(ffi::EVP_PKEY_CTX_set1_hkdf_key(
621
0
                self.as_ptr(),
622
0
                key.as_ptr(),
623
0
                len,
624
0
            ))?;
625
        }
626
627
0
        Ok(())
628
0
    }
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
0
    pub fn set_hkdf_salt(&mut self, salt: &[u8]) -> Result<(), ErrorStack> {
639
0
        #[cfg(not(boringssl))]
640
0
        let len = c_int::try_from(salt.len()).unwrap();
641
0
        #[cfg(boringssl)]
642
0
        let len = salt.len();
643
0
644
0
        unsafe {
645
0
            cvt(ffi::EVP_PKEY_CTX_set1_hkdf_salt(
646
0
                self.as_ptr(),
647
0
                salt.as_ptr(),
648
0
                len,
649
0
            ))?;
650
        }
651
652
0
        Ok(())
653
0
    }
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
0
    pub fn add_hkdf_info(&mut self, info: &[u8]) -> Result<(), ErrorStack> {
664
0
        #[cfg(not(boringssl))]
665
0
        let len = c_int::try_from(info.len()).unwrap();
666
0
        #[cfg(boringssl)]
667
0
        let len = info.len();
668
0
669
0
        unsafe {
670
0
            cvt(ffi::EVP_PKEY_CTX_add1_hkdf_info(
671
0
                self.as_ptr(),
672
0
                info.as_ptr(),
673
0
                len,
674
0
            ))?;
675
        }
676
677
0
        Ok(())
678
0
    }
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
0
    pub fn derive(&mut self, buf: Option<&mut [u8]>) -> Result<usize, ErrorStack> {
685
0
        let mut len = buf.as_ref().map_or(0, |b| b.len());
686
0
        unsafe {
687
0
            cvt(ffi::EVP_PKEY_derive(
688
0
                self.as_ptr(),
689
0
                buf.map_or(ptr::null_mut(), |b| b.as_mut_ptr()),
690
0
                &mut len,
691
0
            ))?;
692
        }
693
694
0
        Ok(len)
695
0
    }
696
697
    /// Like [`Self::derive`] but appends the secret to a [`Vec`].
698
0
    pub fn derive_to_vec(&mut self, buf: &mut Vec<u8>) -> Result<usize, ErrorStack> {
699
0
        let base = buf.len();
700
0
        let len = self.derive(None)?;
701
0
        buf.resize(base + len, 0);
702
0
        let len = self.derive(Some(&mut buf[base..]))?;
703
0
        buf.truncate(base + len);
704
0
        Ok(len)
705
0
    }
706
707
    /// Generates a new public/private keypair.
708
    #[corresponds(EVP_PKEY_keygen)]
709
    #[inline]
710
0
    pub fn keygen(&mut self) -> Result<PKey<Private>, ErrorStack> {
711
0
        unsafe {
712
0
            let mut key = ptr::null_mut();
713
0
            cvt(ffi::EVP_PKEY_keygen(self.as_ptr(), &mut key))?;
714
0
            Ok(PKey::from_ptr(key))
715
        }
716
0
    }
717
}
718
719
#[cfg(test)]
720
mod 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
}