Coverage Report

Created: 2024-05-20 06:38

/rust/registry/src/index.crates.io-6f17d22bba15001f/openssl-0.10.62/src/cipher_ctx.rs
Line
Count
Source (jump to first uncovered line)
1
//! The symmetric encryption context.
2
//!
3
//! # Examples
4
//!
5
//! Encrypt data with AES128 CBC
6
//!
7
//! ```
8
//! use openssl::cipher::Cipher;
9
//! use openssl::cipher_ctx::CipherCtx;
10
//!
11
//! let cipher = Cipher::aes_128_cbc();
12
//! let data = b"Some Crypto Text";
13
//! let key = b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F";
14
//! let iv = b"\x00\x01\x02\x03\x04\x05\x06\x07\x00\x01\x02\x03\x04\x05\x06\x07";
15
//!
16
//! let mut ctx = CipherCtx::new().unwrap();
17
//! ctx.encrypt_init(Some(cipher), Some(key), Some(iv)).unwrap();
18
//!
19
//! let mut ciphertext = vec![];
20
//! ctx.cipher_update_vec(data, &mut ciphertext).unwrap();
21
//! ctx.cipher_final_vec(&mut ciphertext).unwrap();
22
//!
23
//! assert_eq!(
24
//!     b"\xB4\xB9\xE7\x30\xD6\xD6\xF7\xDE\x77\x3F\x1C\xFF\xB3\x3E\x44\x5A\x91\xD7\x27\x62\x87\x4D\
25
//!       \xFB\x3C\x5E\xC4\x59\x72\x4A\xF4\x7C\xA1",
26
//!     &ciphertext[..],
27
//! );
28
//! ```
29
//!
30
//! Decrypt data with AES128 CBC
31
//!
32
//! ```
33
//! use openssl::cipher::Cipher;
34
//! use openssl::cipher_ctx::CipherCtx;
35
//!
36
//! let cipher = Cipher::aes_128_cbc();
37
//! let data = b"\xB4\xB9\xE7\x30\xD6\xD6\xF7\xDE\x77\x3F\x1C\xFF\xB3\x3E\x44\x5A\x91\xD7\x27\x62\
38
//!              \x87\x4D\xFB\x3C\x5E\xC4\x59\x72\x4A\xF4\x7C\xA1";
39
//! let key = b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F";
40
//! let iv = b"\x00\x01\x02\x03\x04\x05\x06\x07\x00\x01\x02\x03\x04\x05\x06\x07";
41
//!
42
//! let mut ctx = CipherCtx::new().unwrap();
43
//! ctx.decrypt_init(Some(cipher), Some(key), Some(iv)).unwrap();
44
//!
45
//! let mut plaintext = vec![];
46
//! ctx.cipher_update_vec(data, &mut plaintext).unwrap();
47
//! ctx.cipher_final_vec(&mut plaintext).unwrap();
48
//!
49
//! assert_eq!(b"Some Crypto Text", &plaintext[..]);
50
//! ```
51
#![warn(missing_docs)]
52
53
use crate::cipher::CipherRef;
54
use crate::error::ErrorStack;
55
#[cfg(not(boringssl))]
56
use crate::pkey::{HasPrivate, HasPublic, PKey, PKeyRef};
57
use crate::{cvt, cvt_p};
58
#[cfg(ossl102)]
59
use bitflags::bitflags;
60
use cfg_if::cfg_if;
61
use foreign_types::{ForeignType, ForeignTypeRef};
62
use libc::{c_int, c_uchar};
63
use openssl_macros::corresponds;
64
use std::convert::{TryFrom, TryInto};
65
use std::ptr;
66
67
cfg_if! {
68
    if #[cfg(ossl300)] {
69
        use ffi::EVP_CIPHER_CTX_get0_cipher;
70
    } else {
71
        use ffi::EVP_CIPHER_CTX_cipher as EVP_CIPHER_CTX_get0_cipher;
72
    }
