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!("Invalid extension used in leaf node: {invalid_extension_types:?}");
487 return Err(LeafNodeValidationError::UnsupportedExtensions);
488 }
489
490 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 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#[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#[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 #[tls_codec(discriminant = 1)]
578 KeyPackage(Lifetime),
579 Update,
581 Commit(ParentHash),
583}
584
585pub type ParentHash = VLBytes;
586
587#[derive(Debug, TlsSerialize, TlsSize)]
615pub struct LeafNodeTbs {
616 payload: LeafNodePayload,
617 tree_info_tbs: TreeInfoTbs,
618}
619
620impl LeafNodeTbs {
621 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 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#[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 pub fn encryption_key(&self) -> &EncryptionKey {
754 &self.payload.encryption_key
755 }
756
757 pub fn signature_key(&self) -> &SignaturePublicKey {
759 &self.payload.signature_key
760 }
761
762 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
828impl 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 #[error(transparent)]
992 LibraryError(#[from] LibraryError),
993
994 #[error("Error storing leaf private key.")]
996 StorageError(StorageError),
997}
998
999#[derive(Error, Debug, PartialEq, Clone)]
1001pub enum LeafNodeUpdateError<StorageError> {
1002 #[error(transparent)]
1004 LibraryError(#[from] LibraryError),
1005
1006 #[error("Error storing leaf private key.")]
1008 Storage(StorageError),
1009
1010 #[error(transparent)]
1012 Signature(#[from] crate::ciphersuite::signable::SignatureError),
1013}