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