Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
beltram committed Dec 22, 2023
1 parent 98f2fda commit 3af88cb
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 31 deletions.
1 change: 0 additions & 1 deletion openmls/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ x509-cert = "0.2"
subtle = "2.5"
fluvio-wasm-timer = "0.2"
indexmap = "2.0"
itertools = "0.11"

# Only required for tests.
rand = { version = "0.8", optional = true, features = ["getrandom"] }
Expand Down
5 changes: 4 additions & 1 deletion openmls/src/credentials/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::error::LibraryError;
use thiserror::Error;

/// An error that occurs in methods of a [`super::Credential`].
#[derive(Error, Debug, PartialEq, Clone)]
#[derive(Error, Debug, Eq, PartialEq, Clone)]
pub enum CredentialError {
/// A library error occurred.
#[error(transparent)]
Expand All @@ -26,4 +26,7 @@ pub enum CredentialError {
/// x509 certificate chain is either unordered or a child is missigned by its issuer
#[error("Invalid x509 certificate chain.")]
InvalidCertificateChain,
/// one of x509 certificate chain member is expired
#[error("Expired x509 certificate chain.")]
ExpiredCertificate,
}
20 changes: 20 additions & 0 deletions openmls/src/credentials/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ mod codec;
#[cfg(test)]
mod tests;
use errors::*;
use openmls_traits::types::CryptoError;
use openmls_x509_credential::X509Ext;
use x509_cert::{der::Decode, PkiPath};

Expand Down Expand Up @@ -273,6 +274,25 @@ impl Credential {
MlsCredentialType::X509(cert) => cert.identity.as_slice(),
}
}

pub fn verify(&self) -> Result<(), CredentialError> {
match &self.credential {
MlsCredentialType::X509(cert) => {
// TODO: implement this on the whole chain with certval
let ee_cert = cert
.certificates
.first()
.ok_or(CredentialError::InvalidCertificateChain)?;
let ee_cert = x509_cert::Certificate::from_der(ee_cert.as_slice())?;
ee_cert.is_valid().map_err(|e| match e {
CryptoError::ExpiredCertificate => CredentialError::ExpiredCertificate,
_ => CredentialError::InvalidCertificateChain,
})?;
}
MlsCredentialType::Basic(_) => {}
}
Ok(())
}
}

