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
103#[derive(Debug, Default)]
105pub struct LeafNodeParametersBuilder {
106 credential_with_key: Option<CredentialWithKey>,
107 capabilities: Option<Capabilities>,
108 extensions: Option<Extensions>,
109}
110
111impl LeafNodeParametersBuilder {
112 pub fn with_credential_with_key(mut self, credential_with_key: CredentialWithKey) -> Self {
114 self.credential_with_key = Some(credential_with_key);
115 self
116 }
117
118 pub fn with_capabilities(mut self, capabilities: Capabilities) -> Self {
120 self.capabilities = Some(capabilities);
121 self
122 }
123
124 pub fn with_extensions(mut self, extensions: Extensions) -> Self {
126 self.extensions = Some(extensions);
127 self
128 }
129
130 pub fn build(self) -> LeafNodeParameters {
132 LeafNodeParameters {
133 credential_with_key: self.credential_with_key,
134 capabilities: self.capabilities,
135 extensions: self.extensions,
136 }
137 }
138}
139
140#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, TlsSerialize, TlsSize)]
168pub struct LeafNode {
169 payload: LeafNodePayload,
170 signature: Signature,
171}
172
173impl LeafNode {
174 pub(crate) fn new(
182 provider: &impl OpenMlsProvider,
183 signer: &impl Signer,
184 new_leaf_node_params: NewLeafNodeParams,
185 ) -> Result<(Self, EncryptionKeyPair), LibraryError> {
186 let NewLeafNodeParams {
187 ciphersuite,
188 credential_with_key,
189 leaf_node_source,
190 capabilities,
191 extensions,
192 tree_info_tbs,
193 } = new_leaf_node_params;
194
195 let encryption_key_pair =
197 EncryptionKeyPair::random(provider.rand(), provider.crypto(), ciphersuite)?;
198
199 let leaf_node = Self::new_with_key(
200 encryption_key_pair.public_key().clone(),
201 credential_with_key,
202 leaf_node_source,
203 capabilities,
204 extensions,
205 tree_info_tbs,
206 signer,
207 )?;
208
209 Ok((leaf_node, encryption_key_pair))
210 }
211
212 pub(crate) fn new_placeholder() -> Self {
218 let payload = LeafNodePayload {
219 encryption_key: EncryptionKey::from(Vec::new()),
220 signature_key: Vec::new().into(),
221 credential: Credential::new(CredentialType::Basic, Vec::new()),
222 capabilities: Capabilities::default(),
223 leaf_node_source: LeafNodeSource::Update,
224 extensions: Extensions::default(),
225 };
226
227 Self {
228 payload,
229 signature: Vec::new().into(),
230 }
231 }
232
233 fn new_with_key(
236 encryption_key: EncryptionKey,
237 credential_with_key: CredentialWithKey,
238 leaf_node_source: LeafNodeSource,
239 capabilities: Capabilities,
240 extensions: Extensions,
241 tree_info_tbs: TreeInfoTbs,
242 signer: &impl Signer,
243 ) -> Result<Self, LibraryError> {
244 let leaf_node_tbs = LeafNodeTbs::new(
245 encryption_key,
246 credential_with_key,
247 capabilities,
248 leaf_node_source,
249 extensions,
250 tree_info_tbs,
251 );
252
253 leaf_node_tbs
254 .sign(signer)
255 .map_err(|_| LibraryError::custom("Signing failed"))
256 }
257
258 #[allow(clippy::too_many_arguments)]
260 pub(in crate::treesync) fn new_with_parent_hash(
261 rand: &impl OpenMlsRand,
262 crypto: &impl OpenMlsCrypto,
263 ciphersuite: Ciphersuite,
264 parent_hash: &[u8],
265 leaf_node_params: UpdateLeafNodeParams,
266 group_id: GroupId,
267 leaf_index: LeafNodeIndex,
268 signer: &impl Signer,
269 ) -> Result<(Self, EncryptionKeyPair), LibraryError> {
270 let encryption_key_pair = EncryptionKeyPair::random(rand, crypto, ciphersuite)?;
271
272 let leaf_node_tbs = LeafNodeTbs::new(
273 encryption_key_pair.public_key().clone(),
274 leaf_node_params.credential_with_key,
275 leaf_node_params.capabilities,
276 LeafNodeSource::Commit(parent_hash.into()),
277 leaf_node_params.extensions,
278 TreeInfoTbs::Commit(TreePosition {
279 group_id,
280 leaf_index,
281 }),
282 );
283
284 let leaf_node = leaf_node_tbs
286 .sign(signer)
287 .map_err(|_| LibraryError::custom("Signing failed"))?;
288
289 Ok((leaf_node, encryption_key_pair))
290 }
291
292 #[cfg(test)]
300 pub(crate) fn generate_update<Provider: OpenMlsProvider>(
301 ciphersuite: Ciphersuite,
302 credential_with_key: CredentialWithKey,
303 capabilities: Capabilities,
304 extensions: Extensions,
305 tree_info_tbs: TreeInfoTbs,
306 provider: &Provider,
307 signer: &impl Signer,
308 ) -> Result<Self, LeafNodeGenerationError<Provider::StorageError>> {
309 let new_leaf_node_params = NewLeafNodeParams {
313 ciphersuite,
314 credential_with_key,
315 leaf_node_source: LeafNodeSource::Update,
316 capabilities,
317 extensions,
318 tree_info_tbs,
319 };
320
321 let (leaf_node, encryption_key_pair) = Self::new(provider, signer, new_leaf_node_params)?;
322
323 encryption_key_pair
325 .write(provider.storage())
326 .map_err(LeafNodeGenerationError::StorageError)?;
327
328 Ok(leaf_node)
329 }
330
331 pub(crate) fn update<Provider: OpenMlsProvider>(
339 &mut self,
340 ciphersuite: Ciphersuite,
341 provider: &Provider,
342 signer: &impl Signer,
343 group_id: GroupId,
344 leaf_index: LeafNodeIndex,
345 leaf_node_parmeters: LeafNodeParameters,
346 ) -> Result<EncryptionKeyPair, LeafNodeUpdateError<Provider::StorageError>> {
347 let tree_info = TreeInfoTbs::Update(TreePosition::new(group_id, leaf_index));
348 let mut leaf_node_tbs = LeafNodeTbs::from(self.clone(), tree_info);
349
350 if let Some(credential_with_key) = leaf_node_parmeters.credential_with_key {
352 leaf_node_tbs.payload.credential = credential_with_key.credential;
353 leaf_node_tbs.payload.signature_key = credential_with_key.signature_key;
354 }
355
356 if let Some(extensions) = leaf_node_parmeters.extensions {
358 leaf_node_tbs.payload.extensions = extensions;
359 }
360
361 if let Some(capabilities) = leaf_node_parmeters.capabilities {
363 leaf_node_tbs.payload.capabilities = capabilities;
364 }
365
366 let encryption_key_pair =
368 EncryptionKeyPair::random(provider.rand(), provider.crypto(), ciphersuite)?;
369 leaf_node_tbs.payload.encryption_key = encryption_key_pair.public_key().clone();
370
371 encryption_key_pair
373 .write(provider.storage())
374 .map_err(LeafNodeUpdateError::Storage)?;
375
376 leaf_node_tbs.payload.leaf_node_source = LeafNodeSource::Update;
378
379 let leaf_node = leaf_node_tbs.sign(signer)?;
381 self.payload = leaf_node.payload;
382 self.signature = leaf_node.signature;
383
384 Ok(encryption_key_pair)
385 }
386
387 pub fn encryption_key(&self) -> &EncryptionKey {
389 &self.payload.encryption_key
390 }
391
392 pub fn signature_key(&self) -> &SignaturePublicKey {
394 &self.payload.signature_key
395 }
396
397 pub fn credential(&self) -> &Credential {
399 &self.payload.credential
400 }
401
402 pub fn parent_hash(&self) -> Option<&[u8]> {
404 match &self.payload.leaf_node_source {
405 LeafNodeSource::Commit(ph) => Some(ph.as_slice()),
406 _ => None,
407 }
408 }
409
410 pub(crate) fn life_time(&self) -> Option<&Lifetime> {
413 if let LeafNodeSource::KeyPackage(life_time) = &self.payload.leaf_node_source {
414 Some(life_time)
415 } else {
416 None
417 }
418 }
419
420 pub fn signature(&self) -> &Signature {
422 &self.signature
423 }
424
425 pub fn capabilities(&self) -> &Capabilities {
427 &self.payload.capabilities
428 }
429
430 pub fn leaf_node_source(&self) -> &LeafNodeSource {
432 &self.payload.leaf_node_source
433 }
434
435 pub fn extensions(&self) -> &Extensions {
437 &self.payload.extensions
438 }
439
440 pub(crate) fn supports_extension(&self, extension_type: &ExtensionType) -> bool {
442 extension_type.is_default()
443 || self
444 .payload
445 .capabilities
446 .extensions
447 .contains(extension_type)
448 }
449
450 pub(crate) fn check_extension_support(
453 &self,
454 extensions: &[ExtensionType],
455 ) -> Result<(), LeafNodeValidationError> {
456 for required in extensions.iter() {
457 if !self.supports_extension(required) {
458 log::error!(
459 "Leaf node does not support required extension {:?}\n
460 Supported extensions: {:?}",
461 required,
462 self.payload.capabilities.extensions
463 );
464 return Err(LeafNodeValidationError::UnsupportedExtensions);
465 }
466 }
467 Ok(())
468 }
469
470 pub(crate) fn validate_locally(&self) -> Result<(), LeafNodeValidationError> {
475 let invalid_extension_types = self
477 .extensions()
478 .iter()
479 .filter(|ext| ext.extension_type().is_valid_in_leaf_node() == Some(false))
480 .collect::<Vec<_>>();
481 if !invalid_extension_types.is_empty() {
482 log::error!(
483 "Invalid extension used in leaf node: {:?}",
484 invalid_extension_types
485 );
486 return Err(LeafNodeValidationError::UnsupportedExtensions);
487 }
488
489 if !self.capabilities().contains_extensions(self.extensions()) {
491 log::error!(
492 "Leaf node does not support all extensions it uses\n
493 Supported extensions: {:?}\n
494 Used extensions: {:?}",
495 self.payload.capabilities.extensions,
496 self.extensions()
497 );
498 return Err(LeafNodeValidationError::UnsupportedExtensions);
499 }
500
501 if !self
504 .capabilities()
505 .contains_credential(self.credential().credential_type())
506 {
507 return Err(LeafNodeValidationError::UnsupportedCredentials);
508 }
509
510 Ok(())
511 }
512}
513
514#[derive(
540 Debug,
541 Clone,
542 PartialEq,
543 Eq,
544 Serialize,
545 Deserialize,
546 TlsSerialize,
547 TlsDeserialize,
548 TlsDeserializeBytes,
549 TlsSize,
550)]
551struct LeafNodePayload {
552 encryption_key: EncryptionKey,
553 signature_key: SignaturePublicKey,
554 credential: Credential,
555 capabilities: Capabilities,
556 leaf_node_source: LeafNodeSource,
557 extensions: Extensions,
558}
559
560#[derive(
562 Debug,
563 Clone,
564 PartialEq,
565 Eq,
566 Serialize,
567 Deserialize,
568 TlsSerialize,
569 TlsDeserialize,
570 TlsDeserializeBytes,
571 TlsSize,
572)]
573#[repr(u8)]
574pub enum LeafNodeSource {
575 #[tls_codec(discriminant = 1)]
577 KeyPackage(Lifetime),
578 Update,
580 Commit(ParentHash),
582}
583
584pub type ParentHash = VLBytes;
585
586#[derive(Debug, TlsSerialize, TlsSize)]
614pub struct LeafNodeTbs {
615 payload: LeafNodePayload,
616 tree_info_tbs: TreeInfoTbs,
617}
618
619impl LeafNodeTbs {
620 pub(crate) fn from(leaf_node: LeafNode, tree_info_tbs: TreeInfoTbs) -> Self {
623 Self {
624 payload: leaf_node.payload,
625 tree_info_tbs,
626 }
627 }
628
629 pub(crate) fn new(
632 encryption_key: EncryptionKey,
633 credential_with_key: CredentialWithKey,
634 capabilities: Capabilities,
635 leaf_node_source: LeafNodeSource,
636 extensions: Extensions,
637 tree_info_tbs: TreeInfoTbs,
638 ) -> Self {
639 let payload = LeafNodePayload {
640 encryption_key,
641 signature_key: credential_with_key.signature_key,
642 credential: credential_with_key.credential,
643 capabilities,
644 leaf_node_source,
645 extensions,
646 };
647
648 LeafNodeTbs {
649 payload,
650 tree_info_tbs,
651 }
652 }
653}
654
655#[derive(Debug)]
677pub(crate) enum TreeInfoTbs {
678 KeyPackage,
679 Update(TreePosition),
680 Commit(TreePosition),
681}
682
683#[derive(Debug, Clone, PartialEq, Eq, TlsSerialize, TlsSize)]
684pub(crate) struct TreePosition {
685 group_id: GroupId,
686 leaf_index: LeafNodeIndex,
687}
688
689impl TreePosition {
690 pub(crate) fn new(group_id: GroupId, leaf_index: LeafNodeIndex) -> Self {
691 Self {
692 group_id,
693 leaf_index,
694 }
695 }
696
697 #[cfg(feature = "test-utils")]
698 pub(crate) fn into_parts(self) -> (GroupId, LeafNodeIndex) {
699 (self.group_id, self.leaf_index)
700 }
701}
702
703const LEAF_NODE_SIGNATURE_LABEL: &str = "LeafNodeTBS";
704
705#[derive(
706 Debug,
707 Clone,
708 PartialEq,
709 Eq,
710 Serialize,
711 Deserialize,
712 TlsSerialize,
713 TlsDeserialize,
714 TlsDeserializeBytes,
715 TlsSize,
716)]
717pub struct LeafNodeIn {
718 payload: LeafNodePayload,
719 signature: Signature,
720}
721
722impl LeafNodeIn {
723 pub(crate) fn into_verifiable_leaf_node(self) -> VerifiableLeafNode {
724 match self.payload.leaf_node_source {
725 LeafNodeSource::KeyPackage(_) => {
726 let verifiable = VerifiableKeyPackageLeafNode {
727 payload: self.payload,
728 signature: self.signature,
729 };
730 VerifiableLeafNode::KeyPackage(verifiable)
731 }
732 LeafNodeSource::Update => {
733 let verifiable = VerifiableUpdateLeafNode {
734 payload: self.payload,
735 signature: self.signature,
736 tree_position: None,
737 };
738 VerifiableLeafNode::Update(verifiable)
739 }
740 LeafNodeSource::Commit(_) => {
741 let verifiable = VerifiableCommitLeafNode {
742 payload: self.payload,
743 signature: self.signature,
744 tree_position: None,
745 };
746 VerifiableLeafNode::Commit(verifiable)
747 }
748 }
749 }
750
751 pub fn encryption_key(&self) -> &EncryptionKey {
753 &self.payload.encryption_key
754 }
755
756 pub fn signature_key(&self) -> &SignaturePublicKey {
758 &self.payload.signature_key
759 }
760
761 pub fn credential(&self) -> &Credential {
763 &self.payload.credential
764 }
765}
766
767impl From<LeafNode> for LeafNodeIn {
768 fn from(leaf_node: LeafNode) -> Self {
769 Self {
770 payload: leaf_node.payload,
771 signature: leaf_node.signature,
772 }
773 }
774}
775
776#[cfg(any(feature = "test-utils", test))]
777impl From<LeafNodeIn> for LeafNode {
778 fn from(deserialized: LeafNodeIn) -> Self {
779 Self {
780 payload: deserialized.payload,
781 signature: deserialized.signature,
782 }
783 }
784}
785
786impl From<KeyPackage> for LeafNode {
787 fn from(key_package: KeyPackage) -> Self {
788 key_package.leaf_node().clone()
789 }
790}
791
792impl From<KeyPackageBundle> for LeafNode {
793 fn from(key_package: KeyPackageBundle) -> Self {
794 key_package.key_package().leaf_node().clone()
795 }
796}
797
798#[derive(Debug, Clone, PartialEq, Eq)]
799pub(crate) enum VerifiableLeafNode {
800 KeyPackage(VerifiableKeyPackageLeafNode),
801 Update(VerifiableUpdateLeafNode),
802 Commit(VerifiableCommitLeafNode),
803}
804
805impl VerifiableLeafNode {
806 pub(crate) fn signature_key(&self) -> &SignaturePublicKey {
807 match self {
808 VerifiableLeafNode::KeyPackage(v) => v.signature_key(),
809 VerifiableLeafNode::Update(v) => v.signature_key(),
810 VerifiableLeafNode::Commit(v) => v.signature_key(),
811 }
812 }
813}
814
815#[derive(Debug, Clone, PartialEq, Eq)]
816pub(crate) struct VerifiableKeyPackageLeafNode {
817 payload: LeafNodePayload,
818 signature: Signature,
819}
820
821impl VerifiableKeyPackageLeafNode {
822 pub(crate) fn signature_key(&self) -> &SignaturePublicKey {
823 &self.payload.signature_key
824 }
825}
826
827impl Verifiable for VerifiableKeyPackageLeafNode {
829 type VerifiedStruct = LeafNode;
830
831 fn unsigned_payload(&self) -> Result<Vec<u8>, tls_codec::Error> {
832 self.payload.tls_serialize_detached()
833 }
834
835 fn signature(&self) -> &Signature {
836 &self.signature
837 }
838
839 fn label(&self) -> &str {
840 LEAF_NODE_SIGNATURE_LABEL
841 }
842
843 fn verify(
844 self,
845 crypto: &impl openmls_traits::crypto::OpenMlsCrypto,
846 pk: &crate::ciphersuite::OpenMlsSignaturePublicKey,
847 ) -> Result<Self::VerifiedStruct, crate::ciphersuite::signable::SignatureError> {
848 self.verify_no_out(crypto, pk)?;
849 Ok(LeafNode {
850 payload: self.payload,
851 signature: self.signature,
852 })
853 }
854}
855
856impl VerifiedStruct for LeafNode {}
857
858#[derive(Debug, Clone, PartialEq, Eq)]
859pub(crate) struct VerifiableUpdateLeafNode {
860 payload: LeafNodePayload,
861 signature: Signature,
862 tree_position: Option<TreePosition>,
863}
864
865impl VerifiableUpdateLeafNode {
866 pub(crate) fn add_tree_position(&mut self, tree_info: TreePosition) {
867 self.tree_position = Some(tree_info);
868 }
869
870 pub(crate) fn signature_key(&self) -> &SignaturePublicKey {
871 &self.payload.signature_key
872 }
873}
874
875impl Verifiable for VerifiableUpdateLeafNode {
876 type VerifiedStruct = LeafNode;
877
878 fn unsigned_payload(&self) -> Result<Vec<u8>, tls_codec::Error> {
879 let tree_info_tbs = match &self.tree_position {
880 Some(tree_position) => TreeInfoTbs::Commit(tree_position.clone()),
881 None => return Err(tls_codec::Error::InvalidInput),
882 };
883 let leaf_node_tbs = LeafNodeTbs {
884 payload: self.payload.clone(),
885 tree_info_tbs,
886 };
887 leaf_node_tbs.tls_serialize_detached()
888 }
889
890 fn signature(&self) -> &Signature {
891 &self.signature
892 }
893
894 fn label(&self) -> &str {
895 LEAF_NODE_SIGNATURE_LABEL
896 }
897
898 fn verify(
899 self,
900 crypto: &impl openmls_traits::crypto::OpenMlsCrypto,
901 pk: &crate::ciphersuite::OpenMlsSignaturePublicKey,
902 ) -> Result<Self::VerifiedStruct, crate::ciphersuite::signable::SignatureError> {
903 self.verify_no_out(crypto, pk)?;
904 Ok(LeafNode {
905 payload: self.payload,
906 signature: self.signature,
907 })
908 }
909}
910
911#[derive(Debug, Clone, PartialEq, Eq)]
912pub(crate) struct VerifiableCommitLeafNode {
913 payload: LeafNodePayload,
914 signature: Signature,
915 tree_position: Option<TreePosition>,
916}
917
918impl VerifiableCommitLeafNode {
919 pub(crate) fn add_tree_position(&mut self, tree_info: TreePosition) {
920 self.tree_position = Some(tree_info);
921 }
922
923 pub(crate) fn signature_key(&self) -> &SignaturePublicKey {
924 &self.payload.signature_key
925 }
926}
927
928impl Verifiable for VerifiableCommitLeafNode {
929 type VerifiedStruct = LeafNode;
930
931 fn unsigned_payload(&self) -> Result<Vec<u8>, tls_codec::Error> {
932 let tree_info_tbs = match &self.tree_position {
933 Some(tree_position) => TreeInfoTbs::Commit(tree_position.clone()),
934 None => return Err(tls_codec::Error::InvalidInput),
935 };
936 let leaf_node_tbs = LeafNodeTbs {
937 payload: self.payload.clone(),
938 tree_info_tbs,
939 };
940
941 leaf_node_tbs.tls_serialize_detached()
942 }
943
944 fn signature(&self) -> &Signature {
945 &self.signature
946 }
947
948 fn label(&self) -> &str {
949 LEAF_NODE_SIGNATURE_LABEL
950 }
951
952 fn verify(
953 self,
954 crypto: &impl openmls_traits::crypto::OpenMlsCrypto,
955 pk: &crate::ciphersuite::OpenMlsSignaturePublicKey,
956 ) -> Result<Self::VerifiedStruct, crate::ciphersuite::signable::SignatureError> {
957 self.verify_no_out(crypto, pk)?;
958 Ok(LeafNode {
959 payload: self.payload,
960 signature: self.signature,
961 })
962 }
963}
964
965impl Signable for LeafNodeTbs {
966 type SignedOutput = LeafNode;
967
968 fn unsigned_payload(&self) -> Result<Vec<u8>, tls_codec::Error> {
969 self.tls_serialize_detached()
970 }
971
972 fn label(&self) -> &str {
973 LEAF_NODE_SIGNATURE_LABEL
974 }
975}
976
977impl SignedStruct<LeafNodeTbs> for LeafNode {
978 fn from_payload(tbs: LeafNodeTbs, signature: Signature) -> Self {
979 Self {
980 payload: tbs.payload,
981 signature,
982 }
983 }
984}
985
986#[cfg(test)]
987#[derive(Error, Debug, PartialEq, Clone)]
988pub enum LeafNodeGenerationError<StorageError> {
989 #[error(transparent)]
991 LibraryError(#[from] LibraryError),
992
993 #[error("Error storing leaf private key.")]
995 StorageError(StorageError),
996}
997
998#[derive(Error, Debug, PartialEq, Clone)]
1000pub enum LeafNodeUpdateError<StorageError> {
1001 #[error(transparent)]
1003 LibraryError(#[from] LibraryError),
1004
1005 #[error("Error storing leaf private key.")]
1007 Storage(StorageError),
1008
1009 #[error(transparent)]
1011 Signature(#[from] crate::ciphersuite::signable::SignatureError),
1012}