Skip to main content

openmls/tree/
secret_tree.rs

1use openmls_traits::crypto::OpenMlsCrypto;
2use openmls_traits::types::{Ciphersuite, CryptoError};
3use thiserror::Error;
4use tls_codec::{Error as TlsCodecError, TlsSerialize, TlsSize};
5
6use super::*;
7#[cfg(feature = "virtual-clients-draft")]
8use crate::tree::dual_use_ratchet::{DualUseRatchet, PeekedDualUseGeneration};
9use crate::{
10    binary_tree::{
11        array_representation::{
12            direct_path, left, right, root, ParentNodeIndex, TreeNodeIndex, TreeSize,
13        },
14        LeafNodeIndex,
15    },
16    framing::*,
17    schedule::*,
18    tree::sender_ratchet::*,
19};
20
21/// Secret tree error
22#[derive(Error, Debug, Eq, PartialEq, Clone)]
23pub enum SecretTreeError {
24    /// Generation is too old to be processed.
25    #[error("Generation is too old to be processed.")]
26    TooDistantInThePast,
27    /// Generation is too far in the future to be processed.
28    #[error("Generation is too far in the future to be processed.")]
29    TooDistantInTheFuture,
30    /// Index out of bounds
31    #[error("Index out of bounds")]
32    IndexOutOfBounds,
33    /// The requested secret was deleted to preserve forward secrecy.
34    #[error("The requested secret was deleted to preserve forward secrecy.")]
35    SecretReuseError,
36    /// Cannot create decryption secrets from own sender ratchet or encryption secrets from the sender ratchets of other members.
37    #[error("Cannot create decryption secrets from own sender ratchet or encryption secrets from the sender ratchets of other members.")]
38    RatchetTypeError,
39    /// Ratchet generation has reached `u32::MAX`.
40    #[error("Ratchet generation has reached `u32::MAX`.")]
41    RatchetTooLong,
42    /// An unrecoverable error has occurred due to a bug in the implementation.
43    #[error("An unrecoverable error has occurred due to a bug in the implementation.")]
44    LibraryError,
45    /// See [`TlsCodecError`] for more details.
46    #[error(transparent)]
47    CodecError(#[from] TlsCodecError),
48    /// See [`CryptoError`] for more details.
49    #[error(transparent)]
50    CryptoError(#[from] CryptoError),
51}
52
53#[derive(Debug, Copy, Clone)]
54pub(crate) enum SecretType {
55    HandshakeSecret,
56    ApplicationSecret,
57}
58
59impl From<&ContentType> for SecretType {
60    fn from(content_type: &ContentType) -> SecretType {
61        match content_type {
62            ContentType::Application => SecretType::ApplicationSecret,
63            ContentType::Commit => SecretType::HandshakeSecret,
64            ContentType::Proposal => SecretType::HandshakeSecret,
65        }
66    }
67}
68
69impl From<&PublicMessage> for SecretType {
70    fn from(public_message: &PublicMessage) -> SecretType {
71        SecretType::from(&public_message.content_type())
72    }
73}
74
75/// Outcome of looking up a decryption secret in the [`SecretTree`].
76#[cfg_attr(test, derive(Debug, PartialEq))]
77pub(crate) enum DecryptionSecret {
78    Available(RatchetKeyMaterial),
79    /// The generation belongs to a message we created and confirmed earlier, so
80    /// its secret was deleted.
81    #[cfg(feature = "virtual-clients-draft")]
82    OwnMessageConfirmed,
83}
84
85#[cfg(any(feature = "test-utils", test))]
86impl DecryptionSecret {
87    pub(crate) fn available(self) -> Option<RatchetKeyMaterial> {
88        match self {
89            Self::Available(ratchet_key_material) => Some(ratchet_key_material),
90            #[cfg(feature = "virtual-clients-draft")]
91            Self::OwnMessageConfirmed => None,
92        }
93    }
94}
95
96/// A sender ratchet change computed by [`SecretTree::prepare_decryption`],
97/// not yet applied to the tree.
98pub(crate) struct PendingRatchetUpdate {
99    index: LeafNodeIndex,
100    secret_type: SecretType,
101    peeked: Box<PeekedRatchetGeneration>,
102}
103
104enum PeekedRatchetGeneration {
105    Decryption(PeekedGeneration),
106    #[cfg(feature = "virtual-clients-draft")]
107    DualUse(PeekedDualUseGeneration),
108}
109
110impl std::fmt::Debug for PendingRatchetUpdate {
111    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
112        f.debug_struct("PendingRatchetUpdate")
113            .field("index", &self.index)
114            .field("secret_type", &self.secret_type)
115            .finish_non_exhaustive()
116    }
117}
118
119pub(crate) fn derive_child_secrets(
120    parent_secret: &Secret,
121    crypto: &impl OpenMlsCrypto,
122    ciphersuite: Ciphersuite,
123) -> Result<(Secret, Secret), CryptoError> {
124    let left_child = parent_secret.kdf_expand_label(
125        crypto,
126        ciphersuite,
127        "tree",
128        b"left",
129        ciphersuite.hash_length(),
130    )?;
131    let right_child = parent_secret.kdf_expand_label(
132        crypto,
133        ciphersuite,
134        "tree",
135        b"right",
136        ciphersuite.hash_length(),
137    )?;
138    Ok((left_child, right_child))
139}
140
141/// Derives secrets for inner nodes of a SecretTree. This function corresponds
142/// to the `DeriveTreeSecret` defined in Section 10.1 of the MLS specification.
143#[inline]
144pub(crate) fn derive_tree_secret(
145    ciphersuite: Ciphersuite,
146    secret: &Secret,
147    label: &str,
148    generation: u32,
149    length: usize,
150    crypto: &impl OpenMlsCrypto,
151) -> Result<Secret, SecretTreeError> {
152    log::debug!(
153        "Derive tree secret with label \"{label}\" in generation {generation} of length {length}"
154    );
155    log_crypto!(trace, "Input secret {:x?}", secret.as_slice());
156
157    let secret = secret.kdf_expand_label(
158        crypto,
159        ciphersuite,
160        label,
161        &generation.to_be_bytes(),
162        length,
163    )?;
164    log_crypto!(trace, "Derived secret {:x?}", secret.as_slice());
165    Ok(secret)
166}
167
168#[derive(Debug, TlsSerialize, TlsSize)]
169pub(crate) struct TreeContext {
170    pub(crate) node: u32,
171    pub(crate) generation: u32,
172}
173
174#[derive(Debug, Serialize, Deserialize, TlsSerialize, TlsSize)]
175#[cfg_attr(any(feature = "test-utils", test), derive(PartialEq, Clone))]
176pub(crate) struct SecretTreeNode {
177    pub(crate) secret: Secret,
178}
179
180#[derive(Serialize, Deserialize)]
181#[cfg_attr(any(feature = "test-utils", test), derive(PartialEq, Clone))]
182#[cfg_attr(any(feature = "crypto-debug", test), derive(Debug))]
183pub(crate) struct SecretTree {
184    own_index: LeafNodeIndex,
185    leaf_nodes: Vec<Option<SecretTreeNode>>,
186    parent_nodes: Vec<Option<SecretTreeNode>>,
187    handshake_sender_ratchets: Vec<Option<SenderRatchet>>,
188    application_sender_ratchets: Vec<Option<SenderRatchet>>,
189    size: TreeSize,
190}
191
192impl SecretTree {
193    /// Creates a new SecretTree based on an `encryption_secret` and group size
194    /// `size`. The inner nodes of the tree and the SenderRatchets only get
195    /// initialized when secrets are requested either through `secret()`
196    /// or `next_secret()`.
197    pub(crate) fn new(
198        encryption_secret: EncryptionSecret,
199        size: TreeSize,
200        own_index: LeafNodeIndex,
201    ) -> Self {
202        let leaf_count = size.leaf_count() as usize;
203        let leaf_nodes = std::iter::repeat_with(|| None).take(leaf_count).collect();
204        let parent_nodes = std::iter::repeat_with(|| None).take(leaf_count).collect();
205        let handshake_sender_ratchets = std::iter::repeat_with(|| None).take(leaf_count).collect();
206        let application_sender_ratchets =
207            std::iter::repeat_with(|| None).take(leaf_count).collect();
208
209        let mut secret_tree = SecretTree {
210            own_index,
211            leaf_nodes,
212            parent_nodes,
213            handshake_sender_ratchets,
214            application_sender_ratchets,
215            size,
216        };
217
218        // Set the encryption secret in the root node. We ignore the Result
219        // here, since the we rely on the tree math to be correct, i.e.
220        // root(size) < size.
221        let _ = secret_tree.set_node(
222            root(size),
223            Some(SecretTreeNode {
224                secret: encryption_secret.consume_secret(),
225            }),
226        );
227
228        secret_tree
229    }
230
231    /// The leaf index this tree was built for.
232    pub(crate) fn own_index(&self) -> LeafNodeIndex {
233        self.own_index
234    }
235
236    /// Get current generation for a specific SenderRatchet
237    #[cfg(test)]
238    pub(crate) fn generation(&self, index: LeafNodeIndex, secret_type: SecretType) -> u32 {
239        match self
240            .ratchet_opt(index, secret_type)
241            .expect("Index out of bounds.")
242        {
243            Some(sender_ratchet) => sender_ratchet.generation(),
244            None => 0,
245        }
246    }
247
248    #[cfg(test)]
249    pub(crate) fn sender_ratchet(
250        &self,
251        index: LeafNodeIndex,
252        secret_type: SecretType,
253    ) -> Option<&SenderRatchet> {
254        self.ratchet_opt(index, secret_type).ok().flatten()
255    }
256
257    /// Initializes a specific SenderRatchet pair for a given index by
258    /// calculating and deleting the appropriate values in the SecretTree
259    fn initialize_sender_ratchets(
260        &mut self,
261        ciphersuite: Ciphersuite,
262        crypto: &impl OpenMlsCrypto,
263        index: LeafNodeIndex,
264    ) -> Result<(), SecretTreeError> {
265        log::trace!("Initializing sender ratchets for {index:?} with {ciphersuite}");
266        if index.u32() >= self.size.leaf_count() {
267            log::error!("Index is larger than the tree size.");
268            return Err(SecretTreeError::IndexOutOfBounds);
269        }
270        // Check if SenderRatchets are already initialized
271        if self
272            .ratchet_opt(index, SecretType::HandshakeSecret)?
273            .is_some()
274            && self
275                .ratchet_opt(index, SecretType::ApplicationSecret)?
276                .is_some()
277        {
278            log::trace!("The sender ratchets are initialized already.");
279            return Ok(());
280        }
281
282        // If we don't have a secret in the leaf node, we derive it
283        if self.get_node(index.into())?.is_none() {
284            // Collect empty nodes in the direct path until a non-empty node is
285            // found
286            let mut empty_nodes: Vec<ParentNodeIndex> = Vec::new();
287            let direct_path = direct_path(index, self.size);
288            log::trace!("Direct path for node {index:?}: {direct_path:?}");
289            for parent_node in direct_path {
290                empty_nodes.push(parent_node);
291                // Stop if we find a non-empty node
292                if self.get_node(parent_node.into())?.is_some() {
293                    break;
294                }
295            }
296
297            // Invert direct path
298            empty_nodes.reverse();
299
300            // Derive the secrets down all the way to the leaf node
301            for n in empty_nodes {
302                log::trace!("Derive down for parent node {n:?}.");
303                self.derive_down(ciphersuite, crypto, n)?;
304            }
305        }
306
307        // Calculate node secret and initialize SenderRatchets
308        let node_secret = match self.get_node(index.into())? {
309            Some(node) => &node.secret,
310            // We just derived all necessary nodes so this should not happen
311            None => {
312                return Err(SecretTreeError::LibraryError);
313            }
314        };
315
316        log::trace!("Deriving leaf node secrets for leaf {index:?}");
317
318        let handshake_ratchet_secret = node_secret.kdf_expand_label(
319            crypto,
320            ciphersuite,
321            "handshake",
322            b"",
323            ciphersuite.hash_length(),
324        )?;
325        let application_ratchet_secret = node_secret.kdf_expand_label(
326            crypto,
327            ciphersuite,
328            "application",
329            b"",
330            ciphersuite.hash_length(),
331        )?;
332
333        log_crypto!(
334            trace,
335            "handshake ratchet secret {handshake_ratchet_secret:x?}"
336        );
337        log_crypto!(
338            trace,
339            "application ratchet secret {application_ratchet_secret:x?}"
340        );
341
342        // Initialize SenderRatchets. We differentiate between the own
343        // SenderRatchets and the SenderRatchets of other members. With the
344        // `virtual-clients-draft` feature, the own SenderRatchets are
345        // [`DualUseRatchet`]s, which can produce key material for both
346        // encryption and decryption.
347        let (handshake_sender_ratchet, application_sender_ratchet) = if index == self.own_index {
348            #[cfg(not(feature = "virtual-clients-draft"))]
349            {
350                (
351                    SenderRatchet::EncryptionRatchet(RatchetSecret::initial_ratchet_secret(
352                        handshake_ratchet_secret,
353                    )),
354                    SenderRatchet::EncryptionRatchet(RatchetSecret::initial_ratchet_secret(
355                        application_ratchet_secret,
356                    )),
357                )
358            }
359            #[cfg(feature = "virtual-clients-draft")]
360            {
361                (
362                    SenderRatchet::DualUse(DualUseRatchet::new(handshake_ratchet_secret)),
363                    SenderRatchet::DualUse(DualUseRatchet::new(application_ratchet_secret)),
364                )
365            }
366        } else {
367            (
368                SenderRatchet::DecryptionRatchet(DecryptionRatchet::new(handshake_ratchet_secret)),
369                SenderRatchet::DecryptionRatchet(DecryptionRatchet::new(
370                    application_ratchet_secret,
371                )),
372            )
373        };
374
375        *self
376            .handshake_sender_ratchets
377            .get_mut(index.usize())
378            .ok_or(SecretTreeError::IndexOutOfBounds)? = Some(handshake_sender_ratchet);
379        *self
380            .application_sender_ratchets
381            .get_mut(index.usize())
382            .ok_or(SecretTreeError::IndexOutOfBounds)? = Some(application_sender_ratchet);
383
384        // Delete leaf node
385        self.set_node(index.into(), None)
386    }
387
388    /// Returns the [`DecryptionSecret`] for a given index and generation
389    /// without changing the sender's ratchet. If the secret is
390    /// [`DecryptionSecret::Available`], also returns the change that
391    /// [`Self::apply_decryption_update`] applies to mark the generation as
392    /// used. Until then, the generation can be requested again.
393    ///
394    /// The sender's ratchets are initialized in the tree if they weren't
395    /// before.
396    ///
397    /// Returns an error if index or generation are out of bound.
398    pub(crate) fn prepare_decryption(
399        &mut self,
400        ciphersuite: Ciphersuite,
401        crypto: &impl OpenMlsCrypto,
402        index: LeafNodeIndex,
403        secret_type: SecretType,
404        generation: u32,
405        configuration: &SenderRatchetConfiguration,
406    ) -> Result<(DecryptionSecret, Option<PendingRatchetUpdate>), SecretTreeError> {
407        log::debug!(
408            "Generating {secret_type:?} decryption secret for {index:?} in generation {generation} with {ciphersuite}",
409        );
410        // Check tree bounds
411        if index.u32() >= self.size.leaf_count() {
412            log::error!("Sender index is not in the tree.");
413            return Err(SecretTreeError::IndexOutOfBounds);
414        }
415        if self.ratchet_opt(index, secret_type)?.is_none() {
416            log::trace!("   initialize sender ratchets");
417            self.initialize_sender_ratchets(ciphersuite, crypto, index)?;
418        }
419        let (decryption_secret, peeked) = match self.ratchet_mut(index, secret_type)? {
420            SenderRatchet::EncryptionRatchet(_) => {
421                log::error!("This is the wrong ratchet type.");
422                return Err(SecretTreeError::RatchetTypeError);
423            }
424            SenderRatchet::DecryptionRatchet(dec_ratchet) => {
425                log::trace!("   getting secret for decryption");
426                let (ratchet_key_material, peeked) =
427                    dec_ratchet.peek(ciphersuite, crypto, generation, configuration)?;
428                (
429                    DecryptionSecret::Available(ratchet_key_material),
430                    Some(PeekedRatchetGeneration::Decryption(peeked)),
431                )
432            }
433            #[cfg(feature = "virtual-clients-draft")]
434            SenderRatchet::DualUse(dual_ratchet) => {
435                log::trace!("   getting secret for decryption (own dual-use ratchet)");
436                let (decryption_secret, peeked) =
437                    dual_ratchet.peek(ciphersuite, crypto, generation, configuration)?;
438                (
439                    decryption_secret,
440                    peeked.map(PeekedRatchetGeneration::DualUse),
441                )
442            }
443        };
444        let update = peeked.map(|peeked| PendingRatchetUpdate {
445            index,
446            secret_type,
447            peeked: Box::new(peeked),
448        });
449        Ok((decryption_secret, update))
450    }
451
452    /// Marks the generation in `update` as used in the sender's ratchet.
453    pub(crate) fn apply_decryption_update(
454        &mut self,
455        update: PendingRatchetUpdate,
456        configuration: &SenderRatchetConfiguration,
457    ) -> Result<(), SecretTreeError> {
458        let ratchet = self.ratchet_mut(update.index, update.secret_type)?;
459        match (ratchet, *update.peeked) {
460            (
461                SenderRatchet::DecryptionRatchet(dec_ratchet),
462                PeekedRatchetGeneration::Decryption(peeked),
463            ) => dec_ratchet.consume(peeked, configuration),
464            #[cfg(feature = "virtual-clients-draft")]
465            (SenderRatchet::DualUse(dual_ratchet), PeekedRatchetGeneration::DualUse(peeked)) => {
466                dual_ratchet.consume(peeked, configuration)
467            }
468            _ => Err(SecretTreeError::RatchetTypeError),
469        }
470    }
471
472    /// Return the [`DecryptionSecret`] for a given index and generation and
473    /// mark the generation as used.
474    /// Returns an error if index or generation are out of bound.
475    #[cfg(any(feature = "test-utils", test))]
476    pub(crate) fn secret_for_decryption(
477        &mut self,
478        ciphersuite: Ciphersuite,
479        crypto: &impl OpenMlsCrypto,
480        index: LeafNodeIndex,
481        secret_type: SecretType,
482        generation: u32,
483        configuration: &SenderRatchetConfiguration,
484    ) -> Result<DecryptionSecret, SecretTreeError> {
485        let (decryption_secret, update) = self.prepare_decryption(
486            ciphersuite,
487            crypto,
488            index,
489            secret_type,
490            generation,
491            configuration,
492        )?;
493        if let Some(update) = update {
494            self.apply_decryption_update(update, configuration)?;
495        }
496        Ok(decryption_secret)
497    }
498
499    /// Return the next RatchetSecrets that should be used for encryption and
500    /// then increments the generation.
501    pub(crate) fn secret_for_encryption(
502        &mut self,
503        ciphersuite: Ciphersuite,
504        crypto: &impl OpenMlsCrypto,
505        index: LeafNodeIndex,
506        secret_type: SecretType,
507    ) -> Result<(u32, RatchetKeyMaterial), SecretTreeError> {
508        if self.ratchet_opt(index, secret_type)?.is_none() {
509            self.initialize_sender_ratchets(ciphersuite, crypto, index)?;
510        }
511        match self.ratchet_mut(index, secret_type)? {
512            SenderRatchet::DecryptionRatchet(_) => {
513                log::error!("Invalid ratchet type. Got decryption, expected encryption.");
514                Err(SecretTreeError::RatchetTypeError)
515            }
516            SenderRatchet::EncryptionRatchet(enc_ratchet) => {
517                enc_ratchet.ratchet_forward(crypto, ciphersuite)
518            }
519            #[cfg(feature = "virtual-clients-draft")]
520            SenderRatchet::DualUse(dual_ratchet) => {
521                dual_ratchet.secret_for_encryption(ciphersuite, crypto)
522            }
523        }
524    }
525
526    #[cfg(feature = "virtual-clients-draft")]
527    pub(crate) fn delete_own_secret_for_generation(
528        &mut self,
529        secret_type: SecretType,
530        generation: Generation,
531    ) -> Result<(), SecretTreeError> {
532        match self.ratchet_mut(self.own_index, secret_type)? {
533            SenderRatchet::DualUse(dual_ratchet) => {
534                dual_ratchet.delete_secret_for_generation(generation);
535                Ok(())
536            }
537            SenderRatchet::EncryptionRatchet(_) | SenderRatchet::DecryptionRatchet(_) => {
538                Err(SecretTreeError::RatchetTypeError)
539            }
540        }
541    }
542
543    /// Returns a mutable reference to a specific SenderRatchet. The
544    /// SenderRatchet needs to be initialized.
545    fn ratchet_mut(
546        &mut self,
547        index: LeafNodeIndex,
548        secret_type: SecretType,
549    ) -> Result<&mut SenderRatchet, SecretTreeError> {
550        let sender_ratchets = match secret_type {
551            SecretType::HandshakeSecret => &mut self.handshake_sender_ratchets,
552            SecretType::ApplicationSecret => &mut self.application_sender_ratchets,
553        };
554        sender_ratchets
555            .get_mut(index.usize())
556            .and_then(|r| r.as_mut())
557            .ok_or(SecretTreeError::IndexOutOfBounds)
558    }
559
560    /// Returns an optional reference to a specific SenderRatchet
561    fn ratchet_opt(
562        &self,
563        index: LeafNodeIndex,
564        secret_type: SecretType,
565    ) -> Result<Option<&SenderRatchet>, SecretTreeError> {
566        let sender_ratchets = match secret_type {
567            SecretType::HandshakeSecret => &self.handshake_sender_ratchets,
568            SecretType::ApplicationSecret => &self.application_sender_ratchets,
569        };
570        match sender_ratchets.get(index.usize()) {
571            Some(sender_ratchet_option) => Ok(sender_ratchet_option.as_ref()),
572            None => Err(SecretTreeError::IndexOutOfBounds),
573        }
574    }
575
576    /// Derives the secrets for the child nodes in a SecretTree and blanks the
577    /// parent node.
578    fn derive_down(
579        &mut self,
580        ciphersuite: Ciphersuite,
581        crypto: &impl OpenMlsCrypto,
582        index_in_tree: ParentNodeIndex,
583    ) -> Result<(), SecretTreeError> {
584        log::debug!(
585            "Deriving tree secret for parent node {} with {}",
586            index_in_tree.u32(),
587            ciphersuite
588        );
589        let node_secret = match &self.get_node(index_in_tree.into())? {
590            Some(node) => &node.secret,
591            // This function only gets called top to bottom, so this should not happen
592            None => {
593                return Err(SecretTreeError::LibraryError);
594            }
595        };
596        log_crypto!(trace, "Node secret: {:x?}", node_secret.as_slice());
597        let left_index = left(index_in_tree);
598        let right_index = right(index_in_tree);
599        let (left_secret, right_secret) = derive_child_secrets(node_secret, crypto, ciphersuite)?;
600        log_crypto!(
601            trace,
602            "Left node ({}) secret: {:x?}",
603            left_index.test_u32(),
604            left_secret.as_slice()
605        );
606        log_crypto!(
607            trace,
608            "Right node ({}) secret: {:x?}",
609            right_index.test_u32(),
610            right_secret.as_slice()
611        );
612
613        // Populate left child
614        self.set_node(
615            left_index,
616            Some(SecretTreeNode {
617                secret: left_secret,
618            }),
619        )?;
620
621        // Populate right child
622        self.set_node(
623            right_index,
624            Some(SecretTreeNode {
625                secret: right_secret,
626            }),
627        )?;
628
629        // Delete parent node
630        self.set_node(index_in_tree.into(), None)
631    }
632
633    fn get_node(&self, index: TreeNodeIndex) -> Result<Option<&SecretTreeNode>, SecretTreeError> {
634        match index {
635            TreeNodeIndex::Leaf(leaf_index) => Ok(self
636                .leaf_nodes
637                .get(leaf_index.usize())
638                .ok_or(SecretTreeError::IndexOutOfBounds)?
639                .as_ref()),
640            TreeNodeIndex::Parent(parent_index) => Ok(self
641                .parent_nodes
642                .get(parent_index.usize())
643                .ok_or(SecretTreeError::IndexOutOfBounds)?
644                .as_ref()),
645        }
646    }
647
648    fn set_node(
649        &mut self,
650        index: TreeNodeIndex,
651        node: Option<SecretTreeNode>,
652    ) -> Result<(), SecretTreeError> {
653        match index {
654            TreeNodeIndex::Leaf(leaf_index) => {
655                *self
656                    .leaf_nodes
657                    .get_mut(leaf_index.usize())
658                    .ok_or(SecretTreeError::IndexOutOfBounds)? = node;
659            }
660            TreeNodeIndex::Parent(parent_index) => {
661                *self
662                    .parent_nodes
663                    .get_mut(parent_index.usize())
664                    .ok_or(SecretTreeError::IndexOutOfBounds)? = node;
665            }
666        }
667        Ok(())
668    }
669}