| From 5c9103f02cb56f0f04444b16dd67eeaa05429d47 Mon Sep 17 00:00:00 2001 | 
 | From: Nabil Wadih <nwadih@google.com> | 
 | Date: Thu, 24 Aug 2023 15:51:26 -0700 | 
 | Subject: [PATCH] Apply android patches | 
 |  | 
 | --- | 
 |  openssl/.cargo/config.toml |   2 + | 
 |  openssl/src/asn1.rs        |   2 +- | 
 |  openssl/src/bio.rs         |   6 +- | 
 |  openssl/src/bn.rs          |   2 +- | 
 |  openssl/src/cipher.rs      |   4 + | 
 |  openssl/src/dh.rs          |   2 +- | 
 |  openssl/src/dsa.rs         |   5 +- | 
 |  openssl/src/ec.rs          |  20 ++++ | 
 |  openssl/src/ecdsa.rs       |   2 +- | 
 |  openssl/src/encrypt.rs     |   4 +- | 
 |  openssl/src/hash.rs        |   2 +- | 
 |  openssl/src/hkdf.rs        |  89 +++++++++++++++ | 
 |  openssl/src/hmac.rs        | 217 +++++++++++++++++++++++++++++++++++++ | 
 |  openssl/src/lib.rs         |  12 ++ | 
 |  openssl/src/md_ctx.rs      |   2 +- | 
 |  openssl/src/pkey.rs        |  22 ++-- | 
 |  openssl/src/pkey_ctx.rs    |  21 +++- | 
 |  openssl/src/rsa.rs         |   2 +- | 
 |  openssl/src/sign.rs        |  10 +- | 
 |  openssl/src/symm.rs        |   7 +- | 
 |  openssl/src/x509/mod.rs    |  52 +++++++-- | 
 |  21 files changed, 439 insertions(+), 46 deletions(-) | 
 |  create mode 100644 openssl/.cargo/config.toml | 
 |  create mode 100644 openssl/src/hkdf.rs | 
 |  create mode 100644 openssl/src/hmac.rs | 
 |  | 
 | diff --git a/openssl/.cargo/config.toml b/openssl/.cargo/config.toml | 
 | new file mode 100644 | 
 | index 00000000..e2b197d8 | 
 | --- /dev/null | 
 | +++ b/openssl/.cargo/config.toml | 
 | @@ -0,0 +1,2 @@ | 
 | +[patch.crates-io] | 
 | +bssl-ffi = { package = "bssl-sys", version = "0.1.0", path = "../../../boringssl/build/rust", optional=true } | 
 | diff --git a/openssl/src/asn1.rs b/openssl/src/asn1.rs | 
 | index b02f9ac4..939a1732 100644 | 
 | --- a/openssl/src/asn1.rs | 
 | +++ b/openssl/src/asn1.rs | 
 | @@ -651,7 +651,7 @@ impl fmt::Debug for Asn1ObjectRef { | 
 |  } | 
 |   | 
 |  cfg_if! { | 
 | -    if #[cfg(any(ossl110, libressl273))] { | 
 | +    if #[cfg(any(ossl110, libressl273, boringssl))] { | 
 |          use ffi::ASN1_STRING_get0_data; | 
 |      } else { | 
 |          #[allow(bad_style)] | 
 | diff --git a/openssl/src/bio.rs b/openssl/src/bio.rs | 
 | index 6a72552a..03242188 100644 | 
 | --- a/openssl/src/bio.rs | 
 | +++ b/openssl/src/bio.rs | 
 | @@ -4,7 +4,7 @@ use std::marker::PhantomData; | 
 |  use std::ptr; | 
 |  use std::slice; | 
 |   | 
 | -use crate::cvt_p; | 
 | +use crate::{cvt_p, SignedLenType}; | 
 |  use crate::error::ErrorStack; | 
 |   | 
 |  pub struct MemBioSlice<'a>(*mut ffi::BIO, PhantomData<&'a [u8]>); | 
 | @@ -25,7 +25,7 @@ impl<'a> MemBioSlice<'a> { | 
 |          let bio = unsafe { | 
 |              cvt_p(BIO_new_mem_buf( | 
 |                  buf.as_ptr() as *const _, | 
 | -                buf.len() as c_int, | 
 | +                buf.len() as SignedLenType, | 
 |              ))? | 
 |          }; | 
 |   | 
 | @@ -78,7 +78,7 @@ cfg_if! { | 
 |          use ffi::BIO_new_mem_buf; | 
 |      } else { | 
 |          #[allow(bad_style)] | 
 | -        unsafe fn BIO_new_mem_buf(buf: *const ::libc::c_void, len: ::libc::c_int) -> *mut ffi::BIO { | 
 | +        unsafe fn BIO_new_mem_buf(buf: *const ::libc::c_void, len: SignedLenType) -> *mut ffi::BIO { | 
 |              ffi::BIO_new_mem_buf(buf as *mut _, len) | 
 |          } | 
 |      } | 
 | diff --git a/openssl/src/bn.rs b/openssl/src/bn.rs | 
 | index 1cd00dd4..dbd7ae94 100644 | 
 | --- a/openssl/src/bn.rs | 
 | +++ b/openssl/src/bn.rs | 
 | @@ -814,7 +814,7 @@ impl BigNumRef { | 
 |      /// assert_eq!(&bn_vec, &[0, 0, 0x45, 0x43]); | 
 |      /// ``` | 
 |      #[corresponds(BN_bn2binpad)] | 
 | -    #[cfg(ossl110)] | 
 | +    #[cfg(any(boringssl, ossl110))] | 
 |      pub fn to_vec_padded(&self, pad_to: i32) -> Result<Vec<u8>, ErrorStack> { | 
 |          let mut v = Vec::with_capacity(pad_to as usize); | 
 |          unsafe { | 
 | diff --git a/openssl/src/cipher.rs b/openssl/src/cipher.rs | 
 | index ab5f49d2..84a82654 100644 | 
 | --- a/openssl/src/cipher.rs | 
 | +++ b/openssl/src/cipher.rs | 
 | @@ -208,6 +208,7 @@ impl Cipher { | 
 |          unsafe { CipherRef::from_ptr(ffi::EVP_aes_192_cfb1() as *mut _) } | 
 |      } | 
 |   | 
 | +    #[cfg(not(boringssl))] | 
 |      pub fn aes_192_cfb128() -> &'static CipherRef { | 
 |          unsafe { CipherRef::from_ptr(ffi::EVP_aes_192_cfb128() as *mut _) } | 
 |      } | 
 | @@ -253,6 +254,7 @@ impl Cipher { | 
 |          unsafe { CipherRef::from_ptr(ffi::EVP_aes_256_cfb1() as *mut _) } | 
 |      } | 
 |   | 
 | +    #[cfg(not(boringssl))] | 
 |      pub fn aes_256_cfb128() -> &'static CipherRef { | 
 |          unsafe { CipherRef::from_ptr(ffi::EVP_aes_256_cfb128() as *mut _) } | 
 |      } | 
 | @@ -282,11 +284,13 @@ impl Cipher { | 
 |      } | 
 |   | 
 |      #[cfg(not(osslconf = "OPENSSL_NO_BF"))] | 
 | +    #[cfg(not(boringssl))] | 
 |      pub fn bf_cbc() -> &'static CipherRef { | 
 |          unsafe { CipherRef::from_ptr(ffi::EVP_bf_cbc() as *mut _) } | 
 |      } | 
 |   | 
 |      #[cfg(not(osslconf = "OPENSSL_NO_BF"))] | 
 | +    #[cfg(not(boringssl))] | 
 |      pub fn bf_ecb() -> &'static CipherRef { | 
 |          unsafe { CipherRef::from_ptr(ffi::EVP_bf_ecb() as *mut _) } | 
 |      } | 
 | diff --git a/openssl/src/dh.rs b/openssl/src/dh.rs | 
 | index 12170b99..e781543e 100644 | 
 | --- a/openssl/src/dh.rs | 
 | +++ b/openssl/src/dh.rs | 
 | @@ -239,7 +239,7 @@ where | 
 |  } | 
 |   | 
 |  cfg_if! { | 
 | -    if #[cfg(any(ossl110, libressl270))] { | 
 | +    if #[cfg(any(ossl110, libressl270, boringssl))] { | 
 |          use ffi::{DH_set0_pqg, DH_get0_pqg, DH_get0_key, DH_set0_key}; | 
 |      } else { | 
 |          #[allow(bad_style)] | 
 | diff --git a/openssl/src/dsa.rs b/openssl/src/dsa.rs | 
 | index 5f59ba8a..0aceeb55 100644 | 
 | --- a/openssl/src/dsa.rs | 
 | +++ b/openssl/src/dsa.rs | 
 | @@ -7,6 +7,7 @@ | 
 |   | 
 |  use cfg_if::cfg_if; | 
 |  use foreign_types::{ForeignType, ForeignTypeRef}; | 
 | +#[cfg(not(boringssl))] | 
 |  use libc::c_int; | 
 |  use std::fmt; | 
 |  use std::mem; | 
 | @@ -283,7 +284,7 @@ impl<T> fmt::Debug for Dsa<T> { | 
 |  } | 
 |   | 
 |  cfg_if! { | 
 | -    if #[cfg(any(ossl110, libressl273))] { | 
 | +    if #[cfg(any(ossl110, libressl273, boringssl))] { | 
 |          use ffi::{DSA_get0_key, DSA_get0_pqg, DSA_set0_key, DSA_set0_pqg}; | 
 |      } else { | 
 |          #[allow(bad_style)] | 
 | @@ -462,7 +463,7 @@ impl DsaSigRef { | 
 |  } | 
 |   | 
 |  cfg_if! { | 
 | -    if #[cfg(any(ossl110, libressl273))] { | 
 | +    if #[cfg(any(ossl110, libressl273, boringssl))] { | 
 |          use ffi::{DSA_SIG_set0, DSA_SIG_get0}; | 
 |      } else { | 
 |          #[allow(bad_style)] | 
 | diff --git a/openssl/src/ec.rs b/openssl/src/ec.rs | 
 | index 24b38322..20785428 100644 | 
 | --- a/openssl/src/ec.rs | 
 | +++ b/openssl/src/ec.rs | 
 | @@ -954,6 +954,26 @@ impl EcKey<Private> { | 
 |          EcKey<Private>, | 
 |          ffi::d2i_ECPrivateKey | 
 |      } | 
 | + | 
 | +    /// Decodes a DER-encoded elliptic curve private key structure for the specified curve. | 
 | +    #[corresponds(EC_KEY_parse_private_key)] | 
 | +    #[cfg(boringssl)] | 
 | +    pub fn private_key_from_der_for_group( | 
 | +        der: &[u8], | 
 | +        group: &EcGroupRef, | 
 | +    ) -> Result<EcKey<Private>, ErrorStack> { | 
 | +        unsafe { | 
 | +            let mut cbs = ffi::CBS { | 
 | +                data: der.as_ptr(), | 
 | +                len: der.len(), | 
 | +            }; | 
 | +            cvt_p(ffi::EC_KEY_parse_private_key( | 
 | +                &mut cbs as *mut ffi::CBS, | 
 | +                group.as_ptr(), | 
 | +            )) | 
 | +            .map(|p| EcKey::from_ptr(p)) | 
 | +        } | 
 | +    } | 
 |  } | 
 |   | 
 |  impl<T> Clone for EcKey<T> { | 
 | diff --git a/openssl/src/ecdsa.rs b/openssl/src/ecdsa.rs | 
 | index 0a960e7b..f3b27b39 100644 | 
 | --- a/openssl/src/ecdsa.rs | 
 | +++ b/openssl/src/ecdsa.rs | 
 | @@ -110,7 +110,7 @@ impl EcdsaSigRef { | 
 |  } | 
 |   | 
 |  cfg_if! { | 
 | -    if #[cfg(any(ossl110, libressl273))] { | 
 | +    if #[cfg(any(ossl110, libressl273, boringssl))] { | 
 |          use ffi::{ECDSA_SIG_set0, ECDSA_SIG_get0}; | 
 |      } else { | 
 |          #[allow(bad_style)] | 
 | diff --git a/openssl/src/encrypt.rs b/openssl/src/encrypt.rs | 
 | index 3cb10fcc..34a9eb8b 100644 | 
 | --- a/openssl/src/encrypt.rs | 
 | +++ b/openssl/src/encrypt.rs | 
 | @@ -148,7 +148,7 @@ impl<'a> Encrypter<'a> { | 
 |      /// This corresponds to [`EVP_PKEY_CTX_set_rsa_oaep_md`]. | 
 |      /// | 
 |      /// [`EVP_PKEY_CTX_set_rsa_oaep_md`]: https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_CTX_set_rsa_oaep_md.html | 
 | -    #[cfg(any(ossl102, libressl310))] | 
 | +    #[cfg(any(ossl102, libressl310, boringssl))] | 
 |      pub fn set_rsa_oaep_md(&mut self, md: MessageDigest) -> Result<(), ErrorStack> { | 
 |          unsafe { | 
 |              cvt(ffi::EVP_PKEY_CTX_set_rsa_oaep_md( | 
 | @@ -352,7 +352,7 @@ impl<'a> Decrypter<'a> { | 
 |      /// This corresponds to [`EVP_PKEY_CTX_set_rsa_oaep_md`]. | 
 |      /// | 
 |      /// [`EVP_PKEY_CTX_set_rsa_oaep_md`]: https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_CTX_set_rsa_oaep_md.html | 
 | -    #[cfg(any(ossl102, libressl310))] | 
 | +    #[cfg(any(ossl102, libressl310, boringssl))] | 
 |      pub fn set_rsa_oaep_md(&mut self, md: MessageDigest) -> Result<(), ErrorStack> { | 
 |          unsafe { | 
 |              cvt(ffi::EVP_PKEY_CTX_set_rsa_oaep_md( | 
 | diff --git a/openssl/src/hash.rs b/openssl/src/hash.rs | 
 | index 8e27505a..7f6fa89e 100644 | 
 | --- a/openssl/src/hash.rs | 
 | +++ b/openssl/src/hash.rs | 
 | @@ -43,7 +43,7 @@ use crate::nid::Nid; | 
 |  use crate::{cvt, cvt_p}; | 
 |   | 
 |  cfg_if! { | 
 | -    if #[cfg(ossl110)] { | 
 | +    if #[cfg(any(ossl110, boringssl))] { | 
 |          use ffi::{EVP_MD_CTX_free, EVP_MD_CTX_new}; | 
 |      } else { | 
 |          use ffi::{EVP_MD_CTX_create as EVP_MD_CTX_new, EVP_MD_CTX_destroy as EVP_MD_CTX_free}; | 
 | diff --git a/openssl/src/hkdf.rs b/openssl/src/hkdf.rs | 
 | new file mode 100644 | 
 | index 00000000..cc7e5b3a | 
 | --- /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/hmac.rs b/openssl/src/hmac.rs | 
 | new file mode 100644 | 
 | index 00000000..465781e2 | 
 | --- /dev/null | 
 | +++ b/openssl/src/hmac.rs | 
 | @@ -0,0 +1,217 @@ | 
 | +use crate::error::ErrorStack; | 
 | +use crate::md::MdRef; | 
 | +use crate::{cvt, cvt_p}; | 
 | +use ffi::HMAC_CTX; | 
 | +use foreign_types::ForeignTypeRef; | 
 | +use libc::{c_uint, c_void}; | 
 | +use openssl_macros::corresponds; | 
 | +use std::convert::TryFrom; | 
 | +use std::ptr; | 
 | + | 
 | +/// Computes the HMAC as a one-shot operation. | 
 | +/// | 
 | +/// Calculates the HMAC of data, using the given |key| | 
 | +/// and hash function |md|, and returns the result re-using the space from | 
 | +/// buffer |out|. On entry, |out| must contain at least |EVP_MD_size| bytes | 
 | +/// of space. The actual length of the result is used to resize the returned | 
 | +/// slice. An output size of |EVP_MAX_MD_SIZE| will always be large enough. | 
 | +/// It returns a resized |out| or ErrorStack on error. | 
 | +#[corresponds(HMAC)] | 
 | +#[inline] | 
 | +pub fn hmac<'a>( | 
 | +    md: &MdRef, | 
 | +    key: &[u8], | 
 | +    data: &[u8], | 
 | +    out: &'a mut [u8], | 
 | +) -> Result<&'a [u8], ErrorStack> { | 
 | +    assert!(out.len() >= md.size()); | 
 | +    let mut out_len = c_uint::try_from(out.len()).unwrap(); | 
 | +    unsafe { | 
 | +        cvt_p(ffi::HMAC( | 
 | +            md.as_ptr(), | 
 | +            key.as_ptr() as *const c_void, | 
 | +            key.len(), | 
 | +            data.as_ptr(), | 
 | +            data.len(), | 
 | +            out.as_mut_ptr(), | 
 | +            &mut out_len, | 
 | +        ))?; | 
 | +    } | 
 | +    Ok(&out[..out_len as usize]) | 
 | +} | 
 | + | 
 | +/// A context object used to perform HMAC operations. | 
 | +/// | 
 | +/// HMAC is a MAC (message authentication code), i.e. a keyed hash function used for message | 
 | +/// authentication, which is based on a hash function. | 
 | +/// | 
 | +/// Note: Only available in boringssl. For openssl, use `PKey::hmac` instead. | 
 | +#[cfg(boringssl)] | 
 | +pub struct HmacCtx { | 
 | +    ctx: *mut HMAC_CTX, | 
 | +    output_size: usize, | 
 | +} | 
 | + | 
 | +#[cfg(boringssl)] | 
 | +impl HmacCtx { | 
 | +    /// Creates a new [HmacCtx] to use the hash function `md` and key `key`. | 
 | +    #[corresponds(HMAC_Init_ex)] | 
 | +    pub fn new(key: &[u8], md: &MdRef) -> Result<Self, ErrorStack> { | 
 | +        unsafe { | 
 | +            // Safety: If an error occurred, the resulting null from HMAC_CTX_new is converted into | 
 | +            // ErrorStack in the returned result by `cvt_p`. | 
 | +            let ctx = cvt_p(ffi::HMAC_CTX_new())?; | 
 | +            // Safety: | 
 | +            // - HMAC_Init_ex must be called with a context previously created with HMAC_CTX_new, | 
 | +            //   which is the line above. | 
 | +            // - HMAC_Init_ex may return an error if key is null but the md is different from | 
 | +            //   before. This is avoided here since key is guaranteed to be non-null. | 
 | +            cvt(ffi::HMAC_Init_ex( | 
 | +                ctx, | 
 | +                key.as_ptr() as *const c_void, | 
 | +                key.len(), | 
 | +                md.as_ptr(), | 
 | +                ptr::null_mut(), | 
 | +            ))?; | 
 | +            Ok(Self { | 
 | +                ctx, | 
 | +                output_size: md.size(), | 
 | +            }) | 
 | +        } | 
 | +    } | 
 | + | 
 | +    /// `update` can be called repeatedly with chunks of the message `data` to be authenticated. | 
 | +    #[corresponds(HMAC_Update)] | 
 | +    pub fn update(&mut self, data: &[u8]) -> Result<(), ErrorStack> { | 
 | +        unsafe { | 
 | +            // Safety: HMAC_Update returns 0 on error, and that is converted into ErrorStack in the | 
 | +            // returned result by `cvt`. | 
 | +            cvt(ffi::HMAC_Update(self.ctx, data.as_ptr(), data.len())).map(|_| ()) | 
 | +        } | 
 | +    } | 
 | + | 
 | +    /// Finishes the HMAC process, and places the message authentication code in `output`. | 
 | +    /// The number of bytes written to `output` is returned. | 
 | +    /// | 
 | +    /// # Panics | 
 | +    /// | 
 | +    /// Panics if the `output` is smaller than the required size. The output size is indicated by | 
 | +    /// `md.size()` for the `Md` instance passed in [new]. An output size of |EVP_MAX_MD_SIZE| will | 
 | +    /// always be large enough. | 
 | +    #[corresponds(HMAC_Final)] | 
 | +    pub fn finalize(&mut self, output: &mut [u8]) -> Result<usize, ErrorStack> { | 
 | +        assert!(output.len() >= self.output_size); | 
 | +        unsafe { | 
 | +            // Safety: The length assertion above makes sure that `HMAC_Final` will not write longer | 
 | +            // than the length of `output`. | 
 | +            let mut size: c_uint = 0; | 
 | +            cvt(ffi::HMAC_Final( | 
 | +                self.ctx, | 
 | +                output.as_mut_ptr(), | 
 | +                &mut size as *mut c_uint, | 
 | +            )) | 
 | +            .map(|_| size as usize) | 
 | +        } | 
 | +    } | 
 | +} | 
 | + | 
 | +impl Drop for HmacCtx { | 
 | +    #[corresponds(HMAC_CTX_free)] | 
 | +    fn drop(&mut self) { | 
 | +        unsafe { | 
 | +            ffi::HMAC_CTX_free(self.ctx); | 
 | +        } | 
 | +    } | 
 | +} | 
 | + | 
 | +#[cfg(test)] | 
 | +mod tests { | 
 | +    use super::*; | 
 | +    use crate::md::Md; | 
 | + | 
 | +    const SHA_256_DIGEST_SIZE: usize = 32; | 
 | + | 
 | +    #[test] | 
 | +    fn hmac_sha256_test() { | 
 | +        let expected_hmac = [ | 
 | +            0xb0, 0x34, 0x4c, 0x61, 0xd8, 0xdb, 0x38, 0x53, 0x5c, 0xa8, 0xaf, 0xce, 0xaf, 0xb, | 
 | +            0xf1, 0x2b, 0x88, 0x1d, 0xc2, 0x0, 0xc9, 0x83, 0x3d, 0xa7, 0x26, 0xe9, 0x37, 0x6c, | 
 | +            0x2e, 0x32, 0xcf, 0xf7, | 
 | +        ]; | 
 | +        let mut out: [u8; SHA_256_DIGEST_SIZE] = [0; SHA_256_DIGEST_SIZE]; | 
 | +        let key: [u8; 20] = [0x0b; 20]; | 
 | +        let data = b"Hi There"; | 
 | +        let hmac_result = | 
 | +            hmac(Md::sha256(), &key, data, &mut out).expect("Couldn't calculate sha256 hmac"); | 
 | +        assert_eq!(&hmac_result, &expected_hmac); | 
 | +    } | 
 | + | 
 | +    #[test] | 
 | +    #[should_panic] | 
 | +    fn hmac_sha256_output_too_short() { | 
 | +        let mut out = vec![0_u8; 1]; | 
 | +        let key: [u8; 20] = [0x0b; 20]; | 
 | +        let data = b"Hi There"; | 
 | +        hmac(Md::sha256(), &key, data, &mut out).expect("Couldn't calculate sha256 hmac"); | 
 | +    } | 
 | + | 
 | +    #[test] | 
 | +    fn hmac_sha256_test_big_buffer() { | 
 | +        let expected_hmac = [ | 
 | +            0xb0, 0x34, 0x4c, 0x61, 0xd8, 0xdb, 0x38, 0x53, 0x5c, 0xa8, 0xaf, 0xce, 0xaf, 0xb, | 
 | +            0xf1, 0x2b, 0x88, 0x1d, 0xc2, 0x0, 0xc9, 0x83, 0x3d, 0xa7, 0x26, 0xe9, 0x37, 0x6c, | 
 | +            0x2e, 0x32, 0xcf, 0xf7, | 
 | +        ]; | 
 | +        let mut out: [u8; 100] = [0; 100]; | 
 | +        let key: [u8; 20] = [0x0b; 20]; | 
 | +        let data = b"Hi There"; | 
 | +        let hmac_result = | 
 | +            hmac(Md::sha256(), &key, data, &mut out).expect("Couldn't calculate sha256 hmac"); | 
 | +        assert_eq!(hmac_result.len(), SHA_256_DIGEST_SIZE); | 
 | +        assert_eq!(&hmac_result, &expected_hmac); | 
 | +    } | 
 | + | 
 | +    #[test] | 
 | +    fn hmac_sha256_update_test() { | 
 | +        let expected_hmac = [ | 
 | +            0xb0, 0x34, 0x4c, 0x61, 0xd8, 0xdb, 0x38, 0x53, 0x5c, 0xa8, 0xaf, 0xce, 0xaf, 0xb, | 
 | +            0xf1, 0x2b, 0x88, 0x1d, 0xc2, 0x0, 0xc9, 0x83, 0x3d, 0xa7, 0x26, 0xe9, 0x37, 0x6c, | 
 | +            0x2e, 0x32, 0xcf, 0xf7, | 
 | +        ]; | 
 | +        let mut out: [u8; SHA_256_DIGEST_SIZE] = [0; SHA_256_DIGEST_SIZE]; | 
 | +        let key: [u8; 20] = [0x0b; 20]; | 
 | +        let data = b"Hi There"; | 
 | +        let mut hmac_ctx = HmacCtx::new(&key, Md::sha256()).unwrap(); | 
 | +        hmac_ctx.update(data).unwrap(); | 
 | +        let size = hmac_ctx.finalize(&mut out).unwrap(); | 
 | +        assert_eq!(&out, &expected_hmac); | 
 | +        assert_eq!(size, SHA_256_DIGEST_SIZE); | 
 | +    } | 
 | + | 
 | +    #[test] | 
 | +    fn hmac_sha256_update_chunks_test() { | 
 | +        let expected_hmac = [ | 
 | +            0xb0, 0x34, 0x4c, 0x61, 0xd8, 0xdb, 0x38, 0x53, 0x5c, 0xa8, 0xaf, 0xce, 0xaf, 0xb, | 
 | +            0xf1, 0x2b, 0x88, 0x1d, 0xc2, 0x0, 0xc9, 0x83, 0x3d, 0xa7, 0x26, 0xe9, 0x37, 0x6c, | 
 | +            0x2e, 0x32, 0xcf, 0xf7, | 
 | +        ]; | 
 | +        let mut out: [u8; SHA_256_DIGEST_SIZE] = [0; SHA_256_DIGEST_SIZE]; | 
 | +        let key: [u8; 20] = [0x0b; 20]; | 
 | +        let mut hmac_ctx = HmacCtx::new(&key, Md::sha256()).unwrap(); | 
 | +        hmac_ctx.update(b"Hi").unwrap(); | 
 | +        hmac_ctx.update(b" There").unwrap(); | 
 | +        let size = hmac_ctx.finalize(&mut out).unwrap(); | 
 | +        assert_eq!(&out, &expected_hmac); | 
 | +        assert_eq!(size, SHA_256_DIGEST_SIZE); | 
 | +    } | 
 | + | 
 | +    #[test] | 
 | +    #[should_panic] | 
 | +    fn hmac_sha256_update_output_too_short() { | 
 | +        let mut out = vec![0_u8; 1]; | 
 | +        let key: [u8; 20] = [0x0b; 20]; | 
 | +        let mut hmac_ctx = HmacCtx::new(&key, Md::sha256()).unwrap(); | 
 | +        hmac_ctx.update(b"Hi There").unwrap(); | 
 | +        hmac_ctx.finalize(&mut out).unwrap(); | 
 | +    } | 
 | +} | 
 | diff --git a/openssl/src/lib.rs b/openssl/src/lib.rs | 
 | index 891651ec..e8d07d8a 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(all(soong, boringssl))] | 
 | +extern crate bssl_ffi as ffi; | 
 | + | 
 |  #[doc(inline)] | 
 |  pub use ffi::init; | 
 |   | 
 | @@ -155,6 +158,10 @@ pub mod ex_data; | 
 |  #[cfg(not(any(libressl, ossl300)))] | 
 |  pub mod fips; | 
 |  pub mod hash; | 
 | +#[cfg(boringssl)] | 
 | +pub mod hkdf; | 
 | +#[cfg(boringssl)] | 
 | +pub mod hmac; | 
 |  #[cfg(ossl300)] | 
 |  pub mod lib_ctx; | 
 |  pub mod md; | 
 | @@ -189,6 +196,11 @@ type LenType = libc::size_t; | 
 |  #[cfg(not(boringssl))] | 
 |  type LenType = libc::c_int; | 
 |   | 
 | +#[cfg(boringssl)] | 
 | +type SignedLenType = libc::ssize_t; | 
 | +#[cfg(not(boringssl))] | 
 | +type SignedLenType = libc::c_int; | 
 | + | 
 |  #[inline] | 
 |  fn cvt_p<T>(r: *mut T) -> Result<*mut T, ErrorStack> { | 
 |      if r.is_null() { | 
 | diff --git a/openssl/src/md_ctx.rs b/openssl/src/md_ctx.rs | 
 | index c4d3f06b..156f3c2f 100644 | 
 | --- a/openssl/src/md_ctx.rs | 
 | +++ b/openssl/src/md_ctx.rs | 
 | @@ -93,7 +93,7 @@ use std::convert::TryFrom; | 
 |  use std::ptr; | 
 |   | 
 |  cfg_if! { | 
 | -    if #[cfg(ossl110)] { | 
 | +    if #[cfg(any(ossl110, boringssl))] { | 
 |          use ffi::{EVP_MD_CTX_free, EVP_MD_CTX_new}; | 
 |      } else { | 
 |          use ffi::{EVP_MD_CTX_create as EVP_MD_CTX_new, EVP_MD_CTX_destroy as EVP_MD_CTX_free}; | 
 | diff --git a/openssl/src/pkey.rs b/openssl/src/pkey.rs | 
 | index 2039e7e9..21ba7118 100644 | 
 | --- a/openssl/src/pkey.rs | 
 | +++ b/openssl/src/pkey.rs | 
 | @@ -47,7 +47,7 @@ use crate::dh::Dh; | 
 |  use crate::dsa::Dsa; | 
 |  use crate::ec::EcKey; | 
 |  use crate::error::ErrorStack; | 
 | -#[cfg(ossl110)] | 
 | +#[cfg(any(boringssl, ossl110))] | 
 |  use crate::pkey_ctx::PkeyCtx; | 
 |  use crate::rsa::Rsa; | 
 |  use crate::symm::Cipher; | 
 | @@ -86,14 +86,14 @@ impl Id { | 
 |      pub const DH: Id = Id(ffi::EVP_PKEY_DH); | 
 |      pub const EC: Id = Id(ffi::EVP_PKEY_EC); | 
 |   | 
 | -    #[cfg(ossl110)] | 
 | +    #[cfg(any(boringssl, ossl110))] | 
 |      pub const HKDF: Id = Id(ffi::EVP_PKEY_HKDF); | 
 |   | 
 | -    #[cfg(ossl111)] | 
 | +    #[cfg(any(boringssl, ossl111))] | 
 |      pub const ED25519: Id = Id(ffi::EVP_PKEY_ED25519); | 
 |      #[cfg(ossl111)] | 
 |      pub const ED448: Id = Id(ffi::EVP_PKEY_ED448); | 
 | -    #[cfg(ossl111)] | 
 | +    #[cfg(any(boringssl, ossl111))] | 
 |      pub const X25519: Id = Id(ffi::EVP_PKEY_X25519); | 
 |      #[cfg(ossl111)] | 
 |      pub const X448: Id = Id(ffi::EVP_PKEY_X448); | 
 | @@ -252,7 +252,7 @@ where | 
 |      /// This function only works for algorithms that support raw public keys. | 
 |      /// Currently this is: [`Id::X25519`], [`Id::ED25519`], [`Id::X448`] or [`Id::ED448`]. | 
 |      #[corresponds(EVP_PKEY_get_raw_public_key)] | 
 | -    #[cfg(ossl111)] | 
 | +    #[cfg(any(boringssl, ossl111))] | 
 |      pub fn raw_public_key(&self) -> Result<Vec<u8>, ErrorStack> { | 
 |          unsafe { | 
 |              let mut len = 0; | 
 | @@ -303,7 +303,7 @@ where | 
 |      /// This function only works for algorithms that support raw private keys. | 
 |      /// Currently this is: [`Id::HMAC`], [`Id::X25519`], [`Id::ED25519`], [`Id::X448`] or [`Id::ED448`]. | 
 |      #[corresponds(EVP_PKEY_get_raw_private_key)] | 
 | -    #[cfg(ossl111)] | 
 | +    #[cfg(any(boringssl, ossl111))] | 
 |      pub fn raw_private_key(&self) -> Result<Vec<u8>, ErrorStack> { | 
 |          unsafe { | 
 |              let mut len = 0; | 
 | @@ -484,7 +484,7 @@ impl PKey<Private> { | 
 |          ctx.keygen() | 
 |      } | 
 |   | 
 | -    #[cfg(ossl111)] | 
 | +    #[cfg(any(boringssl, ossl111))] | 
 |      fn generate_eddsa(id: Id) -> Result<PKey<Private>, ErrorStack> { | 
 |          let mut ctx = PkeyCtx::new_id(id)?; | 
 |          ctx.keygen_init()?; | 
 | @@ -514,7 +514,7 @@ impl PKey<Private> { | 
 |      /// assert_eq!(secret.len(), 32); | 
 |      /// # Ok(()) } | 
 |      /// ``` | 
 | -    #[cfg(ossl111)] | 
 | +    #[cfg(any(boringssl, ossl111))] | 
 |      pub fn generate_x25519() -> Result<PKey<Private>, ErrorStack> { | 
 |          PKey::generate_eddsa(Id::X25519) | 
 |      } | 
 | @@ -568,7 +568,7 @@ impl PKey<Private> { | 
 |      /// assert_eq!(signature.len(), 64); | 
 |      /// # Ok(()) } | 
 |      /// ``` | 
 | -    #[cfg(ossl111)] | 
 | +    #[cfg(any(boringssl, ossl111))] | 
 |      pub fn generate_ed25519() -> Result<PKey<Private>, ErrorStack> { | 
 |          PKey::generate_eddsa(Id::ED25519) | 
 |      } | 
 | @@ -718,7 +718,7 @@ impl PKey<Private> { | 
 |      /// | 
 |      /// Algorithm types that support raw private keys are HMAC, X25519, ED25519, X448 or ED448 | 
 |      #[corresponds(EVP_PKEY_new_raw_private_key)] | 
 | -    #[cfg(ossl111)] | 
 | +    #[cfg(any(boringssl, ossl111))] | 
 |      pub fn private_key_from_raw_bytes( | 
 |          bytes: &[u8], | 
 |          key_type: Id, | 
 | @@ -759,7 +759,7 @@ impl PKey<Public> { | 
 |      /// | 
 |      /// Algorithm types that support raw public keys are X25519, ED25519, X448 or ED448 | 
 |      #[corresponds(EVP_PKEY_new_raw_public_key)] | 
 | -    #[cfg(ossl111)] | 
 | +    #[cfg(any(boringssl, ossl111))] | 
 |      pub fn public_key_from_raw_bytes( | 
 |          bytes: &[u8], | 
 |          key_type: Id, | 
 | diff --git a/openssl/src/pkey_ctx.rs b/openssl/src/pkey_ctx.rs | 
 | index f79372fb..3d4203fa 100644 | 
 | --- a/openssl/src/pkey_ctx.rs | 
 | +++ b/openssl/src/pkey_ctx.rs | 
 | @@ -470,7 +470,7 @@ impl<T> PkeyCtxRef<T> { | 
 |      /// | 
 |      /// Requires OpenSSL 1.1.0 or newer. | 
 |      #[corresponds(EVP_PKEY_CTX_set_hkdf_md)] | 
 | -    #[cfg(ossl110)] | 
 | +    #[cfg(any(ossl110, boringssl))] | 
 |      #[inline] | 
 |      pub fn set_hkdf_md(&mut self, digest: &MdRef) -> Result<(), ErrorStack> { | 
 |          unsafe { | 
 | @@ -503,10 +503,13 @@ impl<T> PkeyCtxRef<T> { | 
 |      /// | 
 |      /// Requires OpenSSL 1.1.0 or newer. | 
 |      #[corresponds(EVP_PKEY_CTX_set1_hkdf_key)] | 
 | -    #[cfg(ossl110)] | 
 | +    #[cfg(any(ossl110, boringssl))] | 
 |      #[inline] | 
 |      pub fn set_hkdf_key(&mut self, key: &[u8]) -> Result<(), ErrorStack> { | 
 | +        #[cfg(not(boringssl))] | 
 |          let len = c_int::try_from(key.len()).unwrap(); | 
 | +        #[cfg(boringssl)] | 
 | +        let len = key.len(); | 
 |   | 
 |          unsafe { | 
 |              cvt(ffi::EVP_PKEY_CTX_set1_hkdf_key( | 
 | @@ -523,10 +526,13 @@ impl<T> PkeyCtxRef<T> { | 
 |      /// | 
 |      /// Requires OpenSSL 1.1.0 or newer. | 
 |      #[corresponds(EVP_PKEY_CTX_set1_hkdf_salt)] | 
 | -    #[cfg(ossl110)] | 
 | +    #[cfg(any(ossl110, boringssl))] | 
 |      #[inline] | 
 |      pub fn set_hkdf_salt(&mut self, salt: &[u8]) -> Result<(), ErrorStack> { | 
 | +        #[cfg(not(boringssl))] | 
 |          let len = c_int::try_from(salt.len()).unwrap(); | 
 | +        #[cfg(boringssl)] | 
 | +        let len = salt.len(); | 
 |   | 
 |          unsafe { | 
 |              cvt(ffi::EVP_PKEY_CTX_set1_hkdf_salt( | 
 | @@ -543,10 +549,13 @@ impl<T> PkeyCtxRef<T> { | 
 |      /// | 
 |      /// Requires OpenSSL 1.1.0 or newer. | 
 |      #[corresponds(EVP_PKEY_CTX_add1_hkdf_info)] | 
 | -    #[cfg(ossl110)] | 
 | +    #[cfg(any(ossl110, boringssl))] | 
 |      #[inline] | 
 |      pub fn add_hkdf_info(&mut self, info: &[u8]) -> Result<(), ErrorStack> { | 
 | +        #[cfg(not(boringssl))] | 
 |          let len = c_int::try_from(info.len()).unwrap(); | 
 | +        #[cfg(boringssl)] | 
 | +        let len = info.len(); | 
 |   | 
 |          unsafe { | 
 |              cvt(ffi::EVP_PKEY_CTX_add1_hkdf_info( | 
 | @@ -604,7 +613,7 @@ mod test { | 
 |      #[cfg(not(boringssl))] | 
 |      use crate::cipher::Cipher; | 
 |      use crate::ec::{EcGroup, EcKey}; | 
 | -    #[cfg(any(ossl102, libressl310))] | 
 | +    #[cfg(any(ossl102, libressl310, boringssl))] | 
 |      use crate::md::Md; | 
 |      use crate::nid::Nid; | 
 |      use crate::pkey::PKey; | 
 | @@ -689,7 +698,7 @@ mod test { | 
 |      } | 
 |   | 
 |      #[test] | 
 | -    #[cfg(ossl110)] | 
 | +    #[cfg(any(ossl110, boringssl))] | 
 |      fn hkdf() { | 
 |          let mut ctx = PkeyCtx::new_id(Id::HKDF).unwrap(); | 
 |          ctx.derive_init().unwrap(); | 
 | diff --git a/openssl/src/rsa.rs b/openssl/src/rsa.rs | 
 | index 68cf64b0..f155b12d 100644 | 
 | --- a/openssl/src/rsa.rs | 
 | +++ b/openssl/src/rsa.rs | 
 | @@ -581,7 +581,7 @@ impl<T> fmt::Debug for Rsa<T> { | 
 |  } | 
 |   | 
 |  cfg_if! { | 
 | -    if #[cfg(any(ossl110, libressl273))] { | 
 | +    if #[cfg(any(ossl110, libressl273, boringssl))] { | 
 |          use ffi::{ | 
 |              RSA_get0_key, RSA_get0_factors, RSA_get0_crt_params, RSA_set0_key, RSA_set0_factors, | 
 |              RSA_set0_crt_params, | 
 | diff --git a/openssl/src/sign.rs b/openssl/src/sign.rs | 
 | index b675825e..e5e80608 100644 | 
 | --- a/openssl/src/sign.rs | 
 | +++ b/openssl/src/sign.rs | 
 | @@ -290,7 +290,7 @@ impl<'a> Signer<'a> { | 
 |          self.len_intern() | 
 |      } | 
 |   | 
 | -    #[cfg(not(ossl111))] | 
 | +    #[cfg(not(any(boringssl, ossl111)))] | 
 |      fn len_intern(&self) -> Result<usize, ErrorStack> { | 
 |          unsafe { | 
 |              let mut len = 0; | 
 | @@ -303,7 +303,7 @@ impl<'a> Signer<'a> { | 
 |          } | 
 |      } | 
 |   | 
 | -    #[cfg(ossl111)] | 
 | +    #[cfg(any(boringssl, ossl111))] | 
 |      fn len_intern(&self) -> Result<usize, ErrorStack> { | 
 |          unsafe { | 
 |              let mut len = 0; | 
 | @@ -360,7 +360,7 @@ impl<'a> Signer<'a> { | 
 |      /// OpenSSL documentation at [`EVP_DigestSign`]. | 
 |      /// | 
 |      /// [`EVP_DigestSign`]: https://www.openssl.org/docs/man1.1.1/man3/EVP_DigestSign.html | 
 | -    #[cfg(ossl111)] | 
 | +    #[cfg(any(boringssl, ossl111))] | 
 |      pub fn sign_oneshot( | 
 |          &mut self, | 
 |          sig_buf: &mut [u8], | 
 | @@ -382,7 +382,7 @@ impl<'a> Signer<'a> { | 
 |      /// Returns the signature. | 
 |      /// | 
 |      /// This is a simple convenience wrapper over `len` and `sign_oneshot`. | 
 | -    #[cfg(ossl111)] | 
 | +    #[cfg(any(boringssl, ossl111))] | 
 |      pub fn sign_oneshot_to_vec(&mut self, data_buf: &[u8]) -> Result<Vec<u8>, ErrorStack> { | 
 |          let mut sig_buf = vec![0; self.len()?]; | 
 |          let len = self.sign_oneshot(&mut sig_buf, data_buf)?; | 
 | @@ -596,7 +596,7 @@ impl<'a> Verifier<'a> { | 
 |      /// OpenSSL documentation at [`EVP_DigestVerify`]. | 
 |      /// | 
 |      /// [`EVP_DigestVerify`]: https://www.openssl.org/docs/man1.1.1/man3/EVP_DigestVerify.html | 
 | -    #[cfg(ossl111)] | 
 | +    #[cfg(any(boringssl, ossl111))] | 
 |      pub fn verify_oneshot(&mut self, signature: &[u8], buf: &[u8]) -> Result<bool, ErrorStack> { | 
 |          unsafe { | 
 |              let r = ffi::EVP_DigestVerify( | 
 | diff --git a/openssl/src/symm.rs b/openssl/src/symm.rs | 
 | index c75bbc0c..beff5fc2 100644 | 
 | --- a/openssl/src/symm.rs | 
 | +++ b/openssl/src/symm.rs | 
 | @@ -119,6 +119,7 @@ impl Cipher { | 
 |          unsafe { Cipher(ffi::EVP_aes_128_cfb1()) } | 
 |      } | 
 |   | 
 | +    #[cfg(not(boringssl))] | 
 |      pub fn aes_128_cfb128() -> Cipher { | 
 |          unsafe { Cipher(ffi::EVP_aes_128_cfb128()) } | 
 |      } | 
 | @@ -164,6 +165,7 @@ impl Cipher { | 
 |          unsafe { Cipher(ffi::EVP_aes_192_cfb1()) } | 
 |      } | 
 |   | 
 | +    #[cfg(not(boringssl))] | 
 |      pub fn aes_192_cfb128() -> Cipher { | 
 |          unsafe { Cipher(ffi::EVP_aes_192_cfb128()) } | 
 |      } | 
 | @@ -214,6 +216,7 @@ impl Cipher { | 
 |          unsafe { Cipher(ffi::EVP_aes_256_cfb1()) } | 
 |      } | 
 |   | 
 | +    #[cfg(not(boringssl))] | 
 |      pub fn aes_256_cfb128() -> Cipher { | 
 |          unsafe { Cipher(ffi::EVP_aes_256_cfb128()) } | 
 |      } | 
 | @@ -242,12 +245,12 @@ impl Cipher { | 
 |          unsafe { Cipher(ffi::EVP_aes_256_ocb()) } | 
 |      } | 
 |   | 
 | -    #[cfg(not(osslconf = "OPENSSL_NO_BF"))] | 
 | +    #[cfg(not(any(boringssl, osslconf = "OPENSSL_NO_BF")))] | 
 |      pub fn bf_cbc() -> Cipher { | 
 |          unsafe { Cipher(ffi::EVP_bf_cbc()) } | 
 |      } | 
 |   | 
 | -    #[cfg(not(osslconf = "OPENSSL_NO_BF"))] | 
 | +    #[cfg(not(any(boringssl, osslconf = "OPENSSL_NO_BF")))] | 
 |      pub fn bf_ecb() -> Cipher { | 
 |          unsafe { Cipher(ffi::EVP_bf_ecb()) } | 
 |      } | 
 | diff --git a/openssl/src/x509/mod.rs b/openssl/src/x509/mod.rs | 
 | index edd54aa8..a03a8aa6 100644 | 
 | --- a/openssl/src/x509/mod.rs | 
 | +++ b/openssl/src/x509/mod.rs | 
 | @@ -353,6 +353,19 @@ impl X509Builder { | 
 |          unsafe { cvt(ffi::X509_sign(self.0.as_ptr(), key.as_ptr(), hash.as_ptr())).map(|_| ()) } | 
 |      } | 
 |   | 
 | +    /// Signs the certificate with a private key but without a digest. | 
 | +    /// | 
 | +    /// This is the only way to sign with Ed25519 keys as BoringSSL doesn't support the null | 
 | +    /// message digest. | 
 | +    #[cfg(boringssl)] | 
 | +    #[corresponds(X509_sign)] | 
 | +    pub fn sign_without_digest<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack> | 
 | +    where | 
 | +        T: HasPrivate, | 
 | +    { | 
 | +        unsafe { cvt(ffi::X509_sign(self.0.as_ptr(), key.as_ptr(), ptr::null())).map(|_| ()) } | 
 | +    } | 
 | + | 
 |      /// Consumes the builder, returning the certificate. | 
 |      pub fn build(self) -> X509 { | 
 |          self.0 | 
 | @@ -880,13 +893,13 @@ impl X509NameBuilder { | 
 |      pub fn append_entry_by_text(&mut self, field: &str, value: &str) -> Result<(), ErrorStack> { | 
 |          unsafe { | 
 |              let field = CString::new(field).unwrap(); | 
 | -            assert!(value.len() <= c_int::max_value() as usize); | 
 | +            assert!(value.len() <= isize::max_value() as usize); | 
 |              cvt(ffi::X509_NAME_add_entry_by_txt( | 
 |                  self.0.as_ptr(), | 
 |                  field.as_ptr() as *mut _, | 
 |                  ffi::MBSTRING_UTF8, | 
 |                  value.as_ptr(), | 
 | -                value.len() as c_int, | 
 | +                value.len() as isize, | 
 |                  -1, | 
 |                  0, | 
 |              )) | 
 | @@ -907,13 +920,13 @@ impl X509NameBuilder { | 
 |      ) -> Result<(), ErrorStack> { | 
 |          unsafe { | 
 |              let field = CString::new(field).unwrap(); | 
 | -            assert!(value.len() <= c_int::max_value() as usize); | 
 | +            assert!(value.len() <= isize::max_value() as usize); | 
 |              cvt(ffi::X509_NAME_add_entry_by_txt( | 
 |                  self.0.as_ptr(), | 
 |                  field.as_ptr() as *mut _, | 
 |                  ty.as_raw(), | 
 |                  value.as_ptr(), | 
 | -                value.len() as c_int, | 
 | +                value.len() as isize, | 
 |                  -1, | 
 |                  0, | 
 |              )) | 
 | @@ -928,13 +941,13 @@ impl X509NameBuilder { | 
 |      /// [`X509_NAME_add_entry_by_NID`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_NAME_add_entry_by_NID.html | 
 |      pub fn append_entry_by_nid(&mut self, field: Nid, value: &str) -> Result<(), ErrorStack> { | 
 |          unsafe { | 
 | -            assert!(value.len() <= c_int::max_value() as usize); | 
 | +            assert!(value.len() <= isize::max_value() as usize); | 
 |              cvt(ffi::X509_NAME_add_entry_by_NID( | 
 |                  self.0.as_ptr(), | 
 |                  field.as_raw(), | 
 |                  ffi::MBSTRING_UTF8, | 
 |                  value.as_ptr() as *mut _, | 
 | -                value.len() as c_int, | 
 | +                value.len() as isize, | 
 |                  -1, | 
 |                  0, | 
 |              )) | 
 | @@ -954,13 +967,13 @@ impl X509NameBuilder { | 
 |          ty: Asn1Type, | 
 |      ) -> Result<(), ErrorStack> { | 
 |          unsafe { | 
 | -            assert!(value.len() <= c_int::max_value() as usize); | 
 | +            assert!(value.len() <= isize::max_value() as usize); | 
 |              cvt(ffi::X509_NAME_add_entry_by_NID( | 
 |                  self.0.as_ptr(), | 
 |                  field.as_raw(), | 
 |                  ty.as_raw(), | 
 |                  value.as_ptr() as *mut _, | 
 | -                value.len() as c_int, | 
 | +                value.len() as isize, | 
 |                  -1, | 
 |                  0, | 
 |              )) | 
 | @@ -1260,6 +1273,29 @@ impl X509ReqBuilder { | 
 |          } | 
 |      } | 
 |   | 
 | +    /// Sign the request using a private key without a digest. | 
 | +    /// | 
 | +    /// This is the only way to sign with Ed25519 keys as BoringSSL doesn't support the null | 
 | +    /// message digest. | 
 | +    /// | 
 | +    /// This corresponds to [`X509_REQ_sign`]. | 
 | +    /// | 
 | +    /// [`X509_REQ_sign`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_REQ_sign.html | 
 | +    #[cfg(boringssl)] | 
 | +    pub fn sign_without_digest<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack> | 
 | +    where | 
 | +        T: HasPrivate, | 
 | +    { | 
 | +        unsafe { | 
 | +            cvt(ffi::X509_REQ_sign( | 
 | +                self.0.as_ptr(), | 
 | +                key.as_ptr(), | 
 | +                ptr::null(), | 
 | +            )) | 
 | +            .map(|_| ()) | 
 | +        } | 
 | +    } | 
 | + | 
 |      /// Returns the `X509Req`. | 
 |      pub fn build(self) -> X509Req { | 
 |          self.0 | 
 | --  | 
 | 2.42.0.rc2.253.gd59a3bf2b4-goog | 
 |  |