Merge "[pvmfw] Use AEAD wrapper from libbssl_avf" into main
diff --git a/libs/bssl/src/aead.rs b/libs/bssl/src/aead.rs
index e0c9fbb..1ac2c22 100644
--- a/libs/bssl/src/aead.rs
+++ b/libs/bssl/src/aead.rs
@@ -18,8 +18,8 @@
 use bssl_avf_error::{ApiName, Result};
 use bssl_ffi::{
     EVP_AEAD_CTX_free, EVP_AEAD_CTX_new, EVP_AEAD_CTX_open, EVP_AEAD_CTX_seal,
-    EVP_AEAD_max_overhead, EVP_AEAD_nonce_length, EVP_aead_aes_256_gcm, EVP_AEAD, EVP_AEAD_CTX,
-    EVP_AEAD_DEFAULT_TAG_LENGTH,
+    EVP_AEAD_max_overhead, EVP_AEAD_nonce_length, EVP_aead_aes_256_gcm,
+    EVP_aead_aes_256_gcm_randnonce, EVP_AEAD, EVP_AEAD_CTX, EVP_AEAD_DEFAULT_TAG_LENGTH,
 };
 use core::ptr::NonNull;
 
@@ -51,6 +51,17 @@
         Self(unsafe { &*p })
     }
 
