[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))
-    }
-}