Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
fa8c32e
feat: Added support for Credential validation
OtaK Jan 24, 2024
883d9b1
fix!: Internal API changes to allow plugging credential validation
OtaK Jan 29, 2024
22b004c
fix: Wire together credential validation in usual operations
OtaK Jan 29, 2024
bf5347c
fix: Send/Sync handling for async validations
OtaK Jan 29, 2024
9b724b7
Appease rustfmt
OtaK Feb 13, 2024
8417551
Updated dependencies
OtaK Feb 14, 2024
9c596b1
fix: verify GroupInfo
beltram Dec 22, 2023
3dd1711
fix: validate of Lifetime in KeyPackages only for senders
beltram Feb 21, 2024
8e52f0a
fix: be lenient about KeyPackage lifetime when joining via external c…
beltram Feb 21, 2024
42fbe01
fix: remove x509 expiration validation when decoding a message
beltram Feb 28, 2024
8c2b1d5
fix: handle incomplete write in 'framed_content_tbs_serialized'
beltram Mar 25, 2024
8f9e4a9
chore: apply clippy lints for Rust 1.77
beltram Mar 25, 2024
945654c
feat: expose processed message's credential with its associated publi…
beltram Mar 19, 2024
58fed9f
feat: add 'signature_public_key_len' & 'validate_signature_key' to Cr…
beltram Apr 15, 2024
29163fe
feat: Full p521 support
OtaK Apr 9, 2024
6d2f5a2
chore: remove support for the Kyber-based KEM
istankovic Jul 4, 2024
8f5df06
chore: replace instant with web-time [WPB-14399]
typfel Dec 13, 2024
c83849e
chore: fix clippy warnings after upgrading to rustc 1.83
typfel Dec 13, 2024
41b0ab8
chore: replace -Zprofile with -Cinstrument-coverage since the former …
typfel Dec 13, 2024
54ee2f6
chore: fix broken code coverage job
typfel Dec 16, 2024
3dead10
openmls: pin test futures to the heap
istankovic Apr 17, 2025
fd243f4
chore: make clippy happy again
istankovic Apr 17, 2025
de9b42d
chore(ephemeral): make `KeyPackageSecretEncapsulation` public, serial…
coriolinus May 2, 2025
f43c7b7
feat(ephemeral): impl `KeyPackageSecretEncapsulation::store`
coriolinus May 2, 2025
1df97fb
feat(ephemeral): impl `KeyPackageSecretEncapsulation::load`
coriolinus May 2, 2025
c47c884
feat(ephemeral): `KeyPackageSecretEncapsulation` can be treated as `K…
coriolinus May 5, 2025
4215403
feat: it is possible to cheaply get a `PublicGroup` from a `MlsGroup`
coriolinus May 20, 2025
eb81a7f
feat: add a public getter for proposal store to public group
coriolinus May 21, 2025
abe690e
feat: `ProposalQueue::from_committed_proposals` is public
coriolinus May 21, 2025
0eecd01
Revert "feat: `ProposalQueue::from_committed_proposals` is public"
coriolinus May 22, 2025
04f570b
Revert "feat: add a public getter for proposal store to public group"
coriolinus May 22, 2025
a1b8833
Revert "feat: it is possible to cheaply get a `PublicGroup` from a `M…
coriolinus May 22, 2025
55fcde8
feat: allow committing to inline proposals directly
SimonThormeyer Jul 1, 2025
e1d5f7d
fix: trim diff tree after processing all proposals
SimonThormeyer Jul 2, 2025
c9cde17
chore: fix clippy warnings
SimonThormeyer Jul 4, 2025
3cb2c68
test: can process old messages with blank leaves
SimonThormeyer Jun 11, 2026
c3bdf5a
ci: switch to 64-bit linux and windows targets for rust tests
SimonThormeyer Jun 11, 2026
79c281e
chore: update to x509-cert 0.3
istankovic Jul 23, 2026
f131c29
chore: update to const-oid 0.10
istankovic Jul 23, 2026
a289291
chore: adjust to new x509_cert API
istankovic Jul 23, 2026
1d20792
chore: fix clippy warnings
istankovic Jul 23, 2026
f683401
ci: remove the interop workflow
istankovic Jul 24, 2026
a43dd82
chore: update various RustCrypto crates
istankovic Aug 12, 2026
43dbd69
chore: to_encoded_point is now to_sec1_point
istankovic Aug 12, 2026
99b6a78
chore: adjust to new hpke API
istankovic Aug 14, 2026
63edeee
chore: there is no ChaCha20Rng::from_entropy anymore
istankovic Aug 14, 2026
d0e3ab0
chore: adjust to new aead nonce API
istankovic Aug 14, 2026
f923a75
chore: adjust to new p{256,384,521} API
istankovic Aug 14, 2026
fbcb243
chore: adjust to new rand and rand_core APIs
istankovic Aug 14, 2026
937c85c
chore: add a dependency on elliptic-curve
istankovic Aug 14, 2026
113b2a6
chore: use the Generate trait instead of random()
istankovic Aug 14, 2026
42e19e9
chore: more adjustments to new rand API
istankovic Aug 14, 2026
088ef82
test: box the test futures so we don't overflow the stack
istankovic Aug 14, 2026
7044a03
fix: don't use invalid vec.set_len
franziskuskiefer Aug 19, 2025
aec92d2
test: remove broken test
istankovic Aug 14, 2026
9252caa
fix: disable failing large test
franziskuskiefer Aug 20, 2025
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
21 changes: 13 additions & 8 deletions .github/workflows/coverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,28 @@ jobs:
uses: actions/checkout@v3
with:
submodules: true

