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 struct net *net, 55 const __be32 *saddr, const __be32 *daddr) 56 { 57 const struct { 58 struct in6_addr saddr; 59 struct in6_addr daddr; 60 } __aligned(SIPHASH_ALIGNMENT) combined = { 61 .saddr = *(struct in6_addr *)saddr, 62 .daddr = *(struct in6_addr *)daddr, 63 }; 64 65 if (net->ipv4.sysctl_tcp_timestamps != 1) 66 return 0; 67 68 ts_secret_init(); 69 return siphash(&combined, offsetofend(typeof(combined), daddr), 70 &ts_secret); 71 } 72 EXPORT_SYMBOL(secure_tcpv6_ts_off); 73 74 u32 secure_tcpv6_seq(const __be32 *saddr, const __be32 *daddr, 75 __be16 sport, __be16 dport) 76 { 77 const struct { 78 struct in6_addr saddr; 79 struct in6_addr daddr; 80 __be16 sport; 81 __be16 dport; 82 } __aligned(SIPHASH_ALIGNMENT) combined = { 83 .saddr = *(struct in6_addr *)saddr, 84 .daddr = *(struct in6_addr *)daddr, 85 .sport = sport, 86 .dport = dport 87 }; 88 u32 hash; 89 90 net_secret_init(); 91 hash = siphash(&combined, offsetofend(typeof(combined), dport), 92 &net_secret); 93 return seq_scale(hash); 94 } 95 EXPORT_SYMBOL(secure_tcpv6_seq); 96 97 u32 secure_ipv6_port_ephemeral(const __be32 *saddr, const __be32 *daddr, 98 __be16 dport) 99 { 100 const struct { 101 struct in6_addr saddr; 102 struct in6_addr daddr; 103 __be16 dport; 104 } __aligned(SIPHASH_ALIGNMENT) combined = { 105 .saddr = *(struct in6_addr *)saddr, 106 .daddr = *(struct in6_addr *)daddr, 107 .dport = dport 108 }; 109 net_secret_init(); 110 return siphash(&combined, offsetofend(typeof(combined), dport), 111 &net_secret); 112 } 113 EXPORT_SYMBOL(secure_ipv6_port_ephemeral); 114 #endif 115 116 #ifdef CONFIG_INET 117 u32 secure_tcp_ts_off(const struct net *net, __be32 saddr, __be32 daddr) 118 { 119 if (net->ipv4.sysctl_tcp_timestamps != 1) 120 return 0; 121 122 ts_secret_init(); 123 return siphash_2u32((__force u32)saddr, (__force u32)daddr, 124 &ts_secret); 125 } 126 127 /* secure_tcp_seq_and_tsoff(a, b, 0, d) == secure_ipv4_port_ephemeral(a, b, d), 128 * but fortunately, `sport' cannot be 0 in any circumstances. If this changes, 129 * it would be easy enough to have the former function use siphash_4u32, passing 130 * the arguments as separate u32. 131 */ 132 u32 secure_tcp_seq(__be32 saddr, __be32 daddr, 133 __be16 sport, __be16 dport) 134 { 135 u32 hash; 136 137 net_secret_init(); 138 hash = siphash_3u32((__force u32)saddr, (__force u32)daddr, 139 (__force u32)sport << 16 | (__force u32)dport, 140 &net_secret); 141 return seq_scale(hash); 142 } 143 144 u32 secure_ipv4_port_ephemeral(__be32 saddr, __be32 daddr, __be16 dport) 145 { 146 net_secret_init(); 147 return siphash_3u32((__force u32)saddr, (__force u32)daddr, 148 (__force u16)dport, &net_secret); 149 } 150 EXPORT_SYMBOL_GPL(secure_ipv4_port_ephemeral); 151 #endif 152 153 #if IS_ENABLED(CONFIG_IP_DCCP) 154 u64 secure_dccp_sequence_number(__be32 saddr, __be32 daddr, 155 __be16 sport, __be16 dport) 156 { 157 u64 seq; 158 net_secret_init(); 159 seq = siphash_3u32((__force u32)saddr, (__force u32)daddr, 160 (__force u32)sport << 16 | (__force u32)dport, 161 &net_secret); 162 seq += ktime_get_real_ns(); 163 seq &= (1ull << 48) - 1; 164 return seq; 165 } 166 EXPORT_SYMBOL(secure_dccp_sequence_number); 167 168 #if IS_ENABLED(CONFIG_IPV6) 169 u64 secure_dccpv6_sequence_number(__be32 *saddr, __be32 *daddr, 170 __be16 sport, __be16 dport) 171 { 172 const struct { 173 struct in6_addr saddr; 174 struct in6_addr daddr; 175 __be16 sport; 176 __be16 dport; 177 } __aligned(SIPHASH_ALIGNMENT) combined = { 178 .saddr = *(struct in6_addr *)saddr, 179 .daddr = *(struct in6_addr *)daddr, 180 .sport = sport, 181 .dport = dport 182 }; 183 u64 seq; 184 net_secret_init(); 185 seq = siphash(&combined, offsetofend(typeof(combined), dport), 186 &net_secret); 187 seq += ktime_get_real_ns(); 188 seq &= (1ull << 48) - 1; 189 return seq; 190 } 191 EXPORT_SYMBOL(secure_dccpv6_sequence_number); 192 #endif 193 #endif 194