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