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