diff options
Diffstat (limited to 'net/core/secure_seq.c')
-rw-r--r-- | net/core/secure_seq.c | 29 |
1 files changed, 26 insertions, 3 deletions
diff --git a/net/core/secure_seq.c b/net/core/secure_seq.c index 6a2f13cee86a..8d9d05edd2eb 100644 --- a/net/core/secure_seq.c +++ b/net/core/secure_seq.c | |||
@@ -10,12 +10,27 @@ | |||
10 | 10 | ||
11 | #include <net/secure_seq.h> | 11 | #include <net/secure_seq.h> |
12 | 12 | ||
13 | static u32 net_secret[MD5_MESSAGE_BYTES / 4] ____cacheline_aligned; | 13 | #if IS_ENABLED(CONFIG_IPV6) || IS_ENABLED(CONFIG_INET) |
14 | #define NET_SECRET_SIZE (MD5_MESSAGE_BYTES / 4) | ||
14 | 15 | ||
15 | void net_secret_init(void) | 16 | static u32 net_secret[NET_SECRET_SIZE] ____cacheline_aligned; |
17 | |||
18 | static void net_secret_init(void) | ||
16 | { | 19 | { |
17 | get_random_bytes(net_secret, sizeof(net_secret)); | 20 | u32 tmp; |
21 | int i; | ||
22 | |||
23 | if (likely(net_secret[0])) | ||
24 | return; | ||
25 | |||
26 | for (i = NET_SECRET_SIZE; i > 0;) { | ||
27 | do { | ||
28 | get_random_bytes(&tmp, sizeof(tmp)); | ||
29 | } while (!tmp); | ||
30 | cmpxchg(&net_secret[--i], 0, tmp); | ||
31 | } | ||
18 | } | 32 | } |
33 | #endif | ||
19 | 34 | ||
20 | #ifdef CONFIG_INET | 35 | #ifdef CONFIG_INET |
21 | static u32 seq_scale(u32 seq) | 36 | static u32 seq_scale(u32 seq) |
@@ -42,6 +57,7 @@ __u32 secure_tcpv6_sequence_number(const __be32 *saddr, const __be32 *daddr, | |||
42 | u32 hash[MD5_DIGEST_WORDS]; | 57 | u32 hash[MD5_DIGEST_WORDS]; |
43 | u32 i; | 58 | u32 i; |
44 | 59 | ||
60 | net_secret_init(); | ||
45 | memcpy(hash, saddr, 16); | 61 | memcpy(hash, saddr, 16); |
46 | for (i = 0; i < 4; i++) | 62 | for (i = 0; i < 4; i++) |
47 | secret[i] = net_secret[i] + (__force u32)daddr[i]; | 63 | secret[i] = net_secret[i] + (__force u32)daddr[i]; |
@@ -63,6 +79,7 @@ u32 secure_ipv6_port_ephemeral(const __be32 *saddr, const __be32 *daddr, | |||
63 | u32 hash[MD5_DIGEST_WORDS]; | 79 | u32 hash[MD5_DIGEST_WORDS]; |
64 | u32 i; | 80 | u32 i; |
65 | 81 | ||
82 | net_secret_init(); | ||
66 | memcpy(hash, saddr, 16); | 83 | memcpy(hash, saddr, 16); |
67 | for (i = 0; i < 4; i++) | 84 | for (i = 0; i < 4; i++) |
68 | secret[i] = net_secret[i] + (__force u32) daddr[i]; | 85 | secret[i] = net_secret[i] + (__force u32) daddr[i]; |
@@ -82,6 +99,7 @@ __u32 secure_ip_id(__be32 daddr) | |||
82 | { | 99 | { |
83 | u32 hash[MD5_DIGEST_WORDS]; | 100 | u32 hash[MD5_DIGEST_WORDS]; |
84 | 101 | ||
102 | net_secret_init(); | ||
85 | hash[0] = (__force __u32) daddr; | 103 | hash[0] = (__force __u32) daddr; |
86 | hash[1] = net_secret[13]; | 104 | hash[1] = net_secret[13]; |
87 | hash[2] = net_secret[14]; | 105 | hash[2] = net_secret[14]; |
@@ -96,6 +114,7 @@ __u32 secure_ipv6_id(const __be32 daddr[4]) | |||
96 | { | 114 | { |
97 | __u32 hash[4]; | 115 | __u32 hash[4]; |
98 | 116 | ||
117 | net_secret_init(); | ||
99 | memcpy(hash, daddr, 16); | 118 | memcpy(hash, daddr, 16); |
100 | md5_transform(hash, net_secret); | 119 | md5_transform(hash, net_secret); |
101 | 120 | ||
@@ -107,6 +126,7 @@ __u32 secure_tcp_sequence_number(__be32 saddr, __be32 daddr, | |||
107 | { | 126 | { |
108 | u32 hash[MD5_DIGEST_WORDS]; | 127 | u32 hash[MD5_DIGEST_WORDS]; |
109 | 128 | ||
129 | net_secret_init(); | ||
110 | hash[0] = (__force u32)saddr; | 130 | hash[0] = (__force u32)saddr; |
111 | hash[1] = (__force u32)daddr; | 131 | hash[1] = (__force u32)daddr; |
112 | hash[2] = ((__force u16)sport << 16) + (__force u16)dport; | 132 | hash[2] = ((__force u16)sport << 16) + (__force u16)dport; |
@@ -121,6 +141,7 @@ u32 secure_ipv4_port_ephemeral(__be32 saddr, __be32 daddr, __be16 dport) | |||
121 | { | 141 | { |
122 | u32 hash[MD5_DIGEST_WORDS]; | 142 | u32 hash[MD5_DIGEST_WORDS]; |
123 | 143 | ||
144 | net_secret_init(); | ||
124 | hash[0] = (__force u32)saddr; | 145 | hash[0] = (__force u32)saddr; |
125 | hash[1] = (__force u32)daddr; | 146 | hash[1] = (__force u32)daddr; |
126 | hash[2] = (__force u32)dport ^ net_secret[14]; | 147 | hash[2] = (__force u32)dport ^ net_secret[14]; |
@@ -140,6 +161,7 @@ u64 secure_dccp_sequence_number(__be32 saddr, __be32 daddr, | |||
140 | u32 hash[MD5_DIGEST_WORDS]; | 161 | u32 hash[MD5_DIGEST_WORDS]; |
141 | u64 seq; | 162 | u64 seq; |
142 | 163 | ||
164 | net_secret_init(); | ||
143 | hash[0] = (__force u32)saddr; | 165 | hash[0] = (__force u32)saddr; |
144 | hash[1] = (__force u32)daddr; | 166 | hash[1] = (__force u32)daddr; |
145 | hash[2] = ((__force u16)sport << 16) + (__force u16)dport; | 167 | hash[2] = ((__force u16)sport << 16) + (__force u16)dport; |
@@ -164,6 +186,7 @@ u64 secure_dccpv6_sequence_number(__be32 *saddr, __be32 *daddr, | |||
164 | u64 seq; | 186 | u64 seq; |
165 | u32 i; | 187 | u32 i; |
166 | 188 | ||
189 | net_secret_init(); | ||
167 | memcpy(hash, saddr, 16); | 190 | memcpy(hash, saddr, 16); |
168 | for (i = 0; i < 4; i++) | 191 | for (i = 0; i < 4; i++) |
169 | secret[i] = net_secret[i] + daddr[i]; | 192 | secret[i] = net_secret[i] + daddr[i]; |