Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
b32ff7c
chore: crypto: remove old x509 impl from TransactionContext
istankovic Apr 1, 2026
ac7df5d
chore: crypto: remove unused import
istankovic Apr 1, 2026
37c67bb
chore: crypto: silence clippy
istankovic Apr 1, 2026
827a6f1
chore: e2e-identity: move acme/identity to under acquisition
istankovic Apr 1, 2026
5c67131
chore: e2e-identity: move CertificateError to the acquisition module
istankovic Apr 1, 2026
c587fb0
chore: e2e-identity: adjust imports after the move
istankovic Apr 1, 2026
a52fd7f
chore: e2e-identity: add CertificateError::X509Check variant
istankovic Apr 1, 2026
0b9ea06
chore: e2e-identity: use correct error types
istankovic Apr 1, 2026
2926ec0
chore: e2e-identity: PKI environment is not optional when validating …
istankovic Apr 1, 2026
3f2639d
chore: e2e-identity: PKI environment is not optional when extracting …
istankovic Apr 1, 2026
9fa3e07
chore: e2e-identity: extend CertificateError with more variants
istankovic Apr 2, 2026
f939910
chore: e2e-identity: identity: use CertificateError instead of RustyA…
istankovic Apr 2, 2026
deb605c
chore: e2e-identity: thumbprint: use CertificateError instead of Rust…
istankovic Apr 2, 2026
9038231
chore: e2e-identity: extend X509CredentialConfiguration with a domain…
istankovic Apr 2, 2026
8a0f029
chore: e2e-identity: move certificate checks out of the acme module
istankovic Apr 1, 2026
f352eca
chore: e2e-identity: hook the new verification code into the acquisition
istankovic Apr 1, 2026
3344577
chore: keystore-dump: the old enrollment is going away
istankovic Apr 2, 2026
b1e5313
chore: e2e-identity: remove the old enrollment type
istankovic Apr 2, 2026
6e79a75
chore: e2e-identity: remove RustyE2eIdentity and related code
istankovic Apr 2, 2026
c83df46
chore: e2e-identity: expose WireIdentityReader
istankovic Apr 2, 2026
5fff9ba
chore: e2e-identity: expose compute_raw_key_thumbprint
istankovic Apr 2, 2026
cbb0cea
test: e2e-identity: make rand_client_id take a domain parameter
istankovic Apr 2, 2026
c3ee437
test: e2e-identity: specify the domain centrally
istankovic Apr 2, 2026
e044886
test: e2e-identity: add PKI environment to identity tests
istankovic Apr 2, 2026
76bcb3e
test: e2e-identity: we can't get a valid status because we don't have…
istankovic Apr 2, 2026
8c2b787
chore: crypto: add MissingPKIEnvironment variant to the credential er…
istankovic Apr 7, 2026
58b8780
chore: crypto: provide PKI environment to extract_identity
istankovic Apr 7, 2026
5ca78c7
chore: crypto: remove get_new_crl_distribution_points
istankovic Apr 8, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 1 addition & 4 deletions crypto/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,7 @@ pub use openmls::{
group_info::VerifiableGroupInfo,
},
};
use wire_e2e_identity::{
legacy::{E2eiEnrollment, device_status::DeviceStatus},
pki_env::PkiEnvironment,
};
use wire_e2e_identity::{legacy::device_status::DeviceStatus, pki_env::PkiEnvironment};

