]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - net/core/secure_seq.c
tcp: switch tcp_fastopen key generation to net_get_random_once
[mirror_ubuntu-artful-kernel.git] / net / core / secure_seq.c
CommitLineData
6e5714ea
DM
1#include <linux/kernel.h>
2#include <linux/init.h>
3#include <linux/cryptohash.h>
4#include <linux/module.h>
5#include <linux/cache.h>
6#include <linux/random.h>
7#include <linux/hrtimer.h>
8#include <linux/ktime.h>
9#include <linux/string.h>
10
11#include <net/secure_seq.h>
12
9a3bab6b 13#define NET_SECRET_SIZE (MD5_MESSAGE_BYTES / 4)
6e5714ea 14
9a3bab6b
ED
15static u32 net_secret[NET_SECRET_SIZE] ____cacheline_aligned;
16
17static void net_secret_init(void)
6e5714ea 18{
9a3bab6b
ED
19 u32 tmp;
20 int i;
21
22 if (likely(net_secret[0]))
23 return;
24
25 for (i = NET_SECRET_SIZE; i > 0;) {
26 do {
27 get_random_bytes(&tmp, sizeof(tmp));
28 } while (!tmp);
29 cmpxchg(&net_secret[--i], 0, tmp);
30 }
6e5714ea 31}
6e5714ea 32
68109090 33#ifdef CONFIG_INET
6e5714ea
DM
34static u32 seq_scale(u32 seq)
35{
36 /*
37 * As close as possible to RFC 793, which
38 * suggests using a 250 kHz clock.
39 * Further reading shows this assumes 2 Mb/s networks.
40 * For 10 Mb/s Ethernet, a 1 MHz clock is appropriate.
41 * For 10 Gb/s Ethernet, a 1 GHz clock should be ok, but
42 * we also need to limit the resolution so that the u32 seq
43 * overlaps less than one time per MSL (2 minutes).
44 * Choosing a clock of 64 ns period is OK. (period of 274 s)
45 */
46 return seq + (ktime_to_ns(ktime_get_real()) >> 6);
47}
68109090 48#endif
6e5714ea 49
dfd56b8b 50#if IS_ENABLED(CONFIG_IPV6)
cf533ea5 51__u32 secure_tcpv6_sequence_number(const __be32 *saddr, const __be32 *daddr,
6e5714ea
DM
52 __be16 sport, __be16 dport)
53{
54 u32 secret[MD5_MESSAGE_BYTES / 4];
55 u32 hash[MD5_DIGEST_WORDS];
56 u32 i;
57
9a3bab6b 58 net_secret_init();
6e5714ea
DM
59 memcpy(hash, saddr, 16);
60 for (i = 0; i < 4; i++)
747465ef 61 secret[i] = net_secret[i] + (__force u32)daddr[i];
6e5714ea
DM
62 secret[4] = net_secret[4] +
63 (((__force u16)sport << 16) + (__force u16)dport);
64 for (i = 5; i < MD5_MESSAGE_BYTES / 4; i++)
65 secret[i] = net_secret[i];
66
67 md5_transform(hash, secret);
68
69 return seq_scale(hash[0]);
70}
71EXPORT_SYMBOL(secure_tcpv6_sequence_number);
72
73u32 secure_ipv6_port_ephemeral(const __be32 *saddr, const __be32 *daddr,
74 __be16 dport)
75{
76 u32 secret[MD5_MESSAGE_BYTES / 4];
77 u32 hash[MD5_DIGEST_WORDS];
78 u32 i;
79
9a3bab6b 80 net_secret_init();
6e5714ea
DM
81 memcpy(hash, saddr, 16);
82 for (i = 0; i < 4; i++)
83 secret[i] = net_secret[i] + (__force u32) daddr[i];
84 secret[4] = net_secret[4] + (__force u32)dport;
85 for (i = 5; i < MD5_MESSAGE_BYTES / 4; i++)
86 secret[i] = net_secret[i];
87
88 md5_transform(hash, secret);
89
90 return hash[0];
91}
58a317f1 92EXPORT_SYMBOL(secure_ipv6_port_ephemeral);
6e5714ea
DM
93#endif
94
95#ifdef CONFIG_INET
96__u32 secure_ip_id(__be32 daddr)
97{
98 u32 hash[MD5_DIGEST_WORDS];
99
9a3bab6b 100 net_secret_init();
6e5714ea
DM
101 hash[0] = (__force __u32) daddr;
102 hash[1] = net_secret[13];
103 hash[2] = net_secret[14];
104 hash[3] = net_secret[15];
105
106 md5_transform(hash, net_secret);
107
108 return hash[0];
109}
110
111__u32 secure_ipv6_id(const __be32 daddr[4])
112{
113 __u32 hash[4];
114
9a3bab6b 115 net_secret_init();
6e5714ea
DM
116 memcpy(hash, daddr, 16);
117 md5_transform(hash, net_secret);
118
119 return hash[0];
120}
121
122__u32 secure_tcp_sequence_number(__be32 saddr, __be32 daddr,
123 __be16 sport, __be16 dport)
124{
125 u32 hash[MD5_DIGEST_WORDS];
126
9a3bab6b 127 net_secret_init();
6e5714ea
DM
128 hash[0] = (__force u32)saddr;
129 hash[1] = (__force u32)daddr;
130 hash[2] = ((__force u16)sport << 16) + (__force u16)dport;
131 hash[3] = net_secret[15];
132
133 md5_transform(hash, net_secret);
134
135 return seq_scale(hash[0]);
136}
137
138u32 secure_ipv4_port_ephemeral(__be32 saddr, __be32 daddr, __be16 dport)
139{
140 u32 hash[MD5_DIGEST_WORDS];
141
9a3bab6b 142 net_secret_init();
6e5714ea
DM
143 hash[0] = (__force u32)saddr;
144 hash[1] = (__force u32)daddr;
145 hash[2] = (__force u32)dport ^ net_secret[14];
146 hash[3] = net_secret[15];
147
148 md5_transform(hash, net_secret);
149
150 return hash[0];
151}
152EXPORT_SYMBOL_GPL(secure_ipv4_port_ephemeral);
153#endif
154
a3bf7ae9 155#if IS_ENABLED(CONFIG_IP_DCCP)
6e5714ea
DM
156u64 secure_dccp_sequence_number(__be32 saddr, __be32 daddr,
157 __be16 sport, __be16 dport)
158{
159 u32 hash[MD5_DIGEST_WORDS];
160 u64 seq;
161
9a3bab6b 162 net_secret_init();
6e5714ea
DM
163 hash[0] = (__force u32)saddr;
164 hash[1] = (__force u32)daddr;
165 hash[2] = ((__force u16)sport << 16) + (__force u16)dport;
166 hash[3] = net_secret[15];
167
168 md5_transform(hash, net_secret);
169
170 seq = hash[0] | (((u64)hash[1]) << 32);
171 seq += ktime_to_ns(ktime_get_real());
172 seq &= (1ull << 48) - 1;
173
174 return seq;
175}
176EXPORT_SYMBOL(secure_dccp_sequence_number);
177
dfd56b8b 178#if IS_ENABLED(CONFIG_IPV6)
6e5714ea
DM
179u64 secure_dccpv6_sequence_number(__be32 *saddr, __be32 *daddr,
180 __be16 sport, __be16 dport)
181{
182 u32 secret[MD5_MESSAGE_BYTES / 4];
183 u32 hash[MD5_DIGEST_WORDS];
184 u64 seq;
185 u32 i;
186
9a3bab6b 187 net_secret_init();
6e5714ea
DM
188 memcpy(hash, saddr, 16);
189 for (i = 0; i < 4; i++)
190 secret[i] = net_secret[i] + daddr[i];
191 secret[4] = net_secret[4] +
192 (((__force u16)sport << 16) + (__force u16)dport);
193 for (i = 5; i < MD5_MESSAGE_BYTES / 4; i++)
194 secret[i] = net_secret[i];
195
196 md5_transform(hash, secret);
197
198 seq = hash[0] | (((u64)hash[1]) << 32);
199 seq += ktime_to_ns(ktime_get_real());
200 seq &= (1ull << 48) - 1;
201
202 return seq;
203}
204EXPORT_SYMBOL(secure_dccpv6_sequence_number);
205#endif
206#endif