1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2016 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved. 4 */ 5 6 #include <linux/kernel.h> 7 #include <linux/init.h> 8 #include <linux/module.h> 9 #include <linux/cache.h> 10 #include <linux/random.h> 11 #include <linux/hrtimer.h> 12 #include <linux/ktime.h> 13 #include <linux/string.h> 14 #include <linux/net.h> 15 #include <linux/siphash.h> 16 #include <net/secure_seq.h> 17 18 #if IS_ENABLED(CONFIG_IPV6) || IS_ENABLED(CONFIG_INET) 19 #include <linux/in6.h> 20 #include <net/tcp.h> 21 22 static siphash_aligned_key_t net_secret; 23 static siphash_aligned_key_t ts_secret; 24 25 #define EPHEMERAL_PORT_SHUFFLE_PERIOD (10 * HZ) 26 27 static __always_inline void net_secret_init(void) 28 { 29 net_get_random_once(&net_secret, sizeof(net_secret)); 30 } 31 32 static __always_inline void ts_secret_init(void) 33 { 34 net_get_random_once(&ts_secret, sizeof(ts_secret)); 35 } 36 #endif 37 38 #ifdef CONFIG_INET 39 static u32 seq_scale(u32 seq) 40 { 41 /* 42 * As close as possible to RFC 793, which 43 * suggests using a 250 kHz clock. 44 * Further reading shows this assumes 2 Mb/s networks. 45 * For 10 Mb/s Ethernet, a 1 MHz clock is appropriate. 46 * For 10 Gb/s Ethernet, a 1 GHz clock should be ok, but 47 * we also need to limit the resolution so that the u32 seq 48 * overlaps less than one time per MSL (2 minutes). 49 * Choosing a clock of 64 ns period is OK. (period of 274 s) 50 */ 51 return seq + (ktime_get_real_ns() >> 6); 52 } 53 #endif 54 55 #if IS_ENABLED(CONFIG_IPV6) 56 u32 secure_tcpv6_ts_off(const struct net *net, 57 const __be32 *saddr, const __be32 *daddr) 58 { 59 const struct { 60 struct in6_addr saddr; 61 struct in6_addr daddr; 62 } __aligned(SIPHASH_ALIGNMENT) combined = { 63 .saddr = *(struct in6_addr *)saddr, 64 .daddr = *(struct in6_addr *)daddr, 65 }; 66 67 if (net->ipv4.sysctl_tcp_timestamps != 1) 68 return 0; 69 70 ts_secret_init(); 71 return siphash(&combined, offsetofend(typeof(combined), daddr), 72 &ts_secret); 73 } 74 EXPORT_SYMBOL(secure_tcpv6_ts_off); 75 76 u32 secure_tcpv6_seq(const __be32 *saddr, const __be32 *daddr, 77 __be16 sport, __be16 dport) 78 { 79 const struct { 80 struct in6_addr saddr; 81 struct in6_addr daddr; 82 __be16 sport; 83 __be16 dport; 84 } __aligned(SIPHASH_ALIGNMENT) combined = { 85 .saddr = *(struct in6_addr *)saddr, 86 .daddr = *(struct in6_addr *)daddr, 87 .sport = sport, 88 .dport = dport 89 }; 90 u32 hash; 91 92 net_secret_init(); 93 hash = siphash(&combined, offsetofend(typeof(combined), dport), 94 &net_secret); 95 return seq_scale(hash); 96 } 97 EXPORT_SYMBOL(secure_tcpv6_seq); 98 99 u64 secure_ipv6_port_ephemeral(const __be32 *saddr, const __be32 *daddr, 100 __be16 dport) 101 { 102 const struct { 103 struct in6_addr saddr; 104 struct in6_addr daddr; 105 unsigned int timeseed; 106 __be16 dport; 107 } __aligned(SIPHASH_ALIGNMENT) combined = { 108 .saddr = *(struct in6_addr *)saddr, 109 .daddr = *(struct in6_addr *)daddr, 110 .timeseed = jiffies / EPHEMERAL_PORT_SHUFFLE_PERIOD, 111 .dport = dport, 112 }; 113 net_secret_init(); 114 return siphash(&combined, offsetofend(typeof(combined), dport), 115 &net_secret); 116 } 117 EXPORT_SYMBOL(secure_ipv6_port_ephemeral); 118 #endif 119 120 #ifdef CONFIG_INET 121 u32 secure_tcp_ts_off(const struct net *net, __be32 saddr, __be32 daddr) 122 { 123 if (net->ipv4.sysctl_tcp_timestamps != 1) 124 return 0; 125 126 ts_secret_init(); 127 return siphash_2u32((__force u32)saddr, (__force u32)daddr, 128 &ts_secret); 129 } 130 131 /* secure_tcp_seq_and_tsoff(a, b, 0, d) == secure_ipv4_port_ephemeral(a, b, d), 132 * but fortunately, `sport' cannot be 0 in any circumstances. If this changes, 133 * it would be easy enough to have the former function use siphash_4u32, passing 134 * the arguments as separate u32. 135 */ 136 u32 secure_tcp_seq(__be32 saddr, __be32 daddr, 137 __be16 sport, __be16 dport) 138 { 139 u32 hash; 140 141 net_secret_init(); 142 hash = siphash_3u32((__force u32)saddr, (__force u32)daddr, 143 (__force u32)sport << 16 | (__force u32)dport, 144 &net_secret); 145 return seq_scale(hash); 146 } 147 EXPORT_SYMBOL_GPL(secure_tcp_seq); 148 149 u64 secure_ipv4_port_ephemeral(__be32 saddr, __be32 daddr, __be16 dport) 150 { 151 net_secret_init(); 152 return siphash_4u32((__force u32)saddr, (__force u32)daddr, 153 (__force u16)dport, 154 jiffies / EPHEMERAL_PORT_SHUFFLE_PERIOD, 155 &net_secret); 156 } 157 EXPORT_SYMBOL_GPL(secure_ipv4_port_ephemeral); 158 #endif 159 160 #if IS_ENABLED(CONFIG_IP_DCCP) 161 u64 secure_dccp_sequence_number(__be32 saddr, __be32 daddr, 162 __be16 sport, __be16 dport) 163 { 164 u64 seq; 165 net_secret_init(); 166 seq = siphash_3u32((__force u32)saddr, (__force u32)daddr, 167 (__force u32)sport << 16 | (__force u32)dport, 168 &net_secret); 169 seq += ktime_get_real_ns(); 170 seq &= (1ull << 48) - 1; 171 return seq; 172 } 173 EXPORT_SYMBOL(secure_dccp_sequence_number); 174 175 #if IS_ENABLED(CONFIG_IPV6) 176 u64 secure_dccpv6_sequence_number(__be32 *saddr, __be32 *daddr, 177 __be16 sport, __be16 dport) 178 { 179 const struct { 180 struct in6_addr saddr; 181 struct in6_addr daddr; 182 __be16 sport; 183 __be16 dport; 184 } __aligned(SIPHASH_ALIGNMENT) combined = { 185 .saddr = *(struct in6_addr *)saddr, 186 .daddr = *(struct in6_addr *)daddr, 187 .sport = sport, 188 .dport = dport 189 }; 190 u64 seq; 191 net_secret_init(); 192 seq = siphash(&combined, offsetofend(typeof(combined), dport), 193 &net_secret); 194 seq += ktime_get_real_ns(); 195 seq &= (1ull << 48) - 1; 196 return seq; 197 } 198 EXPORT_SYMBOL(secure_dccpv6_sequence_number); 199 #endif 200 #endif 201