1use 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<LeafNode>,
41 pub(crate) tree_info_tbs: TreeInfoTbs,
42}
43
44#[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<LeafNode>,
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#[derive(Debug, PartialEq, Clone, Default)]
69pub struct LeafNodeParameters {
70 credential_with_key: Option<CredentialWithKey>,
71 capabilities: Option<Capabilities>,
72 extensions: Option<Extensions<LeafNode>>,
73}
74
75impl LeafNodeParameters {
76 pub fn builder() -> LeafNodeParametersBuilder {
78 LeafNodeParametersBuilder::default()
79 }
80
81 pub fn credential_with_key(&self) -> Option<&CredentialWithKey> {
83 self.credential_with_key.as_ref()
84 }
85
86 pub fn capabilities(&self) -> Option<&Capabilities> {
88 self.capabilities.as_ref()
89 }
90
91 pub fn extensions(&self) -> Option<&Extensions<LeafNode>> {
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#[derive(Debug, Default)]
109pub struct LeafNodeParametersBuilder {
110 credential_with_key: Option<CredentialWithKey>,
111 capabilities: Option<Capabilities>,
112 extensions: Option<Extensions<LeafNode>>,
113}
114
115impl LeafNodeParametersBuilder {
116 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 pub fn with_capabilities(mut self, capabilities: Capabilities) -> Self {
124 self.capabilities = Some(capabilities);
125 self
126 }
127
128 pub fn with_extensions(mut self, extensions: Extensions<LeafNode>) -> Self {
132 self.extensions = Some(extensions);
133 self
134 }
135
136 pub fn build(self) -> LeafNodeParameters {
138 LeafNodeParameters {
139 credential_with_key: self.credential_with_key,
140 capabilities: self.capabilities,
141 extensions: self.extensions,
142 }
143 }
144}
145
146#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, TlsSerialize, TlsSize)]
174pub struct LeafNode {
175 payload: LeafNodePayload,
176 signature: Signature,
177}
178
179impl LeafNode {
180 pub(crate) fn new(
188 provider: &impl OpenMlsProvider,
189 signer: &impl Signer,
190 new_leaf_node_params: NewLeafNodeParams,
191 ) -> Result<(Self, EncryptionKeyPair), LibraryError> {
192 let NewLeafNodeParams {
193 ciphersuite,
194 credential_with_key,
195 leaf_node_source,
196 capabilities,
197 extensions,
198 tree_info_tbs,
199 } = new_leaf_node_params;
200
201 let encryption_key_pair =
203 EncryptionKeyPair::random(provider.rand(), provider.crypto(), ciphersuite)?;
204
205 let leaf_node = Self::new_with_key(
206 encryption_key_pair.public_key().clone(),
207 credential_with_key,
208 leaf_node_source,
209 capabilities,
210 extensions,
211 tree_info_tbs,
212 signer,
213 )?;
214
215 Ok((leaf_node, encryption_key_pair))
216 }
217
218 pub(crate) fn new_placeholder() -> Self {
224 let payload = LeafNodePayload {
225 encryption_key: EncryptionKey::from(Vec::new()),
226 signature_key: Vec::new().into(),
227 credential: Credential::new(CredentialType::Basic, Vec::new()),
228 capabilities: Capabilities::default(),
229 leaf_node_source: LeafNodeSource::Update,
230 extensions: Extensions::default(),
231 };
232
233 Self {
234 payload,
235 signature: Vec::new().into(),
236 }
237 }
238
239 fn new_with_key(
242 encryption_key: EncryptionKey,
243 credential_with_key: CredentialWithKey,
244 leaf_node_source: LeafNodeSource,
245 capabilities: Capabilities,
246 extensions: Extensions<LeafNode>,
247 tree_info_tbs: TreeInfoTbs,
248 signer: &impl Signer,
249 ) -> Result<Self, LibraryError> {
250 let leaf_node_tbs = LeafNodeTbs::new(
251 encryption_key,
252 credential_with_key,
253 capabilities,
254 leaf_node_source,
255 extensions,
256 tree_info_tbs,
257 );
258
259 leaf_node_tbs
260 .sign(signer)
261 .map_err(|_| LibraryError::custom("Signing failed"))
262 }
263
264 #[allow(clippy::too_many_arguments)]
266 pub(in crate::treesync) fn new_with_parent_hash(
267 rand: &impl OpenMlsRand,
268 crypto: &impl OpenMlsCrypto,
269 ciphersuite: Ciphersuite,
270 parent_hash: &[u8],
271 leaf_node_params: UpdateLeafNodeParams,
272 group_id: GroupId,
273 leaf_index: LeafNodeIndex,
274 signer: &impl Signer,
275 ) -> Result<(Self, EncryptionKeyPair), LibraryError> {
276 let encryption_key_pair = EncryptionKeyPair::random(rand, crypto, ciphersuite)?;
277
278 let leaf_node_tbs = LeafNodeTbs::new(
279 encryption_key_pair.public_key().clone(),
280 leaf_node_params.credential_with_key,
281 leaf_node_params.capabilities,
282 LeafNodeSource::Commit(parent_hash.into()),
283 leaf_node_params.extensions,
284 TreeInfoTbs::Commit(TreePosition {
285 group_id,
286 leaf_index,
287 }),
288 );
289
290 let leaf_node = leaf_node_tbs
292 .sign(signer)
293 .map_err(|_| LibraryError::custom("Signing failed"))?;
294
295 Ok((leaf_node, encryption_key_pair))
296 }
297
298 #[cfg(test)]
306 pub(crate) fn generate_update<Provider: OpenMlsProvider>(
307 ciphersuite: Ciphersuite,
308 credential_with_key: CredentialWithKey,
309 capabilities: Capabilities,
310 extensions: Extensions<LeafNode>,
311 tree_info_tbs: TreeInfoTbs,
312 provider: &Provider,
313 signer: &impl Signer,
314 ) -> Result<Self, LeafNodeGenerationError<Provider::StorageError>> {
315 let new_leaf_node_params = NewLeafNodeParams {
319 ciphersuite,
320 credential_with_key,
321 leaf_node_source: LeafNodeSource::Update,
322 capabilities,
323 extensions,
324 tree_info_tbs,
325 };
326
327 let (leaf_node, encryption_key_pair) = Self::new(provider, signer, new_leaf_node_params)?;
328
329 encryption_key_pair
331 .write(provider.storage())
332 .map_err(LeafNodeGenerationError::StorageError)?;
333
334 Ok(leaf_node)
335 }
336
337 pub(crate) fn update<Provider: OpenMlsProvider>(
345 &mut self,
346 ciphersuite: Ciphersuite,
347 provider: &Provider,
348 signer: &impl Signer,
349 group_id: GroupId,
350 leaf_index: LeafNodeIndex,
351 leaf_node_parmeters: LeafNodeParameters,
352 ) -> Result<EncryptionKeyPair, LeafNodeUpdateError<Provider::StorageError>> {
353 let tree_info = TreeInfoTbs::Update(TreePosition::new(group_id, leaf_index));
354 let mut leaf_node_tbs = LeafNodeTbs::from(self.clone(), tree_info);
355
356 if let Some(credential_with_key) = leaf_node_parmeters.credential_with_key {
358 leaf_node_tbs.payload.credential = credential_with_key.credential;
359 leaf_node_tbs.payload.signature_key = credential_with_key.signature_key;
360 }
361
362 if let Some(extensions) = leaf_node_parmeters.extensions {
364 leaf_node_tbs.payload.extensions = extensions;
365 }
366
367 if let Some(capabilities) = leaf_node_parmeters.capabilities {
369 leaf_node_tbs.payload.capabilities = capabilities;
370 }
371
372 let encryption_key_pair =
374 EncryptionKeyPair::random(provider.rand(), provider.crypto(), ciphersuite)?;
375 leaf_node_tbs.payload.encryption_key = encryption_key_pair.public_key().clone();
376
377 encryption_key_pair
379 .write(provider.storage())
380 .map_err(LeafNodeUpdateError::Storage)?;
381
382 leaf_node_tbs.payload.leaf_node_source = LeafNodeSource::Update;
384
385 let leaf_node = leaf_node_tbs.sign(signer)?;
387 self.payload = leaf_node.payload;
388 self.signature = leaf_node.signature;
389
390 Ok(encryption_key_pair)
391 }
392
393 pub fn encryption_key(&self) -> &EncryptionKey {
395 &self.payload.encryption_key
396 }
397
398 pub fn signature_key(&self) -> &SignaturePublicKey {
400 &self.payload.signature_key
401 }
402
403 pub fn credential(&self) -> &Credential {
405 &self.payload.credential
406 }
407
408 pub fn parent_hash(&self) -> Option<&[u8]> {
410 match &self.payload.leaf_node_source {
411 LeafNodeSource::Commit(ph) => Some(ph.as_slice()),
412 _ => None,
413 }
414 }
415
416 pub(crate) fn life_time(&self) -> Option<&Lifetime> {
419 if let LeafNodeSource::KeyPackage(life_time) = &self.payload.leaf_node_source {
420 Some(life_time)
421 } else {
422 None
423 }
424 }
425
426 pub fn signature(&self) -> &Signature {
428 &self.signature
429 }
430
431 pub fn capabilities(&self) -> &Capabilities {
433 &self.payload.capabilities
434 }
435
436 pub fn leaf_node_source(&self) -> &LeafNodeSource {
438 &self.payload.leaf_node_source
439 }
440
441 pub fn extensions(&self) -> &Extensions<LeafNode> {
443 &self.payload.extensions
444 }
445
446 pub(crate) fn supports_extension(&self, extension_type: &ExtensionType) -> bool {
448 extension_type.is_default()
449 || self
450 .payload
451 .capabilities
452 .extensions
453 .contains(extension_type)
454 }
455
456 pub(crate) fn check_extension_support(
459 &self,
460 extensions: &[ExtensionType],
461 ) -> Result<(), LeafNodeValidationError> {
462 for required in extensions.iter() {
463 if !self.supports_extension(required) {
464 log::error!(
465 "Leaf node does not support required extension {:?}\n
466 Supported extensions: {:?}",
467 required,
468 self.payload.capabilities.extensions
469 );
470 return Err(LeafNodeValidationError::UnsupportedExtensions);
471 }
472 }
473 Ok(())
474 }
475
476 pub(crate) fn validate_locally(&self) -> Result<(), LeafNodeValidationError> {
481 let invalid_extension_types = self
490 .extensions()
491 .iter()
492 .filter(|ext| !ext.extension_type().is_valid_in_leaf_node())
493 .collect::<Vec<_>>();
494 if !invalid_extension_types.is_empty() {
495 log::error!("Invalid extension used in leaf node: {invalid_extension_types:?}");
496 return Err(LeafNodeValidationError::UnsupportedExtensions);
497 }
498
499 if !self.capabilities().contains_extensions(self.extensions()) {
501 log::error!(
502 "Leaf node does not support all extensions it uses\n
503 Supported extensions: {:?}\n
504 Used extensions: {:?}",
505 self.payload.capabilities.extensions,
506 self.extensions()
507 );
508 return Err(LeafNodeValidationError::UnsupportedExtensions);
509 }
510
511 if !self
514 .capabilities()
515 .contains_credential(self.credential().credential_type())
516 {
517 return Err(LeafNodeValidationError::UnsupportedCredentials);
518 }
519
520 Ok(())
521 }
522}
523
524#[derive(
550 Debug,
551 Clone,
552 PartialEq,
553 Eq,
554 Serialize,
555 Deserialize,
556 TlsSerialize,
557 TlsDeserialize,
558 TlsDeserializeBytes,
559 TlsSize,
560)]
561struct LeafNodePayload {
562 encryption_key: EncryptionKey,
563 signature_key: SignaturePublicKey,
564 credential: Credential,
565 capabilities: Capabilities,
566 leaf_node_source: LeafNodeSource,
567 extensions: Extensions<LeafNode>,
568}
569
570#[derive(
572 Debug,
573 Clone,
574 PartialEq,
575 Eq,
576 Serialize,
577 Deserialize,
578 TlsSerialize,
579 TlsDeserialize,
580 TlsDeserializeBytes,
581 TlsSize,
582)]
583#[repr(u8)]
584pub enum LeafNodeSource {
585 #[tls_codec(discriminant = 1)]
587 KeyPackage(Lifetime),
588 Update,
590 Commit(ParentHash),
592}
593
594pub type ParentHash = VLBytes;
595
596#[derive(Debug, TlsSerialize, TlsSize)]
624pub struct LeafNodeTbs {
625 payload: LeafNodePayload,
626 tree_info_tbs: TreeInfoTbs,
627}
628
629impl LeafNodeTbs {
630 pub(crate) fn from(leaf_node: LeafNode, tree_info_tbs: TreeInfoTbs) -> Self {
633 Self {
634 payload: leaf_node.payload,
635 tree_info_tbs,
636 }
637 }
638
639 pub(crate) fn new(
642 encryption_key: EncryptionKey,
643 credential_with_key: CredentialWithKey,
644 capabilities: Capabilities,
645 leaf_node_source: LeafNodeSource,
646 extensions: Extensions<LeafNode>,
647 tree_info_tbs: TreeInfoTbs,
648 ) -> Self {
649 let payload = LeafNodePayload {
650 encryption_key,
651 signature_key: credential_with_key.signature_key,
652 credential: credential_with_key.credential,
653 capabilities,
654 leaf_node_source,
655 extensions,
656 };
657
658 LeafNodeTbs {
659 payload,
660 tree_info_tbs,
661 }
662 }
663}
664
665#[derive(Debug)]
687pub(crate) enum TreeInfoTbs {
688 KeyPackage,
689 Update(TreePosition),
690 Commit(TreePosition),
691}
692
693#[derive(Debug, Clone, PartialEq, Eq, TlsSerialize, TlsSize)]
694pub(crate) struct TreePosition {
695 group_id: GroupId,
696 leaf_index: LeafNodeIndex,
697}
698
699impl TreePosition {
700 pub(crate) fn new(group_id: GroupId, leaf_index: LeafNodeIndex) -> Self {
701 Self {
702 group_id,
703 leaf_index,
704 }
705 }
706
707 #[cfg(feature = "test-utils")]
708 pub(crate) fn into_parts(self) -> (GroupId, LeafNodeIndex) {
709 (self.group_id, self.leaf_index)
710 }
711}
712
713const LEAF_NODE_SIGNATURE_LABEL: &str = "LeafNodeTBS";
714
715#[derive(
716 Debug,
717 Clone,
718 PartialEq,
719 Eq,
720 Serialize,
721 Deserialize,
722 TlsSerialize,
723 TlsDeserialize,
724 TlsDeserializeBytes,
725 TlsSize,
726)]
727pub struct LeafNodeIn {
728 payload: LeafNodePayload,
729 signature: Signature,
730}
731
732impl LeafNodeIn {
733 pub(crate) fn into_verifiable_leaf_node(self) -> VerifiableLeafNode {
734 match self.payload.leaf_node_source {
735 LeafNodeSource::KeyPackage(_) => {
736 let verifiable = VerifiableKeyPackageLeafNode {
737 payload: self.payload,
738 signature: self.signature,
739 };
740 VerifiableLeafNode::KeyPackage(verifiable)
741 }
742 LeafNodeSource::Update => {
743 let verifiable = VerifiableUpdateLeafNode {
744 payload: self.payload,
745 signature: self.signature,
746 tree_position: None,
747 };
748 VerifiableLeafNode::Update(verifiable)
749 }
750 LeafNodeSource::Commit(_) => {
751 let verifiable = VerifiableCommitLeafNode {
752 payload: self.payload,
753 signature: self.signature,
754 tree_position: None,
755 };
756 VerifiableLeafNode::Commit(verifiable)
757 }
758 }
759 }
760
761 pub fn encryption_key(&self) -> &EncryptionKey {
763 &self.payload.encryption_key
764 }
765
766 pub fn signature_key(&self) -> &SignaturePublicKey {
768 &self.payload.signature_key
769 }
770
771 pub fn credential(&self) -> &Credential {
773 &self.payload.credential
774 }
775}
776
777impl From<LeafNode> for LeafNodeIn {
778 fn from(leaf_node: LeafNode) -> Self {
779 Self {
780 payload: leaf_node.payload,
781 signature: leaf_node.signature,
782 }
783 }
784}
785
786#[cfg(any(feature = "test-utils", test))]
787impl From<LeafNodeIn> for LeafNode {
788 fn from(deserialized: LeafNodeIn) -> Self {
789 Self {
790 payload: deserialized.payload,
791 signature: deserialized.signature,
792 }
793 }
794}
795
796impl From<KeyPackage> for LeafNode {
797 fn from(key_package: KeyPackage) -> Self {
798 key_package.leaf_node().clone()
799 }
800}
801
802impl From<KeyPackageBundle> for LeafNode {
803 fn from(key_package: KeyPackageBundle) -> Self {
804 key_package.key_package().leaf_node().clone()
805 }
806}
807
808#[derive(Debug, Clone, PartialEq, Eq)]
809pub(crate) enum VerifiableLeafNode {
810 KeyPackage(VerifiableKeyPackageLeafNode),
811 Update(VerifiableUpdateLeafNode),
812 Commit(VerifiableCommitLeafNode),
813}
814
815impl VerifiableLeafNode {
816 pub(crate) fn signature_key(&self) -> &SignaturePublicKey {
817 match self {
818 VerifiableLeafNode::KeyPackage(v) => v.signature_key(),
819 VerifiableLeafNode::Update(v) => v.signature_key(),
820 VerifiableLeafNode::Commit(v) => v.signature_key(),
821 }
822 }
823}
824
825#[derive(Debug, Clone, PartialEq, Eq)]
826pub(crate) struct VerifiableKeyPackageLeafNode {
827 payload: LeafNodePayload,
828 signature: Signature,
829}
830
831impl VerifiableKeyPackageLeafNode {
832 pub(crate) fn signature_key(&self) -> &SignaturePublicKey {
833 &self.payload.signature_key
834 }
835}
836
837impl Verifiable for VerifiableKeyPackageLeafNode {
839 type VerifiedStruct = LeafNode;
840
841 fn unsigned_payload(&self) -> Result<Vec<u8>, tls_codec::Error> {
842 self.payload.tls_serialize_detached()
843 }
844
845 fn signature(&self) -> &Signature {
846 &self.signature
847 }
848
849 fn label(&self) -> &str {
850 LEAF_NODE_SIGNATURE_LABEL
851 }
852
853 fn verify(
854 self,
855 crypto: &impl openmls_traits::crypto::OpenMlsCrypto,
856 pk: &crate::ciphersuite::OpenMlsSignaturePublicKey,
857 ) -> Result<Self::VerifiedStruct, crate::ciphersuite::signable::SignatureError> {
858 self.verify_no_out(crypto, pk)?;
859 Ok(LeafNode {
860 payload: self.payload,
861 signature: self.signature,
862 })
863 }
864}
865
866impl VerifiedStruct for LeafNode {}
867
868#[derive(Debug, Clone, PartialEq, Eq)]
869pub(crate) struct VerifiableUpdateLeafNode {
870 payload: LeafNodePayload,
871 signature: Signature,
872 tree_position: Option<TreePosition>,
873}
874
875impl VerifiableUpdateLeafNode {
876 pub(crate) fn add_tree_position(&mut self, tree_info: TreePosition) {
877 self.tree_position = Some(tree_info);
878 }
879
880 pub(crate) fn signature_key(&self) -> &SignaturePublicKey {
881 &self.payload.signature_key
882 }
883}
884
885impl Verifiable for VerifiableUpdateLeafNode {
886 type VerifiedStruct = LeafNode;
887
888 fn unsigned_payload(&self) -> Result<Vec<u8>, tls_codec::Error> {
889 let tree_info_tbs = match &self.tree_position {
890 Some(tree_position) => TreeInfoTbs::Commit(tree_position.clone()),
891 None => return Err(tls_codec::Error::InvalidInput),
892 };
893 let leaf_node_tbs = LeafNodeTbs {
894 payload: self.payload.clone(),
895 tree_info_tbs,
896 };
897 leaf_node_tbs.tls_serialize_detached()
898 }
899
900 fn signature(&self) -> &Signature {
901 &self.signature
902 }
903
904 fn label(&self) -> &str {
905 LEAF_NODE_SIGNATURE_LABEL
906 }
907
908 fn verify(
909 self,
910 crypto: &impl openmls_traits::crypto::OpenMlsCrypto,
911 pk: &crate::ciphersuite::OpenMlsSignaturePublicKey,
912 ) -> Result<Self::VerifiedStruct, crate::ciphersuite::signable::SignatureError> {
913 self.verify_no_out(crypto, pk)?;
914 Ok(LeafNode {
915 payload: self.payload,
916 signature: self.signature,
917 })
918 }
919}
920
921#[derive(Debug, Clone, PartialEq, Eq)]
922pub(crate) struct VerifiableCommitLeafNode {
923 payload: LeafNodePayload,
924 signature: Signature,
925 tree_position: Option<TreePosition>,
926}
927
928impl VerifiableCommitLeafNode {
929 pub(crate) fn add_tree_position(&mut self, tree_info: TreePosition) {
930 self.tree_position = Some(tree_info);
931 }
932
933 pub(crate) fn signature_key(&self) -> &SignaturePublicKey {
934 &self.payload.signature_key
935 }
936}
937
938impl Verifiable for VerifiableCommitLeafNode {
939 type VerifiedStruct = LeafNode;
940
941 fn unsigned_payload(&self) -> Result<Vec<u8>, tls_codec::Error> {
942 let tree_info_tbs = match &self.tree_position {
943 Some(tree_position) => TreeInfoTbs::Commit(tree_position.clone()),
944 None => return Err(tls_codec::Error::InvalidInput),
945 };
946 let leaf_node_tbs = LeafNodeTbs {
947 payload: self.payload.clone(),
948 tree_info_tbs,
949 };
950
951 leaf_node_tbs.tls_serialize_detached()
952 }
953
954 fn signature(&self) -> &Signature {
955 &self.signature
956 }
957
958 fn label(&self) -> &str {
959 LEAF_NODE_SIGNATURE_LABEL
960 }
961
962 fn verify(
963 self,
964 crypto: &impl openmls_traits::crypto::OpenMlsCrypto,
965 pk: &crate::ciphersuite::OpenMlsSignaturePublicKey,
966 ) -> Result<Self::VerifiedStruct, crate::ciphersuite::signable::SignatureError> {
967 self.verify_no_out(crypto, pk)?;
968 Ok(LeafNode {
969 payload: self.payload,
970 signature: self.signature,
971 })
972 }
973}
974
975impl Signable for LeafNodeTbs {
976 type SignedOutput = LeafNode;
977
978 fn unsigned_payload(&self) -> Result<Vec<u8>, tls_codec::Error> {
979 self.tls_serialize_detached()
980 }
981
982 fn label(&self) -> &str {
983 LEAF_NODE_SIGNATURE_LABEL
984 }
985}
986
987impl SignedStruct<LeafNodeTbs> for LeafNode {
988 fn from_payload(tbs: LeafNodeTbs, signature: Signature, _serialized_payload: Vec<u8>) -> Self {
989 Self {
990 payload: tbs.payload,
991 signature,
992 }
993 }
994}
995
996#[cfg(test)]
997#[derive(Error, Debug, PartialEq, Clone)]
998pub enum LeafNodeGenerationError<StorageError> {
999 #[error(transparent)]
1001 LibraryError(#[from] LibraryError),
1002
1003 #[error("Error storing leaf private key.")]
1005 StorageError(StorageError),
1006}
1007
1008#[derive(Error, Debug, PartialEq, Clone)]
1010pub enum LeafNodeUpdateError<StorageError> {
1011 #[error(transparent)]
1013 LibraryError(#[from] LibraryError),
1014
1015 #[error("Error storing leaf private key.")]
1017 Storage(StorageError),
1018
1019 #[error(transparent)]
1021 Signature(#[from] crate::ciphersuite::signable::SignatureError),
1022}