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/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_aligned_key_t net_secret; 23 static siphash_aligned_key_t ts_secret; 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 EXPORT_SYMBOL_GPL(secure_tcp_seq); 144 145 u32 secure_ipv4_port_ephemeral(__be32 saddr, __be32 daddr, __be16 dport) 146 { 147 net_secret_init(); 148 return siphash_3u32((__force u32)saddr, (__force u32)daddr, 149 (__force u16)dport, &net_secret); 150 } 151 EXPORT_SYMBOL_GPL(secure_ipv4_port_ephemeral); 152 #endif 153 154 #if IS_ENABLED(CONFIG_IP_DCCP) 155 u64 secure_dccp_sequence_number(__be32 saddr, __be32 daddr, 156 __be16 sport, __be16 dport) 157 { 158 u64 seq; 159 net_secret_init(); 160 seq = siphash_3u32((__force u32)saddr, (__force u32)daddr, 161 (__force u32)sport << 16 | (__force u32)dport, 162 &net_secret); 163 seq += ktime_get_real_ns(); 164 seq &= (1ull << 48) - 1; 165 return seq; 166 } 167 EXPORT_SYMBOL(secure_dccp_sequence_number); 168 169 #if IS_ENABLED(CONFIG_IPV6) 170 u64 secure_dccpv6_sequence_number(__be32 *saddr, __be32 *daddr, 171 __be16 sport, __be16 dport) 172 { 173 const struct { 174 struct in6_addr saddr; 175 struct in6_addr daddr; 176 __be16 sport; 177 __be16 dport; 178 } __aligned(SIPHASH_ALIGNMENT) combined = { 179 .saddr = *(struct in6_addr *)saddr, 180 .daddr = *(struct in6_addr *)daddr, 181 .sport = sport, 182 .dport = dport 183 }; 184 u64 seq; 185 net_secret_init(); 186 seq = siphash(&combined, offsetofend(typeof(combined), dport), 187 &net_secret); 188 seq += ktime_get_real_ns(); 189 seq &= (1ull << 48) - 1; 190 return seq; 191 } 192 EXPORT_SYMBOL(secure_dccpv6_sequence_number); 193 #endif 194 #endif 195