Add patch file for local changes
Test: cargo2android.py generates expected Android.bp
Change-Id: Id33f62e94416f606896e7316eaf739e61af7a275
diff --git a/Android.bp b/Android.bp
index 2282c66..4e9011c 100644
--- a/Android.bp
+++ b/Android.bp
@@ -54,11 +54,11 @@
srcs: ["src/lib.rs"],
edition: "2018",
features: ["unstable_boringssl"],
- cfgs: ["boringssl"],
+ cfgs: ["boringssl", "soong"],
rustlibs: [
"libbitflags",
"libcfg_if",
- "libbssl_ffi", // Manually changed from libopenssl_sys
+ "libbssl_ffi",
"libforeign_types",
"liblibc",
"libonce_cell",
diff --git a/README.android b/README.android
new file mode 100644
index 0000000..6499cfe
--- /dev/null
+++ b/README.android
@@ -0,0 +1,31 @@
+## Steps for updating this crate
+
+1. In order to run cargo2android, for this crate, the BoringSSL rust bindings first needs to be
+ built. Copy `googletest` to `boringssl`, which is needed to build the rust bindings
+
+ ```
+ $ cp -r external/googletest/googletest external/boringssl/src/third_party/
+ ```
+2. Build the rust bindings (More information at
+ https://boringssl.googlesource.com/boringssl/+/HEAD/BUILDING.md)
+
+ ```
+ $ cd external/boringssl
+ $ mkdir build && cd build
+ $ cmake .. -DRUST_BINDINGS=x86_64-unknown-linux-gnu
+ $ make
+ ```
+3. Run `tools/external_updater/updater.sh update rust/crates/openssl`. Cargo errors causing the
+ command to fail are expected (since the boringSSL crate is outside of the `openssl` directory,
+ redshell is not able to access it).
+4. The repository should now be in a `tmp_auto_upgrade` branch, and the Android.bp will contain
+ some error message.
+5. Run cargo2android
+
+ ```
+ $ cargo2android.py --config ./cargo2android.json
+ ```
+6. Clean up the changes in external/boringssl repository, and double check that the resulting
+ 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.
diff --git a/cargo2android.json b/cargo2android.json
index 3fc1f63..4caae30 100644
--- a/cargo2android.json
+++ b/cargo2android.json
@@ -6,5 +6,6 @@
"device": true,
"features": "unstable_boringssl",
"run": true,
- "vendor-available": true
+ "vendor-available": true,
+ "patch": "patches/Android.bp.diff"
}
diff --git a/patches/Android.bp.diff b/patches/Android.bp.diff
new file mode 100644
index 0000000..9f7b012
--- /dev/null
+++ b/patches/Android.bp.diff
@@ -0,0 +1,18 @@
+diff --git a/Android.bp b/Android.bp
+index 2282c66..4e9011c 100644
+--- a/Android.bp
++++ b/Android.bp
+@@ -54,11 +54,11 @@ rust_library {
+ srcs: ["src/lib.rs"],
+ edition: "2018",
+ features: ["unstable_boringssl"],
+- cfgs: ["boringssl"],
++ cfgs: ["boringssl", "soong"],
+ rustlibs: [
+ "libbitflags",
+ "libcfg_if",
+- "libopenssl_sys",
++ "libbssl_ffi",
+ "libforeign_types",
+ "liblibc",
+ "libonce_cell",
diff --git a/patches/local_changes.diff b/patches/local_changes.diff
new file mode 100644
index 0000000..06702fa
--- /dev/null
+++ b/patches/local_changes.diff
@@ -0,0 +1,525 @@
+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/lib.rs b/src/lib.rs
index 48b7ed1..b91d067 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -120,7 +120,7 @@
#![doc(html_root_url = "https://docs.rs/openssl/0.10")]
#![warn(rust_2018_idioms)]
-#[cfg(boringssl)]
+#[cfg(all(soong,boringssl))]
extern crate bssl_ffi as ffi;
#[doc(inline)]