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