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