Skip to content

Commit

Permalink
Merge pull request #25 from xmtp/openmls-main
Browse files Browse the repository at this point in the history
Upstream main into main
  • Loading branch information
nplasterer authored May 12, 2024
2 parents 52cad0e + 38744b3 commit dcaef4c
Show file tree
Hide file tree
Showing 197 changed files with 9,248 additions and 5,125 deletions.
15 changes: 15 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,18 @@ jobs:
- name: Build
if: ${{ matrix.arch != 'wasm32-unknown-unknown' }}
run: cargo build $TEST_MODE --verbose --target ${{ matrix.arch }} -p openmls

# Check feature powerset
check:
strategy:
fail-fast: false

runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- uses: taiki-e/install-action@cargo-hack

- name: Cargo hack
run: cargo hack check --feature-powerset --no-dev-deps --verbose -p openmls
1 change: 1 addition & 0 deletions .github/workflows/coverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ jobs:
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'
LIBCRUX_DISABLE_SIMD256: '1'

- name: Run grcov
id: coverage
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/gh-pages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- name: Setup mdBook
uses: peaceiris/actions-mdbook@v1
uses: peaceiris/actions-mdbook@v2
with:
mdbook-version: 'latest'
- name: Build docs
Expand All @@ -43,7 +43,7 @@ jobs:
</html>
EOF
- name: Deploy docs to GitHub Pages
uses: peaceiris/actions-gh-pages@v3
uses: peaceiris/actions-gh-pages@v4
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: temp_docs
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- [#1479](https://github.com/openmls/openmls/pull/1479): Allow the use of extensions with `ExtensionType::Unknown` in group context, key packages and leaf nodes
- [#1488](https://github.com/openmls/openmls/pull/1488): Allow unknown credentials. Credentials other than the basic credential or X.509 may be used now as long as they are encoded as variable-sized vectors.
- [#1527](https://github.com/openmls/openmls/pull/1527): CredentialType::Unknown is now called CredentialType::Other.
- [#1543](https://github.com/openmls/openmls/pull/1543): PreSharedKeyId.write_to_key_store() no longer requires the cipher suite.
- [#1546](https://github.com/openmls/openmls/pull/1546): Add experimental ciphersuite based on the PQ-secure XWing hybrid KEM (currently supported only by the libcrux crypto provider).
- [#1548](https://github.com/openmls/openmls/pull/1548): CryptoConfig is now replaced by just Ciphersuite.
- [#1542](https://github.com/openmls/openmls/pull/1542): Add support for custom proposals. ProposalType::Unknown is now called ProposalType::Other. Proposal::Unknown is now called Proposal::Other.
- [#1559](https://github.com/openmls/openmls/pull/1559): Remove the `PartialEq` type constraint on the error type of both the `OpenMlsRand` and `OpenMlsKeyStore` traits. Additionally, remove the `Clone` type constraint on the error type of the `OpenMlsRand` trait.

### Fixed

Expand Down
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@ members = [
"fuzz",
"cli",
"interop_client",
"memory_keystore",
"memory_storage",
"delivery-service/ds",
"delivery-service/ds-lib",
"basic_credential",
"openmls-wasm",
"openmls_test",
]
resolver = "2"

Expand Down
49 changes: 37 additions & 12 deletions basic_credential/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,15 @@
use std::fmt::Debug;

use openmls_traits::{
key_store::{MlsEntity, MlsEntityId, OpenMlsKeyStore},
signatures::{Signer, SignerError},
storage::{self, StorageProvider, CURRENT_VERSION},
types::{CryptoError, SignatureScheme},
};

use p256::ecdsa::{signature::Signer as P256Signer, Signature, SigningKey};

use rand::rngs::OsRng;
use serde::{Deserialize, Serialize};
use tls_codec::{TlsDeserialize, TlsDeserializeBytes, TlsSerialize, TlsSize};

/// A signature key pair for the basic credential.
Expand Down Expand Up @@ -75,10 +76,6 @@ fn id(public_key: &[u8], signature_scheme: SignatureScheme) -> Vec<u8> {
id
}

impl MlsEntity for SignatureKeyPair {
const ID: MlsEntityId = MlsEntityId::SignatureKeyPair;
}

impl SignatureKeyPair {
/// Generates a fresh signature keypair using the [`SignatureScheme`].
pub fn new(signature_scheme: SignatureScheme) -> Result<Self, CryptoError> {
Expand Down Expand Up @@ -112,25 +109,32 @@ impl SignatureKeyPair {
}
}

fn id(&self) -> Vec<u8> {
id(&self.public, self.signature_scheme)
fn id(&self) -> StorageId {
StorageId {
value: id(&self.public, self.signature_scheme),
}
}

/// Store this signature key pair in the key store.
pub fn store<T>(&self, key_store: &T) -> Result<(), <T as OpenMlsKeyStore>::Error>
pub fn store<T>(&self, store: &T) -> Result<(), T::Error>
where
T: OpenMlsKeyStore,
T: StorageProvider<CURRENT_VERSION>,
{
key_store.store(&self.id(), self)
store.write_signature_key_pair(&self.id(), self)
}

/// Read a signature key pair from the key store.
pub fn read(
key_store: &impl OpenMlsKeyStore,
store: &impl StorageProvider<CURRENT_VERSION>,
public_key: &[u8],
signature_scheme: SignatureScheme,
) -> Option<Self> {
key_store.read(&id(public_key, signature_scheme))
store
.signature_key_pair(&StorageId {
value: id(public_key, signature_scheme),
})
.ok()
.flatten()
}

/// Get the public key as byte slice.
Expand All @@ -153,3 +157,24 @@ impl SignatureKeyPair {
&self.private
}
}

// Storage

#[derive(Debug, Serialize, Deserialize)]
pub struct StorageId {
value: Vec<u8>,
}

impl From<Vec<u8>> for StorageId {
fn from(vec: Vec<u8>) -> Self {
StorageId { value: vec }
}
}

// Implement key traits for the storage id
impl storage::Key<CURRENT_VERSION> for StorageId {}
impl storage::traits::SignaturePublicKey<CURRENT_VERSION> for StorageId {}

// Implement entity trait for the signature key pair
impl storage::Entity<CURRENT_VERSION> for SignatureKeyPair {}
impl storage::traits::SignatureKeyPair<CURRENT_VERSION> for SignatureKeyPair {}
1 change: 1 addition & 0 deletions book/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
- [Removing members from a group](user_manual/remove_members.md)
- [Updating own key package](user_manual/updates.md)
- [Leaving a group](user_manual/leaving.md)
- [Custom proposals](user_manual/custom_proposals.md)
- [Creating application messages](user_manual/application_messages.md)
- [Committing to pending proposals](user_manual/commit_to_proposals.md)
- [Processing incoming messages](user_manual/processing.md)
Expand Down
1 change: 1 addition & 0 deletions book/src/message_validation.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ The following is a list of the individual semantic validation steps performed by
| `ValSem110` | Update Proposal: Encryption key must be unique among proposals & members ||| `openmls/src/group/tests/test_proposal_validation.rs` |
| `ValSem111` | Update Proposal: The sender of a full Commit must not include own update proposals ||| `openmls/src/group/tests/test_proposal_validation.rs` |
| `ValSem112` | Update Proposal: The sender of a standalone update proposal must be of type member ||| `openmls/src/group/tests/test_proposal_validation.rs` |
| `ValSem113` | All Proposals: The proposal type must be supported by all members of the group ||| `openmls/src/group/tests/test_proposal_validation.rs` |

### Commit message validation

Expand Down
23 changes: 11 additions & 12 deletions book/src/traits/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,31 +10,30 @@ enclaves.
- [Traits](./traits.md)
- [External Types](./types.md)

## Using the key store
## Using storage

The key store is probably one of the most interesting traits because applications
The store is probably one of the most interesting traits because applications
that use OpenMLS will interact with it.
See the [OpenMlsKeyStore trait](./traits.md#openmlskeystore) description for details
but note that the key used to store, read, and delete values in the key store has
to be provided as a byte slice.
See the [StorageProvider trait](./traits.md#storageprovider) description for details.

In the following examples, we have a `ciphersuite` and a `provider` (`OpenMlsCryptoProvider`).
In the following examples, we have a `ciphersuite` and a `provider` (`OpenMlsProvider`).

```rust,no_run,noplayground
{{#include ../../../openmls/tests/key_store.rs:key_store_store}}
{{#include ../../../openmls/tests/store.rs:store_store}}
```

The `delete` is called with the identifier to delete a value.
Retrieving a value from the store is as simple as calling `read`.
The retrieved key package bundles the private keys for the init and encryption keys
as well.

```rust,no_run,noplayground
{{#include ../../../openmls/tests/key_store.rs:key_store_delete}}
{{#include ../../../openmls/tests/store.rs:store_read}}
```

Retrieving a value from the key store is as simple as calling `read`.
In this example, we assume we got a `credential` where we want to retrieve the credential bundle, i.e., the private key material.
The `delete` is called with the identifier to delete a value.

```rust,no_run,noplayground
{{#include ../../../openmls/tests/key_store.rs:key_store_read}}
{{#include ../../../openmls/tests/store.rs:store_delete}}
```

[//]: # "links"
Expand Down
73 changes: 66 additions & 7 deletions book/src/traits/traits.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,21 +52,80 @@ This trait defines all cryptographic functions required by OpenMLS. In particula
{{#include ../../../traits/src/crypto.rs:10}}
```

### OpenMlsKeyStore
### StorageProvider

This trait defines a CRUD API for a key store that is used to store long-term
key material from OpenMLS.
This trait defines an API for a storage backend that is used for all OpenMLS
persistence.

The key store provides functions to `store`, `read`, and `delete` values.
The store provides functions to `store`, `read`, and `delete` values.
Note that it does not allow updating values.
Instead, entries must be deleted and newly stored.

```rust,no_run,noplayground
{{#include ../../../traits/src/key_store.rs:15:40}}
{{#include ../../../traits/src/storage.rs:16:25}}
```

**NOTE:** Right now, key material must be extracted from the key store.
This will most likely change in the future.
The trait is generic over a `VERSION`, which is used to ensure that the values
that are persisted can be upgraded when OpenMLS changes the stored structs.

Every function takes `Key` and `Value` arguments.

```rust,no_run,noplayground
{{#include ../../../traits/src/storage.rs:key_trait}}
```

```rust,no_run,noplayground
{{#include ../../../traits/src/storage.rs:entity_trait}}
```

To ensure that each function takes the correct input, they use trait bounds.
These are the available traits.

```rust,no_run,noplayground
{{#include ../../../traits/src/storage.rs:traits}}
```

An implementation of the storage trait should ensure that it can address and
efficiently handle values.

#### Example: Key packages

This is only an example, but it illustrates that the application may need to do more
when it comes to implementing storage.

Key packages are only deleted by OpenMLS when they are used and _not_ last resort
key packages (which may be used multiple times).
The application needs to implement some logic to manage last resort key packages.

```rust,no_run,noplayground
{{#include ../../../traits/src/storage.rs:write_key_package}}
```

The application may store the hash references in a separate list with a validity
period.

```rust,ro_run,noplayground
fn write_key_package<
HashReference: traits::HashReference<VERSION>,
KeyPackage: traits::KeyPackage<VERSION>,
>(
&self,
hash_ref: &HashReference,
key_package: &KeyPackage,
) -> Result<(), Self::Error> {
// Get the validity from the application in some way.
let validity = self.get_validity(hash_ref);
// Store the reference and its validity period.
self.store_hash_ref(hash_ref, validity);
// Store the actual key package.
self.store_key_package(hash_ref, key_package);
}
```

This allows the application to iterate over the hash references and delete outdated
key packages.

### OpenMlsCryptoProvider

Expand Down
15 changes: 15 additions & 0 deletions book/src/user_manual/custom_proposals.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Custom proposals

OpenMLS allows the creation and use of application-defined proposals. To create such a proposal, the application needs to define a Proposal Type in such a way that its value doesn't collide with any Proposal Types defined in Section 17.4. of RFC 9420. If the proposal is meant to be used only inside of a particular application, the value of the Proposal Type is recommended to be in the range between `0xF000` and `0xFFFF`, as that range is reserved for private use.

Custom proposals can contain arbitrary octet-strings as defined by the application. Any policy decisions based on custom proposals will have to be made by the application, such as the decision to include a given custom proposal in a commit, or whether to accept a commit that includes one or more custom proposals. To decide the latter, applications can inspect the queued proposals in a `ProcessedMessageContent::StagedCommitMesage(staged_commit)`.

Example on how to use custom proposals:

```rust,no_run,noplayground
{{#include ../../../openmls/tests/book_code.rs:custom_proposal_type}}
```

```rust,no_run,noplayground
{{#include ../../../openmls/tests/book_code.rs:custom_proposal_usage}}
```
4 changes: 3 additions & 1 deletion cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ openmls = { path = "../openmls", features = ["test-utils"] }
ds-lib = { path = "../delivery-service/ds-lib" }
openmls_traits = { path = "../traits" }
openmls_rust_crypto = { path = "../openmls_rust_crypto" }
openmls_memory_keystore = { path = "../memory_keystore" }
openmls_memory_storage = { path = "../memory_storage", features = [
"persistence",
] }
openmls_basic_credential = { path = "../basic_credential" }
serde = { version = "^1.0" }
thiserror = "1.0"
Expand Down
Loading

0 comments on commit dcaef4c

Please sign in to comment.