mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-05-14 17:43:43 +02:00
Simplify some logic.
This commit is contained in:
parent
07fc8b2d2b
commit
a7fa425830
1 changed files with 52 additions and 50 deletions
|
@ -830,39 +830,11 @@ impl<H: Host> ReceiveContext<H> {
|
||||||
let (offer_id, alice_session_id, alice_s_public, alice_metadata, alice_e1_public, alice_ratchet_key_fingerprint) =
|
let (offer_id, alice_session_id, alice_s_public, alice_metadata, alice_e1_public, alice_ratchet_key_fingerprint) =
|
||||||
parse_key_offer_after_header(&incoming_packet[(HEADER_SIZE + 1 + P384_PUBLIC_KEY_SIZE)..], packet_type)?;
|
parse_key_offer_after_header(&incoming_packet[(HEADER_SIZE + 1 + P384_PUBLIC_KEY_SIZE)..], packet_type)?;
|
||||||
|
|
||||||
// Important! If there's already a session, make sure the caller is the same endpoint as that session and
|
// We either have a session, in which case they should have supplied a ratchet key fingerprint, or
|
||||||
// that the ratchet key fingerprint matches a key that we have.
|
// we don't and they should not have supplied one.
|
||||||
if session.is_some() != alice_ratchet_key_fingerprint.is_some() {
|
if session.is_some() != alice_ratchet_key_fingerprint.is_some() {
|
||||||
// We either have a session, in which case they should have supplied a ratchet key fingerprint, or
|
|
||||||
// we don't and they should not have supplied one.
|
|
||||||
return Err(Error::FailedAuthentication);
|
return Err(Error::FailedAuthentication);
|
||||||
}
|
}
|
||||||
let (ratchet_key, ratchet_count) = if let Some(session) = session.as_ref() {
|
|
||||||
if !session.remote_s_public_hash.eq(&SHA384::hash(&alice_s_public)) {
|
|
||||||
return Err(Error::FailedAuthentication);
|
|
||||||
}
|
|
||||||
let alice_ratchet_key_fingerprint = alice_ratchet_key_fingerprint.as_ref().unwrap();
|
|
||||||
let mut ratchet_key = None;
|
|
||||||
let mut ratchet_count = 0;
|
|
||||||
let state = session.state.read();
|
|
||||||
for k in state.keys.iter() {
|
|
||||||
if let Some(k) = k.as_ref() {
|
|
||||||
if key_fingerprint(k.ratchet_key.as_bytes())[..16].eq(alice_ratchet_key_fingerprint) {
|
|
||||||
ratchet_key = Some(k.ratchet_key.clone());
|
|
||||||
ratchet_count = k.ratchet_count;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ratchet_key.is_none() {
|
|
||||||
// If they supplied a fingerprint that matches none of our keys, this is probably an old
|
|
||||||
// offer packet and should be ignored.
|
|
||||||
return Ok(ReceiveResult::Ignored);
|
|
||||||
}
|
|
||||||
(ratchet_key, ratchet_count)
|
|
||||||
} else {
|
|
||||||
(None, 0)
|
|
||||||
};
|
|
||||||
|
|
||||||
// Extract alice's static NIST P-384 public key from her public blob.
|
// Extract alice's static NIST P-384 public key from her public blob.
|
||||||
let alice_s_public_p384 = H::extract_p384_static(alice_s_public).ok_or(Error::InvalidPacket)?;
|
let alice_s_public_p384 = H::extract_p384_static(alice_s_public).ok_or(Error::InvalidPacket)?;
|
||||||
|
@ -898,39 +870,69 @@ impl<H: Host> ReceiveContext<H> {
|
||||||
// Key agreement: bob (local) static NIST P-384, alice (remote) ephemeral P-384.
|
// Key agreement: bob (local) static NIST P-384, alice (remote) ephemeral P-384.
|
||||||
let se0 = bob_e0_keypair.agree(&alice_s_public_p384).ok_or(Error::FailedAuthentication)?;
|
let se0 = bob_e0_keypair.agree(&alice_s_public_p384).ok_or(Error::FailedAuthentication)?;
|
||||||
|
|
||||||
// Gate (via host) and then create new session object if this is a new session.
|
// Perform checks and match ratchet key if there's an existing session, or gate (via host) and
|
||||||
let new_session = if session.is_some() {
|
// then create new sessions.
|
||||||
None
|
let (new_session, ratchet_key, ratchet_count) = if let Some(session) = session.as_ref() {
|
||||||
|
// Existing session identity must match the one in this offer.
|
||||||
|
if !session.remote_s_public_hash.eq(&SHA384::hash(&alice_s_public)) {
|
||||||
|
return Err(Error::FailedAuthentication);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Match ratchet key fingerprint and fail if no match, which likely indicates an old offer packet.
|
||||||
|
let alice_ratchet_key_fingerprint = alice_ratchet_key_fingerprint.as_ref().unwrap();
|
||||||
|
let mut ratchet_key = None;
|
||||||
|
let mut ratchet_count = 0;
|
||||||
|
let state = session.state.read();
|
||||||
|
for k in state.keys.iter() {
|
||||||
|
if let Some(k) = k.as_ref() {
|
||||||
|
if key_fingerprint(k.ratchet_key.as_bytes())[..16].eq(alice_ratchet_key_fingerprint) {
|
||||||
|
ratchet_key = Some(k.ratchet_key.clone());
|
||||||
|
ratchet_count = k.ratchet_count;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ratchet_key.is_none() {
|
||||||
|
return Ok(ReceiveResult::Ignored); // old packet?
|
||||||
|
}
|
||||||
|
|
||||||
|
(None, ratchet_key, ratchet_count)
|
||||||
} else {
|
} else {
|
||||||
if let Some((new_session_id, psk, associated_object)) =
|
if let Some((new_session_id, psk, associated_object)) =
|
||||||
host.accept_new_session(self, alice_s_public, alice_metadata)
|
host.accept_new_session(self, alice_s_public, alice_metadata)
|
||||||
{
|
{
|
||||||
let header_check_cipher = Aes::new(kbkdf512(ss.as_bytes(), KBKDF_KEY_USAGE_LABEL_HEADER_CHECK).first_n::<16>());
|
let header_check_cipher = Aes::new(kbkdf512(ss.as_bytes(), KBKDF_KEY_USAGE_LABEL_HEADER_CHECK).first_n::<16>());
|
||||||
Some(Session::<H> {
|
(
|
||||||
id: new_session_id,
|
Some(Session::<H> {
|
||||||
associated_object,
|
id: new_session_id,
|
||||||
send_counter: Counter::new(),
|
associated_object,
|
||||||
psk,
|
send_counter: Counter::new(),
|
||||||
ss,
|
psk,
|
||||||
header_check_cipher,
|
ss,
|
||||||
state: RwLock::new(SessionMutableState {
|
header_check_cipher,
|
||||||
remote_session_id: Some(alice_session_id),
|
state: RwLock::new(SessionMutableState {
|
||||||
keys: [None, None, None],
|
remote_session_id: Some(alice_session_id),
|
||||||
key_ptr: 0,
|
keys: [None, None, None],
|
||||||
offer: None,
|
key_ptr: 0,
|
||||||
|
offer: None,
|
||||||
|
}),
|
||||||
|
remote_s_public_hash: SHA384::hash(&alice_s_public),
|
||||||
|
remote_s_public_p384: alice_s_public_p384.as_bytes().clone(),
|
||||||
|
defrag: Mutex::new(RingBufferMap::new(random::xorshift64_random() as u32)),
|
||||||
}),
|
}),
|
||||||
remote_s_public_hash: SHA384::hash(&alice_s_public),
|
None,
|
||||||
remote_s_public_p384: alice_s_public_p384.as_bytes().clone(),
|
0,
|
||||||
defrag: Mutex::new(RingBufferMap::new(random::xorshift64_random() as u32)),
|
)
|
||||||
})
|
|
||||||
} else {
|
} else {
|
||||||
return Err(Error::NewSessionRejected);
|
return Err(Error::NewSessionRejected);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Set 'session' to a reference to either the existing or the new session.
|
||||||
let existing_session = session;
|
let existing_session = session;
|
||||||
let session = existing_session.as_ref().map_or_else(|| new_session.as_ref().unwrap(), |s| &*s);
|
let session = existing_session.as_ref().map_or_else(|| new_session.as_ref().unwrap(), |s| &*s);
|
||||||
|
|
||||||
// Mix in the psk, the key to this point, our ephemeral public, e0e0, and se0, completing Noise_IK on our side.
|
// Mix in the psk, the key to this point, our ephemeral public, e0e0, and se0, completing Noise_IK.
|
||||||
//
|
//
|
||||||
// FIPS note: the order of HMAC parameters are flipped here from the usual Noise HMAC(key, X). That's because
|
// FIPS note: the order of HMAC parameters are flipped here from the usual Noise HMAC(key, X). That's because
|
||||||
// NIST/FIPS allows HKDF with HMAC(salt, key) and salt is allowed to be anything. This way if the PSK is not
|
// NIST/FIPS allows HKDF with HMAC(salt, key) and salt is allowed to be anything. This way if the PSK is not
|
||||||
|
|
Loading…
Add table
Reference in a new issue