+    /// AES-256 in Galois Counter Mode with internal nonce generation.
+    /// The 12-byte nonce is appended to the tag and is generated internally.
+    pub fn aes_256_gcm_randnonce() -> 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_aead_aes_256_gcm_randnonce() };
+        // SAFETY: The returned pointer should always be valid and points to a static
+        // `EVP_AEAD`.
+        Self(unsafe { &*p })
+    }
+
     /// Returns the maximum number of additional bytes added by the act of sealing data.
     pub fn max_overhead(&self) -> usize {
         // SAFETY: This function only reads from self.
diff --git a/pvmfw/src/crypto.rs b/pvmfw/src/crypto.rs
deleted file mode 100644
index 8f31553..0000000
--- a/pvmfw/src/crypto.rs
+++ /dev/null
@@ -1,271 +0,0 @@
-// 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.
-
-//! Wrapper around BoringSSL/OpenSSL symbols.
-
-use core::convert::AsRef;
-use core::ffi::{c_char, c_int, CStr};
-use core::fmt;
-use core::mem::MaybeUninit;
-use core::num::NonZeroU32;
-use core::ptr;
-
-use bssl_ffi::CRYPTO_library_init;
-use bssl_ffi::ERR_get_error_line;
-use bssl_ffi::ERR_lib_error_string;
-use bssl_ffi::ERR_reason_error_string;
-use bssl_ffi::EVP_AEAD_CTX_aead;
-use bssl_ffi::EVP_AEAD_CTX_init;
-use bssl_ffi::EVP_AEAD_CTX_open;
-use bssl_ffi::EVP_AEAD_CTX_seal;
-use bssl_ffi::EVP_AEAD_max_overhead;
-use bssl_ffi::EVP_aead_aes_256_gcm_randnonce;
-use bssl_ffi::EVP_AEAD;
-use bssl_ffi::EVP_AEAD_CTX;
-use cstr::cstr;
-
-#[derive(Debug)]
-pub struct Error {
-    packed: NonZeroU32,
-    file: Option<&'static CStr>,
-    line: c_int,
-}
-
-impl Error {
-    fn get() -> Option<Self> {
-        let mut file = ptr::null();
-        let mut line = 0;
-        // SAFETY: The function writes to the provided pointers, which are valid because they come
-        // from references. It doesn't retain them after it returns.
-        let packed = unsafe { ERR_get_error_line(&mut file, &mut line) };
-
-        let packed = packed.try_into().ok()?;
-        // SAFETY: Any non-NULL result is expected to point to a global const C string.
-        let file = unsafe { as_static_cstr(file) };
-
-        Some(Self { packed, file, line })
-    }
-
-    fn packed_value(&self) -> u32 {
-        self.packed.get()
-    }
-
-    fn library_name(&self) -> Option<&'static CStr> {
-        // SAFETY: Call to a pure function.
-        let name = unsafe { ERR_lib_error_string(self.packed_value()) };
-        // SAFETY: Any non-NULL result is expected to point to a global const C string.
-        unsafe { as_static_cstr(name) }
-    }
-
-    fn reason(&self) -> Option<&'static CStr> {
-        // SAFETY: Call to a pure function.
-        let reason = unsafe { ERR_reason_error_string(self.packed_value()) };
-        // SAFETY: Any non-NULL result is expected to point to a global const C string.
-        unsafe { as_static_cstr(reason) }
-    }
-}
-
-impl fmt::Display for Error {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        let packed = self.packed_value();
-        let library = self.library_name().unwrap_or(cstr!("{unknown library}")).to_str().unwrap();
-        let reason = self.reason().unwrap_or(cstr!("{unknown reason}")).to_str().unwrap();
-        let file = self.file.unwrap_or(cstr!("??")).to_str().unwrap();
-        let line = self.line;
-
-        write!(f, "{file}:{line}: {library}: {reason} ({packed:#x})")
-    }
-}
-
-#[derive(Copy, Clone)]
-pub struct ErrorIterator {}
-
-impl Iterator for ErrorIterator {
-    type Item = Error;
-
-    fn next(&mut self) -> Option<Self::Item> {
-        Self::Item::get()
-    }
-}
-
-pub type Result<T> = core::result::Result<T, ErrorIterator>;
-
-#[repr(transparent)]
-pub struct Aead(EVP_AEAD);
-
-impl Aead {
-    pub fn aes_256_gcm_randnonce() -> Option<&'static Self> {
-        // SAFETY: Returned pointer is checked below.
-        let aead = unsafe { EVP_aead_aes_256_gcm_randnonce() };
-        if aead.is_null() {
-            None
-        } else {
-            // SAFETY: We assume that the non-NULL value points to a valid and static EVP_AEAD.
-            Some(unsafe { &*(aead as *const _) })
-        }
-    }
-
-    pub fn max_overhead(&self) -> usize {
-        // SAFETY: Function should only read from self.
-        unsafe { EVP_AEAD_max_overhead(self.as_ref() as *const _) }
-    }
-}
-
-#[repr(transparent)]
-pub struct AeadCtx(EVP_AEAD_CTX);
-
-impl AeadCtx {
-    pub fn new_aes_256_gcm_randnonce(key: &[u8]) -> Result<Self> {
-        let aead = Aead::aes_256_gcm_randnonce().unwrap();
-
-        Self::new(aead, key)
-    }
-
-    fn new(aead: &'static Aead, key: &[u8]) -> Result<Self> {
-        const DEFAULT_TAG_LENGTH: usize = 0;
-        let engine = ptr::null_mut(); // Use default implementation.
-        let mut ctx = MaybeUninit::zeroed();
-        // SAFETY: Initialize the EVP_AEAD_CTX with const pointers to the AEAD and key.
-        let result = unsafe {
-            EVP_AEAD_CTX_init(
-                ctx.as_mut_ptr(),
-                aead.as_ref() as *const _,
-                key.as_ptr(),
-                key.len(),
-                DEFAULT_TAG_LENGTH,
-                engine,
-            )
-        };
-
-        if result == 1 {
-            // SAFETY: We assume that the non-NULL value points to a valid and static EVP_AEAD.
-            Ok(Self(unsafe { ctx.assume_init() }))
-        } else {
-            Err(ErrorIterator {})
-        }
-    }
-
-    pub fn aead(&self) -> Option<&'static Aead> {
-        // SAFETY: The function should only read from self.
-        let aead = unsafe { EVP_AEAD_CTX_aead(self.as_ref() as *const _) };
-        if aead.is_null() {
-            None
-        } else {
-            // SAFETY: We assume that the non-NULL value points to a valid and static EVP_AEAD.
-            Some(unsafe { &*(aead as *const _) })
-        }
-    }
-
-    pub fn open<'b>(&self, out: &'b mut [u8], data: &[u8]) -> Result<&'b mut [u8]> {
-        let nonce = ptr::null_mut();
-        let nonce_len = 0;
-        let ad = ptr::null_mut();
-        let ad_len = 0;
-        let mut out_len = MaybeUninit::uninit();
-        // SAFETY: The function should only read from self and write to out (at most the provided
-        // number of bytes) and out_len while reading from data (at most the provided number of
-        // bytes), ignoring any NULL input.
-        let result = unsafe {
-            EVP_AEAD_CTX_open(
-                self.as_ref() as *const _,
-                out.as_mut_ptr(),
-                out_len.as_mut_ptr(),
-                out.len(),
-                nonce,
-                nonce_len,
-                data.as_ptr(),
-                data.len(),
-                ad,
-                ad_len,
-            )
-        };
-
-        if result == 1 {
-            // SAFETY: Any value written to out_len could be a valid usize. The value itself is
-            // validated as being a proper slice length by panicking in the following indexing
-            // otherwise.
-            let out_len = unsafe { out_len.assume_init() };
-            Ok(&mut out[..out_len])
-        } else {
-            Err(ErrorIterator {})
-        }
-    }
-
-    pub fn seal<'b>(&self, out: &'b mut [u8], data: &[u8]) -> Result<&'b mut [u8]> {
-        let nonce = ptr::null_mut();
-        let nonce_len = 0;
-        let ad = ptr::null_mut();
-        let ad_len = 0;
-        let mut out_len = MaybeUninit::uninit();
-        // SAFETY: The function should only read from self and write to out (at most the provided
-        // number of bytes) while reading from data (at most the provided number of bytes),
-        // ignoring any NULL input.
-        let result = unsafe {
-            EVP_AEAD_CTX_seal(
-                self.as_ref() as *const _,
-                out.as_mut_ptr(),
-                out_len.as_mut_ptr(),
-                out.len(),
-                nonce,
-                nonce_len,
-                data.as_ptr(),
-                data.len(),
-                ad,
-                ad_len,
-            )
-        };
-
-        if result == 1 {
-            // SAFETY: Any value written to out_len could be a valid usize. The value itself is
-            // validated as being a proper slice length by panicking in the following indexing
-            // otherwise.
-            let out_len = unsafe { out_len.assume_init() };
-            Ok(&mut out[..out_len])
-        } else {
-            Err(ErrorIterator {})
-        }
-    }
-}
-
-/// Cast a C string pointer to a static non-mutable reference.
-///
-/// # Safety
-///
-/// The caller needs to ensure that the pointer is null or points to a valid C string and that the
-/// C lifetime of the string is compatible with a static Rust lifetime.
-unsafe fn as_static_cstr(p: *const c_char) -> Option<&'static CStr> {
-    if p.is_null() {
-        None
-    } else {
-        // Safety: Safe given the requirements of this function.
-        Some(unsafe { CStr::from_ptr(p) })
-    }
-}
-
-impl AsRef<EVP_AEAD> for Aead {
-    fn as_ref(&self) -> &EVP_AEAD {
-        &self.0
-    }
-}
-
-impl AsRef<EVP_AEAD_CTX> for AeadCtx {
-    fn as_ref(&self) -> &EVP_AEAD_CTX {
-        &self.0
-    }
-}
-
-pub fn init() {
-    // SAFETY: Configures the internal state of the library - may be called multiple times.
-    unsafe { CRYPTO_library_init() }
-}
diff --git a/pvmfw/src/entry.rs b/pvmfw/src/entry.rs
index 03f2f62..2475f32 100644
--- a/pvmfw/src/entry.rs
+++ b/pvmfw/src/entry.rs
@@ -15,9 +15,9 @@
 //! Low-level entry and exit points of pvmfw.
 
 use crate::config;
