1use std::collections::HashSet;
3
4use openmls_traits::{
5 crypto::OpenMlsCrypto, random::OpenMlsRand, signatures::Signer, types::Ciphersuite,
6};
7use serde::{Deserialize, Serialize};
8use thiserror::Error;
9use tls_codec::{
10 Serialize as TlsSerializeTrait, TlsDeserialize, TlsDeserializeBytes, TlsSerialize, TlsSize,
11 VLBytes,
12};
13
14use super::encryption_keys::{EncryptionKey, EncryptionKeyPair};
15use crate::{
16 binary_tree::array_representation::LeafNodeIndex,
17 ciphersuite::{
18 signable::{Signable, SignedStruct, Verifiable, VerifiedStruct},
19 Signature, SignaturePublicKey,
20 },
21 credentials::{Credential, CredentialType, CredentialWithKey},
22 error::LibraryError,
23 extensions::{ExtensionType, Extensions},
24 group::GroupId,
25 key_packages::{KeyPackage, Lifetime},
26 prelude::KeyPackageBundle,
27 storage::OpenMlsProvider,
28};
29
30use crate::treesync::errors::LeafNodeValidationError;
31
32mod capabilities;
33mod codec;
34
35pub use capabilities::*;
36
37pub(crate) struct NewLeafNodeParams {
38 pub(crate) ciphersuite: Ciphersuite,
39 pub(crate) credential_with_key: CredentialWithKey,
40 pub(crate) leaf_node_source: LeafNodeSource,
41 pub(crate) capabilities: Capabilities,
42 pub(crate) extensions: Extensions<LeafNode>,
43 pub(crate) tree_info_tbs: TreeInfoTbs,
44}
45
46#[derive(Debug, PartialEq, Clone)]
49pub(crate) struct UpdateLeafNodeParams {
50 pub(crate) credential_with_key: CredentialWithKey,
51 pub(crate) capabilities: Capabilities,
52 pub(crate) extensions: Extensions<LeafNode>,
53}
54
55impl UpdateLeafNodeParams {
56 #[cfg(test)]
57 pub(crate) fn derive(leaf_node: &LeafNode) -> Self {
58 Self {
59 credential_with_key: CredentialWithKey {
60 credential: leaf_node.payload.credential.clone(),
61 signature_key: leaf_node.payload.signature_key.clone(),
62 },
63 capabilities: leaf_node.payload.capabilities.clone(),
64 extensions: leaf_node.payload.extensions.clone(),
65 }
66 }
67}
68
69#[derive(Debug, PartialEq, Clone, Default)]
71pub struct LeafNodeParameters {
72 credential_with_key: Option<CredentialWithKey>,
73 capabilities: Option<Capabilities>,
74 extensions: Option<Extensions<LeafNode>>,
75}
76
77impl LeafNodeParameters {
78 pub fn builder() -> LeafNodeParametersBuilder {
80 LeafNodeParametersBuilder::default()
81 }
82
83 pub fn credential_with_key(&self) -> Option<&CredentialWithKey> {
85 self.credential_with_key.as_ref()
86 }
87
88 pub fn capabilities(&self) -> Option<&Capabilities> {
90 self.capabilities.as_ref()
91 }
92
93 pub fn extensions(&self) -> Option<&Extensions<LeafNode>> {
95 self.extensions.as_ref()
96 }
97
98 pub(crate) fn is_empty(&self) -> bool {
99 self.credential_with_key.is_none()
100 && self.capabilities.is_none()
101 && self.extensions.is_none()
102 }
103
104 pub(crate) fn set_credential_with_key(&mut self, credential_with_key: CredentialWithKey) {
105 self.credential_with_key = Some(credential_with_key);
106 }
107
108 #[cfg(feature = "virtual-clients-draft")]
109 pub(crate) fn set_extensions(&mut self, extensions: Extensions<LeafNode>) {
110 self.extensions = Some(extensions);
111 }
112}
113
114#[derive(Debug, Default)]
116pub struct LeafNodeParametersBuilder {
117 credential_with_key: Option<CredentialWithKey>,
118 capabilities: Option<Capabilities>,
119 extensions: Option<Extensions<LeafNode>>,
120}
121
122impl LeafNodeParametersBuilder {
123 pub fn with_credential_with_key(mut self, credential_with_key: CredentialWithKey) -> Self {
125 self.credential_with_key = Some(credential_with_key);
126 self
127 }
128
129 pub fn with_capabilities(mut self, capabilities: Capabilities) -> Self {
131 self.capabilities = Some(capabilities);
132 self
133 }
134
135 pub fn with_extensions(mut self, extensions: Extensions<LeafNode>) -> Self {
139 self.extensions = Some(extensions);
140 self
141 }
142
143 pub fn build(self) -> LeafNodeParameters {
145 LeafNodeParameters {
146 credential_with_key: self.credential_with_key,
147 capabilities: self.capabilities,
148 extensions: self.extensions,
149 }
150 }
151}
152
153#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, TlsSerialize, TlsSize)]
181pub struct LeafNode {
182 payload: LeafNodePayload,
183 signature: Signature,
184}
185
186impl LeafNode {
187 pub(crate) fn new(
195 provider: &impl OpenMlsProvider,
196 signer: &impl Signer,
197 new_leaf_node_params: NewLeafNodeParams,
198 ) -> Result<(Self, EncryptionKeyPair), LibraryError> {
199 let NewLeafNodeParams {
200 ciphersuite,
201 credential_with_key,
202 leaf_node_source,
203 capabilities,
204 extensions,
205 tree_info_tbs,
206 } = new_leaf_node_params;
207
208 let encryption_key_pair =
210 EncryptionKeyPair::random(provider.rand(), provider.crypto(), ciphersuite)?;
211
212 let leaf_node = Self::new_with_key(
213 encryption_key_pair.public_key().clone(),
214 credential_with_key,
215 leaf_node_source,
216 capabilities,
217 extensions,
218 tree_info_tbs,
219 signer,
220 )?;
221
222 Ok((leaf_node, encryption_key_pair))
223 }
224
225 #[cfg(feature = "virtual-clients-draft")]
232 pub(crate) fn new_with_encryption_key_pair(
233 signer: &impl Signer,
234 new_leaf_node_params: NewLeafNodeParams,
235 encryption_key_pair: EncryptionKeyPair,
236 ) -> Result<(Self, EncryptionKeyPair), LibraryError> {
237 let NewLeafNodeParams {
238 ciphersuite: _,
239 credential_with_key,
240 leaf_node_source,
241 capabilities,
242 extensions,
243 tree_info_tbs,
244 } = new_leaf_node_params;
245
246 let leaf_node = Self::new_with_key(
247 encryption_key_pair.public_key().clone(),
248 credential_with_key,
249 leaf_node_source,
250 capabilities,
251 extensions,
252 tree_info_tbs,
253 signer,
254 )?;
255
256 Ok((leaf_node, encryption_key_pair))
257 }
258
259 pub(crate) fn new_placeholder() -> Self {
265 let payload = LeafNodePayload {
266 encryption_key: EncryptionKey::from(Vec::new()),
267 signature_key: Vec::new().into(),
268 credential: Credential::new(CredentialType::Basic, Vec::new()),
269 capabilities: Capabilities::default(),
270 leaf_node_source: LeafNodeSource::Update,
271 extensions: Extensions::default(),
272 };
273
274 Self {
275 payload,
276 signature: Vec::new().into(),
277 }
278 }
279
280 fn new_with_key(
283 encryption_key: EncryptionKey,
284 credential_with_key: CredentialWithKey,
285 leaf_node_source: LeafNodeSource,
286 capabilities: Capabilities,
287 extensions: Extensions<LeafNode>,
288 tree_info_tbs: TreeInfoTbs,
289 signer: &impl Signer,
290 ) -> Result<Self, LibraryError> {
291 let leaf_node_tbs = LeafNodeTbs::new(
292 encryption_key,
293 credential_with_key,
294 capabilities,
295 leaf_node_source,
296 extensions,
297 tree_info_tbs,
298 );
299
300 leaf_node_tbs
301 .sign(signer)
302 .map_err(|_| LibraryError::custom("Signing failed"))
303 }
304
305 #[allow(clippy::too_many_arguments)]
312 pub(in crate::treesync) fn new_with_parent_hash(
313 rand: &impl OpenMlsRand,
314 crypto: &impl OpenMlsCrypto,
315 ciphersuite: Ciphersuite,
316 parent_hash: &[u8],
317 leaf_node_params: UpdateLeafNodeParams,
318 group_id: GroupId,
319 leaf_index: LeafNodeIndex,
320 signer: &impl Signer,
321 #[cfg(feature = "virtual-clients-draft")] encryption_key_pair_override: Option<
322 EncryptionKeyPair,
323 >,
324 ) -> Result<(Self, EncryptionKeyPair), LibraryError> {
325 #[cfg(feature = "virtual-clients-draft")]
326 let encryption_key_pair = match encryption_key_pair_override {
327 Some(kp) => kp,
328 None => EncryptionKeyPair::random(rand, crypto, ciphersuite)?,
329 };
330 #[cfg(not(feature = "virtual-clients-draft"))]
331 let encryption_key_pair = EncryptionKeyPair::random(rand, crypto, ciphersuite)?;
332
333 let leaf_node_tbs = LeafNodeTbs::new(
334 encryption_key_pair.public_key().clone(),
335 leaf_node_params.credential_with_key,
336 leaf_node_params.capabilities,
337 LeafNodeSource::Commit(parent_hash.into()),
338 leaf_node_params.extensions,
339 TreeInfoTbs::Commit(TreePosition {
340 group_id,
341 leaf_index,
342 }),
343 );
344
345 let leaf_node = leaf_node_tbs
347 .sign(signer)
348 .map_err(|_| LibraryError::custom("Signing failed"))?;
349
350 Ok((leaf_node, encryption_key_pair))
351 }
352
353 #[cfg(all(test, feature = "generate-kats"))]
361 pub(crate) fn generate_update<Provider: OpenMlsProvider>(
362 ciphersuite: Ciphersuite,
363 credential_with_key: CredentialWithKey,
364 capabilities: Capabilities,
365 extensions: Extensions<LeafNode>,
366 tree_info_tbs: TreeInfoTbs,
367 provider: &Provider,
368 signer: &impl Signer,
369 ) -> Result<Self, LeafNodeGenerationError<Provider::StorageError>> {
370 let new_leaf_node_params = NewLeafNodeParams {
374 ciphersuite,
375 credential_with_key,
376 leaf_node_source: LeafNodeSource::Update,
377 capabilities,
378 extensions,
379 tree_info_tbs,
380 };
381
382 let (leaf_node, encryption_key_pair) = Self::new(provider, signer, new_leaf_node_params)?;
383
384 encryption_key_pair
386 .write(provider.storage())
387 .map_err(LeafNodeGenerationError::StorageError)?;
388
389 Ok(leaf_node)
390 }
391
392 pub(crate) fn update<Provider: OpenMlsProvider>(
400 &mut self,
401 ciphersuite: Ciphersuite,
402 provider: &Provider,
403 signer: &impl Signer,
404 group_id: GroupId,
405 leaf_index: LeafNodeIndex,
406 leaf_node_parmeters: LeafNodeParameters,
407 ) -> Result<EncryptionKeyPair, LeafNodeUpdateError<Provider::StorageError>> {
408 let tree_info = TreeInfoTbs::Update(TreePosition::new(group_id, leaf_index));
409 let mut leaf_node_tbs = LeafNodeTbs::from(self.clone(), tree_info);
410
411 if let Some(credential_with_key) = leaf_node_parmeters.credential_with_key {
413 leaf_node_tbs.payload.credential = credential_with_key.credential;
414 leaf_node_tbs.payload.signature_key = credential_with_key.signature_key;
415 }
416
417 if let Some(extensions) = leaf_node_parmeters.extensions {
419 leaf_node_tbs.payload.extensions = extensions;
420 }
421
422 if let Some(capabilities) = leaf_node_parmeters.capabilities {
424 leaf_node_tbs.payload.capabilities = capabilities;
425 }
426
427 let encryption_key_pair =
429 EncryptionKeyPair::random(provider.rand(), provider.crypto(), ciphersuite)?;
430 leaf_node_tbs.payload.encryption_key = encryption_key_pair.public_key().clone();
431
432 encryption_key_pair
434 .write(provider.storage())
435 .map_err(LeafNodeUpdateError::Storage)?;
436
437 leaf_node_tbs.payload.leaf_node_source = LeafNodeSource::Update;
439
440 let leaf_node = leaf_node_tbs.sign(signer)?;
442 self.payload = leaf_node.payload;
443 self.signature = leaf_node.signature;
444
445 Ok(encryption_key_pair)
446 }
447
448 pub fn encryption_key(&self) -> &EncryptionKey {
450 &self.payload.encryption_key
451 }
452
453 pub fn signature_key(&self) -> &SignaturePublicKey {
455 &self.payload.signature_key
456 }
457
458 pub fn credential(&self) -> &Credential {
460 &self.payload.credential
461 }
462
463 pub fn parent_hash(&self) -> Option<&[u8]> {
465 match &self.payload.leaf_node_source {
466 LeafNodeSource::Commit(ph) => Some(ph.as_slice()),
467 _ => None,
468 }
469 }
470
471 pub(crate) fn life_time(&self) -> Option<&Lifetime> {
474 if let LeafNodeSource::KeyPackage(life_time) = &self.payload.leaf_node_source {
475 Some(life_time)
476 } else {
477 None
478 }
479 }
480
481 pub fn signature(&self) -> &Signature {
483 &self.signature
484 }
485
486 pub fn capabilities(&self) -> &Capabilities {
488 &self.payload.capabilities
489 }
490
491 pub fn leaf_node_source(&self) -> &LeafNodeSource {
493 &self.payload.leaf_node_source
494 }
495
496 pub fn extensions(&self) -> &Extensions<LeafNode> {
498 &self.payload.extensions
499 }
500
501 pub(crate) fn supports_extension(&self, extension_type: &ExtensionType) -> bool {
503 extension_type.is_default()
504 || self
505 .payload
506 .capabilities
507 .extensions
508 .contains(extension_type)
509 }
510
511 pub(crate) fn check_extension_support(
514 &self,
515 extensions: &[ExtensionType],
516 ) -> Result<(), LeafNodeValidationError> {
517 let mut required = extensions.iter().filter(|e| !e.is_default()).peekable();
518
519 if required.peek().is_none() {
521 return Ok(());
522 }
523
524 let supported: HashSet<ExtensionType> = self
525 .payload
526 .capabilities
527 .extensions
528 .iter()
529 .copied()
530 .collect();
531
532 if let Some(unsupported) = required.find(|e| !supported.contains(e)) {
533 log::error!(
534 "Leaf node does not support required extension {:?}\n
535 Supported extensions: {:?}",
536 unsupported,
537 self.payload.capabilities.extensions
538 );
539 return Err(LeafNodeValidationError::UnsupportedExtensions);
540 }
541
542 Ok(())
543 }
544
545 pub(crate) fn validate_locally(&self) -> Result<(), LeafNodeValidationError> {
550 let invalid_extension_types = self
559 .extensions()
560 .iter()
561 .filter(|ext| !ext.extension_type().is_valid_in_leaf_node())
562 .collect::<Vec<_>>();
563 if !invalid_extension_types.is_empty() {
564 log::error!("Invalid extension used in leaf node: {invalid_extension_types:?}");
565 return Err(LeafNodeValidationError::UnsupportedExtensions);
566 }
567
568 if !self.capabilities().contains_extensions(self.extensions()) {
570 log::error!(
571 "Leaf node does not support all extensions it uses\n
572 Supported extensions: {:?}\n
573 Used extensions: {:?}",
574 self.payload.capabilities.extensions,
575 self.extensions()
576 );
577 return Err(LeafNodeValidationError::UnsupportedExtensions);
578 }
579
580 if !self
583 .capabilities()
584 .contains_credential(self.credential().credential_type())
585 {
586 return Err(LeafNodeValidationError::UnsupportedCredentials);
587 }
588
589 Ok(())
590 }
591}
592
593#[derive(
619 Debug,
620 Clone,
621 PartialEq,
622 Eq,
623 Serialize,
624 Deserialize,
625 TlsSerialize,
626 TlsDeserialize,
627 TlsDeserializeBytes,
628 TlsSize,
629)]
630struct LeafNodePayload {
631 encryption_key: EncryptionKey,
632 signature_key: SignaturePublicKey,
633 credential: Credential,
634 capabilities: Capabilities,
635 leaf_node_source: LeafNodeSource,
636 extensions: Extensions<LeafNode>,
637}
638
639#[derive(
641 Debug,
642 Clone,
643 PartialEq,
644 Eq,
645 Serialize,
646 Deserialize,
647 TlsSerialize,
648 TlsDeserialize,
649 TlsDeserializeBytes,
650 TlsSize,
651)]
652#[repr(u8)]
653pub enum LeafNodeSource {
654 #[tls_codec(discriminant = 1)]
656 KeyPackage(Lifetime),
657 Update,
659 Commit(ParentHash),
661}
662
663pub type ParentHash = VLBytes;
664
665#[derive(Debug, TlsSerialize, TlsSize)]
693pub struct LeafNodeTbs {
694 payload: LeafNodePayload,
695 tree_info_tbs: TreeInfoTbs,
696}
697
698impl LeafNodeTbs {
699 pub(crate) fn from(leaf_node: LeafNode, tree_info_tbs: TreeInfoTbs) -> Self {
702 Self {
703 payload: leaf_node.payload,
704 tree_info_tbs,
705 }
706 }
707
708 pub(crate) fn new(
711 encryption_key: EncryptionKey,
712 credential_with_key: CredentialWithKey,
713 capabilities: Capabilities,
714 leaf_node_source: LeafNodeSource,
715 extensions: Extensions<LeafNode>,
716 tree_info_tbs: TreeInfoTbs,
717 ) -> Self {
718 let payload = LeafNodePayload {
719 encryption_key,
720 signature_key: credential_with_key.signature_key,
721 credential: credential_with_key.credential,
722 capabilities,
723 leaf_node_source,
724 extensions,
725 };
726
727 LeafNodeTbs {
728 payload,
729 tree_info_tbs,
730 }
731 }
732}
733
734#[derive(Debug)]
756pub(crate) enum TreeInfoTbs {
757 KeyPackage,
758 Update(TreePosition),
759 Commit(TreePosition),
760}
761
762#[derive(Debug, Clone, PartialEq, Eq, TlsSerialize, TlsSize)]
763pub(crate) struct TreePosition {
764 group_id: GroupId,
765 leaf_index: LeafNodeIndex,
766}
767
768impl TreePosition {
769 pub(crate) fn new(group_id: GroupId, leaf_index: LeafNodeIndex) -> Self {
770 Self {
771 group_id,
772 leaf_index,
773 }
774 }
775
776 #[cfg(feature = "test-utils")]
777 pub(crate) fn into_parts(self) -> (GroupId, LeafNodeIndex) {
778 (self.group_id, self.leaf_index)
779 }
780}
781
782const LEAF_NODE_SIGNATURE_LABEL: &str = "LeafNodeTBS";
783
784#[derive(
785 Debug,
786 Clone,
787 PartialEq,
788 Eq,
789 Serialize,
790 Deserialize,
791 TlsSerialize,
792 TlsDeserialize,
793 TlsDeserializeBytes,
794 TlsSize,
795)]
796pub struct LeafNodeIn {
797 payload: LeafNodePayload,
798 signature: Signature,
799}
800
801impl LeafNodeIn {
802 pub(crate) fn into_verifiable_leaf_node(self) -> VerifiableLeafNode {
803 match self.payload.leaf_node_source {
804 LeafNodeSource::KeyPackage(_) => {
805 let verifiable = VerifiableKeyPackageLeafNode {
806 payload: self.payload,
807 signature: self.signature,
808 };
809 VerifiableLeafNode::KeyPackage(verifiable)
810 }
811 LeafNodeSource::Update => {
812 let verifiable = VerifiableUpdateLeafNode {
813 payload: self.payload,
814 signature: self.signature,
815 tree_position: None,
816 };
817 VerifiableLeafNode::Update(verifiable)
818 }
819 LeafNodeSource::Commit(_) => {
820 let verifiable = VerifiableCommitLeafNode {
821 payload: self.payload,
822 signature: self.signature,
823 tree_position: None,
824 };
825 VerifiableLeafNode::Commit(verifiable)
826 }
827 }
828 }
829
830 pub fn encryption_key(&self) -> &EncryptionKey {
832 &self.payload.encryption_key
833 }
834
835 pub fn signature_key(&self) -> &SignaturePublicKey {
837 &self.payload.signature_key
838 }
839
840 pub fn credential(&self) -> &Credential {
842 &self.payload.credential
843 }
844
845 #[cfg(feature = "unchecked-conversions")]
851 pub fn into_unchecked(self) -> LeafNode {
852 LeafNode {
853 payload: self.payload,
854 signature: self.signature,
855 }
856 }
857}
858
859impl From<LeafNode> for LeafNodeIn {
860 fn from(leaf_node: LeafNode) -> Self {
861 Self {
862 payload: leaf_node.payload,
863 signature: leaf_node.signature,
864 }
865 }
866}
867
868#[cfg(any(feature = "test-utils", test))]
869impl From<LeafNodeIn> for LeafNode {
870 fn from(deserialized: LeafNodeIn) -> Self {
871 Self {
872 payload: deserialized.payload,
873 signature: deserialized.signature,
874 }
875 }
876}
877
878impl From<KeyPackage> for LeafNode {
879 fn from(key_package: KeyPackage) -> Self {
880 key_package.leaf_node().clone()
881 }
882}
883
884impl From<KeyPackageBundle> for LeafNode {
885 fn from(key_package: KeyPackageBundle) -> Self {
886 key_package.key_package().leaf_node().clone()
887 }
888}
889
890#[derive(Debug, Clone, PartialEq, Eq)]
891pub(crate) enum VerifiableLeafNode {
892 KeyPackage(VerifiableKeyPackageLeafNode),
893 Update(VerifiableUpdateLeafNode),
894 Commit(VerifiableCommitLeafNode),
895}
896
897impl VerifiableLeafNode {
898 pub(crate) fn signature_key(&self) -> &SignaturePublicKey {
899 match self {
900 VerifiableLeafNode::KeyPackage(v) => v.signature_key(),
901 VerifiableLeafNode::Update(v) => v.signature_key(),
902 VerifiableLeafNode::Commit(v) => v.signature_key(),
903 }
904 }
905}
906
907#[derive(Debug, Clone, PartialEq, Eq)]
908pub(crate) struct VerifiableKeyPackageLeafNode {
909 payload: LeafNodePayload,
910 signature: Signature,
911}
912
913impl VerifiableKeyPackageLeafNode {
914 pub(crate) fn signature_key(&self) -> &SignaturePublicKey {
915 &self.payload.signature_key
916 }
917}
918
919impl Verifiable for VerifiableKeyPackageLeafNode {
921 type VerifiedStruct = LeafNode;
922
923 fn unsigned_payload(&self) -> Result<Vec<u8>, tls_codec::Error> {
924 self.payload.tls_serialize_detached()
925 }
926
927 fn signature(&self) -> &Signature {
928 &self.signature
929 }
930
931 fn label(&self) -> &str {
932 LEAF_NODE_SIGNATURE_LABEL
933 }
934
935 fn verify(
936 self,
937 crypto: &impl openmls_traits::crypto::OpenMlsCrypto,
938 pk: &crate::ciphersuite::OpenMlsSignaturePublicKey,
939 ) -> Result<Self::VerifiedStruct, crate::ciphersuite::signable::SignatureError> {
940 self.verify_no_out(crypto, pk)?;
941 Ok(LeafNode {
942 payload: self.payload,
943 signature: self.signature,
944 })
945 }
946}
947
948impl VerifiedStruct for LeafNode {}
949
950#[derive(Debug, Clone, PartialEq, Eq)]
951pub(crate) struct VerifiableUpdateLeafNode {
952 payload: LeafNodePayload,
953 signature: Signature,
954 tree_position: Option<TreePosition>,
955}
956
957impl VerifiableUpdateLeafNode {
958 pub(crate) fn add_tree_position(&mut self, tree_info: TreePosition) {
959 self.tree_position = Some(tree_info);
960 }
961
962 pub(crate) fn signature_key(&self) -> &SignaturePublicKey {
963 &self.payload.signature_key
964 }
965}
966
967impl Verifiable for VerifiableUpdateLeafNode {
968 type VerifiedStruct = LeafNode;
969
970 fn unsigned_payload(&self) -> Result<Vec<u8>, tls_codec::Error> {
971 let tree_info_tbs = match &self.tree_position {
972 Some(tree_position) => TreeInfoTbs::Commit(tree_position.clone()),
973 None => return Err(tls_codec::Error::InvalidInput),
974 };
975 let leaf_node_tbs = LeafNodeTbs {
976 payload: self.payload.clone(),
977 tree_info_tbs,
978 };
979 leaf_node_tbs.tls_serialize_detached()
980 }
981
982 fn signature(&self) -> &Signature {
983 &self.signature
984 }
985
986 fn label(&self) -> &str {
987 LEAF_NODE_SIGNATURE_LABEL
988 }
989
990 fn verify(
991 self,
992 crypto: &impl openmls_traits::crypto::OpenMlsCrypto,
993 pk: &crate::ciphersuite::OpenMlsSignaturePublicKey,
994 ) -> Result<Self::VerifiedStruct, crate::ciphersuite::signable::SignatureError> {
995 self.verify_no_out(crypto, pk)?;
996 Ok(LeafNode {
997 payload: self.payload,
998 signature: self.signature,
999 })
1000 }
1001}
1002
1003#[derive(Debug, Clone, PartialEq, Eq)]
1004pub(crate) struct VerifiableCommitLeafNode {
1005 payload: LeafNodePayload,
1006 signature: Signature,
1007 tree_position: Option<TreePosition>,
1008}
1009
1010impl VerifiableCommitLeafNode {
1011 pub(crate) fn add_tree_position(&mut self, tree_info: TreePosition) {
1012 self.tree_position = Some(tree_info);
1013 }
1014
1015 pub(crate) fn signature_key(&self) -> &SignaturePublicKey {
1016 &self.payload.signature_key
1017 }
1018}
1019
1020impl Verifiable for VerifiableCommitLeafNode {
1021 type VerifiedStruct = LeafNode;
1022
1023 fn unsigned_payload(&self) -> Result<Vec<u8>, tls_codec::Error> {
1024 let tree_info_tbs = match &self.tree_position {
1025 Some(tree_position) => TreeInfoTbs::Commit(tree_position.clone()),
1026 None => return Err(tls_codec::Error::InvalidInput),
1027 };
1028 let leaf_node_tbs = LeafNodeTbs {
1029 payload: self.payload.clone(),
1030 tree_info_tbs,
1031 };
1032
1033 leaf_node_tbs.tls_serialize_detached()
1034 }
1035
1036 fn signature(&self) -> &Signature {
1037 &self.signature
1038 }
1039
1040 fn label(&self) -> &str {
1041 LEAF_NODE_SIGNATURE_LABEL
1042 }
1043
1044 fn verify(
1045 self,
1046 crypto: &impl openmls_traits::crypto::OpenMlsCrypto,
1047 pk: &crate::ciphersuite::OpenMlsSignaturePublicKey,
1048 ) -> Result<Self::VerifiedStruct, crate::ciphersuite::signable::SignatureError> {
1049 self.verify_no_out(crypto, pk)?;
1050 Ok(LeafNode {
1051 payload: self.payload,
1052 signature: self.signature,
1053 })
1054 }
1055}
1056
1057impl Signable for LeafNodeTbs {
1058 type SignedOutput = LeafNode;
1059
1060 fn unsigned_payload(&self) -> Result<Vec<u8>, tls_codec::Error> {
1061 self.tls_serialize_detached()
1062 }
1063
1064 fn label(&self) -> &str {
1065 LEAF_NODE_SIGNATURE_LABEL
1066 }
1067}
1068
1069impl SignedStruct<LeafNodeTbs> for LeafNode {
1070 fn from_payload(tbs: LeafNodeTbs, signature: Signature, _serialized_payload: Vec<u8>) -> Self {
1071 Self {
1072 payload: tbs.payload,
1073 signature,
1074 }
1075 }
1076}
1077
1078#[cfg(all(test, feature = "generate-kats"))]
1079#[derive(Error, Debug, PartialEq, Clone)]
1080pub enum LeafNodeGenerationError<StorageError> {
1081 #[error(transparent)]
1083 LibraryError(#[from] LibraryError),
1084
1085 #[error("Error storing leaf private key.")]
1087 StorageError(StorageError),
1088}
1089
1090#[derive(Error, Debug, PartialEq, Clone)]
1092pub enum LeafNodeUpdateError<StorageError> {
1093 #[error(transparent)]
1095 LibraryError(#[from] LibraryError),
1096
1097 #[error("Error storing leaf private key.")]
1099 Storage(StorageError),
1100
1101 #[error(transparent)]
1103 Signature(#[from] crate::ciphersuite::signable::SignatureError),
1104}