[rkp] Generate EC P-256 key pair for the RKP HAL

This cl generates the EC P-256 key pair needed by the RKP HAL.
The MAC of the public key and wrapping of the private key will be
handled in subsequent cls.

Bug: 299055662
Test: atest rialto_test
Change-Id: I253130e62bbf70cb5a7abe1a056fc4f77d30aa6e
diff --git a/rialto/Android.bp b/rialto/Android.bp
index 05775c2..cb3e477 100644
--- a/rialto/Android.bp
+++ b/rialto/Android.bp
@@ -9,6 +9,7 @@
     defaults: ["vmbase_ffi_defaults"],
     rustlibs: [
         "libaarch64_paging",
+        "libbssl_ffi_nostd",
         "libciborium_io_nostd",
         "libciborium_nostd",
         "libdiced_open_dice_nostd",
@@ -21,6 +22,10 @@
         "libtinyvec_nostd",
         "libvirtio_drivers",
         "libvmbase",
+        "libzeroize_nostd",
+    ],
+    static_libs: [
+        "libcrypto_baremetal",
     ],
 }
 
diff --git a/rialto/src/main.rs b/rialto/src/main.rs
index 8b73130..43215a0 100644
--- a/rialto/src/main.rs
+++ b/rialto/src/main.rs
@@ -29,6 +29,7 @@
 use crate::error::{Error, Result};
 use crate::fdt::read_dice_range_from;
 use alloc::boxed::Box;
+use bssl_ffi::CRYPTO_library_init;
 use ciborium_io::Write;
 use core::num::NonZeroUsize;
 use core::slice;
@@ -134,6 +135,13 @@
             e
         })?;
     }
