Add wrapper functions for HMAC_CTX_*

Create a rust wrapper for HMAC_CTX_* functions to enable the iterative
HMAC APIs (calling update() for segments of the input rather than
collecting the whole input and calling hmac().

This patch is carried in AOSP because hmac.rs is not available upstream
yet, and the HMAC_CTX_* functions are recommended only for boringssl -
in openssl3 these functions are deprecated and the EVP_MAC functions are
recommended instead.

Bug: 267375624
Test: m libopenssl
Change-Id: I3d77403dd8dd607c8b55bf2be499e08895a76c19
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();
     }
 }