[bssl] Implement nostd bssl wrapper for ECDSA sign/verify

Bug: 310634099
Test: atest rialto_test libbssl_avf_nostd.test
Change-Id: I817bce28a73fd49c218fa14d9c7ff69eb2e0674d
diff --git a/libs/bssl/src/ec_key.rs b/libs/bssl/src/ec_key.rs
index 572ad4b..7e677c4 100644
--- a/libs/bssl/src/ec_key.rs
+++ b/libs/bssl/src/ec_key.rs
@@ -18,11 +18,12 @@
 use crate::cbb::CbbFixed;
 use crate::cbs::Cbs;
 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::{
-    BN_bin2bn, BN_bn2bin_padded, BN_clear_free, BN_new, CBB_flush, CBB_len,
-    EC_GROUP_new_by_curve_name, EC_KEY_check_key, EC_KEY_free, EC_KEY_generate_key,
+    BN_bin2bn, BN_bn2bin_padded, BN_clear_free, BN_new, CBB_flush, CBB_len, ECDSA_sign, ECDSA_size,
+    ECDSA_verify, EC_GROUP_new_by_curve_name, EC_KEY_check_key, EC_KEY_free, EC_KEY_generate_key,
     EC_KEY_get0_group, EC_KEY_get0_public_key, EC_KEY_marshal_private_key,
     EC_KEY_new_by_curve_name, EC_KEY_parse_private_key, EC_KEY_set_public_key_affine_coordinates,
     EC_POINT_get_affine_coordinates, NID_X9_62_prime256v1, BIGNUM, EC_GROUP, EC_KEY, EC_POINT,
@@ -114,18 +115,68 @@
         check_int_result(ret, ApiName::EC_KEY_check_key)
     }
 
-    /// Verifies the DER-encoded ECDSA `signature` of the `message` with the current `EcKey`.
-    pub fn ecdsa_verify(&self, _signature: &[u8], _message: &[u8]) -> Result<()> {
-        // TODO(b/310634099): Implement ECDSA sign with `bssl::ECDSA_do_sign`.
-        Ok(())
+    /// Verifies the DER-encoded ECDSA `signature` of the `digest` with the current `EcKey`.
+    ///
+    /// Returns Ok(()) if the verification succeeds, otherwise an error will be returned.
+    pub fn ecdsa_verify(&self, signature: &[u8], digest: &[u8]) -> Result<()> {
+        // The `type` argument should be 0 as required in the BoringSSL spec.
+        const TYPE: i32 = 0;
+
+        // SAFETY: This function only reads the given data within its bounds.
+        // The `EC_KEY` passed to this function has been initialized and checked non-null.
+        let ret = unsafe {
+            ECDSA_verify(
+                TYPE,
+                digest.as_ptr(),
+                digest.len(),
+                signature.as_ptr(),
+                signature.len(),
+                self.0.as_ptr(),
+            )
+        };
+        check_int_result(ret, ApiName::ECDSA_verify)
     }
 
-    /// Signs the `message` with the current `EcKey` using ECDSA.
+    /// Signs the `digest` with the current `EcKey` using ECDSA.
     ///
     /// Returns the DER-encoded ECDSA signature.
-    pub fn ecdsa_sign(&self, _message: &[u8]) -> Result<Vec<u8>> {
-        // TODO(b/310634099): Implement ECDSA verify with `bssl::ECDSA_do_verify`.
-        Ok(Vec::new())
+    pub fn ecdsa_sign(&self, digest: &[u8]) -> Result<Vec<u8>> {
+        // The `type` argument should be 0 as required in the BoringSSL spec.
+        const TYPE: i32 = 0;
+
+        let mut signature = vec![0u8; self.ecdsa_size()?];
+        let mut signature_len = 0;
+        // SAFETY: This function only reads the given data within its bounds.
+        // The `EC_KEY` passed to this function has been initialized and checked non-null.
+        let ret = unsafe {
+            ECDSA_sign(
+                TYPE,
+                digest.as_ptr(),
+                digest.len(),
+                signature.as_mut_ptr(),
+                &mut signature_len,
+                self.0.as_ptr(),
+            )
+        };
+        check_int_result(ret, ApiName::ECDSA_sign)?;
+        if signature.len() < (signature_len as usize) {
+            Err(to_call_failed_error(ApiName::ECDSA_sign))
+        } else {
+            signature.truncate(signature_len as usize);
+            Ok(signature)
+        }
+    }
+
+    /// Returns the maximum size of an ECDSA signature using the current `EcKey`.
+    fn ecdsa_size(&self) -> Result<usize> {
+        // SAFETY: This function only reads the `EC_KEY` that has been initialized
+        // and checked non-null when this instance is created.
+        let size = unsafe { ECDSA_size(self.0.as_ptr()) };
+        if size == 0 {
+            Err(to_call_failed_error(ApiName::ECDSA_size))
+        } else {
+            Ok(size)
+        }
     }
 
     /// Generates a random, private key, calculates the corresponding public key and stores both