openmls/treesync/node/
leaf_node.rs

1//! This module contains the [`LeafNode`] struct and its implementation.
2use openmls_traits::{
3    crypto::OpenMlsCrypto, random::OpenMlsRand, signatures::Signer, types::Ciphersuite,
4};
5use serde::{Deserialize, Serialize};
6use thiserror::Error;
7use tls_codec::{
8    Serialize as TlsSerializeTrait, TlsDeserialize, TlsDeserializeBytes, TlsSerialize, TlsSize,
9    VLBytes,
10};
11
12use super::encryption_keys::{EncryptionKey, EncryptionKeyPair};
13use crate::{
14    binary_tree::array_representation::LeafNodeIndex,
15    ciphersuite::{
16        signable::{Signable, SignedStruct, Verifiable, VerifiedStruct},
17        Signature, SignaturePublicKey,
18    },
19    credentials::{Credential, CredentialType, CredentialWithKey},
20    error::LibraryError,
21    extensions::{ExtensionType, Extensions},
22    group::GroupId,
23    key_packages::{KeyPackage, Lifetime},
24    prelude::KeyPackageBundle,
25    storage::OpenMlsProvider,
26};
27
28use crate::treesync::errors::LeafNodeValidationError;
29
30mod capabilities;
31mod codec;
32
33pub use capabilities::*;
34
35pub(crate) struct NewLeafNodeParams {
36    pub(crate) ciphersuite: Ciphersuite,
37    pub(crate) credential_with_key: CredentialWithKey,
38    pub(crate) leaf_node_source: LeafNodeSource,
39    pub(crate) capabilities: Capabilities,
40    pub(crate) extensions: Extensions,
41    pub(crate) tree_info_tbs: TreeInfoTbs,
42}
43
44/// Set of LeafNode parameters that are used when regenerating a LeafNodes
45/// during an update operation.
46#[derive(Debug, PartialEq, Clone)]
47pub(crate) struct UpdateLeafNodeParams {
48    pub(crate) credential_with_key: CredentialWithKey,
49    pub(crate) capabilities: Capabilities,
50    pub(crate) extensions: Extensions,
51}
52
53impl UpdateLeafNodeParams {
54    #[cfg(test)]
55    pub(crate) fn derive(leaf_node: &LeafNode) -> Self {
56        Self {
57            credential_with_key: CredentialWithKey {
58                credential: leaf_node.payload.credential.clone(),
59                signature_key: leaf_node.payload.signature_key.clone(),
60            },
61            capabilities: leaf_node.payload.capabilities.clone(),
62            extensions: leaf_node.payload.extensions.clone(),
63        }
64    }
65}
66
67/// Parameters for a leaf node that can be chosen by the application.
68#[derive(Debug, PartialEq, Clone, Default)]
69pub struct LeafNodeParameters {
70    credential_with_key: Option<CredentialWithKey>,
71    capabilities: Option<Capabilities>,
72    extensions: Option<Extensions>,
73}
74
75impl LeafNodeParameters {
76    /// Create a new [`LeafNodeParametersBuilder`].
77    pub fn builder() -> LeafNodeParametersBuilder {
78        LeafNodeParametersBuilder::default()
79    }
80
81    /// Returns the credential with key.
82    pub fn credential_with_key(&self) -> Option<&CredentialWithKey> {
83        self.credential_with_key.as_ref()
84    }
85
86    /// Returns the capabilities.
87    pub fn capabilities(&self) -> Option<&Capabilities> {
88        self.capabilities.as_ref()
89    }
90
91    /// Returns the extensions.
92    pub fn extensions(&self) -> Option<&Extensions> {
93        self.extensions.as_ref()
94    }
95
96    pub(crate) fn is_empty(&self) -> bool {
97        self.credential_with_key.is_none()
98            && self.capabilities.is_none()
99            && self.extensions.is_none()
100    }
101
102    pub(crate) fn set_credential_with_key(&mut self, credential_with_key: CredentialWithKey) {
103        self.credential_with_key = Some(credential_with_key);
104    }
105}
106
107/// Builder for [`LeafNodeParameters`].
108#[derive(Debug, Default)]
109pub struct LeafNodeParametersBuilder {
110    credential_with_key: Option<CredentialWithKey>,
111    capabilities: Option<Capabilities>,
112    extensions: Option<Extensions>,
113}
114
115impl LeafNodeParametersBuilder {
116    /// Set the credential with key.
117    pub fn with_credential_with_key(mut self, credential_with_key: CredentialWithKey) -> Self {
118        self.credential_with_key = Some(credential_with_key);
119        self
120    }
121
122    /// Set the capabilities.
123    pub fn with_capabilities(mut self, capabilities: Capabilities) -> Self {
124        self.capabilities = Some(capabilities);
125        self
126    }
127
128    /// Set the extensions.
129    pub fn with_extensions(mut self, extensions: Extensions) -> Self {
130        self.extensions = Some(extensions);
131        self
132    }
133
134    /// Build the [`LeafNodeParameters`].
135    pub fn build(self) -> LeafNodeParameters {
136        LeafNodeParameters {
137            credential_with_key: self.credential_with_key,
138            capabilities: self.capabilities,
139            extensions: self.extensions,
140        }
141    }
142}
143
144/// This struct implements the MLS leaf node.
145///
146/// ```c
147/// // draft-ietf-mls-protocol-17
148/// struct {
149///     HPKEPublicKey encryption_key;
150///     SignaturePublicKey signature_key;
151///     Credential credential;
152///     Capabilities capabilities;
153///
154///     LeafNodeSource leaf_node_source;
155///     select (LeafNode.leaf_node_source) {
156///         case key_package:
157///             Lifetime lifetime;
158///
159///         case update:
160///             struct{};
161///
162///         case commit:
163///             opaque parent_hash<V>;
164///     };
165///
166///     Extension extensions<V>;
167///     /* SignWithLabel(., "LeafNodeTBS", LeafNodeTBS) */
168///     opaque signature<V>;
169/// } LeafNode;
170/// ```
171#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, TlsSerialize, TlsSize)]
172pub struct LeafNode {
173    payload: LeafNodePayload,
174    signature: Signature,
175}
176
177impl LeafNode {
178    /// Create a new [`LeafNode`].
179    /// This first creates a `LeadNodeTbs` and returns the result of signing
180    /// it.
181    ///
182    /// This function generates a fresh HPKE key pair for the leaf node and
183    /// returns the HPKE key pair along with the new leaf node.
184    /// The caller is responsible for storing the private key.
185    pub(crate) fn new(
186        provider: &impl OpenMlsProvider,
187        signer: &impl Signer,
188        new_leaf_node_params: NewLeafNodeParams,
189    ) -> Result<(Self, EncryptionKeyPair), LibraryError> {
190        let NewLeafNodeParams {
191            ciphersuite,
192            credential_with_key,
193            leaf_node_source,
194            capabilities,
195            extensions,
196            tree_info_tbs,
197        } = new_leaf_node_params;
198
199        // Create a new encryption key pair.
200        let encryption_key_pair =
201            EncryptionKeyPair::random(provider.rand(), provider.crypto(), ciphersuite)?;
202
203        let leaf_node = Self::new_with_key(
204            encryption_key_pair.public_key().clone(),
205            credential_with_key,
206            leaf_node_source,
207            capabilities,
208            extensions,
209            tree_info_tbs,
210            signer,
211        )?;
212
213        Ok((leaf_node, encryption_key_pair))
214    }
215
216    /// Creates a new placeholder [`LeafNode`] that is used to build external
217    /// commits.
218    ///
219    /// Note: This is not a valid leaf node and it must be rekeyed and signed
220    /// before it can be used.
221    pub(crate) fn new_placeholder() -> Self {
222        let payload = LeafNodePayload {
223            encryption_key: EncryptionKey::from(Vec::new()),
224            signature_key: Vec::new().into(),
225            credential: Credential::new(CredentialType::Basic, Vec::new()),
226            capabilities: Capabilities::default(),
227            leaf_node_source: LeafNodeSource::Update,
228            extensions: Extensions::default(),
229        };
230
231        Self {
232            payload,
233            signature: Vec::new().into(),
234        }
235    }
236
237    /// Create a new leaf node with a given HPKE encryption key pair.
238    /// The key pair must be stored in the key store by the caller.
239    fn new_with_key(
240        encryption_key: EncryptionKey,
241        credential_with_key: CredentialWithKey,
242        leaf_node_source: LeafNodeSource,
243        capabilities: Capabilities,
244        extensions: Extensions,
245        tree_info_tbs: TreeInfoTbs,
246        signer: &impl Signer,
247    ) -> Result<Self, LibraryError> {
248        let leaf_node_tbs = LeafNodeTbs::new(
249            encryption_key,
250            credential_with_key,
251            capabilities,
252            leaf_node_source,
253            extensions,
254            tree_info_tbs,
255        );
256
257        leaf_node_tbs
258            .sign(signer)
259            .map_err(|_| LibraryError::custom("Signing failed"))
260    }
261
262    /// New [`LeafNode`] with a parent hash.
263    #[allow(clippy::too_many_arguments)]
264    pub(in crate::treesync) fn new_with_parent_hash(
265        rand: &impl OpenMlsRand,
266        crypto: &impl OpenMlsCrypto,
267        ciphersuite: Ciphersuite,
268        parent_hash: &[u8],
269        leaf_node_params: UpdateLeafNodeParams,
270        group_id: GroupId,
271        leaf_index: LeafNodeIndex,
272        signer: &impl Signer,
273    ) -> Result<(Self, EncryptionKeyPair), LibraryError> {
274        let encryption_key_pair = EncryptionKeyPair::random(rand, crypto, ciphersuite)?;
275
276        let leaf_node_tbs = LeafNodeTbs::new(
277            encryption_key_pair.public_key().clone(),
278            leaf_node_params.credential_with_key,
279            leaf_node_params.capabilities,
280            LeafNodeSource::Commit(parent_hash.into()),
281            leaf_node_params.extensions,
282            TreeInfoTbs::Commit(TreePosition {
283                group_id,
284                leaf_index,
285            }),
286        );
287
288        // Sign the leaf node
289        let leaf_node = leaf_node_tbs
290            .sign(signer)
291            .map_err(|_| LibraryError::custom("Signing failed"))?;
292
293        Ok((leaf_node, encryption_key_pair))
294    }
295
296    /// Generate a fresh leaf node.
297    ///
298    /// This includes generating a new encryption key pair that is stored in the
299    /// key store.
300    ///
301    /// This function can be used when generating an update. In most other cases
302    /// a leaf node should be generated as part of a new [`KeyPackage`].
303    #[cfg(test)]
304    pub(crate) fn generate_update<Provider: OpenMlsProvider>(
305        ciphersuite: Ciphersuite,
306        credential_with_key: CredentialWithKey,
307        capabilities: Capabilities,
308        extensions: Extensions,
309        tree_info_tbs: TreeInfoTbs,
310        provider: &Provider,
311        signer: &impl Signer,
312    ) -> Result<Self, LeafNodeGenerationError<Provider::StorageError>> {
313        // Note that this function is supposed to be used in the public API only
314        // because it is interacting with the key store.
315
316        let new_leaf_node_params = NewLeafNodeParams {
317            ciphersuite,
318            credential_with_key,
319            leaf_node_source: LeafNodeSource::Update,
320            capabilities,
321            extensions,
322            tree_info_tbs,
323        };
324
325        let (leaf_node, encryption_key_pair) = Self::new(provider, signer, new_leaf_node_params)?;
326
327        // Store the encryption key pair in the key store.
328        encryption_key_pair
329            .write(provider.storage())
330            .map_err(LeafNodeGenerationError::StorageError)?;
331
332        Ok(leaf_node)
333    }
334
335    /// Update a leaf node.
336    ///
337    /// This function generates a new encryption key pair that is stored in the
338    /// key store and also returned.
339    ///
340    /// This function can be used when generating an update. In most other cases
341    /// a leaf node should be generated as part of a new [`KeyPackage`].
342    pub(crate) fn update<Provider: OpenMlsProvider>(
343        &mut self,
344        ciphersuite: Ciphersuite,
345        provider: &Provider,
346        signer: &impl Signer,
347        group_id: GroupId,
348        leaf_index: LeafNodeIndex,
349        leaf_node_parmeters: LeafNodeParameters,
350    ) -> Result<EncryptionKeyPair, LeafNodeUpdateError<Provider::StorageError>> {
351        let tree_info = TreeInfoTbs::Update(TreePosition::new(group_id, leaf_index));
352        let mut leaf_node_tbs = LeafNodeTbs::from(self.clone(), tree_info);
353
354        // Update credential
355        if let Some(credential_with_key) = leaf_node_parmeters.credential_with_key {
356            leaf_node_tbs.payload.credential = credential_with_key.credential;
357            leaf_node_tbs.payload.signature_key = credential_with_key.signature_key;
358        }
359
360        // Update extensions
361        if let Some(extensions) = leaf_node_parmeters.extensions {
362            leaf_node_tbs.payload.extensions = extensions;
363        }
364
365        // Update capabilities
366        if let Some(capabilities) = leaf_node_parmeters.capabilities {
367            leaf_node_tbs.payload.capabilities = capabilities;
368        }
369
370        // Create a new encryption key pair
371        let encryption_key_pair =
372            EncryptionKeyPair::random(provider.rand(), provider.crypto(), ciphersuite)?;
373        leaf_node_tbs.payload.encryption_key = encryption_key_pair.public_key().clone();
374
375        // Store the encryption key pair in the key store.
376        encryption_key_pair
377            .write(provider.storage())
378            .map_err(LeafNodeUpdateError::Storage)?;
379
380        // Set the leaf node source to update
381        leaf_node_tbs.payload.leaf_node_source = LeafNodeSource::Update;
382
383        // Sign the leaf node
384        let leaf_node = leaf_node_tbs.sign(signer)?;
385        self.payload = leaf_node.payload;
386        self.signature = leaf_node.signature;
387
388        Ok(encryption_key_pair)
389    }
390
391    /// Returns the `encryption_key`.
392    pub fn encryption_key(&self) -> &EncryptionKey {
393        &self.payload.encryption_key
394    }
395
396    /// Returns the `signature_key` as byte slice.
397    pub fn signature_key(&self) -> &SignaturePublicKey {
398        &self.payload.signature_key
399    }
400
401    /// Returns the `signature_key` as byte slice.
402    pub fn credential(&self) -> &Credential {
403        &self.payload.credential
404    }
405
406    /// Returns the `parent_hash` as byte slice or `None`.
407    pub fn parent_hash(&self) -> Option<&[u8]> {
408        match &self.payload.leaf_node_source {
409            LeafNodeSource::Commit(ph) => Some(ph.as_slice()),
410            _ => None,
411        }
412    }
413
414    /// Returns the [`Lifetime`] if present.
415    /// `None` otherwise.
416    pub(crate) fn life_time(&self) -> Option<&Lifetime> {
417        if let LeafNodeSource::KeyPackage(life_time) = &self.payload.leaf_node_source {
418            Some(life_time)
419        } else {
420            None
421        }
422    }
423
424    /// Returns a reference to the [`Signature`] of this leaf.
425    pub fn signature(&self) -> &Signature {
426        &self.signature
427    }
428
429    /// Return a reference to [`Capabilities`].
430    pub fn capabilities(&self) -> &Capabilities {
431        &self.payload.capabilities
432    }
433
434    /// Return a reference to the leaf node source.
435    pub fn leaf_node_source(&self) -> &LeafNodeSource {
436        &self.payload.leaf_node_source
437    }
438
439    /// Return a reference to the leaf node extensions.
440    pub fn extensions(&self) -> &Extensions {
441        &self.payload.extensions
442    }
443
444    /// Returns `true` if the [`ExtensionType`] is supported by this leaf node.
445    pub(crate) fn supports_extension(&self, extension_type: &ExtensionType) -> bool {
446        extension_type.is_default()
447            || self
448                .payload
449                .capabilities
450                .extensions
451                .contains(extension_type)
452    }
453
454    /// Check whether the this leaf node supports all the required extensions
455    /// in the provided list.
456    pub(crate) fn check_extension_support(
457        &self,
458        extensions: &[ExtensionType],
459    ) -> Result<(), LeafNodeValidationError> {
460        for required in extensions.iter() {
461            if !self.supports_extension(required) {
462                log::error!(
463                    "Leaf node does not support required extension {:?}\n
464                    Supported extensions: {:?}",
465                    required,
466                    self.payload.capabilities.extensions
467                );
468                return Err(LeafNodeValidationError::UnsupportedExtensions);
469            }
470        }
471        Ok(())
472    }
473
474    /// Perform all checks that can be done without further context:
475    /// - the used extensions are not known to be invalid in leaf nodes
476    /// - the types of the used extensions are covered by the capabilities
477    /// - the type of the credential is covered by the capabilities
478    pub(crate) fn validate_locally(&self) -> Result<(), LeafNodeValidationError> {
479        // Check that no extension is invalid when used in leaf nodes.
480        let invalid_extension_types = self
481            .extensions()
482            .iter()
483            .filter(|ext| ext.extension_type().is_valid_in_leaf_node() == Some(false))
484            .collect::<Vec<_>>();
485        if !invalid_extension_types.is_empty() {
486            log::error!("Invalid extension used in leaf node: {invalid_extension_types:?}");
487            return Err(LeafNodeValidationError::UnsupportedExtensions);
488        }
489
490        // Check that all extensions are contained in the capabilities.
491        if !self.capabilities().contains_extensions(self.extensions()) {
492            log::error!(
493                "Leaf node does not support all extensions it uses\n
494                Supported extensions: {:?}\n
495                Used extensions: {:?}",
496                self.payload.capabilities.extensions,
497                self.extensions()
498            );
499            return Err(LeafNodeValidationError::UnsupportedExtensions);
500        }
501
502        // Check that the capabilities contain the leaf node's credential type.
503        // (https://validation.openmls.tech/#valn0113)
504        if !self
505            .capabilities()
506            .contains_credential(self.credential().credential_type())
507        {
508            return Err(LeafNodeValidationError::UnsupportedCredentials);
509        }
510
511        Ok(())
512    }
513}
514
515/// The payload of a [`LeafNode`]
516///
517/// ```text
518/// struct {
519///     HPKEPublicKey encryption_key;
520///     SignaturePublicKey signature_key;
521///     Credential credential;
522///     Capabilities capabilities;
523///
524///     LeafNodeSource leaf_node_source;
525///     select (LeafNode.leaf_node_source) {
526///         case key_package:
527///             Lifetime lifetime;
528///
529///         case update:
530///             struct{};
531///
532///         case commit:
533///             opaque parent_hash<V>;
534///     };
535///
536///     Extension extensions<V>;
537///     ...
538/// } LeafNode;
539/// ```
540#[derive(
541    Debug,
542    Clone,
543    PartialEq,
544    Eq,
545    Serialize,
546    Deserialize,
547    TlsSerialize,
548    TlsDeserialize,
549    TlsDeserializeBytes,
550    TlsSize,
551)]
552struct LeafNodePayload {
553    encryption_key: EncryptionKey,
554    signature_key: SignaturePublicKey,
555    credential: Credential,
556    capabilities: Capabilities,
557    leaf_node_source: LeafNodeSource,
558    extensions: Extensions,
559}
560
561/// The source of the `LeafNode`.
562#[derive(
563    Debug,
564    Clone,
565    PartialEq,
566    Eq,
567    Serialize,
568    Deserialize,
569    TlsSerialize,
570    TlsDeserialize,
571    TlsDeserializeBytes,
572    TlsSize,
573)]
574#[repr(u8)]
575pub enum LeafNodeSource {
576    /// The leaf node was added to the group as part of a key package.
577    #[tls_codec(discriminant = 1)]
578    KeyPackage(Lifetime),
579    /// The leaf node was added through an Update proposal.
580    Update,
581    /// The leaf node was added via a Commit.
582    Commit(ParentHash),
583}
584
585pub type ParentHash = VLBytes;
586
587/// To-be-signed leaf node.
588///
589/// ```c
590/// // draft-ietf-mls-protocol-17
591/// struct {
592///     HPKEPublicKey encryption_key;
593///     SignaturePublicKey signature_key;
594///     Credential credential;
595///     Capabilities capabilities;
596///
597///     LeafNodeSource leaf_node_source;
598///     select (LeafNodeTBS.leaf_node_source) {
599///         case key_package:
600///             Lifetime lifetime;
601///
602///         case update:
603///             struct{};
604///
605///         case commit:
606///             opaque parent_hash<V>;
607///     };
608///
609///     Extension extensions<V>;
610///
611///     // ... continued in [`TreeInfo`] ...
612/// } LeafNodeTBS;
613/// ```
614#[derive(Debug, TlsSerialize, TlsSize)]
615pub struct LeafNodeTbs {
616    payload: LeafNodePayload,
617    tree_info_tbs: TreeInfoTbs,
618}
619
620impl LeafNodeTbs {
621    /// Build a [`LeafNodeTbs`] from a [`LeafNode`] and a [`TreeInfo`]
622    /// to update a leaf node.
623    pub(crate) fn from(leaf_node: LeafNode, tree_info_tbs: TreeInfoTbs) -> Self {
624        Self {
625            payload: leaf_node.payload,
626            tree_info_tbs,
627        }
628    }
629
630    /// Build a new [`LeafNodeTbs`] from a [`KeyPackage`] and [`Credential`].
631    /// To get the [`LeafNode`] call [`LeafNode::sign`].
632    pub(crate) fn new(
633        encryption_key: EncryptionKey,
634        credential_with_key: CredentialWithKey,
635        capabilities: Capabilities,
636        leaf_node_source: LeafNodeSource,
637        extensions: Extensions,
638        tree_info_tbs: TreeInfoTbs,
639    ) -> Self {
640        let payload = LeafNodePayload {
641            encryption_key,
642            signature_key: credential_with_key.signature_key,
643            credential: credential_with_key.credential,
644            capabilities,
645            leaf_node_source,
646            extensions,
647        };
648
649        LeafNodeTbs {
650            payload,
651            tree_info_tbs,
652        }
653    }
654}
655
656/// Helper struct that holds additional information required to sign a leaf node.
657///
658/// ```c
659/// // draft-ietf-mls-protocol-17
660/// struct {
661///     // ... continued from [`LeafNodeTbs`] ...
662///
663///     select (LeafNodeTBS.leaf_node_source) {
664///         case key_package:
665///             struct{};
666///
667///         case update:
668///             opaque group_id<V>;
669///             uint32 leaf_index;
670///
671///         case commit:
672///             opaque group_id<V>;
673///             uint32 leaf_index;
674///     };
675/// } LeafNodeTBS;
676/// ```
677#[derive(Debug)]
678pub(crate) enum TreeInfoTbs {
679    KeyPackage,
680    Update(TreePosition),
681    Commit(TreePosition),
682}
683
684#[derive(Debug, Clone, PartialEq, Eq, TlsSerialize, TlsSize)]
685pub(crate) struct TreePosition {
686    group_id: GroupId,
687    leaf_index: LeafNodeIndex,
688}
689
690impl TreePosition {
691    pub(crate) fn new(group_id: GroupId, leaf_index: LeafNodeIndex) -> Self {
692        Self {
693            group_id,
694            leaf_index,
695        }
696    }
697
698    #[cfg(feature = "test-utils")]
699    pub(crate) fn into_parts(self) -> (GroupId, LeafNodeIndex) {
700        (self.group_id, self.leaf_index)
701    }
702}
703
704const LEAF_NODE_SIGNATURE_LABEL: &str = "LeafNodeTBS";
705
706#[derive(
707    Debug,
708    Clone,
709    PartialEq,
710    Eq,
711    Serialize,
712    Deserialize,
713    TlsSerialize,
714    TlsDeserialize,
715    TlsDeserializeBytes,
716    TlsSize,
717)]
718pub struct LeafNodeIn {
719    payload: LeafNodePayload,
720    signature: Signature,
721}
722
723impl LeafNodeIn {
724    pub(crate) fn into_verifiable_leaf_node(self) -> VerifiableLeafNode {
725        match self.payload.leaf_node_source {
726            LeafNodeSource::KeyPackage(_) => {
727                let verifiable = VerifiableKeyPackageLeafNode {
728                    payload: self.payload,
729                    signature: self.signature,
730                };
731                VerifiableLeafNode::KeyPackage(verifiable)
732            }
733            LeafNodeSource::Update => {
734                let verifiable = VerifiableUpdateLeafNode {
735                    payload: self.payload,
736                    signature: self.signature,
737                    tree_position: None,
738                };
739                VerifiableLeafNode::Update(verifiable)
740            }
741            LeafNodeSource::Commit(_) => {
742                let verifiable = VerifiableCommitLeafNode {
743                    payload: self.payload,
744                    signature: self.signature,
745                    tree_position: None,
746                };
747                VerifiableLeafNode::Commit(verifiable)
748            }
749        }
750    }
751
752    /// Returns the `encryption_key` as byte slice.
753    pub fn encryption_key(&self) -> &EncryptionKey {
754        &self.payload.encryption_key
755    }
756
757    /// Returns the `signature_key` as byte slice.
758    pub fn signature_key(&self) -> &SignaturePublicKey {
759        &self.payload.signature_key
760    }
761
762    /// Returns the `signature_key` as byte slice.
763    pub fn credential(&self) -> &Credential {
764        &self.payload.credential
765    }
766}
767
768impl From<LeafNode> for LeafNodeIn {
769    fn from(leaf_node: LeafNode) -> Self {
770        Self {
771            payload: leaf_node.payload,
772            signature: leaf_node.signature,
773        }
774    }
775}
776
777#[cfg(any(feature = "test-utils", test))]
778impl From<LeafNodeIn> for LeafNode {
779    fn from(deserialized: LeafNodeIn) -> Self {
780        Self {
781            payload: deserialized.payload,
782            signature: deserialized.signature,
783        }
784    }
785}
786
787impl From<KeyPackage> for LeafNode {
788    fn from(key_package: KeyPackage) -> Self {
789        key_package.leaf_node().clone()
790    }
791}
792
793impl From<KeyPackageBundle> for LeafNode {
794    fn from(key_package: KeyPackageBundle) -> Self {
795        key_package.key_package().leaf_node().clone()
796    }
797}
798
799#[derive(Debug, Clone, PartialEq, Eq)]
800pub(crate) enum VerifiableLeafNode {
801    KeyPackage(VerifiableKeyPackageLeafNode),
802    Update(VerifiableUpdateLeafNode),
803    Commit(VerifiableCommitLeafNode),
804}
805
806impl VerifiableLeafNode {
807    pub(crate) fn signature_key(&self) -> &SignaturePublicKey {
808        match self {
809            VerifiableLeafNode::KeyPackage(v) => v.signature_key(),
810            VerifiableLeafNode::Update(v) => v.signature_key(),
811            VerifiableLeafNode::Commit(v) => v.signature_key(),
812        }
813    }
814}
815
816#[derive(Debug, Clone, PartialEq, Eq)]
817pub(crate) struct VerifiableKeyPackageLeafNode {
818    payload: LeafNodePayload,
819    signature: Signature,
820}
821
822impl VerifiableKeyPackageLeafNode {
823    pub(crate) fn signature_key(&self) -> &SignaturePublicKey {
824        &self.payload.signature_key
825    }
826}
827
828// https://validation.openmls.tech/#valn0102
829impl Verifiable for VerifiableKeyPackageLeafNode {
830    type VerifiedStruct = LeafNode;
831
832    fn unsigned_payload(&self) -> Result<Vec<u8>, tls_codec::Error> {
833        self.payload.tls_serialize_detached()
834    }
835
836    fn signature(&self) -> &Signature {
837        &self.signature
838    }
839
840    fn label(&self) -> &str {
841        LEAF_NODE_SIGNATURE_LABEL
842    }
843
844    fn verify(
845        self,
846        crypto: &impl openmls_traits::crypto::OpenMlsCrypto,
847        pk: &crate::ciphersuite::OpenMlsSignaturePublicKey,
848    ) -> Result<Self::VerifiedStruct, crate::ciphersuite::signable::SignatureError> {
849        self.verify_no_out(crypto, pk)?;
850        Ok(LeafNode {
851            payload: self.payload,
852            signature: self.signature,
853        })
854    }
855}
856
857impl VerifiedStruct for LeafNode {}
858
859#[derive(Debug, Clone, PartialEq, Eq)]
860pub(crate) struct VerifiableUpdateLeafNode {
861    payload: LeafNodePayload,
862    signature: Signature,
863    tree_position: Option<TreePosition>,
864}
865
866impl VerifiableUpdateLeafNode {
867    pub(crate) fn add_tree_position(&mut self, tree_info: TreePosition) {
868        self.tree_position = Some(tree_info);
869    }
870
871    pub(crate) fn signature_key(&self) -> &SignaturePublicKey {
872        &self.payload.signature_key
873    }
874}
875
876impl Verifiable for VerifiableUpdateLeafNode {
877    type VerifiedStruct = LeafNode;
878
879    fn unsigned_payload(&self) -> Result<Vec<u8>, tls_codec::Error> {
880        let tree_info_tbs = match &self.tree_position {
881            Some(tree_position) => TreeInfoTbs::Commit(tree_position.clone()),
882            None => return Err(tls_codec::Error::InvalidInput),
883        };
884        let leaf_node_tbs = LeafNodeTbs {
885            payload: self.payload.clone(),
886            tree_info_tbs,
887        };
888        leaf_node_tbs.tls_serialize_detached()
889    }
890
891    fn signature(&self) -> &Signature {
892        &self.signature
893    }
894
895    fn label(&self) -> &str {
896        LEAF_NODE_SIGNATURE_LABEL
897    }
898
899    fn verify(
900        self,
901        crypto: &impl openmls_traits::crypto::OpenMlsCrypto,
902        pk: &crate::ciphersuite::OpenMlsSignaturePublicKey,
903    ) -> Result<Self::VerifiedStruct, crate::ciphersuite::signable::SignatureError> {
904        self.verify_no_out(crypto, pk)?;
905        Ok(LeafNode {
906            payload: self.payload,
907            signature: self.signature,
908        })
909    }
910}
911
912#[derive(Debug, Clone, PartialEq, Eq)]
913pub(crate) struct VerifiableCommitLeafNode {
914    payload: LeafNodePayload,
915    signature: Signature,
916    tree_position: Option<TreePosition>,
917}
918
919impl VerifiableCommitLeafNode {
920    pub(crate) fn add_tree_position(&mut self, tree_info: TreePosition) {
921        self.tree_position = Some(tree_info);
922    }
923
924    pub(crate) fn signature_key(&self) -> &SignaturePublicKey {
925        &self.payload.signature_key
926    }
927}
928
929impl Verifiable for VerifiableCommitLeafNode {
930    type VerifiedStruct = LeafNode;
931
932    fn unsigned_payload(&self) -> Result<Vec<u8>, tls_codec::Error> {
933        let tree_info_tbs = match &self.tree_position {
934            Some(tree_position) => TreeInfoTbs::Commit(tree_position.clone()),
935            None => return Err(tls_codec::Error::InvalidInput),
936        };
937        let leaf_node_tbs = LeafNodeTbs {
938            payload: self.payload.clone(),
939            tree_info_tbs,
940        };
941
942        leaf_node_tbs.tls_serialize_detached()
943    }
944
945    fn signature(&self) -> &Signature {
946        &self.signature
947    }
948
949    fn label(&self) -> &str {
950        LEAF_NODE_SIGNATURE_LABEL
951    }
952
953    fn verify(
954        self,
955        crypto: &impl openmls_traits::crypto::OpenMlsCrypto,
956        pk: &crate::ciphersuite::OpenMlsSignaturePublicKey,
957    ) -> Result<Self::VerifiedStruct, crate::ciphersuite::signable::SignatureError> {
958        self.verify_no_out(crypto, pk)?;
959        Ok(LeafNode {
960            payload: self.payload,
961            signature: self.signature,
962        })
963    }
964}
965
966impl Signable for LeafNodeTbs {
967    type SignedOutput = LeafNode;
968
969    fn unsigned_payload(&self) -> Result<Vec<u8>, tls_codec::Error> {
970        self.tls_serialize_detached()
971    }
972
973    fn label(&self) -> &str {
974        LEAF_NODE_SIGNATURE_LABEL
975    }
976}
977
978impl SignedStruct<LeafNodeTbs> for LeafNode {
979    fn from_payload(tbs: LeafNodeTbs, signature: Signature) -> Self {
980        Self {
981            payload: tbs.payload,
982            signature,
983        }
984    }
985}
986
987#[cfg(test)]
988#[derive(Error, Debug, PartialEq, Clone)]
989pub enum LeafNodeGenerationError<StorageError> {
990    /// See [`LibraryError`] for more details.
991    #[error(transparent)]
992    LibraryError(#[from] LibraryError),
993
994    /// Error storing leaf private key in storage.
995    #[error("Error storing leaf private key.")]
996    StorageError(StorageError),
997}
998
999/// Leaf Node Update Error
1000#[derive(Error, Debug, PartialEq, Clone)]
1001pub enum LeafNodeUpdateError<StorageError> {
1002    /// See [`LibraryError`] for more details.
1003    #[error(transparent)]
1004    LibraryError(#[from] LibraryError),
1005
1006    /// Error storing leaf private key in storage.
1007    #[error("Error storing leaf private key.")]
1008    Storage(StorageError),
1009
1010    /// Signature error.
1011    #[error(transparent)]
1012    Signature(#[from] crate::ciphersuite::signable::SignatureError),
1013}