73
}
74
75
foreign_type_and_impl_send_sync! {
76
    type CType = ffi::EVP_CIPHER_CTX;
77
    fn drop = ffi::EVP_CIPHER_CTX_free;
78
79
    /// A context object used to perform symmetric encryption operations.
80
    pub struct CipherCtx;
81
    /// A reference to a [`CipherCtx`].
82
    pub struct CipherCtxRef;
83
}
84
85
#[cfg(ossl102)]
86
0
bitflags! {
87
0
    /// Flags for `EVP_CIPHER_CTX`.
88
0
    pub struct CipherCtxFlags : c_int {
89
0
        /// The flag used to opt into AES key wrap ciphers.
90
0
        const FLAG_WRAP_ALLOW = ffi::EVP_CIPHER_CTX_FLAG_WRAP_ALLOW;
91
0
    }
92
0
}
93
94
impl CipherCtx {
95
    /// Creates a new context.
96
    #[corresponds(EVP_CIPHER_CTX_new)]
97
0
    pub fn new() -> Result<Self, ErrorStack> {
98
0
        ffi::init();
99
100
        unsafe {
101
0
            let ptr = cvt_p(ffi::EVP_CIPHER_CTX_new())?;
102
0
            Ok(CipherCtx::from_ptr(ptr))
103
        }
104
0
    }
105
}
106
107
impl CipherCtxRef {
108
    #[corresponds(EVP_CIPHER_CTX_copy)]
109
0
    pub fn copy(&mut self, src: &CipherCtxRef) -> Result<(), ErrorStack> {
110
0
        unsafe {
111
0
            cvt(ffi::EVP_CIPHER_CTX_copy(self.as_ptr(), src.as_ptr()))?;
112
0
            Ok(())
113
        }
114
0
    }
115
116
    /// Initializes the context for encryption.
117
    ///
118
    /// Normally this is called once to set all of the cipher, key, and IV. However, this process can be split up
119
    /// by first setting the cipher with no key or IV and then setting the key and IV with no cipher. This can be used
120
    /// to, for example, use a nonstandard IV size.
121
    ///
122
    /// # Panics
123
    ///
124
    /// Panics if the key buffer is smaller than the key size of the cipher, the IV buffer is smaller than the IV size
125
    /// of the cipher, or if a key or IV is provided before a cipher.
126
    #[corresponds(EVP_EncryptInit_ex)]
127
0
    pub fn encrypt_init(
128
0
        &mut self,
129
0
        type_: Option<&CipherRef>,
130
0
        key: Option<&[u8]>,
131
0
        iv: Option<&[u8]>,
132
0
    ) -> Result<(), ErrorStack> {
133
0
        self.cipher_init(type_, key, iv, ffi::EVP_EncryptInit_ex)
134
0
    }
135
136
    /// Initializes the context for decryption.
137
    ///
138
    /// Normally this is called once to set all of the cipher, key, and IV. However, this process can be split up
139
    /// by first setting the cipher with no key or IV and then setting the key and IV with no cipher. This can be used
140
    /// to, for example, use a nonstandard IV size.
141
    ///
142
    /// # Panics
143
    ///
144
    /// Panics if the key buffer is smaller than the key size of the cipher, the IV buffer is smaller than the IV size
145
    /// of the cipher, or if a key or IV is provided before a cipher.
146
    #[corresponds(EVP_DecryptInit_ex)]
147
0
    pub fn decrypt_init(
148
0
        &mut self,
149
0
        type_: Option<&CipherRef>,
150
0
        key: Option<&[u8]>,
151
0
        iv: Option<&[u8]>,
152
0
    ) -> Result<(), ErrorStack> {
153
0
        self.cipher_init(type_, key, iv, ffi::EVP_DecryptInit_ex)
154
0
    }
155
156
0
    fn cipher_init(
157
0
        &mut self,
158
0
        type_: Option<&CipherRef>,
159
0
        key: Option<&[u8]>,
160
0
        iv: Option<&[u8]>,
161
0
        f: unsafe extern "C" fn(
162
0
            *mut ffi::EVP_CIPHER_CTX,
163
0
            *const ffi::EVP_CIPHER,
164
0
            *mut ffi::ENGINE,
165
0
            *const c_uchar,
166
0
            *const c_uchar,
167
0
        ) -> c_int,
168
0
    ) -> Result<(), ErrorStack> {
169
0
        if let Some(key) = key {
170
0
            let key_len = type_.map_or_else(|| self.key_length(), |c| c.key_length());
171
0
            assert!(key_len <= key.len());
172
0
        }
173
174
0
        if let Some(iv) = iv {
175
0
            let iv_len = type_.map_or_else(|| self.iv_length(), |c| c.iv_length());
176
0
            assert!(iv_len <= iv.len());
177
0
        }
178
179
        unsafe {
180
0
            cvt(f(
181
0
                self.as_ptr(),
182
0
                type_.map_or(ptr::null(), |p| p.as_ptr()),
183
0
                ptr::null_mut(),
184
0
                key.map_or(ptr::null(), |k| k.as_ptr()),
185
0
                iv.map_or(ptr::null(), |iv| iv.as_ptr()),
186
0
            ))?;
187
        }
188
189
0
        Ok(())
190
0
    }
191
192
    /// Initializes the context to perform envelope encryption.
193
    ///
194
    /// Normally this is called once to set both the cipher and public keys. However, this process may be split up by
195
    /// first providing the cipher with no public keys and then setting the public keys with no cipher.
196
    ///
197
    /// `encrypted_keys` will contain the generated symmetric key encrypted with each corresponding asymmetric private
198
    /// key. The generated IV will be written to `iv`.
199
    ///
200
    /// # Panics
201
    ///
202
    /// Panics if `pub_keys` is not the same size as `encrypted_keys`, the IV buffer is smaller than the cipher's IV
203
    /// size, or if an IV is provided before the cipher.
204
    #[corresponds(EVP_SealInit)]
205
    #[cfg(not(boringssl))]
206
0
    pub fn seal_init<T>(
207
0
        &mut self,
208
0
        type_: Option<&CipherRef>,
209
0
        pub_keys: &[PKey<T>],
210
0
        encrypted_keys: &mut [Vec<u8>],
211
0
        iv: Option<&mut [u8]>,
212
0
    ) -> Result<(), ErrorStack>
213
0
    where
214
0
        T: HasPublic,
215
0
    {
216
0
        assert_eq!(pub_keys.len(), encrypted_keys.len());
217
0
        if !pub_keys.is_empty() {
218
0
            let iv_len = type_.map_or_else(|| self.iv_length(), |c| c.iv_length());
219
0
            assert!(iv.as_ref().map_or(0, |b| b.len()) >= iv_len);
220
0
        }
221
222
0
        for (pub_key, buf) in pub_keys.iter().zip(&mut *encrypted_keys) {
223
0
            buf.resize(pub_key.size(), 0);
224
0
        }
225
226
0
        let mut keys = encrypted_keys
227
0
            .iter_mut()
228
0
            .map(|b| b.as_mut_ptr())
229
0
            .collect::<Vec<_>>();
230
0
        let mut key_lengths = vec![0; pub_keys.len()];
231
0
        let pub_keys_len = i32::try_from(pub_keys.len()).unwrap();
232
0
233
0
        unsafe {
234
0
            cvt(ffi::EVP_SealInit(
235
0
                self.as_ptr(),
236
0
                type_.map_or(ptr::null(), |p| p.as_ptr()),
237
0
                keys.as_mut_ptr(),
238
0
                key_lengths.as_mut_ptr(),
239
0
                iv.map_or(ptr::null_mut(), |b| b.as_mut_ptr()),
240
0
                pub_keys.as_ptr() as *mut _,
241
0
                pub_keys_len,
242
0
            ))?;
243
        }
244
245
0
        for (buf, len) in encrypted_keys.iter_mut().zip(key_lengths) {
246
0
            buf.truncate(len as usize);
247
0
        }
248
249
0
        Ok(())
250
0
    }
251
252
    /// Initializes the context to perform envelope decryption.
253
    ///
254
    /// Normally this is called once with all of the arguments present. However, this process may be split up by first
255
    /// providing the cipher alone and then after providing the rest of the arguments in a second call.
256
    ///
257
    /// # Panics
258
    ///
259
    /// Panics if the IV buffer is smaller than the cipher's required IV size or if the IV is provided before the
260
    /// cipher.
261
    #[corresponds(EVP_OpenInit)]
262
    #[cfg(not(boringssl))]
263
0
    pub fn open_init<T>(
264
0
        &mut self,
265
0
        type_: Option<&CipherRef>,
266
0
        encrypted_key: &[u8],
267
0
        iv: Option<&[u8]>,
268
0
        priv_key: Option<&PKeyRef<T>>,
269
0
    ) -> Result<(), ErrorStack>
270
0
    where
271
0
        T: HasPrivate,
272
0
    {
273
0
        if priv_key.is_some() {
274
0
            let iv_len = type_.map_or_else(|| self.iv_length(), |c| c.iv_length());
275
0
            assert!(iv.map_or(0, |b| b.len()) >= iv_len);
276
0
        }
277
278
0
        let len = c_int::try_from(encrypted_key.len()).unwrap();
279
0
        unsafe {
280
0
            cvt(ffi::EVP_OpenInit(
281
0
                self.as_ptr(),
282
0
                type_.map_or(ptr::null(), |p| p.as_ptr()),
283
0
                encrypted_key.as_ptr(),
284
0
                len,
285
0
                iv.map_or(ptr::null(), |b| b.as_ptr()),
286
0
                priv_key.map_or(ptr::null_mut(), ForeignTypeRef::as_ptr),
287
0
            ))?;
288
        }
289
290
0
        Ok(())
291
0
    }
292
293
0
    fn assert_cipher(&self) {
294
0
        unsafe {
295
0
            assert!(!EVP_CIPHER_CTX_get0_cipher(self.as_ptr()).is_null());
296
        }
297
0
    }
298
299
    /// Returns the block size of the context's cipher.
300
    ///
301
    /// Stream ciphers will report a block size of 1.
302
    ///
303
    /// # Panics
304
    ///
305
    /// Panics if the context has not been initialized with a cipher.
306
    #[corresponds(EVP_CIPHER_CTX_block_size)]
307
0
    pub fn block_size(&self) -> usize {
308
0
        self.assert_cipher();
309
0
310
0
        unsafe { ffi::EVP_CIPHER_CTX_block_size(self.as_ptr()) as usize }
311
0
    }
312
313
    /// Returns the key length of the context's cipher.
314
    ///
315
    /// # Panics
316
    ///
317
    /// Panics if the context has not been initialized with a cipher.
318
    #[corresponds(EVP_CIPHER_CTX_key_length)]
319
0
    pub fn key_length(&self) -> usize {
320
0
        self.assert_cipher();
321
0
322
0
        unsafe { ffi::EVP_CIPHER_CTX_key_length(self.as_ptr()) as usize }
323
0
    }
324
325
    /// Generates a random key based on the configured cipher.
326
    ///
327
    /// # Panics
328
    ///
329
    /// Panics if the context has not been initialized with a cipher or if the buffer is smaller than the cipher's key
330
    /// length.
331
    ///
332
    /// This corresponds to [`EVP_CIPHER_CTX_rand_key`].
333
    ///
334
    /// [`EVP_CIPHER_CTX_rand_key`]: https://www.openssl.org/docs/manmaster/man3/EVP_CIPHER_CTX_rand_key.html
335
    #[corresponds(EVP_CIPHER_CTX_rand_key)]
336
    #[cfg(not(boringssl))]
337
0
    pub fn rand_key(&self, buf: &mut [u8]) -> Result<(), ErrorStack> {
338
0
        assert!(buf.len() >= self.key_length());
339
340
        unsafe {
341
0
            cvt(ffi::EVP_CIPHER_CTX_rand_key(
342
0
                self.as_ptr(),
343
0
                buf.as_mut_ptr(),
344
0
            ))?;
345
        }
346
347
0
        Ok(())
348
0
    }
349
350
    /// Sets the length of the key expected by the context.
351
    ///
352
    /// Only some ciphers support configurable key lengths.
353
    ///
354
    /// # Panics
355
    ///
356
    /// Panics if the context has not been initialized with a cipher.
357
    #[corresponds(EVP_CIPHER_CTX_set_key_length)]
358
0
    pub fn set_key_length(&mut self, len: usize) -> Result<(), ErrorStack> {
359
0
        self.assert_cipher();
360
0
361
0
        unsafe {
362
0
            cvt(ffi::EVP_CIPHER_CTX_set_key_length(
363
0
                self.as_ptr(),
364
0
                len.try_into().unwrap(),
365
0
            ))?;
366
        }
367
368
0
        Ok(())
369
0
    }
370
371
    /// Returns the length of the IV expected by this context.
372
    ///
373
    /// Returns 0 if the cipher does not use an IV.
374
    ///
375
    /// # Panics
376
    ///
377
    /// Panics if the context has not been initialized with a cipher.
378
    #[corresponds(EVP_CIPHER_CTX_iv_length)]
379
0
    pub fn iv_length(&self) -> usize {
380
0
        self.assert_cipher();
381
0
382
0
        unsafe { ffi::EVP_CIPHER_CTX_iv_length(self.as_ptr()) as usize }
383
0
    }
384
385
    /// Returns the `num` parameter of the cipher.
386
    ///
387
    /// Built-in ciphers typically use this to track how much of the
388
    /// current underlying block has been "used" already.
389
    ///
390
    /// # Panics
391
    ///
392
    /// Panics if the context has not been initialized with a cipher.
393
    #[corresponds(EVP_CIPHER_CTX_num)]
394
    #[cfg(ossl110)]
395
0
    pub fn num(&self) -> usize {
396
0
        self.assert_cipher();
397
0
398
0
        unsafe { ffi::EVP_CIPHER_CTX_num(self.as_ptr()) as usize }
399
0
    }
400
401
    /// Sets the length of the IV expected by this context.
402
    ///
403
    /// Only some ciphers support configurable IV lengths.
404
    ///
405
    /// # Panics
406
    ///
407
    /// Panics if the context has not been initialized with a cipher.
408
    #[corresponds(EVP_CIPHER_CTX_ctrl)]
409
0
    pub fn set_iv_length(&mut self, len: usize) -> Result<(), ErrorStack> {
410
0
        self.assert_cipher();
411
0
412
0
        let len = c_int::try_from(len).unwrap();
413
0
414
0
        unsafe {
415
0
            cvt(ffi::EVP_CIPHER_CTX_ctrl(
416
0
                self.as_ptr(),
417
0
                ffi::EVP_CTRL_GCM_SET_IVLEN,
418
0
                len,
419
0
                ptr::null_mut(),
420
0
            ))?;
421
        }
422
423
0
        Ok(())
424
0
    }
425
426
    /// Returns the length of the authentication tag expected by this context.
427
    ///
428
    /// Returns 0 if the cipher is not authenticated.
429
    ///
430
    /// # Panics
431
    ///
432
    /// Panics if the context has not been initialized with a cipher.
433
    ///
434
    /// Requires OpenSSL 3.0.0 or newer.
435
    #[corresponds(EVP_CIPHER_CTX_get_tag_length)]
436
    #[cfg(ossl300)]
437
    pub fn tag_length(&self) -> usize {
438
        self.assert_cipher();
439
440
        unsafe { ffi::EVP_CIPHER_CTX_get_tag_length(self.as_ptr()) as usize }
441
    }
442
443
    /// Retrieves the calculated authentication tag from the context.
444
    ///
445
    /// This should be called after [`Self::cipher_final`], and is only supported by authenticated ciphers.
446
    ///
447
    /// The size of the buffer indicates the size of the tag. While some ciphers support a range of tag sizes, it is
448
    /// recommended to pick the maximum size.
449
    #[corresponds(EVP_CIPHER_CTX_ctrl)]
450
0
    pub fn tag(&self, tag: &mut [u8]) -> Result<(), ErrorStack> {
451
0
        let len = c_int::try_from(tag.len()).unwrap();
452
0
453
0
        unsafe {
454
0
            cvt(ffi::EVP_CIPHER_CTX_ctrl(
455
0
                self.as_ptr(),
456
0
                ffi::EVP_CTRL_GCM_GET_TAG,
457
0
                len,
458
0
                tag.as_mut_ptr() as *mut _,
459
0
            ))?;
460
        }
461
462
0
        Ok(())
463
0
    }
464
465
    /// Sets the length of the generated authentication tag.
466
    ///
467
    /// This must be called when encrypting with a cipher in CCM mode to use a tag size other than the default.
468
    #[corresponds(EVP_CIPHER_CTX_ctrl)]
469
0
    pub fn set_tag_length(&mut self, len: usize) -> Result<(), ErrorStack> {
470
0
        let len = c_int::try_from(len).unwrap();
471
0
472
0
        unsafe {
473
0
            cvt(ffi::EVP_CIPHER_CTX_ctrl(
474
0
                self.as_ptr(),
475
0
                ffi::EVP_CTRL_GCM_SET_TAG,
476
0
                len,
477
0
                ptr::null_mut(),
478
0
            ))?;
479
        }
480
481
0
        Ok(())
482
0
    }
483
484
    /// Sets the authentication tag for verification during decryption.
485
    #[corresponds(EVP_CIPHER_CTX_ctrl)]
486
0
    pub fn set_tag(&mut self, tag: &[u8]) -> Result<(), ErrorStack> {
487
0
        let len = c_int::try_from(tag.len()).unwrap();
488
0
489
0
        unsafe {
490
0
            cvt(ffi::EVP_CIPHER_CTX_ctrl(
491
0
                self.as_ptr(),
492
0
                ffi::EVP_CTRL_GCM_SET_TAG,
493
0
                len,
494
0
                tag.as_ptr() as *mut _,
495
0
            ))?;
496
        }
497
498
0
        Ok(())
499
0
    }
500
501
    /// Enables or disables padding.
502
    ///
503
    /// If padding is disabled, the plaintext must be an exact multiple of the cipher's block size.
504
    #[corresponds(EVP_CIPHER_CTX_set_padding)]
505
0
    pub fn set_padding(&mut self, padding: bool) {
506
0
        unsafe {
507
0
            ffi::EVP_CIPHER_CTX_set_padding(self.as_ptr(), padding as c_int);
508
0
        }
509
0
    }
510
511
    /// Sets the total length of plaintext data.
512
    ///
513
    /// This is required for ciphers operating in CCM mode.
514
    #[corresponds(EVP_CipherUpdate)]
515
0
    pub fn set_data_len(&mut self, len: usize) -> Result<(), ErrorStack> {
516
0
        let len = c_int::try_from(len).unwrap();
517
0
518
0
        unsafe {
519
0
            cvt(ffi::EVP_CipherUpdate(
520
0
                self.as_ptr(),
521
0
                ptr::null_mut(),
522
0
                &mut 0,
523
0
                ptr::null(),
524
0
                len,
525
0
            ))?;
526
        }
527
528
0
        Ok(())
529
0
    }
530
531
    /// Set ctx flags.
532
    ///
533
    /// This function is currently used to enable AES key wrap feature supported by OpenSSL 1.0.2 or newer.
534
    #[corresponds(EVP_CIPHER_CTX_set_flags)]
535
    #[cfg(ossl102)]
536
0
    pub fn set_flags(&mut self, flags: CipherCtxFlags) {
537
0
        unsafe {
538
0
            ffi::EVP_CIPHER_CTX_set_flags(self.as_ptr(), flags.bits());
539
0
        }
540
0
    }
541
542
    /// Writes data into the context.
543
    ///
544
    /// Providing no output buffer will cause the input to be considered additional authenticated data (AAD).
545
    ///
546
    /// Returns the number of bytes written to `output`.
547
    ///
548
    /// # Panics
549
    ///
550
    /// Panics if `output` doesn't contain enough space for data to be
551
    /// written.
552
    #[corresponds(EVP_CipherUpdate)]
553
0
    pub fn cipher_update(
554
0
        &mut self,
555
0
        input: &[u8],
556
0
        output: Option<&mut [u8]>,
557
0
    ) -> Result<usize, ErrorStack> {
558
0
        if let Some(output) = &output {
559
0
            let mut block_size = self.block_size();
560
0
            if block_size == 1 {
561
0
                block_size = 0;
562
0
            }
563
0
            let min_output_size = input.len() + block_size;
564
0
            assert!(
565
0
                output.len() >= min_output_size,
566
0
                "Output buffer size should be at least {} bytes.",
567
                min_output_size
568
            );
569
0
        }
570
571
0
        unsafe { self.cipher_update_unchecked(input, output) }
572
0
    }
573
574
    /// Writes data into the context.
575
    ///
576
    /// Providing no output buffer will cause the input to be considered additional authenticated data (AAD).
577
    ///
578
    /// Returns the number of bytes written to `output`.
579
    ///
580
    /// This function is the same as [`Self::cipher_update`] but with the
581
    /// output size check removed. It can be used when the exact
582
    /// buffer size control is maintained by the caller.
583
    ///
584
    /// # Safety
585
    ///
586
    /// The caller is expected to provide `output` buffer
587
    /// large enough to contain correct number of bytes. For streaming
588
    /// ciphers the output buffer size should be at least as big as
589
    /// the input buffer. For block ciphers the size of the output
590
    /// buffer depends on the state of partially updated blocks.
591
    #[corresponds(EVP_CipherUpdate)]
592
0
    pub unsafe fn cipher_update_unchecked(
593
0
        &mut self,
594
0
        input: &[u8],
595
0
        output: Option<&mut [u8]>,
596
0
    ) -> Result<usize, ErrorStack> {
597
0
        let inlen = c_int::try_from(input.len()).unwrap();
598
0
599
0
        let mut outlen = 0;
600
0
601
0
        cvt(ffi::EVP_CipherUpdate(
602
0
            self.as_ptr(),
603
0
            output.map_or(ptr::null_mut(), |b| b.as_mut_ptr()),
604
0
            &mut outlen,
605
0
            input.as_ptr(),
606
0
            inlen,
607
0
        ))?;
608
609
0
        Ok(outlen as usize)
610
0
    }
611
612
    /// Like [`Self::cipher_update`] except that it appends output to a [`Vec`].
613
0
    pub fn cipher_update_vec(
614
0
        &mut self,
615
0
        input: &[u8],
616
0
        output: &mut Vec<u8>,
617
0
    ) -> Result<usize, ErrorStack> {
618
0
        let base = output.len();
619
0
        output.resize(base + input.len() + self.block_size(), 0);
620
0
        let len = self.cipher_update(input, Some(&mut output[base..]))?;
621
0
        output.truncate(base + len);
622
0
623
0
        Ok(len)
624
0
    }
625
626
    /// Like [`Self::cipher_update`] except that it writes output into the
627
    /// `data` buffer. The `inlen` parameter specifies the number of bytes in
628
    /// `data` that are considered the input. For streaming ciphers, the size of
629
    /// `data` must be at least the input size. Otherwise, it must be at least
630
    /// an additional block size larger.
631
    ///
632
    /// Note: Use [`Self::cipher_update`] with no output argument to write AAD.
633
    ///
634
    /// # Panics
635
    ///
636
    /// This function panics if the input size cannot be represented as `int` or
637
    /// exceeds the buffer size, or if the output buffer does not contain enough
638
    /// additional space.
639
    #[corresponds(EVP_CipherUpdate)]
640
0
    pub fn cipher_update_inplace(
641
0
        &mut self,
642
0
        data: &mut [u8],
643
0
        inlen: usize,
644
0
    ) -> Result<usize, ErrorStack> {
645
0
        assert!(inlen <= data.len(), "Input size may not exceed buffer size");
646
0
        let block_size = self.block_size();
647
0
        if block_size != 1 {
648
0
            assert!(
649
0
                data.len() >= inlen + block_size,
650
0
                "Output buffer size must be at least {} bytes.",
651
0
                inlen + block_size
652
            );
653
0
        }
654
655
0
        let inlen = c_int::try_from(inlen).unwrap();
656
0
        let mut outlen = 0;
657
0
        unsafe {
658
0
            cvt(ffi::EVP_CipherUpdate(
659
0
                self.as_ptr(),
660
0
                data.as_mut_ptr(),
661
0
                &mut outlen,
662
0
                data.as_ptr(),
663
0
                inlen,
664
0
            ))
665
0
        }?;
666
667
0
        Ok(outlen as usize)
668
0
    }
669
670
    /// Finalizes the encryption or decryption process.
671
    ///
672
    /// Any remaining data will be written to the output buffer.
673
    ///
674
    /// Returns the number of bytes written to `output`.
675
    ///
676
    /// # Panics
677
    ///
678
    /// Panics if `output` is smaller than the cipher's block size.
679
    #[corresponds(EVP_CipherFinal)]
680
0
    pub fn cipher_final(&mut self, output: &mut [u8]) -> Result<usize, ErrorStack> {
681
0
        let block_size = self.block_size();
682
0
        if block_size > 1 {
683
0
            assert!(output.len() >= block_size);
684
0
        }
685
686
0
        unsafe { self.cipher_final_unchecked(output) }
687
0
    }
688
689
    /// Finalizes the encryption or decryption process.
690
    ///
691
    /// Any remaining data will be written to the output buffer.
692
    ///
693
    /// Returns the number of bytes written to `output`.
694
    ///
695
    /// This function is the same as [`Self::cipher_final`] but with
696
    /// the output buffer size check removed.
697
    ///
698
    /// # Safety
699
    ///
700
    /// The caller is expected to provide `output` buffer
701
    /// large enough to contain correct number of bytes. For streaming
702
    /// ciphers the output buffer can be empty, for block ciphers the
703
    /// output buffer should be at least as big as the block.
704
    #[corresponds(EVP_CipherFinal)]
705
0
    pub unsafe fn cipher_final_unchecked(
706
0
        &mut self,
707
0
        output: &mut [u8],
708
0
    ) -> Result<usize, ErrorStack> {
709
0
        let mut outl = 0;
710
0
711
0
        cvt(ffi::EVP_CipherFinal(
712
0
            self.as_ptr(),
713
0
            output.as_mut_ptr(),
714
0
            &mut outl,
715
0
        ))?;
716
717
0
        Ok(outl as usize)
718
0
    }
719
720
    /// Like [`Self::cipher_final`] except that it appends output to a [`Vec`].
721
0
    pub fn cipher_final_vec(&mut self, output: &mut Vec<u8>) -> Result<usize, ErrorStack> {
722
0
        let base = output.len();
723
0
        output.resize(base + self.block_size(), 0);
724
0
        let len = self.cipher_final(&mut output[base..])?;
725
0
        output.truncate(base + len);
726
0
727
0
        Ok(len)
728
0
    }
729
}
730
731
#[cfg(test)]
732
mod test {
733
    use super::*;
734
    use crate::{cipher::Cipher, rand::rand_bytes};
735
    #[cfg(not(boringssl))]
736
    use std::slice;
737
738
    #[test]
739
    #[cfg(not(boringssl))]
740
    fn seal_open() {
741
        let private_pem = include_bytes!("../test/rsa.pem");
742
        let public_pem = include_bytes!("../test/rsa.pem.pub");
743
        let private_key = PKey::private_key_from_pem(private_pem).unwrap();
744
        let public_key = PKey::public_key_from_pem(public_pem).unwrap();
745
        let cipher = Cipher::aes_256_cbc();
746
        let secret = b"My secret message";
747
748
        let mut ctx = CipherCtx::new().unwrap();
749
        let mut encrypted_key = vec![];
750
        let mut iv = vec![0; cipher.iv_length()];
751
        let mut encrypted = vec![];
752
        ctx.seal_init(
753
            Some(cipher),
754
            &[public_key],
755
            slice::from_mut(&mut encrypted_key),
756
            Some(&mut iv),
757
        )
758
        .unwrap();
759
        ctx.cipher_update_vec(secret, &mut encrypted).unwrap();
760
        ctx.cipher_final_vec(&mut encrypted).unwrap();
761
762
        let mut decrypted = vec![];
763
        ctx.open_init(Some(cipher), &encrypted_key, Some(&iv), Some(&private_key))
764
            .unwrap();
765
        ctx.cipher_update_vec(&encrypted, &mut decrypted).unwrap();
766
        ctx.cipher_final_vec(&mut decrypted).unwrap();
767
768
        assert_eq!(secret, &decrypted[..]);
769
    }
770
771
    fn aes_128_cbc(cipher: &CipherRef) {
772
        // from https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38a.pdf
773
        let key = hex::decode("2b7e151628aed2a6abf7158809cf4f3c").unwrap();
774
        let iv = hex::decode("000102030405060708090a0b0c0d0e0f").unwrap();
775
        let pt = hex::decode("6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51")
776
            .unwrap();
777
        let ct = hex::decode("7649abac8119b246cee98e9b12e9197d5086cb9b507219ee95db113a917678b2")
778
            .unwrap();
779
780
        let mut ctx = CipherCtx::new().unwrap();
781
782
        ctx.encrypt_init(Some(cipher), Some(&key), Some(&iv))
783
            .unwrap();
784
        ctx.set_padding(false);
785
786
        let mut buf = vec![];
787
        ctx.cipher_update_vec(&pt, &mut buf).unwrap();
788
        ctx.cipher_final_vec(&mut buf).unwrap();
789
790
        assert_eq!(buf, ct);
791
792
        ctx.decrypt_init(Some(cipher), Some(&key), Some(&iv))
793
            .unwrap();
794
        ctx.set_padding(false);
795
796
        let mut buf = vec![];
797
        ctx.cipher_update_vec(&ct, &mut buf).unwrap();
798
        ctx.cipher_final_vec(&mut buf).unwrap();
799
800
        assert_eq!(buf, pt);
801
    }
802
803
    #[test]
804
    #[cfg(ossl300)]
805
    fn fetched_aes_128_cbc() {
806
        let cipher = Cipher::fetch(None, "AES-128-CBC", None).unwrap();
807
        aes_128_cbc(&cipher);
808
    }
809
810
    #[test]
811
    fn default_aes_128_cbc() {
812
        let cipher = Cipher::aes_128_cbc();
813
        aes_128_cbc(cipher);
814
    }
815
816
    #[test]
817
    fn test_stream_ciphers() {
818
        test_stream_cipher(Cipher::aes_192_ctr());
819
        test_stream_cipher(Cipher::aes_256_ctr());
820
    }
821
822
    fn test_stream_cipher(cipher: &'static CipherRef) {
823
        let mut key = vec![0; cipher.key_length()];
824
        rand_bytes(&mut key).unwrap();
825
        let mut iv = vec![0; cipher.iv_length()];
826
        rand_bytes(&mut iv).unwrap();
827
828
        let mut ctx = CipherCtx::new().unwrap();
829
830
        ctx.encrypt_init(Some(cipher), Some(&key), Some(&iv))
831
            .unwrap();
832
        ctx.set_padding(false);
833
834
        assert_eq!(
835
            1,
836
            cipher.block_size(),
837
            "Need a stream cipher, not a block cipher"
838
        );
839
840
        // update cipher with non-full block
841
        // this is a streaming cipher so the number of output bytes
842
        // will be the same as the number of input bytes
843
        let mut output = vec![0; 32];
844
        let outlen = ctx
845
            .cipher_update(&[1; 15], Some(&mut output[0..15]))
846
            .unwrap();
847
        assert_eq!(15, outlen);
848
849
        // update cipher with missing bytes from the previous block
850
        // as previously it will output the same number of bytes as
851
        // the input
852
        let outlen = ctx
853
            .cipher_update(&[1; 17], Some(&mut output[15..]))
854
            .unwrap();
855
        assert_eq!(17, outlen);
856
857
        ctx.cipher_final_vec(&mut vec![0; 0]).unwrap();
858
859
        // encrypt again, but use in-place encryption this time
860
        // First reset the IV
861
        ctx.encrypt_init(None, None, Some(&iv)).unwrap();
862
        ctx.set_padding(false);
863
        let mut data_inplace: [u8; 32] = [1; 32];
864
        let outlen = ctx
865
            .cipher_update_inplace(&mut data_inplace[0..15], 15)
866
            .unwrap();
867
        assert_eq!(15, outlen);
868
869
        let outlen = ctx
870
            .cipher_update_inplace(&mut data_inplace[15..32], 17)
871
            .unwrap();
872
        assert_eq!(17, outlen);
873
874
        ctx.cipher_final(&mut [0u8; 0]).unwrap();
875
876
        // Check that the resulting data is encrypted in the same manner
877
        assert_eq!(data_inplace.as_slice(), output.as_slice());
878
879
        // try to decrypt
880
        ctx.decrypt_init(Some(cipher), Some(&key), Some(&iv))
881
            .unwrap();
882
        ctx.set_padding(false);
883
884
        // update cipher with non-full block
885
        // expect that the output for stream cipher will contain
886
        // the same number of bytes as the input
887
        let mut output_decrypted = vec![0; 32];
888
        let outlen = ctx
889
            .cipher_update(&output[0..15], Some(&mut output_decrypted[0..15]))
890
            .unwrap();
891
        assert_eq!(15, outlen);
892
893
        let outlen = ctx
894
            .cipher_update(&output[15..], Some(&mut output_decrypted[15..]))
895
            .unwrap();
896
        assert_eq!(17, outlen);
897
898
        ctx.cipher_final_vec(&mut vec![0; 0]).unwrap();
899
        // check if the decrypted blocks are the same as input (all ones)
900
        assert_eq!(output_decrypted, vec![1; 32]);
901
902
        // decrypt again, but now the output in-place
903
        ctx.decrypt_init(None, None, Some(&iv)).unwrap();
904
        ctx.set_padding(false);
905
906
        let outlen = ctx.cipher_update_inplace(&mut output[0..15], 15).unwrap();
907
        assert_eq!(15, outlen);
908
909
        let outlen = ctx.cipher_update_inplace(&mut output[15..], 17).unwrap();
910
        assert_eq!(17, outlen);
911
912
        ctx.cipher_final_vec(&mut vec![0; 0]).unwrap();
913
        assert_eq!(output_decrypted, output);
914
    }
915
916
    #[test]
917
    #[should_panic(expected = "Output buffer size should be at least 33 bytes.")]
918
    fn full_block_updates_aes_128() {
919
        output_buffer_too_small(Cipher::aes_128_cbc());
920
    }
921
922
    #[test]
923
    #[should_panic(expected = "Output buffer size should be at least 33 bytes.")]
924
    fn full_block_updates_aes_256() {
925
        output_buffer_too_small(Cipher::aes_256_cbc());
926
    }
927
928
    #[test]
929
    #[should_panic(expected = "Output buffer size should be at least 17 bytes.")]
930
    fn full_block_updates_3des() {
931
        output_buffer_too_small(Cipher::des_ede3_cbc());
932
    }
933
934
    fn output_buffer_too_small(cipher: &'static CipherRef) {
935
        let mut key = vec![0; cipher.key_length()];
936
        rand_bytes(&mut key).unwrap();
937
        let mut iv = vec![0; cipher.iv_length()];
938
        rand_bytes(&mut iv).unwrap();
939
940
        let mut ctx = CipherCtx::new().unwrap();
941
942
        ctx.encrypt_init(Some(cipher), Some(&key), Some(&iv))
943
            .unwrap();
944
        ctx.set_padding(false);
945
946
        let block_size = cipher.block_size();
947
        assert!(block_size > 1, "Need a block cipher, not a stream cipher");
948
949
        ctx.cipher_update(&vec![0; block_size + 1], Some(&mut vec![0; block_size - 1]))
950
            .unwrap();
951
    }
952
953
    #[cfg(ossl102)]
954
    fn cipher_wrap_test(cipher: &CipherRef, pt: &str, ct: &str, key: &str, iv: Option<&str>) {
955
        let pt = hex::decode(pt).unwrap();
956
        let key = hex::decode(key).unwrap();
957
        let expected = hex::decode(ct).unwrap();
958
        let iv = iv.map(|v| hex::decode(v).unwrap());
959
        let padding = 8 - pt.len() % 8;
960
        let mut computed = vec![0; pt.len() + padding + cipher.block_size() * 2];
961
        let mut ctx = CipherCtx::new().unwrap();
962
963
        ctx.set_flags(CipherCtxFlags::FLAG_WRAP_ALLOW);
964
        ctx.encrypt_init(Some(cipher), Some(&key), iv.as_deref())
965
            .unwrap();
966
967
        let count = ctx.cipher_update(&pt, Some(&mut computed)).unwrap();
968
        let rest = ctx.cipher_final(&mut computed[count..]).unwrap();
969
        computed.truncate(count + rest);
970
971
        if computed != expected {
972
            println!("Computed: {}", hex::encode(&computed));
973
            println!("Expected: {}", hex::encode(&expected));
974
            if computed.len() != expected.len() {
975
                println!(
976
                    "Lengths differ: {} in computed vs {} expected",
977
                    computed.len(),
978
                    expected.len()
979
                );
980
            }
981
            panic!("test failure");
982
        }
983
    }
984
985
    #[test]
986
    #[cfg(ossl102)]
987
    fn test_aes128_wrap() {
988
        let pt = "00112233445566778899aabbccddeeff";
989
        let ct = "7940ff694448b5bb5139c959a4896832e55d69aa04daa27e";
990
        let key = "2b7e151628aed2a6abf7158809cf4f3c";
991
        let iv = "0001020304050607";
992
993
        cipher_wrap_test(Cipher::aes_128_wrap(), pt, ct, key, Some(iv));
994
    }
995
996
    #[test]
997
    #[cfg(ossl102)]
998
    fn test_aes128_wrap_default_iv() {
999
        let pt = "00112233445566778899aabbccddeeff";
1000
        let ct = "38f1215f0212526f8a70b51955b9fbdc9fe3041d9832306e";
1001
        let key = "2b7e151628aed2a6abf7158809cf4f3c";
1002
1003
        cipher_wrap_test(Cipher::aes_128_wrap(), pt, ct, key, None);
1004
    }
1005
1006
    #[test]
1007
    #[cfg(ossl110)]
1008
    fn test_aes128_wrap_pad() {
1009
        let pt = "00112233445566778899aabbccddee";
1010
        let ct = "f13998f5ab32ef82a1bdbcbe585e1d837385b529572a1e1b";
1011
        let key = "2b7e151628aed2a6abf7158809cf4f3c";
1012
        let iv = "00010203";
1013
1014
        cipher_wrap_test(Cipher::aes_128_wrap_pad(), pt, ct, key, Some(iv));
1015
    }
1016
1017
    #[test]
1018
    #[cfg(ossl110)]
1019
    fn test_aes128_wrap_pad_default_iv() {
1020
        let pt = "00112233445566778899aabbccddee";
1021
        let ct = "3a501085fb8cf66f4186b7df851914d471ed823411598add";
1022
        let key = "2b7e151628aed2a6abf7158809cf4f3c";
1023
1024
        cipher_wrap_test(Cipher::aes_128_wrap_pad(), pt, ct, key, None);
1025
    }
1026
1027
    #[test]
1028
    #[cfg(ossl102)]
1029
    fn test_aes192_wrap() {
1030
        let pt = "9f6dee187d35302116aecbfd059657efd9f7589c4b5e7f5b";
1031
        let ct = "83b89142dfeeb4871e078bfb81134d33e23fedc19b03a1cf689973d3831b6813";
1032
        let key = "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b";
1033
        let iv = "0001020304050607";
1034
1035
        cipher_wrap_test(Cipher::aes_192_wrap(), pt, ct, key, Some(iv));
1036
    }
1037
1038
    #[test]
1039
    #[cfg(ossl102)]
1040
    fn test_aes192_wrap_default_iv() {
1041
        let pt = "9f6dee187d35302116aecbfd059657efd9f7589c4b5e7f5b";
1042
        let ct = "c02c2cf11505d3e4851030d5534cbf5a1d7eca7ba8839adbf239756daf1b43e6";
1043
        let key = "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b";
1044
1045
        cipher_wrap_test(Cipher::aes_192_wrap(), pt, ct, key, None);
1046
    }
1047
1048
    #[test]
1049
    #[cfg(ossl110)]
1050
    fn test_aes192_wrap_pad() {
1051
        let pt = "00112233445566778899aabbccddee";
1052
        let ct = "b4f6bb167ef7caf061a74da82b36ad038ca057ab51e98d3a";
1053
        let key = "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b";
1054
        let iv = "00010203";
1055
1056
        cipher_wrap_test(Cipher::aes_192_wrap_pad(), pt, ct, key, Some(iv));
1057
    }
1058
1059
    #[test]
1060
    #[cfg(ossl110)]
1061
    fn test_aes192_wrap_pad_default_iv() {
1062
        let pt = "00112233445566778899aabbccddee";
1063
        let ct = "b2c37a28cc602753a7c944a4c2555a2df9c98b2eded5312e";
1064
        let key = "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b";
1065
1066
        cipher_wrap_test(Cipher::aes_192_wrap_pad(), pt, ct, key, None);
1067
    }
1068
1069
    #[test]
1070
    #[cfg(ossl102)]
1071
    fn test_aes256_wrap() {
1072
        let pt = "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51";
1073
        let ct = "cc05da2a7f56f7dd0c144231f90bce58648fa20a8278f5a6b7d13bba6aa57a33229d4333866b7fd6";
1074
        let key = "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4";
1075
        let iv = "0001020304050607";
1076
1077
        cipher_wrap_test(Cipher::aes_256_wrap(), pt, ct, key, Some(iv));
1078
    }
1079
1080
    #[test]
1081
    #[cfg(ossl102)]
1082
    fn test_aes256_wrap_default_iv() {
1083
        let pt = "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51";
1084
        let ct = "0b24f068b50e52bc6987868411c36e1b03900866ed12af81eb87cef70a8d1911731c1d7abf789d88";
1085
        let key = "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4";
1086
1087
        cipher_wrap_test(Cipher::aes_256_wrap(), pt, ct, key, None);
1088
    }
1089
1090
    #[test]
1091
    #[cfg(ossl110)]
1092
    fn test_aes256_wrap_pad() {
1093
        let pt = "00112233445566778899aabbccddee";
1094
        let ct = "91594e044ccc06130d60e6c84a996aa4f96a9faff8c5f6e7";
1095
        let key = "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4";
1096
        let iv = "00010203";
1097
1098
        cipher_wrap_test(Cipher::aes_256_wrap_pad(), pt, ct, key, Some(iv));
1099
    }
1100
1101
    #[test]
1102
    #[cfg(ossl110)]
1103
    fn test_aes256_wrap_pad_default_iv() {
1104
        let pt = "00112233445566778899aabbccddee";
1105
        let ct = "dc3c166a854afd68aea624a4272693554bf2e4fcbae602cd";
1106
        let key = "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4";
1107
1108
        cipher_wrap_test(Cipher::aes_256_wrap_pad(), pt, ct, key, None);
1109
    }
1110
}