mirror of
https://github.com/zerotier/zssp.git
synced 2026-05-22 16:28:40 -07:00
cargo fmt
This commit is contained in:
+28
-5
@@ -21,7 +21,9 @@ use rand_core::OsRng;
|
||||
use rand_core::RngCore;
|
||||
use sha2::Sha512;
|
||||
|
||||
use zssp_proto::applicationlayer::{AcceptAction, ApplicationLayer, RatchetState, RatchetUpdate, Settings, RATCHET_SIZE};
|
||||
use zssp_proto::applicationlayer::{
|
||||
AcceptAction, ApplicationLayer, RatchetState, RatchetUpdate, Settings, RATCHET_SIZE,
|
||||
};
|
||||
use zssp_proto::crypto_impl::PqcKyberSecretKey;
|
||||
use zssp_proto::Session;
|
||||
|
||||
@@ -81,7 +83,10 @@ impl ApplicationLayer for &TestApplication {
|
||||
}
|
||||
}
|
||||
|
||||
fn restore_by_fingerprint(&self, ratchet_fingerprint: &[u8; RATCHET_SIZE]) -> Result<Option<RatchetState>, Self::StorageError> {
|
||||
fn restore_by_fingerprint(
|
||||
&self,
|
||||
ratchet_fingerprint: &[u8; RATCHET_SIZE],
|
||||
) -> Result<Option<RatchetState>, Self::StorageError> {
|
||||
let ratchets = self.ratchets.lock().unwrap();
|
||||
Ok(ratchets.rf_map.get(ratchet_fingerprint).cloned())
|
||||
}
|
||||
@@ -156,7 +161,14 @@ fn alice_main(
|
||||
up = false;
|
||||
alice_session = Some(
|
||||
context
|
||||
.open(alice_app, |b| alice_out.send(b).is_ok(), TEST_MTU, bob_pubkey.clone(), 0, Vec::new())
|
||||
.open(
|
||||
alice_app,
|
||||
|b| alice_out.send(b).is_ok(),
|
||||
TEST_MTU,
|
||||
bob_pubkey.clone(),
|
||||
0,
|
||||
Vec::new(),
|
||||
)
|
||||
.unwrap(),
|
||||
);
|
||||
println!("[alice] opening session");
|
||||
@@ -225,7 +237,8 @@ fn alice_main(
|
||||
}
|
||||
|
||||
if current_time >= next_service {
|
||||
next_service = current_time + context.service(alice_app, |_| Some((|b| alice_out.send(b).is_ok(), TEST_MTU)));
|
||||
next_service =
|
||||
current_time + context.service(alice_app, |_| Some((|b| alice_out.send(b).is_ok(), TEST_MTU)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -345,7 +358,17 @@ fn core(time: u64, packet_success_rate: u32) {
|
||||
)
|
||||
});
|
||||
}
|
||||
ts.spawn(move || bob_main(run, packet_success_rate, &bob_app, bob_out, bob_in, alice_out, bob_keypair));
|
||||
ts.spawn(move || {
|
||||
bob_main(
|
||||
run,
|
||||
packet_success_rate,
|
||||
&bob_app,
|
||||
bob_out,
|
||||
bob_in,
|
||||
alice_out,
|
||||
bob_keypair,
|
||||
)
|
||||
});
|
||||
|
||||
thread::sleep(Duration::from_secs(time));
|
||||
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
max_width = 150
|
||||
max_width = 120
|
||||
edition = "2021"
|
||||
newline_style = "Unix"
|
||||
struct_lit_width = 60
|
||||
|
||||
@@ -189,7 +189,10 @@ pub trait ApplicationLayer: Sized {
|
||||
/// If `RatchetAction::DowngradeRatchet` is returned we will attempt to convince Alice to downgrade
|
||||
/// to the empty ratchet key, restarting the ratchet chain.
|
||||
/// If `RatchetAction::FailAuthentication` is returned Alice's connection will be silently dropped.
|
||||
fn restore_by_fingerprint(&self, ratchet_fingerprint: &[u8; RATCHET_SIZE]) -> Result<Option<RatchetState>, Self::StorageError>;
|
||||
fn restore_by_fingerprint(
|
||||
&self,
|
||||
ratchet_fingerprint: &[u8; RATCHET_SIZE],
|
||||
) -> Result<Option<RatchetState>, Self::StorageError>;
|
||||
/// Lookup the specific ratchet states based on the identity of the peer being communicated with.
|
||||
/// This function will be called whenever Alice attempts to open a session, or Bob attempts
|
||||
/// to verify Alice's identity.
|
||||
|
||||
+4
-1
@@ -58,7 +58,10 @@ impl ChallengeContext {
|
||||
return Ok(false);
|
||||
}
|
||||
let c = u64::from_be_bytes(response[..COUNTER_SIZE].try_into().unwrap());
|
||||
if self.check_window(c) && secure_eq(&response[COUNTER_SIZE..POW_START], &self.create_mac::<Hash>(c, addr)) && verify_pow::<Hash>(response) {
|
||||
if self.check_window(c)
|
||||
&& secure_eq(&response[COUNTER_SIZE..POW_START], &self.create_mac::<Hash>(c, addr))
|
||||
&& verify_pow::<Hash>(response)
|
||||
{
|
||||
self.update_window(c);
|
||||
Ok(true)
|
||||
} else {
|
||||
|
||||
+154
-85
@@ -149,43 +149,53 @@ impl<App: ApplicationLayer> Context<App> {
|
||||
if let Some(Some(session)) = session {
|
||||
// Process recv fragmentation layer.
|
||||
let mut zeta = session.0.lock().unwrap();
|
||||
let result = zeta.defrag.received_fragment::<App>(raw_fragment, app.time(), |n, frag_no, frag_count| {
|
||||
let (p, c) = from_nonce(n);
|
||||
if p != PACKET_TYPE_DATA {
|
||||
log!(app, ReceivedRawFragment(p, c, frag_no, frag_count));
|
||||
}
|
||||
if p == PACKET_TYPE_HANDSHAKE_RESPONSE {
|
||||
if !matches!(&zeta.beta, ZetaAutomata::A1(_)) {
|
||||
// A resent handshake response from Bob may have arrived out of order,
|
||||
// after we already received one.
|
||||
return Err(byzantine_fault!(OutOfSequence, false));
|
||||
}
|
||||
if c >= COUNTER_WINDOW_MAX_SKIP_AHEAD {
|
||||
return Err(byzantine_fault!(ExpiredCounter, true));
|
||||
}
|
||||
Ok(())
|
||||
} else if PACKET_TYPE_USES_COUNTER_RANGE.contains(&p) {
|
||||
if !zeta.check_counter_window(c) {
|
||||
// The counter window has finite memory and so will occasionally give
|
||||
// false positives on very out-of-order packets.
|
||||
return Err(byzantine_fault!(ExpiredCounter, false));
|
||||
}
|
||||
Ok(())
|
||||
} else if p == PACKET_TYPE_HANDSHAKE_COMPLETION {
|
||||
// The handshake completion packet could have been resent.
|
||||
return Err(byzantine_fault!(InvalidPacket, false));
|
||||
} else {
|
||||
return Err(byzantine_fault!(InvalidPacket, true));
|
||||
}
|
||||
})?;
|
||||
let result =
|
||||
zeta.defrag
|
||||
.received_fragment::<App>(raw_fragment, app.time(), |n, frag_no, frag_count| {
|
||||
let (p, c) = from_nonce(n);
|
||||
if p != PACKET_TYPE_DATA {
|
||||
log!(app, ReceivedRawFragment(p, c, frag_no, frag_count));
|
||||
}
|
||||
if p == PACKET_TYPE_HANDSHAKE_RESPONSE {
|
||||
if !matches!(&zeta.beta, ZetaAutomata::A1(_)) {
|
||||
// A resent handshake response from Bob may have arrived out of order,
|
||||
// after we already received one.
|
||||
return Err(byzantine_fault!(OutOfSequence, false));
|
||||
}
|
||||
if c >= COUNTER_WINDOW_MAX_SKIP_AHEAD {
|
||||
return Err(byzantine_fault!(ExpiredCounter, true));
|
||||
}
|
||||
Ok(())
|
||||
} else if PACKET_TYPE_USES_COUNTER_RANGE.contains(&p) {
|
||||
if !zeta.check_counter_window(c) {
|
||||
// The counter window has finite memory and so will occasionally give
|
||||
// false positives on very out-of-order packets.
|
||||
return Err(byzantine_fault!(ExpiredCounter, false));
|
||||
}
|
||||
Ok(())
|
||||
} else if p == PACKET_TYPE_HANDSHAKE_COMPLETION {
|
||||
// The handshake completion packet could have been resent.
|
||||
return Err(byzantine_fault!(InvalidPacket, false));
|
||||
} else {
|
||||
return Err(byzantine_fault!(InvalidPacket, true));
|
||||
}
|
||||
})?;
|
||||
if let Some((pn, mut assembled_packet)) = result {
|
||||
// Process recv zeta layer.
|
||||
let send_associated = |Packet(kid, nonce, payload): &Packet, hk: Option<&[u8; AES_256_KEY_SIZE]>| {
|
||||
if let Some((send_fragment, mut mtu)) = send_to(&session) {
|
||||
mtu = mtu.max(MIN_TRANSPORT_MTU);
|
||||
send_with_fragmentation::<App>(send_fragment, mtu, *kid, to_packet_nonce(&nonce), payload, hk);
|
||||
}
|
||||
};
|
||||
let send_associated =
|
||||
|Packet(kid, nonce, payload): &Packet, hk: Option<&[u8; AES_256_KEY_SIZE]>| {
|
||||
if let Some((send_fragment, mut mtu)) = send_to(&session) {
|
||||
mtu = mtu.max(MIN_TRANSPORT_MTU);
|
||||
send_with_fragmentation::<App>(
|
||||
send_fragment,
|
||||
mtu,
|
||||
*kid,
|
||||
to_packet_nonce(&nonce),
|
||||
payload,
|
||||
hk,
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
let (p, _) = from_nonce(&pn);
|
||||
let ret = match p {
|
||||
@@ -210,8 +220,15 @@ impl<App: ApplicationLayer> Context<App> {
|
||||
}
|
||||
PACKET_TYPE_KEY_CONFIRM => {
|
||||
log!(app, ReceivedRawKeyConfirm);
|
||||
let result =
|
||||
received_c1_trans(&mut zeta, &app, &ctx.rng, kid_recv, to_aes_nonce(&pn), assembled_packet, send_associated)?;
|
||||
let result = received_c1_trans(
|
||||
&mut zeta,
|
||||
&app,
|
||||
&ctx.rng,
|
||||
kid_recv,
|
||||
to_aes_nonce(&pn),
|
||||
assembled_packet,
|
||||
send_associated,
|
||||
)?;
|
||||
log!(app, KeyConfirmIsAuthSentAck(&session));
|
||||
if result {
|
||||
SessionEvent::Established
|
||||
@@ -221,7 +238,14 @@ impl<App: ApplicationLayer> Context<App> {
|
||||
}
|
||||
PACKET_TYPE_ACK => {
|
||||
log!(app, ReceivedRawAck);
|
||||
received_c2_trans(&mut zeta, &app, &ctx.rng, kid_recv, to_aes_nonce(&pn), assembled_packet)?;
|
||||
received_c2_trans(
|
||||
&mut zeta,
|
||||
&app,
|
||||
&ctx.rng,
|
||||
kid_recv,
|
||||
to_aes_nonce(&pn),
|
||||
assembled_packet,
|
||||
)?;
|
||||
log!(app, AckIsAuth(&session));
|
||||
SessionEvent::Control
|
||||
}
|
||||
@@ -244,7 +268,14 @@ impl<App: ApplicationLayer> Context<App> {
|
||||
}
|
||||
PACKET_TYPE_REKEY_COMPLETE => {
|
||||
log!(app, ReceivedRawK2);
|
||||
received_k2_trans(&mut zeta, &app, kid_recv, to_aes_nonce(&pn), assembled_packet, send_associated)?;
|
||||
received_k2_trans(
|
||||
&mut zeta,
|
||||
&app,
|
||||
kid_recv,
|
||||
to_aes_nonce(&pn),
|
||||
assembled_packet,
|
||||
send_associated,
|
||||
)?;
|
||||
log!(app, K2IsAuthSentKeyConfirm(&session));
|
||||
SessionEvent::Control
|
||||
}
|
||||
@@ -266,28 +297,37 @@ impl<App: ApplicationLayer> Context<App> {
|
||||
if let Entry::Occupied(mut entry) = b2_map.entry(kid_recv) {
|
||||
let zeta = entry.get_mut();
|
||||
// Process recv fragmentation layer.
|
||||
let result = zeta.defrag.received_fragment::<App>(raw_fragment, app.time(), |n, frag_no, frag_count| {
|
||||
let (p, c) = from_nonce(n);
|
||||
log!(app, ReceivedRawFragment(p, c, frag_no, frag_count));
|
||||
if p == PACKET_TYPE_HANDSHAKE_COMPLETION && c == 0 {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(byzantine_fault!(InvalidPacket, true))
|
||||
}
|
||||
})?;
|
||||
let result =
|
||||
zeta.defrag
|
||||
.received_fragment::<App>(raw_fragment, app.time(), |n, frag_no, frag_count| {
|
||||
let (p, c) = from_nonce(n);
|
||||
log!(app, ReceivedRawFragment(p, c, frag_no, frag_count));
|
||||
if p == PACKET_TYPE_HANDSHAKE_COMPLETION && c == 0 {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(byzantine_fault!(InvalidPacket, true))
|
||||
}
|
||||
})?;
|
||||
if let Some((_, assembled_packet)) = result {
|
||||
log!(app, ReceivedRawX3);
|
||||
let zeta = entry.remove();
|
||||
let session = received_x3_trans(zeta, &app, ctx, kid_recv, assembled_packet, |Packet(kid, nonce, payload), hk| {
|
||||
send_with_fragmentation::<App>(
|
||||
send_unassociated_reply,
|
||||
send_unassociated_mtu,
|
||||
*kid,
|
||||
to_packet_nonce(&nonce),
|
||||
payload,
|
||||
hk,
|
||||
);
|
||||
})?;
|
||||
let session = received_x3_trans(
|
||||
zeta,
|
||||
&app,
|
||||
ctx,
|
||||
kid_recv,
|
||||
assembled_packet,
|
||||
|Packet(kid, nonce, payload), hk| {
|
||||
send_with_fragmentation::<App>(
|
||||
send_unassociated_reply,
|
||||
send_unassociated_mtu,
|
||||
*kid,
|
||||
to_packet_nonce(&nonce),
|
||||
payload,
|
||||
hk,
|
||||
);
|
||||
},
|
||||
)?;
|
||||
log!(app, X3IsAuthSentKeyConfirm(&session));
|
||||
Ok(ReceiveOk::Session(session, SessionEvent::NewSession))
|
||||
} else {
|
||||
@@ -301,11 +341,10 @@ impl<App: ApplicationLayer> Context<App> {
|
||||
}
|
||||
} else {
|
||||
// Process recv fragmentation layer.
|
||||
let result = ctx
|
||||
.hello_defrag
|
||||
.lock()
|
||||
.unwrap()
|
||||
.received_fragment::<App>(raw_fragment, app.time(), |n, frag_no, frag_count| {
|
||||
let result = ctx.hello_defrag.lock().unwrap().received_fragment::<App>(
|
||||
raw_fragment,
|
||||
app.time(),
|
||||
|n, frag_no, frag_count| {
|
||||
let (p, c) = from_nonce(n);
|
||||
log!(app, ReceivedRawFragment(p, c, frag_no, frag_count));
|
||||
if p == PACKET_TYPE_HANDSHAKE_HELLO || p == PACKET_TYPE_CHALLENGE {
|
||||
@@ -313,18 +352,18 @@ impl<App: ApplicationLayer> Context<App> {
|
||||
} else {
|
||||
Err(byzantine_fault!(InvalidPacket, true))
|
||||
}
|
||||
})?;
|
||||
},
|
||||
)?;
|
||||
if let Some((n, mut assembled_packet)) = result {
|
||||
let (p, _) = from_nonce(&n);
|
||||
if p == PACKET_TYPE_HANDSHAKE_HELLO {
|
||||
log!(app, ReceivedRawX1);
|
||||
// Process recv challenge layer.
|
||||
let challenge_start = assembled_packet.len() - CHALLENGE_SIZE;
|
||||
let result = ctx
|
||||
.challenge
|
||||
.lock()
|
||||
.unwrap()
|
||||
.process_hello::<App::Hash>(remote_address, (&assembled_packet[challenge_start..]).try_into().unwrap());
|
||||
let result = ctx.challenge.lock().unwrap().process_hello::<App::Hash>(
|
||||
remote_address,
|
||||
(&assembled_packet[challenge_start..]).try_into().unwrap(),
|
||||
);
|
||||
if let Err(challenge) = result {
|
||||
log!(app, X1FailedChallengeSentNewChallenge);
|
||||
let mut challenge_packet = Vec::new();
|
||||
@@ -347,16 +386,22 @@ impl<App: ApplicationLayer> Context<App> {
|
||||
assembled_packet.truncate(challenge_start);
|
||||
|
||||
// Process recv zeta layer.
|
||||
received_x1_trans(&app, &ctx, to_aes_nonce(&n), assembled_packet, |Packet(kid, nonce, payload), hk| {
|
||||
send_with_fragmentation::<App>(
|
||||
send_unassociated_reply,
|
||||
send_unassociated_mtu,
|
||||
*kid,
|
||||
to_packet_nonce(&nonce),
|
||||
payload,
|
||||
Some(hk),
|
||||
);
|
||||
})?;
|
||||
received_x1_trans(
|
||||
&app,
|
||||
&ctx,
|
||||
to_aes_nonce(&n),
|
||||
assembled_packet,
|
||||
|Packet(kid, nonce, payload), hk| {
|
||||
send_with_fragmentation::<App>(
|
||||
send_unassociated_reply,
|
||||
send_unassociated_mtu,
|
||||
*kid,
|
||||
to_packet_nonce(&nonce),
|
||||
payload,
|
||||
Some(hk),
|
||||
);
|
||||
},
|
||||
)?;
|
||||
log!(app, X1IsAuthSentX2);
|
||||
Ok(ReceiveOk::Unassociated)
|
||||
} else if p == PACKET_TYPE_CHALLENGE {
|
||||
@@ -365,10 +410,17 @@ impl<App: ApplicationLayer> Context<App> {
|
||||
if assembled_packet.len() != KID_SIZE + CHALLENGE_SIZE {
|
||||
return Err(byzantine_fault!(InvalidPacket, true));
|
||||
}
|
||||
if let Some(kid_recv) = NonZeroU32::new(u32::from_be_bytes(assembled_packet[..KID_SIZE].try_into().unwrap())) {
|
||||
if let Some(Some(session)) = ctx.session_map.lock().unwrap().get(&kid_recv).map(|r| r.upgrade()) {
|
||||
if let Some(kid_recv) =
|
||||
NonZeroU32::new(u32::from_be_bytes(assembled_packet[..KID_SIZE].try_into().unwrap()))
|
||||
{
|
||||
if let Some(Some(session)) = ctx.session_map.lock().unwrap().get(&kid_recv).map(|r| r.upgrade())
|
||||
{
|
||||
let mut zeta = session.0.lock().unwrap();
|
||||
respond_to_challenge(&mut zeta, &ctx.rng, &assembled_packet[KID_SIZE..].try_into().unwrap());
|
||||
respond_to_challenge(
|
||||
&mut zeta,
|
||||
&ctx.rng,
|
||||
&assembled_packet[KID_SIZE..].try_into().unwrap(),
|
||||
);
|
||||
log!(app, ChallengeIsAuth(&session));
|
||||
return Ok(ReceiveOk::Unassociated);
|
||||
}
|
||||
@@ -390,7 +442,13 @@ impl<App: ApplicationLayer> Context<App> {
|
||||
/// slice of `data`
|
||||
/// * `mtu` - The MTU of the link, all packets passed to `send` will be at most `mtu` in length
|
||||
/// * `payload` - Data to send
|
||||
pub fn send(&self, session: &Arc<Session<App>>, send: impl FnMut(Vec<u8>) -> bool, mut mtu: usize, payload: Vec<u8>) -> Result<(), SendError> {
|
||||
pub fn send(
|
||||
&self,
|
||||
session: &Arc<Session<App>>,
|
||||
send: impl FnMut(Vec<u8>) -> bool,
|
||||
mut mtu: usize,
|
||||
payload: Vec<u8>,
|
||||
) -> Result<(), SendError> {
|
||||
mtu = mtu.max(MIN_TRANSPORT_MTU);
|
||||
let mut zeta = session.0.lock().unwrap();
|
||||
send_payload(&mut zeta, payload, |Packet(kid, nonce, payload), hk| {
|
||||
@@ -405,7 +463,11 @@ impl<App: ApplicationLayer> Context<App> {
|
||||
/// a problem.
|
||||
///
|
||||
/// * `send_to` - Function to get a sender and an MTU to send something over an active session
|
||||
pub fn service<SendFn: FnMut(Vec<u8>) -> bool>(&self, app: App, mut send_to: impl FnMut(&Arc<Session<App>>) -> Option<(SendFn, usize)>) -> i64 {
|
||||
pub fn service<SendFn: FnMut(Vec<u8>) -> bool>(
|
||||
&self,
|
||||
app: App,
|
||||
mut send_to: impl FnMut(&Arc<Session<App>>) -> Option<(SendFn, usize)>,
|
||||
) -> i64 {
|
||||
let ctx = &self.0;
|
||||
let sessions = ctx.sessions.lock().unwrap();
|
||||
let current_time = app.time();
|
||||
@@ -422,7 +484,14 @@ impl<App: ApplicationLayer> Context<App> {
|
||||
|Packet(kid, nonce, payload): &Packet, hk| {
|
||||
if let Some((send_fragment, mut mtu)) = send_to(&session) {
|
||||
mtu = mtu.max(MIN_TRANSPORT_MTU);
|
||||
send_with_fragmentation::<App>(send_fragment, mtu, *kid, to_packet_nonce(&nonce), payload, hk);
|
||||
send_with_fragmentation::<App>(
|
||||
send_fragment,
|
||||
mtu,
|
||||
*kid,
|
||||
to_packet_nonce(&nonce),
|
||||
payload,
|
||||
hk,
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
+6
-1
@@ -27,7 +27,12 @@ pub trait PrpAes256 {
|
||||
pub trait AeadAesGcm {
|
||||
/// Encrypt the given `buffer` of plaintext using AES-GCM-256, with the given `key`, `iv` and `aad`.
|
||||
/// The ciphertext should be written directly back to `buffer`, and the GCM tag should be returned.
|
||||
fn encrypt_in_place(key: &[u8; AES_256_KEY_SIZE], iv: [u8; AES_GCM_IV_SIZE], aad: Option<&[u8]>, buffer: &mut [u8]) -> [u8; AES_GCM_TAG_SIZE];
|
||||
fn encrypt_in_place(
|
||||
key: &[u8; AES_256_KEY_SIZE],
|
||||
iv: [u8; AES_GCM_IV_SIZE],
|
||||
aad: Option<&[u8]>,
|
||||
buffer: &mut [u8],
|
||||
) -> [u8; AES_GCM_TAG_SIZE];
|
||||
/// Decrypt the given `buffer` of ciphertext using AES-GCM-256, with the given `key`, `iv` and `aad`.
|
||||
/// The ciphertext should be written directly back to `buffer`, and the GCM tag should be returned.
|
||||
fn decrypt_in_place(
|
||||
|
||||
@@ -24,7 +24,10 @@ pub trait PrivateKeyKyber1024<Rng: RngCore + CryptoRng>: Sized + Send + Sync {
|
||||
///
|
||||
/// **CRITICAL**: This must return `None` if the given `public_key` is invalid in any way
|
||||
/// according to the Kyber1024 spec.
|
||||
fn encapsulate(rng: &mut Rng, public_key: &[u8; KYBER_PUBLIC_KEY_SIZE]) -> Option<([u8; KYBER_CIPHERTEXT_SIZE], [u8; KYBER_PLAINTEXT_SIZE])>;
|
||||
fn encapsulate(
|
||||
rng: &mut Rng,
|
||||
public_key: &[u8; KYBER_PUBLIC_KEY_SIZE],
|
||||
) -> Option<([u8; KYBER_CIPHERTEXT_SIZE], [u8; KYBER_PLAINTEXT_SIZE])>;
|
||||
/// Decapsulate a Kyber1024 `ciphertext` received from the remote peer, retreiving
|
||||
/// the raw bytes of the original plaintext. This plaintext is immediately hashed and deleted.
|
||||
///
|
||||
|
||||
@@ -18,7 +18,12 @@ impl PrpAes256 for Aes256 {
|
||||
}
|
||||
|
||||
impl AeadAesGcm for Aes256Gcm {
|
||||
fn encrypt_in_place(key: &[u8; AES_256_KEY_SIZE], iv: [u8; AES_GCM_IV_SIZE], aad: Option<&[u8]>, buffer: &mut [u8]) -> [u8; AES_GCM_TAG_SIZE] {
|
||||
fn encrypt_in_place(
|
||||
key: &[u8; AES_256_KEY_SIZE],
|
||||
iv: [u8; AES_GCM_IV_SIZE],
|
||||
aad: Option<&[u8]>,
|
||||
buffer: &mut [u8],
|
||||
) -> [u8; AES_GCM_TAG_SIZE] {
|
||||
let key = Key::<Aes256Gcm>::from_slice(key);
|
||||
let mut cipher = Aes256Gcm::new(&key);
|
||||
cipher
|
||||
|
||||
@@ -13,7 +13,10 @@ impl<Rng: RngCore + CryptoRng> PrivateKeyKyber1024<Rng> for PqcKyberSecretKey {
|
||||
(Zeroizing::new(keypair.secret), keypair.public)
|
||||
}
|
||||
|
||||
fn encapsulate(rng: &mut Rng, public_key: &[u8; KYBER_PUBLIC_KEY_SIZE]) -> Option<([u8; KYBER_CIPHERTEXT_SIZE], [u8; KYBER_PLAINTEXT_SIZE])> {
|
||||
fn encapsulate(
|
||||
rng: &mut Rng,
|
||||
public_key: &[u8; KYBER_PUBLIC_KEY_SIZE],
|
||||
) -> Option<([u8; KYBER_CIPHERTEXT_SIZE], [u8; KYBER_PLAINTEXT_SIZE])> {
|
||||
pqc_kyber::encapsulate(public_key, rng).ok()
|
||||
}
|
||||
|
||||
|
||||
@@ -26,6 +26,12 @@ impl<Rng: RngCore + CryptoRng> KeyPairP384<Rng> for EphemeralSecret {
|
||||
}
|
||||
|
||||
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())
|
||||
Some(
|
||||
self.diffie_hellman(public_key)
|
||||
.raw_secret_bytes()
|
||||
.as_slice()
|
||||
.try_into()
|
||||
.unwrap(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+16
-3
@@ -10,7 +10,12 @@ use crate::proto::*;
|
||||
use crate::result::{byzantine_fault, ReceiveError};
|
||||
|
||||
/// Corresponds to Figure 13 found in Section 6.
|
||||
fn create_fragment_header(kid_send: u32, fragment_count: usize, fragment_no: usize, n: &[u8; PACKET_NONCE_SIZE]) -> [u8; HEADER_SIZE] {
|
||||
fn create_fragment_header(
|
||||
kid_send: u32,
|
||||
fragment_count: usize,
|
||||
fragment_no: usize,
|
||||
n: &[u8; PACKET_NONCE_SIZE],
|
||||
) -> [u8; HEADER_SIZE] {
|
||||
debug_assert!(fragment_count > 0);
|
||||
debug_assert!(fragment_count <= MAX_FRAGMENTS);
|
||||
debug_assert!(fragment_no < MAX_FRAGMENTS);
|
||||
@@ -47,7 +52,10 @@ pub fn send_with_fragmentation<App: ApplicationLayer>(
|
||||
fragment.extend(&packet[i..j]);
|
||||
|
||||
if let Some(hk_send) = hk_send {
|
||||
App::Prp::encrypt_in_place(hk_send, (&mut fragment[HEADER_AUTH_START..HEADER_AUTH_END]).try_into().unwrap());
|
||||
App::Prp::encrypt_in_place(
|
||||
hk_send,
|
||||
(&mut fragment[HEADER_AUTH_START..HEADER_AUTH_END]).try_into().unwrap(),
|
||||
);
|
||||
}
|
||||
if !send(fragment) {
|
||||
return false;
|
||||
@@ -87,7 +95,12 @@ impl DefragBuffer {
|
||||
}
|
||||
|
||||
if let Some(hk_recv) = self.hk_recv.as_ref() {
|
||||
App::Prp::decrypt_in_place(hk_recv, (&mut raw_fragment[HEADER_AUTH_START..HEADER_AUTH_END]).try_into().unwrap())
|
||||
App::Prp::decrypt_in_place(
|
||||
hk_recv,
|
||||
(&mut raw_fragment[HEADER_AUTH_START..HEADER_AUTH_END])
|
||||
.try_into()
|
||||
.unwrap(),
|
||||
)
|
||||
}
|
||||
|
||||
let fragment_no = raw_fragment[FRAGMENT_NO_IDX] as usize;
|
||||
|
||||
+9
-4
@@ -1,4 +1,6 @@
|
||||
use crate::crypto::{AES_GCM_TAG_SIZE, KYBER_CIPHERTEXT_SIZE, KYBER_PUBLIC_KEY_SIZE, P384_PUBLIC_KEY_SIZE, SHA512_HASH_SIZE};
|
||||
use crate::crypto::{
|
||||
AES_GCM_TAG_SIZE, KYBER_CIPHERTEXT_SIZE, KYBER_PUBLIC_KEY_SIZE, P384_PUBLIC_KEY_SIZE, SHA512_HASH_SIZE,
|
||||
};
|
||||
|
||||
/* Common constants */
|
||||
|
||||
@@ -71,7 +73,8 @@ pub(crate) const HASHLEN: usize = SHA512_HASH_SIZE;
|
||||
pub const RATCHET_SIZE: usize = 32;
|
||||
|
||||
/// Initial value of 'h'.
|
||||
pub(crate) const PROTOCOL_NAME_NOISE_XK: &[u8; HASHLEN] = b"Noise_XKhfs+psk2_P384+Kyber1024_AESGCM_SHA512\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
|
||||
pub(crate) const PROTOCOL_NAME_NOISE_XK: &[u8; HASHLEN] =
|
||||
b"Noise_XKhfs+psk2_P384+Kyber1024_AESGCM_SHA512\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
|
||||
/// Initial value of 'ck' for rekeying.
|
||||
pub(crate) const PROTOCOL_NAME_NOISE_KK: &[u8; HASHLEN] =
|
||||
b"Noise_KKpsk0_P384_AESGCM_SHA512\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
|
||||
@@ -112,10 +115,12 @@ pub(crate) const PACKET_TYPE_DATA: u8 = 8;
|
||||
pub(crate) const PACKET_TYPE_CHALLENGE: u8 = 9;
|
||||
pub(crate) const PACKET_TYPE_USES_COUNTER_RANGE: std::ops::Range<u8> = 3..9;
|
||||
|
||||
pub(crate) const HANDSHAKE_HELLO_MIN_SIZE: usize = KID_SIZE + P384_PUBLIC_KEY_SIZE + KYBER_PUBLIC_KEY_SIZE + AES_GCM_TAG_SIZE + AES_GCM_TAG_SIZE;
|
||||
pub(crate) const HANDSHAKE_HELLO_MIN_SIZE: usize =
|
||||
KID_SIZE + P384_PUBLIC_KEY_SIZE + KYBER_PUBLIC_KEY_SIZE + AES_GCM_TAG_SIZE + AES_GCM_TAG_SIZE;
|
||||
pub(crate) const HANDSHAKE_HELLO_MAX_SIZE: usize = HANDSHAKE_HELLO_MIN_SIZE + RATCHET_SIZE;
|
||||
|
||||
pub(crate) const HANDSHAKE_RESPONSE_SIZE: usize = P384_PUBLIC_KEY_SIZE + KYBER_CIPHERTEXT_SIZE + AES_GCM_TAG_SIZE + KID_SIZE + AES_GCM_TAG_SIZE;
|
||||
pub(crate) const HANDSHAKE_RESPONSE_SIZE: usize =
|
||||
P384_PUBLIC_KEY_SIZE + KYBER_CIPHERTEXT_SIZE + AES_GCM_TAG_SIZE + KID_SIZE + AES_GCM_TAG_SIZE;
|
||||
|
||||
pub(crate) const HANDSHAKE_COMPLETION_MIN_SIZE: usize = P384_PUBLIC_KEY_SIZE + AES_GCM_TAG_SIZE + 0 + AES_GCM_TAG_SIZE;
|
||||
pub(crate) const HANDSHAKE_COMPLETION_MAX_SIZE: usize = HANDSHAKE_COMPLETION_MIN_SIZE + IDENTITY_MAX_SIZE;
|
||||
|
||||
+20
-3
@@ -84,7 +84,14 @@ impl<App: ApplicationLayer> SymmetricState<App> {
|
||||
let mut next_ck = [0u8; HASHLEN];
|
||||
let mut temp_k = [0u8; HASHLEN];
|
||||
|
||||
self.kbkdf(input_key_material, LABEL_KBKDF_CHAIN, 2, &mut next_ck, Some(&mut temp_k), None);
|
||||
self.kbkdf(
|
||||
input_key_material,
|
||||
LABEL_KBKDF_CHAIN,
|
||||
2,
|
||||
&mut next_ck,
|
||||
Some(&mut temp_k),
|
||||
None,
|
||||
);
|
||||
|
||||
*self.ck = next_ck;
|
||||
self.k.clone_from_slice(&temp_k[..AES_256_KEY_SIZE]);
|
||||
@@ -116,14 +123,24 @@ impl<App: ApplicationLayer> SymmetricState<App> {
|
||||
self.k.clone_from_slice(&temp_k[..AES_256_KEY_SIZE]);
|
||||
}
|
||||
/// Corresponds to Noise `EncryptAndHash`.
|
||||
pub fn encrypt_and_hash_in_place(&mut self, iv: [u8; AES_GCM_IV_SIZE], plaintext_start: usize, buffer: &mut Vec<u8>) {
|
||||
pub fn encrypt_and_hash_in_place(
|
||||
&mut self,
|
||||
iv: [u8; AES_GCM_IV_SIZE],
|
||||
plaintext_start: usize,
|
||||
buffer: &mut Vec<u8>,
|
||||
) {
|
||||
let tag = App::Aead::encrypt_in_place(&self.k, iv, Some(&self.h), &mut buffer[plaintext_start..]);
|
||||
buffer.extend(&tag);
|
||||
self.mix_hash(&buffer[plaintext_start..]);
|
||||
}
|
||||
/// Corresponds to Noise `DecryptAndHash`.
|
||||
#[must_use]
|
||||
pub fn decrypt_and_hash_in_place(&mut self, iv: [u8; AES_GCM_IV_SIZE], buffer: &mut [u8], tag: [u8; AES_GCM_TAG_SIZE]) -> bool {
|
||||
pub fn decrypt_and_hash_in_place(
|
||||
&mut self,
|
||||
iv: [u8; AES_GCM_IV_SIZE],
|
||||
buffer: &mut [u8],
|
||||
tag: [u8; AES_GCM_TAG_SIZE],
|
||||
) -> bool {
|
||||
let mut hash = App::Hash::new();
|
||||
hash.update(&self.h);
|
||||
hash.update(buffer);
|
||||
|
||||
+139
-36
@@ -276,7 +276,15 @@ pub(crate) fn trans_to_a1<App: ApplicationLayer>(
|
||||
let mut session_map = ctx.session_map.lock().unwrap();
|
||||
let kid_recv = gen_kid(session_map.deref(), ctx.rng.lock().unwrap().deref_mut());
|
||||
|
||||
let a1 = create_a1_state(&ctx.rng, &s_remote, kid_recv, &ratchet_state1, ratchet_state2.as_ref(), identity).ok_or(OpenError::InvalidPublicKey)?;
|
||||
let a1 = create_a1_state(
|
||||
&ctx.rng,
|
||||
&s_remote,
|
||||
kid_recv,
|
||||
&ratchet_state1,
|
||||
ratchet_state2.as_ref(),
|
||||
identity,
|
||||
)
|
||||
.ok_or(OpenError::InvalidPublicKey)?;
|
||||
let packet = a1.packet.clone();
|
||||
|
||||
let (hk_recv, hk_send) = a1.noise.get_ask(LABEL_HEADER_KEY);
|
||||
@@ -304,14 +312,21 @@ pub(crate) fn trans_to_a1<App: ApplicationLayer>(
|
||||
|
||||
let session = Arc::new(Session(Mutex::new(zeta)));
|
||||
session_map.insert(kid_recv, Arc::downgrade(&session));
|
||||
ctx.sessions.lock().unwrap().insert(Arc::as_ptr(&session), Arc::downgrade(&session));
|
||||
ctx.sessions
|
||||
.lock()
|
||||
.unwrap()
|
||||
.insert(Arc::as_ptr(&session), Arc::downgrade(&session));
|
||||
|
||||
send(&packet);
|
||||
|
||||
Ok(session)
|
||||
}
|
||||
/// Corresponds to Algorithm 13 found in Section 5.
|
||||
pub(crate) fn respond_to_challenge<App: ApplicationLayer>(zeta: &mut Zeta<App>, rng: &Mutex<App::Rng>, challenge: &[u8; CHALLENGE_SIZE]) {
|
||||
pub(crate) fn respond_to_challenge<App: ApplicationLayer>(
|
||||
zeta: &mut Zeta<App>,
|
||||
rng: &Mutex<App::Rng>,
|
||||
challenge: &[u8; CHALLENGE_SIZE],
|
||||
) {
|
||||
if let ZetaAutomata::A1(StateA1 { packet: Packet(_, _, x1), .. }) = &mut zeta.beta {
|
||||
let response_start = x1.len() - CHALLENGE_SIZE;
|
||||
respond_to_challenge_in_place::<App::Rng, App::Hash>(
|
||||
@@ -345,13 +360,16 @@ pub(crate) fn received_x1_trans<App: ApplicationLayer>(
|
||||
// Noise process prologue.
|
||||
let j = i + KID_SIZE;
|
||||
noise.mix_hash(&x1[i..j]);
|
||||
let kid_send = NonZeroU32::new(u32::from_be_bytes(x1[i..j].try_into().unwrap())).ok_or(byzantine_fault!(InvalidPacket, true))?;
|
||||
let kid_send = NonZeroU32::new(u32::from_be_bytes(x1[i..j].try_into().unwrap()))
|
||||
.ok_or(byzantine_fault!(InvalidPacket, true))?;
|
||||
noise.mix_hash(&ctx.s_secret.public_key_bytes());
|
||||
i = j;
|
||||
// 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)
|
||||
.ok_or(byzantine_fault!(FailedAuth, true))?;
|
||||
// Process message pattern 1 e1 token.
|
||||
let j = i + KYBER_PUBLIC_KEY_SIZE;
|
||||
let k = j + AES_GCM_TAG_SIZE;
|
||||
@@ -396,12 +414,17 @@ 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)
|
||||
.ok_or(byzantine_fault!(FailedAuth, true))?;
|
||||
// Process message pattern 2 ekem1 token.
|
||||
let i = x2.len();
|
||||
let (ekem1, ekem1_secret) = App::Kem::encapsulate(ctx.rng.lock().unwrap().deref_mut(), (&x1[e1_start..e1_end]).try_into().unwrap())
|
||||
.map(|(ct, secret)| (ct, Zeroizing::new(secret)))
|
||||
.ok_or(byzantine_fault!(FailedAuth, true))?;
|
||||
let (ekem1, ekem1_secret) = App::Kem::encapsulate(
|
||||
ctx.rng.lock().unwrap().deref_mut(),
|
||||
(&x1[e1_start..e1_end]).try_into().unwrap(),
|
||||
)
|
||||
.map(|(ct, secret)| (ct, Zeroizing::new(secret)))
|
||||
.ok_or(byzantine_fault!(FailedAuth, true))?;
|
||||
x2.extend(ekem1);
|
||||
noise.encrypt_and_hash_in_place(to_nonce(PACKET_TYPE_HANDSHAKE_RESPONSE, 0), i, &mut x2);
|
||||
noise.mix_key(ekem1_secret.as_ref());
|
||||
@@ -436,7 +459,10 @@ pub(crate) fn received_x1_trans<App: ApplicationLayer>(
|
||||
},
|
||||
);
|
||||
|
||||
send(&Packet(kid_send.get(), to_nonce(PACKET_TYPE_HANDSHAKE_RESPONSE, c), x2), &hk_send);
|
||||
send(
|
||||
&Packet(kid_send.get(), to_nonce(PACKET_TYPE_HANDSHAKE_RESPONSE, c), x2),
|
||||
&hk_send,
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
/// Corresponds to Transition Algorithm 3 found in Section 4.3.
|
||||
@@ -470,7 +496,9 @@ 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)
|
||||
.ok_or(byzantine_fault!(FailedAuth, true))?;
|
||||
// Process message pattern 2 ekem1 token.
|
||||
let j = i + KYBER_CIPHERTEXT_SIZE;
|
||||
let k = j + AES_GCM_TAG_SIZE;
|
||||
@@ -536,7 +564,9 @@ 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)
|
||||
.ok_or(byzantine_fault!(FailedAuth, true))?;
|
||||
// Process message pattern 3 payload.
|
||||
let i = x3.len();
|
||||
x3.extend(identity);
|
||||
@@ -623,10 +653,13 @@ pub(crate) fn received_x3_trans<App: ApplicationLayer>(
|
||||
if !noise.decrypt_and_hash_in_place(to_nonce(PACKET_TYPE_HANDSHAKE_COMPLETION, 1), &mut x3[i..j], tag) {
|
||||
return Err(byzantine_fault!(FailedAuth, true));
|
||||
}
|
||||
let s_remote = App::PublicKey::from_bytes((&x3[i..j]).try_into().unwrap()).ok_or(byzantine_fault!(FailedAuth, true))?;
|
||||
let s_remote =
|
||||
App::PublicKey::from_bytes((&x3[i..j]).try_into().unwrap()).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)
|
||||
.ok_or(byzantine_fault!(FailedAuth, true))?;
|
||||
// Process message pattern 3 payload.
|
||||
let k = x3.len();
|
||||
let j = k - AES_GCM_TAG_SIZE;
|
||||
@@ -726,7 +759,10 @@ pub(crate) fn received_x3_trans<App: ApplicationLayer>(
|
||||
defrag: zeta.defrag,
|
||||
})));
|
||||
entry.insert(Arc::downgrade(&session));
|
||||
ctx.sessions.lock().unwrap().insert(Arc::as_ptr(&session), Arc::downgrade(&session));
|
||||
ctx.sessions
|
||||
.lock()
|
||||
.unwrap()
|
||||
.insert(Arc::as_ptr(&session), Arc::downgrade(&session));
|
||||
|
||||
send(&Packet(zeta.kid_send.get(), n, c1), Some(&zeta.hk_send));
|
||||
Ok(session)
|
||||
@@ -765,7 +801,12 @@ pub(crate) fn received_c1_trans<App: ApplicationLayer>(
|
||||
return Err(byzantine_fault!(OutOfSequence, false));
|
||||
};
|
||||
|
||||
let specified_key = zeta.key_ref(is_other).recv.kek.as_ref().ok_or(byzantine_fault!(OutOfSequence, true))?;
|
||||
let specified_key = zeta
|
||||
.key_ref(is_other)
|
||||
.recv
|
||||
.kek
|
||||
.as_ref()
|
||||
.ok_or(byzantine_fault!(OutOfSequence, true))?;
|
||||
let tag = c1[..].try_into().unwrap();
|
||||
if !App::Aead::decrypt_in_place(specified_key, n, None, &mut [], tag) {
|
||||
return Err(byzantine_fault!(FailedAuth, true));
|
||||
@@ -800,7 +841,8 @@ pub(crate) fn received_c1_trans<App: ApplicationLayer>(
|
||||
zeta.timeout_timer = app.time()
|
||||
+ App::SETTINGS
|
||||
.rekey_after_time
|
||||
.saturating_sub(rng.lock().unwrap().next_u64() % App::SETTINGS.rekey_time_max_jitter) as i64;
|
||||
.saturating_sub(rng.lock().unwrap().next_u64() % App::SETTINGS.rekey_time_max_jitter)
|
||||
as i64;
|
||||
zeta.resend_timer = i64::MAX;
|
||||
zeta.beta = ZetaAutomata::S2;
|
||||
}
|
||||
@@ -810,11 +852,19 @@ pub(crate) fn received_c1_trans<App: ApplicationLayer>(
|
||||
let c = zeta.send_counter;
|
||||
zeta.send_counter += 1;
|
||||
let n = to_nonce(PACKET_TYPE_ACK, c);
|
||||
let latest_confirmed_key = zeta.key_ref(false).send.kek.as_ref().ok_or(byzantine_fault!(OutOfSequence, true))?;
|
||||
let latest_confirmed_key = zeta
|
||||
.key_ref(false)
|
||||
.send
|
||||
.kek
|
||||
.as_ref()
|
||||
.ok_or(byzantine_fault!(OutOfSequence, true))?;
|
||||
let tag = App::Aead::encrypt_in_place(latest_confirmed_key, n, None, &mut []);
|
||||
c2.extend(&tag);
|
||||
|
||||
send(&Packet(zeta.key_ref(false).send.kid.unwrap().get(), n, c2), Some(&zeta.hk_send));
|
||||
send(
|
||||
&Packet(zeta.key_ref(false).send.kid.unwrap().get(), n, c2),
|
||||
Some(&zeta.hk_send),
|
||||
);
|
||||
Ok(just_establised)
|
||||
}
|
||||
/// Corresponds to the trivial Transition Algorithm described for processing C_2 packets found in
|
||||
@@ -929,7 +979,12 @@ pub(crate) fn service<App: ApplicationLayer>(
|
||||
let c = zeta.send_counter;
|
||||
zeta.send_counter += 1;
|
||||
let n = to_nonce(p, c);
|
||||
let tag = App::Aead::encrypt_in_place(zeta.key_ref(false).send.kek.as_ref().unwrap(), n, None, &mut control_payload);
|
||||
let tag = App::Aead::encrypt_in_place(
|
||||
zeta.key_ref(false).send.kek.as_ref().unwrap(),
|
||||
n,
|
||||
None,
|
||||
&mut control_payload,
|
||||
);
|
||||
control_payload.extend(&tag);
|
||||
send(
|
||||
&Packet(zeta.key_ref(false).send.kid.unwrap().get(), n, control_payload),
|
||||
@@ -937,7 +992,12 @@ pub(crate) fn service<App: ApplicationLayer>(
|
||||
);
|
||||
}
|
||||
}
|
||||
fn remap<App: ApplicationLayer>(session: &Arc<Session<App>>, zeta: &Zeta<App>, rng: &Mutex<App::Rng>, session_map: &SessionMap<App>) -> NonZeroU32 {
|
||||
fn remap<App: ApplicationLayer>(
|
||||
session: &Arc<Session<App>>,
|
||||
zeta: &Zeta<App>,
|
||||
rng: &Mutex<App::Rng>,
|
||||
session_map: &SessionMap<App>,
|
||||
) -> NonZeroU32 {
|
||||
let mut session_map = session_map.lock().unwrap();
|
||||
let weak = if let Some(Some(weak)) = zeta.key_ref(true).recv.kid.as_ref().map(|kid| session_map.remove(kid)) {
|
||||
weak
|
||||
@@ -1034,7 +1094,10 @@ fn timeout_trans<App: ApplicationLayer>(
|
||||
let tag = App::Aead::encrypt_in_place(zeta.key_ref(false).send.kek.as_ref().unwrap(), n, None, &mut k1);
|
||||
k1.extend(&tag);
|
||||
|
||||
send(&Packet(zeta.key_ref(false).send.kid.unwrap().get(), n, k1), Some(&zeta.hk_send));
|
||||
send(
|
||||
&Packet(zeta.key_ref(false).send.kid.unwrap().get(), n, k1),
|
||||
Some(&zeta.hk_send),
|
||||
);
|
||||
}
|
||||
ZetaAutomata::S1 { .. } => {
|
||||
log!(app, TimeoutKeyConfirm(session));
|
||||
@@ -1088,7 +1151,13 @@ pub(crate) fn received_k1_trans<App: ApplicationLayer>(
|
||||
|
||||
let i = k1.len() - AES_GCM_TAG_SIZE;
|
||||
let tag = k1[i..].try_into().unwrap();
|
||||
if !App::Aead::decrypt_in_place(zeta.key_ref(false).recv.kek.as_ref().unwrap(), n, None, &mut k1[..i], tag) {
|
||||
if !App::Aead::decrypt_in_place(
|
||||
zeta.key_ref(false).recv.kek.as_ref().unwrap(),
|
||||
n,
|
||||
None,
|
||||
&mut k1[..i],
|
||||
tag,
|
||||
) {
|
||||
return Err(byzantine_fault!(FailedAuth, true));
|
||||
}
|
||||
let (_, c) = from_nonce(&n);
|
||||
@@ -1108,9 +1177,13 @@ 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)
|
||||
.ok_or(byzantine_fault!(FailedAuth, true))?;
|
||||
// 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)
|
||||
.ok_or(byzantine_fault!(FailedAuth, true))?;
|
||||
// Process message pattern 1 payload.
|
||||
let j = i + KID_SIZE;
|
||||
let k = j + AES_GCM_TAG_SIZE;
|
||||
@@ -1118,15 +1191,20 @@ pub(crate) fn received_k1_trans<App: ApplicationLayer>(
|
||||
if !noise.decrypt_and_hash_in_place(to_nonce(PACKET_TYPE_REKEY_INIT, 0), &mut k1[i..j], tag) {
|
||||
return Err(byzantine_fault!(FailedAuth, true));
|
||||
}
|
||||
let kid_send = NonZeroU32::new(u32::from_be_bytes(k1[i..j].try_into().unwrap())).ok_or(byzantine_fault!(FailedAuth, true))?;
|
||||
let kid_send = NonZeroU32::new(u32::from_be_bytes(k1[i..j].try_into().unwrap()))
|
||||
.ok_or(byzantine_fault!(FailedAuth, true))?;
|
||||
|
||||
let mut k2 = Vec::new();
|
||||
// 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)
|
||||
.ok_or(byzantine_fault!(FailedAuth, true))?;
|
||||
// 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)
|
||||
.ok_or(byzantine_fault!(FailedAuth, true))?;
|
||||
// Process message pattern 2 payload.
|
||||
let i = k2.len();
|
||||
let new_kid_recv = remap(session, &zeta, rng, session_map);
|
||||
@@ -1172,7 +1250,10 @@ pub(crate) fn received_k1_trans<App: ApplicationLayer>(
|
||||
let tag = App::Aead::encrypt_in_place(zeta.key_ref(false).send.kek.as_ref().unwrap(), n, None, &mut k2);
|
||||
k2.extend(&tag);
|
||||
|
||||
send(&Packet(zeta.key_ref(false).send.kid.unwrap().get(), n, k2), Some(&zeta.hk_send));
|
||||
send(
|
||||
&Packet(zeta.key_ref(false).send.kid.unwrap().get(), n, k2),
|
||||
Some(&zeta.hk_send),
|
||||
);
|
||||
Ok(())
|
||||
})();
|
||||
if matches!(result, Err(ReceiveError::ByzantineFault { .. })) {
|
||||
@@ -1205,7 +1286,13 @@ pub(crate) fn received_k2_trans<App: ApplicationLayer>(
|
||||
|
||||
let i = k2.len() - AES_GCM_TAG_SIZE;
|
||||
let tag = k2[i..].try_into().unwrap();
|
||||
if !App::Aead::decrypt_in_place(zeta.key_ref(false).recv.kek.as_ref().unwrap(), n, None, &mut k2[..i], tag) {
|
||||
if !App::Aead::decrypt_in_place(
|
||||
zeta.key_ref(false).recv.kek.as_ref().unwrap(),
|
||||
n,
|
||||
None,
|
||||
&mut k2[..i],
|
||||
tag,
|
||||
) {
|
||||
return Err(byzantine_fault!(FailedAuth, true));
|
||||
}
|
||||
let (_, c) = from_nonce(&n);
|
||||
@@ -1220,9 +1307,13 @@ 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)
|
||||
.ok_or(byzantine_fault!(FailedAuth, true))?;
|
||||
// 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)
|
||||
.ok_or(byzantine_fault!(FailedAuth, true))?;
|
||||
// Process message pattern 2 payload.
|
||||
let j = i + KID_SIZE;
|
||||
let k = j + AES_GCM_TAG_SIZE;
|
||||
@@ -1230,7 +1321,8 @@ pub(crate) fn received_k2_trans<App: ApplicationLayer>(
|
||||
if !noise.decrypt_and_hash_in_place(to_nonce(PACKET_TYPE_REKEY_COMPLETE, 0), &mut k2[i..j], tag) {
|
||||
return Err(byzantine_fault!(FailedAuth, true));
|
||||
}
|
||||
let kid_send = NonZeroU32::new(u32::from_be_bytes(k2[i..j].try_into().unwrap())).ok_or(byzantine_fault!(InvalidPacket, true))?;
|
||||
let kid_send = NonZeroU32::new(u32::from_be_bytes(k2[i..j].try_into().unwrap()))
|
||||
.ok_or(byzantine_fault!(InvalidPacket, true))?;
|
||||
|
||||
let (rk, rf) = noise.get_ask(LABEL_RATCHET_STATE);
|
||||
let new_ratchet_state = RatchetState::new(rk, rf, zeta.ratchet_state1.chain_len + 1);
|
||||
@@ -1271,7 +1363,10 @@ pub(crate) fn received_k2_trans<App: ApplicationLayer>(
|
||||
let tag = App::Aead::encrypt_in_place(zeta.key_ref(false).send.kek.as_ref().unwrap(), n, None, &mut []);
|
||||
c1.extend(&tag);
|
||||
|
||||
send(&Packet(zeta.key_ref(false).send.kid.unwrap().get(), n, c1), Some(&zeta.hk_send));
|
||||
send(
|
||||
&Packet(zeta.key_ref(false).send.kid.unwrap().get(), n, c1),
|
||||
Some(&zeta.hk_send),
|
||||
);
|
||||
Ok(())
|
||||
} else {
|
||||
unreachable!()
|
||||
@@ -1314,7 +1409,10 @@ pub(crate) fn send_payload<App: ApplicationLayer>(
|
||||
let tag = App::Aead::encrypt_in_place(zeta.key_ref(false).send.nk.as_ref().unwrap(), n, None, &mut payload);
|
||||
payload.extend(&tag);
|
||||
|
||||
send(&Packet(zeta.key_ref(false).send.kid.unwrap().get(), n, payload), Some(&zeta.hk_send));
|
||||
send(
|
||||
&Packet(zeta.key_ref(false).send.kid.unwrap().get(), n, payload),
|
||||
Some(&zeta.hk_send),
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
/// Corresponds to Algorithm 10 found in Section 4.3.
|
||||
@@ -1340,7 +1438,12 @@ pub(crate) fn received_payload_in_place<App: ApplicationLayer>(
|
||||
};
|
||||
|
||||
let i = payload.len() - AES_GCM_TAG_SIZE;
|
||||
let specified_key = zeta.key_ref(is_other).recv.nk.as_ref().ok_or(byzantine_fault!(OutOfSequence, true))?;
|
||||
let specified_key = zeta
|
||||
.key_ref(is_other)
|
||||
.recv
|
||||
.nk
|
||||
.as_ref()
|
||||
.ok_or(byzantine_fault!(OutOfSequence, true))?;
|
||||
let tag = payload[i..].try_into().unwrap();
|
||||
if !App::Aead::decrypt_in_place(specified_key, n, None, &mut payload[..i], tag) {
|
||||
return Err(byzantine_fault!(FailedAuth, true));
|
||||
|
||||
Reference in New Issue
Block a user