openssl/
cipher.rs

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, awslc))] {
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.as_ref().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(any(boringssl, awslc)))]
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_256_xts() -> &'static CipherRef {
171        unsafe { CipherRef::from_ptr(ffi::EVP_aes_256_xts() as *mut _) }
172    }
173
174    pub fn aes_128_ctr() -> &'static CipherRef {
175        unsafe { CipherRef::from_ptr(ffi::EVP_aes_128_ctr() as *mut _) }
176    }
177
178    #[cfg(not(boringssl))]
179    pub fn aes_128_cfb1() -> &'static CipherRef {
180        unsafe { CipherRef::from_ptr(ffi::EVP_aes_128_cfb1() as *mut _) }
181    }
182
183    #[cfg(not(boringssl))]
184    pub fn aes_128_cfb128() -> &'static CipherRef {
185        unsafe { CipherRef::from_ptr(ffi::EVP_aes_128_cfb128() as *mut _) }
186    }
187
188    #[cfg(not(boringssl))]
189    pub fn aes_128_cfb8() -> &'static CipherRef {
190        unsafe { CipherRef::from_ptr(ffi::EVP_aes_128_cfb8() as *mut _) }
191    }
192
193    pub fn aes_128_gcm() -> &'static CipherRef {
194        unsafe { CipherRef::from_ptr(ffi::EVP_aes_128_gcm() as *mut _) }
195    }
196
197    #[cfg(not(boringssl))]
198    pub fn aes_128_ccm() -> &'static CipherRef {
199        unsafe { CipherRef::from_ptr(ffi::EVP_aes_128_ccm() as *mut _) }
200    }
201
202    pub fn aes_128_ofb() -> &'static CipherRef {
203        unsafe { CipherRef::from_ptr(ffi::EVP_aes_128_ofb() as *mut _) }
204    }
205
206    /// Requires OpenSSL 1.1.0 or newer.
207    #[cfg(all(ossl110, not(osslconf = "OPENSSL_NO_OCB")))]
208    pub fn aes_128_ocb() -> &'static CipherRef {
209        unsafe { CipherRef::from_ptr(ffi::EVP_aes_128_ocb() as *mut _) }
210    }
211
212    /// Requires OpenSSL 1.0.2 or newer.
213    #[cfg(ossl102)]
214    pub fn aes_128_wrap() -> &'static CipherRef {
215        unsafe { CipherRef::from_ptr(ffi::EVP_aes_128_wrap() as *mut _) }
216    }
217
218    /// Requires OpenSSL 1.1.0 or newer.
219    #[cfg(ossl110)]
220    pub fn aes_128_wrap_pad() -> &'static CipherRef {
221        unsafe { CipherRef::from_ptr(ffi::EVP_aes_128_wrap_pad() as *mut _) }
222    }
223
224    pub fn aes_192_ecb() -> &'static CipherRef {
225        unsafe { CipherRef::from_ptr(ffi::EVP_aes_192_ecb() as *mut _) }
226    }
227
228    pub fn aes_192_cbc() -> &'static CipherRef {
229        unsafe { CipherRef::from_ptr(ffi::EVP_aes_192_cbc() as *mut _) }
230    }
231
232    pub fn aes_192_ctr() -> &'static CipherRef {
233        unsafe { CipherRef::from_ptr(ffi::EVP_aes_192_ctr() as *mut _) }
234    }
235
236    #[cfg(not(boringssl))]
237    pub fn aes_192_cfb1() -> &'static CipherRef {
238        unsafe { CipherRef::from_ptr(ffi::EVP_aes_192_cfb1() as *mut _) }
239    }
240
241    pub fn aes_192_cfb128() -> &'static CipherRef {
242        unsafe { CipherRef::from_ptr(ffi::EVP_aes_192_cfb128() as *mut _) }
243    }
244
245    #[cfg(not(boringssl))]
246    pub fn aes_192_cfb8() -> &'static CipherRef {
247        unsafe { CipherRef::from_ptr(ffi::EVP_aes_192_cfb8() as *mut _) }
248    }
249
250    pub fn aes_192_gcm() -> &'static CipherRef {
251        unsafe { CipherRef::from_ptr(ffi::EVP_aes_192_gcm() as *mut _) }
252    }
253
254    #[cfg(not(boringssl))]
255    pub fn aes_192_ccm() -> &'static CipherRef {
256        unsafe { CipherRef::from_ptr(ffi::EVP_aes_192_ccm() as *mut _) }
257    }
258
259    pub fn aes_192_ofb() -> &'static CipherRef {
260        unsafe { CipherRef::from_ptr(ffi::EVP_aes_192_ofb() as *mut _) }
261    }
262
263    /// Requires OpenSSL 1.1.0 or newer.
264    #[cfg(all(ossl110, not(osslconf = "OPENSSL_NO_OCB")))]
265    pub fn aes_192_ocb() -> &'static CipherRef {
266        unsafe { CipherRef::from_ptr(ffi::EVP_aes_192_ocb() as *mut _) }
267    }
268
269    /// Requires OpenSSL 1.0.2 or newer.
270    #[cfg(ossl102)]
271    pub fn aes_192_wrap() -> &'static CipherRef {
272        unsafe { CipherRef::from_ptr(ffi::EVP_aes_192_wrap() as *mut _) }
273    }
274
275    /// Requires OpenSSL 1.1.0 or newer.
276    #[cfg(ossl110)]
277    pub fn aes_192_wrap_pad() -> &'static CipherRef {
278        unsafe { CipherRef::from_ptr(ffi::EVP_aes_192_wrap_pad() as *mut _) }
279    }
280
281    pub fn aes_256_ecb() -> &'static CipherRef {
282        unsafe { CipherRef::from_ptr(ffi::EVP_aes_256_ecb() as *mut _) }
283    }
284
285    pub fn aes_256_cbc() -> &'static CipherRef {
286        unsafe { CipherRef::from_ptr(ffi::EVP_aes_256_cbc() as *mut _) }
287    }
288
289    pub fn aes_256_ctr() -> &'static CipherRef {
290        unsafe { CipherRef::from_ptr(ffi::EVP_aes_256_ctr() as *mut _) }
291    }
292
293    #[cfg(not(boringssl))]
294    pub fn aes_256_cfb1() -> &'static CipherRef {
295        unsafe { CipherRef::from_ptr(ffi::EVP_aes_256_cfb1() as *mut _) }
296    }
297
298    pub fn aes_256_cfb128() -> &'static CipherRef {
299        unsafe { CipherRef::from_ptr(ffi::EVP_aes_256_cfb128() as *mut _) }
300    }
301
302    #[cfg(not(boringssl))]
303    pub fn aes_256_cfb8() -> &'static CipherRef {
304        unsafe { CipherRef::from_ptr(ffi::EVP_aes_256_cfb8() as *mut _) }
305    }
306
307    pub fn aes_256_gcm() -> &'static CipherRef {
308        unsafe { CipherRef::from_ptr(ffi::EVP_aes_256_gcm() as *mut _) }
309    }
310
311    #[cfg(not(boringssl))]
312    pub fn aes_256_ccm() -> &'static CipherRef {
313        unsafe { CipherRef::from_ptr(ffi::EVP_aes_256_ccm() as *mut _) }
314    }
315
316    pub fn aes_256_ofb() -> &'static CipherRef {
317        unsafe { CipherRef::from_ptr(ffi::EVP_aes_256_ofb() as *mut _) }
318    }
319
320    /// Requires OpenSSL 1.1.0 or newer.
321    #[cfg(all(ossl110, not(osslconf = "OPENSSL_NO_OCB")))]
322    pub fn aes_256_ocb() -> &'static CipherRef {
323        unsafe { CipherRef::from_ptr(ffi::EVP_aes_256_ocb() as *mut _) }
324    }
325
326    /// Requires OpenSSL 1.0.2 or newer.
327    #[cfg(ossl102)]
328    pub fn aes_256_wrap() -> &'static CipherRef {
329        unsafe { CipherRef::from_ptr(ffi::EVP_aes_256_wrap() as *mut _) }
330    }
331
332    /// Requires OpenSSL 1.1.0 or newer.
333    #[cfg(ossl110)]
334    pub fn aes_256_wrap_pad() -> &'static CipherRef {
335        unsafe { CipherRef::from_ptr(ffi::EVP_aes_256_wrap_pad() as *mut _) }
336    }
337
338    #[cfg(not(osslconf = "OPENSSL_NO_BF"))]
339    pub fn bf_cbc() -> &'static CipherRef {
340        unsafe { CipherRef::from_ptr(ffi::EVP_bf_cbc() as *mut _) }
341    }
342
343    #[cfg(not(osslconf = "OPENSSL_NO_BF"))]
344    pub fn bf_ecb() -> &'static CipherRef {
345        unsafe { CipherRef::from_ptr(ffi::EVP_bf_ecb() as *mut _) }
346    }
347
348    #[cfg(not(osslconf = "OPENSSL_NO_BF"))]
349    pub fn bf_cfb64() -> &'static CipherRef {
350        unsafe { CipherRef::from_ptr(ffi::EVP_bf_cfb64() as *mut _) }
351    }
352
353    #[cfg(not(osslconf = "OPENSSL_NO_BF"))]
354    pub fn bf_ofb() -> &'static CipherRef {
355        unsafe { CipherRef::from_ptr(ffi::EVP_bf_ofb() as *mut _) }
356    }
357
358    pub fn des_cbc() -> &'static CipherRef {
359        unsafe { CipherRef::from_ptr(ffi::EVP_des_cbc() as *mut _) }
360    }
361
362    pub fn des_ecb() -> &'static CipherRef {
363        unsafe { CipherRef::from_ptr(ffi::EVP_des_ecb() as *mut _) }
364    }
365
366    pub fn des_ede3() -> &'static CipherRef {
367        unsafe { CipherRef::from_ptr(ffi::EVP_des_ede3() as *mut _) }
368    }
369
370    pub fn des_ede3_ecb() -> &'static CipherRef {
371        unsafe { CipherRef::from_ptr(ffi::EVP_des_ede3_ecb() as *mut _) }
372    }
373
374    pub fn des_ede3_cbc() -> &'static CipherRef {
375        unsafe { CipherRef::from_ptr(ffi::EVP_des_ede3_cbc() as *mut _) }
376    }
377
378    #[cfg(not(any(boringssl, awslc)))]
379    pub fn des_ede3_cfb8() -> &'static CipherRef {
380        unsafe { CipherRef::from_ptr(ffi::EVP_des_ede3_cfb8() as *mut _) }
381    }
382
383    #[cfg(not(any(boringssl, awslc)))]
384    pub fn des_ede3_cfb64() -> &'static CipherRef {
385        unsafe { CipherRef::from_ptr(ffi::EVP_des_ede3_cfb64() as *mut _) }
386    }
387
388    #[cfg(not(any(boringssl, awslc)))]
389    pub fn des_ede3_ofb() -> &'static CipherRef {
390        unsafe { CipherRef::from_ptr(ffi::EVP_des_ede3_ofb() as *mut _) }
391    }
392
393    #[cfg(not(osslconf = "OPENSSL_NO_RC4"))]
394    pub fn rc4() -> &'static CipherRef {
395        unsafe { CipherRef::from_ptr(ffi::EVP_rc4() as *mut _) }
396    }
397
398    #[cfg(not(osslconf = "OPENSSL_NO_CAMELLIA"))]
399    pub fn camellia128_cfb128() -> &'static CipherRef {
400        unsafe { CipherRef::from_ptr(ffi::EVP_camellia_128_cfb128() as *mut _) }
401    }
402
403    #[cfg(not(osslconf = "OPENSSL_NO_CAMELLIA"))]
404    pub fn camellia128_ecb() -> &'static CipherRef {
405        unsafe { CipherRef::from_ptr(ffi::EVP_camellia_128_ecb() as *mut _) }
406    }
407
408    #[cfg(not(osslconf = "OPENSSL_NO_CAMELLIA"))]
409    pub fn camellia128_cbc() -> &'static CipherRef {
410        unsafe { CipherRef::from_ptr(ffi::EVP_camellia_128_cbc() as *mut _) }
411    }
412
413    #[cfg(not(osslconf = "OPENSSL_NO_CAMELLIA"))]
414    pub fn camellia128_ofb() -> &'static CipherRef {
415        unsafe { CipherRef::from_ptr(ffi::EVP_camellia_128_ofb() as *mut _) }
416    }
417
418    #[cfg(not(osslconf = "OPENSSL_NO_CAMELLIA"))]
419    pub fn camellia192_cfb128() -> &'static CipherRef {
420        unsafe { CipherRef::from_ptr(ffi::EVP_camellia_192_cfb128() as *mut _) }
421    }
422
423    #[cfg(not(osslconf = "OPENSSL_NO_CAMELLIA"))]
424    pub fn camellia192_ecb() -> &'static CipherRef {
425        unsafe { CipherRef::from_ptr(ffi::EVP_camellia_192_ecb() as *mut _) }
426    }
427
428    #[cfg(not(osslconf = "OPENSSL_NO_CAMELLIA"))]
429    pub fn camellia192_cbc() -> &'static CipherRef {
430        unsafe { CipherRef::from_ptr(ffi::EVP_camellia_192_cbc() as *mut _) }
431    }
432
433    #[cfg(not(osslconf = "OPENSSL_NO_CAMELLIA"))]
434    pub fn camellia192_ofb() -> &'static CipherRef {
435        unsafe { CipherRef::from_ptr(ffi::EVP_camellia_192_ofb() as *mut _) }
436    }
437
438    #[cfg(not(osslconf = "OPENSSL_NO_CAMELLIA"))]
439    pub fn camellia256_cfb128() -> &'static CipherRef {
440        unsafe { CipherRef::from_ptr(ffi::EVP_camellia_256_cfb128() as *mut _) }
441    }
442
443    #[cfg(not(osslconf = "OPENSSL_NO_CAMELLIA"))]
444    pub fn camellia256_ecb() -> &'static CipherRef {
445        unsafe { CipherRef::from_ptr(ffi::EVP_camellia_256_ecb() as *mut _) }
446    }
447
448    #[cfg(not(osslconf = "OPENSSL_NO_CAMELLIA"))]
449    pub fn camellia256_cbc() -> &'static CipherRef {
450        unsafe { CipherRef::from_ptr(ffi::EVP_camellia_256_cbc() as *mut _) }
451    }
452
453    #[cfg(not(osslconf = "OPENSSL_NO_CAMELLIA"))]
454    pub fn camellia256_ofb() -> &'static CipherRef {
455        unsafe { CipherRef::from_ptr(ffi::EVP_camellia_256_ofb() as *mut _) }
456    }
457
458    #[cfg(not(osslconf = "OPENSSL_NO_CAST"))]
459    pub fn cast5_cfb64() -> &'static CipherRef {
460        unsafe { CipherRef::from_ptr(ffi::EVP_cast5_cfb64() as *mut _) }
461    }
462
463    #[cfg(not(osslconf = "OPENSSL_NO_CAST"))]
464    pub fn cast5_ecb() -> &'static CipherRef {
465        unsafe { CipherRef::from_ptr(ffi::EVP_cast5_ecb() as *mut _) }
466    }
467
468    #[cfg(not(osslconf = "OPENSSL_NO_CAST"))]
469    pub fn cast5_cbc() -> &'static CipherRef {
470        unsafe { CipherRef::from_ptr(ffi::EVP_cast5_cbc() as *mut _) }
471    }
472
473    #[cfg(not(osslconf = "OPENSSL_NO_CAST"))]
474    pub fn cast5_ofb() -> &'static CipherRef {
475        unsafe { CipherRef::from_ptr(ffi::EVP_cast5_ofb() as *mut _) }
476    }
477
478    #[cfg(not(osslconf = "OPENSSL_NO_IDEA"))]
479    pub fn idea_cfb64() -> &'static CipherRef {
480        unsafe { CipherRef::from_ptr(ffi::EVP_idea_cfb64() as *mut _) }
481    }
482
483    #[cfg(not(osslconf = "OPENSSL_NO_IDEA"))]
484    pub fn idea_ecb() -> &'static CipherRef {
485        unsafe { CipherRef::from_ptr(ffi::EVP_idea_ecb() as *mut _) }
486    }
487
488    #[cfg(not(osslconf = "OPENSSL_NO_IDEA"))]
489    pub fn idea_cbc() -> &'static CipherRef {
490        unsafe { CipherRef::from_ptr(ffi::EVP_idea_cbc() as *mut _) }
491    }
492
493    #[cfg(not(osslconf = "OPENSSL_NO_IDEA"))]
494    pub fn idea_ofb() -> &'static CipherRef {
495        unsafe { CipherRef::from_ptr(ffi::EVP_idea_ofb() as *mut _) }
496    }
497
498    #[cfg(all(any(ossl110, libressl310), not(osslconf = "OPENSSL_NO_CHACHA")))]
499    pub fn chacha20() -> &'static CipherRef {
500        unsafe { CipherRef::from_ptr(ffi::EVP_chacha20() as *mut _) }
501    }
502
503    #[cfg(all(any(ossl110, libressl360, awslc), not(osslconf = "OPENSSL_NO_CHACHA")))]
504    pub fn chacha20_poly1305() -> &'static CipherRef {
505        unsafe { CipherRef::from_ptr(ffi::EVP_chacha20_poly1305() as *mut _) }
506    }
507
508    #[cfg(not(osslconf = "OPENSSL_NO_SEED"))]
509    pub fn seed_cbc() -> &'static CipherRef {
510        unsafe { CipherRef::from_ptr(ffi::EVP_seed_cbc() as *mut _) }
511    }
512
513    #[cfg(not(osslconf = "OPENSSL_NO_SEED"))]
514    pub fn seed_cfb128() -> &'static CipherRef {
515        unsafe { CipherRef::from_ptr(ffi::EVP_seed_cfb128() as *mut _) }
516    }
517
518    #[cfg(not(osslconf = "OPENSSL_NO_SEED"))]
519    pub fn seed_ecb() -> &'static CipherRef {
520        unsafe { CipherRef::from_ptr(ffi::EVP_seed_ecb() as *mut _) }
521    }
522
523    #[cfg(not(osslconf = "OPENSSL_NO_SEED"))]
524    pub fn seed_ofb() -> &'static CipherRef {
525        unsafe { CipherRef::from_ptr(ffi::EVP_seed_ofb() as *mut _) }
526    }
527
528    #[cfg(all(any(ossl111, libressl291), not(osslconf = "OPENSSL_NO_SM4")))]
529    pub fn sm4_ecb() -> &'static CipherRef {
530        unsafe { CipherRef::from_ptr(ffi::EVP_sm4_ecb() as *mut _) }
531    }
532
533    #[cfg(all(any(ossl111, libressl291), not(osslconf = "OPENSSL_NO_SM4")))]
534    pub fn sm4_cbc() -> &'static CipherRef {
535        unsafe { CipherRef::from_ptr(ffi::EVP_sm4_cbc() as *mut _) }
536    }
537
538    #[cfg(all(any(ossl111, libressl291), not(osslconf = "OPENSSL_NO_SM4")))]
539    pub fn sm4_ctr() -> &'static CipherRef {
540        unsafe { CipherRef::from_ptr(ffi::EVP_sm4_ctr() as *mut _) }
541    }
542
543    #[cfg(all(any(ossl111, libressl291), not(osslconf = "OPENSSL_NO_SM4")))]
544    pub fn sm4_cfb128() -> &'static CipherRef {
545        unsafe { CipherRef::from_ptr(ffi::EVP_sm4_cfb128() as *mut _) }
546    }
547
548    #[cfg(all(any(ossl111, libressl291), not(osslconf = "OPENSSL_NO_SM4")))]
549    pub fn sm4_ofb() -> &'static CipherRef {
550        unsafe { CipherRef::from_ptr(ffi::EVP_sm4_ofb() as *mut _) }
551    }
552}
553
554/// A reference to a [`Cipher`].
555pub struct CipherRef(Opaque);
556
557impl ForeignTypeRef for CipherRef {
558    type CType = ffi::EVP_CIPHER;
559}
560
561unsafe impl Sync for CipherRef {}
562unsafe impl Send for CipherRef {}
563
564impl CipherRef {
565    /// Returns the cipher's Nid.
566    #[corresponds(EVP_CIPHER_nid)]
567    pub fn nid(&self) -> Nid {
568        let nid = unsafe { ffi::EVP_CIPHER_nid(self.as_ptr()) };
569        Nid::from_raw(nid)
570    }
571
572    /// Returns the length of keys used with this cipher.
573    #[corresponds(EVP_CIPHER_key_length)]
574    pub fn key_length(&self) -> usize {
575        unsafe { EVP_CIPHER_key_length(self.as_ptr()) as usize }
576    }
577
578    /// Returns the length of the IV used with this cipher.
579    ///
580    /// # Note
581    ///
582    /// Ciphers that do not use an IV have an IV length of 0.
583    #[corresponds(EVP_CIPHER_iv_length)]
584    pub fn iv_length(&self) -> usize {
585        unsafe { EVP_CIPHER_iv_length(self.as_ptr()) as usize }
586    }
587
588    /// Returns the block size of the cipher.
589    ///
590    /// # Note
591    ///
592    /// Stream ciphers have a block size of 1.
593    #[corresponds(EVP_CIPHER_block_size)]
594    pub fn block_size(&self) -> usize {
595        unsafe { EVP_CIPHER_block_size(self.as_ptr()) as usize }
596    }
597}
598
599#[cfg(test)]
600mod test {
601    #[cfg(ossl300)]
602    use super::Cipher;
603
604    #[test]
605    #[cfg(ossl300)]
606    fn test_cipher_fetch_properties() {
607        assert!(Cipher::fetch(None, "AES-128-GCM", Some("provider=gibberish")).is_err());
608    }
609}