- uses: dtolnay/rust-toolchain@master
- uses: dtolnay/rust-toolchain@nightly
with:
toolchain: nightly
components: rustc, rust-std, cargo, llvm-tools, llvm-tools-preview
run:
- uses: Swatinem/rust-cache@v2
- name: Install grcov
run: cargo install grcov
- name: Run profiling tests
run: cargo test --no-fail-fast -p openmls
run: |
mkdir -p target/debug/coverage
cargo test --no-fail-fast -p openmls
env:
CARGO_INCREMENTAL: '0'
RUSTFLAGS: '-Zprofile -Ccodegen-units=1 -Cinline-threshold=0 -Clink-dead-code -Coverflow-checks=off -Cpanic=abort -Zpanic_abort_tests'
RUSTDOCFLAGS: '-Zprofile -Ccodegen-units=1 -Cinline-threshold=0 -Clink-dead-code -Coverflow-checks=off -Cpanic=abort -Zpanic_abort_tests'
LLVM_PROFILE_FILE: 'target/debug/coverage/openmls-%p-%m.profraw'
RUSTFLAGS: '-Cinstrument-coverage -Ccodegen-units=1 -Clink-dead-code -Coverflow-checks=off -Cpanic=abort -Zpanic_abort_tests'
RUSTDOCFLAGS: '-Cinstrument-coverage -Ccodegen-units=1 -Clink-dead-code -Coverflow-checks=off -Cpanic=abort -Zpanic_abort_tests'

- name: Run grcov
id: coverage
uses: actions-rs/grcov@v0.1
run: grcov . -s . --binary-path ./target/debug/ -t lcov --branch --ignore-not-existing -o ./target/debug/coverage/

- name: Upload to codecov.io
uses: codecov/codecov-action@v3
with:
files: ${{ steps.coverage.outputs.report }}
files: target/debug/coverage/lcov
113 changes: 0 additions & 113 deletions .github/workflows/interop.yml

This file was deleted.

14 changes: 7 additions & 7 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ jobs:
ref: ${{ github.event.pull_request.head.sha }}
- uses: dtolnay/rust-toolchain@stable
with:
targets: i686-pc-windows-msvc, i686-unknown-linux-gnu
targets: x86_64-pc-windows-msvc, x86_64-unknown-linux-gnu
- uses: Swatinem/rust-cache@v2

- name: Toggle rustc mode
Expand All @@ -49,16 +49,16 @@ jobs:
run: cargo test $TEST_MODE -p openmls --verbose

# Test 32 bit builds on windows
- name: Tests 32bit windows debug
- name: Tests 64bit windows debug
if: matrix.mode == 'debug' && matrix.os == 'windows-latest'
run: cargo test -p openmls --verbose --target i686-pc-windows-msvc
- name: Tests 32bit windows release
run: cargo test -p openmls --verbose --target x86_64-pc-windows-msvc
- name: Tests 64bit windows release
if: matrix.mode == 'release' && matrix.os == 'windows-latest'
run: cargo test --release -p openmls --verbose --target i686-pc-windows-msvc
run: cargo test --release -p openmls --verbose --target x86_64-pc-windows-msvc

# Test 32 bit builds on linux
- name: Tests 32bit linux
- name: Tests 64bit linux
if: matrix.os == 'ubuntu-latest'
run: |
sudo apt update && sudo apt install gcc-multilib
cargo test $TEST_MODE -p openmls --verbose --target i686-unknown-linux-gnu
cargo test $TEST_MODE -p openmls --verbose --target x86_64-unknown-linux-gnu
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ resolver = "2"
async-trait = "0.1"

[workspace.dependencies.tls_codec]
version = "0.4.0"
version = "0.4"
features = ["derive", "serde", "mls"]

