1 // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 // Copyright by contributors to this project. 3 // SPDX-License-Identifier: (Apache-2.0 OR MIT) 4 5 /// Basic credential identity provider. 6 pub mod basic; 7 8 /// X.509 certificate identity provider. 9 #[cfg(feature = "x509")] 10 pub mod x509 { 11 pub use mls_rs_identity_x509::*; 12 } 13 14 pub use mls_rs_core::identity::{ 15 Credential, CredentialType, CustomCredential, MlsCredential, SigningIdentity, 16 }; 17 18 pub use mls_rs_core::group::RosterUpdate; 19 20 #[cfg(test)] 21 pub(crate) mod test_utils { 22 use alloc::boxed::Box; 23 use alloc::vec; 24 use alloc::vec::Vec; 25 use mls_rs_core::{ 26 crypto::{CipherSuite, CipherSuiteProvider, SignatureSecretKey}, 27 error::IntoAnyError, 28 extension::ExtensionList, 29 identity::{Credential, CredentialType, IdentityProvider, SigningIdentity}, 30 time::MlsTime, 31 }; 32 33 use crate::crypto::test_utils::test_cipher_suite_provider; 34 35 use super::basic::{BasicCredential, BasicIdentityProvider}; 36 37 #[derive(Debug)] 38 #[cfg_attr(feature = "std", derive(thiserror::Error))] 39 #[cfg_attr( 40 feature = "std", 41 error("expected basic or custom credential type 42 found: {0:?}") 42 )] 43 pub struct BasicWithCustomProviderError(CredentialType); 44 45 impl IntoAnyError for BasicWithCustomProviderError { 46 #[cfg(feature = "std")] into_dyn_error(self) -> Result<Box<dyn std::error::Error + Send + Sync>, Self>47 fn into_dyn_error(self) -> Result<Box<dyn std::error::Error + Send + Sync>, Self> { 48 Ok(self.into()) 49 } 50 } 51 52 #[derive(Debug, Clone)] 53 pub struct BasicWithCustomProvider { 54 pub(crate) basic: BasicIdentityProvider, 55 pub(crate) allow_any_custom: bool, 56 supported_cred_types: Vec<CredentialType>, 57 } 58 59 impl BasicWithCustomProvider { 60 pub const CUSTOM_CREDENTIAL_TYPE: u16 = 42; 61 new(basic: BasicIdentityProvider) -> BasicWithCustomProvider62 pub fn new(basic: BasicIdentityProvider) -> BasicWithCustomProvider { 63 BasicWithCustomProvider { 64 basic, 65 allow_any_custom: false, 66 supported_cred_types: vec![ 67 CredentialType::BASIC, 68 Self::CUSTOM_CREDENTIAL_TYPE.into(), 69 ], 70 } 71 } 72 with_credential_type(mut self, cred_type: CredentialType) -> Self73 pub fn with_credential_type(mut self, cred_type: CredentialType) -> Self { 74 self.supported_cred_types.push(cred_type); 75 self 76 } 77 78 #[cfg_attr(not(mls_build_async), maybe_async::must_be_sync)] resolve_custom_identity( &self, signing_id: &SigningIdentity, ) -> Result<Vec<u8>, BasicWithCustomProviderError>79 async fn resolve_custom_identity( 80 &self, 81 signing_id: &SigningIdentity, 82 ) -> Result<Vec<u8>, BasicWithCustomProviderError> { 83 self.basic 84 .identity(signing_id, &Default::default()) 85 .await 86 .or_else(|_| { 87 signing_id 88 .credential 89 .as_custom() 90 .map(|c| { 91 if c.credential_type 92 == CredentialType::from(Self::CUSTOM_CREDENTIAL_TYPE) 93 || self.allow_any_custom 94 { 95 Ok(c.data.to_vec()) 96 } else { 97 Err(BasicWithCustomProviderError(c.credential_type)) 98 } 99 }) 100 .transpose()? 101 .ok_or_else(|| { 102 BasicWithCustomProviderError(signing_id.credential.credential_type()) 103 }) 104 }) 105 } 106 } 107 108 impl Default for BasicWithCustomProvider { default() -> Self109 fn default() -> Self { 110 Self::new(BasicIdentityProvider::new()) 111 } 112 } 113 114 #[cfg_attr(not(mls_build_async), maybe_async::must_be_sync)] 115 #[cfg_attr(mls_build_async, maybe_async::must_be_async)] 116 impl IdentityProvider for BasicWithCustomProvider { 117 type Error = BasicWithCustomProviderError; 118 validate_member( &self, _signing_identity: &SigningIdentity, _timestamp: Option<MlsTime>, _extensions: Option<&ExtensionList>, ) -> Result<(), Self::Error>119 async fn validate_member( 120 &self, 121 _signing_identity: &SigningIdentity, 122 _timestamp: Option<MlsTime>, 123 _extensions: Option<&ExtensionList>, 124 ) -> Result<(), Self::Error> { 125 //TODO: Is it actually beneficial to check the key, or does that already happen elsewhere before 126 //this point? 127 Ok(()) 128 } 129 validate_external_sender( &self, _signing_identity: &SigningIdentity, _timestamp: Option<MlsTime>, _extensions: Option<&ExtensionList>, ) -> Result<(), Self::Error>130 async fn validate_external_sender( 131 &self, 132 _signing_identity: &SigningIdentity, 133 _timestamp: Option<MlsTime>, 134 _extensions: Option<&ExtensionList>, 135 ) -> Result<(), Self::Error> { 136 //TODO: Is it actually beneficial to check the key, or does that already happen elsewhere before 137 //this point? 138 Ok(()) 139 } 140 identity( &self, signing_id: &SigningIdentity, _extensions: &ExtensionList, ) -> Result<Vec<u8>, Self::Error>141 async fn identity( 142 &self, 143 signing_id: &SigningIdentity, 144 _extensions: &ExtensionList, 145 ) -> Result<Vec<u8>, Self::Error> { 146 self.resolve_custom_identity(signing_id).await 147 } 148 valid_successor( &self, predecessor: &SigningIdentity, successor: &SigningIdentity, _extensions: &ExtensionList, ) -> Result<bool, Self::Error>149 async fn valid_successor( 150 &self, 151 predecessor: &SigningIdentity, 152 successor: &SigningIdentity, 153 _extensions: &ExtensionList, 154 ) -> Result<bool, Self::Error> { 155 let predecessor = self.resolve_custom_identity(predecessor).await?; 156 let successor = self.resolve_custom_identity(successor).await?; 157 158 Ok(predecessor == successor) 159 } 160 supported_types(&self) -> Vec<CredentialType>161 fn supported_types(&self) -> Vec<CredentialType> { 162 self.supported_cred_types.clone() 163 } 164 } 165 166 #[cfg_attr(not(mls_build_async), maybe_async::must_be_sync)] get_test_signing_identity( cipher_suite: CipherSuite, identity: &[u8], ) -> (SigningIdentity, SignatureSecretKey)167 pub async fn get_test_signing_identity( 168 cipher_suite: CipherSuite, 169 identity: &[u8], 170 ) -> (SigningIdentity, SignatureSecretKey) { 171 let provider = test_cipher_suite_provider(cipher_suite); 172 let (secret_key, public_key) = provider.signature_key_generate().await.unwrap(); 173 174 let basic = get_test_basic_credential(identity.to_vec()); 175 176 (SigningIdentity::new(basic, public_key), secret_key) 177 } 178 get_test_basic_credential(identity: Vec<u8>) -> Credential179 pub fn get_test_basic_credential(identity: Vec<u8>) -> Credential { 180 BasicCredential::new(identity).into_credential() 181 } 182 } 183