Group configuration

Two very similar structs can help configure groups upon their creation: MlsGroupJoinConfig and MlsGroupCreateConfig.

MlsGroupJoinConfig contains the following runtime-relevant configuration options for an MlsGroup and can be set on a per-client basis when a group is joined.

NameTypeExplanation
wire_format_policyWireFormatPolicyDefines the wire format policy for outgoing and incoming handshake messages.
padding_sizeusizeSize of padding in bytes. The default is 0.
max_past_epochsusizeMaximum number of past epochs for which application messages can be decrypted. The default is 0.
number_of_resumption_psksusizeNumber of resumption psks to keep. The default is 0.
use_ratchet_tree_extensionboolFlag indicating the Ratchet Tree Extension should be used. The default is false.
sender_ratchet_configurationSenderRatchetConfigurationSender ratchet configuration.

MlsGroupCreateConfig contains an MlsGroupJoinConfig, as well as a few additional parameters that are part of the group state that is agreed-upon by all group members. It can be set at the time of a group's creation and contains the following additional configuration options.

NameTypeExplanation
group_context_extensionsExtensionsOptional group-level extensions, e.g. RequiredCapabilitiesExtension.
capabilities .CapabilitiesLists the capabilities of the group's creator.
leaf_extensions .ExtensionsExtensions to be included in the group creator's leaf

Both ways of group configurations can be specified by using the struct's builder pattern, or choosing their default values. The default value contains safe values for all parameters and is suitable for scenarios without particular requirements.

Example join configuration:

    let mls_group_config = MlsGroupJoinConfig::builder()
        .padding_size(100)
        .sender_ratchet_configuration(SenderRatchetConfiguration::new(
            10,   // out_of_order_tolerance
            2000, // maximum_forward_distance
        ))
        .use_ratchet_tree_extension(true)
        .build();

Example create configuration:

    let mls_group_create_config = MlsGroupCreateConfig::builder()
        .padding_size(100)
        .sender_ratchet_configuration(SenderRatchetConfiguration::new(
            10,   // out_of_order_tolerance
            2000, // maximum_forward_distance
        ))
        .with_group_context_extensions(Extensions::single(Extension::ExternalSenders(vec![
            ExternalSender::new(
                ds_credential_with_key.signature_key.clone(),
                ds_credential_with_key.credential.clone(),
            ),
        ])))
        .expect("error adding external senders extension to group context extensions")
        .ciphersuite(ciphersuite)
        .capabilities(Capabilities::new(
            None, // Defaults to the group's protocol version
            None, // Defaults to the group's ciphersuite
            None, // Defaults to all basic extension types
            None, // Defaults to all basic proposal types
            Some(&[CredentialType::Basic]),
        ))
        // Example leaf extension
        .with_leaf_node_extensions(Extensions::single(Extension::Unknown(
            0xff00,
            UnknownExtension(vec![0, 1, 2, 3]),
        )))
        .expect("failed to configure leaf extensions")
        .use_ratchet_tree_extension(true)
        .build();

Unknown extensions

Some extensions carry data, but don't alter the behaviour of the protocol (e.g. the application_id extension). OpenMLS allows the use of arbitrary such extensions in the group context, key packages and leaf nodes. Such extensions can be instantiated and retrieved through the use of the UnknownExtension struct and the ExtensionType::Unknown extension type. Such "unknown" extensions are handled transparently by OpenMLS, but can be used by the application, e.g. to have a group agree on pieces of data.