mirror of
https://github.com/zerotier/zssp.git
synced 2026-05-22 16:28:40 -07:00
got rid of unnecessary error type
This commit is contained in:
@@ -4,3 +4,10 @@ members = [
|
||||
"reference",
|
||||
]
|
||||
resolver = "2"
|
||||
|
||||
[profile.bench]
|
||||
opt-level = 3
|
||||
strip = true
|
||||
debug = true
|
||||
codegen-units = 1
|
||||
lto = true
|
||||
|
||||
@@ -10,9 +10,6 @@ name = "zssp"
|
||||
path = "src/lib.rs"
|
||||
doc = true
|
||||
|
||||
[profile.bench]
|
||||
debug = true
|
||||
|
||||
[dependencies]
|
||||
rand_core = { version = "0.6.4" }
|
||||
zeroize = { version = "1.6.0" }
|
||||
|
||||
@@ -10,7 +10,7 @@ pub trait P384PublicKey: Sized + Send + Sync {
|
||||
/// Create a P-384 public key from raw bytes.
|
||||
///
|
||||
/// **CRITICAL**: This function must return `None` if the input `raw_key` is not on the P-384
|
||||
/// curve, or if it breaks the P-384 spec in any other way.
|
||||
/// curve, or if it breaks the P-384 spec in any other way. `P384KeyPair::agree` must never fail.
|
||||
fn from_bytes(raw_key: &[u8; P384_PUBLIC_KEY_SIZE]) -> Option<Self>;
|
||||
|
||||
/// Get the raw bytes that uniquely define the public key.
|
||||
@@ -25,7 +25,7 @@ pub trait P384PublicKey: Sized + Send + Sync {
|
||||
pub trait P384KeyPair<Rng: RngCore + CryptoRng> {
|
||||
/// The `PublicKeyP384` implementation which matches this `KeyPairP384` implementation.
|
||||
type PublicKey: P384PublicKey;
|
||||
/// Randomly generate a new P-384 keypair.
|
||||
/// Randomly generate a new P-384 keypair. This keypair must be fully valid.
|
||||
///
|
||||
/// This function may use the provided RNG or its own, so long as the output is cryptographically random.
|
||||
fn generate(rng: &mut Rng) -> Self;
|
||||
@@ -37,10 +37,6 @@ pub trait P384KeyPair<Rng: RngCore + CryptoRng> {
|
||||
|
||||
/// Perform ECDH key agreement, writing the raw (un-hashed!) ECDH secret to `ecdh_out`.
|
||||
///
|
||||
/// **CRITICAL**: This function must return `false` if key agreement between this private key and
|
||||
/// the input `public_key` key would result in an invalid, non-standard or predictable ECDH secret.
|
||||
/// Please refer to the NIST spec for P-384 ECDH key agreement, or better yet use a peer reviewed
|
||||
/// library that has already implemented this correctly.
|
||||
#[must_use]
|
||||
fn agree(&self, public_key: &Self::PublicKey, ecdh_out: &mut [u8; P384_ECDH_SHARED_SECRET_SIZE]) -> bool;
|
||||
/// If there is any possibility of this function failing, panic instead of returning.
|
||||
fn agree(&self, public_key: &Self::PublicKey, ecdh_out: &mut [u8; P384_ECDH_SHARED_SECRET_SIZE]);
|
||||
}
|
||||
|
||||
@@ -27,13 +27,12 @@ impl<Rng: RngCore + CryptoRng> P384KeyPair<Rng> for CrateP384KeyPair {
|
||||
CompressedPoint::from(self.public_key()).as_slice().try_into().unwrap()
|
||||
}
|
||||
|
||||
fn agree(&self, public_key: &Self::PublicKey, output: &mut [u8; P384_ECDH_SHARED_SECRET_SIZE]) -> bool {
|
||||
fn agree(&self, public_key: &Self::PublicKey, output: &mut [u8; P384_ECDH_SHARED_SECRET_SIZE]) {
|
||||
*output = self
|
||||
.diffie_hellman(public_key)
|
||||
.raw_secret_bytes()
|
||||
.as_slice()
|
||||
.try_into()
|
||||
.unwrap();
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,9 +9,6 @@ use crate::zeta::Session;
|
||||
/// Depending on the error type trying again may not work.
|
||||
#[derive(Debug)]
|
||||
pub enum OpenError {
|
||||
/// An invalid parameter was supplied to the function.
|
||||
InvalidPublicKey,
|
||||
|
||||
/// The given identity string was larger than `IDENTITY_MAX_SIZE`, a.k.a. 4096 bytes.
|
||||
IdentityTooLarge,
|
||||
|
||||
@@ -243,7 +240,6 @@ pub enum SessionEvent {
|
||||
impl Display for OpenError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
OpenError::InvalidPublicKey => f.write_str("invalid public key"),
|
||||
OpenError::IdentityTooLarge => f.write_str("identity too large"),
|
||||
OpenError::StorageError(e) => e.fmt(f),
|
||||
}
|
||||
|
||||
+45
-90
@@ -180,30 +180,15 @@ impl<Crypto: CryptoLayer> SymmetricState<Crypto> {
|
||||
*i = j;
|
||||
Crypto::PublicKey::from_bytes((pub_key).try_into().unwrap())
|
||||
}
|
||||
#[must_use]
|
||||
fn mix_dh(&mut self, hmac: &mut Crypto::Hmac, secret: &Crypto::KeyPair, remote: &Crypto::PublicKey) -> Option<()> {
|
||||
fn mix_dh(&mut self, hmac: &mut Crypto::Hmac, secret: &Crypto::KeyPair, remote: &Crypto::PublicKey) {
|
||||
let mut ecdh_secret = Zeroizing::new([0u8; P384_ECDH_SHARED_SECRET_SIZE]);
|
||||
if secret.agree(&remote, &mut ecdh_secret) {
|
||||
self.mix_key(hmac, ecdh_secret.as_ref());
|
||||
Some(())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
secret.agree(&remote, &mut ecdh_secret);
|
||||
self.mix_key(hmac, ecdh_secret.as_ref());
|
||||
}
|
||||
#[must_use]
|
||||
fn mix_dh_no_init(
|
||||
&mut self,
|
||||
hmac: &mut Crypto::Hmac,
|
||||
secret: &Crypto::KeyPair,
|
||||
remote: &Crypto::PublicKey,
|
||||
) -> Option<()> {
|
||||
fn mix_dh_no_init(&mut self, hmac: &mut Crypto::Hmac, secret: &Crypto::KeyPair, remote: &Crypto::PublicKey) {
|
||||
let mut ecdh_secret = Zeroizing::new([0u8; P384_ECDH_SHARED_SECRET_SIZE]);
|
||||
if secret.agree(&remote, &mut ecdh_secret) {
|
||||
self.mix_key_no_init(hmac, ecdh_secret.as_ref());
|
||||
Some(())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
secret.agree(&remote, &mut ecdh_secret);
|
||||
self.mix_key_no_init(hmac, ecdh_secret.as_ref());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -299,7 +284,7 @@ fn create_a1_state<Crypto: CryptoLayer>(
|
||||
ratchet_state1: &RatchetState,
|
||||
ratchet_state2: Option<&RatchetState>,
|
||||
identity: &[u8],
|
||||
) -> Option<Box<StateA1<Crypto>>> {
|
||||
) -> Box<StateA1<Crypto>> {
|
||||
// <- s
|
||||
// ...
|
||||
// -> e, es, e1
|
||||
@@ -314,7 +299,7 @@ fn create_a1_state<Crypto: CryptoLayer>(
|
||||
// Process message pattern 1 e token.
|
||||
let e_secret = noise.write_e_no_init(hash, hmac, rng, &mut x1);
|
||||
// Process message pattern 1 es token.
|
||||
noise.mix_dh(hmac, &e_secret, s_remote)?;
|
||||
noise.mix_dh(hmac, &e_secret, s_remote);
|
||||
// Process message pattern 1 e1 token.
|
||||
let i = x1.len();
|
||||
let (e1_secret, e1_public) = Crypto::Kem::generate(rng.lock().unwrap().deref_mut());
|
||||
@@ -340,7 +325,7 @@ fn create_a1_state<Crypto: CryptoLayer>(
|
||||
set_header(&mut x1, 0, &to_nonce(PACKET_TYPE_HANDSHAKE_HELLO, c));
|
||||
|
||||
let identity = identity.try_into().unwrap();
|
||||
Some(Box::new(StateA1 { noise, e_secret, e1_secret, identity, x1 }))
|
||||
Box::new(StateA1 { noise, e_secret, e1_secret, identity, x1 })
|
||||
}
|
||||
/// Corresponds to Transition Algorithm 1 found in Section 4.3.
|
||||
pub(crate) fn trans_to_a1<Crypto: CryptoLayer, App: ApplicationLayer<Crypto>>(
|
||||
@@ -371,13 +356,10 @@ pub(crate) fn trans_to_a1<Crypto: CryptoLayer, App: ApplicationLayer<Crypto>>(
|
||||
&state1,
|
||||
state2.as_ref(),
|
||||
identity,
|
||||
)
|
||||
.ok_or(OpenError::InvalidPublicKey)?;
|
||||
);
|
||||
|
||||
let mut noise_kk_ss = Zeroizing::new([0u8; P384_ECDH_SHARED_SECRET_SIZE]);
|
||||
if !ctx.s_secret.agree(&s_remote, &mut noise_kk_ss) {
|
||||
return Err(OpenError::InvalidPublicKey);
|
||||
}
|
||||
ctx.s_secret.agree(&s_remote, &mut noise_kk_ss);
|
||||
|
||||
let mut hk_recv = Zeroizing::new([0u8; HASHLEN]);
|
||||
let mut hk_send = Zeroizing::new([0u8; HASHLEN]);
|
||||
@@ -478,9 +460,7 @@ pub(crate) fn received_x1_trans<Crypto: CryptoLayer, App: ApplicationLayer<Crypt
|
||||
.read_e_no_init(hash, hmac, &mut i, &x1)
|
||||
.ok_or(fault!(FailedAuth, true))?;
|
||||
// Process message pattern 1 es token.
|
||||
noise
|
||||
.mix_dh(hmac, &ctx.s_secret, &e_remote)
|
||||
.ok_or(fault!(FailedAuth, true))?;
|
||||
noise.mix_dh(hmac, &ctx.s_secret, &e_remote);
|
||||
// Process message pattern 1 e1 token.
|
||||
let j = i + KYBER_PUBLIC_KEY_SIZE;
|
||||
let k = j + AES_GCM_TAG_SIZE;
|
||||
@@ -529,9 +509,7 @@ pub(crate) fn received_x1_trans<Crypto: CryptoLayer, App: ApplicationLayer<Crypt
|
||||
// Process message pattern 2 e token.
|
||||
let e_secret = noise.write_e_no_init(hash, hmac, &ctx.rng, &mut x2);
|
||||
// Process message pattern 2 ee token.
|
||||
noise
|
||||
.mix_dh(hmac, &e_secret, &e_remote)
|
||||
.ok_or(fault!(FailedAuth, true))?;
|
||||
noise.mix_dh(hmac, &e_secret, &e_remote);
|
||||
// Process message pattern 2 ekem1 token.
|
||||
{
|
||||
let i = x2.len();
|
||||
@@ -637,9 +615,7 @@ pub(crate) fn received_x2_trans<Crypto: CryptoLayer, App: ApplicationLayer<Crypt
|
||||
.read_e_no_init(hash, hmac, &mut i, &x2)
|
||||
.ok_or(fault!(FailedAuth, true))?;
|
||||
// Process message pattern 2 ee token.
|
||||
noise
|
||||
.mix_dh(hmac, &a1.e_secret, &e_remote)
|
||||
.ok_or(fault!(FailedAuth, true))?;
|
||||
noise.mix_dh(hmac, &a1.e_secret, &e_remote);
|
||||
// Process message pattern 2 ekem1 token.
|
||||
let j = i + KYBER_CIPHERTEXT_SIZE;
|
||||
let k = j + AES_GCM_TAG_SIZE;
|
||||
@@ -710,9 +686,7 @@ pub(crate) fn received_x2_trans<Crypto: CryptoLayer, App: ApplicationLayer<Crypt
|
||||
let tag = noise.encrypt_and_hash_in_place(hash, to_nonce(PACKET_TYPE_HANDSHAKE_COMPLETION, 1), &mut x3[i..]);
|
||||
x3.extend(tag);
|
||||
// Process message pattern 3 se token.
|
||||
noise
|
||||
.mix_dh(hmac, &ctx.s_secret, &e_remote)
|
||||
.ok_or(fault!(FailedAuth, true))?;
|
||||
noise.mix_dh(hmac, &ctx.s_secret, &e_remote);
|
||||
// Process message pattern 3 payload.
|
||||
let i = x3.len();
|
||||
x3.try_extend_from_slice(&a1.identity).unwrap();
|
||||
@@ -848,9 +822,7 @@ pub(crate) fn received_x3_trans<Crypto: CryptoLayer, App: ApplicationLayer<Crypt
|
||||
let s_remote = Crypto::PublicKey::from_bytes((&x3[i..j]).try_into().unwrap()).ok_or(fault!(FailedAuth, true))?;
|
||||
i = k;
|
||||
// Process message pattern 3 se token.
|
||||
noise
|
||||
.mix_dh(hmac, &zeta.e_secret, &s_remote)
|
||||
.ok_or(fault!(FailedAuth, true))?;
|
||||
noise.mix_dh(hmac, &zeta.e_secret, &s_remote);
|
||||
// Process message pattern 3 payload.
|
||||
let k = x3.len();
|
||||
let j = k - AES_GCM_TAG_SIZE;
|
||||
@@ -900,9 +872,7 @@ pub(crate) fn received_x3_trans<Crypto: CryptoLayer, App: ApplicationLayer<Crypt
|
||||
}
|
||||
|
||||
let mut noise_kk_ss = Zeroizing::new([0u8; P384_ECDH_SHARED_SECRET_SIZE]);
|
||||
if !ctx.s_secret.agree(&s_remote, &mut noise_kk_ss) {
|
||||
return Err(fault!(FailedAuth, true));
|
||||
}
|
||||
ctx.s_secret.agree(&s_remote, &mut noise_kk_ss);
|
||||
|
||||
let new_ratchet_state = create_ratchet_state(hmac, &mut noise, zeta.ratchet_state.chain_len);
|
||||
let mut nk_recv = Zeroizing::new([0u8; HASHLEN]);
|
||||
@@ -1194,7 +1164,7 @@ fn timeout_trans<Crypto: CryptoLayer, App: ApplicationLayer<Crypto>>(
|
||||
|
||||
let hash = &mut Crypto::Hash::new();
|
||||
let hmac = &mut Crypto::Hmac::new();
|
||||
if let Some(a1) = create_a1_state(
|
||||
let a1 = create_a1_state(
|
||||
hash,
|
||||
hmac,
|
||||
&ctx.rng,
|
||||
@@ -1203,32 +1173,29 @@ fn timeout_trans<Crypto: CryptoLayer, App: ApplicationLayer<Crypto>>(
|
||||
&state.ratchet_state1,
|
||||
state.ratchet_state2.as_ref(),
|
||||
identity,
|
||||
) {
|
||||
let mut hk_recv = Zeroizing::new([0u8; HASHLEN]);
|
||||
let mut hk_send = Zeroizing::new([0u8; HASHLEN]);
|
||||
a1.noise.get_ask(hmac, LABEL_HEADER_KEY, &mut hk_recv, &mut hk_send);
|
||||
let mut x1 = a1.x1.clone();
|
||||
);
|
||||
let mut hk_recv = Zeroizing::new([0u8; HASHLEN]);
|
||||
let mut hk_send = Zeroizing::new([0u8; HASHLEN]);
|
||||
a1.noise.get_ask(hmac, LABEL_HEADER_KEY, &mut hk_recv, &mut hk_send);
|
||||
let mut x1 = a1.x1.clone();
|
||||
|
||||
drop(state);
|
||||
let resend_timer = {
|
||||
let mut state = session.state.write().unwrap();
|
||||
state.hk_recv.reset((&hk_recv[..AES_256_KEY_SIZE]).try_into().unwrap());
|
||||
state.hk_send.reset((&hk_send[..AES_256_KEY_SIZE]).try_into().unwrap());
|
||||
*state.key_mut(true) = DuplexKey::default();
|
||||
state.key_mut(true).recv.kid = Some(new_kid_recv);
|
||||
let resend_timer = current_time + Crypto::SETTINGS.resend_time as i64;
|
||||
state.resend_timer = AtomicI64::new(resend_timer);
|
||||
state.timeout_timer = current_time + Crypto::SETTINGS.initial_offer_timeout as i64;
|
||||
state.beta = ZetaAutomata::A1(a1);
|
||||
resend_timer
|
||||
};
|
||||
drop(kex_lock);
|
||||
drop(state);
|
||||
let resend_timer = {
|
||||
let mut state = session.state.write().unwrap();
|
||||
state.hk_recv.reset((&hk_recv[..AES_256_KEY_SIZE]).try_into().unwrap());
|
||||
state.hk_send.reset((&hk_send[..AES_256_KEY_SIZE]).try_into().unwrap());
|
||||
*state.key_mut(true) = DuplexKey::default();
|
||||
state.key_mut(true).recv.kid = Some(new_kid_recv);
|
||||
let resend_timer = current_time + Crypto::SETTINGS.resend_time as i64;
|
||||
state.resend_timer = AtomicI64::new(resend_timer);
|
||||
state.timeout_timer = current_time + Crypto::SETTINGS.initial_offer_timeout as i64;
|
||||
state.beta = ZetaAutomata::A1(a1);
|
||||
resend_timer
|
||||
};
|
||||
drop(kex_lock);
|
||||
|
||||
send(&mut x1, None);
|
||||
Some(resend_timer)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
send(&mut x1, None);
|
||||
Some(resend_timer)
|
||||
}
|
||||
ZetaAutomata::S2 => {
|
||||
// Corresponds to Transition Algorithm 6 found in Section 4.3.
|
||||
@@ -1251,9 +1218,7 @@ fn timeout_trans<Crypto: CryptoLayer, App: ApplicationLayer<Crypto>>(
|
||||
// Process message pattern 1 e token.
|
||||
let e_secret = noise.write_e_no_init(hash, hmac, &ctx.rng, &mut k1);
|
||||
// Process message pattern 1 es token.
|
||||
if noise.mix_dh_no_init(hmac, &e_secret, &session.s_remote).is_none() {
|
||||
return None;
|
||||
}
|
||||
noise.mix_dh_no_init(hmac, &e_secret, &session.s_remote);
|
||||
// Process message pattern 1 ss token.
|
||||
noise.mix_key(hmac, session.noise_kk_ss.as_ref());
|
||||
// Process message pattern 1 payload.
|
||||
@@ -1410,9 +1375,7 @@ pub(crate) fn received_k1_trans<Crypto: CryptoLayer, App: ApplicationLayer<Crypt
|
||||
.read_e_no_init(hash, hmac, &mut i, &k1)
|
||||
.ok_or(fault!(FailedAuth, true))?;
|
||||
// Process message pattern 1 es token.
|
||||
noise
|
||||
.mix_dh_no_init(hmac, &ctx.s_secret, &e_remote)
|
||||
.ok_or(fault!(FailedAuth, true))?;
|
||||
noise.mix_dh_no_init(hmac, &ctx.s_secret, &e_remote);
|
||||
// Process message pattern 1 ss token.
|
||||
noise.mix_key(hmac, session.noise_kk_ss.as_ref());
|
||||
// Process message pattern 1 payload.
|
||||
@@ -1430,13 +1393,9 @@ pub(crate) fn received_k1_trans<Crypto: CryptoLayer, App: ApplicationLayer<Crypt
|
||||
// Process message pattern 2 e token.
|
||||
let e_secret = noise.write_e_no_init(hash, hmac, &ctx.rng, &mut k2);
|
||||
// Process message pattern 2 ee token.
|
||||
noise
|
||||
.mix_dh_no_init(hmac, &e_secret, &e_remote)
|
||||
.ok_or(fault!(FailedAuth, true))?;
|
||||
noise.mix_dh_no_init(hmac, &e_secret, &e_remote);
|
||||
// Process message pattern 2 se token.
|
||||
noise
|
||||
.mix_dh(hmac, &ctx.s_secret, &e_remote)
|
||||
.ok_or(fault!(FailedAuth, true))?;
|
||||
noise.mix_dh(hmac, &ctx.s_secret, &e_remote);
|
||||
// Process message pattern 2 payload.
|
||||
let i = k2.len();
|
||||
let new_kid_recv = remap(ctx, session, &state);
|
||||
@@ -1552,13 +1511,9 @@ pub(crate) fn received_k2_trans<Crypto: CryptoLayer, App: ApplicationLayer<Crypt
|
||||
.read_e_no_init(hash, hmac, &mut i, &k2)
|
||||
.ok_or(fault!(FailedAuth, true))?;
|
||||
// Process message pattern 2 ee token.
|
||||
noise
|
||||
.mix_dh_no_init(hmac, e_secret, &e_remote)
|
||||
.ok_or(fault!(FailedAuth, true))?;
|
||||
noise.mix_dh_no_init(hmac, e_secret, &e_remote);
|
||||
// Process message pattern 2 se token.
|
||||
noise
|
||||
.mix_dh(hmac, e_secret, &session.s_remote)
|
||||
.ok_or(fault!(FailedAuth, true))?;
|
||||
noise.mix_dh(hmac, e_secret, &session.s_remote);
|
||||
// Process message pattern 2 payload.
|
||||
let j = i + KID_SIZE;
|
||||
let k = j + AES_GCM_TAG_SIZE;
|
||||
|
||||
@@ -41,5 +41,5 @@ pub trait P384KeyPair<Rng: RngCore + CryptoRng> {
|
||||
/// the input `public_key` key would result in an invalid, non-standard or predictable ECDH secret.
|
||||
/// Please refer to the NIST spec for P-384 ECDH key agreement, or better yet use a peer reviewed
|
||||
/// library that has already implemented this correctly.
|
||||
fn agree(&self, public_key: &Self::PublicKey) -> Option<[u8; P384_ECDH_SHARED_SECRET_SIZE]>;
|
||||
fn agree(&self, public_key: &Self::PublicKey) -> [u8; P384_ECDH_SHARED_SECRET_SIZE];
|
||||
}
|
||||
|
||||
@@ -29,13 +29,11 @@ impl<Rng: RngCore + CryptoRng> P384KeyPair<Rng> for P384CrateKeyPair {
|
||||
CompressedPoint::from(self.public_key()).as_slice().try_into().unwrap()
|
||||
}
|
||||
|
||||
fn agree(&self, public_key: &Self::PublicKey) -> Option<[u8; P384_ECDH_SHARED_SECRET_SIZE]> {
|
||||
Some(
|
||||
self.diffie_hellman(public_key)
|
||||
.raw_secret_bytes()
|
||||
.as_slice()
|
||||
.try_into()
|
||||
.unwrap(),
|
||||
)
|
||||
fn agree(&self, public_key: &Self::PublicKey) -> [u8; P384_ECDH_SHARED_SECRET_SIZE] {
|
||||
self.diffie_hellman(public_key)
|
||||
.raw_secret_bytes()
|
||||
.as_slice()
|
||||
.try_into()
|
||||
.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,9 +9,6 @@ use crate::zeta::Session;
|
||||
/// Depending on the error type trying again may not work.
|
||||
#[derive(Debug)]
|
||||
pub enum OpenError {
|
||||
/// An invalid parameter was supplied to the function.
|
||||
InvalidPublicKey,
|
||||
|
||||
/// The given identity string was larger than `IDENTITY_MAX_SIZE`, a.k.a. 4096 bytes.
|
||||
IdentityTooLarge,
|
||||
|
||||
@@ -243,7 +240,6 @@ pub enum SessionEvent {
|
||||
impl Display for OpenError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
OpenError::InvalidPublicKey => f.write_str("invalid public key"),
|
||||
OpenError::IdentityTooLarge => f.write_str("identity too large"),
|
||||
OpenError::StorageError(e) => e.fmt(f),
|
||||
}
|
||||
|
||||
+33
-69
@@ -123,13 +123,9 @@ impl<Crypto: CryptoLayer> SymmetricState<Crypto> {
|
||||
*i = j;
|
||||
Crypto::PublicKey::from_bytes((pub_key).try_into().unwrap())
|
||||
}
|
||||
fn mix_dh(&mut self, secret: &Crypto::KeyPair, remote: &Crypto::PublicKey) -> Option<()> {
|
||||
if let Some(ecdh) = secret.agree(&remote).map(Zeroizing::new) {
|
||||
self.mix_key(ecdh.as_ref());
|
||||
Some(())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
fn mix_dh(&mut self, secret: &Crypto::KeyPair, remote: &Crypto::PublicKey) {
|
||||
let ecdh = Zeroizing::new(secret.agree(&remote));
|
||||
self.mix_key(ecdh.as_ref());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -247,7 +243,7 @@ fn create_a1_state<App: ApplicationLayer>(
|
||||
ratchet_state1: &RatchetState,
|
||||
ratchet_state2: Option<&RatchetState>,
|
||||
identity: Vec<u8>,
|
||||
) -> Option<StateA1<App::Crypto>> {
|
||||
) -> StateA1<App::Crypto> {
|
||||
// <- s
|
||||
// ...
|
||||
// -> e, es, e1
|
||||
@@ -261,7 +257,7 @@ fn create_a1_state<App: ApplicationLayer>(
|
||||
// Process message pattern 1 e token.
|
||||
let e_secret = noise.write_e(rng, &mut x1);
|
||||
// Process message pattern 1 es token.
|
||||
noise.mix_dh(&e_secret, s_remote)?;
|
||||
noise.mix_dh(&e_secret, s_remote);
|
||||
// Process message pattern 1 e1 token.
|
||||
let i = x1.len();
|
||||
let (e1_secret, e1_public) = <App::Crypto as CryptoLayer>::Kem::generate(rng.borrow_mut().deref_mut());
|
||||
@@ -280,13 +276,13 @@ fn create_a1_state<App: ApplicationLayer>(
|
||||
let c = u64::from_be_bytes(x1[x1.len() - 8..].try_into().unwrap());
|
||||
|
||||
x1.extend(&gen_null_response(rng.borrow_mut().deref_mut()));
|
||||
Some(StateA1 {
|
||||
StateA1 {
|
||||
noise,
|
||||
e_secret,
|
||||
e1_secret,
|
||||
identity,
|
||||
packet: Packet(0, to_nonce(PACKET_TYPE_HANDSHAKE_HELLO, c), x1),
|
||||
})
|
||||
}
|
||||
}
|
||||
/// Corresponds to Transition Algorithm 1 found in Section 4.3.
|
||||
pub(crate) fn trans_to_a1<App: ApplicationLayer>(
|
||||
@@ -305,8 +301,7 @@ pub(crate) fn trans_to_a1<App: ApplicationLayer>(
|
||||
let mut session_map = ctx.session_map.borrow_mut();
|
||||
let kid_recv = gen_kid(session_map.deref(), ctx.rng.borrow_mut().deref_mut());
|
||||
|
||||
let a1 = create_a1_state::<App>(&ctx.rng, &s_remote, kid_recv, &state1, state2.as_ref(), identity)
|
||||
.ok_or(OpenError::InvalidPublicKey)?;
|
||||
let a1 = create_a1_state::<App>(&ctx.rng, &s_remote, kid_recv, &state1, state2.as_ref(), identity);
|
||||
let packet = a1.packet.clone();
|
||||
|
||||
let (hk_recv, hk_send) = a1.noise.get_ask(LABEL_HEADER_KEY);
|
||||
@@ -388,9 +383,7 @@ pub(crate) fn received_x1_trans<App: ApplicationLayer>(
|
||||
// Process message pattern 1 e token.
|
||||
let e_remote = noise.read_e(&mut i, &x1).ok_or(byzantine_fault!(FailedAuth, true))?;
|
||||
// Process message pattern 1 es token.
|
||||
noise
|
||||
.mix_dh(&ctx.s_secret, &e_remote)
|
||||
.ok_or(byzantine_fault!(FailedAuth, true))?;
|
||||
noise.mix_dh(&ctx.s_secret, &e_remote);
|
||||
// Process message pattern 1 e1 token.
|
||||
let j = i + KYBER_PUBLIC_KEY_SIZE;
|
||||
let k = j + AES_GCM_TAG_SIZE;
|
||||
@@ -436,9 +429,7 @@ pub(crate) fn received_x1_trans<App: ApplicationLayer>(
|
||||
// Process message pattern 2 e token.
|
||||
let e_secret = noise.write_e(&ctx.rng, &mut x2);
|
||||
// Process message pattern 2 ee token.
|
||||
noise
|
||||
.mix_dh(&e_secret, &e_remote)
|
||||
.ok_or(byzantine_fault!(FailedAuth, true))?;
|
||||
noise.mix_dh(&e_secret, &e_remote);
|
||||
// Process message pattern 2 ekem1 token.
|
||||
let i = x2.len();
|
||||
let (ekem1, ekem1_secret) = <App::Crypto as CryptoLayer>::Kem::encapsulate(
|
||||
@@ -519,9 +510,7 @@ pub(crate) fn received_x2_trans<App: ApplicationLayer>(
|
||||
// Process message pattern 2 e token.
|
||||
let e_remote = noise.read_e(&mut i, &x2).ok_or(byzantine_fault!(FailedAuth, true))?;
|
||||
// Process message pattern 2 ee token.
|
||||
noise
|
||||
.mix_dh(e_secret, &e_remote)
|
||||
.ok_or(byzantine_fault!(FailedAuth, true))?;
|
||||
noise.mix_dh(e_secret, &e_remote);
|
||||
// Process message pattern 2 ekem1 token.
|
||||
let j = i + KYBER_CIPHERTEXT_SIZE;
|
||||
let k = j + AES_GCM_TAG_SIZE;
|
||||
@@ -587,9 +576,7 @@ pub(crate) fn received_x2_trans<App: ApplicationLayer>(
|
||||
x3.extend(&ctx.s_secret.public_key_bytes());
|
||||
noise.encrypt_and_hash_in_place(to_nonce(PACKET_TYPE_HANDSHAKE_COMPLETION, 1), i, &mut x3);
|
||||
// Process message pattern 3 se token.
|
||||
noise
|
||||
.mix_dh(&ctx.s_secret, &e_remote)
|
||||
.ok_or(byzantine_fault!(FailedAuth, true))?;
|
||||
noise.mix_dh(&ctx.s_secret, &e_remote);
|
||||
// Process message pattern 3 payload.
|
||||
let i = x3.len();
|
||||
x3.extend(identity);
|
||||
@@ -704,9 +691,7 @@ pub(crate) fn received_x3_trans<App: ApplicationLayer>(
|
||||
.ok_or(byzantine_fault!(FailedAuth, true))?;
|
||||
i = k;
|
||||
// Process message pattern 3 se token.
|
||||
noise
|
||||
.mix_dh(&zeta.e_secret, &s_remote)
|
||||
.ok_or(byzantine_fault!(FailedAuth, true))?;
|
||||
noise.mix_dh(&zeta.e_secret, &s_remote);
|
||||
// Process message pattern 3 payload.
|
||||
let k = x3.len();
|
||||
let j = k - AES_GCM_TAG_SIZE;
|
||||
@@ -1048,29 +1033,26 @@ fn timeout_trans<App: ApplicationLayer>(
|
||||
}
|
||||
let new_kid_recv = remap(session, &zeta, &ctx.rng, &ctx.session_map);
|
||||
|
||||
if let Some(a1) = create_a1_state::<App>(
|
||||
let a1 = create_a1_state::<App>(
|
||||
&ctx.rng,
|
||||
&zeta.s_remote,
|
||||
new_kid_recv,
|
||||
&zeta.ratchet_state1,
|
||||
zeta.ratchet_state2.as_ref(),
|
||||
identity.clone(),
|
||||
) {
|
||||
let (hk_recv, hk_send) = a1.noise.get_ask(LABEL_HEADER_KEY);
|
||||
let packet = a1.packet.clone();
|
||||
);
|
||||
let (hk_recv, hk_send) = a1.noise.get_ask(LABEL_HEADER_KEY);
|
||||
let packet = a1.packet.clone();
|
||||
|
||||
zeta.hk_send = hk_send;
|
||||
*zeta.key_mut(true) = DuplexKey::default();
|
||||
zeta.key_mut(true).recv.kid = Some(new_kid_recv);
|
||||
zeta.resend_timer = current_time + <App::Crypto as CryptoLayer>::SETTINGS.resend_time as i64;
|
||||
zeta.timeout_timer = current_time + <App::Crypto as CryptoLayer>::SETTINGS.initial_offer_timeout as i64;
|
||||
zeta.beta = ZetaAutomata::A1(a1);
|
||||
zeta.defrag = DefragBuffer::new(Some(hk_recv));
|
||||
zeta.hk_send = hk_send;
|
||||
*zeta.key_mut(true) = DuplexKey::default();
|
||||
zeta.key_mut(true).recv.kid = Some(new_kid_recv);
|
||||
zeta.resend_timer = current_time + <App::Crypto as CryptoLayer>::SETTINGS.resend_time as i64;
|
||||
zeta.timeout_timer = current_time + <App::Crypto as CryptoLayer>::SETTINGS.initial_offer_timeout as i64;
|
||||
zeta.beta = ZetaAutomata::A1(a1);
|
||||
zeta.defrag = DefragBuffer::new(Some(hk_recv));
|
||||
|
||||
send(&packet, None);
|
||||
} else {
|
||||
zeta.expire();
|
||||
}
|
||||
send(&packet, None);
|
||||
}
|
||||
ZetaAutomata::S2 => {
|
||||
// Corresponds to Transition Algorithm 6 found in Section 4.3.
|
||||
@@ -1090,15 +1072,9 @@ fn timeout_trans<App: ApplicationLayer>(
|
||||
// Process message pattern 1 e token.
|
||||
let e_secret = noise.write_e(&ctx.rng, &mut k1);
|
||||
// Process message pattern 1 es token.
|
||||
if noise.mix_dh(&e_secret, &zeta.s_remote).is_none() {
|
||||
zeta.expire();
|
||||
return;
|
||||
}
|
||||
noise.mix_dh(&e_secret, &zeta.s_remote);
|
||||
// Process message pattern 1 ss token.
|
||||
if noise.mix_dh(&ctx.s_secret, &zeta.s_remote).is_none() {
|
||||
zeta.expire();
|
||||
return;
|
||||
}
|
||||
noise.mix_dh(&ctx.s_secret, &zeta.s_remote);
|
||||
// Process message pattern 1 payload.
|
||||
let i = k1.len();
|
||||
k1.extend(&new_kid_recv.get().to_be_bytes());
|
||||
@@ -1189,13 +1165,9 @@ pub(crate) fn received_k1_trans<App: ApplicationLayer>(
|
||||
// Process message pattern 1 e token.
|
||||
let e_remote = noise.read_e(&mut i, &k1).ok_or(byzantine_fault!(FailedAuth, true))?;
|
||||
// Process message pattern 1 es token.
|
||||
noise
|
||||
.mix_dh(s_secret, &e_remote)
|
||||
.ok_or(byzantine_fault!(FailedAuth, true))?;
|
||||
noise.mix_dh(s_secret, &e_remote);
|
||||
// Process message pattern 1 ss token.
|
||||
noise
|
||||
.mix_dh(s_secret, &zeta.s_remote)
|
||||
.ok_or(byzantine_fault!(FailedAuth, true))?;
|
||||
noise.mix_dh(s_secret, &zeta.s_remote);
|
||||
// Process message pattern 1 payload.
|
||||
let j = i + KID_SIZE;
|
||||
let k = j + AES_GCM_TAG_SIZE;
|
||||
@@ -1210,13 +1182,9 @@ pub(crate) fn received_k1_trans<App: ApplicationLayer>(
|
||||
// Process message pattern 2 e token.
|
||||
let e_secret = noise.write_e(rng, &mut k2);
|
||||
// Process message pattern 2 ee token.
|
||||
noise
|
||||
.mix_dh(&e_secret, &e_remote)
|
||||
.ok_or(byzantine_fault!(FailedAuth, true))?;
|
||||
noise.mix_dh(&e_secret, &e_remote);
|
||||
// Process message pattern 2 se token.
|
||||
noise
|
||||
.mix_dh(&s_secret, &e_remote)
|
||||
.ok_or(byzantine_fault!(FailedAuth, true))?;
|
||||
noise.mix_dh(&s_secret, &e_remote);
|
||||
// Process message pattern 2 payload.
|
||||
let i = k2.len();
|
||||
let new_kid_recv = remap(session, &zeta, rng, session_map);
|
||||
@@ -1310,13 +1278,9 @@ pub(crate) fn received_k2_trans<App: ApplicationLayer>(
|
||||
// Process message pattern 2 e token.
|
||||
let e_remote = noise.read_e(&mut i, &k2).ok_or(byzantine_fault!(FailedAuth, true))?;
|
||||
// Process message pattern 2 ee token.
|
||||
noise
|
||||
.mix_dh(e_secret, &e_remote)
|
||||
.ok_or(byzantine_fault!(FailedAuth, true))?;
|
||||
noise.mix_dh(e_secret, &e_remote);
|
||||
// Process message pattern 2 se token.
|
||||
noise
|
||||
.mix_dh(e_secret, &zeta.s_remote)
|
||||
.ok_or(byzantine_fault!(FailedAuth, true))?;
|
||||
noise.mix_dh(e_secret, &zeta.s_remote);
|
||||
// Process message pattern 2 payload.
|
||||
let j = i + KID_SIZE;
|
||||
let k = j + AES_GCM_TAG_SIZE;
|
||||
|
||||
Reference in New Issue
Block a user