Adds functionality for instantiating and using `Algorithm`

This CL moves some methods that exist in every hashing algorithm
implementation to the `Algorithm` trait; namely, `new`, `update`,
and `digest`. This allows for clients to instantiate the hashing
algorithms, and to call `update` and `digest` on objects that
have this trait. It allows a generic representation of an algorithm
that can be used.

This CL also adds the block size as a const field in the `Algorithm`
trait.

Note: this specifically supports the hashing algorithm use in the
style of what is done in AOSP's
`packages/modules/Virtualization/libs/apkverify`, which was previously
using the rust openssl `Hasher` to instantiate algorithms specified
by their `MessageDigest`.

Change-Id: Ic47691ee2a4303923519b246de7d9724da90f60d
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/68748
Commit-Queue: Ellen Arteca <emarteca@google.com>
Commit-Queue: Adam Langley <agl@google.com>
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/rust/bssl-crypto/src/digest.rs b/rust/bssl-crypto/src/digest.rs
index 645ab80..125f427 100644
--- a/rust/bssl-crypto/src/digest.rs
+++ b/rust/bssl-crypto/src/digest.rs
@@ -45,6 +45,8 @@
 pub trait Algorithm {
     /// The size of the resulting digest.
     const OUTPUT_LEN: usize;
+    /// The block length (in bytes).
+    const BLOCK_LEN: usize;
 
     /// Gets a reference to a message digest algorithm to be used by the HKDF implementation.
     #[doc(hidden)]
@@ -52,6 +54,23 @@
 
     /// Hashes a message.
     fn hash_to_vec(input: &[u8]) -> Vec<u8>;
+
+    /// Create a new context for incremental hashing.
+    fn new() -> Self;
+
+    /// Hash the contents of `input`.
+    fn update(&mut self, input: &[u8]);
+
+    /// Finish the hashing and return the digest.
+    fn digest_to_vec(mut self) -> Vec<u8>;
+}
+
+/// Trait parameterized by the size of the output of the digest
+/// so that it can provide algorithm functions that depend on
+/// this parameter.
+pub trait WithOutputLength<const OUTPUT_LEN: usize> {
+    /// Finish the hashing and return the digest.
+    fn digest(mut self) -> [u8; OUTPUT_LEN];
 }
 
 /// The insecure SHA-1 hash algorithm.
@@ -67,6 +86,7 @@
 unsafe_iuf_algo!(
     InsecureSha1,
     20,
+    64,
     EVP_sha1,
     SHA1,
     SHA1_Init,
@@ -83,6 +103,7 @@
 unsafe_iuf_algo!(
     Sha256,
     32,
+    64,
     EVP_sha256,
     SHA256,
     SHA256_Init,
@@ -99,6 +120,7 @@
 unsafe_iuf_algo!(
     Sha384,
     48,
+    128,
     EVP_sha384,
     SHA384,
     SHA384_Init,
@@ -115,6 +137,7 @@
 unsafe_iuf_algo!(
     Sha512,
     64,
+    128,
     EVP_sha512,
     SHA512,
     SHA512_Init,
@@ -131,6 +154,7 @@
 unsafe_iuf_algo!(
     Sha512_256,
     32,
+    128,
     EVP_sha512_256,
     SHA512_256,
     SHA512_256_Init,
diff --git a/rust/bssl-crypto/src/macros.rs b/rust/bssl-crypto/src/macros.rs
index 6ac3d37..0d49646 100644
--- a/rust/bssl-crypto/src/macros.rs
+++ b/rust/bssl-crypto/src/macros.rs
@@ -22,9 +22,10 @@
 // Safety: see the "Safety" sections within about the requirements for the
 // functions named in the macro parameters.
 macro_rules! unsafe_iuf_algo {
-    ($name:ident, $output_len:expr, $evp_md:ident, $one_shot:ident, $init:ident, $update:ident, $final_func:ident) => {
+    ($name:ident, $output_len:expr, $block_len:expr, $evp_md:ident, $one_shot:ident, $init:ident, $update:ident, $final_func:ident) => {
         impl Algorithm for $name {
             const OUTPUT_LEN: usize = $output_len as usize;
+            const BLOCK_LEN: usize = $block_len as usize;
 
             fn get_md(_: sealed::Sealed) -> &'static MdRef {
                 // Safety:
@@ -35,6 +36,45 @@
             fn hash_to_vec(input: &[u8]) -> Vec<u8> {
                 Self::hash(input).as_slice().to_vec()
             }
+
+            /// Create a new context for incremental hashing.
+            fn new() -> Self {
+                unsafe {
+                    Self {
+                        ctx: crate::initialized_struct(|ctx| {
+                            // Safety: type checking will ensure that `ctx` is the
+                            // correct type for `$init` to write into.
+                            bssl_sys::$init(ctx);
+                        }),
+                    }
+                }
+            }
+
+            /// Hash the contents of `input`.
+            fn update(&mut self, input: &[u8]) {
+                // Safety: arguments point to a valid buffer.
+                unsafe {
+                    bssl_sys::$update(&mut self.ctx, input.as_ffi_void_ptr(), input.len());
+                }
+            }
+
+            /// Finish the hashing and return the digest.
+            fn digest_to_vec(mut self) -> alloc::vec::Vec<u8> {
+                WithOutputLength::<$output_len>::digest(self).to_vec()
+            }
+        }
+
+        impl<const OUTPUT_LEN: usize> WithOutputLength<OUTPUT_LEN> for $name {
+            /// Finish the hashing and return the digest.
+            fn digest(mut self) -> [u8; OUTPUT_LEN] {
+                // Safety: it is assumed that `$final_func` indeed writes
+                // `$output_len` bytes.
+                unsafe {
+                    crate::with_output_array(|out, _| {
+                        bssl_sys::$final_func(out, &mut self.ctx);
+                    })
+                }
+            }
         }
 
         impl $name {
@@ -48,38 +88,6 @@
                     })
                 }
             }
-
-            /// Create a new context for incremental hashing.
-            pub fn new() -> Self {
-                unsafe {
-                    Self {
-                        ctx: crate::initialized_struct(|ctx| {
-                            // Safety: type checking will ensure that `ctx` is the
-                            // correct type for `$init` to write into.
-                            bssl_sys::$init(ctx);
-                        }),
-                    }
-                }
-            }
-
-            /// Hash the contents of `input`.
-            pub fn update(&mut self, input: &[u8]) {
-                // Safety: arguments point to a valid buffer.
-                unsafe {
-                    bssl_sys::$update(&mut self.ctx, input.as_ffi_void_ptr(), input.len());
-                }
-            }
-
-            /// Finish the hashing and return the digest.
-            pub fn digest(mut self) -> [u8; $output_len] {
-                // Safety: it is assumed that `$final_func` indeed writes
-                // `$output_len` bytes.
-                unsafe {
-                    crate::with_output_array(|out, _| {
-                        bssl_sys::$final_func(out, &mut self.ctx);
-                    })
-                }
-            }
         }
 
         impl From<$name> for [u8; $output_len] {
@@ -90,7 +98,7 @@
 
         impl From<$name> for alloc::vec::Vec<u8> {
             fn from(ctx: $name) -> alloc::vec::Vec<u8> {
-                ctx.digest().into()
+                ctx.digest_to_vec()
             }
         }