// SPDX-License-Identifier: MIT // // Copyright IBM Corp. 2024 use enum_dispatch::enum_dispatch; use pv::request::openssl::pkey::{PKey, Public}; use pv::request::{decrypt_aead, encrypt_aead, Confidential, SymKey, SymKeyType}; use super::se_hdr::{SeHdrBinV1, SeHdrBinV2, SeHdrData, SeHdrVersioned}; use crate::pv_utils::error::{Error, Result}; use crate::pv_utils::serializing::deserialize_from_bytes; /// Trait to be used for Authenticated Encryption with Associated Data (AEAD) /// data structures. #[enum_dispatch] pub trait AeadCipherTrait { /// Returns the AEAD key type used by the data structure. fn aead_key_type(&self) -> SymKeyType; /// Returns the AEAD tag size used by the data structure. fn aead_tag_size(&self) -> usize; /// Returns the initialization vector (IV) used for AEAD /// encryption/decryption. fn iv(&self) -> &[u8]; } /// Trait to be used for AEAD cipher data #[enum_dispatch] pub trait AeadDataTrait { /// Returns the authenticated associated data. fn aad(&self) -> Result>; /// Returns the encrypted data. fn data(&self) -> Vec; /// Returns the tag data. fn tag(&self) -> Vec; } /// Trait to be used for AEAD plaintext data #[enum_dispatch] pub trait AeadPlainDataTrait { /// Returns the authenticated associated data. fn aad(&self) -> Result>; /// Returns the unencrypted data. fn data(&self) -> Result>>; /// Returns the tag data. fn tag(&self) -> Vec; } /// Key exchange related methods pub trait KeyExchangeTrait { type TargetKeyType; type PrivateKeyType: ToOwned; /// Checks if a public target key was used. /// /// # Errors /// /// This function will return an error if the public key cannot be converted /// into a hash. fn contains(&self, key: K) -> Result where K: AsRef; /// Checks if the hash of a public key was used. fn contains_hash>(&self, hash: H) -> bool; /// Returns the public key from the party (e.g. guest owner) that is stored /// in the data structed. /// /// # Errors /// /// This function will return an error if the public key cannot be /// reconstructed. fn cust_pub_key(&mut self) -> Result>; /// Returns the key type of the exchanged key. fn key_type(&self) -> SymKeyType; // TODO Implement it // /// Derive the key. // /// // /// # Errors // /// // /// This function will return an error if there is no customer public key is // /// available or the key derivations fails. // fn derive_key(&mut self, other_priv_key: K) -> Result where // K: AsRef{ // match self.key_type() { // SymKeyType::Aes256Gcm => // match Self::TargetKeyType { // PKeyRef:: => {todo!()}, // HybridPKey => {todo!()}, // } // _ => unreachable!("BUG"), // } // } } /// Trait to be used for plain UV data. #[enum_dispatch] pub trait UvDataPlainTrait: AeadPlainDataTrait + AeadCipherTrait + KeyExchangeTrait + Clone { /// Returned type by [`Self::encrypt`]. type C: UvDataTrait; /// Encrypt the plain data. /// /// # Errors /// /// This function will return an error if the passed `key` has the wrong /// key type or the encryption fails. fn encrypt(&self, key: &SymKey) -> Result where ::C: for<'a> deku::DekuContainerRead<'a>, { if key.key_type() != self.aead_key_type() { return Err(Error::UnexpectedKeyType { given: self.key_type().to_string(), expected: self.aead_key_type().to_string(), }); } let aad = self.aad().map_err(|err| match err { Error::Deku(_) => Error::InvalidSeHdr, err => err, })?; let unecrypted_data = self.data().map_err(|err| match err { Error::Deku(_) => Error::InvalidSeHdr, err => err, })?; let iv = self.iv(); let result = encrypt_aead(key, iv, &aad, unecrypted_data.value())?; Self::C::try_from_data(&result.into_buf()) } /// Parses and converts the data into an instance of [`Self`] if possible. /// /// # Errors /// /// This function will return an error if the data could not parsed or /// converted. fn try_from_data<'a>(data: &'a [u8]) -> Result where Self: deku::DekuContainerRead<'a> + Sized, { deserialize_from_bytes(data) } } /// Trait to be used for (cipher) UV data. #[enum_dispatch] pub trait UvDataTrait: AeadDataTrait + AeadCipherTrait + KeyExchangeTrait + Clone { /// Returned type by [`Self::decrypt`]. type P: UvDataPlainTrait; /// Decrypt the UV data. /// /// # Errors /// /// This function will return an error if the passed `key` has the wrong key /// type or the decryption fails. fn decrypt(&self, key: &SymKey) -> Result where ::P: for<'a> deku::DekuContainerRead<'a>, { if key.key_type() != self.aead_key_type() { return Err(Error::UnexpectedKeyType { given: key.key_type().to_string(), expected: self.aead_key_type().to_string(), }); } let tag_size = self.aead_tag_size(); let aad = self.aad()?; let unecrypted_data = self.data(); let iv = self.iv(); let tag = self.tag(); assert_eq!(tag.len(), tag_size); let result = decrypt_aead(key, iv, &aad, &unecrypted_data, &tag)?; Self::P::try_from_data(result.into_buf().value()) } /// Parses and converts the data into an instance of [`Self`] if possible. /// /// # Errors /// /// This function will return an error if the data could not parsed or /// converted. fn try_from_data<'a>(data: &'a [u8]) -> Result where Self: deku::DekuContainerRead<'a> + Sized, { deserialize_from_bytes(data) } }