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 #if IS_ENABLED(CONFIG_IPV6) || IS_ENABLED(CONFIG_INET)
14 #define NET_SECRET_SIZE (MD5_MESSAGE_BYTES / 4)
16 static u32 net_secret
[NET_SECRET_SIZE
] ____cacheline_aligned
;
18 static void net_secret_init(void)
23 if (likely(net_secret
[0]))
26 for (i
= NET_SECRET_SIZE
; i
> 0;) {
28 get_random_bytes(&tmp
, sizeof(tmp
));
30 cmpxchg(&net_secret
[--i
], 0, tmp
);
36 static u32
seq_scale(u32 seq
)
39 * As close as possible to RFC 793, which
40 * suggests using a 250 kHz clock.
41 * Further reading shows this assumes 2 Mb/s networks.
42 * For 10 Mb/s Ethernet, a 1 MHz clock is appropriate.
43 * For 10 Gb/s Ethernet, a 1 GHz clock should be ok, but
44 * we also need to limit the resolution so that the u32 seq
45 * overlaps less than one time per MSL (2 minutes).
46 * Choosing a clock of 64 ns period is OK. (period of 274 s)
48 return seq
+ (ktime_to_ns(ktime_get_real()) >> 6);
52 #if IS_ENABLED(CONFIG_IPV6)
53 __u32
secure_tcpv6_sequence_number(const __be32
*saddr
, const __be32
*daddr
,
54 __be16 sport
, __be16 dport
)
56 u32 secret
[MD5_MESSAGE_BYTES
/ 4];
57 u32 hash
[MD5_DIGEST_WORDS
];
61 memcpy(hash
, saddr
, 16);
62 for (i
= 0; i
< 4; i
++)
63 secret
[i
] = net_secret
[i
] + (__force u32
)daddr
[i
];
64 secret
[4] = net_secret
[4] +
65 (((__force u16
)sport
<< 16) + (__force u16
)dport
);
66 for (i
= 5; i
< MD5_MESSAGE_BYTES
/ 4; i
++)
67 secret
[i
] = net_secret
[i
];
69 md5_transform(hash
, secret
);
71 return seq_scale(hash
[0]);
73 EXPORT_SYMBOL(secure_tcpv6_sequence_number
);
75 u32
secure_ipv6_port_ephemeral(const __be32
*saddr
, const __be32
*daddr
,
78 u32 secret
[MD5_MESSAGE_BYTES
/ 4];
79 u32 hash
[MD5_DIGEST_WORDS
];
83 memcpy(hash
, saddr
, 16);
84 for (i
= 0; i
< 4; i
++)
85 secret
[i
] = net_secret
[i
] + (__force u32
) daddr
[i
];
86 secret
[4] = net_secret
[4] + (__force u32
)dport
;
87 for (i
= 5; i
< MD5_MESSAGE_BYTES
/ 4; i
++)
88 secret
[i
] = net_secret
[i
];
90 md5_transform(hash
, secret
);
94 EXPORT_SYMBOL(secure_ipv6_port_ephemeral
);
99 __u32
secure_tcp_sequence_number(__be32 saddr
, __be32 daddr
,
100 __be16 sport
, __be16 dport
)
102 u32 hash
[MD5_DIGEST_WORDS
];
105 hash
[0] = (__force u32
)saddr
;
106 hash
[1] = (__force u32
)daddr
;
107 hash
[2] = ((__force u16
)sport
<< 16) + (__force u16
)dport
;
108 hash
[3] = net_secret
[15];
110 md5_transform(hash
, net_secret
);
112 return seq_scale(hash
[0]);
115 u32
secure_ipv4_port_ephemeral(__be32 saddr
, __be32 daddr
, __be16 dport
)
117 u32 hash
[MD5_DIGEST_WORDS
];
120 hash
[0] = (__force u32
)saddr
;
121 hash
[1] = (__force u32
)daddr
;
122 hash
[2] = (__force u32
)dport
^ net_secret
[14];
123 hash
[3] = net_secret
[15];
125 md5_transform(hash
, net_secret
);
129 EXPORT_SYMBOL_GPL(secure_ipv4_port_ephemeral
);
132 #if IS_ENABLED(CONFIG_IP_DCCP)
133 u64
secure_dccp_sequence_number(__be32 saddr
, __be32 daddr
,
134 __be16 sport
, __be16 dport
)
136 u32 hash
[MD5_DIGEST_WORDS
];
140 hash
[0] = (__force u32
)saddr
;
141 hash
[1] = (__force u32
)daddr
;
142 hash
[2] = ((__force u16
)sport
<< 16) + (__force u16
)dport
;
143 hash
[3] = net_secret
[15];
145 md5_transform(hash
, net_secret
);
147 seq
= hash
[0] | (((u64
)hash
[1]) << 32);
148 seq
+= ktime_to_ns(ktime_get_real());
149 seq
&= (1ull << 48) - 1;
153 EXPORT_SYMBOL(secure_dccp_sequence_number
);
155 #if IS_ENABLED(CONFIG_IPV6)
156 u64
secure_dccpv6_sequence_number(__be32
*saddr
, __be32
*daddr
,
157 __be16 sport
, __be16 dport
)
159 u32 secret
[MD5_MESSAGE_BYTES
/ 4];
160 u32 hash
[MD5_DIGEST_WORDS
];
165 memcpy(hash
, saddr
, 16);
166 for (i
= 0; i
< 4; i
++)
167 secret
[i
] = net_secret
[i
] + daddr
[i
];
168 secret
[4] = net_secret
[4] +
169 (((__force u16
)sport
<< 16) + (__force u16
)dport
);
170 for (i
= 5; i
< MD5_MESSAGE_BYTES
/ 4; i
++)
171 secret
[i
] = net_secret
[i
];
173 md5_transform(hash
, secret
);
175 seq
= hash
[0] | (((u64
)hash
[1]) << 32);
176 seq
+= ktime_to_ns(ktime_get_real());
177 seq
&= (1ull << 48) - 1;
181 EXPORT_SYMBOL(secure_dccpv6_sequence_number
);