// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // Copyright by contributors to this project. // SPDX-License-Identifier: (Apache-2.0 OR MIT) use mls_rs_core::{ crypto::{CipherSuite, HpkePublicKey, HpkeSecretKey}, error::IntoAnyError, }; use alloc::vec::Vec; #[cfg(feature = "mock")] use mockall::automock; /// A trait that provides the required KEM functions #[cfg_attr(not(mls_build_async), maybe_async::must_be_sync)] #[cfg_attr(all(target_arch = "wasm32", mls_build_async), maybe_async::must_be_async(?Send))] #[cfg_attr( all(not(target_arch = "wasm32"), mls_build_async), maybe_async::must_be_async )] #[cfg_attr(feature = "mock", automock(type Error = crate::mock::TestError;))] pub trait KemType: Send + Sync { type Error: IntoAnyError + Send + Sync; /// KEM Id, as specified in RFC 9180, Section 5.1 and Table 2. fn kem_id(&self) -> u16; async fn derive(&self, ikm: &[u8]) -> Result<(HpkeSecretKey, HpkePublicKey), Self::Error>; async fn generate(&self) -> Result<(HpkeSecretKey, HpkePublicKey), Self::Error>; fn public_key_validate(&self, key: &HpkePublicKey) -> Result<(), Self::Error>; async fn encap(&self, remote_key: &HpkePublicKey) -> Result; async fn decap( &self, enc: &[u8], secret_key: &HpkeSecretKey, local_public: &HpkePublicKey, ) -> Result, Self::Error>; } /// Struct to represent the output of the kem [encap](KemType::encap) function pub struct KemResult { pub shared_secret: Vec, pub enc: Vec, } impl KemResult { pub fn new(shared_secret: Vec, enc: Vec) -> Self { Self { shared_secret, enc } } pub fn shared_secret(&self) -> &[u8] { &self.shared_secret } /// Returns the ciphertext encapsulating the shared secret. pub fn enc(&self) -> &[u8] { &self.enc } } /// Kem identifiers for HPKE #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] #[repr(u16)] #[non_exhaustive] pub enum KemId { DhKemP256Sha256 = 0x0010, DhKemP384Sha384 = 0x0011, DhKemP521Sha512 = 0x0012, DhKemX25519Sha256 = 0x0020, DhKemX448Sha512 = 0x0021, } impl KemId { pub fn new(cipher_suite: CipherSuite) -> Option { match cipher_suite { CipherSuite::CURVE25519_AES128 | CipherSuite::CURVE25519_CHACHA => { Some(KemId::DhKemX25519Sha256) } CipherSuite::P256_AES128 => Some(KemId::DhKemP256Sha256), CipherSuite::CURVE448_AES256 | CipherSuite::CURVE448_CHACHA => { Some(KemId::DhKemX448Sha512) } CipherSuite::P384_AES256 => Some(KemId::DhKemP384Sha384), CipherSuite::P521_AES256 => Some(KemId::DhKemP521Sha512), _ => None, } } pub fn n_secret(&self) -> usize { match self { KemId::DhKemP256Sha256 => 32, KemId::DhKemP384Sha384 => 48, KemId::DhKemP521Sha512 => 64, KemId::DhKemX25519Sha256 => 32, KemId::DhKemX448Sha512 => 64, } } }