mirror of
https://github.com/rosenpass/rosenpass.git
synced 2026-02-28 06:23:08 -08:00
feat: Move prftree into ciphers crate
- Use a new nomenclature for these functions based on the idea of a hash domain (as in domain separation); this makes much more sence - Remove the ciphers::hash export; we did not even export a hash function in the purest sence of the word. This gets us around the difficulty of figuring out what we should call the underlying primitive
This commit is contained in:
committed by
Karolin Varner
parent
0f89ab7976
commit
77cd8a9fd1
1
Cargo.lock
generated
1
Cargo.lock
generated
@@ -1096,6 +1096,7 @@ version = "0.1.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"rosenpass-constant-time",
|
"rosenpass-constant-time",
|
||||||
|
"rosenpass-secret-memory",
|
||||||
"rosenpass-sodium",
|
"rosenpass-sodium",
|
||||||
"rosenpass-to",
|
"rosenpass-to",
|
||||||
"static_assertions",
|
"static_assertions",
|
||||||
|
|||||||
@@ -14,5 +14,6 @@ anyhow = { workspace = true }
|
|||||||
rosenpass-sodium = { workspace = true }
|
rosenpass-sodium = { workspace = true }
|
||||||
rosenpass-to = { workspace = true }
|
rosenpass-to = { workspace = true }
|
||||||
rosenpass-constant-time = { workspace = true }
|
rosenpass-constant-time = { workspace = true }
|
||||||
|
rosenpass-secret-memory = { workspace = true }
|
||||||
static_assertions = { workspace = true }
|
static_assertions = { workspace = true }
|
||||||
zeroize = { workspace = true }
|
zeroize = { workspace = true }
|
||||||
|
|||||||
@@ -1,31 +1,32 @@
|
|||||||
//! Implementation of the tree-like structure used for the label derivation in [labeled_prf](crate::labeled_prf)
|
|
||||||
use rosenpass_secret_memory::Secret;
|
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use rosenpass_ciphers::{hash, KEY_LEN};
|
use rosenpass_secret_memory::Secret;
|
||||||
use rosenpass_to::To;
|
use rosenpass_to::To;
|
||||||
|
|
||||||
|
use crate::subtle::incorrect_hmac_blake2b as hash;
|
||||||
|
|
||||||
|
pub use hash::KEY_LEN;
|
||||||
|
|
||||||
// TODO Use a proper Dec interface
|
// TODO Use a proper Dec interface
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct PrfTree([u8; KEY_LEN]);
|
pub struct HashDomain([u8; KEY_LEN]);
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct PrfTreeBranch([u8; KEY_LEN]);
|
pub struct HashDomainNamespace([u8; KEY_LEN]);
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct SecretPrfTree(Secret<KEY_LEN>);
|
pub struct SecretHashDomain(Secret<KEY_LEN>);
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct SecretPrfTreeBranch(Secret<KEY_LEN>);
|
pub struct SecretHashDomainNamespace(Secret<KEY_LEN>);
|
||||||
|
|
||||||
impl PrfTree {
|
impl HashDomain {
|
||||||
pub fn zero() -> Self {
|
pub fn zero() -> Self {
|
||||||
Self([0u8; KEY_LEN])
|
Self([0u8; KEY_LEN])
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn dup(self) -> PrfTreeBranch {
|
pub fn dup(self) -> HashDomainNamespace {
|
||||||
PrfTreeBranch(self.0)
|
HashDomainNamespace(self.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn into_secret_prf_tree(self) -> SecretPrfTree {
|
pub fn turn_secret(self) -> SecretHashDomain {
|
||||||
SecretPrfTree(Secret::from_slice(&self.0))
|
SecretHashDomain(Secret::from_slice(&self.0))
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Protocol! Use domain separation to ensure that
|
// TODO: Protocol! Use domain separation to ensure that
|
||||||
@@ -33,8 +34,8 @@ impl PrfTree {
|
|||||||
Ok(Self(hash::hash(&self.0, v).collect::<[u8; KEY_LEN]>()?))
|
Ok(Self(hash::hash(&self.0, v).collect::<[u8; KEY_LEN]>()?))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mix_secret<const N: usize>(self, v: Secret<N>) -> Result<SecretPrfTree> {
|
pub fn mix_secret<const N: usize>(self, v: Secret<N>) -> Result<SecretHashDomain> {
|
||||||
SecretPrfTree::prf_invoc(&self.0, v.secret())
|
SecretHashDomain::invoke_primitive(&self.0, v.secret())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn into_value(self) -> [u8; KEY_LEN] {
|
pub fn into_value(self) -> [u8; KEY_LEN] {
|
||||||
@@ -42,19 +43,21 @@ impl PrfTree {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PrfTreeBranch {
|
impl HashDomainNamespace {
|
||||||
pub fn mix(&self, v: &[u8]) -> Result<PrfTree> {
|
pub fn mix(&self, v: &[u8]) -> Result<HashDomain> {
|
||||||
Ok(PrfTree(hash::hash(&self.0, v).collect::<[u8; KEY_LEN]>()?))
|
Ok(HashDomain(
|
||||||
|
hash::hash(&self.0, v).collect::<[u8; KEY_LEN]>()?,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mix_secret<const N: usize>(&self, v: Secret<N>) -> Result<SecretPrfTree> {
|
pub fn mix_secret<const N: usize>(&self, v: Secret<N>) -> Result<SecretHashDomain> {
|
||||||
SecretPrfTree::prf_invoc(&self.0, v.secret())
|
SecretHashDomain::invoke_primitive(&self.0, v.secret())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SecretPrfTree {
|
impl SecretHashDomain {
|
||||||
pub fn prf_invoc(k: &[u8], d: &[u8]) -> Result<SecretPrfTree> {
|
pub fn invoke_primitive(k: &[u8], d: &[u8]) -> Result<SecretHashDomain> {
|
||||||
let mut r = SecretPrfTree(Secret::zero());
|
let mut r = SecretHashDomain(Secret::zero());
|
||||||
hash::hash(k, d).to(r.0.secret_mut())?;
|
hash::hash(k, d).to(r.0.secret_mut())?;
|
||||||
Ok(r)
|
Ok(r)
|
||||||
}
|
}
|
||||||
@@ -63,20 +66,20 @@ impl SecretPrfTree {
|
|||||||
Self(Secret::zero())
|
Self(Secret::zero())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn dup(self) -> SecretPrfTreeBranch {
|
pub fn dup(self) -> SecretHashDomainNamespace {
|
||||||
SecretPrfTreeBranch(self.0)
|
SecretHashDomainNamespace(self.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn danger_from_secret(k: Secret<KEY_LEN>) -> Self {
|
pub fn danger_from_secret(k: Secret<KEY_LEN>) -> Self {
|
||||||
Self(k)
|
Self(k)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mix(self, v: &[u8]) -> Result<SecretPrfTree> {
|
pub fn mix(self, v: &[u8]) -> Result<SecretHashDomain> {
|
||||||
Self::prf_invoc(self.0.secret(), v)
|
Self::invoke_primitive(self.0.secret(), v)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mix_secret<const N: usize>(self, v: Secret<N>) -> Result<SecretPrfTree> {
|
pub fn mix_secret<const N: usize>(self, v: Secret<N>) -> Result<SecretHashDomain> {
|
||||||
Self::prf_invoc(self.0.secret(), v.secret())
|
Self::invoke_primitive(self.0.secret(), v.secret())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn into_secret(self) -> Secret<KEY_LEN> {
|
pub fn into_secret(self) -> Secret<KEY_LEN> {
|
||||||
@@ -88,13 +91,13 @@ impl SecretPrfTree {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SecretPrfTreeBranch {
|
impl SecretHashDomainNamespace {
|
||||||
pub fn mix(&self, v: &[u8]) -> Result<SecretPrfTree> {
|
pub fn mix(&self, v: &[u8]) -> Result<SecretHashDomain> {
|
||||||
SecretPrfTree::prf_invoc(self.0.secret(), v)
|
SecretHashDomain::invoke_primitive(self.0.secret(), v)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mix_secret<const N: usize>(&self, v: Secret<N>) -> Result<SecretPrfTree> {
|
pub fn mix_secret<const N: usize>(&self, v: Secret<N>) -> Result<SecretHashDomain> {
|
||||||
SecretPrfTree::prf_invoc(self.0.secret(), v.secret())
|
SecretHashDomain::invoke_primitive(self.0.secret(), v.secret())
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: This entire API is not very nice; we need this for biscuits, but
|
// TODO: This entire API is not very nice; we need this for biscuits, but
|
||||||
@@ -5,7 +5,7 @@ pub mod subtle;
|
|||||||
pub const KEY_LEN: usize = 32;
|
pub const KEY_LEN: usize = 32;
|
||||||
const_assert!(KEY_LEN == aead::KEY_LEN);
|
const_assert!(KEY_LEN == aead::KEY_LEN);
|
||||||
const_assert!(KEY_LEN == xaead::KEY_LEN);
|
const_assert!(KEY_LEN == xaead::KEY_LEN);
|
||||||
const_assert!(KEY_LEN == hash::KEY_LEN);
|
const_assert!(KEY_LEN == hash_domain::KEY_LEN);
|
||||||
|
|
||||||
/// Authenticated encryption with associated data
|
/// Authenticated encryption with associated data
|
||||||
pub mod aead {
|
pub mod aead {
|
||||||
@@ -21,8 +21,4 @@ pub mod xaead {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod hash {
|
pub mod hash_domain;
|
||||||
pub use crate::subtle::incorrect_hmac_blake2b::{
|
|
||||||
hash, KEY_LEN, KEY_MAX, KEY_MIN, OUT_MAX, OUT_MIN,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|||||||
46
rosenpass/src/hash_domains.rs
Normal file
46
rosenpass/src/hash_domains.rs
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
//! Pseudo Random Functions (PRFs) with a tree-like label scheme which
|
||||||
|
//! ensures their uniqueness
|
||||||
|
|
||||||
|
use anyhow::Result;
|
||||||
|
use rosenpass_ciphers::{hash_domain::HashDomain, KEY_LEN};
|
||||||
|
|
||||||
|
// TODO Use labels that can serve as identifiers
|
||||||
|
macro_rules! hash_domain_ns {
|
||||||
|
($base:ident, $name:ident, $($lbl:expr),* ) => {
|
||||||
|
pub fn $name() -> Result<HashDomain> {
|
||||||
|
let t = $base()?;
|
||||||
|
$( let t = t.mix($lbl.as_bytes())?; )*
|
||||||
|
Ok(t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! hash_domain {
|
||||||
|
($base:ident, $name:ident, $($lbl:expr),* ) => {
|
||||||
|
pub fn $name() -> Result<[u8; KEY_LEN]> {
|
||||||
|
let t = $base()?;
|
||||||
|
$( let t = t.mix($lbl.as_bytes())?; )*
|
||||||
|
Ok(t.into_value())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn protocol() -> Result<HashDomain> {
|
||||||
|
HashDomain::zero().mix("Rosenpass v1 mceliece460896 Kyber512 ChaChaPoly1305 BLAKE2s".as_bytes())
|
||||||
|
}
|
||||||
|
|
||||||
|
hash_domain_ns!(protocol, mac, "mac");
|
||||||
|
hash_domain_ns!(protocol, cookie, "cookie");
|
||||||
|
hash_domain_ns!(protocol, peerid, "peer id");
|
||||||
|
hash_domain_ns!(protocol, biscuit_ad, "biscuit additional data");
|
||||||
|
hash_domain_ns!(protocol, ckinit, "chaining key init");
|
||||||
|
hash_domain_ns!(protocol, _ckextract, "chaining key extract");
|
||||||
|
|
||||||
|
hash_domain!(_ckextract, mix, "mix");
|
||||||
|
hash_domain!(_ckextract, hs_enc, "handshake encryption");
|
||||||
|
hash_domain!(_ckextract, ini_enc, "initiator handshake encryption");
|
||||||
|
hash_domain!(_ckextract, res_enc, "responder handshake encryption");
|
||||||
|
|
||||||
|
hash_domain_ns!(_ckextract, _user, "user");
|
||||||
|
hash_domain_ns!(_user, _rp, "rosenpass.eu");
|
||||||
|
hash_domain!(_rp, osk, "wireguard psk");
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
//! Pseudo Random Functions (PRFs) with a tree-like label scheme which
|
|
||||||
//! ensures their uniqueness
|
|
||||||
|
|
||||||
|
|
||||||
use crate::prftree::PrfTree;
|
|
||||||
use anyhow::Result;
|
|
||||||
use rosenpass_ciphers::KEY_LEN;
|
|
||||||
|
|
||||||
pub fn protocol() -> Result<PrfTree> {
|
|
||||||
PrfTree::zero().mix("Rosenpass v1 mceliece460896 Kyber512 ChaChaPoly1305 BLAKE2s".as_bytes())
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO Use labels that can serve as identifiers
|
|
||||||
macro_rules! prflabel {
|
|
||||||
($base:ident, $name:ident, $($lbl:expr),* ) => {
|
|
||||||
pub fn $name() -> Result<PrfTree> {
|
|
||||||
let t = $base()?;
|
|
||||||
$( let t = t.mix($lbl.as_bytes())?; )*
|
|
||||||
Ok(t)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
prflabel!(protocol, mac, "mac");
|
|
||||||
prflabel!(protocol, cookie, "cookie");
|
|
||||||
prflabel!(protocol, peerid, "peer id");
|
|
||||||
prflabel!(protocol, biscuit_ad, "biscuit additional data");
|
|
||||||
prflabel!(protocol, ckinit, "chaining key init");
|
|
||||||
prflabel!(protocol, _ckextract, "chaining key extract");
|
|
||||||
|
|
||||||
macro_rules! prflabel_leaf {
|
|
||||||
($base:ident, $name:ident, $($lbl:expr),* ) => {
|
|
||||||
pub fn $name() -> Result<[u8; KEY_LEN]> {
|
|
||||||
let t = $base()?;
|
|
||||||
$( let t = t.mix($lbl.as_bytes())?; )*
|
|
||||||
Ok(t.into_value())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
prflabel_leaf!(_ckextract, mix, "mix");
|
|
||||||
prflabel_leaf!(_ckextract, hs_enc, "handshake encryption");
|
|
||||||
prflabel_leaf!(_ckextract, ini_enc, "initiator handshake encryption");
|
|
||||||
prflabel_leaf!(_ckextract, res_enc, "responder handshake encryption");
|
|
||||||
|
|
||||||
prflabel!(_ckextract, _user, "user");
|
|
||||||
prflabel!(_user, _rp, "rosenpass.eu");
|
|
||||||
prflabel_leaf!(_rp, osk, "wireguard psk");
|
|
||||||
@@ -1,11 +1,9 @@
|
|||||||
#[rustfmt::skip]
|
|
||||||
pub mod labeled_prf;
|
|
||||||
pub mod app_server;
|
pub mod app_server;
|
||||||
pub mod cli;
|
pub mod cli;
|
||||||
pub mod config;
|
pub mod config;
|
||||||
|
pub mod hash_domains;
|
||||||
pub mod msgs;
|
pub mod msgs;
|
||||||
pub mod pqkem;
|
pub mod pqkem;
|
||||||
pub mod prftree;
|
|
||||||
pub mod protocol;
|
pub mod protocol;
|
||||||
|
|
||||||
#[derive(thiserror::Error, Debug)]
|
#[derive(thiserror::Error, Debug)]
|
||||||
|
|||||||
@@ -67,13 +67,9 @@
|
|||||||
//! # }
|
//! # }
|
||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
use crate::{
|
use crate::{hash_domains, msgs::*, pqkem::*};
|
||||||
labeled_prf as lprf,
|
|
||||||
msgs::*,
|
|
||||||
pqkem::*,
|
|
||||||
prftree::{SecretPrfTree, SecretPrfTreeBranch},
|
|
||||||
};
|
|
||||||
use anyhow::{bail, ensure, Context, Result};
|
use anyhow::{bail, ensure, Context, Result};
|
||||||
|
use rosenpass_ciphers::hash_domain::{SecretHashDomain, SecretHashDomainNamespace};
|
||||||
use rosenpass_ciphers::{aead, xaead, KEY_LEN};
|
use rosenpass_ciphers::{aead, xaead, KEY_LEN};
|
||||||
use rosenpass_secret_memory::{Public, Secret};
|
use rosenpass_secret_memory::{Public, Secret};
|
||||||
use rosenpass_util::{cat, mem::cpy_min, ord::max_usize, time::Timebase};
|
use rosenpass_util::{cat, mem::cpy_min, ord::max_usize, time::Timebase};
|
||||||
@@ -233,7 +229,7 @@ pub struct HandshakeState {
|
|||||||
/// Session ID of Responder
|
/// Session ID of Responder
|
||||||
pub sidr: SessionId,
|
pub sidr: SessionId,
|
||||||
/// Chaining Key
|
/// Chaining Key
|
||||||
pub ck: SecretPrfTreeBranch,
|
pub ck: SecretHashDomainNamespace, // TODO: We should probably add an abstr
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Hash, PartialEq, Eq, PartialOrd, Ord, Debug, Copy, Clone)]
|
#[derive(Hash, PartialEq, Eq, PartialOrd, Ord, Debug, Copy, Clone)]
|
||||||
@@ -285,7 +281,7 @@ pub struct Session {
|
|||||||
pub sidt: SessionId,
|
pub sidt: SessionId,
|
||||||
pub handshake_role: HandshakeRole,
|
pub handshake_role: HandshakeRole,
|
||||||
// Crypto
|
// Crypto
|
||||||
pub ck: SecretPrfTreeBranch,
|
pub ck: SecretHashDomainNamespace,
|
||||||
/// Key for Transmission ("transmission key mine")
|
/// Key for Transmission ("transmission key mine")
|
||||||
pub txkm: SymKey,
|
pub txkm: SymKey,
|
||||||
/// Key for Reception ("transmission key theirs")
|
/// Key for Reception ("transmission key theirs")
|
||||||
@@ -460,7 +456,7 @@ impl CryptoServer {
|
|||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
pub fn pidm(&self) -> Result<PeerId> {
|
pub fn pidm(&self) -> Result<PeerId> {
|
||||||
Ok(Public::new(
|
Ok(Public::new(
|
||||||
lprf::peerid()?
|
hash_domains::peerid()?
|
||||||
.mix(self.spkm.secret())?
|
.mix(self.spkm.secret())?
|
||||||
.into_value()))
|
.into_value()))
|
||||||
}
|
}
|
||||||
@@ -590,7 +586,7 @@ impl Peer {
|
|||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
pub fn pidt(&self) -> Result<PeerId> {
|
pub fn pidt(&self) -> Result<PeerId> {
|
||||||
Ok(Public::new(
|
Ok(Public::new(
|
||||||
lprf::peerid()?
|
hash_domains::peerid()?
|
||||||
.mix(self.spkt.secret())?
|
.mix(self.spkt.secret())?
|
||||||
.into_value()))
|
.into_value()))
|
||||||
}
|
}
|
||||||
@@ -603,7 +599,7 @@ impl Session {
|
|||||||
sidm: SessionId::zero(),
|
sidm: SessionId::zero(),
|
||||||
sidt: SessionId::zero(),
|
sidt: SessionId::zero(),
|
||||||
handshake_role: HandshakeRole::Initiator,
|
handshake_role: HandshakeRole::Initiator,
|
||||||
ck: SecretPrfTree::zero().dup(),
|
ck: SecretHashDomain::zero().dup(),
|
||||||
txkm: SymKey::zero(),
|
txkm: SymKey::zero(),
|
||||||
txkt: SymKey::zero(),
|
txkt: SymKey::zero(),
|
||||||
txnm: 0,
|
txnm: 0,
|
||||||
@@ -1174,7 +1170,7 @@ where
|
|||||||
{
|
{
|
||||||
/// Calculate the message authentication code (`mac`)
|
/// Calculate the message authentication code (`mac`)
|
||||||
pub fn seal(&mut self, peer: PeerPtr, srv: &CryptoServer) -> Result<()> {
|
pub fn seal(&mut self, peer: PeerPtr, srv: &CryptoServer) -> Result<()> {
|
||||||
let mac = lprf::mac()?
|
let mac = hash_domains::mac()?
|
||||||
.mix(peer.get(srv).spkt.secret())?
|
.mix(peer.get(srv).spkt.secret())?
|
||||||
.mix(self.until_mac())?;
|
.mix(self.until_mac())?;
|
||||||
self.mac_mut()
|
self.mac_mut()
|
||||||
@@ -1189,7 +1185,9 @@ where
|
|||||||
{
|
{
|
||||||
/// Check the message authentication code
|
/// Check the message authentication code
|
||||||
pub fn check_seal(&self, srv: &CryptoServer) -> Result<bool> {
|
pub fn check_seal(&self, srv: &CryptoServer) -> Result<bool> {
|
||||||
let expected = lprf::mac()?.mix(srv.spkm.secret())?.mix(self.until_mac())?;
|
let expected = hash_domains::mac()?
|
||||||
|
.mix(srv.spkm.secret())?
|
||||||
|
.mix(self.until_mac())?;
|
||||||
Ok(rosenpass_sodium::helpers::memcmp(
|
Ok(rosenpass_sodium::helpers::memcmp(
|
||||||
self.mac(),
|
self.mac(),
|
||||||
&expected.into_value()[..16],
|
&expected.into_value()[..16],
|
||||||
@@ -1219,32 +1217,32 @@ impl HandshakeState {
|
|||||||
Self {
|
Self {
|
||||||
sidi: SessionId::zero(),
|
sidi: SessionId::zero(),
|
||||||
sidr: SessionId::zero(),
|
sidr: SessionId::zero(),
|
||||||
ck: SecretPrfTree::zero().dup(),
|
ck: SecretHashDomain::zero().dup(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn erase(&mut self) {
|
pub fn erase(&mut self) {
|
||||||
self.ck = SecretPrfTree::zero().dup();
|
self.ck = SecretHashDomain::zero().dup();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn init(&mut self, spkr: &[u8]) -> Result<&mut Self> {
|
pub fn init(&mut self, spkr: &[u8]) -> Result<&mut Self> {
|
||||||
self.ck = lprf::ckinit()?.mix(spkr)?.into_secret_prf_tree().dup();
|
self.ck = hash_domains::ckinit()?.turn_secret().mix(spkr)?.dup();
|
||||||
Ok(self)
|
Ok(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mix(&mut self, a: &[u8]) -> Result<&mut Self> {
|
pub fn mix(&mut self, a: &[u8]) -> Result<&mut Self> {
|
||||||
self.ck = self.ck.mix(&lprf::mix()?)?.mix(a)?.dup();
|
self.ck = self.ck.mix(&hash_domains::mix()?)?.mix(a)?.dup();
|
||||||
Ok(self)
|
Ok(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn encrypt_and_mix(&mut self, ct: &mut [u8], pt: &[u8]) -> Result<&mut Self> {
|
pub fn encrypt_and_mix(&mut self, ct: &mut [u8], pt: &[u8]) -> Result<&mut Self> {
|
||||||
let k = self.ck.mix(&lprf::hs_enc()?)?.into_secret();
|
let k = self.ck.mix(&hash_domains::hs_enc()?)?.into_secret();
|
||||||
aead::encrypt(ct, k.secret(), &[0u8; aead::NONCE_LEN], &[], pt)?;
|
aead::encrypt(ct, k.secret(), &[0u8; aead::NONCE_LEN], &[], pt)?;
|
||||||
self.mix(ct)
|
self.mix(ct)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn decrypt_and_mix(&mut self, pt: &mut [u8], ct: &[u8]) -> Result<&mut Self> {
|
pub fn decrypt_and_mix(&mut self, pt: &mut [u8], ct: &[u8]) -> Result<&mut Self> {
|
||||||
let k = self.ck.mix(&lprf::hs_enc()?)?.into_secret();
|
let k = self.ck.mix(&hash_domains::hs_enc()?)?.into_secret();
|
||||||
aead::decrypt(pt, k.secret(), &[0u8; aead::NONCE_LEN], &[], ct)?;
|
aead::decrypt(pt, k.secret(), &[0u8; aead::NONCE_LEN], &[], ct)?;
|
||||||
self.mix(ct)
|
self.mix(ct)
|
||||||
}
|
}
|
||||||
@@ -1290,7 +1288,7 @@ impl HandshakeState {
|
|||||||
.copy_from_slice(self.ck.clone().danger_into_secret().secret());
|
.copy_from_slice(self.ck.clone().danger_into_secret().secret());
|
||||||
|
|
||||||
// calculate ad contents
|
// calculate ad contents
|
||||||
let ad = lprf::biscuit_ad()?
|
let ad = hash_domains::biscuit_ad()?
|
||||||
.mix(srv.spkm.secret())?
|
.mix(srv.spkm.secret())?
|
||||||
.mix(self.sidi.as_slice())?
|
.mix(self.sidi.as_slice())?
|
||||||
.mix(self.sidr.as_slice())?
|
.mix(self.sidr.as_slice())?
|
||||||
@@ -1325,7 +1323,7 @@ impl HandshakeState {
|
|||||||
let bk = BiscuitKeyPtr(((biscuit_ct[0] & 0b1000_0000) >> 7) as usize);
|
let bk = BiscuitKeyPtr(((biscuit_ct[0] & 0b1000_0000) >> 7) as usize);
|
||||||
|
|
||||||
// Calculate additional data fields
|
// Calculate additional data fields
|
||||||
let ad = lprf::biscuit_ad()?
|
let ad = hash_domains::biscuit_ad()?
|
||||||
.mix(srv.spkm.secret())?
|
.mix(srv.spkm.secret())?
|
||||||
.mix(sidi.as_slice())?
|
.mix(sidi.as_slice())?
|
||||||
.mix(sidr.as_slice())?
|
.mix(sidr.as_slice())?
|
||||||
@@ -1343,7 +1341,7 @@ impl HandshakeState {
|
|||||||
|
|
||||||
// Reconstruct the biscuit fields
|
// Reconstruct the biscuit fields
|
||||||
let no = BiscuitId::from_slice(biscuit.biscuit_no());
|
let no = BiscuitId::from_slice(biscuit.biscuit_no());
|
||||||
let ck = SecretPrfTree::danger_from_secret(Secret::from_slice(biscuit.ck())).dup();
|
let ck = SecretHashDomain::danger_from_secret(Secret::from_slice(biscuit.ck())).dup();
|
||||||
let pid = PeerId::from_slice(biscuit.pidi());
|
let pid = PeerId::from_slice(biscuit.pidi());
|
||||||
|
|
||||||
// Reconstruct the handshake state
|
// Reconstruct the handshake state
|
||||||
@@ -1370,8 +1368,8 @@ impl HandshakeState {
|
|||||||
|
|
||||||
pub fn enter_live(self, srv: &CryptoServer, role: HandshakeRole) -> Result<Session> {
|
pub fn enter_live(self, srv: &CryptoServer, role: HandshakeRole) -> Result<Session> {
|
||||||
let HandshakeState { ck, sidi, sidr } = self;
|
let HandshakeState { ck, sidi, sidr } = self;
|
||||||
let tki = ck.mix(&lprf::ini_enc()?)?.into_secret();
|
let tki = ck.mix(&hash_domains::ini_enc()?)?.into_secret();
|
||||||
let tkr = ck.mix(&lprf::res_enc()?)?.into_secret();
|
let tkr = ck.mix(&hash_domains::res_enc()?)?.into_secret();
|
||||||
let created_at = srv.timebase.now();
|
let created_at = srv.timebase.now();
|
||||||
let (ntx, nrx) = (0, 0);
|
let (ntx, nrx) = (0, 0);
|
||||||
let (mysid, peersid, ktx, krx) = match role {
|
let (mysid, peersid, ktx, krx) = match role {
|
||||||
@@ -1402,7 +1400,7 @@ impl CryptoServer {
|
|||||||
.get(self)
|
.get(self)
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.with_context(|| format!("No current session for peer {:?}", peer))?;
|
.with_context(|| format!("No current session for peer {:?}", peer))?;
|
||||||
Ok(session.ck.mix(&lprf::osk()?)?.into_secret())
|
Ok(session.ck.mix(&hash_domains::osk()?)?.into_secret())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user