Revert^2 "Update to work with new BoringSSL" am: 2a93b21a43

Original change: https://android-review.googlesource.com/c/platform/external/rust/crates/openssl/+/2470948

Change-Id: I254a0112c1cb3ee266d908140140447ec58e5152
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/README.android b/README.android
index 6499cfe..1957c30 100644
--- a/README.android
+++ b/README.android
@@ -29,3 +29,13 @@
     Android.bp builds correctly by running `m libopenssl`.
 7.  Commit the changes and upload the CL.
 8.  `external/rust/crates/openssl-macros` should also be updated at the same time.
+
+## Generating patch files
+
+If you make changes to this repo that is not in upstream `rust-openssl` yet, please generate a
+patch file to keep track of those changes.
+
+1. Commit your changes
+2. Create the patch file: `git diff -u HEAD~ > <XXXX-topic>.diff` where XXXX is the number to track
+   the order of the patches to apply.
+3. Amend the patch file into your CL `git add -A && git commit --amend`
diff --git a/patches/0001-cfgs.diff b/patches/0001-cfgs.diff
new file mode 100644
index 0000000..f118c41
--- /dev/null
+++ b/patches/0001-cfgs.diff
@@ -0,0 +1,271 @@
+diff --git a/.cargo/config.toml b/.cargo/config.toml
+new file mode 100644
+index 0000000..e2b197d
+--- /dev/null
++++ b/.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/src/cipher.rs b/src/cipher.rs
+index ab5f49d..84a8265 100644
+--- a/src/cipher.rs
++++ b/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/src/encrypt.rs b/src/encrypt.rs
+index 3cb10fc..34a9eb8 100644
+--- a/src/encrypt.rs
++++ b/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/src/lib.rs b/src/lib.rs
+index 891651e..f149bfd 100644
+--- a/src/lib.rs
++++ b/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;
+diff --git a/src/pkey.rs b/src/pkey.rs
+index 7d438eb..7eaf068 100644
+--- a/src/pkey.rs
++++ b/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;
+@@ -89,11 +89,11 @@ impl Id {
+     #[cfg(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);
+@@ -243,7 +243,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;
+@@ -294,7 +294,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;
+@@ -475,7 +475,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()?;
+@@ -505,7 +505,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)
+     }
+@@ -559,7 +559,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)
+     }
+@@ -709,7 +709,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,
+@@ -750,7 +750,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/src/sign.rs b/src/sign.rs
+index 457ff12..4de8ad0 100644
+--- a/src/sign.rs
++++ b/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)?;
+@@ -594,7 +594,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/src/symm.rs b/src/symm.rs
+index c75bbc0..beff5fc 100644
+--- a/src/symm.rs
++++ b/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/patches/0002-ec.diff b/patches/0002-ec.diff
new file mode 100644
index 0000000..1a27bbe
--- /dev/null
+++ b/patches/0002-ec.diff
@@ -0,0 +1,31 @@
+diff --git a/src/ec.rs b/src/ec.rs
+index a6a6dc9..88dcaaf 100644
+--- a/src/ec.rs
++++ b/src/ec.rs
+@@ -908,6 +908,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/patches/0003-hkdf.diff b/patches/0003-hkdf.diff
new file mode 100644
index 0000000..d99ab7f
--- /dev/null
+++ b/patches/0003-hkdf.diff
@@ -0,0 +1,95 @@
+diff --git a/src/hkdf.rs b/src/hkdf.rs
+new file mode 100644
+index 0000000..cc7e5b3
+--- /dev/null
++++ b/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/patches/0004-hmac.diff b/patches/0004-hmac.diff
new file mode 100644
index 0000000..e9000d2
--- /dev/null
+++ b/patches/0004-hmac.diff
@@ -0,0 +1,74 @@
+diff --git a/src/hmac.rs b/src/hmac.rs
+new file mode 100644
+index 0000000..601ae01
+--- /dev/null
++++ b/src/hmac.rs
+@@ -0,0 +1,68 @@
++use crate::cvt_p;
++use crate::error::ErrorStack;
++use crate::md::MdRef;
++use foreign_types::ForeignTypeRef;
++use openssl_macros::corresponds;
++use libc::{c_void, c_uint};
++use std::convert::TryFrom;
++
++/// 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> {
++    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])
++}
++
++#[cfg(test)]
++mod tests {
++    use super::*;
++    use crate::md::Md;
++    use crate::memcmp;
++
++    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");
++        expect!(memcmp::eq(&hmac_result, &expected_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");
++        expect_eq!(hmac_result.len(), SHA_256_DIGEST_SIZE);
++        expect!(memcmp::eq(&hmac_result, &expected_hmac));
++    }
++}
diff --git a/patches/0005-hmac_ctx_wrappers.diff b/patches/0005-hmac_ctx_wrappers.diff
new file mode 100644
index 0000000..305f5bc
--- /dev/null
+++ b/patches/0005-hmac_ctx_wrappers.diff
@@ -0,0 +1,228 @@
+diff --git a/src/hmac.rs b/src/hmac.rs
+index 601ae01..465781e 100644
+--- a/src/hmac.rs
++++ b/src/hmac.rs
+@@ -1,10 +1,12 @@
+-use crate::cvt_p;
+ 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 libc::{c_void, c_uint};
+ use std::convert::TryFrom;
++use std::ptr;
+ 
+ /// Computes the HMAC as a one-shot operation.
+ ///
+@@ -20,8 +22,9 @@ pub fn hmac<'a>(
+     md: &MdRef,
+     key: &[u8],
+     data: &[u8],
+-    out: &'a mut [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(
+@@ -31,38 +34,184 @@ pub fn hmac<'a>(
+             data.as_ptr(),
+             data.len(),
+             out.as_mut_ptr(),
+-            &mut out_len
+-            ))?;
++            &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;
+-    use crate::memcmp;
+ 
+-    const SHA_256_DIGEST_SIZE:usize = 32;
++    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 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 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");
+-        expect!(memcmp::eq(&hmac_result, &expected_hmac));
++        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 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 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 hmac_result = hmac(Md::sha256(), &key, data, &mut out).expect("Couldn't calculate sha256 hmac");
+-        expect_eq!(hmac_result.len(), SHA_256_DIGEST_SIZE);
+-        expect!(memcmp::eq(&hmac_result, &expected_hmac));
++        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/patches/0006-x509.diff b/patches/0006-x509.diff
new file mode 100644
index 0000000..244e775
--- /dev/null
+++ b/patches/0006-x509.diff
@@ -0,0 +1,54 @@
+diff --git a/src/x509/mod.rs b/src/x509/mod.rs
+index edd54aa..45f2467 100644
+--- a/src/x509/mod.rs
++++ b/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
+@@ -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
diff --git a/patches/local_changes.diff b/patches/local_changes.diff
deleted file mode 100644
index 06702fa..0000000
--- a/patches/local_changes.diff
+++ /dev/null
@@ -1,525 +0,0 @@
-diff --git a/.cargo/config.toml b/.cargo/config.toml
-new file mode 100644
-index 0000000..e2b197d
---- /dev/null
-+++ b/.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/src/cipher.rs b/src/cipher.rs
-index ab5f49d..84a8265 100644
---- a/src/cipher.rs
-+++ b/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/src/ec.rs b/src/ec.rs
-index a6a6dc9..88dcaaf 100644
---- a/src/ec.rs
-+++ b/src/ec.rs
-@@ -908,6 +908,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/src/encrypt.rs b/src/encrypt.rs
-index 3cb10fc..34a9eb8 100644
---- a/src/encrypt.rs
-+++ b/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/src/hkdf.rs b/src/hkdf.rs
-new file mode 100644
-index 0000000..cc7e5b3
---- /dev/null
-+++ b/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/src/hmac.rs b/src/hmac.rs
-new file mode 100644
-index 0000000..601ae01
---- /dev/null
-+++ b/src/hmac.rs
-@@ -0,0 +1,68 @@
-+use crate::cvt_p;
-+use crate::error::ErrorStack;
-+use crate::md::MdRef;
-+use foreign_types::ForeignTypeRef;
-+use openssl_macros::corresponds;
-+use libc::{c_void, c_uint};
-+use std::convert::TryFrom;
-+
-+/// 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> {
-+    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])
-+}
-+
-+#[cfg(test)]
-+mod tests {
-+    use super::*;
-+    use crate::md::Md;
-+    use crate::memcmp;
-+
-+    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");
-+        expect!(memcmp::eq(&hmac_result, &expected_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");
-+        expect_eq!(hmac_result.len(), SHA_256_DIGEST_SIZE);
-+        expect!(memcmp::eq(&hmac_result, &expected_hmac));
-+    }
-+}
-diff --git a/src/lib.rs b/src/lib.rs
-index 891651e..48b7ed1 100644
---- a/src/lib.rs
-+++ b/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;
-diff --git a/src/pkey.rs b/src/pkey.rs
-index 7d438eb..7eaf068 100644
---- a/src/pkey.rs
-+++ b/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;
-@@ -89,11 +89,11 @@ impl Id {
-     #[cfg(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);
-@@ -243,7 +243,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;
-@@ -294,7 +294,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;
-@@ -475,7 +475,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()?;
-@@ -505,7 +505,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)
-     }
-@@ -559,7 +559,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)
-     }
-@@ -709,7 +709,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,
-@@ -750,7 +750,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/src/sign.rs b/src/sign.rs
-index 457ff12..4de8ad0 100644
---- a/src/sign.rs
-+++ b/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)?;
-@@ -594,7 +594,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/src/symm.rs b/src/symm.rs
-index c75bbc0..beff5fc 100644
---- a/src/symm.rs
-+++ b/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/src/x509/mod.rs b/src/x509/mod.rs
-index edd54aa..45f2467 100644
---- a/src/x509/mod.rs
-+++ b/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
-@@ -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
diff --git a/src/hmac.rs b/src/hmac.rs
index 601ae01..465781e 100644
--- a/src/hmac.rs
+++ b/src/hmac.rs
@@ -1,10 +1,12 @@
-use crate::cvt_p;
 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 libc::{c_void, c_uint};
 use std::convert::TryFrom;
+use std::ptr;
 
 /// Computes the HMAC as a one-shot operation.
 ///
@@ -20,8 +22,9 @@
     md: &MdRef,
     key: &[u8],
     data: &[u8],
-    out: &'a mut [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(
@@ -31,38 +34,184 @@
             data.as_ptr(),
             data.len(),
             out.as_mut_ptr(),
-            &mut out_len
-            ))?;
+            &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;
-    use crate::memcmp;
 
-    const SHA_256_DIGEST_SIZE:usize = 32;
+    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 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 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");
-        expect!(memcmp::eq(&hmac_result, &expected_hmac));
+        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 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 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");
-        expect_eq!(hmac_result.len(), SHA_256_DIGEST_SIZE);
-        expect!(memcmp::eq(&hmac_result, &expected_hmac));
+        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();
     }
 }