bramble-transport 0.1.0

Bramble Transport Protocol
Documentation
//! BTP rotation mode

use super::{Keychain, RotateKeys};
use crate::{Error, Result};
use bramble_common::transport::{Id, Latency};
use bramble_crypto::{kdf, Role, SymmetricKey};
use futures::{AsyncRead, AsyncWrite};
use std::marker::PhantomData;

/// Key rotator for rotation mode
pub struct RotationKeys<T>
where
    T: Id + Latency + AsyncRead + AsyncWrite,
{
    now: u64,
    outgoing: Keychain,

    incoming_previous: Keychain,
    incoming_current: Keychain,
    incoming_next: Keychain,
    transport: PhantomData<T>,
}

impl<T> RotateKeys for RotationKeys<T>
where
    T: Id + Latency + AsyncRead + AsyncWrite,
{
    fn outgoing_keys_for(&mut self, period: u64) -> Result<Keychain> {
        if period < self.now {
            return Err(Error::TimePeriodIsPast);
        }
        while self.now != period {
            self.rotate();
        }
        Ok(self.outgoing)
    }

    fn incoming_keys_for(&mut self, period: u64) -> Result<Keychain> {
        if period < self.now - 1 {
            return Err(Error::TimePeriodIsPast);
        }
        while period > self.now + 1 {
            self.rotate();
        }
        Ok(if period == self.now - 1 {
            self.incoming_previous
        } else if period == self.now {
            self.incoming_current
        } else {
            self.incoming_next
        })
    }
}

impl<T> RotationKeys<T>
where
    T: Id + Latency + AsyncRead + AsyncWrite,
{
    /// Creates a new rotation mode key manager
    pub fn new(root_key: SymmetricKey, now: u64, role: Role) -> Self {
        let (our_tag_key_label, our_header_key_label, their_tag_key_label, their_header_key_label) =
            match role {
                Role::Alice => (
                    ALICE_TAG_KEY_LABEL,
                    ALICE_HEADER_KEY_LABEL,
                    BOB_TAG_KEY_LABEL,
                    BOB_HEADER_KEY_LABEL,
                ),
                Role::Bob => (
                    BOB_TAG_KEY_LABEL,
                    BOB_HEADER_KEY_LABEL,
                    ALICE_TAG_KEY_LABEL,
                    ALICE_HEADER_KEY_LABEL,
                ),
            };
        let outgoing = Keychain::new(
            kdf(our_tag_key_label, &root_key, &[T::ID]),
            kdf(our_header_key_label, &root_key, &[T::ID]),
        )
        .next(now);

        let incoming_previous = Keychain::new(
            kdf(their_tag_key_label, &root_key, &[T::ID]),
            kdf(their_header_key_label, &root_key, &[T::ID]),
        );
        let incoming_current = incoming_previous.next(now);
        let incoming_next = incoming_current.next(now + 1);
        Self {
            now,
            outgoing,
            incoming_previous,
            incoming_current,
            incoming_next,
            transport: PhantomData,
        }
    }

    /// Performs one key rotation
    pub fn rotate(&mut self) {
        self.now += 1;
        self.outgoing.rotate(self.now);
        self.incoming_previous = self.incoming_current;
        self.incoming_current = self.incoming_next;
        self.incoming_next.rotate(self.now + 1);
    }
}

const ALICE_TAG_KEY_LABEL: &[u8] = b"org.briarproject.bramble.transport/ALICE_TAG_KEY";
const ALICE_HEADER_KEY_LABEL: &[u8] = b"org.briarproject.bramble.transport/ALICE_HEADER_KEY";
const BOB_TAG_KEY_LABEL: &[u8] = b"org.briarproject.bramble.transport/BOB_TAG_KEY";
const BOB_HEADER_KEY_LABEL: &[u8] = b"org.briarproject.bramble.transport/BOB_HEADER_KEY";