Skip to content

Commit

Permalink
feat: remove any transitive crate using ring. As a consequence suppor…
Browse files Browse the repository at this point in the history
…ts EcDSA on WASM
  • Loading branch information
beltram committed Mar 28, 2023
1 parent b96507e commit 1588676
Show file tree
Hide file tree
Showing 7 changed files with 159 additions and 171 deletions.
10 changes: 3 additions & 7 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,12 @@ branch = "otak/2.0-error-codes"
[patch.crates-io.openmls]
package = "openmls"
git = "https://github.com/wireapp/openmls"
tag = "v0.5.4-pre.core-crypto-0.7.0"
tag = "v0.5.5-pre.core-crypto-0.7.0"

[patch.crates-io.openmls_traits]
package = "openmls_traits"
git = "https://github.com/wireapp/openmls"
tag = "v0.5.4-pre.core-crypto-0.7.0"
tag = "v0.5.5-pre.core-crypto-0.7.0"

[patch.crates-io.hpke-rs]
git = "https://github.com/wireapp/hpke-rs"
Expand Down Expand Up @@ -74,16 +74,12 @@ package = "openssl-src"
[patch.crates-io.wire-e2e-identity]
git = "https://github.com/wireapp/rusty-jwt-tools"
package = "wire-e2e-identity"
tag = "v0.3.1"
tag = "v0.3.2"

[patch.crates-io.jwt-simple]
git = "https://github.com/wireapp/rust-jwt-simple"
tag = "v0.11.4-pre.core-crypto-0.7.0"

[patch.crates-io.biscuit]
git = "https://github.com/beltram/biscuit"
tag = "v0.6.0-pre.core-crypto-0.6.0"