pub use crate::{
build_metadata::{BUILD_METADATA, BuildMetadata},
Expand Down
4 changes: 3 additions & 1 deletion crypto/src/mls/conversation/own_commit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use core_crypto_keystore::Database;
use openmls::prelude::{
ConfirmationTag, ContentType, CredentialWithKey, FramedContentBodyIn, MlsMessageIn, MlsMessageInBody, Sender,
};
use openmls_traits::OpenMlsCryptoProvider as _;

use super::{Error, Result};
use crate::{
Expand Down Expand Up @@ -98,8 +99,9 @@ impl MlsConversation {
credential: own_leaf.credential().clone(),
signature_key: own_leaf.signature_key().clone(),
};
let provider = client.crypto_provider.authentication_service();
let identity = own_leaf_credential_with_key
.extract_identity(self.ciphersuite(), None)
.extract_identity(self.ciphersuite(), provider.borrow().await.as_ref())
.map_err(RecursiveError::mls_credential("extracting identity"))?;

Ok(MlsConversationDecryptMessage {
Expand Down
19 changes: 16 additions & 3 deletions crypto/src/mls/conversation/pending_conversation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,9 +184,22 @@ impl PendingConversation {
credential: own_leaf.credential().clone(),
signature_key: own_leaf.signature_key().clone(),
};
let identity = own_leaf_credential_with_key
.extract_identity(conversation.ciphersuite(), None)
.map_err(RecursiveError::mls_credential("extracting identity"))?;
let pki_env = self
.context
.pki_environment_option()
.await
.map_err(RecursiveError::transaction("getting PKI environment"))?;
let identity = match pki_env {
Some(pki_env) => {
let provider = pki_env.mls_pki_env_provider();
own_leaf_credential_with_key
.extract_identity(conversation.ciphersuite(), provider.borrow().await.as_ref())
.map_err(RecursiveError::mls_credential("extracting identity"))?
}
None => own_leaf_credential_with_key
.extract_identity(conversation.ciphersuite(), None)
.map_err(RecursiveError::mls_credential("extracting identity"))?,
};

Ok(MlsConversationDecryptMessage {
app_msg: None,
Expand Down
23 changes: 2 additions & 21 deletions crypto/src/mls/credential/crl.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
use std::collections::HashSet;

use core_crypto_keystore::{entities::E2eiCrl, traits::FetchFromDatabase};
use openmls::{
group::MlsGroup,
prelude::{Certificate, MlsCredentialType},
};
use wire_e2e_identity::{NewCrlDistributionPoints, x509_check::extract_crl_uris};
use wire_e2e_identity::x509_check::extract_crl_uris;

use super::{Error, Result};
use crate::{KeystoreError, RecursiveError};
use crate::RecursiveError;

#[derive(
Debug,
Expand Down Expand Up @@ -52,24 +51,6 @@ pub(crate) fn extract_dp(cert: &Certificate) -> Result<CrlUris> {
})
}

pub(crate) async fn get_new_crl_distribution_points(
database: &impl FetchFromDatabase,
mut crl_dps: HashSet<String>,
) -> Result<NewCrlDistributionPoints> {
if crl_dps.is_empty() {
return Ok(None.into());
}

let stored_crls = database
.load_all::<E2eiCrl>()
.await
.map_err(KeystoreError::wrap("finding all e2e crl"))?;
let stored_crl_dps: HashSet<&str> = stored_crls.iter().map(|crl| crl.distribution_point.as_str()).collect();
crl_dps.retain(|dp| !stored_crl_dps.contains(&dp.as_str()));

Ok(Some(crl_dps).into())
}

impl CrlUris {
fn new() -> Self {
HashSet::new().into()
Expand Down
2 changes: 2 additions & 0 deletions crypto/src/mls/credential/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ pub enum Error {
InvalidIdentity,
#[error("No credential for the given public key ({0:?}) was found in this database")]
CredentialNotFound(SignaturePublicKey),
#[error("missing PKI environment")]
MissingPKIEnvironment,
/// Unsupported credential type.
///
/// Supported credential types:
Expand Down
1 change: 1 addition & 0 deletions crypto/src/mls/credential/ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ impl CredentialExt for openmls::prelude::Certificate {
cs: Ciphersuite,
env: Option<&wire_e2e_identity::x509_check::revocation::PkiEnvironment>,
) -> Result<WireIdentity> {
let env = env.ok_or_else(|| Error::MissingPKIEnvironment)?;
let leaf = self.certificates.first().ok_or(Error::InvalidIdentity)?;
let leaf = leaf.as_slice();
use wire_e2e_identity::WireIdentityReader as _;
Expand Down
8 changes: 6 additions & 2 deletions crypto/src/mls/credential/x509.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,11 @@ impl fmt::Debug for CertificateBundle {

impl CertificateBundle {
/// Reads the client_id from the leaf certificate
pub fn get_client_id(&self) -> Result<ClientId> {
pub fn get_client_id(
&self,
env: Option<&wire_e2e_identity::x509_check::revocation::PkiEnvironment>,
) -> Result<ClientId> {
let env = env.ok_or_else(|| Error::MissingPKIEnvironment)?;
let leaf = self.certificate_chain.first().ok_or(Error::InvalidIdentity)?;

let hash_alg = match self.signature_scheme {
Expand All @@ -79,7 +83,7 @@ impl CertificateBundle {
};

let identity = leaf
.extract_identity(None, hash_alg)
.extract_identity(env, hash_alg)
.map_err(|_| Error::InvalidIdentity)?;

use wire_e2e_identity::legacy::id as legacy_id;
Expand Down
3 changes: 2 additions & 1 deletion crypto/src/mls/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,9 @@ mod tests {
CertificateBundle::rand_identifier(&session_id, &[x509_test_chain.find_local_intermediate_ca()])
}
};
let provider = cc.get_pki_environment().await.unwrap().mls_pki_env_provider();
let session_id = identifier
.get_id()
.get_id(provider.borrow().await.as_ref())
.expect("get session_id from identifier")
.into_owned();
context
Expand Down
10 changes: 6 additions & 4 deletions crypto/src/mls/session/e2e_identity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,11 @@ impl<D> Session<D> {
_credential_type: CredentialType,
env: Option<&wire_e2e_identity::x509_check::revocation::PkiEnvironment>,
) -> E2eiConversationState {
let env = match env {
Some(e) => e,
None => return E2eiConversationState::NotEnabled,
};

let mut is_e2ei = false;
let mut state = E2eiConversationState::Verified;

Expand All @@ -138,10 +143,7 @@ impl<D> Session<D> {
use openmls_x509_credential::X509Ext as _;
let is_time_valid = cert.is_time_valid().unwrap_or(false);
let is_time_invalid = !is_time_valid;
let is_revoked_or_invalid = env
.map(|e| e.validate_cert_and_revocation(&cert).is_err())
.unwrap_or(false);

let is_revoked_or_invalid = env.validate_cert_and_revocation(&cert).is_err();
let is_invalid = invalid_identity || is_time_invalid || is_revoked_or_invalid;
if is_invalid {
state = E2eiConversationState::NotVerified;
Expand Down
7 changes: 5 additions & 2 deletions crypto/src/mls/session/identifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@ pub enum ClientIdentifier {
impl ClientIdentifier {
/// Extract the unique [ClientId] from an identifier. Use with parsimony as, in case of a x509
/// certificate this leads to parsing the certificate
pub fn get_id(&self) -> Result<std::borrow::Cow<'_, ClientIdRef>> {
pub fn get_id(
&self,
env: Option<&wire_e2e_identity::x509_check::revocation::PkiEnvironment>,
) -> Result<std::borrow::Cow<'_, ClientIdRef>> {
match self {
ClientIdentifier::Basic(id) => Ok(std::borrow::Cow::Borrowed(id)),
ClientIdentifier::X509(certs) => {
Expand All @@ -28,7 +31,7 @@ impl ClientIdentifier {
// that's not a getter's job
let cert = certs.values().next().ok_or(Error::NoX509CertificateBundle)?;
let id = cert
.get_client_id()
.get_client_id(env)
.map_err(RecursiveError::mls_credential("getting client id"))?;
Ok(std::borrow::Cow::Owned(id))
}
Expand Down
3 changes: 3 additions & 0 deletions crypto/src/mls_provider/crypto_provider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ impl RustCrypto {
Ok(())
}

// TODO: remove this expect(unused) once we start using it again or we drop
// it completely (see WPB-23594)
#[expect(unused)]
pub(crate) fn normalize_p521_secret_key(sk: &[u8]) -> zeroize::Zeroizing<[u8; 66]> {
normalize_p521_secret_key(sk)
}
Expand Down
3 changes: 2 additions & 1 deletion crypto/src/proteus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -645,8 +645,9 @@ mod tests {
CertificateBundle::rand_identifier(&session_id, &[x509_test_chain.find_local_intermediate_ca()])
}
};
let provider = cc.get_pki_environment().await.unwrap().mls_pki_env_provider();
let session_id = identifier
.get_id()
.get_id(provider.borrow().await.as_ref())
.expect("Getting session id from identifier")
.into_owned();
transaction.mls_init(session_id, transport).await.unwrap();
Expand Down
13 changes: 10 additions & 3 deletions crypto/src/test_utils/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,15 +230,22 @@ impl SessionContext {
if let openmls::prelude::MlsCredentialType::X509(certificate) =
&expected_credential.mls_credential().mls_credential()
{
let mls_identity = certificate.extract_identity(case.ciphersuite(), None).unwrap();
let session = self.session().await;
let provider = session.crypto_provider;
let guard = provider.authentication_service().borrow().await;
let env = match guard.as_ref() {
Some(env) => env,
None => unreachable!("PKI environment must be set"),
};
let mls_identity = certificate.extract_identity(case.ciphersuite(), Some(env)).unwrap();
let mls_client_id = mls_identity.client_id.as_bytes();

let decrypted_identity = &decrypted.identity;

let leaf: Vec<u8> = certificate.certificates.first().unwrap().clone().into();
let identity = leaf
.as_slice()
.extract_identity(None, case.ciphersuite().e2ei_hash_alg())
.extract_identity(env, case.ciphersuite().e2ei_hash_alg())
.unwrap();
let identity = WireIdentity::try_from((identity, leaf.as_slice())).unwrap();

Expand All @@ -263,7 +270,7 @@ impl SessionContext {
);
let chain = x509_cert::Certificate::load_pem_chain(decrypted_x509_identity.certificate.as_bytes()).unwrap();
let leaf = chain.first().unwrap();
let cert_identity = leaf.extract_identity(None, case.ciphersuite().e2ei_hash_alg()).unwrap();
let cert_identity = leaf.extract_identity(env, case.ciphersuite().e2ei_hash_alg()).unwrap();

let cert_identity = WireIdentity::try_from((cert_identity, leaf.to_der().unwrap().as_slice())).unwrap();
assert_eq!(cert_identity.client_id, identity.client_id);
Expand Down
36 changes: 25 additions & 11 deletions crypto/src/test_utils/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use std::{collections::HashMap, sync::Arc};

use async_lock::RwLock;
use openmls::framing::MlsMessageOut;
use openmls_traits::OpenMlsCryptoProvider as _;
pub use openmls_traits::types::SignatureScheme;
use wire_e2e_identity::pki_env::PkiEnvironment;

Expand Down Expand Up @@ -118,18 +119,8 @@ impl SessionContext {
.unwrap();

let core_crypto = CoreCrypto::new(db.clone());

let transaction = core_crypto.new_transaction().await.unwrap();

let session_id = identifier
.get_id()
.map_err(RecursiveError::mls_client("getting client id"))?
.into_owned();
transaction
.mls_init(session_id, context.transport.clone())
.await
.map_err(RecursiveError::transaction("mls init"))?;

// Setup the X509 PKI environment
if let Some(chain) = chain.as_ref() {
let dummy_hooks = Arc::new(DummyPkiEnvironmentHooks);
Expand All @@ -143,6 +134,25 @@ impl SessionContext {
chain.register_with_central(&transaction).await;
}

let pki_env = core_crypto.get_pki_environment().await;
let session_id = match pki_env {
Some(pki_env) => {
let provider = pki_env.mls_pki_env_provider();
identifier
.get_id(provider.borrow().await.as_ref())
.map_err(RecursiveError::mls_client("getting client id"))?
.into_owned()
}
None => identifier
.get_id(None)
.map_err(RecursiveError::mls_client("getting client id"))?
.into_owned(),
};
transaction
.mls_init(session_id, context.transport.clone())
.await
.map_err(RecursiveError::transaction("mls init"))?;

let session = transaction.session().await.unwrap();

let credential = Credential::from_identifier(&identifier, context.ciphersuite())
Expand Down Expand Up @@ -306,7 +316,11 @@ impl SessionContext {
CredentialType::X509 => {
let signer = signer.expect("Missing intermediate CA");
let cert = CertificateBundle::rand(&session_id, signer);
let session_id = cert.get_client_id().expect("Getting client id from certificate bundle");
let session = self.session.read().await;
let guard = session.crypto_provider.authentication_service().borrow().await;
let session_id = cert
.get_client_id(guard.as_ref())
.expect("Getting client id from certificate bundle");

let credential = Credential::x509(case.ciphersuite(), cert).expect("creating x509 credential");

Expand Down
11 changes: 9 additions & 2 deletions crypto/src/test_utils/test_conversation/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::sync::Arc;

use openmls::{group::QueuedProposal, prelude::group_info::VerifiableGroupInfo};
use openmls_traits::OpenMlsCryptoProvider as _;

use super::{CredentialType, MessageExt as _, MlsTransportTestExt, SessionContext, TestContext, TestError};
use crate::{
Expand Down Expand Up @@ -385,7 +386,11 @@ impl<'a> TestConversation<'a> {
let credential = credential_ref.load(&database).await.unwrap();
let mls_credential_with_key = credential.to_mls_credential_with_key();
let ciphersuite = self.case.ciphersuite();
let local_identity = mls_credential_with_key.extract_identity(ciphersuite, None).unwrap();
let session = self.actor().session().await;
let provider = session.crypto_provider.authentication_service();
let local_identity = mls_credential_with_key
.extract_identity(ciphersuite, provider.borrow().await.as_ref())
.unwrap();

assert_eq!(&local_identity.client_id.as_bytes(), &cid.0);
assert_eq!(
Expand All @@ -404,7 +409,9 @@ impl<'a> TestConversation<'a> {
};

assert_eq!(credential.credential.identity(), &cid.0);
let keystore_identity = credential.extract_identity(ciphersuite, None).unwrap();
let keystore_identity = credential
.extract_identity(ciphersuite, provider.borrow().await.as_ref())
.unwrap();
assert_eq!(
keystore_identity.x509_identity.as_ref().unwrap().display_name,
new_display_name
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,11 +82,6 @@ impl TransactionContext {
self.e2ei_register_intermediate_ca(inter_ca).await
}

pub(crate) async fn e2ei_register_intermediate_ca_der(&self, cert_der: &[u8]) -> Result<NewCrlDistributionPoints> {
let inter_ca = x509_cert::Certificate::from_der(cert_der)?;
self.e2ei_register_intermediate_ca(inter_ca).await
}

async fn e2ei_register_intermediate_ca(
&self,
inter_ca: x509_cert::Certificate,
Expand Down
Loading
Loading