1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
//! # MLS
//!
//! Deriving `SFrame` keys from an [MLS](https://datatracker.ietf.org/doc/html/rfc9420) group as of
//! [RFC 9605 Section 5.2](https://www.rfc-editor.org/rfc/rfc9605.html#name-mls), so a conference
//! does not need to distribute key material of its own.
//!
//! Implement [`MlsExporter`] on top of the MLS library in use, then `derive_from_mls` on the
//! keys of [`crate::key`] exports the base key from the group and derives the `SFrame` key
//! from it.
//!
//! An [`MlsKeyId`] splits the 64 bit `SFrame` Key ID into three fields, so every sender in the
//! group gets its own key id without any further coordination:
//!
//! ```text
//! 64-S-E bits S bits E bits
//! <-----------> <------> <------>
//! +-------------+--------+-------+
//! | Context ID | Index | Epoch |
//! +-------------+--------+-------+
//! ```
//!
//! - **Epoch**: the `E` least significant bits of the MLS epoch, so a key id changes whenever the
//! group does
//! - **Index**: the MLS member index of the sender, the group size must fit into `S` bits
//! - **Context ID**: chosen by the sender, `0` produces the shortest Key ID on the wire
//!
//! How many bits each field gets is fixed for the session by an [`MlsKeyIdBitRange`].
//!
//! ## Example
//!
//! ```rust
//! use sframe::{
//! CipherSuite,
//! key::EncryptionKey,
//! mls::{MlsExporter, MlsKeyId, MlsKeyIdBitRange},
//! };
//!
//! // in a real application this delegates to the MLS library holding the group state
//! struct Group;
//!
//! impl MlsExporter for Group {
//! type BaseKey = Vec<u8>;
//! type Error = std::convert::Infallible;
//!
//! fn export_secret(
//! &self,
//! label: &str,
//! context: &[u8],
//! key_length: usize,
//! ) -> Result<Self::BaseKey, Self::Error> {
//! Ok(vec![0x2a; key_length])
//! }
//! }
//!
//! # fn main() -> sframe::error::Result<()> {
//! // 4 bits of epoch and 4 bits of member index, the rest is context
//! let bit_range = MlsKeyIdBitRange::new(4, 4);
//! // member 3 of the group, at MLS epoch 7
//! let key_id = MlsKeyId::try_new(0u64, 7u64, 3u64, bit_range)?;
//!
//! let key = EncryptionKey::derive_from_mls(CipherSuite::AesGcm256Sha512, &Group, key_id)?;
//!
//! assert_eq!(key_id.member_index(), 3);
//! assert_eq!(key_id.epoch_lsb(), 7);
//! # Ok(())
//! # }
//! ```
use crate::;
use error;
/// definitions of a key id according to [RFC 9605 Section 5.2](https://www.rfc-editor.org/rfc/rfc9605.html#section-5.2)
pub use ;
/// Trait abstraction for an MLS exporter defined in [RFC 9420](https://datatracker.ietf.org/doc/html/rfc9420#exporters).
/// As of [RFC 9605 Section 5.2](https://www.rfc-editor.org/rfc/rfc9605.html#section-5.2) this exporter
/// can be used to derive the `SFrame` keys of [`crate::key`].
mls_key!;
mls_key!;