Skip to content

Commit

Permalink
fix: make RwLock in RustCrypto async [WPB-10044]
Browse files Browse the repository at this point in the history
  • Loading branch information
SimonThormeyer committed Jul 8, 2024
1 parent 6d2f5a2 commit aa39a39
Show file tree
Hide file tree
Showing 83 changed files with 616 additions and 385 deletions.
4 changes: 2 additions & 2 deletions interop_client/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ impl MlsClient for MlsClientImpl {

let signature_keys = SignatureKeyPair::new(
ciphersuite.signature_algorithm(),
&mut *backend.rand().borrow_rand().unwrap(),
&mut *backend.rand().borrow_rand().await,
)
.unwrap();
signature_keys.store(backend.key_store()).await.unwrap();
Expand Down Expand Up @@ -353,7 +353,7 @@ impl MlsClient for MlsClientImpl {
let credential = Credential::new(identity, CredentialType::Basic).unwrap();
let signature_keys = SignatureKeyPair::new(
ciphersuite.signature_algorithm(),
&mut *crypto_provider.rand().borrow_rand().unwrap(),
&mut *crypto_provider.rand().borrow_rand().await,
)
.unwrap();

Expand Down
1 change: 1 addition & 0 deletions openmls/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ async-lock = { version = "3.3", optional = true }
rstest = { version = "0.18.2", optional = true }
rstest_reuse = { version = "0.6.0", optional = true }
tokio = { version = "1.24", optional = true, features = ["macros", "rt", "rt-multi-thread"] }
futures = "0.3.30"

[features]
default = []
Expand Down
8 changes: 3 additions & 5 deletions openmls/benches/benchmark.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use criterion::{
async_executor::FuturesExecutor, criterion_group, criterion_main, BenchmarkId, Criterion,
};
use futures::executor;
use openmls::prelude::{config::CryptoConfig, *};
use openmls_basic_credential::SignatureKeyPair;
use openmls_rust_crypto::OpenMlsRustCrypto;
Expand All @@ -9,12 +10,9 @@ use openmls_traits::{crypto::OpenMlsCrypto, OpenMlsCryptoProvider};
fn criterion_benchmark(c: &mut Criterion) {
let backend = OpenMlsRustCrypto::default();
for &ciphersuite in backend.crypto().supported_ciphersuites().iter() {
let mut rng = executor::block_on(backend.rand().borrow_rand());
let credential = Credential::new_basic(vec![1, 2, 3]);
let signer = SignatureKeyPair::new(
ciphersuite.signature_algorithm(),
&mut *backend.rand().borrow_rand().unwrap(),
)
.unwrap();
let signer = SignatureKeyPair::new(ciphersuite.signature_algorithm(), &mut *rng).unwrap();
let credential_with_key = CredentialWithKey {
credential,
signature_key: signer.to_public_vec().into(),
Expand Down
24 changes: 16 additions & 8 deletions openmls/src/ciphersuite/aead.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,10 @@ impl AeadKey {

#[cfg(test)]
/// Generate a random AEAD Key
pub(crate) fn random(ciphersuite: Ciphersuite, rng: &impl OpenMlsRand) -> Self {
pub(crate) async fn random(ciphersuite: Ciphersuite, rng: &impl OpenMlsRand) -> Self {
AeadKey {
aead_mode: ciphersuite.aead_algorithm(),
value: aead_key_gen(ciphersuite.aead_algorithm(), rng),
value: aead_key_gen(ciphersuite.aead_algorithm(), rng).await,
}
}

Expand Down Expand Up @@ -111,8 +111,13 @@ impl AeadNonce {
/// **NOTE: This has to wait until it can acquire the lock to get randomness!**
/// TODO: This panics if another thread holding the rng panics.
#[cfg(test)]
pub(crate) fn random(rng: &impl OpenMlsCryptoProvider) -> Self {
Self(rng.rand().random_array().expect("Not enough entropy."))
pub(crate) async fn random(rng: &impl OpenMlsCryptoProvider) -> Self {
Self(
rng.rand()
.random_array()
.await
.expect("Not enough entropy."),
)
}

/// Get a slice to the nonce value.
Expand All @@ -138,18 +143,20 @@ impl AeadNonce {
}

#[cfg(test)]
pub(crate) fn aead_key_gen(
pub(crate) async fn aead_key_gen(
alg: openmls_traits::types::AeadType,
rng: &impl OpenMlsRand,
) -> SecretVLBytes {
match alg {
openmls_traits::types::AeadType::Aes128Gcm => rng
.random_vec(16)
.await
.expect("An unexpected error occurred.")
.into(),
openmls_traits::types::AeadType::Aes256Gcm
| openmls_traits::types::AeadType::ChaCha20Poly1305 => rng
.random_vec(32)
.await
.expect("An unexpected error occurred.")
.into(),
}
Expand All @@ -166,9 +173,10 @@ mod unit_tests {
/// state.
#[apply(backends)]
async fn test_xor(backend: &impl OpenMlsCryptoProvider) {
let reuse_guard: ReuseGuard =
ReuseGuard::try_from_random(backend).expect("An unexpected error occurred.");
let original_nonce = AeadNonce::random(backend);
let reuse_guard: ReuseGuard = ReuseGuard::try_from_random(backend)
.await
.expect("An unexpected error occurred.");
let original_nonce = AeadNonce::random(backend).await;
let xored_once = original_nonce.clone().xor_with_reuse_guard(&reuse_guard);
assert_ne!(
original_nonce, xored_once,
Expand Down
18 changes: 10 additions & 8 deletions openmls/src/ciphersuite/hpke.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ impl From<(&str, &[u8])> for EncryptContext {
}

/// Encrypt to an HPKE key with a label.
pub(crate) fn encrypt_with_label(
pub(crate) async fn encrypt_with_label(
public_key: &[u8],
label: &str,
context: &[u8],
Expand All @@ -109,13 +109,15 @@ pub(crate) fn encrypt_with_label(
log_crypto!(debug, "* public key: {public_key:x?}");
log_crypto!(debug, "* plaintext: {plaintext:x?}");

let cipher = crypto.hpke_seal(
ciphersuite.hpke_config(),
public_key,
&context,
&[],
plaintext,
)?;
let cipher = crypto
.hpke_seal(
ciphersuite.hpke_config(),
public_key,
&context,
&[],
plaintext,
)
.await?;

log_crypto!(debug, "* ciphertext: {:x?}", cipher);

Expand Down
3 changes: 2 additions & 1 deletion openmls/src/ciphersuite/reuse_guard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,14 @@ pub struct ReuseGuard {

impl ReuseGuard {
/// Samples a fresh reuse guard uniformly at random.
pub(crate) fn try_from_random(
pub(crate) async fn try_from_random(
crypto: &impl OpenMlsCryptoProvider,
) -> Result<Self, CryptoError> {
Ok(Self {
value: crypto
.rand()
.random_array()
.await
.map_err(|_| CryptoError::InsufficientRandomness)?,
})
}
Expand Down
3 changes: 2 additions & 1 deletion openmls/src/ciphersuite/secret.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ impl Secret {
/// Randomly sample a fresh `Secret`.
/// This default random initialiser uses the default Secret length of `hash_length`.
/// The function can return a [`CryptoError`] if there is insufficient randomness.
pub(crate) fn random(
pub(crate) async fn random(
ciphersuite: Ciphersuite,
crypto: &impl OpenMlsCryptoProvider,
version: impl Into<Option<ProtocolVersion>>,
Expand All @@ -88,6 +88,7 @@ impl Secret {
value: crypto
.rand()
.random_vec(ciphersuite.hash_length())
.await
.map_err(|_| CryptoError::InsufficientRandomness)?
.into(),
mls_version,
Expand Down
19 changes: 11 additions & 8 deletions openmls/src/ciphersuite/tests/kat_crypto_basics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -341,14 +341,17 @@ pub fn run_test_vector(
assert_eq!(plaintext, decrypted_plaintext);

// Check that encryption works.
let my_ciphertext = hpke::encrypt_with_label(
&public,
&label,
&context,
&plaintext,
ciphersuite,
backend.crypto(),
)
let my_ciphertext = async_std::task::block_on(async {
hpke::encrypt_with_label(
&public,
&label,
&context,
&plaintext,
ciphersuite,
backend.crypto(),
)
.await
})
.unwrap();
let decrypted_plaintext = hpke::decrypt_with_label(
&private,
Expand Down
2 changes: 2 additions & 0 deletions openmls/src/ciphersuite/tests/test_ciphersuite.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ async fn test_hpke_seal_open(ciphersuite: Ciphersuite, backend: &impl OpenMlsCry
.derive_hpke_keypair(
ciphersuite.hpke_config(),
Secret::random(ciphersuite, backend, None)
.await
.expect("Not enough randomness.")
.as_slice(),
)
Expand All @@ -28,6 +29,7 @@ async fn test_hpke_seal_open(ciphersuite: Ciphersuite, backend: &impl OpenMlsCry
ciphersuite,
backend.crypto(),
)
.await
.unwrap();
let decrypted_payload = hpke::decrypt_with_label(
&kp.private,
Expand Down
12 changes: 8 additions & 4 deletions openmls/src/ciphersuite/tests/test_secrets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@ wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser);
#[wasm_bindgen_test::wasm_bindgen_test]
async fn secret_init(ciphersuite: Ciphersuite, backend: &impl OpenMlsCryptoProvider) {
// These two secrets must be incompatible
let default_secret =
Secret::random(ciphersuite, backend, None).expect("Not enough randomness.");
let default_secret = Secret::random(ciphersuite, backend, None)
.await
.expect("Not enough randomness.");
let draft_secret = Secret::random(ciphersuite, backend, ProtocolVersion::Mls10Draft11)
.await
.expect("Not enough randomness.");

let derived_default_secret = default_secret.derive_secret(backend, "my_test_label");
Expand All @@ -26,9 +28,11 @@ async fn secret_init(ciphersuite: Ciphersuite, backend: &impl OpenMlsCryptoProvi
#[wasm_bindgen_test::wasm_bindgen_test]
pub async fn secret_incompatible(ciphersuite: Ciphersuite, backend: &impl OpenMlsCryptoProvider) {
// These two secrets must be incompatible
let default_secret =
Secret::random(ciphersuite, backend, None).expect("Not enough randomness.");
let default_secret = Secret::random(ciphersuite, backend, None)
.await
.expect("Not enough randomness.");
let draft_secret = Secret::random(ciphersuite, backend, ProtocolVersion::Mls10Draft11)
.await
.expect("Not enough randomness.");

// This must panic because the two secrets have incompatible MLS versions.
Expand Down
8 changes: 3 additions & 5 deletions openmls/src/credentials/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -436,11 +436,9 @@ pub mod test_utils {
CredentialType::X509 => Credential::new_x509(cert_data.unwrap()).unwrap(),
CredentialType::Unknown(_) => unimplemented!(),
};
let signature_keys = SignatureKeyPair::new(
signature_scheme,
&mut *backend.rand().borrow_rand().unwrap(),
)
.unwrap();
let signature_keys =
SignatureKeyPair::new(signature_scheme, &mut *backend.rand().borrow_rand().await)
.unwrap();
signature_keys.store(backend.key_store()).await.unwrap();

(
Expand Down
14 changes: 9 additions & 5 deletions openmls/src/extensions/external_pub_extension.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ impl ExternalPubExtension {

#[cfg(test)]
mod test {
use async_std::task::block_on;
use openmls_rust_crypto::OpenMlsRustCrypto;
use openmls_traits::{crypto::OpenMlsCrypto, types::Ciphersuite, OpenMlsCryptoProvider};
use tls_codec::{Deserialize, Serialize};
Expand All @@ -47,11 +48,14 @@ mod test {
for _ in 0..8 {
let hpke_public_key =
{
let ikm = Secret::random(
Ciphersuite::MLS_128_DHKEMX25519_CHACHA20POLY1305_SHA256_Ed25519,
&backend,
ProtocolVersion::default(),
)
let ikm = block_on(async {
Secret::random(
Ciphersuite::MLS_128_DHKEMX25519_CHACHA20POLY1305_SHA256_Ed25519,
&backend,
ProtocolVersion::default(),
)
.await
})
.unwrap();
let init_key = backend.crypto().derive_hpke_keypair(
Ciphersuite::hpke_config(
Expand Down
4 changes: 2 additions & 2 deletions openmls/src/extensions/test_extensions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ async fn ratchet_tree_extension(ciphersuite: Ciphersuite, backend: &impl OpenMls

// === Alice creates a group with the ratchet tree extension ===
let mut alice_group = CoreGroup::builder(
GroupId::random(backend),
GroupId::random(backend).await,
config::CryptoConfig::with_default_version(ciphersuite),
alice_credential_with_key.clone(),
)
Expand Down Expand Up @@ -146,7 +146,7 @@ async fn ratchet_tree_extension(ciphersuite: Ciphersuite, backend: &impl OpenMls
};

let mut alice_group = CoreGroup::builder(
GroupId::random(backend),
GroupId::random(backend).await,
config::CryptoConfig::with_default_version(ciphersuite),
alice_credential_with_key,
)
Expand Down
17 changes: 11 additions & 6 deletions openmls/src/framing/private_message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ impl PrivateMessage {
///
/// TODO #1148: Refactor theses constructors to avoid test code in main and
/// to avoid validation using a special feature flag.
pub(crate) fn try_from_authenticated_content(
pub(crate) async fn try_from_authenticated_content(
public_message: &AuthenticatedContent,
ciphersuite: Ciphersuite,
backend: &impl OpenMlsCryptoProvider,
Expand All @@ -90,10 +90,11 @@ impl PrivateMessage {
message_secrets,
padding_size,
)
.await
}

#[cfg(any(feature = "test-utils", test))]
pub(crate) fn encrypt_without_check(
pub(crate) async fn encrypt_without_check(
public_message: &AuthenticatedContent,
ciphersuite: Ciphersuite,
backend: &impl OpenMlsCryptoProvider,
Expand All @@ -108,10 +109,11 @@ impl PrivateMessage {
message_secrets,
padding_size,
)
.await
}

#[cfg(test)]
pub(crate) fn encrypt_with_different_header(
pub(crate) async fn encrypt_with_different_header(
public_message: &AuthenticatedContent,
ciphersuite: Ciphersuite,
backend: &impl OpenMlsCryptoProvider,
Expand All @@ -127,11 +129,12 @@ impl PrivateMessage {
message_secrets,
padding_size,
)
.await
}

/// Internal function to encrypt content. The extra message header is only used
/// for tests. Otherwise, the data from the given `AuthenticatedContent` is used.
fn encrypt_content(
async fn encrypt_content(
test_header: Option<MlsMessageHeader>,
public_message: &AuthenticatedContent,
ciphersuite: Ciphersuite,
Expand Down Expand Up @@ -170,8 +173,9 @@ impl PrivateMessage {
// Even in tests we want to use the real sender index, so we have a key to encrypt.
.secret_for_encryption(ciphersuite, backend, sender_index, secret_type)?;
// Sample reuse guard uniformly at random.
let reuse_guard: ReuseGuard =
ReuseGuard::try_from_random(backend).map_err(LibraryError::unexpected_crypto_error)?;
let reuse_guard: ReuseGuard = ReuseGuard::try_from_random(backend)
.await
.map_err(LibraryError::unexpected_crypto_error)?;
// Prepare the nonce by xoring with the reuse guard.
let prepared_nonce = ratchet_nonce.xor_with_reuse_guard(&reuse_guard);
// Encrypt the payload
Expand Down Expand Up @@ -320,6 +324,7 @@ impl PrivateMessage {
/// opaque padding[length_of_padding];
/// } PrivateMessageContent;
/// ```
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub(crate) struct PrivateMessageContent {
// The `content` field is serialized and deserialized manually without the
Expand Down
Loading

0 comments on commit aa39a39

Please sign in to comment.