[bssl] Support ECDSA P-384 signature verification
This functionality is required for the verification of DICE
certificate chain in a subsequent cl.
Bug: 314266221
Test: atest libbssl_avf_nostd.test
Change-Id: Idcc3c7e8b22a0c6151490585d0f16474a17e33b9
diff --git a/libs/bssl/src/digest.rs b/libs/bssl/src/digest.rs
index 8189584..e986a38 100644
--- a/libs/bssl/src/digest.rs
+++ b/libs/bssl/src/digest.rs
@@ -14,12 +14,18 @@
//! Wrappers of the digest functions in BoringSSL digest.h.
-use crate::util::to_call_failed_error;
-use bssl_avf_error::{ApiName, Result};
+use crate::util::{check_int_result, to_call_failed_error};
+use alloc::vec;
+use alloc::vec::Vec;
+use bssl_avf_error::{ApiName, Error, Result};
use bssl_ffi::{
- EVP_MD_CTX_free, EVP_MD_CTX_new, EVP_MD_size, EVP_sha256, EVP_sha512, EVP_MD, EVP_MD_CTX,
+ EVP_Digest, EVP_MD_CTX_free, EVP_MD_CTX_new, EVP_MD_size, EVP_sha256, EVP_sha384, EVP_sha512,
+ EVP_MAX_MD_SIZE, EVP_MD, EVP_MD_CTX,
};
-use core::ptr::NonNull;
+use core::ptr::{self, NonNull};
+use log::error;
+
+const MAX_DIGEST_SIZE: usize = EVP_MAX_MD_SIZE as usize;
/// Message digester wrapping `EVP_MD`.
#[derive(Clone, Debug)]
@@ -33,7 +39,17 @@
let p = unsafe { EVP_sha256() };
// SAFETY: The returned pointer should always be valid and points to a static
// `EVP_MD`.
- Self(unsafe { &*p })
+ Self(unsafe { p.as_ref().unwrap() })
+ }
+
+ /// Returns a `Digester` implementing `SHA-384` algorithm.
+ pub fn sha384() -> Self {
+ // SAFETY: This function does not access any Rust variables and simply returns
+ // a pointer to the static variable in BoringSSL.
+ let p = unsafe { EVP_sha384() };
+ // SAFETY: The returned pointer should always be valid and points to a static
+ // `EVP_MD`.
+ Self(unsafe { p.as_ref().unwrap() })
}
/// Returns a `Digester` implementing `SHA-512` algorithm.
@@ -43,7 +59,7 @@
let p = unsafe { EVP_sha512() };
// SAFETY: The returned pointer should always be valid and points to a static
// `EVP_MD`.
- Self(unsafe { &*p })
+ Self(unsafe { p.as_ref().unwrap() })
}
/// Returns the digest size in bytes.
@@ -51,6 +67,39 @@
// SAFETY: The inner pointer is fetched from EVP_* hash functions in BoringSSL digest.h
unsafe { EVP_MD_size(self.0) }
}
+
+ /// Computes the digest of the provided `data`.
+ pub fn digest(&self, data: &[u8]) -> Result<Vec<u8>> {
+ let mut out = vec![0u8; MAX_DIGEST_SIZE];
+ let mut out_size = 0;
+ let engine = ptr::null_mut(); // Use the default engine.
+ let ret =
+ // SAFETY: This function reads `data` and writes to `out` within its bounds.
+ // `out` has `MAX_DIGEST_SIZE` bytes of space for write as required in the
+ // BoringSSL spec.
+ // The digester is a valid pointer to a static `EVP_MD` as it is returned by
+ // BoringSSL API during the construction of this struct.
+ unsafe {
+ EVP_Digest(
+ data.as_ptr() as *const _,
+ data.len(),
+ out.as_mut_ptr(),
+ &mut out_size,
+ self.0,
+ engine,
+ )
+ };
+ check_int_result(ret, ApiName::EVP_Digest)?;
+ let out_size = usize::try_from(out_size).map_err(|e| {
+ error!("Failed to convert digest size to usize: {:?}", e);
+ Error::InternalError
+ })?;
+ if self.size() != out_size {
+ return Err(to_call_failed_error(ApiName::EVP_Digest));
+ }
+ out.truncate(out_size);
+ Ok(out)
+ }
}
/// Message digester context wrapping `EVP_MD_CTX`.