linux/net/core/secure_seq.c
<<
>>
Prefs
   1#include <linux/kernel.h>
   2#include <linux/init.h>
   3#include <linux/cryptohash.h>
   4#include <linux/module.h>
   5#include <linux/cache.h>
   6#include <linux/random.h>
   7#include <linux/hrtimer.h>
   8#include <linux/ktime.h>
   9#include <linux/string.h>
  10#include <linux/net.h>
  11
  12#include <net/secure_seq.h>
  13
  14#if IS_ENABLED(CONFIG_IPV6) || IS_ENABLED(CONFIG_INET)
  15#define NET_SECRET_SIZE (MD5_MESSAGE_BYTES / 4)
  16
  17static u32 net_secret[NET_SECRET_SIZE] ____cacheline_aligned;
  18
  19static __always_inline void net_secret_init(void)
  20{
  21        net_get_random_once(net_secret, sizeof(net_secret));
  22}
  23#endif
  24
  25#ifdef CONFIG_INET
  26static u32 seq_scale(u32 seq)
  27{
  28        /*
  29         *      As close as possible to RFC 793, which
  30         *      suggests using a 250 kHz clock.
  31         *      Further reading shows this assumes 2 Mb/s networks.
  32         *      For 10 Mb/s Ethernet, a 1 MHz clock is appropriate.
  33         *      For 10 Gb/s Ethernet, a 1 GHz clock should be ok, but
  34         *      we also need to limit the resolution so that the u32 seq
  35         *      overlaps less than one time per MSL (2 minutes).
  36         *      Choosing a clock of 64 ns period is OK. (period of 274 s)
  37         */
  38        return seq + (ktime_get_real_ns() >> 6);
  39}
  40#endif
  41
  42#if IS_ENABLED(CONFIG_IPV6)
  43__u32 secure_tcpv6_sequence_number(const __be32 *saddr, const __be32 *daddr,
  44                                   __be16 sport, __be16 dport)
  45{
  46        u32 secret[MD5_MESSAGE_BYTES / 4];
  47        u32 hash[MD5_DIGEST_WORDS];
  48        u32 i;
  49
  50        net_secret_init();
  51        memcpy(hash, saddr, 16);
  52        for (i = 0; i < 4; i++)
  53                secret[i] = net_secret[i] + (__force u32)daddr[i];
  54        secret[4] = net_secret[4] +
  55                (((__force u16)sport << 16) + (__force u16)dport);
  56        for (i = 5; i < MD5_MESSAGE_BYTES / 4; i++)
  57                secret[i] = net_secret[i];
  58
  59        md5_transform(hash, secret);
  60
  61        return seq_scale(hash[0]);
  62}
  63EXPORT_SYMBOL(secure_tcpv6_sequence_number);
  64
  65u32 secure_ipv6_port_ephemeral(const __be32 *saddr, const __be32 *daddr,
  66                               __be16 dport)
  67{
  68        u32 secret[MD5_MESSAGE_BYTES / 4];
  69        u32 hash[MD5_DIGEST_WORDS];
  70        u32 i;
  71
  72        net_secret_init();
  73        memcpy(hash, saddr, 16);
  74        for (i = 0; i < 4; i++)
  75                secret[i] = net_secret[i] + (__force u32) daddr[i];
  76        secret[4] = net_secret[4] + (__force u32)dport;
  77        for (i = 5; i < MD5_MESSAGE_BYTES / 4; i++)
  78                secret[i] = net_secret[i];
  79
  80        md5_transform(hash, secret);
  81
  82        return hash[0];
  83}
  84EXPORT_SYMBOL(secure_ipv6_port_ephemeral);
  85#endif
  86
  87#ifdef CONFIG_INET
  88
  89__u32 secure_tcp_sequence_number(__be32 saddr, __be32 daddr,
  90                                 __be16 sport, __be16 dport)
  91{
  92        u32 hash[MD5_DIGEST_WORDS];
  93
  94        net_secret_init();
  95        hash[0] = (__force u32)saddr;
  96        hash[1] = (__force u32)daddr;
  97        hash[2] = ((__force u16)sport << 16) + (__force u16)dport;
  98        hash[3] = net_secret[15];
  99
 100        md5_transform(hash, net_secret);
 101
 102        return seq_scale(hash[0]);
 103}
 104
 105u32 secure_ipv4_port_ephemeral(__be32 saddr, __be32 daddr, __be16 dport)
 106{
 107        u32 hash[MD5_DIGEST_WORDS];
 108
 109        net_secret_init();
 110        hash[0] = (__force u32)saddr;
 111        hash[1] = (__force u32)daddr;
 112        hash[2] = (__force u32)dport ^ net_secret[14];
 113        hash[3] = net_secret[15];
 114
 115        md5_transform(hash, net_secret);
 116
 117        return hash[0];
 118}
 119EXPORT_SYMBOL_GPL(secure_ipv4_port_ephemeral);
 120#endif
 121
 122#if IS_ENABLED(CONFIG_IP_DCCP)
 123u64 secure_dccp_sequence_number(__be32 saddr, __be32 daddr,
 124                                __be16 sport, __be16 dport)
 125{
 126        u32 hash[MD5_DIGEST_WORDS];
 127        u64 seq;
 128
 129        net_secret_init();
 130        hash[0] = (__force u32)saddr;
 131        hash[1] = (__force u32)daddr;
 132        hash[2] = ((__force u16)sport << 16) + (__force u16)dport;
 133        hash[3] = net_secret[15];
 134
 135        md5_transform(hash, net_secret);
 136
 137        seq = hash[0] | (((u64)hash[1]) << 32);
 138        seq += ktime_get_real_ns();
 139        seq &= (1ull << 48) - 1;
 140
 141        return seq;
 142}
 143EXPORT_SYMBOL(secure_dccp_sequence_number);
 144
 145#if IS_ENABLED(CONFIG_IPV6)
 146u64 secure_dccpv6_sequence_number(__be32 *saddr, __be32 *daddr,
 147                                  __be16 sport, __be16 dport)
 148{
 149        u32 secret[MD5_MESSAGE_BYTES / 4];
 150        u32 hash[MD5_DIGEST_WORDS];
 151        u64 seq;
 152        u32 i;
 153
 154        net_secret_init();
 155        memcpy(hash, saddr, 16);
 156        for (i = 0; i < 4; i++)
 157                secret[i] = net_secret[i] + (__force u32)daddr[i];
 158        secret[4] = net_secret[4] +
 159                (((__force u16)sport << 16) + (__force u16)dport);
 160        for (i = 5; i < MD5_MESSAGE_BYTES / 4; i++)
 161                secret[i] = net_secret[i];
 162
 163        md5_transform(hash, secret);
 164
 165        seq = hash[0] | (((u64)hash[1]) << 32);
 166        seq += ktime_get_real_ns();
 167        seq &= (1ull << 48) - 1;
 168
 169        return seq;
 170}
 171EXPORT_SYMBOL(secure_dccpv6_sequence_number);
 172#endif
 173#endif
 174