openssl/
encrypt.rs

1//! Message encryption.
2//!
3//! The [`Encrypter`] allows for encryption of data given a public key. The [`Decrypter`] can be
4//! used with the corresponding private key to decrypt the data.
5//!
6//! # Examples
7//!
8//! Encrypt and decrypt data given an RSA keypair:
9//!
10//! ```rust
11//! use openssl::encrypt::{Encrypter, Decrypter};
12//! use openssl::rsa::{Rsa, Padding};
13//! use openssl::pkey::PKey;
14//!
15//! // Generate a keypair
16//! let keypair = Rsa::generate(2048).unwrap();
17//! let keypair = PKey::from_rsa(keypair).unwrap();
18//!
19//! let data = b"hello, world!";
20//!
21//! // Encrypt the data with RSA PKCS1
22//! let mut encrypter = Encrypter::new(&keypair).unwrap();
23//! encrypter.set_rsa_padding(Padding::PKCS1).unwrap();
24//! // Create an output buffer
25//! let buffer_len = encrypter.encrypt_len(data).unwrap();
26//! let mut encrypted = vec![0; buffer_len];
27//! // Encrypt and truncate the buffer
28//! let encrypted_len = encrypter.encrypt(data, &mut encrypted).unwrap();
29//! encrypted.truncate(encrypted_len);
30//!
31//! // Decrypt the data
32//! let mut decrypter = Decrypter::new(&keypair).unwrap();
33//! decrypter.set_rsa_padding(Padding::PKCS1).unwrap();
34//! // Create an output buffer
35//! let buffer_len = decrypter.decrypt_len(&encrypted).unwrap();
36//! let mut decrypted = vec![0; buffer_len];
37//! // Encrypt and truncate the buffer
38//! let decrypted_len = decrypter.decrypt(&encrypted, &mut decrypted).unwrap();
39//! decrypted.truncate(decrypted_len);
40//! assert_eq!(&*decrypted, data);
41//! ```
42use std::{marker::PhantomData, ptr};
43
44use crate::error::ErrorStack;
45use crate::hash::MessageDigest;
46use crate::pkey::{HasPrivate, HasPublic, PKeyRef};
47use crate::rsa::Padding;
48use crate::{cvt, cvt_p};
49use foreign_types::ForeignTypeRef;
50use openssl_macros::corresponds;
51
52/// A type which encrypts data.
53pub struct Encrypter<'a> {
54    pctx: *mut ffi::EVP_PKEY_CTX,
55    _p: PhantomData<&'a ()>,
56}
57
58unsafe impl Sync for Encrypter<'_> {}
59unsafe impl Send for Encrypter<'_> {}
60
61impl Drop for Encrypter<'_> {
62    fn drop(&mut self) {
63        unsafe {
64            ffi::EVP_PKEY_CTX_free(self.pctx);
65        }
66    }
67}
68
69impl<'a> Encrypter<'a> {
70    /// Creates a new `Encrypter`.
71    #[corresponds(EVP_PKEY_encrypt_init)]
72    pub fn new<T>(pkey: &'a PKeyRef<T>) -> Result<Encrypter<'a>, ErrorStack>
73    where
74        T: HasPublic,
75    {
76        unsafe {
77            ffi::init();
78
79            let pctx = cvt_p(ffi::EVP_PKEY_CTX_new(pkey.as_ptr(), ptr::null_mut()))?;
80            let r = ffi::EVP_PKEY_encrypt_init(pctx);
81            if r != 1 {
82                ffi::EVP_PKEY_CTX_free(pctx);
83                return Err(ErrorStack::get());
84            }
85
86            Ok(Encrypter {
87                pctx,
88                _p: PhantomData,
89            })
90        }
91    }
92
93    /// Returns the RSA padding mode in use.
94    ///
95    /// This is only useful for RSA keys.
96    ///
97    /// This corresponds to `EVP_PKEY_CTX_get_rsa_padding`.
98    pub fn rsa_padding(&self) -> Result<Padding, ErrorStack> {
99        unsafe {
100            let mut pad = 0;
101            cvt(ffi::EVP_PKEY_CTX_get_rsa_padding(self.pctx, &mut pad))
102                .map(|_| Padding::from_raw(pad))
103        }
104    }
105
106    /// Sets the RSA padding mode.
107    ///
108    /// This is only useful for RSA keys.
109    #[corresponds(EVP_PKEY_CTX_set_rsa_padding)]
110    pub fn set_rsa_padding(&mut self, padding: Padding) -> Result<(), ErrorStack> {
111        unsafe {
112            cvt(ffi::EVP_PKEY_CTX_set_rsa_padding(
113                self.pctx,
114                padding.as_raw(),
115            ))
116            .map(|_| ())
117        }
118    }
119
120    /// Sets the RSA MGF1 algorithm.
121    ///
122    /// This is only useful for RSA keys.
123    #[corresponds(EVP_PKEY_CTX_set_rsa_mgf1_md)]
124    pub fn set_rsa_mgf1_md(&mut self, md: MessageDigest) -> Result<(), ErrorStack> {
125        unsafe {
126            cvt(ffi::EVP_PKEY_CTX_set_rsa_mgf1_md(
127                self.pctx,
128                md.as_ptr() as *mut _,
129            ))
130            .map(|_| ())
131        }
132    }
133
134    /// Sets the RSA OAEP algorithm.
135    ///
136    /// This is only useful for RSA keys.
137    #[corresponds(EVP_PKEY_CTX_set_rsa_oaep_md)]
138    pub fn set_rsa_oaep_md(&mut self, md: MessageDigest) -> Result<(), ErrorStack> {
139        unsafe {
140            cvt(ffi::EVP_PKEY_CTX_set_rsa_oaep_md(
141                self.pctx,
142                md.as_ptr() as *mut _,
143            ))
144            .map(|_| ())
145        }
146    }
147
148    /// Sets the RSA OAEP label.
149    ///
150    /// This is only useful for RSA keys.
151    #[corresponds(EVP_PKEY_CTX_set0_rsa_oaep_label)]
152    pub fn set_rsa_oaep_label(&mut self, label: &[u8]) -> Result<(), ErrorStack> {
153        unsafe {
154            let p = cvt_p(ffi::OPENSSL_malloc(label.len() as _))?;
155            ptr::copy_nonoverlapping(label.as_ptr(), p as *mut u8, label.len());
156
157            cvt(ffi::EVP_PKEY_CTX_set0_rsa_oaep_label(
158                self.pctx,
159                p.cast(),
160                label.len() as _,
161            ))
162            .map(|_| ())
163            .map_err(|e| {
164                ffi::OPENSSL_free(p);
165                e
166            })
167        }
168    }
169
170    /// Performs public key encryption.
171    ///
172    /// In order to know the size needed for the output buffer, use [`encrypt_len`](Encrypter::encrypt_len).
173    /// Note that the length of the output buffer can be greater of the length of the encoded data.
174    /// ```
175    /// # use openssl::{
176    /// #   encrypt::Encrypter,
177    /// #   pkey::PKey,
178    /// #   rsa::{Rsa, Padding},
179    /// # };
180    /// #
181    /// # let key = include_bytes!("../test/rsa.pem");
182    /// # let private_key = Rsa::private_key_from_pem(key).unwrap();
183    /// # let pkey = PKey::from_rsa(private_key).unwrap();
184    /// # let input = b"hello world".to_vec();
185    /// #
186    /// let mut encrypter = Encrypter::new(&pkey).unwrap();
187    /// encrypter.set_rsa_padding(Padding::PKCS1).unwrap();
188    ///
189    /// // Get the length of the output buffer
190    /// let buffer_len = encrypter.encrypt_len(&input).unwrap();
191    /// let mut encoded = vec![0u8; buffer_len];
192    ///
193    /// // Encode the data and get its length
194    /// let encoded_len = encrypter.encrypt(&input, &mut encoded).unwrap();
195    ///
196    /// // Use only the part of the buffer with the encoded data
197    /// let encoded = &encoded[..encoded_len];
198    /// ```
199    ///
200    #[corresponds(EVP_PKEY_encrypt)]
201    pub fn encrypt(&self, from: &[u8], to: &mut [u8]) -> Result<usize, ErrorStack> {
202        let mut written = to.len();
203        unsafe {
204            cvt(ffi::EVP_PKEY_encrypt(
205                self.pctx,
206                to.as_mut_ptr(),
207                &mut written,
208                from.as_ptr(),
209                from.len(),
210            ))?;
211        }
212
213        Ok(written)
214    }
215
216    /// Gets the size of the buffer needed to encrypt the input data.
217    ///
218    /// This corresponds to `EVP_PKEY_encrypt` called with a null pointer as output argument.
219    #[corresponds(EVP_PKEY_encrypt)]
220    pub fn encrypt_len(&self, from: &[u8]) -> Result<usize, ErrorStack> {
221        let mut written = 0;
222        unsafe {
223            cvt(ffi::EVP_PKEY_encrypt(
224                self.pctx,
225                ptr::null_mut(),
226                &mut written,
227                from.as_ptr(),
228                from.len(),
229            ))?;
230        }
231
232        Ok(written)
233    }
234}
235
236/// A type which decrypts data.
237pub struct Decrypter<'a> {
238    pctx: *mut ffi::EVP_PKEY_CTX,
239    _p: PhantomData<&'a ()>,
240}
241
242unsafe impl Sync for Decrypter<'_> {}
243unsafe impl Send for Decrypter<'_> {}
244
245impl Drop for Decrypter<'_> {
246    fn drop(&mut self) {
247        unsafe {
248            ffi::EVP_PKEY_CTX_free(self.pctx);
249        }
250    }
251}
252
253impl<'a> Decrypter<'a> {
254    /// Creates a new `Decrypter`.
255    #[corresponds(EVP_PKEY_decrypt_init)]
256    pub fn new<T>(pkey: &'a PKeyRef<T>) -> Result<Decrypter<'a>, ErrorStack>
257    where
258        T: HasPrivate,
259    {
260        unsafe {
261            ffi::init();
262
263            let pctx = cvt_p(ffi::EVP_PKEY_CTX_new(pkey.as_ptr(), ptr::null_mut()))?;
264            let r = ffi::EVP_PKEY_decrypt_init(pctx);
265            if r != 1 {
266                ffi::EVP_PKEY_CTX_free(pctx);
267                return Err(ErrorStack::get());
268            }
269
270            Ok(Decrypter {
271                pctx,
272                _p: PhantomData,
273            })
274        }
275    }
276
277    /// Returns the RSA padding mode in use.
278    ///
279    /// This is only useful for RSA keys.
280    ///
281    /// This corresponds to `EVP_PKEY_CTX_get_rsa_padding`.
282    pub fn rsa_padding(&self) -> Result<Padding, ErrorStack> {
283        unsafe {
284            let mut pad = 0;
285            cvt(ffi::EVP_PKEY_CTX_get_rsa_padding(self.pctx, &mut pad))
286                .map(|_| Padding::from_raw(pad))
287        }
288    }
289
290    /// Sets the RSA padding mode.
291    ///
292    /// This is only useful for RSA keys.
293    #[corresponds(EVP_PKEY_CTX_set_rsa_padding)]
294    pub fn set_rsa_padding(&mut self, padding: Padding) -> Result<(), ErrorStack> {
295        unsafe {
296            cvt(ffi::EVP_PKEY_CTX_set_rsa_padding(
297                self.pctx,
298                padding.as_raw(),
299            ))
300            .map(|_| ())
301        }
302    }
303
304    /// Sets the RSA MGF1 algorithm.
305    ///
306    /// This is only useful for RSA keys.
307    #[corresponds(EVP_PKEY_CTX_set_rsa_mgf1_md)]
308    pub fn set_rsa_mgf1_md(&mut self, md: MessageDigest) -> Result<(), ErrorStack> {
309        unsafe {
310            cvt(ffi::EVP_PKEY_CTX_set_rsa_mgf1_md(
311                self.pctx,
312                md.as_ptr() as *mut _,
313            ))
314            .map(|_| ())
315        }
316    }
317
318    /// Sets the RSA OAEP algorithm.
319    ///
320    /// This is only useful for RSA keys.
321    #[corresponds(EVP_PKEY_CTX_set_rsa_oaep_md)]
322    pub fn set_rsa_oaep_md(&mut self, md: MessageDigest) -> Result<(), ErrorStack> {
323        unsafe {
324            cvt(ffi::EVP_PKEY_CTX_set_rsa_oaep_md(
325                self.pctx,
326                md.as_ptr() as *mut _,
327            ))
328            .map(|_| ())
329        }
330    }
331
332    /// Sets the RSA OAEP label.
333    ///
334    /// This is only useful for RSA keys.
335    #[corresponds(EVP_PKEY_CTX_set0_rsa_oaep_label)]
336    pub fn set_rsa_oaep_label(&mut self, label: &[u8]) -> Result<(), ErrorStack> {
337        unsafe {
338            let p = cvt_p(ffi::OPENSSL_malloc(label.len() as _))?;
339            ptr::copy_nonoverlapping(label.as_ptr(), p as *mut u8, label.len());
340
341            cvt(ffi::EVP_PKEY_CTX_set0_rsa_oaep_label(
342                self.pctx,
343                p.cast(),
344                label.len() as _,
345            ))
346            .map(|_| ())
347            .map_err(|e| {
348                ffi::OPENSSL_free(p);
349                e
350            })
351        }
352    }
353
354    /// Performs public key decryption.
355    ///
356    /// In order to know the size needed for the output buffer, use [`decrypt_len`](Decrypter::decrypt_len).
357    /// Note that the length of the output buffer can be greater of the length of the decoded data.
358    /// ```
359    /// # use openssl::{
360    /// #   encrypt::Decrypter,
361    /// #   pkey::PKey,
362    /// #   rsa::{Rsa, Padding},
363    /// # };
364    /// #
365    /// # const INPUT: &[u8] = b"\
366    /// #     \x26\xa1\xc1\x13\xc5\x7f\xb4\x9f\xa0\xb4\xde\x61\x5e\x2e\xc6\xfb\x76\x5c\xd1\x2b\x5f\
367    /// #     \x1d\x36\x60\xfa\xf8\xe8\xb3\x21\xf4\x9c\x70\xbc\x03\xea\xea\xac\xce\x4b\xb3\xf6\x45\
368    /// #     \xcc\xb3\x80\x9e\xa8\xf7\xc3\x5d\x06\x12\x7a\xa3\x0c\x30\x67\xf1\xe7\x94\x6c\xf6\x26\
369    /// #     \xac\x28\x17\x59\x69\xe1\xdc\xed\x7e\xc0\xe9\x62\x57\x49\xce\xdd\x13\x07\xde\x18\x03\
370    /// #     \x0f\x9d\x61\x65\xb9\x23\x8c\x78\x4b\xad\x23\x49\x75\x47\x64\xa0\xa0\xa2\x90\xc1\x49\
371    /// #     \x1b\x05\x24\xc2\xe9\x2c\x0d\x49\x78\x72\x61\x72\xed\x8b\x6f\x8a\xe8\xca\x05\x5c\x58\
372    /// #     \xd6\x95\xd6\x7b\xe3\x2d\x0d\xaa\x3e\x6d\x3c\x9a\x1c\x1d\xb4\x6c\x42\x9d\x9a\x82\x55\
373    /// #     \xd9\xde\xc8\x08\x7b\x17\xac\xd7\xaf\x86\x7b\x69\x9e\x3c\xf4\x5e\x1c\x39\x52\x6d\x62\
374    /// #     \x50\x51\xbd\xa6\xc8\x4e\xe9\x34\xf0\x37\x0d\xa9\xa9\x77\xe6\xf5\xc2\x47\x2d\xa8\xee\
375    /// #     \x3f\x69\x78\xff\xa9\xdc\x70\x22\x20\x9a\x5c\x9b\x70\x15\x90\xd3\xb4\x0e\x54\x9e\x48\
376    /// #     \xed\xb6\x2c\x88\xfc\xb4\xa9\x37\x10\xfa\x71\xb2\xec\x75\xe7\xe7\x0e\xf4\x60\x2c\x7b\
377    /// #     \x58\xaf\xa0\x53\xbd\x24\xf1\x12\xe3\x2e\x99\x25\x0a\x54\x54\x9d\xa1\xdb\xca\x41\x85\
378    /// #     \xf4\x62\x78\x64";
379    /// #
380    /// # let key = include_bytes!("../test/rsa.pem");
381    /// # let private_key = Rsa::private_key_from_pem(key).unwrap();
382    /// # let pkey = PKey::from_rsa(private_key).unwrap();
383    /// # let input = INPUT.to_vec();
384    /// #
385    /// let mut decrypter = Decrypter::new(&pkey).unwrap();
386    /// decrypter.set_rsa_padding(Padding::PKCS1).unwrap();
387    ///
388    /// // Get the length of the output buffer
389    /// let buffer_len = decrypter.decrypt_len(&input).unwrap();
390    /// let mut decoded = vec![0u8; buffer_len];
391    ///
392    /// // Decrypt the data and get its length
393    /// let decoded_len = decrypter.decrypt(&input, &mut decoded).unwrap();
394    ///
395    /// // Use only the part of the buffer with the decrypted data
396    /// let decoded = &decoded[..decoded_len];
397    /// ```
398    ///
399    #[corresponds(EVP_PKEY_decrypt)]
400    pub fn decrypt(&self, from: &[u8], to: &mut [u8]) -> Result<usize, ErrorStack> {
401        let mut written = to.len();
402        unsafe {
403            cvt(ffi::EVP_PKEY_decrypt(
404                self.pctx,
405                to.as_mut_ptr(),
406                &mut written,
407                from.as_ptr(),
408                from.len(),
409            ))?;
410        }
411
412        Ok(written)
413    }
414
415    /// Gets the size of the buffer needed to decrypt the input data.
416    ///
417    /// This corresponds to `EVP_PKEY_decrypt` called with a null pointer as output argument.
418    #[corresponds(EVP_PKEY_decrypt)]
419    pub fn decrypt_len(&self, from: &[u8]) -> Result<usize, ErrorStack> {
420        let mut written = 0;
421        unsafe {
422            cvt(ffi::EVP_PKEY_decrypt(
423                self.pctx,
424                ptr::null_mut(),
425                &mut written,
426                from.as_ptr(),
427                from.len(),
428            ))?;
429        }
430
431        Ok(written)
432    }
433}
434
435#[cfg(test)]
436mod test {
437    use hex::FromHex;
438
439    use crate::encrypt::{Decrypter, Encrypter};
440    use crate::hash::MessageDigest;
441    use crate::pkey::PKey;
442    use crate::rsa::{Padding, Rsa};
443
444    const INPUT: &str =
445        "65794a68624763694f694a53557a49314e694a392e65794a7063334d694f694a71623255694c41304b49434a6c\
446         654841694f6a457a4d4441344d546b7a4f44417344516f67496d6830644841364c79396c654746746347786c4c\
447         6d4e76625339706331397962323930496a7030636e566c6651";
448
449    #[test]
450    fn rsa_encrypt_decrypt() {
451        let key = include_bytes!("../test/rsa.pem");
452        let private_key = Rsa::private_key_from_pem(key).unwrap();
453        let pkey = PKey::from_rsa(private_key).unwrap();
454
455        let mut encrypter = Encrypter::new(&pkey).unwrap();
456        encrypter.set_rsa_padding(Padding::PKCS1).unwrap();
457        let input = Vec::from_hex(INPUT).unwrap();
458        let buffer_len = encrypter.encrypt_len(&input).unwrap();
459        let mut encoded = vec![0u8; buffer_len];
460        let encoded_len = encrypter.encrypt(&input, &mut encoded).unwrap();
461        let encoded = &encoded[..encoded_len];
462
463        let mut decrypter = Decrypter::new(&pkey).unwrap();
464        decrypter.set_rsa_padding(Padding::PKCS1).unwrap();
465        let buffer_len = decrypter.decrypt_len(encoded).unwrap();
466        let mut decoded = vec![0u8; buffer_len];
467        let decoded_len = decrypter.decrypt(encoded, &mut decoded).unwrap();
468        let decoded = &decoded[..decoded_len];
469
470        assert_eq!(decoded, &*input);
471    }
472
473    #[test]
474    fn rsa_encrypt_decrypt_with_sha256() {
475        let key = include_bytes!("../test/rsa.pem");
476        let private_key = Rsa::private_key_from_pem(key).unwrap();
477        let pkey = PKey::from_rsa(private_key).unwrap();
478
479        let md = MessageDigest::sha256();
480
481        let mut encrypter = Encrypter::new(&pkey).unwrap();
482        encrypter.set_rsa_padding(Padding::PKCS1_OAEP).unwrap();
483        encrypter.set_rsa_oaep_md(md).unwrap();
484        encrypter.set_rsa_mgf1_md(md).unwrap();
485        let input = Vec::from_hex(INPUT).unwrap();
486        let buffer_len = encrypter.encrypt_len(&input).unwrap();
487        let mut encoded = vec![0u8; buffer_len];
488        let encoded_len = encrypter.encrypt(&input, &mut encoded).unwrap();
489        let encoded = &encoded[..encoded_len];
490
491        let mut decrypter = Decrypter::new(&pkey).unwrap();
492        decrypter.set_rsa_padding(Padding::PKCS1_OAEP).unwrap();
493        decrypter.set_rsa_oaep_md(md).unwrap();
494        decrypter.set_rsa_mgf1_md(md).unwrap();
495        let buffer_len = decrypter.decrypt_len(encoded).unwrap();
496        let mut decoded = vec![0u8; buffer_len];
497        let decoded_len = decrypter.decrypt(encoded, &mut decoded).unwrap();
498        let decoded = &decoded[..decoded_len];
499
500        assert_eq!(decoded, &*input);
501    }
502
503    #[test]
504    fn rsa_encrypt_decrypt_oaep_label() {
505        let key = include_bytes!("../test/rsa.pem");
506        let private_key = Rsa::private_key_from_pem(key).unwrap();
507        let pkey = PKey::from_rsa(private_key).unwrap();
508
509        let mut encrypter = Encrypter::new(&pkey).unwrap();
510        encrypter.set_rsa_padding(Padding::PKCS1_OAEP).unwrap();
511        encrypter.set_rsa_oaep_label(b"test_oaep_label").unwrap();
512        let input = Vec::from_hex(INPUT).unwrap();
513        let buffer_len = encrypter.encrypt_len(&input).unwrap();
514        let mut encoded = vec![0u8; buffer_len];
515        let encoded_len = encrypter.encrypt(&input, &mut encoded).unwrap();
516        let encoded = &encoded[..encoded_len];
517
518        let mut decrypter = Decrypter::new(&pkey).unwrap();
519        decrypter.set_rsa_padding(Padding::PKCS1_OAEP).unwrap();
520        decrypter.set_rsa_oaep_label(b"test_oaep_label").unwrap();
521        let buffer_len = decrypter.decrypt_len(encoded).unwrap();
522        let mut decoded = vec![0u8; buffer_len];
523        let decoded_len = decrypter.decrypt(encoded, &mut decoded).unwrap();
524        let decoded = &decoded[..decoded_len];
525
526        assert_eq!(decoded, &*input);
527
528        decrypter.set_rsa_oaep_label(b"wrong_oaep_label").unwrap();
529        let buffer_len = decrypter.decrypt_len(encoded).unwrap();
530        let mut decoded = vec![0u8; buffer_len];
531
532        assert!(decrypter.decrypt(encoded, &mut decoded).is_err());
533    }
534}