openmls/group/mls_group/config.rs
1//! Configuration module for [`MlsGroup`] configurations.
2//!
3//! ## Building an MlsGroupCreateConfig
4//! The [`MlsGroupCreateConfigBuilder`] makes it easy to build configurations for the
5//! [`MlsGroup`].
6//!
7//! ```
8//! use openmls::prelude::*;
9//!
10//! let group_config = MlsGroupCreateConfig::builder()
11//! .use_ratchet_tree_extension(true)
12//! .build();
13//! ```
14//!
15//! See [`MlsGroupCreateConfigBuilder`](MlsGroupCreateConfigBuilder#implementations) for
16//! all options that can be configured.
17//!
18//! ### Wire format policies
19//! Only some combination of possible wire formats are valid within OpenMLS.
20//! The [`WIRE_FORMAT_POLICIES`] lists all valid options that can be set.
21//!
22//! ```
23//! use openmls::prelude::*;
24//!
25//! let group_config = MlsGroupCreateConfig::builder()
26//! .wire_format_policy(MIXED_CIPHERTEXT_WIRE_FORMAT_POLICY)
27//! .build();
28//! ```
29
30use super::*;
31use crate::{
32 extensions::Extensions,
33 key_packages::Lifetime,
34 tree::sender_ratchet::SenderRatchetConfiguration,
35 treesync::{errors::LeafNodeValidationError, node::leaf_node::Capabilities},
36};
37use serde::{Deserialize, Serialize};
38
39/// Configures the automatic deletion of past epoch secrets.
40///
41/// **WARNING**
42///
43/// Policies other than `MaxEpochs(0)` enable the storage of message secrets from past epochs.
44/// It is a trade-off between functionality and forward secrecy and should only be enabled
45/// if the Delivery Service cannot guarantee that application messages will be sent in
46/// the same epoch in which they were generated. The number for `max_epochs` should be
47/// as low as possible.
48#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
49pub enum PastEpochDeletionPolicy {
50 /// Keep at most `n` past epoch secrets.
51 MaxEpochs(usize),
52 /// Keep all past epoch secrets.
53 ///
54 /// NOTE: The application is responsible for deleting past epoch secrets when
55 /// `KeepAll` is set. Past epoch secrets can be deleted manually using:
56 /// - [`MlsGroup::delete_past_epoch_secrets()`]
57 KeepAll,
58}
59
60impl Default for PastEpochDeletionPolicy {
61 fn default() -> Self {
62 Self::MaxEpochs(0)
63 }
64}
65
66/// The input to [`MlsGroup::delete_past_epoch_secrets()`].
67///
68/// This struct can be used for manual deletion of past epoch secrets by the application.
69///
70/// An [`MlsGroup`] also applies automatic deletion of past epoch secrets by default.
71///
72/// For more information, see [`PastEpochDeletionPolicy`] and [`MlsGroup::set_past_epoch_deletion_policy()`].
73///
74/// These methods can be used by the application to set up time-based deletion schedules:
75/// - [`PastEpochDeletion::before_timestamp()`]
76/// - [`PastEpochDeletion::older_than_duration()`]
77///
78/// **NOTE**: Epoch secrets that were created using `openmls=0.8.1` or earlier will not yet include a timestamp.
79/// After migration, these may not always be deleted by applying a time-based [`PastEpochDeletion`]. Only if a new secret that does include a timestamp is added later, and it matches the time-based condition in the [`PastEpochDeletion`], all earlier past epoch secrets without timestamps will be deleted, as well. However, otherwise, past epoch secrets without timestamps will not be affected by applying time-based [`PastEpochDeletion`]s.
80///
81/// To manually delete all past epoch secrets without timestamps, see:
82/// [`PastEpochDeletion::delete_all_without_timestamps()`]
83pub struct PastEpochDeletion {
84 pub(crate) config: Option<PastEpochDeletionTimeConfig>,
85 pub(crate) max_past_epochs: Option<usize>,
86}
87
88/// A duration or timestamp before which to delete past epoch secrets.
89pub(crate) enum PastEpochDeletionTimeConfig {
90 OlderThanDuration(std::time::Duration),
91 BeforeTimestamp(std::time::SystemTime),
92 DeleteAllWithoutTimestamp,
93}
94
95impl PastEpochDeletion {
96 /// Delete all past epoch secrets older than a provided duration.
97 pub fn older_than_duration(duration: std::time::Duration) -> Self {
98 Self {
99 config: Some(PastEpochDeletionTimeConfig::OlderThanDuration(duration)),
100 max_past_epochs: None,
101 }
102 }
103
104 /// Delete all past epoch secrets before a provided timestamp.
105 pub fn before_timestamp(timestamp: std::time::SystemTime) -> Self {
106 Self {
107 config: Some(PastEpochDeletionTimeConfig::BeforeTimestamp(timestamp)),
108 max_past_epochs: None,
109 }
110 }
111
112 /// Delete all past epoch secrets without timestamps.
113 ///
114 /// NOTE: This will delete all past epoch secrets having the legacy
115 /// format that does not include a timestamp.
116 pub fn delete_all_without_timestamps() -> Self {
117 Self {
118 config: Some(PastEpochDeletionTimeConfig::DeleteAllWithoutTimestamp),
119 max_past_epochs: None,
120 }
121 }
122
123 /// Delete all past epoch secrets.
124 pub fn delete_all() -> Self {
125 Self {
126 config: None,
127 max_past_epochs: None,
128 }
129 }
130
131 /// Set the number of `max_past_epochs` that should be kept, at most.
132 pub fn max_past_epochs(mut self, max_past_epochs: usize) -> Self {
133 self.max_past_epochs = Some(max_past_epochs);
134 self
135 }
136}
137
138/// Helper deserialization function to ensure that
139/// both plain `usize` and `PastEpochDeletionPolicy`
140/// are correctly deserialized.
141fn deserialize_past_epoch_deletion_policy<'de, D>(
142 deserializer: D,
143) -> Result<PastEpochDeletionPolicy, D::Error>
144where
145 D: serde::Deserializer<'de>,
146{
147 #[derive(Deserialize)]
148 #[serde(untagged)]
149 enum Format {
150 Legacy(usize),
151 Policy(PastEpochDeletionPolicy),
152 }
153
154 let format = Format::deserialize(deserializer)?;
155
156 let policy = match format {
157 Format::Legacy(epochs) => PastEpochDeletionPolicy::MaxEpochs(epochs),
158 Format::Policy(policy) => policy,
159 };
160
161 Ok(policy)
162}
163
164impl PastEpochDeletionPolicy {
165 pub(crate) fn max_epochs(&self) -> Option<usize> {
166 match self {
167 Self::MaxEpochs(epochs) => Some(*epochs),
168 Self::KeepAll => None,
169 }
170 }
171}
172
173/// The [`MlsGroupJoinConfig`] contains all configuration parameters that are
174/// relevant to group operation at runtime. It is used to configure the group's
175/// behaviour when joining an existing group. To configure a newly created
176/// group, use [`MlsGroupCreateConfig`].
177#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
178pub struct MlsGroupJoinConfig {
179 /// Defines the wire format policy for outgoing and incoming handshake messages.
180 /// Application are always encrypted regardless.
181 pub(crate) wire_format_policy: WireFormatPolicy,
182 /// Size of padding in bytes
183 pub(crate) padding_size: usize,
184 /// Maximum number of past epochs for which application messages
185 /// can be decrypted. The default is 0.
186 #[serde(alias = "max_past_epochs")]
187 #[serde(deserialize_with = "deserialize_past_epoch_deletion_policy")]
188 // alias for backwards compatibility after renaming field
189 pub(crate) past_epoch_deletion_policy: PastEpochDeletionPolicy,
190 /// Number of resumption secrets to keep
191 pub(crate) number_of_resumption_psks: usize,
192 /// Flag to indicate the Ratchet Tree Extension should be used
193 pub(crate) use_ratchet_tree_extension: bool,
194 /// Sender ratchet configuration
195 pub(crate) sender_ratchet_configuration: SenderRatchetConfiguration,
196}
197
198impl MlsGroupJoinConfig {
199 /// Returns a builder for [`MlsGroupJoinConfig`].
200 pub fn builder() -> MlsGroupJoinConfigBuilder {
201 MlsGroupJoinConfigBuilder::new()
202 }
203
204 /// Returns the wire format policy set in this [`MlsGroupJoinConfig`].
205 pub fn wire_format_policy(&self) -> WireFormatPolicy {
206 self.wire_format_policy
207 }
208
209 /// Returns the padding size set in this [`MlsGroupJoinConfig`].
210 pub fn padding_size(&self) -> usize {
211 self.padding_size
212 }
213
214 /// Returns the [`SenderRatchetConfiguration`] set in this [`MlsGroupJoinConfig`].
215 pub fn sender_ratchet_configuration(&self) -> &SenderRatchetConfiguration {
216 &self.sender_ratchet_configuration
217 }
218
219 /// Returns the max past epochs configured in this [`MlsGroupJoinConfig`]
220 pub(crate) fn max_past_epochs(&self) -> Option<usize> {
221 self.past_epoch_deletion_policy.max_epochs()
222 }
223
224 pub(crate) fn past_epoch_deletion_policy(&self) -> &PastEpochDeletionPolicy {
225 &self.past_epoch_deletion_policy
226 }
227}
228
229/// Specifies configuration for the creation of an [`MlsGroup`]. Refer to the
230/// [User Manual](https://book.openmls.tech/user_manual/group_config.html) for
231/// more information about the different configuration values.
232#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
233pub struct MlsGroupCreateConfig {
234 /// Capabilities advertised in the creator's leaf node
235 pub(crate) capabilities: Capabilities,
236 /// Lifetime of the own leaf node
237 pub(crate) lifetime: Lifetime,
238 /// Ciphersuite and protocol version
239 pub(crate) ciphersuite: Ciphersuite,
240 /// Configuration parameters relevant to group operation at runtime
241 pub(crate) join_config: MlsGroupJoinConfig,
242 /// List of initial group context extensions
243 pub(crate) group_context_extensions: Extensions<GroupContext>,
244 /// List of initial leaf node extensions
245 pub(crate) leaf_node_extensions: Extensions<LeafNode>,
246}
247
248impl Default for MlsGroupCreateConfig {
249 fn default() -> Self {
250 Self {
251 capabilities: Capabilities::default(),
252 lifetime: Lifetime::default(),
253 ciphersuite: Ciphersuite::MLS_128_DHKEMX25519_AES128GCM_SHA256_Ed25519,
254 join_config: MlsGroupJoinConfig::default(),
255 group_context_extensions: Extensions::default(),
256 leaf_node_extensions: Extensions::default(),
257 }
258 }
259}
260
261/// Builder struct for an [`MlsGroupJoinConfig`].
262#[derive(Default)]
263pub struct MlsGroupJoinConfigBuilder {
264 join_config: MlsGroupJoinConfig,
265}
266
267impl MlsGroupJoinConfigBuilder {
268 /// Creates a new builder with default values.
269 fn new() -> Self {
270 Self {
271 join_config: MlsGroupJoinConfig::default(),
272 }
273 }
274
275 /// Sets the `wire_format` property of the [`MlsGroupJoinConfig`].
276 pub fn wire_format_policy(mut self, wire_format_policy: WireFormatPolicy) -> Self {
277 self.join_config.wire_format_policy = wire_format_policy;
278 self
279 }
280
281 /// Sets the `padding_size` property of the [`MlsGroupJoinConfig`].
282 pub fn padding_size(mut self, padding_size: usize) -> Self {
283 self.join_config.padding_size = padding_size;
284 self
285 }
286
287 /// Sets the `max_past_epochs` property of the [`MlsGroupJoinConfig`].
288 ///
289 /// This method overrides the policy set by [`Self::set_past_epoch_deletion_policy()`],
290 /// and is equivalent to setting the past epoch deletion policy to
291 /// `PastEpochDeletionPolicy::MaxEpochs(max_past_epochs)`.
292 ///
293 /// **WARNING**
294 ///
295 /// This feature enables the storage of message secrets from past epochs.
296 /// It is a trade-off between functionality and forward secrecy and should only be enabled
297 /// if the Delivery Service cannot guarantee that application messages will be sent in
298 /// the same epoch in which they were generated. The number for `max_epochs` should be
299 /// as low as possible.
300 pub fn max_past_epochs(mut self, max_past_epochs: usize) -> Self {
301 self.join_config.past_epoch_deletion_policy =
302 PastEpochDeletionPolicy::MaxEpochs(max_past_epochs);
303 self
304 }
305
306 /// Set the policy for deleting past epoch secrets.
307 ///
308 /// By default, storage of past epoch secrets is disabled.
309 ///
310 /// This method overrides the configuration set by [`Self::max_past_epochs()`].
311 ///
312 /// **WARNING**
313 ///
314 /// This feature enables the storage of message secrets from past epochs.
315 /// It is a trade-off between functionality and forward secrecy and should only be enabled
316 /// if the Delivery Service cannot guarantee that application messages will be sent in
317 /// the same epoch in which they were generated. The number for `max_epochs` should be
318 /// as low as possible.
319 pub fn set_past_epoch_deletion_policy(mut self, policy: PastEpochDeletionPolicy) -> Self {
320 self.join_config.past_epoch_deletion_policy = policy;
321 self
322 }
323
324 /// Sets the `number_of_resumption_psks` property of the [`MlsGroupJoinConfig`].
325 pub fn number_of_resumption_psks(mut self, number_of_resumption_psks: usize) -> Self {
326 self.join_config.number_of_resumption_psks = number_of_resumption_psks;
327 self
328 }
329
330 /// Sets the `use_ratchet_tree_extension` property of the [`MlsGroupJoinConfig`].
331 pub fn use_ratchet_tree_extension(mut self, use_ratchet_tree_extension: bool) -> Self {
332 self.join_config.use_ratchet_tree_extension = use_ratchet_tree_extension;
333 self
334 }
335
336 /// Sets the `sender_ratchet_configuration` property of the [`MlsGroupJoinConfig`].
337 pub fn sender_ratchet_configuration(
338 mut self,
339 sender_ratchet_configuration: SenderRatchetConfiguration,
340 ) -> Self {
341 self.join_config.sender_ratchet_configuration = sender_ratchet_configuration;
342 self
343 }
344
345 /// Finalizes the builder and returns an [`MlsGroupJoinConfig`].
346 pub fn build(self) -> MlsGroupJoinConfig {
347 self.join_config
348 }
349}
350
351impl MlsGroupCreateConfig {
352 /// Returns a builder for [`MlsGroupCreateConfig`]
353 pub fn builder() -> MlsGroupCreateConfigBuilder {
354 MlsGroupCreateConfigBuilder::new()
355 }
356
357 /// Returns the [`MlsGroupCreateConfig`] wire format policy.
358 pub fn wire_format_policy(&self) -> WireFormatPolicy {
359 self.join_config.wire_format_policy
360 }
361
362 /// Returns the [`MlsGroupCreateConfig`] padding size.
363 pub fn padding_size(&self) -> usize {
364 self.join_config.padding_size
365 }
366
367 /// Returns the [`MlsGroupCreateConfig`] max past epochs.
368 pub fn max_past_epochs(&self) -> Option<usize> {
369 self.join_config.max_past_epochs()
370 }
371
372 /// Returns the [`MlsGroupCreateConfig`] number of resumption psks.
373 pub fn number_of_resumption_psks(&self) -> usize {
374 self.join_config.number_of_resumption_psks
375 }
376
377 /// Returns the [`MlsGroupCreateConfig`] boolean flag that indicates whether ratchet_tree_extension should be used.
378 pub fn use_ratchet_tree_extension(&self) -> bool {
379 self.join_config.use_ratchet_tree_extension
380 }
381
382 /// Returns the [`MlsGroupCreateConfig`] sender ratchet configuration.
383 pub fn sender_ratchet_configuration(&self) -> &SenderRatchetConfiguration {
384 &self.join_config.sender_ratchet_configuration
385 }
386
387 /// Returns the [`Extensions`] set as the initial group context.
388 /// This does not contain the initial group context extensions
389 /// added from builder calls to `external_senders` or `required_capabilities`.
390 pub fn group_context_extensions(&self) -> &Extensions<GroupContext> {
391 &self.group_context_extensions
392 }
393
394 /// Returns the [`MlsGroupCreateConfig`] lifetime configuration.
395 pub fn lifetime(&self) -> &Lifetime {
396 &self.lifetime
397 }
398
399 /// Returns the [`Ciphersuite`].
400 pub fn ciphersuite(&self) -> Ciphersuite {
401 self.ciphersuite
402 }
403
404 #[cfg(any(feature = "test-utils", test))]
405 pub fn test_default(ciphersuite: Ciphersuite) -> Self {
406 Self::builder()
407 .wire_format_policy(WireFormatPolicy::new(
408 OutgoingWireFormatPolicy::AlwaysPlaintext,
409 IncomingWireFormatPolicy::Mixed,
410 ))
411 .ciphersuite(ciphersuite)
412 .build()
413 }
414
415 /// Returns the [`MlsGroupJoinConfig`] of groups created with this create config.
416 pub fn join_config(&self) -> &MlsGroupJoinConfig {
417 &self.join_config
418 }
419}
420
421/// Builder for an [`MlsGroupCreateConfig`].
422#[derive(Default, Debug)]
423pub struct MlsGroupCreateConfigBuilder {
424 config: MlsGroupCreateConfig,
425}
426
427impl MlsGroupCreateConfigBuilder {
428 /// Creates a new builder with default values.
429 fn new() -> Self {
430 MlsGroupCreateConfigBuilder {
431 config: MlsGroupCreateConfig::default(),
432 }
433 }
434
435 /// Sets the `wire_format` property of the MlsGroupCreateConfig.
436 pub fn wire_format_policy(mut self, wire_format_policy: WireFormatPolicy) -> Self {
437 self.config.join_config.wire_format_policy = wire_format_policy;
438 self
439 }
440
441 /// Sets the `padding_size` property of the MlsGroupCreateConfig.
442 pub fn padding_size(mut self, padding_size: usize) -> Self {
443 self.config.join_config.padding_size = padding_size;
444 self
445 }
446
447 /// Sets the `max_past_epochs` property of the MlsGroupCreateConfig.
448 /// This allows application messages from previous epochs to be decrypted.
449 ///
450 /// This method overrides the policy set by [`Self::set_past_epoch_deletion_policy()`],
451 /// and is equivalent to setting the past epoch deletion policy to
452 /// `PastEpochDeletionPolicy::MaxEpochs(max_past_epochs)`.
453 ///
454 /// **WARNING**
455 ///
456 /// This feature enables the storage of message secrets from past epochs.
457 /// It is a trade-off between functionality and forward secrecy and should only be enabled
458 /// if the Delivery Service cannot guarantee that application messages will be sent in
459 /// the same epoch in which they were generated. The number for `max_epochs` should be
460 /// as low as possible.
461 pub fn max_past_epochs(mut self, max_past_epochs: usize) -> Self {
462 self.config.join_config.past_epoch_deletion_policy =
463 PastEpochDeletionPolicy::MaxEpochs(max_past_epochs);
464 self
465 }
466
467 /// Set the policy for deleting past epoch secrets.
468 ///
469 /// By default, storage of past epoch secrets is disabled.
470 ///
471 /// This method overrides the configuration set by [`Self::max_past_epochs()`].
472 ///
473 /// **WARNING**
474 ///
475 /// This feature enables the storage of message secrets from past epochs.
476 /// It is a trade-off between functionality and forward secrecy and should only be enabled
477 /// if the Delivery Service cannot guarantee that application messages will be sent in
478 /// the same epoch in which they were generated. The number for `max_epochs` should be
479 /// as low as possible.
480 pub fn set_past_epoch_deletion_policy(mut self, policy: PastEpochDeletionPolicy) -> Self {
481 self.config.join_config.past_epoch_deletion_policy = policy;
482 self
483 }
484
485 /// Sets the `number_of_resumption_psks` property of the MlsGroupCreateConfig.
486 pub fn number_of_resumption_psks(mut self, number_of_resumption_psks: usize) -> Self {
487 self.config.join_config.number_of_resumption_psks = number_of_resumption_psks;
488 self
489 }
490
491 /// Sets the `use_ratchet_tree_extension` property of the MlsGroupCreateConfig.
492 pub fn use_ratchet_tree_extension(mut self, use_ratchet_tree_extension: bool) -> Self {
493 self.config.join_config.use_ratchet_tree_extension = use_ratchet_tree_extension;
494 self
495 }
496
497 /// Sets the `capabilities` of the group creator's leaf node.
498 pub fn capabilities(mut self, capabilities: Capabilities) -> Self {
499 self.config.capabilities = capabilities;
500 self
501 }
502
503 /// Sets the `sender_ratchet_configuration` property of the MlsGroupCreateConfig.
504 /// See [`SenderRatchetConfiguration`] for more information.
505 pub fn sender_ratchet_configuration(
506 mut self,
507 sender_ratchet_configuration: SenderRatchetConfiguration,
508 ) -> Self {
509 self.config.join_config.sender_ratchet_configuration = sender_ratchet_configuration;
510 self
511 }
512
513 /// Sets the `lifetime` property of the MlsGroupCreateConfig.
514 pub fn lifetime(mut self, lifetime: Lifetime) -> Self {
515 self.config.lifetime = lifetime;
516 self
517 }
518
519 /// Sets the `ciphersuite` property of the MlsGroupCreateConfig.
520 pub fn ciphersuite(mut self, ciphersuite: Ciphersuite) -> Self {
521 self.config.ciphersuite = ciphersuite;
522 self
523 }
524
525 /// Sets initial group context extensions.
526 pub fn with_group_context_extensions(mut self, extensions: Extensions<GroupContext>) -> Self {
527 self.config.group_context_extensions = extensions;
528 self
529 }
530
531 /// Sets extensions of the group creator's [`LeafNode`].
532 ///
533 /// Returns an error if the extension types are not valid in a leaf node.
534 pub fn with_leaf_node_extensions(
535 mut self,
536 extensions: Extensions<LeafNode>,
537 ) -> Result<Self, LeafNodeValidationError> {
538 // Make sure that the extension type is supported in this context.
539 // This means that the leaf node needs to have support listed in the
540 // the capabilities (https://validation.openmls.tech/#valn0107).
541 if !self.config.capabilities.contains_extensions(&extensions) {
542 return Err(LeafNodeValidationError::ExtensionsNotInCapabilities);
543 }
544
545 // Note that the extensions have already been checked to be allowed here.
546 self.config.leaf_node_extensions = extensions;
547 Ok(self)
548 }
549
550 /// Finalizes the builder and returns an [`MlsGroupCreateConfig`].
551 pub fn build(self) -> MlsGroupCreateConfig {
552 self.config
553 }
554}
555
556/// Defines what wire format is acceptable for incoming handshake messages.
557/// Note that application messages must always be encrypted.
558#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
559pub enum IncomingWireFormatPolicy {
560 /// Handshake messages must always be PrivateMessage
561 AlwaysCiphertext,
562 /// Handshake messages must always be PublicMessage
563 AlwaysPlaintext,
564 /// Handshake messages can either be PrivateMessage or PublicMessage
565 Mixed,
566}
567
568impl IncomingWireFormatPolicy {
569 pub(crate) fn is_compatible_with(&self, wire_format: WireFormat) -> bool {
570 match self {
571 IncomingWireFormatPolicy::AlwaysCiphertext => wire_format == WireFormat::PrivateMessage,
572 IncomingWireFormatPolicy::AlwaysPlaintext => wire_format == WireFormat::PublicMessage,
573 IncomingWireFormatPolicy::Mixed => {
574 wire_format == WireFormat::PrivateMessage
575 || wire_format == WireFormat::PublicMessage
576 }
577 }
578 }
579}
580
581/// Defines what wire format should be used for outgoing handshake messages.
582/// Note that application messages must always be encrypted.
583#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
584pub enum OutgoingWireFormatPolicy {
585 /// Handshake messages must always be PrivateMessage
586 AlwaysCiphertext,
587 /// Handshake messages must always be PublicMessage
588 AlwaysPlaintext,
589}
590
591/// Defines what wire format is desired for outgoing handshake messages.
592/// Note that application messages must always be encrypted.
593#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
594pub struct WireFormatPolicy {
595 outgoing: OutgoingWireFormatPolicy,
596 incoming: IncomingWireFormatPolicy,
597}
598
599impl WireFormatPolicy {
600 /// Creates a new wire format policy from an [`OutgoingWireFormatPolicy`]
601 /// and an [`IncomingWireFormatPolicy`].
602 #[cfg(any(feature = "test-utils", test))]
603 pub(crate) fn new(
604 outgoing: OutgoingWireFormatPolicy,
605 incoming: IncomingWireFormatPolicy,
606 ) -> Self {
607 Self { outgoing, incoming }
608 }
609
610 /// Returns a reference to the wire format policy's outgoing wire format policy.
611 pub fn outgoing(&self) -> OutgoingWireFormatPolicy {
612 self.outgoing
613 }
614
615 /// Returns a reference to the wire format policy's incoming wire format policy.
616 pub fn incoming(&self) -> IncomingWireFormatPolicy {
617 self.incoming
618 }
619}
620
621impl Default for WireFormatPolicy {
622 fn default() -> Self {
623 PURE_CIPHERTEXT_WIRE_FORMAT_POLICY
624 }
625}
626
627impl From<OutgoingWireFormatPolicy> for WireFormat {
628 fn from(outgoing: OutgoingWireFormatPolicy) -> Self {
629 match outgoing {
630 OutgoingWireFormatPolicy::AlwaysCiphertext => WireFormat::PrivateMessage,
631 OutgoingWireFormatPolicy::AlwaysPlaintext => WireFormat::PublicMessage,
632 }
633 }
634}
635
636/// All valid wire format policy combinations.
637/// - [`PURE_PLAINTEXT_WIRE_FORMAT_POLICY`]
638/// - [`PURE_CIPHERTEXT_WIRE_FORMAT_POLICY`]
639/// - [`MIXED_PLAINTEXT_WIRE_FORMAT_POLICY`]
640/// - [`MIXED_CIPHERTEXT_WIRE_FORMAT_POLICY`]
641pub const WIRE_FORMAT_POLICIES: [WireFormatPolicy; 4] = [
642 PURE_PLAINTEXT_WIRE_FORMAT_POLICY,
643 PURE_CIPHERTEXT_WIRE_FORMAT_POLICY,
644 MIXED_PLAINTEXT_WIRE_FORMAT_POLICY,
645 MIXED_CIPHERTEXT_WIRE_FORMAT_POLICY,
646];
647
648/// Incoming and outgoing wire formats are always plaintext.
649pub const PURE_PLAINTEXT_WIRE_FORMAT_POLICY: WireFormatPolicy = WireFormatPolicy {
650 outgoing: OutgoingWireFormatPolicy::AlwaysPlaintext,
651 incoming: IncomingWireFormatPolicy::AlwaysPlaintext,
652};
653
654/// Incoming and outgoing wire formats are always ciphertext.
655pub const PURE_CIPHERTEXT_WIRE_FORMAT_POLICY: WireFormatPolicy = WireFormatPolicy {
656 outgoing: OutgoingWireFormatPolicy::AlwaysCiphertext,
657 incoming: IncomingWireFormatPolicy::AlwaysCiphertext,
658};
659
660/// Incoming wire formats can be mixed while outgoing wire formats are always
661/// plaintext.
662pub const MIXED_PLAINTEXT_WIRE_FORMAT_POLICY: WireFormatPolicy = WireFormatPolicy {
663 outgoing: OutgoingWireFormatPolicy::AlwaysPlaintext,
664 incoming: IncomingWireFormatPolicy::Mixed,
665};
666
667/// Incoming wire formats can be mixed while outgoing wire formats are always
668/// ciphertext.
669pub const MIXED_CIPHERTEXT_WIRE_FORMAT_POLICY: WireFormatPolicy = WireFormatPolicy {
670 outgoing: OutgoingWireFormatPolicy::AlwaysCiphertext,
671 incoming: IncomingWireFormatPolicy::Mixed,
672};