[bssl] Support ED25519/X25519 public key types for EVP_PKEY

These ED25519 key type will be needed in DICE certificate
verification later.

Bug: 310931749
Test: atest libbssl_avf_nostd.test
Change-Id: I9dda103f3f46f781dec6f0062cdbf29d3078559f
diff --git a/libs/bssl/src/evp.rs b/libs/bssl/src/evp.rs
index 5362925..330f317 100644
--- a/libs/bssl/src/evp.rs
+++ b/libs/bssl/src/evp.rs
@@ -15,22 +15,24 @@
 //! Wrappers of the EVP functions in BoringSSL evp.h.
 
 use crate::cbb::CbbFixed;
+use crate::digest::{Digester, DigesterContext};
 use crate::ec_key::EcKey;
 use crate::util::{check_int_result, to_call_failed_error};
 use alloc::vec::Vec;
 use bssl_avf_error::{ApiName, Result};
 use bssl_ffi::{
-    CBB_flush, CBB_len, EVP_PKEY_free, EVP_PKEY_new, EVP_PKEY_set1_EC_KEY, EVP_marshal_public_key,
-    EVP_PKEY,
+    CBB_flush, CBB_len, EVP_DigestVerify, EVP_DigestVerifyInit, EVP_PKEY_free, EVP_PKEY_new,
+    EVP_PKEY_new_raw_public_key, EVP_PKEY_set1_EC_KEY, EVP_marshal_public_key, EVP_PKEY,
+    EVP_PKEY_ED25519, EVP_PKEY_X25519,
 };
-use core::ptr::NonNull;
+use core::ptr::{self, NonNull};
 
 /// Wrapper of an `EVP_PKEY` object, representing a public or private key.
 pub struct PKey {
     pkey: NonNull<EVP_PKEY>,
-    /// Since this struct owns the inner key, the inner key remains valid as
+    /// If this struct owns the inner EC key, the inner EC key should remain valid as
     /// long as the pointer to `EVP_PKEY` is valid.
-    _inner_key: EcKey,
+    _inner_ec_key: Option<EcKey>,
 }
 
 impl Drop for PKey {
@@ -53,14 +55,14 @@
 
     fn try_from(key: EcKey) -> Result<Self> {
         let pkey = new_pkey()?;
-        // SAFETY: The function only sets the inner key of the initialized and
+        // SAFETY: The function only sets the inner EC key of the initialized and
         // non-null `EVP_PKEY` to point to the given `EC_KEY`. It only reads from
         // and writes to the initialized `EVP_PKEY`.
         // Since this struct owns the inner key, the inner key remains valid as
         // long as `EVP_PKEY` is valid.
         let ret = unsafe { EVP_PKEY_set1_EC_KEY(pkey.as_ptr(), key.0.as_ptr()) };
         check_int_result(ret, ApiName::EVP_PKEY_set1_EC_KEY)?;
-        Ok(Self { pkey, _inner_key: key })
+        Ok(Self { pkey, _inner_ec_key: Some(key) })
     }
 }
 
@@ -87,4 +89,89 @@
         let len = unsafe { CBB_len(cbb.as_ref()) };
         Ok(buf.get(0..len).ok_or(to_call_failed_error(ApiName::CBB_len))?.to_vec())
     }
+
+    /// This function takes a raw public key data slice and creates a `PKey` instance wrapping
+    /// a freshly allocated `EVP_PKEY` object from it.
+    ///
+    /// The lifetime of the returned instance is not tied to the lifetime of the raw public
+    /// key slice because the raw data is copied into the `EVP_PKEY` object.
+    ///
+    /// Currently the only supported raw formats are X25519 and Ed25519, where the formats
+    /// are specified in RFC 7748 and RFC 8032 respectively.
+    pub fn new_raw_public_key(raw_public_key: &[u8], type_: PKeyType) -> Result<Self> {
+        let engine = ptr::null_mut(); // Engine is not used.
+        let pkey =
+            // SAFETY: The function only reads from the given raw public key within its bounds.
+            // The returned pointer is checked below.
+            unsafe {
+                EVP_PKEY_new_raw_public_key(
+                    type_.0,
+                    engine,
+                    raw_public_key.as_ptr(),
+                    raw_public_key.len(),
+                )
+            };
+        let pkey =
+            NonNull::new(pkey).ok_or(to_call_failed_error(ApiName::EVP_PKEY_new_raw_public_key))?;
+        Ok(Self { pkey, _inner_ec_key: None })
+    }
+
+    /// Verifies the given `signature` of the `message` using the current public key.
+    ///
+    /// The `message` will be hashed using the given `digester` before verification.
+    ///
+    /// For algorithms like Ed25519 that do not use pre-hashed inputs, the `digester` should
+    /// be `None`.
+    pub fn verify(
+        &self,
+        signature: &[u8],
+        message: &[u8],
+        digester: Option<Digester>,
+    ) -> Result<()> {
+        let mut digester_context = DigesterContext::new()?;
+        // The `EVP_PKEY_CTX` is set to null as this function does not collect the context
+        // during the verification.
+        let pkey_context = ptr::null_mut();
+        let engine = ptr::null_mut(); // Use the default engine.
+        let ret =
+            // SAFETY: All the non-null parameters passed to this function have been properly
+            // initialized as required in the BoringSSL spec.
+            unsafe {
+                EVP_DigestVerifyInit(
+                    digester_context.as_mut_ptr(),
+                    pkey_context,
+                    digester.map_or(ptr::null(), |d| d.0),
+                    engine,
+                    self.pkey.as_ptr(),
+                )
+            };
+        check_int_result(ret, ApiName::EVP_DigestVerifyInit)?;
+
+        // SAFETY: The function only reads from the given slices within their bounds.
+        // The `EVP_MD_CTX` is successfully initialized before this call.
+        let ret = unsafe {
+            EVP_DigestVerify(
+                digester_context.as_mut_ptr(),
+                signature.as_ptr(),
+                signature.len(),
+                message.as_ptr(),
+                message.len(),
+            )
+        };
+        check_int_result(ret, ApiName::EVP_DigestVerify)
+    }
+}
+
+/// Type of the keys supported by `PKey`.
+///
+/// It is a wrapper of the `EVP_PKEY_*` macros defined BoringSSL evp.h, which are the
+/// NID values of the corresponding keys.
+#[derive(Debug, Copy, Clone, PartialEq, Eq)]
+pub struct PKeyType(i32);
+
+impl PKeyType {
+    /// EVP_PKEY_X25519 / NID_X25519
+    pub const X25519: PKeyType = PKeyType(EVP_PKEY_X25519);
+    /// EVP_PKEY_ED25519 / NID_ED25519
+    pub const ED25519: PKeyType = PKeyType(EVP_PKEY_ED25519);
 }