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,
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(mut self, extensions: Extensions) -> Self {
130 self.extensions = Some(extensions);
131 self
132 }
133
134 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#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, TlsSerialize, TlsSize)]
172pub struct LeafNode {
173 payload: LeafNodePayload,
174 signature: Signature,
175}
176
177impl LeafNode {
178 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 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 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 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 #[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 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 #[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 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 encryption_key_pair
329 .write(provider.storage())
330 .map_err(LeafNodeGenerationError::StorageError)?;
331
332 Ok(leaf_node)
333 }
334
335 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 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 if let Some(extensions) = leaf_node_parmeters.extensions {
362 leaf_node_tbs.payload.extensions = extensions;
363 }
364
365 if let Some(capabilities) = leaf_node_parmeters.capabilities {
367 leaf_node_tbs.payload.capabilities = capabilities;
368 }
369
370 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 encryption_key_pair
377 .write(provider.storage())
378 .map_err(LeafNodeUpdateError::Storage)?;
379
380 leaf_node_tbs.payload.leaf_node_source = LeafNodeSource::Update;
382
383 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 pub fn encryption_key(&self) -> &EncryptionKey {
393 &self.payload.encryption_key
394 }
395
396 pub fn signature_key(&self) -> &SignaturePublicKey {
398 &self.payload.signature_key
399 }
400
401 pub fn credential(&self) -> &Credential {
403 &self.payload.credential
404 }
405
406 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 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 pub fn signature(&self) -> &Signature {
426 &self.signature
427 }
428
429 pub fn capabilities(&self) -> &Capabilities {
431 &self.payload.capabilities
432 }
433
434 pub fn leaf_node_source(&self) -> &LeafNodeSource {
436 &self.payload.leaf_node_source
437 }
438
439 pub fn extensions(&self) -> &Extensions {
441 &self.payload.extensions
442 }
443
444 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 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 pub(crate) fn validate_locally(&self) -> Result<(), LeafNodeValidationError> {
479 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!(
487 "Invalid extension used in leaf node: {:?}",
488 invalid_extension_types
489 );
490 return Err(LeafNodeValidationError::UnsupportedExtensions);
491 }
492
493 if !self.capabilities().contains_extensions(self.extensions()) {
495 log::error!(
496 "Leaf node does not support all extensions it uses\n
497 Supported extensions: {:?}\n
498 Used extensions: {:?}",
499 self.payload.capabilities.extensions,
500 self.extensions()
501 );
502 return Err(LeafNodeValidationError::UnsupportedExtensions);
503 }
504
505 if !self
508 .capabilities()
509 .contains_credential(self.credential().credential_type())
510 {
511 return Err(LeafNodeValidationError::UnsupportedCredentials);
512 }
513
514 Ok(())
515 }
516}
517
518#[derive(
544 Debug,
545 Clone,
546 PartialEq,
547 Eq,
548 Serialize,
549 Deserialize,
550 TlsSerialize,
551 TlsDeserialize,
552 TlsDeserializeBytes,
553 TlsSize,
554)]
555struct LeafNodePayload {
556 encryption_key: EncryptionKey,
557 signature_key: SignaturePublicKey,
558 credential: Credential,
559 capabilities: Capabilities,
560 leaf_node_source: LeafNodeSource,
561 extensions: Extensions,
562}
563
564#[derive(
566 Debug,
567 Clone,
568 PartialEq,
569 Eq,
570 Serialize,
571 Deserialize,
572 TlsSerialize,
573 TlsDeserialize,
574 TlsDeserializeBytes,
575 TlsSize,
576)]
577#[repr(u8)]
578pub enum LeafNodeSource {
579 #[tls_codec(discriminant = 1)]
581 KeyPackage(Lifetime),
582 Update,
584 Commit(ParentHash),
586}
587
588pub type ParentHash = VLBytes;
589
590#[derive(Debug, TlsSerialize, TlsSize)]
618pub struct LeafNodeTbs {
619 payload: LeafNodePayload,
620 tree_info_tbs: TreeInfoTbs,
621}
622
623impl LeafNodeTbs {
624 pub(crate) fn from(leaf_node: LeafNode, tree_info_tbs: TreeInfoTbs) -> Self {
627 Self {
628 payload: leaf_node.payload,
629 tree_info_tbs,
630 }
631 }
632
633 pub(crate) fn new(
636 encryption_key: EncryptionKey,
637 credential_with_key: CredentialWithKey,
638 capabilities: Capabilities,
639 leaf_node_source: LeafNodeSource,
640 extensions: Extensions,
641 tree_info_tbs: TreeInfoTbs,
642 ) -> Self {
643 let payload = LeafNodePayload {
644 encryption_key,
645 signature_key: credential_with_key.signature_key,
646 credential: credential_with_key.credential,
647 capabilities,
648 leaf_node_source,
649 extensions,
650 };
651
652 LeafNodeTbs {
653 payload,
654 tree_info_tbs,
655 }
656 }
657}
658
659#[derive(Debug)]
681pub(crate) enum TreeInfoTbs {
682 KeyPackage,
683 Update(TreePosition),
684 Commit(TreePosition),
685}
686
687#[derive(Debug, Clone, PartialEq, Eq, TlsSerialize, TlsSize)]
688pub(crate) struct TreePosition {
689 group_id: GroupId,
690 leaf_index: LeafNodeIndex,
691}
692
693impl TreePosition {
694 pub(crate) fn new(group_id: GroupId, leaf_index: LeafNodeIndex) -> Self {
695 Self {
696 group_id,
697 leaf_index,
698 }
699 }
700
701 #[cfg(feature = "test-utils")]
702 pub(crate) fn into_parts(self) -> (GroupId, LeafNodeIndex) {
703 (self.group_id, self.leaf_index)
704 }
705}
706
707const LEAF_NODE_SIGNATURE_LABEL: &str = "LeafNodeTBS";
708
709#[derive(
710 Debug,
711 Clone,
712 PartialEq,
713 Eq,
714 Serialize,
715 Deserialize,
716 TlsSerialize,
717 TlsDeserialize,
718 TlsDeserializeBytes,
719 TlsSize,
720)]
721pub struct LeafNodeIn {
722 payload: LeafNodePayload,
723 signature: Signature,
724}
725
726impl LeafNodeIn {
727 pub(crate) fn into_verifiable_leaf_node(self) -> VerifiableLeafNode {
728 match self.payload.leaf_node_source {
729 LeafNodeSource::KeyPackage(_) => {
730 let verifiable = VerifiableKeyPackageLeafNode {
731 payload: self.payload,
732 signature: self.signature,
733 };
734 VerifiableLeafNode::KeyPackage(verifiable)
735 }
736 LeafNodeSource::Update => {
737 let verifiable = VerifiableUpdateLeafNode {
738 payload: self.payload,
739 signature: self.signature,
740 tree_position: None,
741 };
742 VerifiableLeafNode::Update(verifiable)
743 }
744 LeafNodeSource::Commit(_) => {
745 let verifiable = VerifiableCommitLeafNode {
746 payload: self.payload,
747 signature: self.signature,
748 tree_position: None,
749 };
750 VerifiableLeafNode::Commit(verifiable)
751 }
752 }
753 }
754
755 pub fn encryption_key(&self) -> &EncryptionKey {
757 &self.payload.encryption_key
758 }
759
760 pub fn signature_key(&self) -> &SignaturePublicKey {
762 &self.payload.signature_key
763 }
764
765 pub fn credential(&self) -> &Credential {
767 &self.payload.credential
768 }
769}
770
771impl From<LeafNode> for LeafNodeIn {
772 fn from(leaf_node: LeafNode) -> Self {
773 Self {
774 payload: leaf_node.payload,
775 signature: leaf_node.signature,
776 }
777 }
778}
779
780#[cfg(any(feature = "test-utils", test))]
781impl From<LeafNodeIn> for LeafNode {
782 fn from(deserialized: LeafNodeIn) -> Self {
783 Self {
784 payload: deserialized.payload,
785 signature: deserialized.signature,
786 }
787 }
788}
789
790impl From<KeyPackage> for LeafNode {
791 fn from(key_package: KeyPackage) -> Self {
792 key_package.leaf_node().clone()
793 }
794}
795
796impl From<KeyPackageBundle> for LeafNode {
797 fn from(key_package: KeyPackageBundle) -> Self {
798 key_package.key_package().leaf_node().clone()
799 }
800}
801
802#[derive(Debug, Clone, PartialEq, Eq)]
803pub(crate) enum VerifiableLeafNode {
804 KeyPackage(VerifiableKeyPackageLeafNode),
805 Update(VerifiableUpdateLeafNode),
806 Commit(VerifiableCommitLeafNode),
807}
808
809impl VerifiableLeafNode {
810 pub(crate) fn signature_key(&self) -> &SignaturePublicKey {
811 match self {
812 VerifiableLeafNode::KeyPackage(v) => v.signature_key(),
813 VerifiableLeafNode::Update(v) => v.signature_key(),
814 VerifiableLeafNode::Commit(v) => v.signature_key(),
815 }
816 }
817}
818
819#[derive(Debug, Clone, PartialEq, Eq)]
820pub(crate) struct VerifiableKeyPackageLeafNode {
821 payload: LeafNodePayload,
822 signature: Signature,
823}
824
825impl VerifiableKeyPackageLeafNode {
826 pub(crate) fn signature_key(&self) -> &SignaturePublicKey {
827 &self.payload.signature_key
828 }
829}
830
831impl Verifiable for VerifiableKeyPackageLeafNode {
833 type VerifiedStruct = LeafNode;
834
835 fn unsigned_payload(&self) -> Result<Vec<u8>, tls_codec::Error> {
836 self.payload.tls_serialize_detached()
837 }
838
839 fn signature(&self) -> &Signature {
840 &self.signature
841 }
842
843 fn label(&self) -> &str {
844 LEAF_NODE_SIGNATURE_LABEL
845 }
846
847 fn verify(
848 self,
849 crypto: &impl openmls_traits::crypto::OpenMlsCrypto,
850 pk: &crate::ciphersuite::OpenMlsSignaturePublicKey,
851 ) -> Result<Self::VerifiedStruct, crate::ciphersuite::signable::SignatureError> {
852 self.verify_no_out(crypto, pk)?;
853 Ok(LeafNode {
854 payload: self.payload,
855 signature: self.signature,
856 })
857 }
858}
859
860impl VerifiedStruct for LeafNode {}
861
862#[derive(Debug, Clone, PartialEq, Eq)]
863pub(crate) struct VerifiableUpdateLeafNode {
864 payload: LeafNodePayload,
865 signature: Signature,
866 tree_position: Option<TreePosition>,
867}
868
869impl VerifiableUpdateLeafNode {
870 pub(crate) fn add_tree_position(&mut self, tree_info: TreePosition) {
871 self.tree_position = Some(tree_info);
872 }
873
874 pub(crate) fn signature_key(&self) -> &SignaturePublicKey {
875 &self.payload.signature_key
876 }
877}
878
879impl Verifiable for VerifiableUpdateLeafNode {
880 type VerifiedStruct = LeafNode;
881
882 fn unsigned_payload(&self) -> Result<Vec<u8>, tls_codec::Error> {
883 let tree_info_tbs = match &self.tree_position {
884 Some(tree_position) => TreeInfoTbs::Commit(tree_position.clone()),
885 None => return Err(tls_codec::Error::InvalidInput),
886 };
887 let leaf_node_tbs = LeafNodeTbs {
888 payload: self.payload.clone(),
889 tree_info_tbs,
890 };
891 leaf_node_tbs.tls_serialize_detached()
892 }
893
894 fn signature(&self) -> &Signature {
895 &self.signature
896 }
897
898 fn label(&self) -> &str {
899 LEAF_NODE_SIGNATURE_LABEL
900 }
901
902 fn verify(
903 self,
904 crypto: &impl openmls_traits::crypto::OpenMlsCrypto,
905 pk: &crate::ciphersuite::OpenMlsSignaturePublicKey,
906 ) -> Result<Self::VerifiedStruct, crate::ciphersuite::signable::SignatureError> {
907 self.verify_no_out(crypto, pk)?;
908 Ok(LeafNode {
909 payload: self.payload,
910 signature: self.signature,
911 })
912 }
913}
914
915#[derive(Debug, Clone, PartialEq, Eq)]
916pub(crate) struct VerifiableCommitLeafNode {
917 payload: LeafNodePayload,
918 signature: Signature,
919 tree_position: Option<TreePosition>,
920}
921
922impl VerifiableCommitLeafNode {
923 pub(crate) fn add_tree_position(&mut self, tree_info: TreePosition) {
924 self.tree_position = Some(tree_info);
925 }
926
927 pub(crate) fn signature_key(&self) -> &SignaturePublicKey {
928 &self.payload.signature_key
929 }
930}
931
932impl Verifiable for VerifiableCommitLeafNode {
933 type VerifiedStruct = LeafNode;
934
935 fn unsigned_payload(&self) -> Result<Vec<u8>, tls_codec::Error> {
936 let tree_info_tbs = match &self.tree_position {
937 Some(tree_position) => TreeInfoTbs::Commit(tree_position.clone()),
938 None => return Err(tls_codec::Error::InvalidInput),
939 };
940 let leaf_node_tbs = LeafNodeTbs {
941 payload: self.payload.clone(),
942 tree_info_tbs,
943 };
944
945 leaf_node_tbs.tls_serialize_detached()
946 }
947
948 fn signature(&self) -> &Signature {
949 &self.signature
950 }
951
952 fn label(&self) -> &str {
953 LEAF_NODE_SIGNATURE_LABEL
954 }
955
956 fn verify(
957 self,
958 crypto: &impl openmls_traits::crypto::OpenMlsCrypto,
959 pk: &crate::ciphersuite::OpenMlsSignaturePublicKey,
960 ) -> Result<Self::VerifiedStruct, crate::ciphersuite::signable::SignatureError> {
961 self.verify_no_out(crypto, pk)?;
962 Ok(LeafNode {
963 payload: self.payload,
964 signature: self.signature,
965 })
966 }
967}
968
969impl Signable for LeafNodeTbs {
970 type SignedOutput = LeafNode;
971
972 fn unsigned_payload(&self) -> Result<Vec<u8>, tls_codec::Error> {
973 self.tls_serialize_detached()
974 }
975
976 fn label(&self) -> &str {
977 LEAF_NODE_SIGNATURE_LABEL
978 }
979}
980
981impl SignedStruct<LeafNodeTbs> for LeafNode {
982 fn from_payload(tbs: LeafNodeTbs, signature: Signature) -> Self {
983 Self {
984 payload: tbs.payload,
985 signature,
986 }
987 }
988}
989
990#[cfg(test)]
991#[derive(Error, Debug, PartialEq, Clone)]
992pub enum LeafNodeGenerationError<StorageError> {
993 #[error(transparent)]
995 LibraryError(#[from] LibraryError),
996
997 #[error("Error storing leaf private key.")]
999 StorageError(StorageError),
1000}
1001
1002#[derive(Error, Debug, PartialEq, Clone)]
1004pub enum LeafNodeUpdateError<StorageError> {
1005 #[error(transparent)]
1007 LibraryError(#[from] LibraryError),
1008
1009 #[error("Error storing leaf private key.")]
1011 Storage(StorageError),
1012
1013 #[error(transparent)]
1015 Signature(#[from] crate::ciphersuite::signable::SignatureError),
1016}