aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src/noise.c
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2017-03-30 15:28:57 +0200
committerJason A. Donenfeld <Jason@zx2c4.com>2017-03-30 15:58:30 +0200
commitba631f262d929bba3a77f470a21c6ada45eadf3c (patch)
tree19bfb0bb69c999a3e67326e0510cd063dd2a8b5c /src/noise.c
parentconfig: do not allow peers with public keys the same as the interface (diff)
downloadwireguard-monolithic-historical-ba631f262d929bba3a77f470a21c6ada45eadf3c.tar.xz
wireguard-monolithic-historical-ba631f262d929bba3a77f470a21c6ada45eadf3c.zip
curve25519: protect against potential invalid point attacks
Diffstat (limited to 'src/noise.c')
-rw-r--r--src/noise.c39
1 files changed, 25 insertions, 14 deletions
diff --git a/src/noise.c b/src/noise.c
index 0ffffd7..608a175 100644
--- a/src/noise.c
+++ b/src/noise.c
@@ -189,8 +189,7 @@ void noise_set_static_identity_private_key(struct noise_static_identity *static_
down_write(&static_identity->lock);
if (private_key) {
memcpy(static_identity->static_private, private_key, NOISE_PUBLIC_KEY_LEN);
- curve25519_generate_public(static_identity->static_public, private_key);
- static_identity->has_identity = true;
+ static_identity->has_identity = curve25519_generate_public(static_identity->static_public, private_key);
} else {
memset(static_identity->static_private, 0, NOISE_PUBLIC_KEY_LEN);
memset(static_identity->static_public, 0, NOISE_PUBLIC_KEY_LEN);
@@ -263,13 +262,15 @@ static void mix_key(u8 key[NOISE_SYMMETRIC_KEY_LEN], u8 chaining_key[NOISE_HASH_
kdf(chaining_key, key, src, NOISE_HASH_LEN, NOISE_SYMMETRIC_KEY_LEN, src_len, chaining_key);
}
-static void mix_dh(u8 key[NOISE_SYMMETRIC_KEY_LEN], u8 chaining_key[NOISE_HASH_LEN],
+static __must_check bool mix_dh(u8 key[NOISE_SYMMETRIC_KEY_LEN], u8 chaining_key[NOISE_HASH_LEN],
const u8 private[NOISE_PUBLIC_KEY_LEN], const u8 public[NOISE_PUBLIC_KEY_LEN])
{
u8 dh_calculation[NOISE_PUBLIC_KEY_LEN];
- curve25519(dh_calculation, private, public);
+ if (unlikely(!curve25519(dh_calculation, private, public)))
+ return false;
mix_key(key, chaining_key, dh_calculation, NOISE_PUBLIC_KEY_LEN);
memzero_explicit(dh_calculation, NOISE_PUBLIC_KEY_LEN);
+ return true;
}
static void mix_hash(u8 hash[NOISE_HASH_LEN], const u8 *src, size_t src_len)
@@ -346,20 +347,23 @@ bool noise_handshake_create_initiation(struct message_handshake_initiation *dst,
/* e */
curve25519_generate_secret(handshake->ephemeral_private);
- curve25519_generate_public(handshake->ephemeral_public, handshake->ephemeral_private);
+ if (!curve25519_generate_public(handshake->ephemeral_public, handshake->ephemeral_private))
+ goto out;
handshake_nocrypt(dst->unencrypted_ephemeral, handshake->ephemeral_public, NOISE_PUBLIC_KEY_LEN, handshake->hash);
if (handshake->static_identity->has_psk)
mix_key(handshake->key, handshake->chaining_key, handshake->ephemeral_public, NOISE_PUBLIC_KEY_LEN);
/* es */
- mix_dh(handshake->key, handshake->chaining_key, handshake->ephemeral_private, handshake->remote_static);
+ if (!mix_dh(handshake->key, handshake->chaining_key, handshake->ephemeral_private, handshake->remote_static))
+ goto out;
/* s */
if (!handshake_encrypt(dst->encrypted_static, handshake->static_identity->static_public, NOISE_PUBLIC_KEY_LEN, handshake->key, handshake->hash))
goto out;
/* ss */
- mix_dh(handshake->key, handshake->chaining_key, handshake->static_identity->static_private, handshake->remote_static);
+ if (!mix_dh(handshake->key, handshake->chaining_key, handshake->static_identity->static_private, handshake->remote_static))
+ goto out;
/* t */
tai64n_now(timestamp);
@@ -402,14 +406,16 @@ struct wireguard_peer *noise_handshake_consume_initiation(struct message_handsha
mix_key(key, chaining_key, e, NOISE_PUBLIC_KEY_LEN);
/* es */
- mix_dh(key, chaining_key, wg->static_identity.static_private, e);
+ if (!mix_dh(key, chaining_key, wg->static_identity.static_private, e))
+ goto out;
/* s */
if (!handshake_decrypt(s, src->encrypted_static, sizeof(src->encrypted_static), key, hash))
goto out;
/* ss */
- mix_dh(key, chaining_key, wg->static_identity.static_private, s);
+ if (!mix_dh(key, chaining_key, wg->static_identity.static_private, s))
+ goto out;
/* t */
if (!handshake_decrypt(t, src->encrypted_timestamp, sizeof(src->encrypted_timestamp), key, hash))
@@ -464,16 +470,19 @@ bool noise_handshake_create_response(struct message_handshake_response *dst, str
/* e */
curve25519_generate_secret(handshake->ephemeral_private);
- curve25519_generate_public(handshake->ephemeral_public, handshake->ephemeral_private);
+ if (!curve25519_generate_public(handshake->ephemeral_public, handshake->ephemeral_private))
+ goto out;
handshake_nocrypt(dst->unencrypted_ephemeral, handshake->ephemeral_public, NOISE_PUBLIC_KEY_LEN, handshake->hash);
if (handshake->static_identity->has_psk)
mix_key(handshake->key, handshake->chaining_key, handshake->ephemeral_public, NOISE_PUBLIC_KEY_LEN);
/* ee */
- mix_dh(handshake->key, handshake->chaining_key, handshake->ephemeral_private, handshake->remote_ephemeral);
+ if (!mix_dh(handshake->key, handshake->chaining_key, handshake->ephemeral_private, handshake->remote_ephemeral))
+ goto out;
/* se */
- mix_dh(handshake->key, handshake->chaining_key, handshake->ephemeral_private, handshake->remote_static);
+ if (!mix_dh(handshake->key, handshake->chaining_key, handshake->ephemeral_private, handshake->remote_static))
+ goto out;
if (!handshake_encrypt(dst->encrypted_nothing, NULL, 0, handshake->key, handshake->hash))
goto out;
@@ -527,10 +536,12 @@ struct wireguard_peer *noise_handshake_consume_response(struct message_handshake
mix_key(key, chaining_key, e, NOISE_PUBLIC_KEY_LEN);
/* ee */
- mix_dh(key, chaining_key, ephemeral_private, e);
+ if (!mix_dh(key, chaining_key, ephemeral_private, e))
+ goto out;
/* se */
- mix_dh(key, chaining_key, wg->static_identity.static_private, e);
+ if (!mix_dh(key, chaining_key, wg->static_identity.static_private, e))
+ goto out;
/* decrypt nothing */
if (!handshake_decrypt(NULL, src->encrypted_nothing, sizeof(src->encrypted_nothing), key, hash))