diff options
author | Ard Biesheuvel <ard.biesheuvel@linaro.org> | 2019-06-17 10:09:33 +0200 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2019-06-17 13:56:26 -0700 |
commit | c681edae33e86ff27be2d6cc717663d91df20b0e (patch) | |
tree | 95e0fb78d34c4a223c29fb265ea0033be8c78db7 /include | |
parent | 6a6b5c8bff89c76b09a921ef05b042fdee940f2a (diff) | |
download | linux-c681edae33e86ff27be2d6cc717663d91df20b0e.tar.bz2 |
net: ipv4: move tcp_fastopen server side code to SipHash library
Using a bare block cipher in non-crypto code is almost always a bad idea,
not only for security reasons (and we've seen some examples of this in
the kernel in the past), but also for performance reasons.
In the TCP fastopen case, we call into the bare AES block cipher one or
two times (depending on whether the connection is IPv4 or IPv6). On most
systems, this results in a call chain such as
crypto_cipher_encrypt_one(ctx, dst, src)
crypto_cipher_crt(tfm)->cit_encrypt_one(crypto_cipher_tfm(tfm), ...);
aesni_encrypt
kernel_fpu_begin();
aesni_enc(ctx, dst, src); // asm routine
kernel_fpu_end();
It is highly unlikely that the use of special AES instructions has a
benefit in this case, especially since we are doing the above twice
for IPv6 connections, instead of using a transform which can process
the entire input in one go.
We could switch to the cbcmac(aes) shash, which would at least get
rid of the duplicated overhead in *some* cases (i.e., today, only
arm64 has an accelerated implementation of cbcmac(aes), while x86 will
end up using the generic cbcmac template wrapping the AES-NI cipher,
which basically ends up doing exactly the above). However, in the given
context, it makes more sense to use a light-weight MAC algorithm that
is more suitable for the purpose at hand, such as SipHash.
Since the output size of SipHash already matches our chosen value for
TCP_FASTOPEN_COOKIE_SIZE, and given that it accepts arbitrary input
sizes, this greatly simplifies the code as well.
NOTE: Server farms backing a single server IP for load balancing purposes
and sharing a single fastopen key will be adversely affected by
this change unless all systems in the pool receive their kernel
upgrades at the same time.
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include')
-rw-r--r-- | include/linux/tcp.h | 7 | ||||
-rw-r--r-- | include/net/tcp.h | 10 |
2 files changed, 5 insertions, 12 deletions
diff --git a/include/linux/tcp.h b/include/linux/tcp.h index c23019a3b264..9ea0e71f5c6a 100644 --- a/include/linux/tcp.h +++ b/include/linux/tcp.h @@ -58,12 +58,7 @@ static inline unsigned int tcp_optlen(const struct sk_buff *skb) /* TCP Fast Open Cookie as stored in memory */ struct tcp_fastopen_cookie { - union { - u8 val[TCP_FASTOPEN_COOKIE_MAX]; -#if IS_ENABLED(CONFIG_IPV6) - struct in6_addr addr; -#endif - }; + u64 val[TCP_FASTOPEN_COOKIE_MAX / sizeof(u64)]; s8 len; bool exp; /* In RFC6994 experimental option format */ }; diff --git a/include/net/tcp.h b/include/net/tcp.h index 96e0e53ff440..184930b02779 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -1628,9 +1628,9 @@ bool tcp_fastopen_defer_connect(struct sock *sk, int *err); /* Fastopen key context */ struct tcp_fastopen_context { - struct crypto_cipher *tfm[TCP_FASTOPEN_KEY_MAX]; - __u8 key[TCP_FASTOPEN_KEY_BUF_LENGTH]; - struct rcu_head rcu; + __u8 key[TCP_FASTOPEN_KEY_MAX][TCP_FASTOPEN_KEY_LENGTH]; + int num; + struct rcu_head rcu; }; extern unsigned int sysctl_tcp_fastopen_blackhole_timeout; @@ -1665,9 +1665,7 @@ bool tcp_fastopen_cookie_match(const struct tcp_fastopen_cookie *foc, static inline int tcp_fastopen_context_len(const struct tcp_fastopen_context *ctx) { - if (ctx->tfm[1]) - return 2; - return 1; + return ctx->num; } /* Latencies incurred by various limits for a sender. They are |