[bssl] Add digest and hmac modules to libbssl
Bug: 301068421
Test: atest rialto_test
Change-Id: I1d61902b80cc71c554b1009e6e1c91401164e7cf
diff --git a/libs/bssl/error/src/lib.rs b/libs/bssl/error/src/lib.rs
index 73afbc2..24e5a56 100644
--- a/libs/bssl/error/src/lib.rs
+++ b/libs/bssl/error/src/lib.rs
@@ -55,6 +55,5 @@
EC_KEY_marshal_private_key,
EC_KEY_new_by_curve_name,
EC_POINT_get_affine_coordinates,
- EVP_sha256,
HMAC,
}
diff --git a/libs/bssl/src/digest.rs b/libs/bssl/src/digest.rs
new file mode 100644
index 0000000..47e4aba
--- /dev/null
+++ b/libs/bssl/src/digest.rs
@@ -0,0 +1,50 @@
+// Copyright 2023, The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//! Wrappers of the digest functions in BoringSSL digest.h.
+
+use bssl_ffi::{EVP_MD_size, EVP_sha256, EVP_sha512, EVP_MD};
+
+/// Message digester wrapping `EVP_MD`.
+#[derive(Clone, Debug)]
+pub struct Digester(pub(crate) &'static EVP_MD);
+
+impl Digester {
+ /// Returns a `Digester` implementing `SHA-256` algorithm.
+ pub fn sha256() -> 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_sha256() };
+ // SAFETY: The returned pointer should always be valid and points to a static
+ // `EVP_MD`.
+ Self(unsafe { &*p })
+ }
+
+ /// Returns a `Digester` implementing `SHA-512` algorithm.
+ #[allow(dead_code)]
+ pub fn sha512() -> 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_sha512() };
+ // SAFETY: The returned pointer should always be valid and points to a static
+ // `EVP_MD`.
+ Self(unsafe { &*p })
+ }
+
+ /// Returns the digest size in bytes.
+ pub fn size(&self) -> usize {
+ // SAFETY: The inner pointer is fetched from EVP_* hash functions in BoringSSL digest.h
+ unsafe { EVP_MD_size(self.0) }
+ }
+}
diff --git a/libs/bssl/src/hmac.rs b/libs/bssl/src/hmac.rs
new file mode 100644
index 0000000..1e09315
--- /dev/null
+++ b/libs/bssl/src/hmac.rs
@@ -0,0 +1,58 @@
+// Copyright 2023, The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//! Wrappers of the HMAC functions in BoringSSL hmac.h.
+
+use crate::digest::Digester;
+use bssl_avf_error::{ApiName, Error, Result};
+use bssl_ffi::{HMAC, SHA256_DIGEST_LENGTH};
+
+const SHA256_LEN: usize = SHA256_DIGEST_LENGTH as usize;
+
+/// Computes the HMAC using SHA-256 for the given `data` with the given `key`.
+pub fn hmac_sha256(key: &[u8], data: &[u8]) -> Result<[u8; SHA256_LEN]> {
+ hmac::<SHA256_LEN>(key, data, Digester::sha256())
+}
+
+/// Computes the HMAC for the given `data` with the given `key` and `digester`.
+///
+/// The output size `HASH_LEN` should correspond to the length of the hash function's
+/// digest size in bytes.
+fn hmac<const HASH_LEN: usize>(
+ key: &[u8],
+ data: &[u8],
+ digester: Digester,
+) -> Result<[u8; HASH_LEN]> {
+ assert_eq!(digester.size(), HASH_LEN);
+
+ let mut out = [0u8; HASH_LEN];
+ let mut out_len = 0;
+ // SAFETY: Only reads from/writes to the provided slices and the digester was non-null.
+ let ret = unsafe {
+ HMAC(
+ digester.0,
+ key.as_ptr() as *const _,
+ key.len(),
+ data.as_ptr(),
+ data.len(),
+ out.as_mut_ptr(),
+ &mut out_len,
+ )
+ };
+ if !ret.is_null() && out_len == (out.len() as u32) {
+ Ok(out)
+ } else {
+ Err(Error::CallFailed(ApiName::HMAC))
+ }
+}
diff --git a/libs/bssl/src/lib.rs b/libs/bssl/src/lib.rs
index 85890ee..500419b 100644
--- a/libs/bssl/src/lib.rs
+++ b/libs/bssl/src/lib.rs
@@ -19,8 +19,11 @@
extern crate alloc;
mod cbb;
+mod digest;
mod ec_key;
+mod hmac;
pub use bssl_avf_error::{ApiName, Error, Result};
pub use cbb::CbbFixed;
pub use ec_key::{EcKey, ZVec};
+pub use hmac::hmac_sha256;
diff --git a/rialto/src/requests/pub_key.rs b/rialto/src/requests/pub_key.rs
index a86ddee..110e3d2 100644
--- a/rialto/src/requests/pub_key.rs
+++ b/rialto/src/requests/pub_key.rs
@@ -14,11 +14,8 @@
//! Handles the construction of the MACed public key.
-use alloc::vec;
use alloc::vec::Vec;
-use bssl_avf::{self, ApiName};
-use bssl_ffi::EVP_sha256;
-use bssl_ffi::HMAC;
+use bssl_avf::hmac_sha256;
use core::result;
use coset::{iana, CborSerializable, CoseKey, CoseMac0, CoseMac0Builder, HeaderBuilder};
use service_vm_comm::RequestProcessingError;
@@ -51,39 +48,7 @@
let cose_mac = CoseMac0Builder::new()
.protected(protected)
.payload(public_key.to_vec()?)
- .try_create_tag(external_aad, |data| hmac_sha256(hmac_key, data))?
+ .try_create_tag(external_aad, |data| hmac_sha256(hmac_key, data).map(|v| v.to_vec()))?
.build();
Ok(cose_mac.to_vec()?)
}
-
-/// Computes the HMAC using SHA-256 for the given `data` with the given `key`.
-fn hmac_sha256(key: &[u8], data: &[u8]) -> bssl_avf::Result<Vec<u8>> {
- const SHA256_HMAC_LEN: usize = 32;
-
- let mut out = vec![0u8; SHA256_HMAC_LEN];
- let mut out_len = 0;
- // SAFETY: The function shouldn't access any Rust variable and the returned value is accepted
- // as a potentially NULL pointer.
- let digester = unsafe { EVP_sha256() };
- if digester.is_null() {
- return Err(bssl_avf::Error::CallFailed(ApiName::EVP_sha256));
- }
- // SAFETY: Only reads from/writes to the provided slices and supports digester was checked not
- // be NULL.
- let ret = unsafe {
- HMAC(
- digester,
- key.as_ptr() as *const _,
- key.len(),
- data.as_ptr(),
- data.len(),
- out.as_mut_ptr(),
- &mut out_len,
- )
- };
- if !ret.is_null() && out_len == (out.len() as u32) {
- Ok(out)
- } else {
- Err(bssl_avf::Error::CallFailed(ApiName::HMAC))
- }
-}