diff --git a/openssl/Cargo.toml b/openssl/Cargo.toml index 57a5bf1194..ff97db98e9 100644 --- a/openssl/Cargo.toml +++ b/openssl/Cargo.toml @@ -19,6 +19,8 @@ v111 = [] vendored = ['ffi/vendored'] bindgen = ['ffi/bindgen'] +boringssl = ["bssl-ffi"] +default = ["ffi"] [dependencies] bitflags = "1.0" @@ -28,7 +30,8 @@ libc = "0.2" once_cell = "1.5.2" openssl-macros = { version = "0.1.0", path = "../openssl-macros" } -ffi = { package = "openssl-sys", version = "0.9.73", path = "../openssl-sys" } +ffi = { package = "openssl-sys", version = "0.9.73", path = "../openssl-sys", optional = true } +bssl-ffi = { package = "bssl-sys", version = "0.1.0", path = "../../boringssl/build/rust", optional=true } [dev-dependencies] hex = "0.3" diff --git a/openssl/build.rs b/openssl/build.rs index 96ab615e58..bfb5207b1d 100644 --- a/openssl/build.rs +++ b/openssl/build.rs @@ -7,6 +7,11 @@ fn main() { println!("cargo:rustc-cfg=libressl"); } + if env::var("CARGO_FEATURE_BORINGSSL").is_ok() { + println!("cargo:rustc-cfg=boringssl"); + return; + } + if let Ok(v) = env::var("DEP_OPENSSL_LIBRESSL_VERSION") { println!("cargo:rustc-cfg=libressl{}", v); } diff --git a/openssl/src/aes.rs b/openssl/src/aes.rs index 3407199c59..a0447e8561 100644 --- a/openssl/src/aes.rs +++ b/openssl/src/aes.rs @@ -55,6 +55,7 @@ //! assert_eq!(&orig_key[..], &key_to_wrap[..]); //! ``` //! +use cfg_if::cfg_if; use libc::{c_int, c_uint}; use std::mem::MaybeUninit; use std::ptr; @@ -69,6 +70,16 @@ pub struct KeyError(()); /// The key used to encrypt or decrypt cipher blocks. pub struct AesKey(ffi::AES_KEY); +cfg_if! { + if #[cfg(boringssl)] { + type AesBitType = c_uint; + type AesSizeType = usize; + } else { + type AesBitType = c_int; + type AesSizeType = c_uint; + } +} + impl AesKey { /// Prepares a key for encryption. /// @@ -83,7 +94,7 @@ impl AesKey { let mut aes_key = MaybeUninit::uninit(); let r = ffi::AES_set_encrypt_key( key.as_ptr() as *const _, - key.len() as c_int * 8, + key.len() as AesBitType * 8, aes_key.as_mut_ptr(), ); if r == 0 { @@ -107,7 +118,7 @@ impl AesKey { let mut aes_key = MaybeUninit::uninit(); let r = ffi::AES_set_decrypt_key( key.as_ptr() as *const _, - key.len() as c_int * 8, + key.len() as AesBitType * 8, aes_key.as_mut_ptr(), ); @@ -138,6 +149,7 @@ impl AesKey { /// /// Panics if `in_` is not the same length as `out`, if that length is not a multiple of 16, or if /// `iv` is not at least 32 bytes. +#[cfg(not(boringssl))] #[corresponds(AES_ige_encrypt)] pub fn aes_ige(in_: &[u8], out: &mut [u8], key: &AesKey, iv: &mut [u8], mode: Mode) { unsafe { @@ -189,7 +201,7 @@ pub fn wrap_key( .map_or(ptr::null(), |iv| iv.as_ptr() as *const _), out.as_ptr() as *mut _, in_.as_ptr() as *const _, - in_.len() as c_uint, + in_.len() as AesSizeType, ); if written <= 0 { Err(KeyError(())) @@ -228,7 +240,7 @@ pub fn unwrap_key( .map_or(ptr::null(), |iv| iv.as_ptr() as *const _), out.as_ptr() as *mut _, in_.as_ptr() as *const _, - in_.len() as c_uint, + in_.len() as AesSizeType, ); if written <= 0 { @@ -248,6 +260,7 @@ mod test { // From https://www.mgp25.com/AESIGE/ #[test] + #[cfg(not(boringssl))] fn ige_vector_1() { let raw_key = "000102030405060708090A0B0C0D0E0F"; let raw_iv = "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F"; diff --git a/openssl/src/base64.rs b/openssl/src/base64.rs index d53c0c05ab..75822d63b8 100644 --- a/openssl/src/base64.rs +++ b/openssl/src/base64.rs @@ -1,8 +1,13 @@ //! Base64 encoding support. use crate::cvt_n; use crate::error::ErrorStack; -use libc::c_int; use openssl_macros::corresponds; +use libc::{c_int, size_t}; + +#[cfg(not(boringssl))] +type LenType = c_int; +#[cfg(boringssl)] +type LenType = size_t; /// Encodes a slice of bytes to a base64 string. /// @@ -12,7 +17,7 @@ use openssl_macros::corresponds; #[corresponds(EVP_EncodeBlock)] pub fn encode_block(src: &[u8]) -> String { assert!(src.len() <= c_int::max_value() as usize); - let src_len = src.len() as c_int; + let src_len = src.len() as LenType; let len = encoded_len(src_len).unwrap(); let mut out = Vec::with_capacity(len as usize); @@ -43,7 +48,7 @@ pub fn decode_block(src: &str) -> Result, ErrorStack> { } assert!(src.len() <= c_int::max_value() as usize); - let src_len = src.len() as c_int; + let src_len = src.len() as LenType; let len = decoded_len(src_len).unwrap(); let mut out = Vec::with_capacity(len as usize); @@ -72,7 +77,7 @@ pub fn decode_block(src: &str) -> Result, ErrorStack> { Ok(out) } -fn encoded_len(src_len: c_int) -> Option { +fn encoded_len(src_len: LenType) -> Option { let mut len = (src_len / 3).checked_mul(4)?; if src_len % 3 != 0 { @@ -84,7 +89,7 @@ fn encoded_len(src_len: c_int) -> Option { Some(len) } -fn decoded_len(src_len: c_int) -> Option { +fn decoded_len(src_len: LenType) -> Option { let mut len = (src_len / 4).checked_mul(3)?; if src_len % 4 != 0 { diff --git a/openssl/src/bn.rs b/openssl/src/bn.rs index 80cfd04229..dd705d3501 100644 --- a/openssl/src/bn.rs +++ b/openssl/src/bn.rs @@ -43,6 +43,8 @@ cfg_if! { BN_get_rfc3526_prime_2048, BN_get_rfc3526_prime_3072, BN_get_rfc3526_prime_4096, BN_get_rfc3526_prime_6144, BN_get_rfc3526_prime_8192, BN_is_negative, }; + } else if #[cfg(boringssl)] { + use ffi::BN_is_negative; } else { use ffi::{ get_rfc2409_prime_1024 as BN_get_rfc2409_prime_1024, @@ -946,6 +948,7 @@ impl BigNum { /// /// [`RFC 2409`]: https://tools.ietf.org/html/rfc2409#page-21 #[corresponds(BN_get_rfc2409_prime_768)] + #[cfg(not(boringssl))] pub fn get_rfc2409_prime_768() -> Result { unsafe { ffi::init(); @@ -959,6 +962,7 @@ impl BigNum { /// /// [`RFC 2409`]: https://tools.ietf.org/html/rfc2409#page-21 #[corresponds(BN_get_rfc2409_prime_1024)] + #[cfg(not(boringssl))] pub fn get_rfc2409_prime_1024() -> Result { unsafe { ffi::init(); @@ -972,6 +976,7 @@ impl BigNum { /// /// [`RFC 3526`]: https://tools.ietf.org/html/rfc3526#page-3 #[corresponds(BN_get_rfc3526_prime_1536)] + #[cfg(not(boringssl))] pub fn get_rfc3526_prime_1536() -> Result { unsafe { ffi::init(); @@ -985,6 +990,7 @@ impl BigNum { /// /// [`RFC 3526`]: https://tools.ietf.org/html/rfc3526#page-3 #[corresponds(BN_get_rfc3526_prime_2048)] + #[cfg(not(boringssl))] pub fn get_rfc3526_prime_2048() -> Result { unsafe { ffi::init(); @@ -998,6 +1004,7 @@ impl BigNum { /// /// [`RFC 3526`]: https://tools.ietf.org/html/rfc3526#page-4 #[corresponds(BN_get_rfc3526_prime_3072)] + #[cfg(not(boringssl))] pub fn get_rfc3526_prime_3072() -> Result { unsafe { ffi::init(); @@ -1011,6 +1018,7 @@ impl BigNum { /// /// [`RFC 3526`]: https://tools.ietf.org/html/rfc3526#page-4 #[corresponds(BN_get_rfc3526_prime_4096)] + #[cfg(not(boringssl))] pub fn get_rfc3526_prime_4096() -> Result { unsafe { ffi::init(); @@ -1024,6 +1032,7 @@ impl BigNum { /// /// [`RFC 3526`]: https://tools.ietf.org/html/rfc3526#page-6 #[corresponds(BN_get_rfc3526_prime_6114)] + #[cfg(not(boringssl))] pub fn get_rfc3526_prime_6144() -> Result { unsafe { ffi::init(); @@ -1037,6 +1046,7 @@ impl BigNum { /// /// [`RFC 3526`]: https://tools.ietf.org/html/rfc3526#page-6 #[corresponds(BN_get_rfc3526_prime_8192)] + #[cfg(not(boringssl))] pub fn get_rfc3526_prime_8192() -> Result { unsafe { ffi::init(); @@ -1061,12 +1071,12 @@ impl BigNum { unsafe { ffi::init(); assert!(n.len() <= c_int::max_value() as usize); - cvt_p(ffi::BN_bin2bn( - n.as_ptr(), - n.len() as c_int, - ptr::null_mut(), - )) - .map(|p| BigNum::from_ptr(p)) + #[cfg(boringssl)] + let len = n.len(); + #[cfg(not(boringssl))] + let len = n.len() as c_int; + + cvt_p(ffi::BN_bin2bn(n.as_ptr(), len, ptr::null_mut())).map(|p| BigNum::from_ptr(p)) } } } diff --git a/openssl/src/cipher.rs b/openssl/src/cipher.rs index 65f806f997..b11f4f3c4e 100644 --- a/openssl/src/cipher.rs +++ b/openssl/src/cipher.rs @@ -16,7 +16,7 @@ use std::ffi::CString; use std::ptr; cfg_if! { - if #[cfg(any(ossl110, libressl273))] { + if #[cfg(any(boringssl, ossl110, libressl273))] { use ffi::{EVP_CIPHER_block_size, EVP_CIPHER_iv_length, EVP_CIPHER_key_length}; } else { use libc::c_int; @@ -145,34 +145,42 @@ impl Cipher { unsafe { CipherRef::from_ptr(ffi::EVP_aes_128_cbc() as *mut _) } } + #[cfg(not(boringssl))] pub fn aes_128_xts() -> &'static CipherRef { unsafe { CipherRef::from_ptr(ffi::EVP_aes_128_xts() as *mut _) } } + #[cfg(not(boringssl))] pub fn aes_128_ctr() -> &'static CipherRef { unsafe { CipherRef::from_ptr(ffi::EVP_aes_128_ctr() as *mut _) } } + #[cfg(not(boringssl))] pub fn aes_128_cfb1() -> &'static CipherRef { unsafe { CipherRef::from_ptr(ffi::EVP_aes_128_cfb1() as *mut _) } } + #[cfg(not(boringssl))] pub fn aes_128_cfb128() -> &'static CipherRef { unsafe { CipherRef::from_ptr(ffi::EVP_aes_128_cfb128() as *mut _) } } + #[cfg(not(boringssl))] pub fn aes_128_cfb8() -> &'static CipherRef { unsafe { CipherRef::from_ptr(ffi::EVP_aes_128_cfb8() as *mut _) } } + #[cfg(not(boringssl))] pub fn aes_128_gcm() -> &'static CipherRef { unsafe { CipherRef::from_ptr(ffi::EVP_aes_128_gcm() as *mut _) } } + #[cfg(not(boringssl))] pub fn aes_128_ccm() -> &'static CipherRef { unsafe { CipherRef::from_ptr(ffi::EVP_aes_128_ccm() as *mut _) } } + #[cfg(not(boringssl))] pub fn aes_128_ofb() -> &'static CipherRef { unsafe { CipherRef::from_ptr(ffi::EVP_aes_128_ofb() as *mut _) } } @@ -195,6 +203,7 @@ impl Cipher { unsafe { CipherRef::from_ptr(ffi::EVP_aes_192_ctr() as *mut _) } } + #[cfg(not(boringssl))] pub fn aes_192_cfb1() -> &'static CipherRef { unsafe { CipherRef::from_ptr(ffi::EVP_aes_192_cfb1() as *mut _) } } @@ -203,6 +212,7 @@ impl Cipher { unsafe { CipherRef::from_ptr(ffi::EVP_aes_192_cfb128() as *mut _) } } + #[cfg(not(boringssl))] pub fn aes_192_cfb8() -> &'static CipherRef { unsafe { CipherRef::from_ptr(ffi::EVP_aes_192_cfb8() as *mut _) } } @@ -211,6 +221,7 @@ impl Cipher { unsafe { CipherRef::from_ptr(ffi::EVP_aes_192_gcm() as *mut _) } } + #[cfg(not(boringssl))] pub fn aes_192_ccm() -> &'static CipherRef { unsafe { CipherRef::from_ptr(ffi::EVP_aes_192_ccm() as *mut _) } } @@ -237,6 +248,7 @@ impl Cipher { unsafe { CipherRef::from_ptr(ffi::EVP_aes_256_ctr() as *mut _) } } + #[cfg(not(boringssl))] pub fn aes_256_cfb1() -> &'static CipherRef { unsafe { CipherRef::from_ptr(ffi::EVP_aes_256_cfb1() as *mut _) } } @@ -245,6 +257,7 @@ impl Cipher { unsafe { CipherRef::from_ptr(ffi::EVP_aes_256_cfb128() as *mut _) } } + #[cfg(not(boringssl))] pub fn aes_256_cfb8() -> &'static CipherRef { unsafe { CipherRef::from_ptr(ffi::EVP_aes_256_cfb8() as *mut _) } } @@ -253,6 +266,7 @@ impl Cipher { unsafe { CipherRef::from_ptr(ffi::EVP_aes_256_gcm() as *mut _) } } + #[cfg(not(boringssl))] pub fn aes_256_ccm() -> &'static CipherRef { unsafe { CipherRef::from_ptr(ffi::EVP_aes_256_ccm() as *mut _) } } @@ -278,11 +292,13 @@ impl Cipher { } #[cfg(not(osslconf = "OPENSSL_NO_BF"))] + #[cfg(not(boringssl))] pub fn bf_cfb64() -> &'static CipherRef { unsafe { CipherRef::from_ptr(ffi::EVP_bf_cfb64() as *mut _) } } #[cfg(not(osslconf = "OPENSSL_NO_BF"))] + #[cfg(not(boringssl))] pub fn bf_ofb() -> &'static CipherRef { unsafe { CipherRef::from_ptr(ffi::EVP_bf_ofb() as *mut _) } } @@ -303,6 +319,7 @@ impl Cipher { unsafe { CipherRef::from_ptr(ffi::EVP_des_ede3_cbc() as *mut _) } } + #[cfg(not(boringssl))] pub fn des_ede3_cfb64() -> &'static CipherRef { unsafe { CipherRef::from_ptr(ffi::EVP_des_ede3_cfb64() as *mut _) } } @@ -322,21 +339,25 @@ impl Cipher { } #[cfg(not(osslconf = "OPENSSL_NO_SEED"))] + #[cfg(not(boringssl))] pub fn seed_cbc() -> &'static CipherRef { unsafe { CipherRef::from_ptr(ffi::EVP_seed_cbc() as *mut _) } } #[cfg(not(osslconf = "OPENSSL_NO_SEED"))] + #[cfg(not(boringssl))] pub fn seed_cfb128() -> &'static CipherRef { unsafe { CipherRef::from_ptr(ffi::EVP_seed_cfb128() as *mut _) } } #[cfg(not(osslconf = "OPENSSL_NO_SEED"))] + #[cfg(not(boringssl))] pub fn seed_ecb() -> &'static CipherRef { unsafe { CipherRef::from_ptr(ffi::EVP_seed_ecb() as *mut _) } } #[cfg(not(osslconf = "OPENSSL_NO_SEED"))] + #[cfg(not(boringssl))] pub fn seed_ofb() -> &'static CipherRef { unsafe { CipherRef::from_ptr(ffi::EVP_seed_ofb() as *mut _) } } diff --git a/openssl/src/cipher_ctx.rs b/openssl/src/cipher_ctx.rs index 1084a8aa57..3f32ec28e1 100644 --- a/openssl/src/cipher_ctx.rs +++ b/openssl/src/cipher_ctx.rs @@ -56,9 +56,9 @@ use crate::pkey::{HasPrivate, HasPublic, PKey, PKeyRef}; use crate::{cvt, cvt_p}; use cfg_if::cfg_if; use foreign_types::{ForeignType, ForeignTypeRef}; +use std::convert::{TryInto, TryFrom}; use libc::{c_int, c_uchar}; use openssl_macros::corresponds; -use std::convert::TryFrom; use std::ptr; cfg_if! { @@ -182,6 +182,7 @@ impl CipherCtxRef { /// Panics if `pub_keys` is not the same size as `encrypted_keys`, the IV buffer is smaller than the cipher's IV /// size, or if an IV is provided before the cipher. #[corresponds(EVP_SealInit)] + #[cfg(not(boringssl))] pub fn seal_init( &mut self, type_: Option<&CipherRef>, @@ -238,6 +239,7 @@ impl CipherCtxRef { /// Panics if the IV buffer is smaller than the cipher's required IV size or if the IV is provided before the /// cipher. #[corresponds(EVP_OpenInit)] + #[cfg(not(boringssl))] pub fn open_init( &mut self, type_: Option<&CipherRef>, @@ -311,6 +313,7 @@ impl CipherCtxRef { /// /// [`EVP_CIPHER_CTX_rand_key`]: https://www.openssl.org/docs/manmaster/man3/EVP_CIPHER_CTX_rand_key.html #[corresponds(EVP_CIPHER_CTX_rand_key)] + #[cfg(not(boringssl))] pub fn rand_key(&self, buf: &mut [u8]) -> Result<(), ErrorStack> { assert!(buf.len() >= self.key_length()); @@ -338,7 +341,7 @@ impl CipherCtxRef { let len = c_int::try_from(len).unwrap(); unsafe { - cvt(ffi::EVP_CIPHER_CTX_set_key_length(self.as_ptr(), len))?; + cvt(ffi::EVP_CIPHER_CTX_set_key_length(self.as_ptr(), len.try_into().unwrap()))?; } Ok(()) @@ -587,6 +590,7 @@ mod test { use std::slice; #[test] + #[cfg(not(boringssl))] fn seal_open() { let private_pem = include_bytes!("../test/rsa.pem"); let public_pem = include_bytes!("../test/rsa.pem.pub"); diff --git a/openssl/src/conf.rs b/openssl/src/conf.rs index add95f7b48..e21f069802 100644 --- a/openssl/src/conf.rs +++ b/openssl/src/conf.rs @@ -4,8 +4,10 @@ use crate::cvt_p; use crate::error::ErrorStack; use openssl_macros::corresponds; +#[cfg(not(boringssl))] pub struct ConfMethod(*mut ffi::CONF_METHOD); +#[cfg(not(boringssl))] impl ConfMethod { /// Retrieve handle to the default OpenSSL configuration file processing function. #[corresponds(NCONF_default)] @@ -41,6 +43,7 @@ foreign_type_and_impl_send_sync! { pub struct ConfRef; } +#[cfg(not(boringssl))] impl Conf { /// Create a configuration parser. /// diff --git a/openssl/src/dsa.rs b/openssl/src/dsa.rs index 9fa5ff9bd0..7f04f4e473 100644 --- a/openssl/src/dsa.rs +++ b/openssl/src/dsa.rs @@ -7,7 +7,7 @@ use cfg_if::cfg_if; use foreign_types::{ForeignType, ForeignTypeRef}; -use libc::c_int; +use libc::{c_int, c_uint}; use std::fmt; use std::mem; use std::ptr; @@ -178,6 +178,10 @@ where } } } +#[cfg(boringssl)] +type BitType = c_uint; +#[cfg(not(boringssl))] +type BitType = c_int; impl Dsa { /// Generate a DSA key pair. @@ -195,7 +199,7 @@ impl Dsa { let dsa = Dsa::from_ptr(cvt_p(ffi::DSA_new())?); cvt(ffi::DSA_generate_parameters_ex( dsa.0, - bits as c_int, + bits as BitType, ptr::null(), 0, ptr::null_mut(), @@ -397,6 +401,7 @@ mod test { } #[test] + #[cfg(not(boringssl))] fn test_signature() { const TEST_DATA: &[u8] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; let dsa_ref = Dsa::generate(1024).unwrap(); diff --git a/openssl/src/ec.rs b/openssl/src/ec.rs index 8488b88629..13f8bb3dba 100644 --- a/openssl/src/ec.rs +++ b/openssl/src/ec.rs @@ -155,7 +155,7 @@ impl EcGroupRef { /// a term in the polynomial. It will be set to 3 `1`s or 5 `1`s depending on /// using a trinomial or pentanomial. #[corresponds(EC_GROUP_get_curve_GF2m)] - #[cfg(not(osslconf = "OPENSSL_NO_EC2M"))] + #[cfg(not(any(boringssl, osslconf = "OPENSSL_NO_EC2M")))] pub fn components_gf2m( &self, p: &mut BigNumRef, @@ -479,7 +479,7 @@ impl EcPointRef { /// Places affine coordinates of a curve over a binary field in the provided /// `x` and `y` `BigNum`s #[corresponds(EC_POINT_get_affine_coordinates_GF2m)] - #[cfg(not(osslconf = "OPENSSL_NO_EC2M"))] + #[cfg(not(any(boringssl, osslconf = "OPENSSL_NO_EC2M")))] pub fn affine_coordinates_gf2m( &self, group: &EcGroupRef, @@ -1058,7 +1058,7 @@ mod test { } #[test] - #[cfg(not(osslconf = "OPENSSL_NO_EC2M"))] + #[cfg(not(any(boringssl, osslconf = "OPENSSL_NO_EC2M")))] fn is_on_curve() { let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap(); let mut ctx = BigNumContext::new().unwrap(); diff --git a/openssl/src/ecdsa.rs b/openssl/src/ecdsa.rs index c1ea016e33..e0c6c1b5ca 100644 --- a/openssl/src/ecdsa.rs +++ b/openssl/src/ecdsa.rs @@ -2,7 +2,7 @@ use cfg_if::cfg_if; use foreign_types::{ForeignType, ForeignTypeRef}; -use libc::c_int; +use libc::{c_int, size_t}; use std::mem; use std::ptr; @@ -24,6 +24,11 @@ foreign_type_and_impl_send_sync! { pub struct EcdsaSigRef; } +#[cfg(boringssl)] +type LenType = size_t; +#[cfg(not(boringssl))] +type LenType = c_int; + impl EcdsaSig { /// Computes a digital signature of the hash value `data` using the private EC key eckey. #[corresponds(ECDSA_do_sign)] @@ -35,7 +40,7 @@ impl EcdsaSig { assert!(data.len() <= c_int::max_value() as usize); let sig = cvt_p(ffi::ECDSA_do_sign( data.as_ptr(), - data.len() as c_int, + data.len() as LenType, eckey.as_ptr(), ))?; Ok(EcdsaSig::from_ptr(sig)) @@ -80,7 +85,7 @@ impl EcdsaSigRef { assert!(data.len() <= c_int::max_value() as usize); cvt_n(ffi::ECDSA_do_verify( data.as_ptr(), - data.len() as c_int, + data.len() as LenType, self.as_ptr(), eckey.as_ptr(), )) @@ -160,7 +165,7 @@ mod test { #[test] #[cfg_attr(osslconf = "OPENSSL_NO_EC2M", ignore)] fn sign_and_verify() { - let group = EcGroup::from_curve_name(Nid::X9_62_PRIME192V1).unwrap(); + let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap(); let private_key = EcKey::generate(&group).unwrap(); let public_key = get_public_key(&group, &private_key).unwrap(); @@ -188,7 +193,7 @@ mod test { #[test] #[cfg_attr(osslconf = "OPENSSL_NO_EC2M", ignore)] fn check_private_components() { - let group = EcGroup::from_curve_name(Nid::X9_62_PRIME192V1).unwrap(); + let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap(); let private_key = EcKey::generate(&group).unwrap(); let public_key = get_public_key(&group, &private_key).unwrap(); let data = String::from("hello"); @@ -208,7 +213,7 @@ mod test { #[test] #[cfg_attr(osslconf = "OPENSSL_NO_EC2M", ignore)] fn serialize_deserialize() { - let group = EcGroup::from_curve_name(Nid::SECP256K1).unwrap(); + let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap(); let private_key = EcKey::generate(&group).unwrap(); let public_key = get_public_key(&group, &private_key).unwrap(); diff --git a/openssl/src/error.rs b/openssl/src/error.rs index 3d2cfac65e..572937b4e9 100644 --- a/openssl/src/error.rs +++ b/openssl/src/error.rs @@ -16,8 +16,9 @@ //! } //! ``` use cfg_if::cfg_if; -use libc::{c_char, c_int, c_ulong}; +use libc::{c_char, c_int, c_uint, c_ulong}; use std::borrow::Cow; +use std::convert::TryInto; use std::error; use std::ffi::CStr; use std::fmt; @@ -25,6 +26,11 @@ use std::io; use std::ptr; use std::str; +#[cfg(not(boringssl))] +type ErrType = c_ulong; +#[cfg(boringssl)] +type ErrType = c_uint; + /// Collection of [`Error`]s from OpenSSL. /// /// [`Error`]: struct.Error.html @@ -91,7 +97,7 @@ impl From for fmt::Error { /// An error reported from OpenSSL. #[derive(Clone)] pub struct Error { - code: c_ulong, + code: ErrType, file: *const c_char, line: c_int, func: *const c_char, @@ -120,11 +126,14 @@ impl Error { let data = if flags & ffi::ERR_TXT_STRING != 0 { let bytes = CStr::from_ptr(data as *const _).to_bytes(); let data = str::from_utf8(bytes).unwrap(); + #[cfg(not(boringssl))] let data = if flags & ffi::ERR_TXT_MALLOCED != 0 { Cow::Owned(data.to_string()) } else { Cow::Borrowed(data) }; + #[cfg(boringssl)] + let data = Cow::Borrowed(data); Some(data) } else { None @@ -191,13 +200,13 @@ impl Error { ffi::ERR_GET_FUNC(self.code), ffi::ERR_GET_REASON(self.code), self.file, - self.line, + self.line.try_into().unwrap(), ); } } /// Returns the raw OpenSSL error code for this error. - pub fn code(&self) -> c_ulong { + pub fn code(&self) -> ErrType { self.code } @@ -317,7 +326,7 @@ cfg_if! { func: *mut *const c_char, data: *mut *const c_char, flags: *mut c_int, - ) -> c_ulong { + ) -> ErrType { let code = ffi::ERR_get_error_line_data(file, line, data, flags); *func = ffi::ERR_func_error_string(code); code diff --git a/openssl/src/hash.rs b/openssl/src/hash.rs index d4d5ceacef..a7c02fa240 100644 --- a/openssl/src/hash.rs +++ b/openssl/src/hash.rs @@ -65,6 +65,7 @@ impl MessageDigest { } } + #[cfg(not(boringssl))] pub fn null() -> MessageDigest { unsafe { MessageDigest(ffi::EVP_md_null()) } } @@ -123,7 +124,7 @@ impl MessageDigest { unsafe { MessageDigest(ffi::EVP_shake256()) } } - #[cfg(not(osslconf = "OPENSSL_NO_RMD160"))] + #[cfg(not(any(boringssl, osslconf = "OPENSSL_NO_RMD160")))] pub fn ripemd160() -> MessageDigest { unsafe { MessageDigest(ffi::EVP_ripemd160()) } } @@ -285,7 +286,10 @@ impl Hasher { self.init()?; } unsafe { + #[cfg(not(boringssl))] let mut len = ffi::EVP_MAX_MD_SIZE; + #[cfg(boringssl)] + let mut len = ffi::EVP_MAX_MD_SIZE as u32; let mut buf = [0; ffi::EVP_MAX_MD_SIZE as usize]; cvt(ffi::EVP_DigestFinal_ex( self.ctx, @@ -656,6 +660,8 @@ mod tests { } #[test] + #[cfg(not(boringssl))] + #[cfg_attr(ossl300, ignore)] fn test_ripemd160() { #[cfg(ossl300)] let _provider = crate::provider::Provider::try_load(None, "legacy", true).unwrap(); diff --git a/openssl/src/hkdf.rs b/openssl/src/hkdf.rs new file mode 100644 index 0000000000..cc7e5b3a00 --- /dev/null +++ b/openssl/src/hkdf.rs @@ -0,0 +1,89 @@ +use crate::cvt; +use crate::error::ErrorStack; +use crate::md::MdRef; +use foreign_types::ForeignTypeRef; +use openssl_macros::corresponds; + +/// Computes HKDF (as specified by RFC 5869). +/// +/// HKDF is an Extract-and-Expand algorithm. It does not do any key stretching, +/// and as such, is not suited to be used alone to generate a key from a +/// password. +#[corresponds(HKDF)] +#[inline] +pub fn hkdf( + out_key: &mut [u8], + md: &MdRef, + secret: &[u8], + salt: &[u8], + info: &[u8], +) -> Result<(), ErrorStack> { + unsafe { + cvt(ffi::HKDF( + out_key.as_mut_ptr(), + out_key.len(), + md.as_ptr(), + secret.as_ptr(), + secret.len(), + salt.as_ptr(), + salt.len(), + info.as_ptr(), + info.len(), + ))?; + } + + Ok(()) +} + +/// Computes a HKDF PRK (as specified by RFC 5869). +/// +/// WARNING: This function orders the inputs differently from RFC 5869 +/// specification. Double-check which parameter is the secret/IKM and which is +/// the salt when using. +#[corresponds(HKDF_extract)] +#[inline] +pub fn hkdf_extract<'a>( + out_key: &'a mut [u8], + md: &MdRef, + secret: &[u8], + salt: &[u8], +) -> Result<&'a [u8], ErrorStack> { + let mut out_len = out_key.len(); + unsafe { + cvt(ffi::HKDF_extract( + out_key.as_mut_ptr(), + &mut out_len, + md.as_ptr(), + secret.as_ptr(), + secret.len(), + salt.as_ptr(), + salt.len(), + ))?; + } + + Ok(&out_key[..out_len]) +} + +/// Computes a HKDF OKM (as specified by RFC 5869). +#[corresponds(HKDF_expand)] +#[inline] +pub fn hkdf_expand( + out_key: &mut [u8], + md: &MdRef, + prk: &[u8], + info: &[u8], +) -> Result<(), ErrorStack> { + unsafe { + cvt(ffi::HKDF_expand( + out_key.as_mut_ptr(), + out_key.len(), + md.as_ptr(), + prk.as_ptr(), + prk.len(), + info.as_ptr(), + info.len(), + ))?; + } + + Ok(()) +} diff --git a/openssl/src/lib.rs b/openssl/src/lib.rs index 71221adecc..9059f4d54f 100644 --- a/openssl/src/lib.rs +++ b/openssl/src/lib.rs @@ -120,6 +120,9 @@ #![doc(html_root_url = "https://docs.rs/openssl/0.10")] #![warn(rust_2018_idioms)] +#[cfg(boringssl)] +extern crate bssl_ffi as ffi; + #[doc(inline)] pub use ffi::init; @@ -139,7 +142,7 @@ pub mod base64; pub mod bn; pub mod cipher; pub mod cipher_ctx; -#[cfg(all(not(libressl), not(osslconf = "OPENSSL_NO_CMS")))] +#[cfg(all(not(boringssl), not(libressl), not(osslconf = "OPENSSL_NO_CMS")))] pub mod cms; pub mod conf; pub mod derive; @@ -148,22 +151,27 @@ pub mod dsa; pub mod ec; pub mod ecdsa; pub mod encrypt; +#[cfg(not(boringssl))] pub mod envelope; pub mod error; pub mod ex_data; #[cfg(not(any(libressl, ossl300)))] pub mod fips; pub mod hash; +#[cfg(boringssl)] +pub mod hkdf; #[cfg(ossl300)] pub mod lib_ctx; pub mod md; pub mod md_ctx; pub mod memcmp; pub mod nid; -#[cfg(not(osslconf = "OPENSSL_NO_OCSP"))] +#[cfg(not(any(boringssl, osslconf = "OPENSSL_NO_OCSP")))] pub mod ocsp; pub mod pkcs12; +#[cfg(not(boringssl))] pub mod pkcs5; +#[cfg(not(boringssl))] pub mod pkcs7; pub mod pkey; pub mod pkey_ctx; diff --git a/openssl/src/macros.rs b/openssl/src/macros.rs index c448bcd6ef..671a11b82d 100644 --- a/openssl/src/macros.rs +++ b/openssl/src/macros.rs @@ -106,10 +106,11 @@ macro_rules! from_der { ($(#[$m:meta])* $n:ident, $t:ty, $f:path) => { $(#[$m])* pub fn $n(der: &[u8]) -> Result<$t, crate::error::ErrorStack> { + use std::convert::TryInto; unsafe { ffi::init(); let len = ::std::cmp::min(der.len(), ::libc::c_long::max_value() as usize) as ::libc::c_long; - crate::cvt_p($f(::std::ptr::null_mut(), &mut der.as_ptr(), len)) + crate::cvt_p($f(::std::ptr::null_mut(), &mut der.as_ptr(), len.try_into().unwrap())) .map(|p| ::foreign_types::ForeignType::from_ptr(p)) } } diff --git a/openssl/src/md.rs b/openssl/src/md.rs index 922521e9f6..b9297e29a7 100644 --- a/openssl/src/md.rs +++ b/openssl/src/md.rs @@ -113,6 +113,7 @@ impl Md { } #[inline] + #[cfg(not(boringssl))] pub fn null() -> &'static MdRef { unsafe { MdRef::from_ptr(ffi::EVP_md_null() as *mut _) } } @@ -185,12 +186,14 @@ impl Md { #[cfg(not(osslconf = "OPENSSL_NO_RMD160"))] #[inline] + #[cfg(not(boringssl))] pub fn ripemd160() -> &'static MdRef { unsafe { MdRef::from_ptr(ffi::EVP_ripemd160() as *mut _) } } #[cfg(all(any(ossl111, libressl291), not(osslconf = "OPENSSL_NO_SM3")))] #[inline] + #[cfg(not(boringssl))] pub fn sm3() -> &'static MdRef { unsafe { MdRef::from_ptr(ffi::EVP_sm3() as *mut _) } } diff --git a/openssl/src/nid.rs b/openssl/src/nid.rs index 1fe5df2748..d4544285db 100644 --- a/openssl/src/nid.rs +++ b/openssl/src/nid.rs @@ -120,9 +120,11 @@ impl Nid { pub const UNDEF: Nid = Nid(ffi::NID_undef); pub const ITU_T: Nid = Nid(ffi::NID_itu_t); + #[cfg(not(boringssl))] pub const CCITT: Nid = Nid(ffi::NID_ccitt); pub const ISO: Nid = Nid(ffi::NID_iso); pub const JOINT_ISO_ITU_T: Nid = Nid(ffi::NID_joint_iso_itu_t); + #[cfg(not(boringssl))] pub const JOINT_ISO_CCITT: Nid = Nid(ffi::NID_joint_iso_ccitt); pub const MEMBER_BODY: Nid = Nid(ffi::NID_member_body); pub const IDENTIFIED_ORGANIZATION: Nid = Nid(ffi::NID_identified_organization); diff --git a/openssl/src/pkcs12.rs b/openssl/src/pkcs12.rs index 3bc4749e01..758c7b9c51 100644 --- a/openssl/src/pkcs12.rs +++ b/openssl/src/pkcs12.rs @@ -76,7 +76,7 @@ impl Pkcs12 { /// * `nid_cert` - `AES_256_CBC` (3.0.0+) or `PBE_WITHSHA1AND40BITRC2_CBC` /// * `iter` - `2048` /// * `mac_iter` - `2048` - /// * `mac_md` - `SHA-256` (3.0.0+) or `SHA-1` + /// * `mac_md` - `SHA-256` (3.0.0+) or `SHA-1` (`SHA-1` only for BoringSSL) pub fn builder() -> Pkcs12Builder { ffi::init(); @@ -85,6 +85,7 @@ impl Pkcs12 { nid_cert: Nid::UNDEF, iter: ffi::PKCS12_DEFAULT_ITER, mac_iter: ffi::PKCS12_DEFAULT_ITER, + #[cfg(not(boringssl))] mac_md: None, ca: None, } @@ -102,6 +103,7 @@ pub struct Pkcs12Builder { nid_cert: Nid, iter: c_int, mac_iter: c_int, + #[cfg(not(boringssl))] mac_md: Option, ca: Option>, } @@ -135,6 +137,7 @@ impl Pkcs12Builder { } /// MAC message digest type + #[cfg(not(boringssl))] pub fn mac_md(&mut self, md: MessageDigest) -> &mut Self { self.mac_md = Some(md); self @@ -178,10 +181,6 @@ impl Pkcs12Builder { .unwrap_or(ptr::null_mut()); let nid_key = self.nid_key.as_raw(); let nid_cert = self.nid_cert.as_raw(); - let md_type = self - .mac_md - .map(|md_type| md_type.as_ptr()) - .unwrap_or(ptr::null()); // According to the OpenSSL docs, keytype is a non-standard extension for MSIE, // It's values are KEY_SIG or KEY_EX, see the OpenSSL docs for more information: @@ -202,15 +201,25 @@ impl Pkcs12Builder { )) .map(Pkcs12)?; - cvt(ffi::PKCS12_set_mac( - pkcs12.as_ptr(), - pass.as_ptr(), - -1, - ptr::null_mut(), - 0, - self.mac_iter, - md_type, - ))?; + #[cfg(not(boringssl))] + // BoringSSL does not support overriding the MAC and will always + // use SHA-1 + { + let md_type = self + .mac_md + .map(|md_type| md_type.as_ptr()) + .unwrap_or(ptr::null()); + + cvt(ffi::PKCS12_set_mac( + pkcs12.as_ptr(), + pass.as_ptr(), + -1, + ptr::null_mut(), + 0, + self.mac_iter, + md_type, + ))?; + } Ok(pkcs12) } diff --git a/openssl/src/pkey.rs b/openssl/src/pkey.rs index 420c16e0d7..d85e1bdc5d 100644 --- a/openssl/src/pkey.rs +++ b/openssl/src/pkey.rs @@ -78,7 +78,9 @@ pub struct Id(c_int); impl Id { pub const RSA: Id = Id(ffi::EVP_PKEY_RSA); + #[cfg(not(boringssl))] pub const HMAC: Id = Id(ffi::EVP_PKEY_HMAC); +#[cfg(not(boringssl))] pub const CMAC: Id = Id(ffi::EVP_PKEY_CMAC); pub const DSA: Id = Id(ffi::EVP_PKEY_DSA); pub const DH: Id = Id(ffi::EVP_PKEY_DH); @@ -347,6 +349,7 @@ impl fmt::Debug for PKey { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { let alg = match self.id() { Id::RSA => "RSA", + #[cfg(not(boringssl))] Id::HMAC => "HMAC", Id::DSA => "DSA", Id::DH => "DH", @@ -441,6 +444,7 @@ impl PKey { /// /// To compute HMAC values, use the `sign` module. #[corresponds(EVP_PKEY_new_mac_key)] + #[cfg(not(boringssl))] pub fn hmac(key: &[u8]) -> Result, ErrorStack> { unsafe { assert!(key.len() <= c_int::max_value() as usize); @@ -461,7 +465,7 @@ impl PKey { /// # Note /// /// To compute CMAC values, use the `sign` module. - #[cfg(ossl110)] + #[cfg(any(not(boringssl), ossl110))] #[allow(clippy::trivially_copy_pass_by_ref)] pub fn cmac(cipher: &Cipher, key: &[u8]) -> Result, ErrorStack> { let mut ctx = PkeyCtx::new_id(Id::CMAC)?; @@ -679,7 +683,7 @@ impl PKey { } cfg_if! { - if #[cfg(any(ossl110, libressl270))] { + if #[cfg(any(boringssl, ossl110, libressl270))] { use ffi::EVP_PKEY_up_ref; } else { #[allow(bad_style)] @@ -879,6 +883,7 @@ mod tests { } #[test] + #[cfg(not(boringssl))] fn test_dh_accessor() { let dh = include_bytes!("../test/dhparams.pem"); let dh = Dh::params_from_pem(dh).unwrap(); @@ -927,6 +932,7 @@ mod tests { } #[test] + #[cfg(not(boringssl))] fn test_dh_conversion() { let dh_params = include_bytes!("../test/dhparams.pem"); let dh_params = Dh::params_from_pem(dh_params).unwrap(); diff --git a/openssl/src/pkey_ctx.rs b/openssl/src/pkey_ctx.rs index 52be72f1a8..a1d8a22373 100644 --- a/openssl/src/pkey_ctx.rs +++ b/openssl/src/pkey_ctx.rs @@ -64,6 +64,8 @@ use crate::error::ErrorStack; use crate::md::MdRef; use crate::pkey::{HasPrivate, HasPublic, Id, PKey, PKeyRef, Private}; use crate::rsa::Padding; +#[cfg(any(boringssl, ossl102, libressl310))] +use crate::util; use crate::{cvt, cvt_n, cvt_p}; use foreign_types::{ForeignType, ForeignTypeRef}; use libc::c_int; @@ -415,6 +417,7 @@ impl PkeyCtxRef { } /// Sets the cipher used during key generation. + #[cfg(not(boringssl))] #[corresponds(EVP_PKEY_CTX_ctrl)] #[inline] pub fn set_keygen_cipher(&mut self, cipher: &CipherRef) -> Result<(), ErrorStack> { @@ -433,6 +436,7 @@ impl PkeyCtxRef { } /// Sets the key MAC key used during key generation. + #[cfg(not(boringssl))] #[corresponds(EVP_PKEY_CTX_ctrl)] #[inline] pub fn set_keygen_mac_key(&mut self, key: &[u8]) -> Result<(), ErrorStack> { @@ -663,6 +667,7 @@ mod test { } #[test] + #[cfg(not(boringssl))] fn cmac_keygen() { let mut ctx = PkeyCtx::new_id(Id::CMAC).unwrap(); ctx.keygen_init().unwrap(); diff --git a/openssl/src/rand.rs b/openssl/src/rand.rs index 3a54b33f04..ff1dd44b21 100644 --- a/openssl/src/rand.rs +++ b/openssl/src/rand.rs @@ -10,12 +10,17 @@ //! let mut buf = [0; 256]; //! rand_bytes(&mut buf).unwrap(); //! ``` -use libc::c_int; +use libc::{c_int, size_t}; use crate::cvt; use crate::error::ErrorStack; use openssl_macros::corresponds; +#[cfg(not(boringssl))] +type RandType = c_int; +#[cfg(boringssl)] +type RandType = size_t; + /// Fill buffer with cryptographically strong pseudo-random bytes. /// /// # Examples @@ -33,7 +38,7 @@ pub fn rand_bytes(buf: &mut [u8]) -> Result<(), ErrorStack> { unsafe { ffi::init(); assert!(buf.len() <= c_int::max_value() as usize); - cvt(ffi::RAND_bytes(buf.as_mut_ptr(), buf.len() as c_int)).map(|_| ()) + cvt(ffi::RAND_bytes(buf.as_mut_ptr(), buf.len() as RandType)).map(|_| ()) } } @@ -44,7 +49,7 @@ pub fn rand_bytes(buf: &mut [u8]) -> Result<(), ErrorStack> { #[cfg(ossl111)] pub fn keep_random_devices_open(keep: bool) { unsafe { - ffi::RAND_keep_random_devices_open(keep as c_int); + ffi::RAND_keep_random_devices_open(keep as RandType); } } diff --git a/openssl/src/rsa.rs b/openssl/src/rsa.rs index c96e21d8d7..0bb9e71e7a 100644 --- a/openssl/src/rsa.rs +++ b/openssl/src/rsa.rs @@ -25,7 +25,7 @@ //! ``` use cfg_if::cfg_if; use foreign_types::{ForeignType, ForeignTypeRef}; -use libc::c_int; +use libc::{c_int, size_t}; use std::fmt; use std::mem; use std::ptr; @@ -37,6 +37,11 @@ use crate::util::ForeignTypeRefExt; use crate::{cvt, cvt_n, cvt_p}; use openssl_macros::corresponds; +#[cfg(boringssl)] +type BitType = size_t; +#[cfg(not(boringssl))] +type BitType = c_int; + /// Type of encryption padding to use. /// /// Random length padding is primarily used to prevent attackers from @@ -134,7 +139,7 @@ where unsafe { let len = cvt_n(ffi::RSA_private_decrypt( - from.len() as c_int, + from.len() as BitType, from.as_ptr(), to.as_mut_ptr(), self.as_ptr(), @@ -162,7 +167,7 @@ where unsafe { let len = cvt_n(ffi::RSA_private_encrypt( - from.len() as c_int, + from.len() as BitType, from.as_ptr(), to.as_mut_ptr(), self.as_ptr(), @@ -305,7 +310,7 @@ where unsafe { let len = cvt_n(ffi::RSA_public_decrypt( - from.len() as c_int, + from.len() as BitType, from.as_ptr(), to.as_mut_ptr(), self.as_ptr(), @@ -332,7 +337,7 @@ where unsafe { let len = cvt_n(ffi::RSA_public_encrypt( - from.len() as c_int, + from.len() as BitType, from.as_ptr(), to.as_mut_ptr(), self.as_ptr(), diff --git a/openssl/src/sign.rs b/openssl/src/sign.rs index d813623530..77b8de9875 100644 --- a/openssl/src/sign.rs +++ b/openssl/src/sign.rs @@ -700,6 +700,7 @@ mod test { assert!(!verifier.verify(&Vec::from_hex(SIGNATURE).unwrap()).unwrap()); } + #[cfg(not(boringssl))] fn test_hmac(ty: MessageDigest, tests: &[(Vec, Vec, Vec)]) { for &(ref key, ref data, ref res) in tests.iter() { let pkey = PKey::hmac(key).unwrap(); @@ -710,6 +711,7 @@ mod test { } #[test] + #[cfg(not(boringssl))] fn hmac_md5() { // test vectors from RFC 2202 let tests: [(Vec, Vec, Vec); 7] = [ @@ -756,6 +758,7 @@ mod test { } #[test] + #[cfg(not(boringssl))] fn hmac_sha1() { // test vectors from RFC 2202 let tests: [(Vec, Vec, Vec); 7] = [ diff --git a/openssl/src/srtp.rs b/openssl/src/srtp.rs index bddddaf49b..7ed3135963 100644 --- a/openssl/src/srtp.rs +++ b/openssl/src/srtp.rs @@ -36,12 +36,16 @@ impl SrtpProtectionProfileRef { pub struct SrtpProfileId(c_ulong); impl SrtpProfileId { - pub const SRTP_AES128_CM_SHA1_80: SrtpProfileId = SrtpProfileId(ffi::SRTP_AES128_CM_SHA1_80); - pub const SRTP_AES128_CM_SHA1_32: SrtpProfileId = SrtpProfileId(ffi::SRTP_AES128_CM_SHA1_32); - pub const SRTP_AES128_F8_SHA1_80: SrtpProfileId = SrtpProfileId(ffi::SRTP_AES128_F8_SHA1_80); - pub const SRTP_AES128_F8_SHA1_32: SrtpProfileId = SrtpProfileId(ffi::SRTP_AES128_F8_SHA1_32); - pub const SRTP_NULL_SHA1_80: SrtpProfileId = SrtpProfileId(ffi::SRTP_NULL_SHA1_80); - pub const SRTP_NULL_SHA1_32: SrtpProfileId = SrtpProfileId(ffi::SRTP_NULL_SHA1_32); + pub const SRTP_AES128_CM_SHA1_80: SrtpProfileId = + SrtpProfileId(ffi::SRTP_AES128_CM_SHA1_80 as c_ulong); + pub const SRTP_AES128_CM_SHA1_32: SrtpProfileId = + SrtpProfileId(ffi::SRTP_AES128_CM_SHA1_32 as c_ulong); + pub const SRTP_AES128_F8_SHA1_80: SrtpProfileId = + SrtpProfileId(ffi::SRTP_AES128_F8_SHA1_80 as c_ulong); + pub const SRTP_AES128_F8_SHA1_32: SrtpProfileId = + SrtpProfileId(ffi::SRTP_AES128_F8_SHA1_32 as c_ulong); + pub const SRTP_NULL_SHA1_80: SrtpProfileId = SrtpProfileId(ffi::SRTP_NULL_SHA1_80 as c_ulong); + pub const SRTP_NULL_SHA1_32: SrtpProfileId = SrtpProfileId(ffi::SRTP_NULL_SHA1_32 as c_ulong); #[cfg(ossl110)] pub const SRTP_AEAD_AES_128_GCM: SrtpProfileId = SrtpProfileId(ffi::SRTP_AEAD_AES_128_GCM); #[cfg(ossl110)] diff --git a/openssl/src/ssl/callbacks.rs b/openssl/src/ssl/callbacks.rs index f33f6ec0aa..e4db9dc634 100644 --- a/openssl/src/ssl/callbacks.rs +++ b/openssl/src/ssl/callbacks.rs @@ -388,7 +388,7 @@ pub unsafe extern "C" fn raw_remove_session( } cfg_if! { - if #[cfg(any(ossl110, libressl280))] { + if #[cfg(any(ossl110, libressl280, boringssl))] { type DataPtr = *const c_uchar; } else { type DataPtr = *mut c_uchar; @@ -486,6 +486,7 @@ where (*callback)(ssl, slice) as c_int } +#[cfg(not(boringssl))] pub extern "C" fn raw_cookie_generate( ssl: *mut ffi::SSL, cookie: *mut c_uchar, diff --git a/openssl/src/ssl/connector.rs b/openssl/src/ssl/connector.rs index e398458010..1039425f80 100644 --- a/openssl/src/ssl/connector.rs +++ b/openssl/src/ssl/connector.rs @@ -27,15 +27,19 @@ ssbzSibBsu/6iGtCOGEoXJf//////////wIBAg== fn ctx(method: SslMethod) -> Result { let mut ctx = SslContextBuilder::new(method)?; - let mut opts = SslOptions::ALL - | SslOptions::NO_COMPRESSION - | SslOptions::NO_SSLV2 - | SslOptions::NO_SSLV3 - | SslOptions::SINGLE_DH_USE - | SslOptions::SINGLE_ECDH_USE; - opts &= !SslOptions::DONT_INSERT_EMPTY_FRAGMENTS; - - ctx.set_options(opts); + cfg_if! { + if #[cfg(not(boringssl))] { + let mut opts = SslOptions::ALL + | SslOptions::NO_COMPRESSION + | SslOptions::NO_SSLV2 + | SslOptions::NO_SSLV3 + | SslOptions::SINGLE_DH_USE + | SslOptions::SINGLE_ECDH_USE; + opts &= !SslOptions::DONT_INSERT_EMPTY_FRAGMENTS; + + ctx.set_options(opts); + } + } let mut mode = SslMode::AUTO_RETRY | SslMode::ACCEPT_MOVING_WRITE_BUFFER | SslMode::ENABLE_PARTIAL_WRITE; diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index 6896a22f10..fd5facdbe1 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -57,6 +57,27 @@ //! } //! } //! ``` +// use bitflags::bitflags; +// use cfg_if::cfg_if; +// use foreign_types::{ForeignType, ForeignTypeRef, Opaque}; +use libc::{c_char, c_int, c_long, c_uchar, c_uint, c_ulong, c_void}; +// use once_cell::sync::{Lazy, OnceCell}; +// use std::any::TypeId; +// use std::cmp; +// use std::collections::HashMap; +// use std::ffi::{CStr, CString}; +// use std::fmt; +// use std::io; +// use std::io::prelude::*; +// use std::marker::PhantomData; +// use std::mem::{self, ManuallyDrop}; +// use std::ops::{Deref, DerefMut}; +// use std::panic::resume_unwind; +// use std::path::Path; +// use std::ptr; +// use std::slice; +// use std::str; +// use std::sync::{Arc, Mutex}; use crate::dh::{Dh, DhRef}; #[cfg(all(ossl101, not(ossl110)))] use crate::ec::EcKey; @@ -82,7 +103,6 @@ use crate::{cvt, cvt_n, cvt_p, init}; use bitflags::bitflags; use cfg_if::cfg_if; use foreign_types::{ForeignType, ForeignTypeRef, Opaque}; -use libc::{c_char, c_int, c_long, c_uchar, c_uint, c_void}; use once_cell::sync::{Lazy, OnceCell}; use openssl_macros::corresponds; use std::any::TypeId; @@ -134,6 +154,8 @@ pub fn cipher_name(std_name: &str) -> &'static str { cfg_if! { if #[cfg(ossl300)] { type SslOptionsRepr = u64; + } else if #[cfg(boringssl)] { + type SslOptionsRepr = i32; } else { type SslOptionsRepr = libc::c_ulong; } @@ -146,6 +168,7 @@ bitflags! { const DONT_INSERT_EMPTY_FRAGMENTS = ffi::SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS; /// A "reasonable default" set of options which enables compatibility flags. + #[cfg(not(boringssl))] const ALL = ffi::SSL_OP_ALL; /// Do not query the MTU. @@ -158,16 +181,19 @@ bitflags! { /// Only affects DTLS connections. /// /// [RFC 4347 Section 4.2.1]: https://tools.ietf.org/html/rfc4347#section-4.2.1 + #[cfg(not(boringssl))] const COOKIE_EXCHANGE = ffi::SSL_OP_COOKIE_EXCHANGE; /// Disables the use of session tickets for session resumption. const NO_TICKET = ffi::SSL_OP_NO_TICKET; /// Always start a new session when performing a renegotiation on the server side. + #[cfg(not(boringssl))] const NO_SESSION_RESUMPTION_ON_RENEGOTIATION = ffi::SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION; /// Disables the use of TLS compression. + #[cfg(not(boringssl))] const NO_COMPRESSION = ffi::SSL_OP_NO_COMPRESSION; /// Allow legacy insecure renegotiation with servers or clients that do not support secure @@ -261,7 +287,7 @@ bitflags! { bitflags! { /// Options controlling the behavior of an `SslContext`. - pub struct SslMode: c_long { + pub struct SslMode: SslBitType { /// Enables "short writes". /// /// Normally, a write in OpenSSL will always write out all of the requested data, even if it @@ -378,9 +404,19 @@ bitflags! { } } +#[cfg(boringssl)] +type SslBitType = c_int; +#[cfg(not(boringssl))] +type SslBitType = c_long; + +#[cfg(boringssl)] +type SslTimeTy = c_ulong; +#[cfg(not(boringssl))] +type SslTimeTy = c_long; + bitflags! { /// Options controlling the behavior of session caching. - pub struct SslSessionCacheMode: c_long { + pub struct SslSessionCacheMode: SslBitType { /// No session caching for the client or server takes place. const OFF = ffi::SSL_SESS_CACHE_OFF; @@ -616,6 +652,26 @@ impl SslVersion { pub const TLS1_3: SslVersion = SslVersion(ffi::TLS1_3_VERSION); } +cfg_if! { + if #[cfg(boringssl)] { + type SslTy = i32; + type SslModeTy = i32; + type SslCacheTy = i64; + type SslCacheSize = c_ulong; + type MtuTy = u32; + type BitTy = u32; + type SizeTy = usize; + } else { + type SslTy = u64; + type SslModeTy = i64; + type SslCacheTy = i64; + type SslCacheSize = c_long; + type MtuTy = i64; + type BitTy = u64; + type SizeTy = u32; + } +} + /// A standard implementation of protocol selection for Application Layer Protocol Negotiation /// (ALPN). /// @@ -723,9 +779,12 @@ impl SslContextBuilder { let arg = self.set_ex_data_inner(SslContext::cached_ex_index::(), callback); ffi::SSL_CTX_set_tlsext_servername_arg(self.as_ptr(), arg); - ffi::SSL_CTX_set_tlsext_servername_callback__fixed_rust( + let f: extern "C" fn(_, _, _) -> _ = raw_sni::; + #[cfg(not(boringssl))] + let f: extern "C" fn() = mem::transmute(f); + ffi::SSL_CTX_set_tlsext_servername_callback( self.as_ptr(), - Some(raw_sni::), + Some(f), ); } } @@ -773,7 +832,7 @@ impl SslContextBuilder { #[corresponds(SSL_CTX_set_read_ahead)] pub fn set_read_ahead(&mut self, read_ahead: bool) { unsafe { - ffi::SSL_CTX_set_read_ahead(self.as_ptr(), read_ahead as c_long); + ffi::SSL_CTX_set_read_ahead(self.as_ptr(), read_ahead as SslBitType); } } @@ -781,7 +840,7 @@ impl SslContextBuilder { #[corresponds(SSL_CTX_set_mode)] pub fn set_mode(&mut self, mode: SslMode) -> SslMode { unsafe { - let bits = ffi::SSL_CTX_set_mode(self.as_ptr(), mode.bits()); + let bits = ffi::SSL_CTX_set_mode(self.as_ptr(), mode.bits() as MtuTy) as SslModeTy; SslMode { bits } } } @@ -805,7 +864,11 @@ impl SslContextBuilder { { unsafe { self.set_ex_data(SslContext::cached_ex_index::(), callback); + + #[cfg(not(boringssl))] ffi::SSL_CTX_set_tmp_dh_callback__fixed_rust(self.as_ptr(), Some(raw_tmp_dh::)); + #[cfg(boringssl)] + ffi::SSL_CTX_set_tmp_dh_callback(self.as_ptr(), Some(raw_tmp_dh::)); } } @@ -895,7 +958,7 @@ impl SslContextBuilder { cvt(ffi::SSL_CTX_set_session_id_context( self.as_ptr(), sid_ctx.as_ptr(), - sid_ctx.len() as c_uint, + sid_ctx.len() as SizeTy, )) .map(|_| ()) } @@ -1048,21 +1111,23 @@ impl SslContextBuilder { /// `clear_options` for that. #[corresponds(SSL_CTX_set_options)] pub fn set_options(&mut self, option: SslOptions) -> SslOptions { - let bits = unsafe { ffi::SSL_CTX_set_options(self.as_ptr(), option.bits()) }; + let bits = + unsafe { ffi::SSL_CTX_set_options(self.as_ptr(), option.bits() as BitTy) } as SslTy; SslOptions { bits } } /// Returns the options used by the context. #[corresponds(SSL_CTX_get_options)] pub fn options(&self) -> SslOptions { - let bits = unsafe { ffi::SSL_CTX_get_options(self.as_ptr()) }; + let bits = unsafe { ffi::SSL_CTX_get_options(self.as_ptr()) } as SslTy; SslOptions { bits } } /// Clears the options used by the context, returning the old set. #[corresponds(SSL_CTX_clear_options)] pub fn clear_options(&mut self, option: SslOptions) -> SslOptions { - let bits = unsafe { ffi::SSL_CTX_clear_options(self.as_ptr(), option.bits()) }; + let bits = + unsafe { ffi::SSL_CTX_clear_options(self.as_ptr(), option.bits() as BitTy) } as SslTy; SslOptions { bits } } @@ -1464,6 +1529,7 @@ impl SslContextBuilder { /// The callback will be called with the SSL context and a slice into which the cookie /// should be written. The callback should return the number of bytes written. #[corresponds(SSL_CTX_set_cookie_generate_cb)] + #[cfg(not(boringssl))] pub fn set_cookie_generate_cb(&mut self, callback: F) where F: Fn(&mut SslRef, &mut [u8]) -> Result + 'static + Sync + Send, @@ -1479,6 +1545,7 @@ impl SslContextBuilder { /// The callback will be called with the SSL context and the cookie supplied by the /// client. It should return true if and only if the cookie is valid. #[corresponds(SSL_CTX_set_cookie_verify_cb)] + #[cfg(not(boringssl))] pub fn set_cookie_verify_cb(&mut self, callback: F) where F: Fn(&mut SslRef, &[u8]) -> bool + 'static + Sync + Send, @@ -1603,7 +1670,9 @@ impl SslContextBuilder { #[corresponds(SSL_CTX_sess_set_cache_size)] #[allow(clippy::useless_conversion)] pub fn set_session_cache_size(&mut self, size: i32) -> i64 { - unsafe { ffi::SSL_CTX_sess_set_cache_size(self.as_ptr(), size.into()).into() } + unsafe { + ffi::SSL_CTX_sess_set_cache_size(self.as_ptr(), size as SslCacheSize) as SslCacheTy + } } /// Sets the context's supported signature algorithms. @@ -1694,6 +1763,9 @@ impl SslContext { { unsafe { ffi::init(); + #[cfg(boringssl)] + let idx = cvt_n(get_new_idx(Some(free_data_box::)))?; + #[cfg(not(boringssl))] let idx = cvt_n(get_new_idx(free_data_box::))?; Ok(Index::from_raw(idx)) } @@ -1810,7 +1882,7 @@ impl SslContextRef { #[corresponds(SSL_CTX_sess_get_cache_size)] #[allow(clippy::useless_conversion)] pub fn session_cache_size(&self) -> i64 { - unsafe { ffi::SSL_CTX_sess_get_cache_size(self.as_ptr()).into() } + unsafe { ffi::SSL_CTX_sess_get_cache_size(self.as_ptr()) as c_long } } /// Returns the verify mode that was set on this context from [`SslContextBuilder::set_verify`]. @@ -2045,8 +2117,8 @@ impl SslSessionRef { /// Returns the time at which the session was established, in seconds since the Unix epoch. #[corresponds(SSL_SESSION_get_time)] #[allow(clippy::useless_conversion)] - pub fn time(&self) -> i64 { - unsafe { ffi::SSL_SESSION_get_time(self.as_ptr()).into() } + pub fn time(&self) -> SslTimeTy { + unsafe { ffi::SSL_SESSION_get_time(self.as_ptr()) } } /// Returns the sessions timeout, in seconds. @@ -2114,6 +2186,9 @@ impl Ssl { { unsafe { ffi::init(); + #[cfg(boringssl)] + let idx = cvt_n(get_new_ssl_idx(Some(free_data_box::)))?; + #[cfg(not(boringssl))] let idx = cvt_n(get_new_ssl_idx(free_data_box::))?; Ok(Index::from_raw(idx)) } @@ -2284,7 +2359,10 @@ impl SslRef { unsafe { // this needs to be in an Arc since the callback can register a new callback! self.set_ex_data(Ssl::cached_ex_index(), Arc::new(callback)); - ffi::SSL_set_tmp_dh_callback__fixed_rust(self.as_ptr(), Some(raw_tmp_dh_ssl::)); + #[cfg(boringssl)] + ffi::SSL_set_tmp_dh_callback(self.as_ptr(), Some(raw_tmp_dh_ssl::)); + #[cfg(not(boringssl))] + ffi::SSL_set_tmp_dh_callback(self.as_ptr(), raw_tmp_dh_ssl::); } } @@ -2770,6 +2848,7 @@ impl SslRef { /// Returns the server's OCSP response, if present. #[corresponds(SSL_get_tlsext_status_ocsp_resp)] + #[cfg(not(boringssl))] pub fn ocsp_status(&self) -> Option<&[u8]> { unsafe { let mut p = ptr::null_mut(); @@ -2785,6 +2864,7 @@ impl SslRef { /// Sets the OCSP response to be returned to the client. #[corresponds(SSL_set_tlsext_status_oscp_resp)] + #[cfg(not(boringssl))] pub fn set_ocsp_status(&mut self, response: &[u8]) -> Result<(), ErrorStack> { unsafe { assert!(response.len() <= c_int::max_value() as usize); @@ -2793,7 +2873,7 @@ impl SslRef { cvt(ffi::SSL_set_tlsext_status_ocsp_resp( self.as_ptr(), p as *mut c_uchar, - response.len() as c_long, + response.len() as i64, ) as c_int) .map(|_| ()) } @@ -3005,7 +3085,7 @@ impl SslRef { /// Sets the MTU used for DTLS connections. #[corresponds(SSL_set_mtu)] pub fn set_mtu(&mut self, mtu: u32) -> Result<(), ErrorStack> { - unsafe { cvt(ffi::SSL_set_mtu(self.as_ptr(), mtu as c_long) as c_int).map(|_| ()) } + unsafe { cvt(ffi::SSL_set_mtu(self.as_ptr(), mtu as MtuTy) as c_int).map(|_| ()) } } } @@ -3677,7 +3757,7 @@ bitflags! { } cfg_if! { - if #[cfg(any(ossl110, libressl273))] { + if #[cfg(any(boringssl, ossl110, libressl273))] { use ffi::{SSL_CTX_up_ref, SSL_SESSION_get_master_key, SSL_SESSION_up_ref, SSL_is_server}; } else { #[allow(bad_style)] @@ -3735,7 +3815,7 @@ cfg_if! { } } cfg_if! { - if #[cfg(any(ossl110, libressl291))] { + if #[cfg(any(boringssl, ossl110, libressl291))] { use ffi::{TLS_method, DTLS_method, TLS_client_method, TLS_server_method}; } else { use ffi::{ @@ -3774,20 +3854,38 @@ cfg_if! { // hack around https://rt.openssl.org/Ticket/Display.html?id=3710&user=guest&pass=guest static ONCE: Once = Once::new(); ONCE.call_once(|| { - ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), None, None, None); + cfg_if! { + if #[cfg(not(boringssl))] { + ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), None, None, None); + } else { + ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, None); + } + } }); - ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), None, None, Some(f)) + cfg_if! { + if #[cfg(not(boringssl))] { + ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), None, None, Some(f)) + } else { + ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, f) + } + } } unsafe fn get_new_ssl_idx(f: ffi::CRYPTO_EX_free) -> c_int { // hack around https://rt.openssl.org/Ticket/Display.html?id=3710&user=guest&pass=guest static ONCE: Once = Once::new(); ONCE.call_once(|| { + #[cfg(not(boringssl))] ffi::SSL_get_ex_new_index(0, ptr::null_mut(), None, None, None); + #[cfg(boringssl)] + ffi::SSL_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, None); }); - ffi::SSL_get_ex_new_index(0, ptr::null_mut(), None, None, Some(f)) + #[cfg(not(boringssl))] + return ffi::SSL_get_ex_new_index(0, ptr::null_mut(), None, None, Some(f)); + #[cfg(boringssl)] + return ffi::SSL_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, f); } } } diff --git a/openssl/src/ssl/test/mod.rs b/openssl/src/ssl/test/mod.rs index de64a3e020..8bd2ed0b97 100644 --- a/openssl/src/ssl/test/mod.rs +++ b/openssl/src/ssl/test/mod.rs @@ -17,6 +17,7 @@ use std::time::Duration; use crate::dh::Dh; use crate::error::ErrorStack; use crate::hash::MessageDigest; +#[cfg(not(boringssl))] use crate::ocsp::{OcspResponse, OcspResponseStatus}; use crate::pkey::PKey; use crate::srtp::SrtpProfileId; @@ -247,6 +248,7 @@ fn set_ctx_options() { } #[test] +#[cfg(not(boringssl))] fn clear_ctx_options() { let mut ctx = SslContext::builder(SslMethod::tls()).unwrap(); ctx.set_options(SslOptions::ALL); @@ -294,7 +296,10 @@ fn state() { let server = Server::builder().build(); let s = server.client().connect(); + #[cfg(not(boringssl))] assert_eq!(s.ssl().state_string().trim(), "SSLOK"); + #[cfg(boringssl)] + assert_eq!(s.ssl().state_string(), "!!!!!!"); assert_eq!( s.ssl().state_string_long(), "SSL negotiation finished successfully" @@ -838,7 +843,7 @@ fn cert_store() { } #[test] -#[cfg_attr(all(libressl321, not(libressl340)), ignore)] +#[cfg_attr(any(all(libressl321, not(libressl340)), boringssl), ignore)] fn tmp_dh_callback() { static CALLED_BACK: AtomicBool = AtomicBool::new(false); @@ -886,7 +891,7 @@ fn tmp_ecdh_callback() { } #[test] -#[cfg_attr(all(libressl321, not(libressl340)), ignore)] +#[cfg_attr(any(all(libressl321, not(libressl340)), boringssl), ignore)] fn tmp_dh_callback_ssl() { static CALLED_BACK: AtomicBool = AtomicBool::new(false); @@ -963,6 +968,7 @@ fn active_session() { } #[test] +#[cfg(not(boringssl))] fn status_callbacks() { static CALLED_BACK_SERVER: AtomicBool = AtomicBool::new(false); static CALLED_BACK_CLIENT: AtomicBool = AtomicBool::new(false); @@ -1305,7 +1311,7 @@ fn stateless() { #[cfg(not(osslconf = "OPENSSL_NO_PSK"))] #[test] fn psk_ciphers() { - const CIPHER: &str = "PSK-AES128-CBC-SHA"; + const CIPHER: &str = "PSK-AES256-CBC-SHA"; const PSK: &[u8] = b"thisisaverysecurekey"; const CLIENT_IDENT: &[u8] = b"thisisaclient"; static CLIENT_CALLED: AtomicBool = AtomicBool::new(false); @@ -1314,7 +1320,9 @@ fn psk_ciphers() { let mut server = Server::builder(); server.ctx().set_cipher_list(CIPHER).unwrap(); server.ctx().set_psk_server_callback(|_, identity, psk| { + eprintln!("hello???!"); assert!(identity.unwrap_or(&[]) == CLIENT_IDENT); + eprintln!("hello???!"); psk[..PSK.len()].copy_from_slice(PSK); SERVER_CALLED.store(true, Ordering::SeqCst); Ok(PSK.len()) @@ -1330,6 +1338,7 @@ fn psk_ciphers() { client .ctx() .set_psk_client_callback(move |_, _, identity, psk| { + eprintln!("hello???! 2"); identity[..CLIENT_IDENT.len()].copy_from_slice(CLIENT_IDENT); identity[CLIENT_IDENT.len()] = 0; psk[..PSK.len()].copy_from_slice(PSK); @@ -1339,7 +1348,8 @@ fn psk_ciphers() { client.connect(); - assert!(CLIENT_CALLED.load(Ordering::SeqCst) && SERVER_CALLED.load(Ordering::SeqCst)); + assert!(SERVER_CALLED.load(Ordering::SeqCst)); + assert!(CLIENT_CALLED.load(Ordering::SeqCst)); } #[test] diff --git a/openssl/src/stack.rs b/openssl/src/stack.rs index 2c21b57bf0..70098df1d9 100644 --- a/openssl/src/stack.rs +++ b/openssl/src/stack.rs @@ -1,6 +1,6 @@ use cfg_if::cfg_if; use foreign_types::{ForeignType, ForeignTypeRef, Opaque}; -use libc::c_int; +use libc::{c_int, size_t}; use std::borrow::Borrow; use std::convert::AsRef; use std::fmt; @@ -13,6 +13,11 @@ use crate::error::ErrorStack; use crate::util::ForeignTypeExt; use crate::{cvt, cvt_p}; +#[cfg(not(boringssl))] +type IdxType = c_int; +#[cfg(boringssl)] +type IdxType = size_t; + cfg_if! { if #[cfg(ossl110)] { use ffi::{ @@ -80,7 +85,7 @@ impl iter::IntoIterator for Stack { fn into_iter(self) -> IntoIter { let it = IntoIter { stack: self.0, - idxs: 0..self.len() as c_int, + idxs: 0..self.len() as IdxType, }; mem::forget(self); it @@ -135,7 +140,7 @@ impl DerefMut for Stack { pub struct IntoIter { stack: *mut T::StackType, - idxs: Range, + idxs: Range, } impl Drop for IntoIter { @@ -204,13 +209,13 @@ impl StackRef { pub fn iter(&self) -> Iter<'_, T> { Iter { stack: self, - idxs: 0..self.len() as c_int, + idxs: 0..self.len() as IdxType, } } pub fn iter_mut(&mut self) -> IterMut<'_, T> { IterMut { - idxs: 0..self.len() as c_int, + idxs: 0..self.len() as IdxType, stack: self, } } @@ -242,7 +247,7 @@ impl StackRef { /// Pushes a value onto the top of the stack. pub fn push(&mut self, data: T) -> Result<(), ErrorStack> { unsafe { - cvt(OPENSSL_sk_push(self.as_stack(), data.as_ptr() as *mut _))?; + cvt(OPENSSL_sk_push(self.as_stack(), data.as_ptr() as *mut _) as c_int)?; mem::forget(data); Ok(()) } @@ -257,7 +262,7 @@ impl StackRef { } unsafe fn _get(&self, idx: usize) -> *mut T::CType { - OPENSSL_sk_value(self.as_stack(), idx as c_int) as *mut _ + OPENSSL_sk_value(self.as_stack(), idx as IdxType) as *mut _ } } @@ -314,7 +319,7 @@ impl<'a, T: Stackable> iter::IntoIterator for &'a mut Stack { /// An iterator over the stack's contents. pub struct Iter<'a, T: Stackable> { stack: &'a StackRef, - idxs: Range, + idxs: Range, } impl<'a, T: Stackable> Iterator for Iter<'a, T> { @@ -348,7 +353,7 @@ impl<'a, T: Stackable> ExactSizeIterator for Iter<'a, T> {} /// A mutable iterator over the stack's contents. pub struct IterMut<'a, T: Stackable> { stack: &'a mut StackRef, - idxs: Range, + idxs: Range, } impl<'a, T: Stackable> Iterator for IterMut<'a, T> { diff --git a/openssl/src/string.rs b/openssl/src/string.rs index df151b23ea..559218e8df 100644 --- a/openssl/src/string.rs +++ b/openssl/src/string.rs @@ -80,6 +80,17 @@ impl fmt::Debug for OpensslStringRef { } #[inline] +#[cfg(not(boringssl))] unsafe fn free(buf: *mut c_char) { ffi::OPENSSL_free(buf as *mut c_void); } + +#[inline] +#[cfg(boringssl)] +unsafe fn free(buf: *mut c_char) { + ffi::CRYPTO_free( + buf as *mut c_void, + concat!(file!(), "\0").as_ptr() as *const c_char, + line!() as ::libc::c_int, + ); +} diff --git a/openssl/src/symm.rs b/openssl/src/symm.rs index e228c71495..8b75d8fb72 100644 --- a/openssl/src/symm.rs +++ b/openssl/src/symm.rs @@ -51,6 +51,11 @@ //! assert_eq!("Foo bar", output_string); //! println!("Decrypted: '{}'", output_string); //! ``` + +use libc::{c_int, c_uint}; +use std::cmp; +use std::ptr; + use crate::cipher::CipherRef; use crate::cipher_ctx::{CipherCtx, CipherCtxRef}; use crate::error::ErrorStack; @@ -105,6 +110,7 @@ impl Cipher { unsafe { Cipher(ffi::EVP_aes_128_cbc()) } } + #[cfg(not(boringssl))] pub fn aes_128_xts() -> Cipher { unsafe { Cipher(ffi::EVP_aes_128_xts()) } } @@ -113,6 +119,7 @@ impl Cipher { unsafe { Cipher(ffi::EVP_aes_128_ctr()) } } + #[cfg(not(boringssl))] pub fn aes_128_cfb1() -> Cipher { unsafe { Cipher(ffi::EVP_aes_128_cfb1()) } } @@ -121,6 +128,7 @@ impl Cipher { unsafe { Cipher(ffi::EVP_aes_128_cfb128()) } } + #[cfg(not(boringssl))] pub fn aes_128_cfb8() -> Cipher { unsafe { Cipher(ffi::EVP_aes_128_cfb8()) } } @@ -129,6 +137,7 @@ impl Cipher { unsafe { Cipher(ffi::EVP_aes_128_gcm()) } } + #[cfg(not(boringssl))] pub fn aes_128_ccm() -> Cipher { unsafe { Cipher(ffi::EVP_aes_128_ccm()) } } @@ -155,6 +164,7 @@ impl Cipher { unsafe { Cipher(ffi::EVP_aes_192_ctr()) } } + #[cfg(not(boringssl))] pub fn aes_192_cfb1() -> Cipher { unsafe { Cipher(ffi::EVP_aes_192_cfb1()) } } @@ -163,6 +173,7 @@ impl Cipher { unsafe { Cipher(ffi::EVP_aes_192_cfb128()) } } + #[cfg(not(boringssl))] pub fn aes_192_cfb8() -> Cipher { unsafe { Cipher(ffi::EVP_aes_192_cfb8()) } } @@ -171,6 +182,7 @@ impl Cipher { unsafe { Cipher(ffi::EVP_aes_192_gcm()) } } + #[cfg(not(boringssl))] pub fn aes_192_ccm() -> Cipher { unsafe { Cipher(ffi::EVP_aes_192_ccm()) } } @@ -193,6 +205,7 @@ impl Cipher { unsafe { Cipher(ffi::EVP_aes_256_cbc()) } } + #[cfg(not(boringssl))] pub fn aes_256_xts() -> Cipher { unsafe { Cipher(ffi::EVP_aes_256_xts()) } } @@ -201,6 +214,7 @@ impl Cipher { unsafe { Cipher(ffi::EVP_aes_256_ctr()) } } + #[cfg(not(boringssl))] pub fn aes_256_cfb1() -> Cipher { unsafe { Cipher(ffi::EVP_aes_256_cfb1()) } } @@ -209,6 +223,7 @@ impl Cipher { unsafe { Cipher(ffi::EVP_aes_256_cfb128()) } } + #[cfg(not(boringssl))] pub fn aes_256_cfb8() -> Cipher { unsafe { Cipher(ffi::EVP_aes_256_cfb8()) } } @@ -217,6 +232,7 @@ impl Cipher { unsafe { Cipher(ffi::EVP_aes_256_gcm()) } } + #[cfg(not(boringssl))] pub fn aes_256_ccm() -> Cipher { unsafe { Cipher(ffi::EVP_aes_256_ccm()) } } @@ -241,12 +257,12 @@ impl Cipher { unsafe { Cipher(ffi::EVP_bf_ecb()) } } - #[cfg(not(osslconf = "OPENSSL_NO_BF"))] + #[cfg(not(any(boringssl, osslconf = "OPENSSL_NO_BF")))] pub fn bf_cfb64() -> Cipher { unsafe { Cipher(ffi::EVP_bf_cfb64()) } } - #[cfg(not(osslconf = "OPENSSL_NO_BF"))] + #[cfg(not(any(boringssl, osslconf = "OPENSSL_NO_BF")))] pub fn bf_ofb() -> Cipher { unsafe { Cipher(ffi::EVP_bf_ofb()) } } @@ -267,6 +283,7 @@ impl Cipher { unsafe { Cipher(ffi::EVP_des_ede3_cbc()) } } + #[cfg(not(boringssl))] pub fn des_ede3_cfb64() -> Cipher { unsafe { Cipher(ffi::EVP_des_ede3_cfb64()) } } @@ -287,22 +304,22 @@ impl Cipher { unsafe { Cipher(ffi::EVP_chacha20_poly1305()) } } - #[cfg(not(osslconf = "OPENSSL_NO_SEED"))] + #[cfg(not(any(boringssl, osslconf = "OPENSSL_NO_SEED")))] pub fn seed_cbc() -> Cipher { unsafe { Cipher(ffi::EVP_seed_cbc()) } } - #[cfg(not(osslconf = "OPENSSL_NO_SEED"))] + #[cfg(not(any(boringssl, osslconf = "OPENSSL_NO_SEED")))] pub fn seed_cfb128() -> Cipher { unsafe { Cipher(ffi::EVP_seed_cfb128()) } } - #[cfg(not(osslconf = "OPENSSL_NO_SEED"))] + #[cfg(not(any(boringssl, osslconf = "OPENSSL_NO_SEED")))] pub fn seed_ecb() -> Cipher { unsafe { Cipher(ffi::EVP_seed_ecb()) } } - #[cfg(not(osslconf = "OPENSSL_NO_SEED"))] + #[cfg(not(any(boringssl, osslconf = "OPENSSL_NO_SEED")))] pub fn seed_ofb() -> Cipher { unsafe { Cipher(ffi::EVP_seed_ofb()) } } @@ -352,11 +369,17 @@ impl Cipher { } /// Determines whether the cipher is using CCM mode + #[cfg(not(boringssl))] fn is_ccm(self) -> bool { // NOTE: OpenSSL returns pointers to static structs, which makes this work as expected self == Cipher::aes_128_ccm() || self == Cipher::aes_256_ccm() } + #[cfg(boringssl)] + fn is_ccm(self) -> bool { + false + } + /// Determines whether the cipher is using OCB mode #[cfg(ossl110)] fn is_ocb(self) -> bool { @@ -731,24 +754,29 @@ pub fn decrypt_aead( Ok(out) } +#[cfg(not(boringssl))] +type CipherRet = c_int; +#[cfg(boringssl)] +type CipherRet = c_uint; + cfg_if! { - if #[cfg(any(ossl110, libressl273))] { + if #[cfg(any(boringssl, ossl110, libressl273))] { use ffi::{EVP_CIPHER_block_size, EVP_CIPHER_iv_length, EVP_CIPHER_key_length}; } else { use libc::c_int; #[allow(bad_style)] - pub unsafe fn EVP_CIPHER_iv_length(ptr: *const ffi::EVP_CIPHER) -> c_int { + pub unsafe fn EVP_CIPHER_iv_length(ptr: *const ffi::EVP_CIPHER) -> CipherRet { (*ptr).iv_len } #[allow(bad_style)] - pub unsafe fn EVP_CIPHER_block_size(ptr: *const ffi::EVP_CIPHER) -> c_int { + pub unsafe fn EVP_CIPHER_block_size(ptr: *const ffi::EVP_CIPHER) -> CipherRet { (*ptr).block_size } #[allow(bad_style)] - pub unsafe fn EVP_CIPHER_key_length(ptr: *const ffi::EVP_CIPHER) -> c_int { + pub unsafe fn EVP_CIPHER_key_length(ptr: *const ffi::EVP_CIPHER) -> CipherRet { (*ptr).key_len } } @@ -923,6 +951,7 @@ mod tests { } #[test] + #[cfg(not(boringssl))] fn test_aes256_xts() { // Test case 174 from // http://csrc.nist.gov/groups/STM/cavp/documents/aes/XTSTestVectors.zip @@ -950,6 +979,7 @@ mod tests { } #[test] + #[cfg(not(boringssl))] fn test_aes128_cfb1() { // Lifted from http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf @@ -962,6 +992,7 @@ mod tests { } #[test] + #[cfg(not(boringssl))] fn test_aes128_cfb128() { let pt = "6bc1bee22e409f96e93d7e117393172a"; let ct = "3b3fd92eb72dad20333449f8e83cfb4a"; @@ -972,6 +1003,7 @@ mod tests { } #[test] + #[cfg(not(boringssl))] fn test_aes128_cfb8() { let pt = "6bc1bee22e409f96e93d7e117393172aae2d"; let ct = "3b79424c9c0dd436bace9e0ed4586a4f32b9"; @@ -1006,6 +1038,7 @@ mod tests { } #[test] + #[cfg(not(boringssl))] fn test_aes192_cfb1() { // Lifted from http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf @@ -1018,6 +1051,7 @@ mod tests { } #[test] + #[cfg(not(boringssl))] fn test_aes192_cfb128() { // Lifted from http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf @@ -1030,6 +1064,7 @@ mod tests { } #[test] + #[cfg(not(boringssl))] fn test_aes192_cfb8() { // Lifted from http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf @@ -1054,6 +1089,7 @@ mod tests { } #[test] + #[cfg(not(boringssl))] fn test_aes256_cfb1() { let pt = "6bc1"; let ct = "9029"; @@ -1064,6 +1100,7 @@ mod tests { } #[test] + #[cfg(not(boringssl))] fn test_aes256_cfb128() { let pt = "6bc1bee22e409f96e93d7e117393172a"; let ct = "dc7e84bfda79164b7ecd8486985d3860"; @@ -1074,6 +1111,7 @@ mod tests { } #[test] + #[cfg(not(boringssl))] fn test_aes256_cfb8() { let pt = "6bc1bee22e409f96e93d7e117393172aae2d"; let ct = "dc1f1a8520a64db55fcc8ac554844e889700"; @@ -1096,6 +1134,8 @@ mod tests { } #[test] + #[cfg_attr(ossl300, ignore)] + #[cfg(not(boringssl))] fn test_bf_cbc() { #[cfg(ossl300)] let _provider = crate::provider::Provider::try_load(None, "legacy", true).unwrap(); @@ -1111,6 +1151,8 @@ mod tests { } #[test] + #[cfg_attr(ossl300, ignore)] + #[cfg(not(boringssl))] fn test_bf_ecb() { #[cfg(ossl300)] let _provider = crate::provider::Provider::try_load(None, "legacy", true).unwrap(); @@ -1124,6 +1166,8 @@ mod tests { } #[test] + #[cfg_attr(ossl300, ignore)] + #[cfg(not(boringssl))] fn test_bf_cfb64() { #[cfg(ossl300)] let _provider = crate::provider::Provider::try_load(None, "legacy", true).unwrap(); @@ -1137,6 +1181,8 @@ mod tests { } #[test] + #[cfg_attr(ossl300, ignore)] + #[cfg(not(boringssl))] fn test_bf_ofb() { #[cfg(ossl300)] let _provider = crate::provider::Provider::try_load(None, "legacy", true).unwrap(); @@ -1196,6 +1242,7 @@ mod tests { } #[test] + #[cfg(not(boringssl))] fn test_des_ede3_cfb64() { let pt = "2b1773784b5889dc788477367daa98ad"; let ct = "6f2867cfefda048a4046ef7e556c7132"; @@ -1242,6 +1289,7 @@ mod tests { } #[test] + #[cfg(not(boringssl))] fn test_aes128_ccm() { let key = "3ee186594f110fb788a8bf8aa8be5d4a"; let nonce = "44f705d52acf27b7f17196aa9b"; @@ -1278,6 +1326,7 @@ mod tests { } #[test] + #[cfg(not(boringssl))] fn test_aes128_ccm_verify_fail() { let key = "3ee186594f110fb788a8bf8aa8be5d4a"; let nonce = "44f705d52acf27b7f17196aa9b"; @@ -1298,6 +1347,7 @@ mod tests { } #[test] + #[cfg(not(boringssl))] fn test_aes256_ccm() { let key = "7f4af6765cad1d511db07e33aaafd57646ec279db629048aa6770af24849aa0d"; let nonce = "dde2a362ce81b2b6913abc3095"; @@ -1334,6 +1384,7 @@ mod tests { } #[test] + #[cfg(not(boringssl))] fn test_aes256_ccm_verify_fail() { let key = "7f4af6765cad1d511db07e33aaafd57646ec279db629048aa6770af24849aa0d"; let nonce = "dde2a362ce81b2b6913abc3095"; @@ -1466,7 +1517,7 @@ mod tests { } #[test] - #[cfg(not(osslconf = "OPENSSL_NO_SEED"))] + #[cfg(not(any(boringssl, osslconf = "OPENSSL_NO_SEED", ossl300)))] fn test_seed_cbc() { #[cfg(ossl300)] let _provider = crate::provider::Provider::try_load(None, "legacy", true).unwrap(); @@ -1480,7 +1531,7 @@ mod tests { } #[test] - #[cfg(not(osslconf = "OPENSSL_NO_SEED"))] + #[cfg(not(any(boringssl, osslconf = "OPENSSL_NO_SEED", ossl300)))] fn test_seed_cfb128() { #[cfg(ossl300)] let _provider = crate::provider::Provider::try_load(None, "legacy", true).unwrap(); @@ -1494,7 +1545,7 @@ mod tests { } #[test] - #[cfg(not(osslconf = "OPENSSL_NO_SEED"))] + #[cfg(not(any(boringssl, osslconf = "OPENSSL_NO_SEED", ossl300)))] fn test_seed_ecb() { #[cfg(ossl300)] let _provider = crate::provider::Provider::try_load(None, "legacy", true).unwrap(); @@ -1508,7 +1559,7 @@ mod tests { } #[test] - #[cfg(not(osslconf = "OPENSSL_NO_SEED"))] + #[cfg(not(any(boringssl, osslconf = "OPENSSL_NO_SEED", ossl300)))] fn test_seed_ofb() { #[cfg(ossl300)] let _provider = crate::provider::Provider::try_load(None, "legacy", true).unwrap(); diff --git a/openssl/src/util.rs b/openssl/src/util.rs index d852a4b9d8..be04030498 100644 --- a/openssl/src/util.rs +++ b/openssl/src/util.rs @@ -1,6 +1,9 @@ use crate::error::ErrorStack; use foreign_types::{ForeignType, ForeignTypeRef}; +use std::convert::TryFrom; use libc::{c_char, c_int, c_void}; +use crate::{cvt, cvt_p}; +use cfg_if::cfg_if; use std::any::Any; use std::panic::{self, AssertUnwindSafe}; use std::slice; @@ -91,3 +94,30 @@ pub trait ForeignTypeRefExt: ForeignTypeRef { } } impl ForeignTypeRefExt for FT {} + +#[track_caller] +#[inline] +pub fn crypto_malloc(len: usize) -> Result<*mut c_void, ErrorStack> { + // 1.0.2 uses c_int but 1.1.0+ uses size_t + let len = TryFrom::try_from(len).unwrap(); + + unsafe { + cvt_p(ffi::CRYPTO_malloc( + len, + concat!(file!(), "\0").as_ptr() as *const _, + line!() as _, + )) + } +} + +#[track_caller] +#[inline] +pub unsafe fn crypto_free(ptr: *mut c_void) { + cfg_if! { + if #[cfg(any(ossl110, boringssl))] { + ffi::CRYPTO_free(ptr, concat!(file!(), "\0").as_ptr() as *const _, line!() as _); + } else { + ffi::CRYPTO_free(ptr); + } + } +} diff --git a/openssl/src/version.rs b/openssl/src/version.rs index 17799e1d01..da9d24e9fc 100644 --- a/openssl/src/version.rs +++ b/openssl/src/version.rs @@ -109,7 +109,7 @@ fn test_versions() { println!("Platform: '{}'", platform()); println!("Dir: '{}'", dir()); - #[cfg(not(libressl))] + #[cfg(not(any(libressl, boringssl)))] fn expected_name() -> &'static str { "OpenSSL" } @@ -117,6 +117,10 @@ fn test_versions() { fn expected_name() -> &'static str { "LibreSSL" } + #[cfg(boringssl)] + fn expected_name() -> &'static str { + "BoringSSL" + } assert!(number() > 0); assert!(version().starts_with(expected_name())); diff --git a/openssl/src/x509/mod.rs b/openssl/src/x509/mod.rs index 02b89549a3..62e566d880 100644 --- a/openssl/src/x509/mod.rs +++ b/openssl/src/x509/mod.rs @@ -9,7 +9,7 @@ use cfg_if::cfg_if; use foreign_types::{ForeignType, ForeignTypeRef}; -use libc::{c_int, c_long}; +use libc::{c_int, c_long, c_uint}; use std::cmp; use std::error::Error; use std::ffi::{CStr, CString}; @@ -369,6 +369,11 @@ foreign_type_and_impl_send_sync! { pub struct X509Ref; } +#[cfg(boringssl)] +type X509LenTy = c_uint; +#[cfg(not(boringssl))] +type X509LenTy = c_int; + impl X509Ref { /// Returns this certificate's subject name. #[corresponds(X509_get_subject_name)] @@ -460,7 +465,7 @@ impl X509Ref { buf: [0; ffi::EVP_MAX_MD_SIZE as usize], len: ffi::EVP_MAX_MD_SIZE as usize, }; - let mut len = ffi::EVP_MAX_MD_SIZE; + let mut len = ffi::EVP_MAX_MD_SIZE as c_uint; cvt(ffi::X509_digest( self.as_ptr(), hash_type.as_ptr(), @@ -673,7 +678,7 @@ impl X509 { ffi::PEM_read_bio_X509(bio.as_ptr(), ptr::null_mut(), None, ptr::null_mut()); if r.is_null() { let err = ffi::ERR_peek_last_error(); - if ffi::ERR_GET_LIB(err) == ffi::ERR_LIB_PEM + if ffi::ERR_GET_LIB(err) as X509LenTy == ffi::ERR_LIB_PEM && ffi::ERR_GET_REASON(err) == ffi::PEM_R_NO_START_LINE { ffi::ERR_clear_error(); @@ -1440,8 +1445,13 @@ impl GeneralNameRef { return None; } - let ptr = ASN1_STRING_get0_data((*self.as_ptr()).d as *mut _); - let len = ffi::ASN1_STRING_length((*self.as_ptr()).d as *mut _); + #[cfg(boringssl)] + let d: *const ffi::ASN1_STRING = std::mem::transmute((*self.as_ptr()).d); + #[cfg(not(boringssl))] + let d = (*self.as_ptr()).d; + + let ptr = ASN1_STRING_get0_data(d as *mut _); + let len = ffi::ASN1_STRING_length(d as *mut _); let slice = slice::from_raw_parts(ptr as *const u8, len as usize); // IA5Strings are stated to be ASCII (specifically IA5). Hopefully @@ -1472,9 +1482,13 @@ impl GeneralNameRef { if (*self.as_ptr()).type_ != ffi::GEN_IPADD { return None; } + #[cfg(boringssl)] + let d: *const ffi::ASN1_STRING = std::mem::transmute((*self.as_ptr()).d); + #[cfg(not(boringssl))] + let d = (*self.as_ptr()).d; - let ptr = ASN1_STRING_get0_data((*self.as_ptr()).d as *mut _); - let len = ffi::ASN1_STRING_length((*self.as_ptr()).d as *mut _); + let ptr = ASN1_STRING_get0_data(d as *mut _); + let len = ffi::ASN1_STRING_length(d as *mut _); Some(slice::from_raw_parts(ptr as *const u8, len as usize)) } @@ -1573,7 +1587,7 @@ impl Stackable for X509Object { } cfg_if! { - if #[cfg(any(ossl110, libressl273))] { + if #[cfg(any(boringssl, ossl110, libressl273))] { use ffi::{X509_getm_notAfter, X509_getm_notBefore, X509_up_ref, X509_get0_signature}; } else { #[allow(bad_style)] @@ -1614,7 +1628,7 @@ cfg_if! { } cfg_if! { - if #[cfg(any(ossl110, libressl350))] { + if #[cfg(any(boringssl, ossl110, libressl350))] { use ffi::{ X509_ALGOR_get0, ASN1_STRING_get0_data, X509_STORE_CTX_get0_chain, X509_set1_notAfter, X509_set1_notBefore, X509_REQ_get_version, X509_REQ_get_subject_name, @@ -1654,7 +1668,7 @@ cfg_if! { } cfg_if! { - if #[cfg(any(ossl110, libressl270))] { + if #[cfg(any(ossl110, boringssl, libressl270))] { use ffi::X509_OBJECT_get0_X509; } else { #[allow(bad_style)] @@ -1671,6 +1685,8 @@ cfg_if! { cfg_if! { if #[cfg(any(ossl110, libressl350))] { use ffi::X509_OBJECT_free; + } else if #[cfg(boringssl)] { + use ffi::X509_OBJECT_free_contents as X509_OBJECT_free; } else { #[allow(bad_style)] unsafe fn X509_OBJECT_free(x: *mut ffi::X509_OBJECT) { diff --git a/openssl/src/x509/store.rs b/openssl/src/x509/store.rs index a4d2444970..f4835d9bec 100644 --- a/openssl/src/x509/store.rs +++ b/openssl/src/x509/store.rs @@ -143,6 +143,7 @@ impl X509Lookup { } } +#[cfg(not(boringssl))] impl X509LookupRef { /// Specifies a directory from which certificates and CRLs will be loaded /// on-demand. Must be used with `X509Lookup::hash_dir`. @@ -189,7 +190,7 @@ impl X509StoreRef { } cfg_if! { - if #[cfg(any(ossl110, libressl270))] { + if #[cfg(any(boringssl, ossl110, libressl270))] { use ffi::X509_STORE_get0_objects; } else { #[allow(bad_style)] diff --git a/openssl/src/x509/tests.rs b/openssl/src/x509/tests.rs index 90cb8a5c4a..e5bb96233f 100644 --- a/openssl/src/x509/tests.rs +++ b/openssl/src/x509/tests.rs @@ -39,6 +39,9 @@ fn test_debug() { let cert = include_bytes!("../../test/cert.pem"); let cert = X509::from_pem(cert).unwrap(); let debugged = format!("{:#?}", cert); + #[cfg(boringssl)] + assert!(debugged.contains(r#"serial_number: "8771f7bdee982fa5""#)); + #[cfg(not(boringssl))] assert!(debugged.contains(r#"serial_number: "8771F7BDEE982FA5""#)); assert!(debugged.contains(r#"signature_algorithm: sha256WithRSAEncryption"#)); assert!(debugged.contains(r#"countryName = "AU""#));