awslabs / mls-rs

An implementation of Messaging Layer Security (RFC 9420)
Apache License 2.0
104 stars 19 forks source link

Add a Replace proposal #170

Open bifurcation opened 5 months ago

bifurcation commented 5 months ago

Description of feature:

The proposal here is to add a Replace proposal of the following form:

struct {
    uint32 leaf_index;
    LeafNode leaf_node;
} Replace;

The semantic of this proposal would be the same as an Update from the member at leaf_index with the indicated leaf_node. In particular, the proposal validation rules and identity continuity rules would apply in the same way, mutatis mutandis. But of course, it could be sent by someone other than the updating member.

@mulmarta notes that this mechanism could be used to "roll back" a member to an earlier (possibly compromised) state. We could mitigate this risk by adding a leaf_node_version extension carrying a uint32 counter and requiring that Updates/Replaces increase this counter.

Use case:

MLS proposals have to be committed in the epoch in which they are sent, but the asynchronous nature of MLS operations means that the Commit advancing from epoch N to epoch N+1 might not include some proposals sent in epoch N. For Add and Remove proposals, the committer can "re-originate" the proposals as inline proposals with the commit. For Update, however, this is not possible, since the location of the replaced leaf is determined by the sender of the proposal. This slows down PCS, since the sender might have to re-send an Update, potentially multiple times.

Implementation discussion (Optional)

The implementation of this feature should parallel the implementation of the Update proposal. I have begun hacking a little bit, and aside from understanding the whole flow of proposal generation, validation, and application, the main challenging thing I have seen so far is managing the caching of the secrets corresponding to a LeafNode. Right now, since we know an Update will never be applied after the Commit for its epoch is received, we can erase the cached secrets when advancing from the epoch. Here, the lifetime of the secrets can span epochs, so we would need some story for how they are deleted.