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::{errors::InvalidExtensionError, 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#[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#[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 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> {
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>,
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(
132 mut self,
133 extensions: Extensions,
134 ) -> Result<Self, InvalidExtensionError> {
135 extensions.validate_extension_types_for_leaf_node()?;
137
138 self.extensions = Some(extensions);
139 Ok(self)
140 }
141
142 pub fn build(self) -> LeafNodeParameters {
144 LeafNodeParameters {
145 credential_with_key: self.credential_with_key,
146 capabilities: self.capabilities,
147 extensions: self.extensions,
148 }
149 }
150}
151
152#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, TlsSerialize, TlsSize)]
180pub struct LeafNode {
181 payload: LeafNodePayload,
182 signature: Signature,
183}
184
185impl LeafNode {
186 pub(crate) fn new(
194 provider: &impl OpenMlsProvider,
195 signer: &impl Signer,
196 new_leaf_node_params: NewLeafNodeParams,
197 ) -> Result<(Self, EncryptionKeyPair), LibraryError> {
198 let NewLeafNodeParams {
199 ciphersuite,
200 credential_with_key,
201 leaf_node_source,
202 capabilities,
203 extensions,
204 tree_info_tbs,
205 } = new_leaf_node_params;
206
207 let encryption_key_pair =
209 EncryptionKeyPair::random(provider.rand(), provider.crypto(), ciphersuite)?;
210
211 let leaf_node = Self::new_with_key(
212 encryption_key_pair.public_key().clone(),
213 credential_with_key,
214 leaf_node_source,
215 capabilities,
216 extensions,
217 tree_info_tbs,
218 signer,
219 )?;
220
221 Ok((leaf_node, encryption_key_pair))
222 }
223
224 pub(crate) fn new_placeholder() -> Self {
230 let payload = LeafNodePayload {
231 encryption_key: EncryptionKey::from(Vec::new()),
232 signature_key: Vec::new().into(),
233 credential: Credential::new(CredentialType::Basic, Vec::new()),
234 capabilities: Capabilities::default(),
235 leaf_node_source: LeafNodeSource::Update,
236 extensions: Extensions::default(),
237 };
238
239 Self {
240 payload,
241 signature: Vec::new().into(),
242 }
243 }
244
245 fn new_with_key(
248 encryption_key: EncryptionKey,
249 credential_with_key: CredentialWithKey,
250 leaf_node_source: LeafNodeSource,
251 capabilities: Capabilities,
252 extensions: Extensions,
253 tree_info_tbs: TreeInfoTbs,
254 signer: &impl Signer,
255 ) -> Result<Self, LibraryError> {
256 let leaf_node_tbs = LeafNodeTbs::new(
257 encryption_key,
258 credential_with_key,
259 capabilities,
260 leaf_node_source,
261 extensions,
262 tree_info_tbs,
263 );
264
265 leaf_node_tbs
266 .sign(signer)
267 .map_err(|_| LibraryError::custom("Signing failed"))
268 }
269
270 #[allow(clippy::too_many_arguments)]
272 pub(in crate::treesync) fn new_with_parent_hash(
273 rand: &impl OpenMlsRand,
274 crypto: &impl OpenMlsCrypto,
275 ciphersuite: Ciphersuite,
276 parent_hash: &[u8],
277 leaf_node_params: UpdateLeafNodeParams,
278 group_id: GroupId,
279 leaf_index: LeafNodeIndex,
280 signer: &impl Signer,
281 ) -> Result<(Self, EncryptionKeyPair), LibraryError> {
282 let encryption_key_pair = EncryptionKeyPair::random(rand, crypto, ciphersuite)?;
283
284 let leaf_node_tbs = LeafNodeTbs::new(
285 encryption_key_pair.public_key().clone(),
286 leaf_node_params.credential_with_key,
287 leaf_node_params.capabilities,
288 LeafNodeSource::Commit(parent_hash.into()),
289 leaf_node_params.extensions,
290 TreeInfoTbs::Commit(TreePosition {
291 group_id,
292 leaf_index,
293 }),
294 );
295
296 let leaf_node = leaf_node_tbs
298 .sign(signer)
299 .map_err(|_| LibraryError::custom("Signing failed"))?;
300
301 Ok((leaf_node, encryption_key_pair))
302 }
303
304 #[cfg(test)]
312 pub(crate) fn generate_update<Provider: OpenMlsProvider>(
313 ciphersuite: Ciphersuite,
314 credential_with_key: CredentialWithKey,
315 capabilities: Capabilities,
316 extensions: Extensions,
317 tree_info_tbs: TreeInfoTbs,
318 provider: &Provider,
319 signer: &impl Signer,
320 ) -> Result<Self, LeafNodeGenerationError<Provider::StorageError>> {
321 let new_leaf_node_params = NewLeafNodeParams {
325 ciphersuite,
326 credential_with_key,
327 leaf_node_source: LeafNodeSource::Update,
328 capabilities,
329 extensions,
330 tree_info_tbs,
331 };
332
333 let (leaf_node, encryption_key_pair) = Self::new(provider, signer, new_leaf_node_params)?;
334
335 encryption_key_pair
337 .write(provider.storage())
338 .map_err(LeafNodeGenerationError::StorageError)?;
339
340 Ok(leaf_node)
341 }
342
343 pub(crate) fn update<Provider: OpenMlsProvider>(
351 &mut self,
352 ciphersuite: Ciphersuite,
353 provider: &Provider,
354 signer: &impl Signer,
355 group_id: GroupId,
356 leaf_index: LeafNodeIndex,
357 leaf_node_parmeters: LeafNodeParameters,
358 ) -> Result<EncryptionKeyPair, LeafNodeUpdateError<Provider::StorageError>> {
359 let tree_info = TreeInfoTbs::Update(TreePosition::new(group_id, leaf_index));
360 let mut leaf_node_tbs = LeafNodeTbs::from(self.clone(), tree_info);
361
362 if let Some(credential_with_key) = leaf_node_parmeters.credential_with_key {
364 leaf_node_tbs.payload.credential = credential_with_key.credential;
365 leaf_node_tbs.payload.signature_key = credential_with_key.signature_key;
366 }
367
368 if let Some(extensions) = leaf_node_parmeters.extensions {
370 leaf_node_tbs.payload.extensions = extensions;
371 }
372
373 if let Some(capabilities) = leaf_node_parmeters.capabilities {
375 leaf_node_tbs.payload.capabilities = capabilities;
376 }
377
378 let encryption_key_pair =
380 EncryptionKeyPair::random(provider.rand(), provider.crypto(), ciphersuite)?;
381 leaf_node_tbs.payload.encryption_key = encryption_key_pair.public_key().clone();
382
383 encryption_key_pair
385 .write(provider.storage())
386 .map_err(LeafNodeUpdateError::Storage)?;
387
388 leaf_node_tbs.payload.leaf_node_source = LeafNodeSource::Update;
390
391 let leaf_node = leaf_node_tbs.sign(signer)?;
393 self.payload = leaf_node.payload;
394 self.signature = leaf_node.signature;
395
396 Ok(encryption_key_pair)
397 }
398
399 pub fn encryption_key(&self) -> &EncryptionKey {
401 &self.payload.encryption_key
402 }
403
404 pub fn signature_key(&self) -> &SignaturePublicKey {
406 &self.payload.signature_key
407 }
408
409 pub fn credential(&self) -> &Credential {
411 &self.payload.credential
412 }
413
414 pub fn parent_hash(&self) -> Option<&[u8]> {
416 match &self.payload.leaf_node_source {
417 LeafNodeSource::Commit(ph) => Some(ph.as_slice()),
418 _ => None,
419 }
420 }
421
422 pub(crate) fn life_time(&self) -> Option<&Lifetime> {
425 if let LeafNodeSource::KeyPackage(life_time) = &self.payload.leaf_node_source {
426 Some(life_time)
427 } else {
428 None
429 }
430 }
431
432 pub fn signature(&self) -> &Signature {
434 &self.signature
435 }
436
437 pub fn capabilities(&self) -> &Capabilities {
439 &self.payload.capabilities
440 }
441
442 pub fn leaf_node_source(&self) -> &LeafNodeSource {
444 &self.payload.leaf_node_source
445 }
446
447 pub fn extensions(&self) -> &Extensions {
449 &self.payload.extensions
450 }
451
452 pub(crate) fn supports_extension(&self, extension_type: &ExtensionType) -> bool {
454 extension_type.is_default()
455 || self
456 .payload
457 .capabilities
458 .extensions
459 .contains(extension_type)
460 }
461
462 pub(crate) fn check_extension_support(
465 &self,
466 extensions: &[ExtensionType],
467 ) -> Result<(), LeafNodeValidationError> {
468 for required in extensions.iter() {
469 if !self.supports_extension(required) {
470 log::error!(
471 "Leaf node does not support required extension {:?}\n
472 Supported extensions: {:?}",
473 required,
474 self.payload.capabilities.extensions
475 );
476 return Err(LeafNodeValidationError::UnsupportedExtensions);
477 }
478 }
479 Ok(())
480 }
481
482 pub(crate) fn validate_locally(&self) -> Result<(), LeafNodeValidationError> {
487 let invalid_extension_types = self
496 .extensions()
497 .iter()
498 .filter(|ext| ext.extension_type().is_valid_in_leaf_node() == Some(false))
499 .collect::<Vec<_>>();
500 if !invalid_extension_types.is_empty() {
501 log::error!("Invalid extension used in leaf node: {invalid_extension_types:?}");
502 return Err(LeafNodeValidationError::UnsupportedExtensions);
503 }
504
505 if !self.capabilities().contains_extensions(self.extensions()) {
507 log::error!(
508 "Leaf node does not support all extensions it uses\n
509 Supported extensions: {:?}\n
510 Used extensions: {:?}",
511 self.payload.capabilities.extensions,
512 self.extensions()
513 );
514 return Err(LeafNodeValidationError::UnsupportedExtensions);
515 }
516
517 if !self
520 .capabilities()
521 .contains_credential(self.credential().credential_type())
522 {
523 return Err(LeafNodeValidationError::UnsupportedCredentials);
524 }
525
526 Ok(())
527 }
528}
529
530#[derive(
556 Debug,
557 Clone,
558 PartialEq,
559 Eq,
560 Serialize,
561 Deserialize,
562 TlsSerialize,
563 TlsDeserialize,
564 TlsDeserializeBytes,
565 TlsSize,
566)]
567struct LeafNodePayload {
568 encryption_key: EncryptionKey,
569 signature_key: SignaturePublicKey,
570 credential: Credential,
571 capabilities: Capabilities,
572 leaf_node_source: LeafNodeSource,
573 extensions: Extensions,
574}
575
576#[derive(
578 Debug,
579 Clone,
580 PartialEq,
581 Eq,
582 Serialize,
583 Deserialize,
584 TlsSerialize,
585 TlsDeserialize,
586 TlsDeserializeBytes,
587 TlsSize,
588)]
589#[repr(u8)]
590pub enum LeafNodeSource {
591 #[tls_codec(discriminant = 1)]
593 KeyPackage(Lifetime),
594 Update,
596 Commit(ParentHash),
598}
599
600pub type ParentHash = VLBytes;
601
602#[derive(Debug, TlsSerialize, TlsSize)]
630pub struct LeafNodeTbs {
631 payload: LeafNodePayload,
632 tree_info_tbs: TreeInfoTbs,
633}
634
635impl LeafNodeTbs {
636 pub(crate) fn from(leaf_node: LeafNode, tree_info_tbs: TreeInfoTbs) -> Self {
639 Self {
640 payload: leaf_node.payload,
641 tree_info_tbs,
642 }
643 }
644
645 pub(crate) fn new(
648 encryption_key: EncryptionKey,
649 credential_with_key: CredentialWithKey,
650 capabilities: Capabilities,
651 leaf_node_source: LeafNodeSource,
652 extensions: Extensions,
653 tree_info_tbs: TreeInfoTbs,
654 ) -> Self {
655 let payload = LeafNodePayload {
656 encryption_key,
657 signature_key: credential_with_key.signature_key,
658 credential: credential_with_key.credential,
659 capabilities,
660 leaf_node_source,
661 extensions,
662 };
663
664 LeafNodeTbs {
665 payload,
666 tree_info_tbs,
667 }
668 }
669}
670
671#[derive(Debug)]
693pub(crate) enum TreeInfoTbs {
694 KeyPackage,
695 Update(TreePosition),
696 Commit(TreePosition),
697}
698
699#[derive(Debug, Clone, PartialEq, Eq, TlsSerialize, TlsSize)]
700pub(crate) struct TreePosition {
701 group_id: GroupId,
702 leaf_index: LeafNodeIndex,
703}
704
705impl TreePosition {
706 pub(crate) fn new(group_id: GroupId, leaf_index: LeafNodeIndex) -> Self {
707 Self {
708 group_id,
709 leaf_index,
710 }
711 }
712
713 #[cfg(feature = "test-utils")]
714 pub(crate) fn into_parts(self) -> (GroupId, LeafNodeIndex) {
715 (self.group_id, self.leaf_index)
716 }
717}
718
719const LEAF_NODE_SIGNATURE_LABEL: &str = "LeafNodeTBS";
720
721#[derive(
722 Debug,
723 Clone,
724 PartialEq,
725 Eq,
726 Serialize,
727 Deserialize,
728 TlsSerialize,
729 TlsDeserialize,
730 TlsDeserializeBytes,
731 TlsSize,
732)]
733pub struct LeafNodeIn {
734 payload: LeafNodePayload,
735 signature: Signature,
736}
737
738impl LeafNodeIn {
739 pub(crate) fn into_verifiable_leaf_node(self) -> VerifiableLeafNode {
740 match self.payload.leaf_node_source {
741 LeafNodeSource::KeyPackage(_) => {
742 let verifiable = VerifiableKeyPackageLeafNode {
743 payload: self.payload,
744 signature: self.signature,
745 };
746 VerifiableLeafNode::KeyPackage(verifiable)
747 }
748 LeafNodeSource::Update => {
749 let verifiable = VerifiableUpdateLeafNode {
750 payload: self.payload,
751 signature: self.signature,
752 tree_position: None,
753 };
754 VerifiableLeafNode::Update(verifiable)
755 }
756 LeafNodeSource::Commit(_) => {
757 let verifiable = VerifiableCommitLeafNode {
758 payload: self.payload,
759 signature: self.signature,
760 tree_position: None,
761 };
762 VerifiableLeafNode::Commit(verifiable)
763 }
764 }
765 }
766
767 pub fn encryption_key(&self) -> &EncryptionKey {
769 &self.payload.encryption_key
770 }
771
772 pub fn signature_key(&self) -> &SignaturePublicKey {
774 &self.payload.signature_key
775 }
776
777 pub fn credential(&self) -> &Credential {
779 &self.payload.credential
780 }
781}
782
783impl From<LeafNode> for LeafNodeIn {
784 fn from(leaf_node: LeafNode) -> Self {
785 Self {
786 payload: leaf_node.payload,
787 signature: leaf_node.signature,
788 }
789 }
790}
791
792#[cfg(any(feature = "test-utils", test))]
793impl From<LeafNodeIn> for LeafNode {
794 fn from(deserialized: LeafNodeIn) -> Self {
795 Self {
796 payload: deserialized.payload,
797 signature: deserialized.signature,
798 }
799 }
800}
801
802impl From<KeyPackage> for LeafNode {
803 fn from(key_package: KeyPackage) -> Self {
804 key_package.leaf_node().clone()
805 }
806}
807
808impl From<KeyPackageBundle> for LeafNode {
809 fn from(key_package: KeyPackageBundle) -> Self {
810 key_package.key_package().leaf_node().clone()
811 }
812}
813
814#[derive(Debug, Clone, PartialEq, Eq)]
815pub(crate) enum VerifiableLeafNode {
816 KeyPackage(VerifiableKeyPackageLeafNode),
817 Update(VerifiableUpdateLeafNode),
818 Commit(VerifiableCommitLeafNode),
819}
820
821impl VerifiableLeafNode {
822 pub(crate) fn signature_key(&self) -> &SignaturePublicKey {
823 match self {
824 VerifiableLeafNode::KeyPackage(v) => v.signature_key(),
825 VerifiableLeafNode::Update(v) => v.signature_key(),
826 VerifiableLeafNode::Commit(v) => v.signature_key(),
827 }
828 }
829}
830
831#[derive(Debug, Clone, PartialEq, Eq)]
832pub(crate) struct VerifiableKeyPackageLeafNode {
833 payload: LeafNodePayload,
834 signature: Signature,
835}
836
837impl VerifiableKeyPackageLeafNode {
838 pub(crate) fn signature_key(&self) -> &SignaturePublicKey {
839 &self.payload.signature_key
840 }
841}
842
843impl Verifiable for VerifiableKeyPackageLeafNode {
845 type VerifiedStruct = LeafNode;
846
847 fn unsigned_payload(&self) -> Result<Vec<u8>, tls_codec::Error> {
848 self.payload.tls_serialize_detached()
849 }
850
851 fn signature(&self) -> &Signature {
852 &self.signature
853 }
854
855 fn label(&self) -> &str {
856 LEAF_NODE_SIGNATURE_LABEL
857 }
858
859 fn verify(
860 self,
861 crypto: &impl openmls_traits::crypto::OpenMlsCrypto,
862 pk: &crate::ciphersuite::OpenMlsSignaturePublicKey,
863 ) -> Result<Self::VerifiedStruct, crate::ciphersuite::signable::SignatureError> {
864 self.verify_no_out(crypto, pk)?;
865 Ok(LeafNode {
866 payload: self.payload,
867 signature: self.signature,
868 })
869 }
870}
871
872impl VerifiedStruct for LeafNode {}
873
874#[derive(Debug, Clone, PartialEq, Eq)]
875pub(crate) struct VerifiableUpdateLeafNode {
876 payload: LeafNodePayload,
877 signature: Signature,
878 tree_position: Option<TreePosition>,
879}
880
881impl VerifiableUpdateLeafNode {
882 pub(crate) fn add_tree_position(&mut self, tree_info: TreePosition) {
883 self.tree_position = Some(tree_info);
884 }
885
886 pub(crate) fn signature_key(&self) -> &SignaturePublicKey {
887 &self.payload.signature_key
888 }
889}
890
891impl Verifiable for VerifiableUpdateLeafNode {
892 type VerifiedStruct = LeafNode;
893
894 fn unsigned_payload(&self) -> Result<Vec<u8>, tls_codec::Error> {
895 let tree_info_tbs = match &self.tree_position {
896 Some(tree_position) => TreeInfoTbs::Commit(tree_position.clone()),
897 None => return Err(tls_codec::Error::InvalidInput),
898 };
899 let leaf_node_tbs = LeafNodeTbs {
900 payload: self.payload.clone(),
901 tree_info_tbs,
902 };
903 leaf_node_tbs.tls_serialize_detached()
904 }
905
906 fn signature(&self) -> &Signature {
907 &self.signature
908 }
909
910 fn label(&self) -> &str {
911 LEAF_NODE_SIGNATURE_LABEL
912 }
913
914 fn verify(
915 self,
916 crypto: &impl openmls_traits::crypto::OpenMlsCrypto,
917 pk: &crate::ciphersuite::OpenMlsSignaturePublicKey,
918 ) -> Result<Self::VerifiedStruct, crate::ciphersuite::signable::SignatureError> {
919 self.verify_no_out(crypto, pk)?;
920 Ok(LeafNode {
921 payload: self.payload,
922 signature: self.signature,
923 })
924 }
925}
926
927#[derive(Debug, Clone, PartialEq, Eq)]
928pub(crate) struct VerifiableCommitLeafNode {
929 payload: LeafNodePayload,
930 signature: Signature,
931 tree_position: Option<TreePosition>,
932}
933
934impl VerifiableCommitLeafNode {
935 pub(crate) fn add_tree_position(&mut self, tree_info: TreePosition) {
936 self.tree_position = Some(tree_info);
937 }
938
939 pub(crate) fn signature_key(&self) -> &SignaturePublicKey {
940 &self.payload.signature_key
941 }
942}
943
944impl Verifiable for VerifiableCommitLeafNode {
945 type VerifiedStruct = LeafNode;
946
947 fn unsigned_payload(&self) -> Result<Vec<u8>, tls_codec::Error> {
948 let tree_info_tbs = match &self.tree_position {
949 Some(tree_position) => TreeInfoTbs::Commit(tree_position.clone()),
950 None => return Err(tls_codec::Error::InvalidInput),
951 };
952 let leaf_node_tbs = LeafNodeTbs {
953 payload: self.payload.clone(),
954 tree_info_tbs,
955 };
956
957 leaf_node_tbs.tls_serialize_detached()
958 }
959
960 fn signature(&self) -> &Signature {
961 &self.signature
962 }
963
964 fn label(&self) -> &str {
965 LEAF_NODE_SIGNATURE_LABEL
966 }
967
968 fn verify(
969 self,
970 crypto: &impl openmls_traits::crypto::OpenMlsCrypto,
971 pk: &crate::ciphersuite::OpenMlsSignaturePublicKey,
972 ) -> Result<Self::VerifiedStruct, crate::ciphersuite::signable::SignatureError> {
973 self.verify_no_out(crypto, pk)?;
974 Ok(LeafNode {
975 payload: self.payload,
976 signature: self.signature,
977 })
978 }
979}
980
981impl Signable for LeafNodeTbs {
982 type SignedOutput = LeafNode;
983
984 fn unsigned_payload(&self) -> Result<Vec<u8>, tls_codec::Error> {
985 self.tls_serialize_detached()
986 }
987
988 fn label(&self) -> &str {
989 LEAF_NODE_SIGNATURE_LABEL
990 }
991}
992
993impl SignedStruct<LeafNodeTbs> for LeafNode {
994 fn from_payload(tbs: LeafNodeTbs, signature: Signature) -> Self {
995 Self {
996 payload: tbs.payload,
997 signature,
998 }
999 }
1000}
1001
1002#[cfg(test)]
1003#[derive(Error, Debug, PartialEq, Clone)]
1004pub enum LeafNodeGenerationError<StorageError> {
1005 #[error(transparent)]
1007 LibraryError(#[from] LibraryError),
1008
1009 #[error("Error storing leaf private key.")]
1011 StorageError(StorageError),
1012}
1013
1014#[derive(Error, Debug, PartialEq, Clone)]
1016pub enum LeafNodeUpdateError<StorageError> {
1017 #[error(transparent)]
1019 LibraryError(#[from] LibraryError),
1020
1021 #[error("Error storing leaf private key.")]
1023 Storage(StorageError),
1024
1025 #[error(transparent)]
1027 Signature(#[from] crate::ciphersuite::signable::SignatureError),
1028}