mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-06-07 21:13:44 +02:00
Merge branch 'tetanus' of https://github.com/zerotier/ZeroTierOne into tetanus
This commit is contained in:
commit
cd6f29fa82
4 changed files with 40 additions and 24 deletions
|
@ -12,3 +12,16 @@ pub mod verified;
|
||||||
pub mod x25519;
|
pub mod x25519;
|
||||||
|
|
||||||
pub const ZEROES: [u8; 64] = [0_u8; 64];
|
pub const ZEROES: [u8; 64] = [0_u8; 64];
|
||||||
|
|
||||||
|
/// Constant time byte slice equality.
|
||||||
|
pub fn secure_eq(a: &[u8], b: &[u8]) -> bool {
|
||||||
|
if a.len() == b.len() {
|
||||||
|
let mut x = 0u8;
|
||||||
|
for (aa, bb) in a.iter().zip(b.iter()) {
|
||||||
|
x |= *aa ^ *bb;
|
||||||
|
}
|
||||||
|
x == 0
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -49,6 +49,7 @@ impl<const ROUNDS: usize> Salsa<ROUNDS> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn crypt(&mut self, mut plaintext: &[u8], mut ciphertext: &mut [u8]) {
|
pub fn crypt(&mut self, mut plaintext: &[u8], mut ciphertext: &mut [u8]) {
|
||||||
let (j0, j1, j2, j3, j4, j5, j6, j7, mut j8, mut j9, j10, j11, j12, j13, j14, j15) = (
|
let (j0, j1, j2, j3, j4, j5, j6, j7, mut j8, mut j9, j10, j11, j12, j13, j14, j15) = (
|
||||||
self.state[0],
|
self.state[0],
|
||||||
|
|
|
@ -19,7 +19,6 @@ pub const ED25519_SIGNATURE_SIZE: usize = 64;
|
||||||
pub struct X25519KeyPair(x25519_dalek::StaticSecret, Secret<32>, x25519_dalek::PublicKey);
|
pub struct X25519KeyPair(x25519_dalek::StaticSecret, Secret<32>, x25519_dalek::PublicKey);
|
||||||
|
|
||||||
impl X25519KeyPair {
|
impl X25519KeyPair {
|
||||||
#[inline(always)]
|
|
||||||
pub fn generate() -> X25519KeyPair {
|
pub fn generate() -> X25519KeyPair {
|
||||||
let sk = x25519_dalek::StaticSecret::new(SecureRandom::get());
|
let sk = x25519_dalek::StaticSecret::new(SecureRandom::get());
|
||||||
let sk2 = Secret(sk.to_bytes());
|
let sk2 = Secret(sk.to_bytes());
|
||||||
|
@ -96,7 +95,6 @@ impl Clone for X25519KeyPair {
|
||||||
pub struct Ed25519KeyPair(ed25519_dalek::Keypair, Secret<32>);
|
pub struct Ed25519KeyPair(ed25519_dalek::Keypair, Secret<32>);
|
||||||
|
|
||||||
impl Ed25519KeyPair {
|
impl Ed25519KeyPair {
|
||||||
#[inline(always)]
|
|
||||||
pub fn generate() -> Ed25519KeyPair {
|
pub fn generate() -> Ed25519KeyPair {
|
||||||
let mut rng = SecureRandom::get();
|
let mut rng = SecureRandom::get();
|
||||||
let kp = ed25519_dalek::Keypair::generate(&mut rng);
|
let kp = ed25519_dalek::Keypair::generate(&mut rng);
|
||||||
|
|
|
@ -10,6 +10,7 @@ use zerotier_crypto::hash::{hmac_sha512, HMACSHA384, SHA384};
|
||||||
use zerotier_crypto::p384::{P384KeyPair, P384PublicKey, P384_PUBLIC_KEY_SIZE};
|
use zerotier_crypto::p384::{P384KeyPair, P384PublicKey, P384_PUBLIC_KEY_SIZE};
|
||||||
use zerotier_crypto::random;
|
use zerotier_crypto::random;
|
||||||
use zerotier_crypto::secret::Secret;
|
use zerotier_crypto::secret::Secret;
|
||||||
|
use zerotier_crypto::secure_eq;
|
||||||
|
|
||||||
use zerotier_utils::gatherarray::GatherArray;
|
use zerotier_utils::gatherarray::GatherArray;
|
||||||
use zerotier_utils::memory;
|
use zerotier_utils::memory;
|
||||||
|
@ -736,13 +737,14 @@ impl<Application: ApplicationLayer> ReceiveContext<Application> {
|
||||||
let hmac1_end = kex_packet_len - HMAC_SIZE;
|
let hmac1_end = kex_packet_len - HMAC_SIZE;
|
||||||
|
|
||||||
// Check the secondary HMAC first, which proves that the sender knows the recipient's full static identity.
|
// Check the secondary HMAC first, which proves that the sender knows the recipient's full static identity.
|
||||||
if !hmac_sha384_2(
|
if !secure_eq(
|
||||||
app.get_local_s_public_blob_hash(),
|
&hmac_sha384_2(
|
||||||
canonical_header_bytes,
|
app.get_local_s_public_blob_hash(),
|
||||||
&kex_packet[HEADER_SIZE..hmac1_end],
|
canonical_header_bytes,
|
||||||
)
|
&kex_packet[HEADER_SIZE..hmac1_end],
|
||||||
.eq(&kex_packet[hmac1_end..kex_packet_len])
|
),
|
||||||
{
|
&kex_packet[hmac1_end..kex_packet_len],
|
||||||
|
) {
|
||||||
return Err(Error::FailedAuthentication);
|
return Err(Error::FailedAuthentication);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -814,13 +816,14 @@ impl<Application: ApplicationLayer> ReceiveContext<Application> {
|
||||||
|
|
||||||
// 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.
|
||||||
if !hmac_sha384_2(
|
if !secure_eq(
|
||||||
kbkdf512(noise_ik_incomplete_es_ss.as_bytes(), KBKDF_KEY_USAGE_LABEL_HMAC).first_n::<48>(),
|
&hmac_sha384_2(
|
||||||
canonical_header_bytes,
|
kbkdf512(noise_ik_incomplete_es_ss.as_bytes(), KBKDF_KEY_USAGE_LABEL_HMAC).first_n::<48>(),
|
||||||
&kex_packet_saved_ciphertext[HEADER_SIZE..aes_gcm_tag_end],
|
canonical_header_bytes,
|
||||||
)
|
&kex_packet_saved_ciphertext[HEADER_SIZE..aes_gcm_tag_end],
|
||||||
.eq(&kex_packet[aes_gcm_tag_end..hmac1_end])
|
),
|
||||||
{
|
&kex_packet[aes_gcm_tag_end..hmac1_end],
|
||||||
|
) {
|
||||||
return Err(Error::FailedAuthentication);
|
return Err(Error::FailedAuthentication);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -830,7 +833,7 @@ impl<Application: ApplicationLayer> ReceiveContext<Application> {
|
||||||
// then create new sessions.
|
// then create new sessions.
|
||||||
let (new_session, ratchet_key, last_ratchet_count) = if let Some(session) = session.as_ref() {
|
let (new_session, ratchet_key, last_ratchet_count) = if let Some(session) = session.as_ref() {
|
||||||
// Existing session identity must match the one in this offer.
|
// Existing session identity must match the one in this offer.
|
||||||
if !session.remote_s_public_blob_hash.eq(&SHA384::hash(&alice_s_public_blob)) {
|
if !secure_eq(&session.remote_s_public_blob_hash, &SHA384::hash(&alice_s_public_blob)) {
|
||||||
return Err(Error::FailedAuthentication);
|
return Err(Error::FailedAuthentication);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1118,13 +1121,14 @@ impl<Application: ApplicationLayer> ReceiveContext<Application> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check main packet HMAC for full validation of session key.
|
// Check main packet HMAC for full validation of session key.
|
||||||
if !hmac_sha384_2(
|
if !secure_eq(
|
||||||
kbkdf512(session_key.as_bytes(), KBKDF_KEY_USAGE_LABEL_HMAC).first_n::<48>(),
|
&hmac_sha384_2(
|
||||||
canonical_header_bytes,
|
kbkdf512(session_key.as_bytes(), KBKDF_KEY_USAGE_LABEL_HMAC).first_n::<48>(),
|
||||||
&kex_packet_saved_ciphertext[HEADER_SIZE..aes_gcm_tag_end],
|
canonical_header_bytes,
|
||||||
)
|
&kex_packet_saved_ciphertext[HEADER_SIZE..aes_gcm_tag_end],
|
||||||
.eq(&kex_packet[aes_gcm_tag_end..kex_packet_len])
|
),
|
||||||
{
|
&kex_packet[aes_gcm_tag_end..kex_packet_len],
|
||||||
|
) {
|
||||||
return Err(Error::FailedAuthentication);
|
return Err(Error::FailedAuthentication);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue