use super::{Keychain, RotateKeys};
use crate::Result;
use bramble_common::transport::{Id, Latency};
use bramble_crypto::{kdf, Role, SymmetricKey};
use futures::{AsyncRead, AsyncWrite};
use std::marker::PhantomData;
pub struct HandshakeKeys<T>
where
T: Id + Latency + AsyncRead + AsyncWrite,
{
root_key: SymmetricKey,
role: Role,
transport: PhantomData<T>,
}
impl<T> RotateKeys for HandshakeKeys<T>
where
T: Id + Latency + AsyncRead + AsyncWrite,
{
fn outgoing_keys_for(&mut self, period: u64) -> Result<Keychain> {
Ok(self.derive_outgoing_keys(period))
}
fn incoming_keys_for(&mut self, period: u64) -> Result<Keychain> {
Ok(self.derive_incoming_keys(period))
}
}
impl<T> HandshakeKeys<T>
where
T: Id + Latency + AsyncRead + AsyncWrite,
{
pub fn new(root_key: SymmetricKey, role: Role) -> Self {
Self {
root_key,
role,
transport: PhantomData,
}
}
fn derive_outgoing_keys(&self, period: u64) -> Keychain {
let (our_tag_key_label, our_header_key_label) = match self.role {
Role::Alice => (
ALICE_HANDSHAKE_TAG_KEY_LABEL,
ALICE_HANDSHAKE_HEADER_KEY_LABEL,
),
Role::Bob => (BOB_HANDSHAKE_TAG_KEY_LABEL, BOB_HANDSHAKE_HEADER_KEY_LABEL),
};
self.derive_keys(period, our_tag_key_label, our_header_key_label)
}
fn derive_incoming_keys(&self, period: u64) -> Keychain {
let (their_tag_key_label, their_header_key_label) = match self.role {
Role::Alice => (BOB_HANDSHAKE_TAG_KEY_LABEL, BOB_HANDSHAKE_HEADER_KEY_LABEL),
Role::Bob => (
ALICE_HANDSHAKE_TAG_KEY_LABEL,
ALICE_HANDSHAKE_HEADER_KEY_LABEL,
),
};
self.derive_keys(period, their_tag_key_label, their_header_key_label)
}
fn derive_keys(
&self,
period: u64,
tag_key_label: &'static [u8],
header_key_label: &'static [u8],
) -> Keychain {
Keychain::new(
kdf(
tag_key_label,
&self.root_key,
&[T::ID, &period.to_be_bytes()],
),
kdf(
header_key_label,
&self.root_key,
&[T::ID, &period.to_be_bytes()],
),
)
}
}
const ALICE_HANDSHAKE_TAG_KEY_LABEL: &[u8] =
b"org.briarproject.bramble.transport/ALICE_HANDSHAKE_TAG_KEY";
const ALICE_HANDSHAKE_HEADER_KEY_LABEL: &[u8] =
b"org.briarproject.bramble.transport/ALICE_HANDSHAKE_HEADER_KEY";
const BOB_HANDSHAKE_TAG_KEY_LABEL: &[u8] =
b"org.briarproject.bramble.transport/BOB_HANDSHAKE_TAG_KEY";
const BOB_HANDSHAKE_HEADER_KEY_LABEL: &[u8] =
b"org.briarproject.bramble.transport/BOB_HANDSHAKE_HEADER_KEY";