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