Expand description

This module represents the key schedule as introduced in Section 8 of the MLS specification. The key schedule evolves in epochs, where in each epoch new key material is injected.

The flow of the key schedule is as follows (from Section 8 of the MLS specification):

                 init_secret_[n-1]
                        |
                        V
   commit_secret -> KDF.Extract
                        |
                        V
                  DeriveSecret(., "joiner")
                        |
                        V
                   joiner_secret
                        |
                        V
psk_secret (or 0) -> KDF.Extract (= intermediary_secret)
                        |
                        +--> DeriveSecret(., "welcome")
                        |    = welcome_secret
                        |
                        V
                  ExpandWithLabel(., "epoch", GroupContext_[n], KDF.Nh)
                        |
                        V
                   epoch_secret
                        |
                        +--> DeriveSecret(., <label>)
                        |    = <secret>
                        |
                        V
                  DeriveSecret(., "init")
                        |
                        V
                  init_secret_[n]

Each of the secrets in the key schedule (with exception of the welcome_secret) is represented by its own struct to ensure that the keys are not confused with one-another and/or that the schedule is not derived out-of-order.

The real key schedules

The key schedule as described in the spec isn’t really one key schedule. The joiner_secret is an intermediate value and an output value. This must never be the case within a key schedule. The actual key schedule is therefore only the second half starting with the joiner_secret, which indeed is what happens when starting a group from a welcome message.

The joiner_secret is computed as

    DeriveSecret(KDF.Extract(init_secret_[n-1], commit_secret), "joiner")

or

                 init_secret_[n-1]
                        |
                        V
   commit_secret -> KDF.Extract
                        |
                        V
                  DeriveSecret(., "joiner")
                        |
                        V
                   joiner_secret

The remainder of the key schedule then starts with the joiner_secret and psk_secret. Note that the following graph also adds the GroupContext_[n] as input, which is omitted in the spec. Further note that the derivation of the secrets from the epoch_secret is simplified here.

                   joiner_secret
                        |
                        V
psk_secret (or 0) -> KDF.Extract
                        |
                        +--> DeriveSecret(., "welcome")
                        |    = welcome_secret
                        |
                        V
GroupContext_[n] -> ExpandWithLabel(., "epoch", GroupContext_[n], KDF.Nh)
                        |
                        V
                   epoch_secret
                        |
                        v
                DeriveSecret(., <label>)
                    = <secret>

with

| secret                  | label           |
|:------------------------|:----------------|
| `init_secret`           | "init"          |
| `sender_data_secret`    | "sender data"   |
| `encryption_secret`     | "encryption"    |
| `exporter_secret`       | "exporter"      |
| `authentication_secret` | "authentication"|
| `external_secret`       | "external"      |
| `confirmation_key`      | "confirm"       |
| `membership_key`        | "membership"    |
| `resumption_secret`     | "resumption"    |

Don’t Panic!

Functions in this module should never panic. However, if there is a bug in the implementation, a function will return an unrecoverable LibraryError. This means that some functions that are not expected to fail and throw an error, will still return a Result since they may throw a LibraryError.

Re-exports

pub use errors::*;

Modules

TLS codec implementation for preshared keys.

Key schedule errors.

Structs

The confirmation key is used to calculate the ConfirmationTag.

The membership key is used to calculate the MembershipTag.

A secret used in cross-group operations.

A key that can be used to derive an AeadKey and an AeadNonce.