[workspace.dependencies.tls_codec_derive]
version = "0.4.0"
version = "0.4"
features = ["derive", "serde", "mls"]
14 changes: 8 additions & 6 deletions basic_credential/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,17 @@ async-trait = { workspace = true }
serde = "1.0"

# Rust Crypto
ed25519-dalek = { version = "2.0.0-rc.3", features = ["rand_core"] }
p256 = "0.13"
p384 = "0.13"
ed25519-dalek = { version = "3.0", features = ["rand_core"] }
elliptic-curve = "0.14"
p256 = "0.14"
p384 = "0.14"
p521 = "0.14"
secrecy = { version = "0.8", features = ["serde"] }
rand_core = "0.6"
getrandom = { version = "0.2", features = ["js"] }
rand_core = "0.10"
getrandom = { version = "0.4", features = ["wasm_js"] }

[dev-dependencies]
rand = "0.8"
rand = "0.10"

[features]
clonable = [] # Make the keys clonable
Expand Down
46 changes: 35 additions & 11 deletions basic_credential/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
//!
//! For now this credential uses only RustCrypto.

use elliptic_curve::Generate as _;
use secrecy::{ExposeSecret, SecretVec};
use std::fmt::Debug;

Expand Down Expand Up @@ -108,17 +109,25 @@ impl SignatureKeyPair {
/// Generates a fresh signature keypair using the [`SignatureScheme`].
pub fn new(
signature_scheme: SignatureScheme,
csprng: &mut impl rand_core::CryptoRngCore,
csprng: &mut impl rand_core::CryptoRng,
) -> Result<Self, CryptoError> {
let (private, public): (SecretVec<u8>, Vec<u8>) = match signature_scheme {
SignatureScheme::ECDSA_SECP256R1_SHA256 => {
let sk = p256::ecdsa::SigningKey::random(csprng);
let pk = sk.verifying_key().to_encoded_point(false).to_bytes().into();
let sk = p256::ecdsa::SigningKey::generate_from_rng(csprng);
let pk = sk.verifying_key().to_sec1_point(false).to_bytes().into();
(sk.to_bytes().to_vec().into(), pk)
}
SignatureScheme::ECDSA_SECP384R1_SHA384 => {
let sk = p384::ecdsa::SigningKey::random(csprng);
let pk = sk.verifying_key().to_encoded_point(false).to_bytes().into();
let sk = p384::ecdsa::SigningKey::generate_from_rng(csprng);
let pk = sk.verifying_key().to_sec1_point(false).to_bytes().into();
(sk.to_bytes().to_vec().into(), pk)
}
SignatureScheme::ECDSA_SECP521R1_SHA512 => {
let sk = p521::ecdsa::SigningKey::generate_from_rng(csprng);
let pk = p521::ecdsa::VerifyingKey::from(&sk)
.to_sec1_point(false)
.to_bytes()
.into();
(sk.to_bytes().to_vec().into(), pk)
}
SignatureScheme::ED25519 => {
Expand Down Expand Up @@ -159,31 +168,45 @@ impl SignatureKeyPair {
&private[..ed25519_dalek::SECRET_KEY_LENGTH],
)
.map_err(|_| CryptoError::InvalidKey)?;
let pk = ed25519_dalek::VerifyingKey::try_from(&public[..])
let pk = ed25519_dalek::VerifyingKey::try_from(public.as_slice())
.map_err(|_| CryptoError::InvalidKey)?;

if sk.verifying_key() != pk {
return Err(CryptoError::MismatchKeypair);
}
}
SignatureScheme::ECDSA_SECP256R1_SHA256 => {
let sk = p256::ecdsa::SigningKey::try_from(&private[..])
let sk = p256::ecdsa::SigningKey::from_slice(&private)
.map_err(|_| CryptoError::InvalidKey)?;
let pk = p256::ecdsa::VerifyingKey::try_from(&public[..])
let pk = p256::ecdsa::VerifyingKey::from_sec1_bytes(&public)
.map_err(|_| CryptoError::InvalidKey)?;

if sk.verifying_key() != &pk {
return Err(CryptoError::MismatchKeypair);
}
}
SignatureScheme::ECDSA_SECP384R1_SHA384 => {
let sk = p384::ecdsa::SigningKey::try_from(&private[..])
let sk = p384::ecdsa::SigningKey::from_slice(&private)
.map_err(|_| CryptoError::InvalidKey)?;
let pk = p384::ecdsa::VerifyingKey::try_from(&public[..])

let pk = p384::ecdsa::VerifyingKey::from_sec1_bytes(&public)
.map_err(|_| CryptoError::InvalidKey)?;

if sk.verifying_key() != &pk {
return Err(CryptoError::MismatchKeypair);
}
}
SignatureScheme::ECDSA_SECP521R1_SHA512 => {
let sk = p521::ecdsa::SigningKey::from_slice(&private)
.map_err(|_| CryptoError::InvalidKey)?;
let pk = p521::ecdsa::VerifyingKey::from_sec1_bytes(&public)
.map_err(|_| CryptoError::InvalidKey)?;
let sk_pk = p521::ecdsa::VerifyingKey::from(&sk);

if sk_pk.to_sec1_point(false) != pk.to_sec1_point(false) {
return Err(CryptoError::MismatchKeypair);
}
}
_ => {}
};

Expand Down Expand Up @@ -238,9 +261,10 @@ pub mod tests {
SignatureScheme::ED25519,
SignatureScheme::ECDSA_SECP256R1_SHA256,
SignatureScheme::ECDSA_SECP384R1_SHA384,
SignatureScheme::ECDSA_SECP521R1_SHA512,
];
for scheme in schemes {
let kp = SignatureKeyPair::new(scheme, &mut rand::thread_rng()).unwrap();
let kp = SignatureKeyPair::new(scheme, &mut rand::rng()).unwrap();
let sk = kp.private.expose_secret().clone();
let pk = kp.public.clone();
SignatureKeyPair::try_from_raw(scheme, sk, pk).unwrap();
Expand Down
12 changes: 6 additions & 6 deletions openmls/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,19 @@ hex = "0.4"
async-trait = { workspace = true }
openmls_basic_credential = { version = "0.2.0", path = "../basic_credential", features = ["clonable", "test-utils"] }
openmls_x509_credential = { version = "0.2.0", path = "../x509_credential" }
x509-cert = "0.2"
x509-cert = "0.3"
subtle = "2.5"
fluvio-wasm-timer = "0.2"
web-time = "1.1.0"
indexmap = "2.0"
itertools = "0.11"
itertools = "0.12"

# Only required for tests.
rand = { version = "0.8", optional = true, features = ["getrandom"] }
rand = { version = "0.10", optional = true }
getrandom = { version = "0.2", optional = true, features = ["js"] }
serde_json = { version = "1.0", optional = true }
# Crypto backends required for KAT and testing - "test-utils" feature
openmls_rust_crypto = { version = "0.2.0", path = "../openmls_rust_crypto", optional = true }
async-lock = { version = "2.7", optional = true }
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"] }
Expand Down Expand Up @@ -60,7 +60,7 @@ hex = { version = "0.4", features = ["serde"] }
lazy_static = "1.4"
openmls = { path = ".", features = ["test-utils"] }
openmls_traits = { version = "0.2.0", path = "../traits", features = ["test-utils"] }
pretty_env_logger = "0.4"
pretty_env_logger = "0.5"
rstest = "0.18.2"
rstest_reuse = "0.6.0"
tempfile = "3"
Expand Down
2 changes: 1 addition & 1 deletion openmls/src/binary_tree/array_representation/diff.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ impl<'a, L: Clone + Debug + Default, P: Clone + Debug + Default> From<&'a ABinar
}
}

impl<'a, L: Clone + Debug + Default, P: Clone + Debug + Default> AbDiff<'a, L, P> {
impl<L: Clone + Debug + Default, P: Clone + Debug + Default> AbDiff<'_, L, P> {
// Functions handling interactions with leaves.
///////////////////////////////////////////////

Expand Down
8 changes: 4 additions & 4 deletions openmls/src/binary_tree/array_representation/treemath.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ impl LeafNodeIndex {
}

/// Warning: Only use when the node index represents a leaf node
fn from_tree_index(node_index: u32) -> Self {
debug_assert!(node_index % 2 == 0);
pub fn from_tree_index(node_index: u32) -> Self {
debug_assert!(node_index.is_multiple_of(2));
LeafNodeIndex(node_index / 2)
}
}
Expand Down Expand Up @@ -140,7 +140,7 @@ pub enum TreeNodeIndex {
impl TreeNodeIndex {
/// Create a new `TreeNodeIndex` from a `u32`.
fn new(index: u32) -> Self {
if index % 2 == 0 {
if index.is_multiple_of(2) {
TreeNodeIndex::Leaf(LeafNodeIndex::from_tree_index(index))
} else {
TreeNodeIndex::Parent(ParentNodeIndex::from_tree_index(index))
Expand Down Expand Up @@ -239,7 +239,7 @@ impl TreeSize {
pub(super) fn dec(&mut self) {
debug_assert!(self.0 >= 2);
if self.0 >= 2 {
self.0 = (self.0 + 1) / 2 - 1;
self.0 = self.0.div_ceil(2) - 1;
} else {
self.0 = 0;
}
Expand Down
Loading
Loading