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