mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-06-07 21:13:44 +02:00
Moar cleanup.
This commit is contained in:
parent
d415f1c31b
commit
4219ad3078
1 changed files with 26 additions and 15 deletions
|
@ -695,7 +695,9 @@ impl<Application: ApplicationLayer> ReceiveContext<Application> {
|
||||||
let mut kex_packet_len = 0;
|
let mut kex_packet_len = 0;
|
||||||
for i in 0..fragments.len() {
|
for i in 0..fragments.len() {
|
||||||
let mut ff = fragments[i].as_ref();
|
let mut ff = fragments[i].as_ref();
|
||||||
debug_assert!(ff.len() >= MIN_PACKET_SIZE);
|
if ff.len() < MIN_PACKET_SIZE {
|
||||||
|
return Err(Error::InvalidPacket);
|
||||||
|
}
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
ff = &ff[HEADER_SIZE..];
|
ff = &ff[HEADER_SIZE..];
|
||||||
}
|
}
|
||||||
|
@ -708,7 +710,8 @@ impl<Application: ApplicationLayer> ReceiveContext<Application> {
|
||||||
}
|
}
|
||||||
let kex_packet_saved_ciphertext = kex_packet.clone(); // save for HMAC check later
|
let kex_packet_saved_ciphertext = kex_packet.clone(); // save for HMAC check later
|
||||||
|
|
||||||
// Key exchange packets begin (after header) with the session protocol version.
|
// Key exchange packets begin (after header) with the session protocol version. This could be
|
||||||
|
// changed in the future to support a different cipher suite.
|
||||||
if kex_packet[HEADER_SIZE] != SESSION_PROTOCOL_VERSION {
|
if kex_packet[HEADER_SIZE] != SESSION_PROTOCOL_VERSION {
|
||||||
return Err(Error::UnknownProtocolVersion);
|
return Err(Error::UnknownProtocolVersion);
|
||||||
}
|
}
|
||||||
|
@ -720,9 +723,11 @@ impl<Application: ApplicationLayer> ReceiveContext<Application> {
|
||||||
// packet decoding for noise initial key offer
|
// packet decoding for noise initial key offer
|
||||||
// -> e, es, s, ss
|
// -> e, es, s, ss
|
||||||
////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
if kex_packet_len < (HEADER_SIZE + 1 + P384_PUBLIC_KEY_SIZE + AES_GCM_TAG_SIZE + HMAC_SIZE + HMAC_SIZE) {
|
if kex_packet_len < (HEADER_SIZE + 1 + P384_PUBLIC_KEY_SIZE + AES_GCM_TAG_SIZE + HMAC_SIZE + HMAC_SIZE) {
|
||||||
return Err(Error::InvalidPacket);
|
return Err(Error::InvalidPacket);
|
||||||
}
|
}
|
||||||
|
|
||||||
let plaintext_end = HEADER_SIZE + 1 + P384_PUBLIC_KEY_SIZE;
|
let plaintext_end = HEADER_SIZE + 1 + P384_PUBLIC_KEY_SIZE;
|
||||||
let payload_end = kex_packet_len - (AES_GCM_TAG_SIZE + HMAC_SIZE + HMAC_SIZE);
|
let payload_end = kex_packet_len - (AES_GCM_TAG_SIZE + HMAC_SIZE + HMAC_SIZE);
|
||||||
let aes_gcm_tag_end = kex_packet_len - (HMAC_SIZE + HMAC_SIZE);
|
let aes_gcm_tag_end = kex_packet_len - (HMAC_SIZE + HMAC_SIZE);
|
||||||
|
@ -760,14 +765,14 @@ impl<Application: ApplicationLayer> ReceiveContext<Application> {
|
||||||
.ok_or(Error::FailedAuthentication)?;
|
.ok_or(Error::FailedAuthentication)?;
|
||||||
|
|
||||||
// Initial key derivation from starting point, mixing in alice's ephemeral public and the es.
|
// Initial key derivation from starting point, mixing in alice's ephemeral public and the es.
|
||||||
let es_key = Secret(hmac_sha512(
|
let noise_ik_incomplete_es = Secret(hmac_sha512(
|
||||||
&hmac_sha512(&INITIAL_KEY, alice_e_public.as_bytes()),
|
&hmac_sha512(&INITIAL_KEY, alice_e_public.as_bytes()),
|
||||||
noise_es.as_bytes(),
|
noise_es.as_bytes(),
|
||||||
));
|
));
|
||||||
|
|
||||||
// Decrypt the encrypted part of the packet payload and authenticate the above key exchange via AES-GCM auth.
|
// Decrypt the encrypted part of the packet payload and authenticate the above key exchange via AES-GCM auth.
|
||||||
let mut c = AesGcm::new(
|
let mut c = AesGcm::new(
|
||||||
kbkdf512(es_key.as_bytes(), KBKDF_KEY_USAGE_LABEL_AES_GCM_ALICE_TO_BOB).first_n::<AES_KEY_SIZE>(),
|
kbkdf512(noise_ik_incomplete_es.as_bytes(), KBKDF_KEY_USAGE_LABEL_AES_GCM_ALICE_TO_BOB).first_n::<AES_KEY_SIZE>(),
|
||||||
false,
|
false,
|
||||||
);
|
);
|
||||||
c.reset_init_gcm(canonical_header_bytes);
|
c.reset_init_gcm(canonical_header_bytes);
|
||||||
|
@ -803,14 +808,14 @@ impl<Application: ApplicationLayer> ReceiveContext<Application> {
|
||||||
.ok_or(Error::FailedAuthentication)?;
|
.ok_or(Error::FailedAuthentication)?;
|
||||||
|
|
||||||
// Mix result of 'ss' agreement into master key.
|
// Mix result of 'ss' agreement into master key.
|
||||||
let ss_key = Secret(hmac_sha512(es_key.as_bytes(), noise_ss.as_bytes()));
|
let noise_ik_incomplete_es_ss = Secret(hmac_sha512(noise_ik_incomplete_es.as_bytes(), noise_ss.as_bytes()));
|
||||||
drop(es_key);
|
drop(noise_ik_incomplete_es);
|
||||||
|
|
||||||
// Authenticate entire packet with HMAC-SHA384, verifying alice's identity via 'ss' secret that was
|
// Authenticate entire packet with HMAC-SHA384, verifying alice's identity via 'ss' secret that was
|
||||||
// just mixed into the key.
|
// just mixed into the key.
|
||||||
let hmac1 = &kex_packet[aes_gcm_tag_end..hmac1_end];
|
let hmac1 = &kex_packet[aes_gcm_tag_end..hmac1_end];
|
||||||
if !hmac_sha384_2(
|
if !hmac_sha384_2(
|
||||||
kbkdf512(ss_key.as_bytes(), KBKDF_KEY_USAGE_LABEL_HMAC).first_n::<48>(),
|
kbkdf512(noise_ik_incomplete_es_ss.as_bytes(), KBKDF_KEY_USAGE_LABEL_HMAC).first_n::<48>(),
|
||||||
canonical_header_bytes,
|
canonical_header_bytes,
|
||||||
&kex_packet_saved_ciphertext[HEADER_SIZE..aes_gcm_tag_end],
|
&kex_packet_saved_ciphertext[HEADER_SIZE..aes_gcm_tag_end],
|
||||||
)
|
)
|
||||||
|
@ -901,17 +906,19 @@ impl<Application: ApplicationLayer> ReceiveContext<Application> {
|
||||||
// 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
|
||||||
// FIPS compliant the compliance of the entire key derivation is not invalidated. Both inputs are secrets of
|
// FIPS compliant the compliance of the entire key derivation is not invalidated. Both inputs are secrets of
|
||||||
// fixed size so this shouldn't matter cryptographically.
|
// fixed size so this shouldn't matter cryptographically.
|
||||||
let noise_ik_key = Secret(hmac_sha512(
|
let noise_ik_complete = Secret(hmac_sha512(
|
||||||
session.psk.as_bytes(),
|
session.psk.as_bytes(),
|
||||||
&hmac_sha512(
|
&hmac_sha512(
|
||||||
&hmac_sha512(
|
&hmac_sha512(
|
||||||
&hmac_sha512(ss_key.as_bytes(), bob_e_keypair.public_key_bytes()),
|
&hmac_sha512(noise_ik_incomplete_es_ss.as_bytes(), bob_e_keypair.public_key_bytes()),
|
||||||
noise_ee.as_bytes(),
|
noise_ee.as_bytes(),
|
||||||
),
|
),
|
||||||
noise_se.as_bytes(),
|
noise_se.as_bytes(),
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
drop(ss_key);
|
drop(noise_ik_incomplete_es_ss);
|
||||||
|
drop(noise_ee);
|
||||||
|
drop(noise_se);
|
||||||
|
|
||||||
// At this point we've completed Noise_IK key derivation with NIST P-384 ECDH, but now for hybrid and ratcheting...
|
// At this point we've completed Noise_IK key derivation with NIST P-384 ECDH, but now for hybrid and ratcheting...
|
||||||
|
|
||||||
|
@ -972,7 +979,7 @@ impl<Application: ApplicationLayer> ReceiveContext<Application> {
|
||||||
// Encrypt reply packet using final Noise_IK key BEFORE mixing hybrid or ratcheting, since the other side
|
// Encrypt reply packet using final Noise_IK key BEFORE mixing hybrid or ratcheting, since the other side
|
||||||
// must decrypt before doing these things.
|
// must decrypt before doing these things.
|
||||||
let mut c = AesGcm::new(
|
let mut c = AesGcm::new(
|
||||||
kbkdf512(noise_ik_key.as_bytes(), KBKDF_KEY_USAGE_LABEL_AES_GCM_BOB_TO_ALICE).first_n::<AES_KEY_SIZE>(),
|
kbkdf512(noise_ik_complete.as_bytes(), KBKDF_KEY_USAGE_LABEL_AES_GCM_BOB_TO_ALICE).first_n::<AES_KEY_SIZE>(),
|
||||||
true,
|
true,
|
||||||
);
|
);
|
||||||
c.reset_init_gcm(reply_canonical_header.as_bytes());
|
c.reset_init_gcm(reply_canonical_header.as_bytes());
|
||||||
|
@ -981,8 +988,9 @@ impl<Application: ApplicationLayer> ReceiveContext<Application> {
|
||||||
|
|
||||||
idx = safe_write_all(&mut reply_buf, idx, &gcm_tag)?;
|
idx = safe_write_all(&mut reply_buf, idx, &gcm_tag)?;
|
||||||
let aes_gcm_tag_end = idx;
|
let aes_gcm_tag_end = idx;
|
||||||
|
|
||||||
// Mix ratchet key from previous session key (if any) and Kyber1024 hybrid shared key (if any).
|
// Mix ratchet key from previous session key (if any) and Kyber1024 hybrid shared key (if any).
|
||||||
let mut session_key = noise_ik_key;
|
let mut session_key = noise_ik_complete;
|
||||||
if let Some(ratchet_key) = ratchet_key {
|
if let Some(ratchet_key) = ratchet_key {
|
||||||
session_key = Secret(hmac_sha512(ratchet_key.as_bytes(), session_key.as_bytes()));
|
session_key = Secret(hmac_sha512(ratchet_key.as_bytes(), session_key.as_bytes()));
|
||||||
}
|
}
|
||||||
|
@ -1050,16 +1058,19 @@ impl<Application: ApplicationLayer> ReceiveContext<Application> {
|
||||||
let noise_ee = offer.alice_e_keypair.agree(&bob_e_public).ok_or(Error::FailedAuthentication)?;
|
let noise_ee = offer.alice_e_keypair.agree(&bob_e_public).ok_or(Error::FailedAuthentication)?;
|
||||||
let noise_se = app.get_local_s_keypair().agree(&bob_e_public).ok_or(Error::FailedAuthentication)?;
|
let noise_se = app.get_local_s_keypair().agree(&bob_e_public).ok_or(Error::FailedAuthentication)?;
|
||||||
|
|
||||||
let noise_ik_key = Secret(hmac_sha512(
|
let noise_ik_complete = Secret(hmac_sha512(
|
||||||
session.psk.as_bytes(),
|
session.psk.as_bytes(),
|
||||||
&hmac_sha512(
|
&hmac_sha512(
|
||||||
&hmac_sha512(&hmac_sha512(offer.ss_key.as_bytes(), bob_e_public.as_bytes()), noise_ee.as_bytes()),
|
&hmac_sha512(&hmac_sha512(offer.ss_key.as_bytes(), bob_e_public.as_bytes()), noise_ee.as_bytes()),
|
||||||
noise_se.as_bytes(),
|
noise_se.as_bytes(),
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
|
drop(noise_ee);
|
||||||
|
drop(noise_se);
|
||||||
|
|
||||||
let mut c = AesGcm::new(
|
let mut c = AesGcm::new(
|
||||||
kbkdf512(noise_ik_key.as_bytes(), KBKDF_KEY_USAGE_LABEL_AES_GCM_BOB_TO_ALICE).first_n::<AES_KEY_SIZE>(),
|
kbkdf512(noise_ik_complete.as_bytes(), KBKDF_KEY_USAGE_LABEL_AES_GCM_BOB_TO_ALICE)
|
||||||
|
.first_n::<AES_KEY_SIZE>(),
|
||||||
false,
|
false,
|
||||||
);
|
);
|
||||||
c.reset_init_gcm(canonical_header_bytes);
|
c.reset_init_gcm(canonical_header_bytes);
|
||||||
|
@ -1092,7 +1103,7 @@ impl<Application: ApplicationLayer> ReceiveContext<Application> {
|
||||||
|
|
||||||
// Mix ratchet key from previous session key (if any) and Kyber1024 hybrid shared key (if any).
|
// Mix ratchet key from previous session key (if any) and Kyber1024 hybrid shared key (if any).
|
||||||
let mut ratchet_count = 0;
|
let mut ratchet_count = 0;
|
||||||
let mut session_key = noise_ik_key;
|
let mut session_key = noise_ik_complete;
|
||||||
if bob_ratchet_key_id.is_some() && offer.ratchet_key.is_some() {
|
if bob_ratchet_key_id.is_some() && offer.ratchet_key.is_some() {
|
||||||
session_key = Secret(hmac_sha512(offer.ratchet_key.as_ref().unwrap().as_bytes(), session_key.as_bytes()));
|
session_key = Secret(hmac_sha512(offer.ratchet_key.as_ref().unwrap().as_bytes(), session_key.as_bytes()));
|
||||||
ratchet_count = offer.ratchet_count;
|
ratchet_count = offer.ratchet_count;
|
||||||
|
|
Loading…
Add table
Reference in a new issue