# Needed for quick mode and (later) result comparison see (https://www.tweag.io/blog/2022-03-03-criterion-rs/)
# TODO: remove once branch got merged in 0.4 release
[patch.crates-io.criterion]
Expand Down
44 changes: 23 additions & 21 deletions crypto-ffi/bindings/js/test/CoreCrypto.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -967,29 +967,31 @@ test("end-to-end-identity", async () => {
const certificateReq = enrollment.certificateRequest(previousNonce);

const certificateResp = "-----BEGIN CERTIFICATE-----\n" +
"MIIB7DCCAZKgAwIBAgIRAIErw6bhWUQXxeS0xsdMvyEwCgYIKoZIzj0EAwIwLjEN\n" +
"MAsGA1UEChMEd2lyZTEdMBsGA1UEAxMUd2lyZSBJbnRlcm1lZGlhdGUgQ0EwHhcN\n" +
"MjMwMTA1MjAwMDQxWhcNMjMwMTA2MjAwMTQxWjAAMFkwEwYHKoZIzj0CAQYIKoZI\n" +
"zj0DAQcDQgAEq9rybsGxEBLpn6Tx5LHladF6jw3Vuc5Yr27NKRLwFWbCUXUmwApv\n" +
"arn35O3u+w1CnwTyCA2tt605GhvbL039AKOBvjCBuzAOBgNVHQ8BAf8EBAMCB4Aw\n" +
"HQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMB0GA1UdDgQWBBTlxc6/odBa\n" +
"eTAlHYZcoCeFyn0BCjAfBgNVHSMEGDAWgBRsNCwlQHq5dXTxxfhhKHYOFQtlXzAm\n" +
"BgNVHREBAf8EHDAagg5sb2dpbi53aXJlLmNvbYIId2lyZS5jb20wIgYMKwYBBAGC\n" +
"pGTGKEABBBIwEAIBBgQJd2lyZS1hY21lBAAwCgYIKoZIzj0EAwIDSAAwRQIgAwhX\n" +
"Jvnc7hOUOT41I35ZZi5rgJKF4FtMyImvCFY1UQ0CIQC2k+k7uqwgMRp10z3xzWHE\n" +
"3sMuOBJG/UAR+VtFvCmGSA==\n" +
"MIICaDCCAg6gAwIBAgIQH3CanUzXJpP+pbXNUVpp7TAKBggqhkjOPQQDAjAuMQ0w\n" +
"CwYDVQQKEwR3aXJlMR0wGwYDVQQDExR3aXJlIEludGVybWVkaWF0ZSBDQTAeFw0y\n" +
"MzAyMDkxNDU5MjBaFw0yMzAyMDkxNTU5MjBaMDQxFDASBgNVBAoTC2V4YW1wbGUu\n" +
"Y29tMRwwGgYDVQQDExNTbWl0aCwgQWxpY2UgTSAoUUEpMCowBQYDK2VwAyEAVCw/\n" +
"lxGMV2Zx723yhVv94Fb+LCARV0h1F1/zmvRZGy6jggE1MIIBMTAOBgNVHQ8BAf8E\n" +
"BAMCB4AwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMB0GA1UdDgQWBBSr\n" +
"zp+ejXBydYcjmBr4cTp931ceUTAfBgNVHSMEGDAWgBS04sLODR52O3cPNlNdK3f6\n" +
"tinkIzCBoAYDVR0RBIGYMIGVghNzbWl0aCwgYWxpY2UgbSAocWEphidpbXBwOndp\n" +
"cmVhcHA9YWxpY2Uuc21pdGgucWFAZXhhbXBsZS5jb22GVWltcHA6d2lyZWFwcD1u\n" +
"amppeXRyam10aXlvZGpqbmR5NXltZTVuZ3ptbWpoaG5qZmtvZGEwbmprL2QyYmEy\n" +
"YzFhNTc1ODhlZTRAZXhhbXBsZS5jb20wHQYMKwYBBAGCpGTGKEABBA0wCwIBBgQE\n" +
"YWNtZQQAMAoGCCqGSM49BAMCA0gAMEUCIG6cfFB2En9YKVPuQhEZcoELtZbkFsTJ\n" +
"PeWa6zTkrI47AiEApQP8piMQWhofGLL6oTWoks3+6JfPRWZP9Z7JkhdiBmY=\n" +
"-----END CERTIFICATE-----\n" +
"-----BEGIN CERTIFICATE-----\n" +
"MIIBuTCCAV+gAwIBAgIRAOzPGCzghRSFfL08VAXS/DQwCgYIKoZIzj0EAwIwJjEN\n" +
"MAsGA1UEChMEd2lyZTEVMBMGA1UEAxMMd2lyZSBSb290IENBMB4XDTIzMDEwNTIw\n" +
"MDEzOFoXDTMzMDEwMjIwMDEzOFowLjENMAsGA1UEChMEd2lyZTEdMBsGA1UEAxMU\n" +
"d2lyZSBJbnRlcm1lZGlhdGUgQ0EwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARc\n" +
"LwmNj175LF1Wd+CC7lVGVUzr/ys+mR7XbN0csRx3okfJKZFxx0PGs6JO+pTUG0C3\n" +
"27GSfNQU+2tz5fnrmahxo2YwZDAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgw\n" +
"BgEB/wIBADAdBgNVHQ4EFgQUbDQsJUB6uXV08cX4YSh2DhULZV8wHwYDVR0jBBgw\n" +
"FoAUuL+rLbn8HEXbB6Pw5wzGhGjlE24wCgYIKoZIzj0EAwIDSAAwRQIgEltwd9QL\n" +
"LdKVfvqnrQ/H3a4uIPgJz0+YQI1Y0eYuMB4CIQCYMrIYAqC7nqjqVXrROShrISO+\n" +
"S26guHAMqXDlqqueOQ==\n" +
"MIIBuDCCAV6gAwIBAgIQP5i/9/vpRPXels/aSa5lZTAKBggqhkjOPQQDAjAmMQ0w\n" +
"CwYDVQQKEwR3aXJlMRUwEwYDVQQDEwx3aXJlIFJvb3QgQ0EwHhcNMjMwMjA5MTQ1\n" +
"OTE4WhcNMzMwMjA2MTQ1OTE4WjAuMQ0wCwYDVQQKEwR3aXJlMR0wGwYDVQQDExR3\n" +
"aXJlIEludGVybWVkaWF0ZSBDQTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABFNd\n" +
"5wbJjtVSmXxftBSmHgTJS3F1LGMlb789KtcSTjjJVO//VNdg3XDYvhHyitHx/Bz+\n" +
"5yxkrPaRzeGeJkZfkuejZjBkMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAG\n" +
"AQH/AgEAMB0GA1UdDgQWBBS04sLODR52O3cPNlNdK3f6tinkIzAfBgNVHSMEGDAW\n" +
"gBTqNi9/bemraZjLYA8TGat3ianEizAKBggqhkjOPQQDAgNIADBFAiEAuo8JLvys\n" +
"IvUCvPUJi1++80IgPeRxxRvn5zlHDh3qKZECIHONc1xx1ixlIyp9mOtdeTvG5Dql\n" +
"RheWYpDHRiLax1Id\n" +
"-----END CERTIFICATE-----";

await cc.e2eiMlsInit(enrollment, certificateResp);
Expand Down
9 changes: 0 additions & 9 deletions crypto/src/e2e_identity/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -406,21 +406,12 @@ pub mod tests {

#[apply(all_cred_cipher)]
#[wasm_bindgen_test]
// #[async_std::test]
pub async fn e2e_identity_should_work(case: TestCase) {
/*let case = TestCase::new(
crate::mls::credential::CertificateBundle::rand_basic(),
openmls::prelude::Ciphersuite::MLS_128_DHKEMX25519_AES128GCM_SHA256_Ed25519,
);*/
#[cfg(not(target_family = "wasm"))]
let supported_alg = [
SignatureScheme::ED25519,
SignatureScheme::ECDSA_SECP256R1_SHA256,
SignatureScheme::ECDSA_SECP384R1_SHA384,
];
// EC signature are not supported because not supported by ring on WASM
#[cfg(target_family = "wasm")]
let supported_alg = [SignatureScheme::ED25519];

if supported_alg.contains(&case.signature_scheme()) {
run_test_wo_clients(case.clone(), move |mut cc| {
Expand Down
189 changes: 96 additions & 93 deletions crypto/src/mls/credential.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,16 +37,20 @@ impl CertificateBundle {
// generate the leaf certificate
let (leaf_kp, leaf_sk) = Self::key_pair(cs);
let leaf_params = Self::certificate_params(leaf_kp, false);
Some(Self::certificate_bundle_from_leaf(cs, leaf_params, leaf_sk))
Some(Self::new_certificate_bundle_from_leaf(cs, leaf_params, leaf_sk))
}
}

fn certificate_bundle_from_leaf(
fn new_certificate_bundle_from_leaf(
cs: MlsCiphersuite,
leaf_params: rcgen::CertificateParams,
leaf_sk: SignaturePrivateKey,
) -> CertificateBundle {
// those fields are lost when we generate a csr, hence we restore it later
// generate an issuer who is also a root ca
let (issuer_kp, _) = Self::key_pair(cs);
let issuer_params = Self::certificate_params(issuer_kp, true);
let issuer = rcgen::Certificate::from_params(issuer_params).unwrap();

let not_after = leaf_params.not_after;
let not_before = leaf_params.not_before;

Expand All @@ -59,17 +63,11 @@ impl CertificateBundle {
csr.params.not_after = not_after;
csr.params.not_before = not_before;

// generate an issuer who is also a root ca
let (issuer_kp, _) = Self::key_pair(cs);
let issuer_params = Self::certificate_params(issuer_kp, true);
let issuer = rcgen::Certificate::from_params(issuer_params).unwrap();
let issuer_der = issuer.serialize_der().unwrap();

// generate leaf certificate from the csr
let leaf_der = csr.serialize_der_with_signer(&issuer).unwrap();

Self {
certificate_chain: vec![leaf_der, issuer_der],
certificate_chain: vec![leaf_der, issuer.serialize_der().unwrap()],
private_key: leaf_sk,
}
}
Expand Down Expand Up @@ -135,7 +133,6 @@ impl Client {
#[cfg(test)]
pub mod tests {
use openmls::prelude::{CredentialError, WelcomeError};
use openmls_traits::types::SignatureScheme;
use wasm_bindgen_test::*;

use crate::{
Expand All @@ -159,31 +156,25 @@ pub mod tests {
#[apply(all_cred_cipher)]
#[wasm_bindgen_test]
async fn certificate_clients_can_send_messages(case: TestCase) {
// TODO we only support ed25519 signatures for certificates currently
if case.ciphersuite().0.signature_algorithm() == SignatureScheme::ED25519 {
let alice_cred = CertificateBundle::rand_certificate_bundle();
let bob_cred = CertificateBundle::rand_certificate_bundle();
assert!(alice_and_bob_talk(alice_cred, bob_cred, case.cfg).await.is_ok());
}
let alice_cred = CertificateBundle::rand_certificate_bundle();
let bob_cred = CertificateBundle::rand_certificate_bundle();
assert!(alice_and_bob_talk(alice_cred, bob_cred, case.cfg).await.is_ok());
}

#[apply(all_cred_cipher)]
#[wasm_bindgen_test]
async fn heterogeneous_clients_can_send_messages(case: TestCase) {
// TODO we only support ed25519 signatures for certificates currently
if case.ciphersuite().0.signature_algorithm() == SignatureScheme::ED25519 {
// check that both credentials can initiate/join a group
{
let alice_cred = CertificateBundle::rand_basic();
let bob_cred = CertificateBundle::rand_certificate_bundle();
assert!(alice_and_bob_talk(alice_cred, bob_cred, case.cfg.clone()).await.is_ok());
// drop alice & bob key stores
}
{
let alice_cred = CertificateBundle::rand_certificate_bundle();
let bob_cred = CertificateBundle::rand_basic();
assert!(alice_and_bob_talk(alice_cred, bob_cred, case.cfg).await.is_ok());
}
// check that both credentials can initiate/join a group
{
let alice_cred = CertificateBundle::rand_basic();
let bob_cred = CertificateBundle::rand_certificate_bundle();
assert!(alice_and_bob_talk(alice_cred, bob_cred, case.cfg.clone()).await.is_ok());
// drop alice & bob key stores
}
{
let alice_cred = CertificateBundle::rand_certificate_bundle();
let bob_cred = CertificateBundle::rand_basic();
assert!(alice_and_bob_talk(alice_cred, bob_cred, case.cfg).await.is_ok());
}
}

Expand Down Expand Up @@ -227,85 +218,97 @@ pub mod tests {
#[apply(all_cred_cipher)]
#[wasm_bindgen_test]
async fn should_fail_when_certificate_chain_is_unordered(case: TestCase) {
// TODO we only support ed25519 signatures for certificates currently
if case.ciphersuite().0.signature_algorithm() == SignatureScheme::ED25519 {
// chain must be [leaf, leaf-issuer, ..., root-ca]
let alice_cred = |cs: MlsCiphersuite| {
let mut bundle = CertificateBundle::rand_certificate_bundle()(cs).unwrap();
bundle.certificate_chain.reverse();
Some(bundle)
};
let bob_cred = CertificateBundle::rand_certificate_bundle();
assert!(matches!(
alice_and_bob_talk(alice_cred, bob_cred, case.cfg).await.unwrap_err(),
CryptoError::MlsError(MlsError::MlsWelcomeError(WelcomeError::InvalidGroupInfoSignature))
));
}
// chain must be [leaf, leaf-issuer, ..., root-ca]
let alice_cred = |cs: MlsCiphersuite| {
let mut bundle = CertificateBundle::rand_certificate_bundle()(cs).unwrap();
bundle.certificate_chain.reverse();
Some(bundle)
};
let bob_cred = CertificateBundle::rand_certificate_bundle();
assert!(matches!(
alice_and_bob_talk(alice_cred, bob_cred, case.cfg).await.unwrap_err(),
CryptoError::MlsError(MlsError::MlsWelcomeError(WelcomeError::InvalidGroupInfoSignature))
));
}

#[apply(all_cred_cipher)]
#[wasm_bindgen_test]
async fn should_fail_when_invalid_intermediates(case: TestCase) {
let alice_cred = |cs: MlsCiphersuite| {
let (malicious_kp, _) = CertificateBundle::key_pair(cs);
let malicious_params = CertificateBundle::certificate_params(malicious_kp, true);
let malicious_intermediate = rcgen::Certificate::from_params(malicious_params).unwrap();

let mut bundle = CertificateBundle::rand_certificate_bundle()(cs).unwrap();
// remove the valid intermediate
bundle.certificate_chain.pop().unwrap();
// and replace it with the malicious one
bundle
.certificate_chain
.push(malicious_intermediate.serialize_der().unwrap());
Some(bundle)
};
let bob_cred = CertificateBundle::rand_certificate_bundle();
assert!(matches!(
alice_and_bob_talk(alice_cred, bob_cred, case.cfg).await.unwrap_err(),
CryptoError::MlsError(MlsError::MlsWelcomeError(WelcomeError::InvalidGroupInfoSignature))
));
}

#[apply(all_cred_cipher)]
#[wasm_bindgen_test]
async fn should_fail_when_signature_key_doesnt_match_certificate_public_key(case: TestCase) {
// TODO we only support ed25519 signatures for certificates currently
if case.ciphersuite().0.signature_algorithm() == SignatureScheme::ED25519 {
let alice_cred = |cs: MlsCiphersuite| {
let bundle = CertificateBundle::rand_certificate_bundle()(cs).unwrap();
let other_bundle = CertificateBundle::rand_certificate_bundle()(cs).unwrap();
Some(CertificateBundle {
certificate_chain: bundle.certificate_chain,
private_key: other_bundle.private_key,
})
};
let bob_cred = CertificateBundle::rand_certificate_bundle();
assert!(matches!(
alice_and_bob_talk(alice_cred, bob_cred, case.cfg).await.unwrap_err(),
CryptoError::MlsError(MlsError::MlsWelcomeError(WelcomeError::InvalidGroupInfoSignature))
));
}
let alice_cred = |cs: MlsCiphersuite| {
let bundle = CertificateBundle::rand_certificate_bundle()(cs).unwrap();
let other_bundle = CertificateBundle::rand_certificate_bundle()(cs).unwrap();
Some(CertificateBundle {
certificate_chain: bundle.certificate_chain,
private_key: other_bundle.private_key,
})
};
let bob_cred = CertificateBundle::rand_certificate_bundle();
assert!(matches!(
alice_and_bob_talk(alice_cred, bob_cred, case.cfg).await.unwrap_err(),
CryptoError::MlsError(MlsError::MlsWelcomeError(WelcomeError::InvalidGroupInfoSignature))
));
}

#[apply(all_cred_cipher)]
#[wasm_bindgen_test]
async fn should_fail_when_certificate_expired(case: TestCase) {
// TODO we only support ed25519 signatures for certificates currently
if case.ciphersuite().0.signature_algorithm() == SignatureScheme::ED25519 {
let alice_cred = |cs: MlsCiphersuite| {
let (leaf_kp, leaf_sk) = CertificateBundle::key_pair(cs);
let mut params = rcgen::CertificateParams::new(vec!["wire.com".to_string()]);
params.alg = &rcgen::PKCS_ED25519;
params.key_pair = Some(leaf_kp);
params.not_after = rcgen::date_time_ymd(1970, 1, 1);
Some(CertificateBundle::certificate_bundle_from_leaf(cs, params, leaf_sk))
};
let alice_cred = |cs: MlsCiphersuite| {
let (leaf_kp, leaf_sk) = CertificateBundle::key_pair(cs);
let mut params = rcgen::CertificateParams::new(vec!["wire.com".to_string()]);
params.alg = &rcgen::PKCS_ED25519;
params.key_pair = Some(leaf_kp);
params.not_after = rcgen::date_time_ymd(1970, 1, 1);
Some(CertificateBundle::new_certificate_bundle_from_leaf(cs, params, leaf_sk))
};

let bob_cred = CertificateBundle::rand_certificate_bundle();
assert!(matches!(
alice_and_bob_talk(alice_cred, bob_cred, case.cfg).await.unwrap_err(),
CryptoError::MlsError(MlsError::MlsWelcomeError(WelcomeError::InvalidGroupInfoSignature))
));
}
let bob_cred = CertificateBundle::rand_certificate_bundle();
assert!(matches!(
alice_and_bob_talk(alice_cred, bob_cred, case.cfg).await.unwrap_err(),
CryptoError::MlsError(MlsError::MlsWelcomeError(WelcomeError::InvalidGroupInfoSignature))
));
}

#[apply(all_cred_cipher)]
#[wasm_bindgen_test]
async fn should_fail_when_certificate_not_valid_yet(case: TestCase) {
// TODO we only support ed25519 signatures for certificates currently
if case.ciphersuite().0.signature_algorithm() == SignatureScheme::ED25519 {
let alice_cred = |cs: MlsCiphersuite| {
let (leaf_kp, leaf_sk) = CertificateBundle::key_pair(cs);
let mut params = rcgen::CertificateParams::new(vec!["wire.com".to_string()]);
params.alg = &rcgen::PKCS_ED25519;
params.key_pair = Some(leaf_kp);
params.not_before = rcgen::date_time_ymd(3000, 1, 1);
Some(CertificateBundle::certificate_bundle_from_leaf(cs, params, leaf_sk))
};
let alice_cred = |cs: MlsCiphersuite| {
let (leaf_kp, leaf_sk) = CertificateBundle::key_pair(cs);
let mut params = rcgen::CertificateParams::new(vec!["wire.com".to_string()]);
params.alg = &rcgen::PKCS_ED25519;
params.key_pair = Some(leaf_kp);
params.not_before = rcgen::date_time_ymd(3000, 1, 1);
Some(CertificateBundle::new_certificate_bundle_from_leaf(cs, params, leaf_sk))
};

let bob_cred = CertificateBundle::rand_certificate_bundle();
assert!(matches!(
alice_and_bob_talk(alice_cred, bob_cred, case.cfg).await.unwrap_err(),
CryptoError::MlsError(MlsError::MlsWelcomeError(WelcomeError::InvalidGroupInfoSignature))
));
}
let bob_cred = CertificateBundle::rand_certificate_bundle();
assert!(matches!(
alice_and_bob_talk(alice_cred, bob_cred, case.cfg).await.unwrap_err(),
CryptoError::MlsError(MlsError::MlsWelcomeError(WelcomeError::InvalidGroupInfoSignature))
));
}

async fn alice_and_bob_talk(
Expand Down
Loading

0 comments on commit 1588676

Please sign in to comment.