-use crate::crypto;
 use crate::fdt;
 use crate::memory;
+use bssl_ffi::CRYPTO_library_init;
 use core::arch::asm;
 use core::mem::{drop, size_of};
 use core::num::NonZeroUsize;
@@ -196,7 +196,12 @@
     // - only access non-pvmfw memory once (and while) it has been mapped
 
     log::set_max_level(LevelFilter::Info);
-    crypto::init();
+    // TODO(https://crbug.com/boringssl/35): Remove this init when BoringSSL can handle this
+    // internally.
+    // SAFETY: Configures the internal state of the library - may be called multiple times.
+    unsafe {
+        CRYPTO_library_init();
+    }
 
     let page_table = memory::init_page_table().map_err(|e| {
         error!("Failed to set up the dynamic page tables: {e}");
diff --git a/pvmfw/src/instance.rs b/pvmfw/src/instance.rs
index a998bfb..e98f663 100644
--- a/pvmfw/src/instance.rs
+++ b/pvmfw/src/instance.rs
@@ -14,13 +14,11 @@
 
 //! Support for reading and writing to the instance.img.
 
-use crate::crypto;
-use crate::crypto::AeadCtx;
 use crate::dice::PartialInputs;
 use crate::gpt;
 use crate::gpt::Partition;
 use crate::gpt::Partitions;
-use bssl_avf::{self, hkdf, Digester};
+use bssl_avf::{self, hkdf, Aead, AeadContext, Digester};
 use core::fmt;
 use core::mem::size_of;
 use diced_open_dice::DiceMode;
@@ -40,12 +38,8 @@
 pub enum Error {
     /// Unexpected I/O error while accessing the underlying disk.
     FailedIo(gpt::Error),
-    /// Failed to decrypt the entry.
-    FailedOpen(crypto::ErrorIterator),
     /// Failed to generate a random salt to be stored.
     FailedSaltGeneration(rand::Error),
-    /// Failed to encrypt the entry.
-    FailedSeal(crypto::ErrorIterator),
     /// Impossible to create a new instance.img entry.
     InstanceImageFull,
     /// Badly formatted instance.img header block.
@@ -72,21 +66,7 @@
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match self {
             Self::FailedIo(e) => write!(f, "Failed I/O to disk: {e}"),
-            Self::FailedOpen(e_iter) => {
-                writeln!(f, "Failed to open the instance.img partition:")?;
-                for e in *e_iter {
-                    writeln!(f, "\t{e}")?;
-                }
-                Ok(())
-            }
             Self::FailedSaltGeneration(e) => write!(f, "Failed to generate salt: {e}"),
-            Self::FailedSeal(e_iter) => {
-                writeln!(f, "Failed to seal the instance.img partition:")?;
-                for e in *e_iter {
-                    writeln!(f, "\t{e}")?;
-                }
-                Ok(())
-            }
             Self::InstanceImageFull => write!(f, "Failed to obtain a free instance.img partition"),
             Self::InvalidInstanceImageHeader => write!(f, "instance.img header is invalid"),
             Self::MissingInstanceImage => write!(f, "Failed to find the instance.img partition"),
@@ -124,6 +104,13 @@
     trace!("Found pvmfw instance.img entry: {entry:?}");
 
     let key = hkdf::<32>(secret, /* salt= */ &[], b"vm-instance", Digester::sha512())?;
+    let tag_len = None;
+    let aead_ctx = AeadContext::new(Aead::aes_256_gcm_randnonce(), key.as_slice(), tag_len)?;
+    let ad = &[];
+    // The nonce is generated internally for `aes_256_gcm_randnonce`, so no additional
+    // nonce is required.
+    let nonce = &[];
+
     let mut blk = [0; BLK_SIZE];
     match entry {
         PvmfwEntry::Existing { header_index, payload_size } => {
@@ -136,9 +123,7 @@
 
             let payload = &blk[..payload_size];
             let mut entry = [0; size_of::<EntryBody>()];
-            let aead =
-                AeadCtx::new_aes_256_gcm_randnonce(key.as_slice()).map_err(Error::FailedOpen)?;
-            let decrypted = aead.open(&mut entry, payload).map_err(Error::FailedOpen)?;
+            let decrypted = aead_ctx.open(payload, nonce, ad, &mut entry)?;
 
             let body = EntryBody::read_from(decrypted).unwrap();
             if dice_inputs.rkp_vm_marker {
@@ -166,12 +151,10 @@
             let salt = rand::random_array().map_err(Error::FailedSaltGeneration)?;
             let body = EntryBody::new(dice_inputs, &salt);
 
-            let aead =
-                AeadCtx::new_aes_256_gcm_randnonce(key.as_slice()).map_err(Error::FailedSeal)?;
             // We currently only support single-blk entries.
             let plaintext = body.as_bytes();
-            assert!(plaintext.len() + aead.aead().unwrap().max_overhead() < blk.len());
-            let encrypted = aead.seal(&mut blk, plaintext).map_err(Error::FailedSeal)?;
+            assert!(plaintext.len() + aead_ctx.aead().max_overhead() < blk.len());
+            let encrypted = aead_ctx.seal(plaintext, nonce, ad, &mut blk)?;
             let payload_size = encrypted.len();
             let payload_index = header_index + 1;
             instance_img.write_block(payload_index, &blk).map_err(Error::FailedIo)?;
diff --git a/pvmfw/src/main.rs b/pvmfw/src/main.rs
index 09bb899..f80bae1 100644
--- a/pvmfw/src/main.rs
+++ b/pvmfw/src/main.rs
@@ -22,7 +22,6 @@
 mod bcc;
 mod bootargs;
 mod config;
-mod crypto;
 mod device_assignment;
 mod dice;
 mod entry;