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 #[cfg(feature = "virtual-clients-draft")]
107 pub(crate) fn set_extensions(&mut self, extensions: Extensions<LeafNode>) {
108 self.extensions = Some(extensions);
109 }
110}
111
112#[derive(Debug, Default)]
114pub struct LeafNodeParametersBuilder {
115 credential_with_key: Option<CredentialWithKey>,
116 capabilities: Option<Capabilities>,
117 extensions: Option<Extensions<LeafNode>>,
118}
119
120impl LeafNodeParametersBuilder {
121 pub fn with_credential_with_key(mut self, credential_with_key: CredentialWithKey) -> Self {
123 self.credential_with_key = Some(credential_with_key);
124 self
125 }
126
127 pub fn with_capabilities(mut self, capabilities: Capabilities) -> Self {
129 self.capabilities = Some(capabilities);
130 self
131 }
132
133 pub fn with_extensions(mut self, extensions: Extensions<LeafNode>) -> Self {
137 self.extensions = Some(extensions);
138 self
139 }
140
141 pub fn build(self) -> LeafNodeParameters {
143 LeafNodeParameters {
144 credential_with_key: self.credential_with_key,
145 capabilities: self.capabilities,
146 extensions: self.extensions,
147 }
148 }
149}
150
151#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, TlsSerialize, TlsSize)]
179pub struct LeafNode {
180 payload: LeafNodePayload,
181 signature: Signature,
182}
183
184impl LeafNode {
185 pub(crate) fn new(
193 provider: &impl OpenMlsProvider,
194 signer: &impl Signer,
195 new_leaf_node_params: NewLeafNodeParams,
196 ) -> Result<(Self, EncryptionKeyPair), LibraryError> {
197 let NewLeafNodeParams {
198 ciphersuite,
199 credential_with_key,
200 leaf_node_source,
201 capabilities,
202 extensions,
203 tree_info_tbs,
204 } = new_leaf_node_params;
205
206 let encryption_key_pair =
208 EncryptionKeyPair::random(provider.rand(), provider.crypto(), ciphersuite)?;
209
210 let leaf_node = Self::new_with_key(
211 encryption_key_pair.public_key().clone(),
212 credential_with_key,
213 leaf_node_source,
214 capabilities,
215 extensions,
216 tree_info_tbs,
217 signer,
218 )?;
219
220 Ok((leaf_node, encryption_key_pair))
221 }
222
223 pub(crate) fn new_placeholder() -> Self {
229 let payload = LeafNodePayload {
230 encryption_key: EncryptionKey::from(Vec::new()),
231 signature_key: Vec::new().into(),
232 credential: Credential::new(CredentialType::Basic, Vec::new()),
233 capabilities: Capabilities::default(),
234 leaf_node_source: LeafNodeSource::Update,
235 extensions: Extensions::default(),
236 };
237
238 Self {
239 payload,
240 signature: Vec::new().into(),
241 }
242 }
243
244 fn new_with_key(
247 encryption_key: EncryptionKey,
248 credential_with_key: CredentialWithKey,
249 leaf_node_source: LeafNodeSource,
250 capabilities: Capabilities,
251 extensions: Extensions<LeafNode>,
252 tree_info_tbs: TreeInfoTbs,
253 signer: &impl Signer,
254 ) -> Result<Self, LibraryError> {
255 let leaf_node_tbs = LeafNodeTbs::new(
256 encryption_key,
257 credential_with_key,
258 capabilities,
259 leaf_node_source,
260 extensions,
261 tree_info_tbs,
262 );
263
264 leaf_node_tbs
265 .sign(signer)
266 .map_err(|_| LibraryError::custom("Signing failed"))
267 }
268
269 #[allow(clippy::too_many_arguments)]
276 pub(in crate::treesync) fn new_with_parent_hash(
277 rand: &impl OpenMlsRand,
278 crypto: &impl OpenMlsCrypto,
279 ciphersuite: Ciphersuite,
280 parent_hash: &[u8],
281 leaf_node_params: UpdateLeafNodeParams,
282 group_id: GroupId,
283 leaf_index: LeafNodeIndex,
284 signer: &impl Signer,
285 #[cfg(feature = "virtual-clients-draft")] encryption_key_pair_override: Option<
286 EncryptionKeyPair,
287 >,
288 ) -> Result<(Self, EncryptionKeyPair), LibraryError> {
289 #[cfg(feature = "virtual-clients-draft")]
290 let encryption_key_pair = match encryption_key_pair_override {
291 Some(kp) => kp,
292 None => EncryptionKeyPair::random(rand, crypto, ciphersuite)?,
293 };
294 #[cfg(not(feature = "virtual-clients-draft"))]
295 let encryption_key_pair = EncryptionKeyPair::random(rand, crypto, ciphersuite)?;
296
297 let leaf_node_tbs = LeafNodeTbs::new(
298 encryption_key_pair.public_key().clone(),
299 leaf_node_params.credential_with_key,
300 leaf_node_params.capabilities,
301 LeafNodeSource::Commit(parent_hash.into()),
302 leaf_node_params.extensions,
303 TreeInfoTbs::Commit(TreePosition {
304 group_id,
305 leaf_index,
306 }),
307 );
308
309 let leaf_node = leaf_node_tbs
311 .sign(signer)
312 .map_err(|_| LibraryError::custom("Signing failed"))?;
313
314 Ok((leaf_node, encryption_key_pair))
315 }
316
317 #[cfg(all(test, feature = "generate-kats"))]
325 pub(crate) fn generate_update<Provider: OpenMlsProvider>(
326 ciphersuite: Ciphersuite,
327 credential_with_key: CredentialWithKey,
328 capabilities: Capabilities,
329 extensions: Extensions<LeafNode>,
330 tree_info_tbs: TreeInfoTbs,
331 provider: &Provider,
332 signer: &impl Signer,
333 ) -> Result<Self, LeafNodeGenerationError<Provider::StorageError>> {
334 let new_leaf_node_params = NewLeafNodeParams {
338 ciphersuite,
339 credential_with_key,
340 leaf_node_source: LeafNodeSource::Update,
341 capabilities,
342 extensions,
343 tree_info_tbs,
344 };
345
346 let (leaf_node, encryption_key_pair) = Self::new(provider, signer, new_leaf_node_params)?;
347
348 encryption_key_pair
350 .write(provider.storage())
351 .map_err(LeafNodeGenerationError::StorageError)?;
352
353 Ok(leaf_node)
354 }
355
356 pub(crate) fn update<Provider: OpenMlsProvider>(
364 &mut self,
365 ciphersuite: Ciphersuite,
366 provider: &Provider,
367 signer: &impl Signer,
368 group_id: GroupId,
369 leaf_index: LeafNodeIndex,
370 leaf_node_parmeters: LeafNodeParameters,
371 ) -> Result<EncryptionKeyPair, LeafNodeUpdateError<Provider::StorageError>> {
372 let tree_info = TreeInfoTbs::Update(TreePosition::new(group_id, leaf_index));
373 let mut leaf_node_tbs = LeafNodeTbs::from(self.clone(), tree_info);
374
375 if let Some(credential_with_key) = leaf_node_parmeters.credential_with_key {
377 leaf_node_tbs.payload.credential = credential_with_key.credential;
378 leaf_node_tbs.payload.signature_key = credential_with_key.signature_key;
379 }
380
381 if let Some(extensions) = leaf_node_parmeters.extensions {
383 leaf_node_tbs.payload.extensions = extensions;
384 }
385
386 if let Some(capabilities) = leaf_node_parmeters.capabilities {
388 leaf_node_tbs.payload.capabilities = capabilities;
389 }
390
391 let encryption_key_pair =
393 EncryptionKeyPair::random(provider.rand(), provider.crypto(), ciphersuite)?;
394 leaf_node_tbs.payload.encryption_key = encryption_key_pair.public_key().clone();
395
396 encryption_key_pair
398 .write(provider.storage())
399 .map_err(LeafNodeUpdateError::Storage)?;
400
401 leaf_node_tbs.payload.leaf_node_source = LeafNodeSource::Update;
403
404 let leaf_node = leaf_node_tbs.sign(signer)?;
406 self.payload = leaf_node.payload;
407 self.signature = leaf_node.signature;
408
409 Ok(encryption_key_pair)
410 }
411
412 pub fn encryption_key(&self) -> &EncryptionKey {
414 &self.payload.encryption_key
415 }
416
417 pub fn signature_key(&self) -> &SignaturePublicKey {
419 &self.payload.signature_key
420 }
421
422 pub fn credential(&self) -> &Credential {
424 &self.payload.credential
425 }
426
427 pub fn parent_hash(&self) -> Option<&[u8]> {
429 match &self.payload.leaf_node_source {
430 LeafNodeSource::Commit(ph) => Some(ph.as_slice()),
431 _ => None,
432 }
433 }
434
435 pub(crate) fn life_time(&self) -> Option<&Lifetime> {
438 if let LeafNodeSource::KeyPackage(life_time) = &self.payload.leaf_node_source {
439 Some(life_time)
440 } else {
441 None
442 }
443 }
444
445 pub fn signature(&self) -> &Signature {
447 &self.signature
448 }
449
450 pub fn capabilities(&self) -> &Capabilities {
452 &self.payload.capabilities
453 }
454
455 pub fn leaf_node_source(&self) -> &LeafNodeSource {
457 &self.payload.leaf_node_source
458 }
459
460 pub fn extensions(&self) -> &Extensions<LeafNode> {
462 &self.payload.extensions
463 }
464
465 pub(crate) fn supports_extension(&self, extension_type: &ExtensionType) -> bool {
467 extension_type.is_default()
468 || self
469 .payload
470 .capabilities
471 .extensions
472 .contains(extension_type)
473 }
474
475 pub(crate) fn check_extension_support(
478 &self,
479 extensions: &[ExtensionType],
480 ) -> Result<(), LeafNodeValidationError> {
481 for required in extensions.iter() {
482 if !self.supports_extension(required) {
483 log::error!(
484 "Leaf node does not support required extension {:?}\n
485 Supported extensions: {:?}",
486 required,
487 self.payload.capabilities.extensions
488 );
489 return Err(LeafNodeValidationError::UnsupportedExtensions);
490 }
491 }
492 Ok(())
493 }
494
495 pub(crate) fn validate_locally(&self) -> Result<(), LeafNodeValidationError> {
500 let invalid_extension_types = self
509 .extensions()
510 .iter()
511 .filter(|ext| !ext.extension_type().is_valid_in_leaf_node())
512 .collect::<Vec<_>>();
513 if !invalid_extension_types.is_empty() {
514 log::error!("Invalid extension used in leaf node: {invalid_extension_types:?}");
515 return Err(LeafNodeValidationError::UnsupportedExtensions);
516 }
517
518 if !self.capabilities().contains_extensions(self.extensions()) {
520 log::error!(
521 "Leaf node does not support all extensions it uses\n
522 Supported extensions: {:?}\n
523 Used extensions: {:?}",
524 self.payload.capabilities.extensions,
525 self.extensions()
526 );
527 return Err(LeafNodeValidationError::UnsupportedExtensions);
528 }
529
530 if !self
533 .capabilities()
534 .contains_credential(self.credential().credential_type())
535 {
536 return Err(LeafNodeValidationError::UnsupportedCredentials);
537 }
538
539 Ok(())
540 }
541}
542
543#[derive(
569 Debug,
570 Clone,
571 PartialEq,
572 Eq,
573 Serialize,
574 Deserialize,
575 TlsSerialize,
576 TlsDeserialize,
577 TlsDeserializeBytes,
578 TlsSize,
579)]
580struct LeafNodePayload {
581 encryption_key: EncryptionKey,
582 signature_key: SignaturePublicKey,
583 credential: Credential,
584 capabilities: Capabilities,
585 leaf_node_source: LeafNodeSource,
586 extensions: Extensions<LeafNode>,
587}
588
589#[derive(
591 Debug,
592 Clone,
593 PartialEq,
594 Eq,
595 Serialize,
596 Deserialize,
597 TlsSerialize,
598 TlsDeserialize,
599 TlsDeserializeBytes,
600 TlsSize,
601)]
602#[repr(u8)]
603pub enum LeafNodeSource {
604 #[tls_codec(discriminant = 1)]
606 KeyPackage(Lifetime),
607 Update,
609 Commit(ParentHash),
611}
612
613pub type ParentHash = VLBytes;
614
615#[derive(Debug, TlsSerialize, TlsSize)]
643pub struct LeafNodeTbs {
644 payload: LeafNodePayload,
645 tree_info_tbs: TreeInfoTbs,
646}
647
648impl LeafNodeTbs {
649 pub(crate) fn from(leaf_node: LeafNode, tree_info_tbs: TreeInfoTbs) -> Self {
652 Self {
653 payload: leaf_node.payload,
654 tree_info_tbs,
655 }
656 }
657
658 pub(crate) fn new(
661 encryption_key: EncryptionKey,
662 credential_with_key: CredentialWithKey,
663 capabilities: Capabilities,
664 leaf_node_source: LeafNodeSource,
665 extensions: Extensions<LeafNode>,
666 tree_info_tbs: TreeInfoTbs,
667 ) -> Self {
668 let payload = LeafNodePayload {
669 encryption_key,
670 signature_key: credential_with_key.signature_key,
671 credential: credential_with_key.credential,
672 capabilities,
673 leaf_node_source,
674 extensions,
675 };
676
677 LeafNodeTbs {
678 payload,
679 tree_info_tbs,
680 }
681 }
682}
683
684#[derive(Debug)]
706pub(crate) enum TreeInfoTbs {
707 KeyPackage,
708 Update(TreePosition),
709 Commit(TreePosition),
710}
711
712#[derive(Debug, Clone, PartialEq, Eq, TlsSerialize, TlsSize)]
713pub(crate) struct TreePosition {
714 group_id: GroupId,
715 leaf_index: LeafNodeIndex,
716}
717
718impl TreePosition {
719 pub(crate) fn new(group_id: GroupId, leaf_index: LeafNodeIndex) -> Self {
720 Self {
721 group_id,
722 leaf_index,
723 }
724 }
725
726 #[cfg(feature = "test-utils")]
727 pub(crate) fn into_parts(self) -> (GroupId, LeafNodeIndex) {
728 (self.group_id, self.leaf_index)
729 }
730}
731
732const LEAF_NODE_SIGNATURE_LABEL: &str = "LeafNodeTBS";
733
734#[derive(
735 Debug,
736 Clone,
737 PartialEq,
738 Eq,
739 Serialize,
740 Deserialize,
741 TlsSerialize,
742 TlsDeserialize,
743 TlsDeserializeBytes,
744 TlsSize,
745)]
746pub struct LeafNodeIn {
747 payload: LeafNodePayload,
748 signature: Signature,
749}
750
751impl LeafNodeIn {
752 pub(crate) fn into_verifiable_leaf_node(self) -> VerifiableLeafNode {
753 match self.payload.leaf_node_source {
754 LeafNodeSource::KeyPackage(_) => {
755 let verifiable = VerifiableKeyPackageLeafNode {
756 payload: self.payload,
757 signature: self.signature,
758 };
759 VerifiableLeafNode::KeyPackage(verifiable)
760 }
761 LeafNodeSource::Update => {
762 let verifiable = VerifiableUpdateLeafNode {
763 payload: self.payload,
764 signature: self.signature,
765 tree_position: None,
766 };
767 VerifiableLeafNode::Update(verifiable)
768 }
769 LeafNodeSource::Commit(_) => {
770 let verifiable = VerifiableCommitLeafNode {
771 payload: self.payload,
772 signature: self.signature,
773 tree_position: None,
774 };
775 VerifiableLeafNode::Commit(verifiable)
776 }
777 }
778 }
779
780 pub fn encryption_key(&self) -> &EncryptionKey {
782 &self.payload.encryption_key
783 }
784
785 pub fn signature_key(&self) -> &SignaturePublicKey {
787 &self.payload.signature_key
788 }
789
790 pub fn credential(&self) -> &Credential {
792 &self.payload.credential
793 }
794
795 #[cfg(feature = "unchecked-conversions")]
801 pub fn into_unchecked(self) -> LeafNode {
802 LeafNode {
803 payload: self.payload,
804 signature: self.signature,
805 }
806 }
807}
808
809impl From<LeafNode> for LeafNodeIn {
810 fn from(leaf_node: LeafNode) -> Self {
811 Self {
812 payload: leaf_node.payload,
813 signature: leaf_node.signature,
814 }
815 }
816}
817
818#[cfg(any(feature = "test-utils", test))]
819impl From<LeafNodeIn> for LeafNode {
820 fn from(deserialized: LeafNodeIn) -> Self {
821 Self {
822 payload: deserialized.payload,
823 signature: deserialized.signature,
824 }
825 }
826}
827
828impl From<KeyPackage> for LeafNode {
829 fn from(key_package: KeyPackage) -> Self {
830 key_package.leaf_node().clone()
831 }
832}
833
834impl From<KeyPackageBundle> for LeafNode {
835 fn from(key_package: KeyPackageBundle) -> Self {
836 key_package.key_package().leaf_node().clone()
837 }
838}
839
840#[derive(Debug, Clone, PartialEq, Eq)]
841pub(crate) enum VerifiableLeafNode {
842 KeyPackage(VerifiableKeyPackageLeafNode),
843 Update(VerifiableUpdateLeafNode),
844 Commit(VerifiableCommitLeafNode),
845}
846
847impl VerifiableLeafNode {
848 pub(crate) fn signature_key(&self) -> &SignaturePublicKey {
849 match self {
850 VerifiableLeafNode::KeyPackage(v) => v.signature_key(),
851 VerifiableLeafNode::Update(v) => v.signature_key(),
852 VerifiableLeafNode::Commit(v) => v.signature_key(),
853 }
854 }
855}
856
857#[derive(Debug, Clone, PartialEq, Eq)]
858pub(crate) struct VerifiableKeyPackageLeafNode {
859 payload: LeafNodePayload,
860 signature: Signature,
861}
862
863impl VerifiableKeyPackageLeafNode {
864 pub(crate) fn signature_key(&self) -> &SignaturePublicKey {
865 &self.payload.signature_key
866 }
867}
868
869impl Verifiable for VerifiableKeyPackageLeafNode {
871 type VerifiedStruct = LeafNode;
872
873 fn unsigned_payload(&self) -> Result<Vec<u8>, tls_codec::Error> {
874 self.payload.tls_serialize_detached()
875 }
876
877 fn signature(&self) -> &Signature {
878 &self.signature
879 }
880
881 fn label(&self) -> &str {
882 LEAF_NODE_SIGNATURE_LABEL
883 }
884
885 fn verify(
886 self,
887 crypto: &impl openmls_traits::crypto::OpenMlsCrypto,
888 pk: &crate::ciphersuite::OpenMlsSignaturePublicKey,
889 ) -> Result<Self::VerifiedStruct, crate::ciphersuite::signable::SignatureError> {
890 self.verify_no_out(crypto, pk)?;
891 Ok(LeafNode {
892 payload: self.payload,
893 signature: self.signature,
894 })
895 }
896}
897
898impl VerifiedStruct for LeafNode {}
899
900#[derive(Debug, Clone, PartialEq, Eq)]
901pub(crate) struct VerifiableUpdateLeafNode {
902 payload: LeafNodePayload,
903 signature: Signature,
904 tree_position: Option<TreePosition>,
905}
906
907impl VerifiableUpdateLeafNode {
908 pub(crate) fn add_tree_position(&mut self, tree_info: TreePosition) {
909 self.tree_position = Some(tree_info);
910 }
911
912 pub(crate) fn signature_key(&self) -> &SignaturePublicKey {
913 &self.payload.signature_key
914 }
915}
916
917impl Verifiable for VerifiableUpdateLeafNode {
918 type VerifiedStruct = LeafNode;
919
920 fn unsigned_payload(&self) -> Result<Vec<u8>, tls_codec::Error> {
921 let tree_info_tbs = match &self.tree_position {
922 Some(tree_position) => TreeInfoTbs::Commit(tree_position.clone()),
923 None => return Err(tls_codec::Error::InvalidInput),
924 };
925 let leaf_node_tbs = LeafNodeTbs {
926 payload: self.payload.clone(),
927 tree_info_tbs,
928 };
929 leaf_node_tbs.tls_serialize_detached()
930 }
931
932 fn signature(&self) -> &Signature {
933 &self.signature
934 }
935
936 fn label(&self) -> &str {
937 LEAF_NODE_SIGNATURE_LABEL
938 }
939
940 fn verify(
941 self,
942 crypto: &impl openmls_traits::crypto::OpenMlsCrypto,
943 pk: &crate::ciphersuite::OpenMlsSignaturePublicKey,
944 ) -> Result<Self::VerifiedStruct, crate::ciphersuite::signable::SignatureError> {
945 self.verify_no_out(crypto, pk)?;
946 Ok(LeafNode {
947 payload: self.payload,
948 signature: self.signature,
949 })
950 }
951}
952
953#[derive(Debug, Clone, PartialEq, Eq)]
954pub(crate) struct VerifiableCommitLeafNode {
955 payload: LeafNodePayload,
956 signature: Signature,
957 tree_position: Option<TreePosition>,
958}
959
960impl VerifiableCommitLeafNode {
961 pub(crate) fn add_tree_position(&mut self, tree_info: TreePosition) {
962 self.tree_position = Some(tree_info);
963 }
964
965 pub(crate) fn signature_key(&self) -> &SignaturePublicKey {
966 &self.payload.signature_key
967 }
968}
969
970impl Verifiable for VerifiableCommitLeafNode {
971 type VerifiedStruct = LeafNode;
972
973 fn unsigned_payload(&self) -> Result<Vec<u8>, tls_codec::Error> {
974 let tree_info_tbs = match &self.tree_position {
975 Some(tree_position) => TreeInfoTbs::Commit(tree_position.clone()),
976 None => return Err(tls_codec::Error::InvalidInput),
977 };
978 let leaf_node_tbs = LeafNodeTbs {
979 payload: self.payload.clone(),
980 tree_info_tbs,
981 };
982
983 leaf_node_tbs.tls_serialize_detached()
984 }
985
986 fn signature(&self) -> &Signature {
987 &self.signature
988 }
989
990 fn label(&self) -> &str {
991 LEAF_NODE_SIGNATURE_LABEL
992 }
993
994 fn verify(
995 self,
996 crypto: &impl openmls_traits::crypto::OpenMlsCrypto,
997 pk: &crate::ciphersuite::OpenMlsSignaturePublicKey,
998 ) -> Result<Self::VerifiedStruct, crate::ciphersuite::signable::SignatureError> {
999 self.verify_no_out(crypto, pk)?;
1000 Ok(LeafNode {
1001 payload: self.payload,
1002 signature: self.signature,
1003 })
1004 }
1005}
1006
1007impl Signable for LeafNodeTbs {
1008 type SignedOutput = LeafNode;
1009
1010 fn unsigned_payload(&self) -> Result<Vec<u8>, tls_codec::Error> {
1011 self.tls_serialize_detached()
1012 }
1013
1014 fn label(&self) -> &str {
1015 LEAF_NODE_SIGNATURE_LABEL
1016 }
1017}
1018
1019impl SignedStruct<LeafNodeTbs> for LeafNode {
1020 fn from_payload(tbs: LeafNodeTbs, signature: Signature, _serialized_payload: Vec<u8>) -> Self {
1021 Self {
1022 payload: tbs.payload,
1023 signature,
1024 }
1025 }
1026}
1027
1028#[cfg(all(test, feature = "generate-kats"))]
1029#[derive(Error, Debug, PartialEq, Clone)]
1030pub enum LeafNodeGenerationError<StorageError> {
1031 #[error(transparent)]
1033 LibraryError(#[from] LibraryError),
1034
1035 #[error("Error storing leaf private key.")]
1037 StorageError(StorageError),
1038}
1039
1040#[derive(Error, Debug, PartialEq, Clone)]
1042pub enum LeafNodeUpdateError<StorageError> {
1043 #[error(transparent)]
1045 LibraryError(#[from] LibraryError),
1046
1047 #[error("Error storing leaf private key.")]
1049 Storage(StorageError),
1050
1051 #[error(transparent)]
1053 Signature(#[from] crate::ciphersuite::signable::SignatureError),
1054}