Revision control

Copy as Markdown

Other Tools

// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// Copyright by contributors to this project.
// SPDX-License-Identifier: (Apache-2.0 OR MIT)
/// Basic credential identity provider.
pub mod basic;
/// X.509 certificate identity provider.
#[cfg(feature = "x509")]
pub mod x509 {
pub use mls_rs_identity_x509::*;
}
pub use mls_rs_core::identity::{
Credential, CredentialType, CustomCredential, MlsCredential, SigningIdentity,
};
pub use mls_rs_core::group::RosterUpdate;
#[cfg(test)]
pub(crate) mod test_utils {
use alloc::boxed::Box;
use alloc::vec;
use alloc::vec::Vec;
use mls_rs_core::{
crypto::{CipherSuite, CipherSuiteProvider, SignatureSecretKey},
error::IntoAnyError,
extension::ExtensionList,
identity::{Credential, CredentialType, IdentityProvider, SigningIdentity},
time::MlsTime,
};
use crate::crypto::test_utils::test_cipher_suite_provider;
use super::basic::{BasicCredential, BasicIdentityProvider};
#[derive(Debug)]
#[cfg_attr(feature = "std", derive(thiserror::Error))]
#[cfg_attr(
feature = "std",
error("expected basic or custom credential type 42 found: {0:?}")
)]
pub struct BasicWithCustomProviderError(CredentialType);
impl IntoAnyError for BasicWithCustomProviderError {
#[cfg(feature = "std")]
fn into_dyn_error(self) -> Result<Box<dyn std::error::Error + Send + Sync>, Self> {
Ok(self.into())
}
}
#[derive(Debug, Clone)]
pub struct BasicWithCustomProvider {
pub(crate) basic: BasicIdentityProvider,
pub(crate) allow_any_custom: bool,
supported_cred_types: Vec<CredentialType>,
}
impl BasicWithCustomProvider {
pub const CUSTOM_CREDENTIAL_TYPE: u16 = 42;
pub fn new(basic: BasicIdentityProvider) -> BasicWithCustomProvider {
BasicWithCustomProvider {
basic,
allow_any_custom: false,
supported_cred_types: vec![
CredentialType::BASIC,
Self::CUSTOM_CREDENTIAL_TYPE.into(),
],
}
}
pub fn with_credential_type(mut self, cred_type: CredentialType) -> Self {
self.supported_cred_types.push(cred_type);
self
}
#[cfg_attr(not(mls_build_async), maybe_async::must_be_sync)]
async fn resolve_custom_identity(
&self,
signing_id: &SigningIdentity,
) -> Result<Vec<u8>, BasicWithCustomProviderError> {
self.basic
.identity(signing_id, &Default::default())
.await
.or_else(|_| {
signing_id
.credential
.as_custom()
.map(|c| {
if c.credential_type
== CredentialType::from(Self::CUSTOM_CREDENTIAL_TYPE)
|| self.allow_any_custom
{
Ok(c.data.to_vec())
} else {
Err(BasicWithCustomProviderError(c.credential_type))
}
})
.transpose()?
.ok_or_else(|| {
BasicWithCustomProviderError(signing_id.credential.credential_type())
})
})
}
}
impl Default for BasicWithCustomProvider {
fn default() -> Self {
Self::new(BasicIdentityProvider::new())
}
}
#[cfg_attr(not(mls_build_async), maybe_async::must_be_sync)]
#[cfg_attr(mls_build_async, maybe_async::must_be_async)]
impl IdentityProvider for BasicWithCustomProvider {
type Error = BasicWithCustomProviderError;
async fn validate_member(
&self,
_signing_identity: &SigningIdentity,
_timestamp: Option<MlsTime>,
_extensions: Option<&ExtensionList>,
) -> Result<(), Self::Error> {
//TODO: Is it actually beneficial to check the key, or does that already happen elsewhere before
//this point?
Ok(())
}
async fn validate_external_sender(
&self,
_signing_identity: &SigningIdentity,
_timestamp: Option<MlsTime>,
_extensions: Option<&ExtensionList>,
) -> Result<(), Self::Error> {
//TODO: Is it actually beneficial to check the key, or does that already happen elsewhere before
//this point?
Ok(())
}
async fn identity(
&self,
signing_id: &SigningIdentity,
_extensions: &ExtensionList,
) -> Result<Vec<u8>, Self::Error> {
self.resolve_custom_identity(signing_id).await
}
async fn valid_successor(
&self,
predecessor: &SigningIdentity,
successor: &SigningIdentity,
_extensions: &ExtensionList,
) -> Result<bool, Self::Error> {
let predecessor = self.resolve_custom_identity(predecessor).await?;
let successor = self.resolve_custom_identity(successor).await?;
Ok(predecessor == successor)
}
fn supported_types(&self) -> Vec<CredentialType> {
self.supported_cred_types.clone()
}
}
#[cfg_attr(not(mls_build_async), maybe_async::must_be_sync)]
pub async fn get_test_signing_identity(
cipher_suite: CipherSuite,
identity: &[u8],
) -> (SigningIdentity, SignatureSecretKey) {
let provider = test_cipher_suite_provider(cipher_suite);
let (secret_key, public_key) = provider.signature_key_generate().await.unwrap();
let basic = get_test_basic_credential(identity.to_vec());
(SigningIdentity::new(basic, public_key), secret_key)
}
pub fn get_test_basic_credential(identity: Vec<u8>) -> Credential {
BasicCredential::new(identity).into_credential()
}
}