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_seq_and_tsoff(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_seq_and_tsoff); 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_seq_and_tsoff(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 u32 secure_tcp_seq_and_tsoff(__be32 saddr, __be32 daddr, 125 __be16 sport, __be16 dport, u32 *tsoff) 126 { 127 u64 hash; 128 net_secret_init(); 129 hash = siphash_3u32((__force u32)saddr, (__force u32)daddr, 130 (__force u32)sport << 16 | (__force u32)dport, 131 &net_secret); 132 *tsoff = secure_tcp_ts_off(saddr, daddr); 133 return seq_scale(hash); 134 } 135 136 u32 secure_ipv4_port_ephemeral(__be32 saddr, __be32 daddr, __be16 dport) 137 { 138 net_secret_init(); 139 return siphash_3u32((__force u32)saddr, (__force u32)daddr, 140 (__force u16)dport, &net_secret); 141 } 142 EXPORT_SYMBOL_GPL(secure_ipv4_port_ephemeral); 143 #endif 144 145 #if IS_ENABLED(CONFIG_IP_DCCP) 146 u64 secure_dccp_sequence_number(__be32 saddr, __be32 daddr, 147 __be16 sport, __be16 dport) 148 { 149 u64 seq; 150 net_secret_init(); 151 seq = siphash_3u32((__force u32)saddr, (__force u32)daddr, 152 (__force u32)sport << 16 | (__force u32)dport, 153 &net_secret); 154 seq += ktime_get_real_ns(); 155 seq &= (1ull << 48) - 1; 156 return seq; 157 } 158 EXPORT_SYMBOL(secure_dccp_sequence_number); 159 160 #if IS_ENABLED(CONFIG_IPV6) 161 u64 secure_dccpv6_sequence_number(__be32 *saddr, __be32 *daddr, 162 __be16 sport, __be16 dport) 163 { 164 const struct { 165 struct in6_addr saddr; 166 struct in6_addr daddr; 167 __be16 sport; 168 __be16 dport; 169 } __aligned(SIPHASH_ALIGNMENT) combined = { 170 .saddr = *(struct in6_addr *)saddr, 171 .daddr = *(struct in6_addr *)daddr, 172 .sport = sport, 173 .dport = dport 174 }; 175 u64 seq; 176 net_secret_init(); 177 seq = siphash(&combined, offsetofend(typeof(combined), dport), 178 &net_secret); 179 seq += ktime_get_real_ns(); 180 seq &= (1ull << 48) - 1; 181 return seq; 182 } 183 EXPORT_SYMBOL(secure_dccpv6_sequence_number); 184 #endif 185 #endif 186