xref: /openbmc/linux/net/core/secure_seq.c (revision e23feb16)
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 
13 #define NET_SECRET_SIZE (MD5_MESSAGE_BYTES / 4)
14 
15 static u32 net_secret[NET_SECRET_SIZE] ____cacheline_aligned;
16 
17 static void net_secret_init(void)
18 {
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 	}
31 }
32 
33 #ifdef CONFIG_INET
34 static 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 }
48 #endif
49 
50 #if IS_ENABLED(CONFIG_IPV6)
51 __u32 secure_tcpv6_sequence_number(const __be32 *saddr, const __be32 *daddr,
52 				   __be16 sport, __be16 dport)
53 {
54 	u32 secret[MD5_MESSAGE_BYTES / 4];
55 	u32 hash[MD5_DIGEST_WORDS];
56 	u32 i;
57 
58 	net_secret_init();
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];
66 
67 	md5_transform(hash, secret);
68 
69 	return seq_scale(hash[0]);
70 }
71 EXPORT_SYMBOL(secure_tcpv6_sequence_number);
72 
73 u32 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 
80 	net_secret_init();
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 }
92 EXPORT_SYMBOL(secure_ipv6_port_ephemeral);
93 #endif
94 
95 #ifdef CONFIG_INET
96 __u32 secure_ip_id(__be32 daddr)
97 {
98 	u32 hash[MD5_DIGEST_WORDS];
99 
100 	net_secret_init();
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 
115 	net_secret_init();
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 
127 	net_secret_init();
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 
138 u32 secure_ipv4_port_ephemeral(__be32 saddr, __be32 daddr, __be16 dport)
139 {
140 	u32 hash[MD5_DIGEST_WORDS];
141 
142 	net_secret_init();
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 }
152 EXPORT_SYMBOL_GPL(secure_ipv4_port_ephemeral);
153 #endif
154 
155 #if IS_ENABLED(CONFIG_IP_DCCP)
156 u64 secure_dccp_sequence_number(__be32 saddr, __be32 daddr,
157 				__be16 sport, __be16 dport)
158 {
159 	u32 hash[MD5_DIGEST_WORDS];
160 	u64 seq;
161 
162 	net_secret_init();
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 }
176 EXPORT_SYMBOL(secure_dccp_sequence_number);
177 
178 #if IS_ENABLED(CONFIG_IPV6)
179 u64 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 
187 	net_secret_init();
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 }
204 EXPORT_SYMBOL(secure_dccpv6_sequence_number);
205 #endif
206 #endif
207