ARM: dts: AM33XX: Add MMC support and documentation
[deliverable/linux.git] / net / core / secure_seq.c
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
This page took 0.042324 seconds and 5 git commands to generate.