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>
11 #include <net/secure_seq.h>
13 #define NET_SECRET_SIZE (MD5_MESSAGE_BYTES / 4)
15 static u32 net_secret[NET_SECRET_SIZE] ____cacheline_aligned;
17 static void net_secret_init(void)
22 if (likely(net_secret[0]))
25 for (i = NET_SECRET_SIZE; i > 0;) {
27 get_random_bytes(&tmp, sizeof(tmp));
29 cmpxchg(&net_secret[--i], 0, tmp);
34 static u32 seq_scale(u32 seq)
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)
46 return seq + (ktime_to_ns(ktime_get_real()) >> 6);
50 #if IS_ENABLED(CONFIG_IPV6)
51 __u32 secure_tcpv6_sequence_number(const __be32 *saddr, const __be32 *daddr,
52 __be16 sport, __be16 dport)
54 u32 secret[MD5_MESSAGE_BYTES / 4];
55 u32 hash[MD5_DIGEST_WORDS];
59 memcpy(hash, saddr, 16);
60 for (i = 0; i < 4; i++)
61 secret[i] = net_secret[i] + (__force u32)daddr[i];
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];
67 md5_transform(hash, secret);
69 return seq_scale(hash[0]);
71 EXPORT_SYMBOL(secure_tcpv6_sequence_number);
73 u32 secure_ipv6_port_ephemeral(const __be32 *saddr, const __be32 *daddr,
76 u32 secret[MD5_MESSAGE_BYTES / 4];
77 u32 hash[MD5_DIGEST_WORDS];
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];
88 md5_transform(hash, secret);
92 EXPORT_SYMBOL(secure_ipv6_port_ephemeral);
96 __u32 secure_ip_id(__be32 daddr)
98 u32 hash[MD5_DIGEST_WORDS];
101 hash[0] = (__force __u32) daddr;
102 hash[1] = net_secret[13];
103 hash[2] = net_secret[14];
104 hash[3] = net_secret[15];
106 md5_transform(hash, net_secret);
111 __u32 secure_ipv6_id(const __be32 daddr[4])
116 memcpy(hash, daddr, 16);
117 md5_transform(hash, net_secret);
122 __u32 secure_tcp_sequence_number(__be32 saddr, __be32 daddr,
123 __be16 sport, __be16 dport)
125 u32 hash[MD5_DIGEST_WORDS];
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];
133 md5_transform(hash, net_secret);
135 return seq_scale(hash[0]);
138 u32 secure_ipv4_port_ephemeral(__be32 saddr, __be32 daddr, __be16 dport)
140 u32 hash[MD5_DIGEST_WORDS];
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];
148 md5_transform(hash, net_secret);
152 EXPORT_SYMBOL_GPL(secure_ipv4_port_ephemeral);
155 #if IS_ENABLED(CONFIG_IP_DCCP)
156 u64 secure_dccp_sequence_number(__be32 saddr, __be32 daddr,
157 __be16 sport, __be16 dport)
159 u32 hash[MD5_DIGEST_WORDS];
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];
168 md5_transform(hash, net_secret);
170 seq = hash[0] | (((u64)hash[1]) << 32);
171 seq += ktime_to_ns(ktime_get_real());
172 seq &= (1ull << 48) - 1;
176 EXPORT_SYMBOL(secure_dccp_sequence_number);
178 #if IS_ENABLED(CONFIG_IPV6)
179 u64 secure_dccpv6_sequence_number(__be32 *saddr, __be32 *daddr,
180 __be16 sport, __be16 dport)
182 u32 secret[MD5_MESSAGE_BYTES / 4];
183 u32 hash[MD5_DIGEST_WORDS];
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];
196 md5_transform(hash, secret);
198 seq = hash[0] | (((u64)hash[1]) << 32);
199 seq += ktime_to_ns(ktime_get_real());
200 seq &= (1ull << 48) - 1;
204 EXPORT_SYMBOL(secure_dccpv6_sequence_number);