Merge branch 'tetanus' of https://github.com/zerotier/ZeroTierOne into tetanus

This commit is contained in:
mamoniot 2022-12-19 10:56:35 -05:00
commit cd6f29fa82
4 changed files with 40 additions and 24 deletions

View file

@ -12,3 +12,16 @@ pub mod verified;
pub mod x25519;
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
}
}

View file

@ -49,6 +49,7 @@ impl<const ROUNDS: usize> Salsa<ROUNDS> {
}
}
#[inline]
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) = (
self.state[0],

View file

@ -19,7 +19,6 @@ pub const ED25519_SIGNATURE_SIZE: usize = 64;
pub struct X25519KeyPair(x25519_dalek::StaticSecret, Secret<32>, x25519_dalek::PublicKey);
impl X25519KeyPair {
#[inline(always)]
pub fn generate() -> X25519KeyPair {
let sk = x25519_dalek::StaticSecret::new(SecureRandom::get());
let sk2 = Secret(sk.to_bytes());
@ -96,7 +95,6 @@ impl Clone for X25519KeyPair {
pub struct Ed25519KeyPair(ed25519_dalek::Keypair, Secret<32>);
impl Ed25519KeyPair {
#[inline(always)]
pub fn generate() -> Ed25519KeyPair {
let mut rng = SecureRandom::get();
let kp = ed25519_dalek::Keypair::generate(&mut rng);

View file

@ -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::random;
use zerotier_crypto::secret::Secret;
use zerotier_crypto::secure_eq;
use zerotier_utils::gatherarray::GatherArray;
use zerotier_utils::memory;
@ -736,13 +737,14 @@ impl<Application: ApplicationLayer> ReceiveContext<Application> {
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.
if !hmac_sha384_2(
app.get_local_s_public_blob_hash(),
canonical_header_bytes,
&kex_packet[HEADER_SIZE..hmac1_end],
)
.eq(&kex_packet[hmac1_end..kex_packet_len])
{
if !secure_eq(
&hmac_sha384_2(
app.get_local_s_public_blob_hash(),
canonical_header_bytes,
&kex_packet[HEADER_SIZE..hmac1_end],
),
&kex_packet[hmac1_end..kex_packet_len],
) {
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
// just mixed into the key.
if !hmac_sha384_2(
kbkdf512(noise_ik_incomplete_es_ss.as_bytes(), KBKDF_KEY_USAGE_LABEL_HMAC).first_n::<48>(),
canonical_header_bytes,
&kex_packet_saved_ciphertext[HEADER_SIZE..aes_gcm_tag_end],
)
.eq(&kex_packet[aes_gcm_tag_end..hmac1_end])
{
if !secure_eq(
&hmac_sha384_2(
kbkdf512(noise_ik_incomplete_es_ss.as_bytes(), KBKDF_KEY_USAGE_LABEL_HMAC).first_n::<48>(),
canonical_header_bytes,
&kex_packet_saved_ciphertext[HEADER_SIZE..aes_gcm_tag_end],
),
&kex_packet[aes_gcm_tag_end..hmac1_end],
) {
return Err(Error::FailedAuthentication);
}
@ -830,7 +833,7 @@ impl<Application: ApplicationLayer> ReceiveContext<Application> {
// then create new sessions.
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.
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);
}
@ -1118,13 +1121,14 @@ impl<Application: ApplicationLayer> ReceiveContext<Application> {
}
// Check main packet HMAC for full validation of session key.
if !hmac_sha384_2(
kbkdf512(session_key.as_bytes(), KBKDF_KEY_USAGE_LABEL_HMAC).first_n::<48>(),
canonical_header_bytes,
&kex_packet_saved_ciphertext[HEADER_SIZE..aes_gcm_tag_end],
)
.eq(&kex_packet[aes_gcm_tag_end..kex_packet_len])
{
if !secure_eq(
&hmac_sha384_2(
kbkdf512(session_key.as_bytes(), KBKDF_KEY_USAGE_LABEL_HMAC).first_n::<48>(),
canonical_header_bytes,
&kex_packet_saved_ciphertext[HEADER_SIZE..aes_gcm_tag_end],
),
&kex_packet[aes_gcm_tag_end..kex_packet_len],
) {
return Err(Error::FailedAuthentication);
}