1//! Symmetric ciphers.
2
3#[cfg(ossl300)]
4use crate::cvt_p;
5#[cfg(ossl300)]
6use crate::error::ErrorStack;
7#[cfg(ossl300)]
8use crate::lib_ctx::LibCtxRef;
9use crate::nid::Nid;
10use cfg_if::cfg_if;
11use foreign_types::{ForeignTypeRef, Opaque};
12use openssl_macros::corresponds;
13#[cfg(ossl300)]
14use std::ffi::CString;
15use std::ops::{Deref, DerefMut};
16#[cfg(ossl300)]
17use std::ptr;
18
19cfg_if! {
20    if #[cfg(any(boringssl, ossl110, libressl273))] {
21        use ffi::{EVP_CIPHER_block_size, EVP_CIPHER_iv_length, EVP_CIPHER_key_length};
22    } else {
23        use libc::c_int;
24
25        #[allow(bad_style)]
26        pub unsafe fn EVP_CIPHER_iv_length(ptr: *const ffi::EVP_CIPHER) -> c_int {
27            (*ptr).iv_len
28        }
29
30        #[allow(bad_style)]
31        pub unsafe fn EVP_CIPHER_block_size(ptr: *const ffi::EVP_CIPHER) -> c_int {
32            (*ptr).block_size
33        }
34
35        #[allow(bad_style)]
36        pub unsafe fn EVP_CIPHER_key_length(ptr: *const ffi::EVP_CIPHER) -> c_int {
37            (*ptr).key_len
38        }
39    }
40}
41
42cfg_if! {
43    if #[cfg(ossl300)] {
44        use foreign_types::ForeignType;
45
46        type Inner = *mut ffi::EVP_CIPHER;
47
48        impl Drop for Cipher {
49            #[inline]
50            fn drop(&mut self) {
51                unsafe {
52                    ffi::EVP_CIPHER_free(self.as_ptr());
53                }
54            }
55        }
56
57        impl ForeignType for Cipher {
58            type CType = ffi::EVP_CIPHER;
59            type Ref = CipherRef;
60
61            #[inline]
62            unsafe fn from_ptr(ptr: *mut Self::CType) -> Self {
63                Cipher(ptr)
64            }
65
66            #[inline]
67            fn as_ptr(&self) -> *mut Self::CType {
68                self.0
69            }
70        }
71
72        impl Deref for Cipher {
73            type Target = CipherRef;
74
75            #[inline]
76            fn deref(&self) -> &Self::Target {
77                unsafe {
78                    CipherRef::from_ptr(self.as_ptr())
79                }
80            }
81        }
82
83        impl DerefMut for Cipher {
84            #[inline]
85            fn deref_mut(&mut self) -> &mut Self::Target {
86                unsafe {
87                    CipherRef::from_ptr_mut(self.as_ptr())
88                }
89            }
90        }
91    } else {
92        enum Inner {}
93
94        impl Deref for Cipher {
95            type Target = CipherRef;
96
97            #[inline]
98            fn deref(&self) -> &Self::Target {
99                match self.0 {}
100            }
101        }
102
103        impl DerefMut for Cipher {
104            #[inline]
105            fn deref_mut(&mut self) -> &mut Self::Target {
106                match self.0 {}
107            }
108        }
109    }
110}
111
112/// A symmetric cipher.
113pub struct Cipher(Inner);
114
115unsafe impl Sync for Cipher {}
116unsafe impl Send for Cipher {}
117
118impl Cipher {
119    /// Looks up the cipher for a certain nid.
120    #[corresponds(EVP_get_cipherbynid)]
121    pub fn from_nid(nid: Nid) -> Option<&'static CipherRef> {
122        unsafe {
123            let ptr = ffi::EVP_get_cipherbyname(ffi::OBJ_nid2sn(nid.as_raw()));
124            if ptr.is_null() {
125                None
126            } else {
127                Some(CipherRef::from_ptr(ptr as *mut _))
128            }
129        }
130    }
131
132    /// Fetches a cipher object corresponding to the specified algorithm name and properties.
133    ///
134    /// Requires OpenSSL 3.0.0 or newer.
135    #[corresponds(EVP_CIPHER_fetch)]
136    #[cfg(ossl300)]
137    pub fn fetch(
138        ctx: Option<&LibCtxRef>,
139        algorithm: &str,
140        properties: Option<&str>,
141    ) -> Result<Self, ErrorStack> {
142        let algorithm = CString::new(algorithm).unwrap();
143        let properties = properties.map(|s| CString::new(s).unwrap());
144
145        unsafe {
146            let ptr = cvt_p(ffi::EVP_CIPHER_fetch(
147                ctx.map_or(ptr::null_mut(), ForeignTypeRef::as_ptr),
148                algorithm.as_ptr(),
149                properties.map_or(ptr::null_mut(), |s| s.as_ptr()),
150            ))?;
151
152            Ok(Cipher::from_ptr(ptr))
153        }
154    }
155
156    pub fn aes_128_ecb() -> &'static CipherRef {
157        unsafe { CipherRef::from_ptr(ffi::EVP_aes_128_ecb() as *mut _) }
158    }
159
160    pub fn aes_128_cbc() -> &'static CipherRef {
161        unsafe { CipherRef::from_ptr(ffi::EVP_aes_128_cbc() as *mut _) }
162    }
163
164    #[cfg(not(boringssl))]
165    pub fn aes_128_xts() -> &'static CipherRef {
166        unsafe { CipherRef::from_ptr(ffi::EVP_aes_128_xts() as *mut _) }
167    }
168
169    #[cfg(not(boringssl))]
170    pub fn aes_128_ctr() -> &'static CipherRef {
171        unsafe { CipherRef::from_ptr(ffi::EVP_aes_128_ctr() as *mut _) }
172    }
173
174    #[cfg(not(boringssl))]
175    pub fn aes_128_cfb1() -> &'static CipherRef {
176        unsafe { CipherRef::from_ptr(ffi::EVP_aes_128_cfb1() as *mut _) }
177    }
178
179    #[cfg(not(boringssl))]
180    pub fn aes_128_cfb128() -> &'static CipherRef {
181        unsafe { CipherRef::from_ptr(ffi::EVP_aes_128_cfb128() as *mut _) }
182    }
183
184    #[cfg(not(boringssl))]
185    pub fn aes_128_cfb8() -> &'static CipherRef {
186        unsafe { CipherRef::from_ptr(ffi::EVP_aes_128_cfb8() as *mut _) }
187    }
188
189    pub fn aes_128_gcm() -> &'static CipherRef {
190        unsafe { CipherRef::from_ptr(ffi::EVP_aes_128_gcm() as *mut _) }
191    }
192
193    #[cfg(not(boringssl))]
194    pub fn aes_128_ccm() -> &'static CipherRef {
195        unsafe { CipherRef::from_ptr(ffi::EVP_aes_128_ccm() as *mut _) }
196    }
197
198    #[cfg(not(boringssl))]
199    pub fn aes_128_ofb() -> &'static CipherRef {
200        unsafe { CipherRef::from_ptr(ffi::EVP_aes_128_ofb() as *mut _) }
201    }
202
203    /// Requires OpenSSL 1.1.0 or newer.
204    #[cfg(ossl110)]
205    pub fn aes_128_ocb() -> &'static CipherRef {
206        unsafe { CipherRef::from_ptr(ffi::EVP_aes_128_ocb() as *mut _) }
207    }
208
209    /// Requires OpenSSL 1.0.2 or newer.
210    #[cfg(ossl102)]
211    pub fn aes_128_wrap() -> &'static CipherRef {
212        unsafe { CipherRef::from_ptr(ffi::EVP_aes_128_wrap() as *mut _) }
213    }
214
215    /// Requires OpenSSL 1.1.0 or newer.
216    #[cfg(ossl110)]
217    pub fn aes_128_wrap_pad() -> &'static CipherRef {
218        unsafe { CipherRef::from_ptr(ffi::EVP_aes_128_wrap_pad() as *mut _) }
219    }
220
221    pub fn aes_192_ecb() -> &'static CipherRef {
222        unsafe { CipherRef::from_ptr(ffi::EVP_aes_192_ecb() as *mut _) }
223    }
224
225    pub fn aes_192_cbc() -> &'static CipherRef {
226        unsafe { CipherRef::from_ptr(ffi::EVP_aes_192_cbc() as *mut _) }
227    }
228
229    pub fn aes_192_ctr() -> &'static CipherRef {
230        unsafe { CipherRef::from_ptr(ffi::EVP_aes_192_ctr() as *mut _) }
231    }
232
233    #[cfg(not(boringssl))]
234    pub fn aes_192_cfb1() -> &'static CipherRef {
235        unsafe { CipherRef::from_ptr(ffi::EVP_aes_192_cfb1() as *mut _) }
236    }
237
238    pub fn aes_192_cfb128() -> &'static CipherRef {
239        unsafe { CipherRef::from_ptr(ffi::EVP_aes_192_cfb128() as *mut _) }
240    }
241
242    #[cfg(not(boringssl))]
243    pub fn aes_192_cfb8() -> &'static CipherRef {
244        unsafe { CipherRef::from_ptr(ffi::EVP_aes_192_cfb8() as *mut _) }
245    }
246
247    pub fn aes_192_gcm() -> &'static CipherRef {
248        unsafe { CipherRef::from_ptr(ffi::EVP_aes_192_gcm() as *mut _) }
249    }
250
251    #[cfg(not(boringssl))]
252    pub fn aes_192_ccm() -> &'static CipherRef {
253        unsafe { CipherRef::from_ptr(ffi::EVP_aes_192_ccm() as *mut _) }
254    }
255
256    pub fn aes_192_ofb() -> &'static CipherRef {
257        unsafe { CipherRef::from_ptr(ffi::EVP_aes_192_ofb() as *mut _) }
258    }
259
260    /// Requires OpenSSL 1.1.0 or newer.
261    #[cfg(ossl110)]
262    pub fn aes_192_ocb() -> &'static CipherRef {
263        unsafe { CipherRef::from_ptr(ffi::EVP_aes_192_ocb() as *mut _) }
264    }
265
266    /// Requires OpenSSL 1.0.2 or newer.
267    #[cfg(ossl102)]
268    pub fn aes_192_wrap() -> &'static CipherRef {
269        unsafe { CipherRef::from_ptr(ffi::EVP_aes_192_wrap() as *mut _) }
270    }
271
272    /// Requires OpenSSL 1.1.0 or newer.
273    #[cfg(ossl110)]
274    pub fn aes_192_wrap_pad() -> &'static CipherRef {
275        unsafe { CipherRef::from_ptr(ffi::EVP_aes_192_wrap_pad() as *mut _) }
276    }
277
278    pub fn aes_256_ecb() -> &'static CipherRef {
279        unsafe { CipherRef::from_ptr(ffi::EVP_aes_256_ecb() as *mut _) }
280    }
281
282    pub fn aes_256_cbc() -> &'static CipherRef {
283        unsafe { CipherRef::from_ptr(ffi::EVP_aes_256_cbc() as *mut _) }
284    }
285
286    pub fn aes_256_ctr() -> &'static CipherRef {
287        unsafe { CipherRef::from_ptr(ffi::EVP_aes_256_ctr() as *mut _) }
288    }
289
290    #[cfg(not(boringssl))]
291    pub fn aes_256_cfb1() -> &'static CipherRef {
292        unsafe { CipherRef::from_ptr(ffi::EVP_aes_256_cfb1() as *mut _) }
293    }
294
295    pub fn aes_256_cfb128() -> &'static CipherRef {
296        unsafe { CipherRef::from_ptr(ffi::EVP_aes_256_cfb128() as *mut _) }
297    }
298
299    #[cfg(not(boringssl))]
300    pub fn aes_256_cfb8() -> &'static CipherRef {
301        unsafe { CipherRef::from_ptr(ffi::EVP_aes_256_cfb8() as *mut _) }
302    }
303
304    pub fn aes_256_gcm() -> &'static CipherRef {
305        unsafe { CipherRef::from_ptr(ffi::EVP_aes_256_gcm() as *mut _) }
306    }
307
308    #[cfg(not(boringssl))]
309    pub fn aes_256_ccm() -> &'static CipherRef {
310        unsafe { CipherRef::from_ptr(ffi::EVP_aes_256_ccm() as *mut _) }
311    }
312
313    pub fn aes_256_ofb() -> &'static CipherRef {
314        unsafe { CipherRef::from_ptr(ffi::EVP_aes_256_ofb() as *mut _) }
315    }
316
317    /// Requires OpenSSL 1.1.0 or newer.
318    #[cfg(ossl110)]
319    pub fn aes_256_ocb() -> &'static CipherRef {
320        unsafe { CipherRef::from_ptr(ffi::EVP_aes_256_ocb() as *mut _) }
321    }
322
323    /// Requires OpenSSL 1.0.2 or newer.
324    #[cfg(ossl102)]
325    pub fn aes_256_wrap() -> &'static CipherRef {
326        unsafe { CipherRef::from_ptr(ffi::EVP_aes_256_wrap() as *mut _) }
327    }
328
329    /// Requires OpenSSL 1.1.0 or newer.
330    #[cfg(ossl110)]
331    pub fn aes_256_wrap_pad() -> &'static CipherRef {
332        unsafe { CipherRef::from_ptr(ffi::EVP_aes_256_wrap_pad() as *mut _) }
333    }
334
335    #[cfg(not(osslconf = "OPENSSL_NO_BF"))]
336    pub fn bf_cbc() -> &'static CipherRef {
337        unsafe { CipherRef::from_ptr(ffi::EVP_bf_cbc() as *mut _) }
338    }
339
340    #[cfg(not(osslconf = "OPENSSL_NO_BF"))]
341    pub fn bf_ecb() -> &'static CipherRef {
342        unsafe { CipherRef::from_ptr(ffi::EVP_bf_ecb() as *mut _) }
343    }
344
345    #[cfg(not(osslconf = "OPENSSL_NO_BF"))]
346    #[cfg(not(boringssl))]
347    pub fn bf_cfb64() -> &'static CipherRef {
348        unsafe { CipherRef::from_ptr(ffi::EVP_bf_cfb64() as *mut _) }
349    }
350
351    #[cfg(not(osslconf = "OPENSSL_NO_BF"))]
352    #[cfg(not(boringssl))]
353    pub fn bf_ofb() -> &'static CipherRef {
354        unsafe { CipherRef::from_ptr(ffi::EVP_bf_ofb() as *mut _) }
355    }
356
357    pub fn des_cbc() -> &'static CipherRef {
358        unsafe { CipherRef::from_ptr(ffi::EVP_des_cbc() as *mut _) }
359    }
360
361    pub fn des_ecb() -> &'static CipherRef {
362        unsafe { CipherRef::from_ptr(ffi::EVP_des_ecb() as *mut _) }
363    }
364
365    pub fn des_ede3() -> &'static CipherRef {
366        unsafe { CipherRef::from_ptr(ffi::EVP_des_ede3() as *mut _) }
367    }
368
369    pub fn des_ede3_cbc() -> &'static CipherRef {
370        unsafe { CipherRef::from_ptr(ffi::EVP_des_ede3_cbc() as *mut _) }
371    }
372
373    #[cfg(not(boringssl))]
374    pub fn des_ede3_cfb64() -> &'static CipherRef {
375        unsafe { CipherRef::from_ptr(ffi::EVP_des_ede3_cfb64() as *mut _) }
376    }
377
378    #[cfg(not(osslconf = "OPENSSL_NO_RC4"))]
379    pub fn rc4() -> &'static CipherRef {
380        unsafe { CipherRef::from_ptr(ffi::EVP_rc4() as *mut _) }
381    }
382
383    #[cfg(not(any(boringssl, osslconf = "OPENSSL_NO_CAMELLIA")))]
384    pub fn camellia128_cfb128() -> &'static CipherRef {
385        unsafe { CipherRef::from_ptr(ffi::EVP_camellia_128_cfb128() as *mut _) }
386    }
387
388    #[cfg(not(any(boringssl, osslconf = "OPENSSL_NO_CAMELLIA")))]
389    pub fn camellia128_ecb() -> &'static CipherRef {
390        unsafe { CipherRef::from_ptr(ffi::EVP_camellia_128_ecb() as *mut _) }
391    }
392
393    #[cfg(not(any(boringssl, osslconf = "OPENSSL_NO_CAMELLIA")))]
394    pub fn camellia192_cfb128() -> &'static CipherRef {
395        unsafe { CipherRef::from_ptr(ffi::EVP_camellia_192_cfb128() as *mut _) }
396    }
397
398    #[cfg(not(any(boringssl, osslconf = "OPENSSL_NO_CAMELLIA")))]
399    pub fn camellia192_ecb() -> &'static CipherRef {
400        unsafe { CipherRef::from_ptr(ffi::EVP_camellia_192_ecb() as *mut _) }
401    }
402
403    #[cfg(not(any(boringssl, osslconf = "OPENSSL_NO_CAMELLIA")))]
404    pub fn camellia256_cfb128() -> &'static CipherRef {
405        unsafe { CipherRef::from_ptr(ffi::EVP_camellia_256_cfb128() as *mut _) }
406    }
407
408    #[cfg(not(any(boringssl, osslconf = "OPENSSL_NO_CAMELLIA")))]
409    pub fn camellia256_ecb() -> &'static CipherRef {
410        unsafe { CipherRef::from_ptr(ffi::EVP_camellia_256_ecb() as *mut _) }
411    }
412
413    #[cfg(not(any(boringssl, osslconf = "OPENSSL_NO_CAST")))]
414    pub fn cast5_cfb64() -> &'static CipherRef {
415        unsafe { CipherRef::from_ptr(ffi::EVP_cast5_cfb64() as *mut _) }
416    }
417
418    #[cfg(not(any(boringssl, osslconf = "OPENSSL_NO_CAST")))]
419    pub fn cast5_ecb() -> &'static CipherRef {
420        unsafe { CipherRef::from_ptr(ffi::EVP_cast5_ecb() as *mut _) }
421    }
422
423    #[cfg(not(any(boringssl, osslconf = "OPENSSL_NO_IDEA")))]
424    pub fn idea_cfb64() -> &'static CipherRef {
425        unsafe { CipherRef::from_ptr(ffi::EVP_idea_cfb64() as *mut _) }
426    }
427
428    #[cfg(not(any(boringssl, osslconf = "OPENSSL_NO_IDEA")))]
429    pub fn idea_ecb() -> &'static CipherRef {
430        unsafe { CipherRef::from_ptr(ffi::EVP_idea_ecb() as *mut _) }
431    }
432
433    #[cfg(all(ossl110, not(osslconf = "OPENSSL_NO_CHACHA")))]
434    pub fn chacha20() -> &'static CipherRef {
435        unsafe { CipherRef::from_ptr(ffi::EVP_chacha20() as *mut _) }
436    }
437
438    #[cfg(all(ossl110, not(osslconf = "OPENSSL_NO_CHACHA")))]
439    pub fn chacha20_poly1305() -> &'static CipherRef {
440        unsafe { CipherRef::from_ptr(ffi::EVP_chacha20_poly1305() as *mut _) }
441    }
442
443    #[cfg(not(osslconf = "OPENSSL_NO_SEED"))]
444    #[cfg(not(boringssl))]
445    pub fn seed_cbc() -> &'static CipherRef {
446        unsafe { CipherRef::from_ptr(ffi::EVP_seed_cbc() as *mut _) }
447    }
448
449    #[cfg(not(osslconf = "OPENSSL_NO_SEED"))]
450    #[cfg(not(boringssl))]
451    pub fn seed_cfb128() -> &'static CipherRef {
452        unsafe { CipherRef::from_ptr(ffi::EVP_seed_cfb128() as *mut _) }
453    }
454
455    #[cfg(not(osslconf = "OPENSSL_NO_SEED"))]
456    #[cfg(not(boringssl))]
457    pub fn seed_ecb() -> &'static CipherRef {
458        unsafe { CipherRef::from_ptr(ffi::EVP_seed_ecb() as *mut _) }
459    }
460
461    #[cfg(not(osslconf = "OPENSSL_NO_SEED"))]
462    #[cfg(not(boringssl))]
463    pub fn seed_ofb() -> &'static CipherRef {
464        unsafe { CipherRef::from_ptr(ffi::EVP_seed_ofb() as *mut _) }
465    }
466
467    #[cfg(all(any(ossl111, libressl291), not(osslconf = "OPENSSL_NO_SM4")))]
468    pub fn sm4_ecb() -> &'static CipherRef {
469        unsafe { CipherRef::from_ptr(ffi::EVP_sm4_ecb() as *mut _) }
470    }
471
472    #[cfg(all(any(ossl111, libressl291), not(osslconf = "OPENSSL_NO_SM4")))]
473    pub fn sm4_cbc() -> &'static CipherRef {
474        unsafe { CipherRef::from_ptr(ffi::EVP_sm4_cbc() as *mut _) }
475    }
476
477    #[cfg(all(any(ossl111, libressl291), not(osslconf = "OPENSSL_NO_SM4")))]
478    pub fn sm4_ctr() -> &'static CipherRef {
479        unsafe { CipherRef::from_ptr(ffi::EVP_sm4_ctr() as *mut _) }
480    }
481
482    #[cfg(all(any(ossl111, libressl291), not(osslconf = "OPENSSL_NO_SM4")))]
483    pub fn sm4_cfb128() -> &'static CipherRef {
484        unsafe { CipherRef::from_ptr(ffi::EVP_sm4_cfb128() as *mut _) }
485    }
486
487    #[cfg(all(any(ossl111, libressl291), not(osslconf = "OPENSSL_NO_SM4")))]
488    pub fn sm4_ofb() -> &'static CipherRef {
489        unsafe { CipherRef::from_ptr(ffi::EVP_sm4_ofb() as *mut _) }
490    }
491}
492
493/// A reference to a [`Cipher`].
494pub struct CipherRef(Opaque);
495
496impl ForeignTypeRef for CipherRef {
497    type CType = ffi::EVP_CIPHER;
498}
499
500unsafe impl Sync for CipherRef {}
501unsafe impl Send for CipherRef {}
502
503impl CipherRef {
504    /// Returns the cipher's Nid.
505    #[corresponds(EVP_CIPHER_nid)]
506    pub fn nid(&self) -> Nid {
507        let nid = unsafe { ffi::EVP_CIPHER_nid(self.as_ptr()) };
508        Nid::from_raw(nid)
509    }
510
511    /// Returns the length of keys used with this cipher.
512    #[corresponds(EVP_CIPHER_key_length)]
513    pub fn key_length(&self) -> usize {
514        unsafe { EVP_CIPHER_key_length(self.as_ptr()) as usize }
515    }
516
517    /// Returns the length of the IV used with this cipher.
518    ///
519    /// # Note
520    ///
521    /// Ciphers that do not use an IV have an IV length of 0.
522    #[corresponds(EVP_CIPHER_iv_length)]
523    pub fn iv_length(&self) -> usize {
524        unsafe { EVP_CIPHER_iv_length(self.as_ptr()) as usize }
525    }
526
527    /// Returns the block size of the cipher.
528    ///
529    /// # Note
530    ///
531    /// Stream ciphers have a block size of 1.
532    #[corresponds(EVP_CIPHER_block_size)]
533    pub fn block_size(&self) -> usize {
534        unsafe { EVP_CIPHER_block_size(self.as_ptr()) as usize }
535    }
536}
537