+
+    // Initializes the crypto library before any crypto operations and after the heap is
+    // initialized.
+    // SAFETY: It is safe to call this function multiple times and concurrently.
+    unsafe {
+        CRYPTO_library_init();
+    }
     let bcc_handover: Box<dyn DiceArtifacts> = match vm_type() {
         VmType::ProtectedVm => {
             let dice_range = read_dice_range_from(fdt)?;
diff --git a/rialto/src/requests/ec_key.rs b/rialto/src/requests/ec_key.rs
new file mode 100644
index 0000000..2f3fe90
--- /dev/null
+++ b/rialto/src/requests/ec_key.rs
@@ -0,0 +1,131 @@
+// 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.
+
+//! Contains struct and functions that wraps the API related to EC_KEY in
+//! BoringSSL.
+
+use alloc::vec::Vec;
+use bssl_ffi::CBB_flush;
+use bssl_ffi::CBB_init_fixed;
+use bssl_ffi::CBB_len;
+use bssl_ffi::EC_KEY_free;
+use bssl_ffi::EC_KEY_generate_key;
+use bssl_ffi::EC_KEY_marshal_private_key;
+use bssl_ffi::EC_KEY_new_by_curve_name;
+use bssl_ffi::NID_X9_62_prime256v1; // EC P-256 CURVE Nid
+use bssl_ffi::EC_KEY;
+use core::mem::MaybeUninit;
+use core::ptr::NonNull;
+use core::result;
+use service_vm_comm::{BoringSSLApiName, RequestProcessingError};
+use zeroize::{Zeroize, ZeroizeOnDrop, Zeroizing};
+
+type Result<T> = result::Result<T, RequestProcessingError>;
+
+/// Wrapper of an `EC_KEY` object, representing a public or private EC key.
+pub struct EcKey(NonNull<EC_KEY>);
+
+impl Drop for EcKey {
+    fn drop(&mut self) {
+        // SAFETY: It is safe because the key has been allocated by BoringSSL and isn't
+        // used after this.
+        unsafe { EC_KEY_free(self.0.as_ptr()) }
+    }
+}
+
+impl EcKey {
+    /// Creates a new EC P-256 key pair.
+    pub fn new_p256() -> Result<Self> {
+        // SAFETY: The returned pointer is checked below.
+        let ec_key = unsafe { EC_KEY_new_by_curve_name(NID_X9_62_prime256v1) };
+        let mut ec_key = NonNull::new(ec_key).map(Self).ok_or(
+            RequestProcessingError::BoringSSLCallFailed(BoringSSLApiName::EC_KEY_new_by_curve_name),
+        )?;
+        ec_key.generate_key()?;
+        Ok(ec_key)
+    }
+
+    /// Generates a random, private key, calculates the corresponding public key and stores both
+    /// in the `EC_KEY`.
+    fn generate_key(&mut self) -> Result<()> {
+        // SAFETY: The non-null pointer is created with `EC_KEY_new_by_curve_name` and should
+        // point to a valid `EC_KEY`.
+        // The randomness is provided by `getentropy()` in `vmbase`.
+        let ret = unsafe { EC_KEY_generate_key(self.0.as_ptr()) };
+        check_int_result(ret, BoringSSLApiName::EC_KEY_generate_key)
+    }
+
+    // TODO(b/300068317): Returns the CoseKey for the public key.
+
+    /// Returns the DER-encoded ECPrivateKey structure described in RFC 5915 Section 3:
+    ///
+    /// https://datatracker.ietf.org/doc/html/rfc5915#section-3
+    pub fn private_key(&self) -> Result<ZVec> {
+        const CAPACITY: usize = 256;
+        let mut buf = Zeroizing::new([0u8; CAPACITY]);
+        // SAFETY: `CBB_init_fixed()` is infallible and always returns one.
+        // The `buf` is never moved and remains valid during the lifetime of `cbb`.
+        let mut cbb = unsafe {
+            let mut cbb = MaybeUninit::uninit();
+            CBB_init_fixed(cbb.as_mut_ptr(), buf.as_mut_ptr(), buf.len());
+            cbb.assume_init()
+        };
+        let enc_flags = 0;
+        let ret =
+            // SAFETY: The function only write bytes to the buffer managed by the valid `CBB`
+            // object, and the key has been allocated by BoringSSL.
+            unsafe { EC_KEY_marshal_private_key(&mut cbb, self.0.as_ptr(), enc_flags) };
+
+        check_int_result(ret, BoringSSLApiName::EC_KEY_marshal_private_key)?;
+        // SAFETY: This is safe because the CBB pointer is a valid pointer initialized with
+        // `CBB_init_fixed()`.
+        check_int_result(unsafe { CBB_flush(&mut cbb) }, BoringSSLApiName::CBB_flush)?;
+        // SAFETY: This is safe because the CBB pointer is initialized with `CBB_init_fixed()`,
+        // and it has been flushed, thus it has no active children.
+        let len = unsafe { CBB_len(&cbb) };
+        Ok(buf
+            .get(0..len)
+            .ok_or(RequestProcessingError::BoringSSLCallFailed(BoringSSLApiName::CBB_len))?
+            .to_vec()
+            .into())
+    }
+}
+
+/// A u8 vector that is zeroed when dropped.
+#[derive(Zeroize, ZeroizeOnDrop)]
+pub struct ZVec(Vec<u8>);
+
+impl ZVec {
+    /// Extracts a slice containing the entire vector.
+    pub fn as_slice(&self) -> &[u8] {
+        &self.0[..]
+    }
+}
+
+impl From<Vec<u8>> for ZVec {
+    fn from(v: Vec<u8>) -> Self {
+        Self(v)
+    }
+}
+
+fn check_int_result(ret: i32, api_name: BoringSSLApiName) -> Result<()> {
+    if ret == 1 {
+        Ok(())
+    } else {
+        assert_eq!(ret, 0, "Unexpected return value {ret} for {api_name:?}");
+        Err(RequestProcessingError::BoringSSLCallFailed(api_name))
+    }
+}
+
+// TODO(b/301068421): Unit tests the EcKey.
diff --git a/rialto/src/requests/mod.rs b/rialto/src/requests/mod.rs
index 2ed568c..d70791f 100644
--- a/rialto/src/requests/mod.rs
+++ b/rialto/src/requests/mod.rs
@@ -15,6 +15,7 @@
 //! This module contains functions for the request processing.
 
 mod api;
+mod ec_key;
 mod rkp;
 
 pub use api::process_request;
diff --git a/rialto/src/requests/rkp.rs b/rialto/src/requests/rkp.rs
index a73b9f4..66d3603 100644
--- a/rialto/src/requests/rkp.rs
+++ b/rialto/src/requests/rkp.rs
@@ -13,8 +13,9 @@
 // limitations under the License.
 
 //! This module contains functions related to the attestation of the
-//! service VM via the RKP (Remote Key Provisionning) server.
+//! service VM via the RKP (Remote Key Provisioning) server.
 
+use super::ec_key::EcKey;
 use alloc::vec::Vec;
 use core::result;
 use diced_open_dice::DiceArtifacts;
@@ -25,7 +26,13 @@
 pub(super) fn generate_ecdsa_p256_key_pair(
     _dice_artifacts: &dyn DiceArtifacts,
 ) -> Result<EcdsaP256KeyPair> {
-    // TODO(b/299055662): Generate the key pair.
+    let ec_key = EcKey::new_p256()?;
+
+    // TODO(b/279425980): Encrypt the private key in a key blob.
+    // Remove the printing of the private key.
+    log::debug!("Private key: {:?}", ec_key.private_key()?.as_slice());
+
+    // TODO(b/300068317): Build MACed public key.
     let key_pair = EcdsaP256KeyPair { maced_public_key: Vec::new(), key_blob: Vec::new() };
     Ok(key_pair)
 }