impl From<MlsCredentialType> for Credential {
Expand Down
4 changes: 4 additions & 0 deletions openmls/src/treesync/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use thiserror::Error;

use super::*;
use crate::prelude::CredentialError;
use crate::{
binary_tree::MlsBinaryTreeDiffError, ciphersuite::signable::SignatureError,
error::LibraryError, extensions::errors::ExtensionError,
Expand Down Expand Up @@ -271,6 +272,9 @@ pub enum LeafNodeValidationError {
/// See [`SignatureError`] for more details.
#[error(transparent)]
SignatureError(#[from] SignatureError),
/// See [`CredentialError`] for more details.
#[error(transparent)]
CredentialError(#[from] CredentialError),
}

/// Errors that can happen during lifetime validation.
Expand Down
70 changes: 41 additions & 29 deletions openmls/src/treesync/node/validate.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::prelude::Credential;
use crate::{
prelude::{
Capabilities, CredentialType, ExtensionType, Extensions, SignaturePublicKey, Verifiable,
Expand All @@ -12,8 +13,8 @@ use crate::{
},
},
};
use itertools::Itertools;
use openmls_traits::{crypto::OpenMlsCrypto, types::SignatureScheme};
use std::collections::HashSet;

impl ValidatableLeafNode for VerifiableCommitLeafNode {
fn signature_key(&self) -> &SignaturePublicKey {
Expand All @@ -28,6 +29,10 @@ impl ValidatableLeafNode for VerifiableCommitLeafNode {
&self.payload.credential.credential_type
}

fn credential(&self) -> &Credential {
&self.payload.credential
}

fn extensions(&self) -> &Extensions {
&self.payload.extensions
}
Expand Down Expand Up @@ -55,6 +60,10 @@ impl ValidatableLeafNode for VerifiableUpdateLeafNode {
&self.payload.credential.credential_type
}

fn credential(&self) -> &Credential {
&self.payload.credential
}

fn extensions(&self) -> &Extensions {
&self.payload.extensions
}
Expand Down Expand Up @@ -108,6 +117,10 @@ impl ValidatableLeafNode for VerifiableKeyPackageLeafNode {
&self.payload.credential.credential_type
}

fn credential(&self) -> &Credential {
&self.payload.credential
}

fn extensions(&self) -> &Extensions {
&self.payload.extensions
}
Expand Down Expand Up @@ -137,17 +150,6 @@ where
self._generic_standalone_validate(crypto, signature_scheme)
}

fn _generic_standalone_validate(
self,
crypto: &impl OpenMlsCrypto,
signature_scheme: SignatureScheme,
) -> Result<LeafNode, LeafNodeValidationError> {
let extension_types = self.extension_types();
let leaf_node = self.verify_signature(crypto, signature_scheme)?;
Self::validate_extension_support(&leaf_node, &extension_types[..])?;
Ok(leaf_node)
}

/// Validate a LeafNode as per https://www.rfc-editor.org/rfc/rfc9420.html#name-leaf-node-validation
fn validate(
self,
Expand All @@ -166,11 +168,18 @@ where
self.validate_capabilities(group)?;
self.validate_credential_type(group)?;
let tree = group.treesync();
self.validate_signature_key_unique(tree)?;
self.validate_encryption_key_unique(tree)?;
self.validate_signature_encryption_key_unique(tree)?;

let extension_types = self.extension_types();
let signature_scheme = group.ciphersuite().signature_algorithm();
self._generic_standalone_validate(crypto, signature_scheme)
}

fn _generic_standalone_validate(
self,
crypto: &impl OpenMlsCrypto,
signature_scheme: SignatureScheme,
) -> Result<LeafNode, LeafNodeValidationError> {
let extension_types = self.extension_types();
let leaf_node = self.verify_signature(crypto, signature_scheme)?;
Self::validate_extension_support(&leaf_node, &extension_types[..])?;
Ok(leaf_node)
Expand All @@ -179,6 +188,7 @@ where
fn signature_key(&self) -> &SignaturePublicKey;
fn capabilities(&self) -> &Capabilities;
fn credential_type(&self) -> &CredentialType;
fn credential(&self) -> &Credential;
fn extensions(&self) -> &Extensions;

fn extension_types(&self) -> Vec<ExtensionType> {
Expand Down Expand Up @@ -219,24 +229,21 @@ where
}

/// Verify that the following fields are unique among the members of the group: signature_key
fn validate_signature_key_unique(
fn validate_signature_encryption_key_unique(
&self,
tree: &TreeSync,
) -> Result<(), LeafNodeValidationError> {
if !tree.raw_leaves().map(LeafNode::signature_key).all_unique() {
return Err(LeafNodeValidationError::SignatureKeyAlreadyInUse);
}
Ok(())
}
/// Verify that the following fields are unique among the members of the group: encryption_key
fn validate_encryption_key_unique(
&self,
tree: &TreeSync,
) -> Result<(), LeafNodeValidationError> {
if !tree.raw_leaves().map(LeafNode::encryption_key).all_unique() {
return Err(LeafNodeValidationError::EncryptionKeyAlreadyInUse);
let size = tree.tree_size().leaf_count() as usize;
let mut used_signature_keys = HashSet::with_capacity(size);
let mut used_encryption_keys = HashSet::with_capacity(size);
for ln in tree.raw_leaves() {
if !used_signature_keys.insert(ln.signature_key()) {
return Err(LeafNodeValidationError::SignatureKeyAlreadyInUse);
}
if !used_encryption_keys.insert(ln.encryption_key()) {
return Err(LeafNodeValidationError::EncryptionKeyAlreadyInUse);
}
}

Ok(())
}

Expand All @@ -261,4 +268,9 @@ where
.into_signature_public_key_enriched(signature_scheme);
Ok(self.verify::<LeafNode>(crypto, &pk)?)
}

/// Verify that the credential in the LeafNode is valid, as described in Section 5.3.1
fn verify_credential(&self) -> Result<(), LeafNodeValidationError> {
Ok(self.credential().verify()?)
}
}

0 comments on commit 3af88cb

Please sign in to comment.