summaryrefslogtreecommitdiff
blob: 0b5803c839d628dced40b3c0571cfae3e6399e61 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
From 401294f7526de40a15c06997fceae58278807d22 Mon Sep 17 00:00:00 2001
From: "Jason A. Donenfeld" <Jason@zx2c4.com>
Date: Mon, 12 Jun 2017 16:32:59 +0200
Subject: [PATCH] random: wait for random bytes when generating nonces and
 ephemerals

We can let userspace configure wireguard interfaces before the RNG is
fully initialized, since what we mostly care about is having good
randomness for ephemerals and xchacha nonces. By deferring the wait to
actually asking for the randomness, we give a lot more opportunity for
gathering entropy. This won't cover entropy for hash table secrets or
cookie secrets (which rotate anyway), but those have far less
catastrophic failure modes, so ensuring good randomness for elliptic
curve points and nonces should be sufficient.
---
 src/compat/compat.h     | 10 ++++++++++
 src/config.c            |  5 -----
 src/cookie.c            |  2 +-
 src/crypto/curve25519.c |  2 +-
 4 files changed, 12 insertions(+), 7 deletions(-)

diff --git a/src/compat/compat.h b/src/compat/compat.h
index 68d62b9..6c1bfa3 100644
--- a/src/compat/compat.h
+++ b/src/compat/compat.h
@@ -265,6 +265,16 @@ static inline int wait_for_random_bytes(void)
 	return 0;
 }
 #endif
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0)
+static inline int get_random_bytes_wait(void *buf, int nbytes)
+{
+	int ret = wait_for_random_bytes();
+	if (unlikely(ret))
+		return ret;
+	get_random_bytes(buf, nbytes);
+	return 0;
+}
+#endif
 
 /* https://lkml.org/lkml/2015/6/12/415 */
 #include <linux/netdevice.h>
diff --git a/src/config.c b/src/config.c
index 286c874..d3b6611 100644
--- a/src/config.c
+++ b/src/config.c
@@ -8,7 +8,6 @@
 #include "hashtables.h"
 #include "peer.h"
 #include "uapi.h"
-#include <linux/random.h>
 
 static int set_device_port(struct wireguard_device *wg, u16 port)
 {
@@ -135,10 +134,6 @@ int config_set_device(struct wireguard_device *wg, void __user *user_device)
 	void __user *user_peer;
 	bool modified_static_identity = false;
 
-	/* It's important that the Linux RNG is fully seeded before we let the user
-	 * actually configure the device, so that we're assured to have good ephemerals. */
-	wait_for_random_bytes();
-
 	BUILD_BUG_ON(WG_KEY_LEN != NOISE_PUBLIC_KEY_LEN);
 	BUILD_BUG_ON(WG_KEY_LEN != NOISE_SYMMETRIC_KEY_LEN);
 
diff --git a/src/cookie.c b/src/cookie.c
index 21b7c7b..ce22b53 100644
--- a/src/cookie.c
+++ b/src/cookie.c
@@ -161,7 +161,7 @@ void cookie_message_create(struct message_handshake_cookie *dst, struct sk_buff
 
 	dst->header.type = cpu_to_le32(MESSAGE_HANDSHAKE_COOKIE);
 	dst->receiver_index = index;
-	get_random_bytes(dst->nonce, COOKIE_NONCE_LEN);
+	get_random_bytes_wait(dst->nonce, COOKIE_NONCE_LEN);
 
 	make_cookie(cookie, skb, checker);
 	xchacha20poly1305_encrypt(dst->encrypted_cookie, cookie, COOKIE_LEN, macs->mac1, COOKIE_LEN, dst->nonce, checker->cookie_encryption_key);
diff --git a/src/crypto/curve25519.c b/src/crypto/curve25519.c
index f0e045e..119d41a 100644
--- a/src/crypto/curve25519.c
+++ b/src/crypto/curve25519.c
@@ -1545,7 +1545,7 @@ bool curve25519_generate_public(u8 pub[CURVE25519_POINT_SIZE], const u8 secret[C
 
 void curve25519_generate_secret(u8 secret[CURVE25519_POINT_SIZE])
 {
-	get_random_bytes(secret, CURVE25519_POINT_SIZE);
+	get_random_bytes_wait(secret, CURVE25519_POINT_SIZE);
 	normalize_secret(secret);
 }
 
-- 
2.13.1