summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/tcp.h7
-rw-r--r--include/net/tcp.h10
-rw-r--r--net/Kconfig2
-rw-r--r--net/ipv4/tcp_fastopen.c97
4 files changed, 36 insertions, 80 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)
58 58
59/* TCP Fast Open Cookie as stored in memory */ 59/* TCP Fast Open Cookie as stored in memory */
60struct tcp_fastopen_cookie { 60struct tcp_fastopen_cookie {
61 union { 61 u64 val[TCP_FASTOPEN_COOKIE_MAX / sizeof(u64)];
62 u8 val[TCP_FASTOPEN_COOKIE_MAX];
63#if IS_ENABLED(CONFIG_IPV6)
64 struct in6_addr addr;
65#endif
66 };
67 s8 len; 62 s8 len;
68 bool exp; /* In RFC6994 experimental option format */ 63 bool exp; /* In RFC6994 experimental option format */
69}; 64};
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);
1628 1628
1629/* Fastopen key context */ 1629/* Fastopen key context */
1630struct tcp_fastopen_context { 1630struct tcp_fastopen_context {
1631 struct crypto_cipher *tfm[TCP_FASTOPEN_KEY_MAX]; 1631 __u8 key[TCP_FASTOPEN_KEY_MAX][TCP_FASTOPEN_KEY_LENGTH];
1632 __u8 key[TCP_FASTOPEN_KEY_BUF_LENGTH]; 1632 int num;
1633 struct rcu_head rcu; 1633 struct rcu_head rcu;
1634}; 1634};
1635 1635
1636extern unsigned int sysctl_tcp_fastopen_blackhole_timeout; 1636extern unsigned int sysctl_tcp_fastopen_blackhole_timeout;
@@ -1665,9 +1665,7 @@ bool tcp_fastopen_cookie_match(const struct tcp_fastopen_cookie *foc,
1665static inline 1665static inline
1666int tcp_fastopen_context_len(const struct tcp_fastopen_context *ctx) 1666int tcp_fastopen_context_len(const struct tcp_fastopen_context *ctx)
1667{ 1667{
1668 if (ctx->tfm[1]) 1668 return ctx->num;
1669 return 2;
1670 return 1;
1671} 1669}
1672 1670
1673/* Latencies incurred by various limits for a sender. They are 1671/* Latencies incurred by various limits for a sender. They are
diff --git a/net/Kconfig b/net/Kconfig
index d122f53c6fa2..57f51a279ad6 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -67,8 +67,6 @@ source "net/xdp/Kconfig"
67 67
68config INET 68config INET
69 bool "TCP/IP networking" 69 bool "TCP/IP networking"
70 select CRYPTO
71 select CRYPTO_AES
72 ---help--- 70 ---help---
73 These are the protocols used on the Internet and on most local 71 These are the protocols used on the Internet and on most local
74 Ethernets. It is highly recommended to say Y here (this will enlarge 72 Ethernets. It is highly recommended to say Y here (this will enlarge
diff --git a/net/ipv4/tcp_fastopen.c b/net/ipv4/tcp_fastopen.c
index 7d19fa4c8121..46b67128e1ca 100644
--- a/net/ipv4/tcp_fastopen.c
+++ b/net/ipv4/tcp_fastopen.c
@@ -7,6 +7,7 @@
7#include <linux/tcp.h> 7#include <linux/tcp.h>
8#include <linux/rcupdate.h> 8#include <linux/rcupdate.h>
9#include <linux/rculist.h> 9#include <linux/rculist.h>
10#include <linux/siphash.h>
10#include <net/inetpeer.h> 11#include <net/inetpeer.h>
11#include <net/tcp.h> 12#include <net/tcp.h>
12 13
@@ -37,14 +38,8 @@ static void tcp_fastopen_ctx_free(struct rcu_head *head)
37{ 38{
38 struct tcp_fastopen_context *ctx = 39 struct tcp_fastopen_context *ctx =
39 container_of(head, struct tcp_fastopen_context, rcu); 40 container_of(head, struct tcp_fastopen_context, rcu);
40 int i;
41 41
42 /* We own ctx, thus no need to hold the Fastopen-lock */ 42 kzfree(ctx);
43 for (i = 0; i < TCP_FASTOPEN_KEY_MAX; i++) {
44 if (ctx->tfm[i])
45 crypto_free_cipher(ctx->tfm[i]);
46 }
47 kfree(ctx);
48} 43}
49 44
50void tcp_fastopen_destroy_cipher(struct sock *sk) 45void tcp_fastopen_destroy_cipher(struct sock *sk)
@@ -72,41 +67,6 @@ void tcp_fastopen_ctx_destroy(struct net *net)
72 call_rcu(&ctxt->rcu, tcp_fastopen_ctx_free); 67 call_rcu(&ctxt->rcu, tcp_fastopen_ctx_free);
73} 68}
74 69
75static struct tcp_fastopen_context *tcp_fastopen_alloc_ctx(void *primary_key,
76 void *backup_key,
77 unsigned int len)
78{
79 struct tcp_fastopen_context *new_ctx;
80 void *key = primary_key;
81 int err, i;
82
83 new_ctx = kmalloc(sizeof(*new_ctx), GFP_KERNEL);
84 if (!new_ctx)
85 return ERR_PTR(-ENOMEM);
86 for (i = 0; i < TCP_FASTOPEN_KEY_MAX; i++)
87 new_ctx->tfm[i] = NULL;
88 for (i = 0; i < (backup_key ? 2 : 1); i++) {
89 new_ctx->tfm[i] = crypto_alloc_cipher("aes", 0, 0);
90 if (IS_ERR(new_ctx->tfm[i])) {
91 err = PTR_ERR(new_ctx->tfm[i]);
92 new_ctx->tfm[i] = NULL;
93 pr_err("TCP: TFO aes cipher alloc error: %d\n", err);
94 goto out;
95 }
96 err = crypto_cipher_setkey(new_ctx->tfm[i], key, len);
97 if (err) {
98 pr_err("TCP: TFO cipher key error: %d\n", err);
99 goto out;
100 }
101 memcpy(&new_ctx->key[i * TCP_FASTOPEN_KEY_LENGTH], key, len);
102 key = backup_key;
103 }
104 return new_ctx;
105out:
106 tcp_fastopen_ctx_free(&new_ctx->rcu);
107 return ERR_PTR(err);
108}
109
110int tcp_fastopen_reset_cipher(struct net *net, struct sock *sk, 70int tcp_fastopen_reset_cipher(struct net *net, struct sock *sk,
111 void *primary_key, void *backup_key, 71 void *primary_key, void *backup_key,
112 unsigned int len) 72 unsigned int len)
@@ -115,11 +75,20 @@ int tcp_fastopen_reset_cipher(struct net *net, struct sock *sk,
115 struct fastopen_queue *q; 75 struct fastopen_queue *q;
116 int err = 0; 76 int err = 0;
117 77
118 ctx = tcp_fastopen_alloc_ctx(primary_key, backup_key, len); 78 ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
119 if (IS_ERR(ctx)) { 79 if (!ctx) {
120 err = PTR_ERR(ctx); 80 err = -ENOMEM;
121 goto out; 81 goto out;
122 } 82 }
83
84 memcpy(ctx->key[0], primary_key, len);
85 if (backup_key) {
86 memcpy(ctx->key[1], backup_key, len);
87 ctx->num = 2;
88 } else {
89 ctx->num = 1;
90 }
91
123 spin_lock(&net->ipv4.tcp_fastopen_ctx_lock); 92 spin_lock(&net->ipv4.tcp_fastopen_ctx_lock);
124 if (sk) { 93 if (sk) {
125 q = &inet_csk(sk)->icsk_accept_queue.fastopenq; 94 q = &inet_csk(sk)->icsk_accept_queue.fastopenq;
@@ -141,31 +110,30 @@ out:
141 110
142static bool __tcp_fastopen_cookie_gen_cipher(struct request_sock *req, 111static bool __tcp_fastopen_cookie_gen_cipher(struct request_sock *req,
143 struct sk_buff *syn, 112 struct sk_buff *syn,
144 struct crypto_cipher *tfm, 113 const u8 *key,
145 struct tcp_fastopen_cookie *foc) 114 struct tcp_fastopen_cookie *foc)
146{ 115{
116 BUILD_BUG_ON(TCP_FASTOPEN_KEY_LENGTH != sizeof(siphash_key_t));
117 BUILD_BUG_ON(TCP_FASTOPEN_COOKIE_SIZE != sizeof(u64));
118
147 if (req->rsk_ops->family == AF_INET) { 119 if (req->rsk_ops->family == AF_INET) {
148 const struct iphdr *iph = ip_hdr(syn); 120 const struct iphdr *iph = ip_hdr(syn);
149 __be32 path[4] = { iph->saddr, iph->daddr, 0, 0 };
150 121
151 crypto_cipher_encrypt_one(tfm, foc->val, (void *)path); 122 foc->val[0] = siphash(&iph->saddr,
123 sizeof(iph->saddr) +
124 sizeof(iph->daddr),
125 (const siphash_key_t *)key);
152 foc->len = TCP_FASTOPEN_COOKIE_SIZE; 126 foc->len = TCP_FASTOPEN_COOKIE_SIZE;
153 return true; 127 return true;
154 } 128 }
155
156#if IS_ENABLED(CONFIG_IPV6) 129#if IS_ENABLED(CONFIG_IPV6)
157 if (req->rsk_ops->family == AF_INET6) { 130 if (req->rsk_ops->family == AF_INET6) {
158 const struct ipv6hdr *ip6h = ipv6_hdr(syn); 131 const struct ipv6hdr *ip6h = ipv6_hdr(syn);
159 struct tcp_fastopen_cookie tmp; 132
160 struct in6_addr *buf; 133 foc->val[0] = siphash(&ip6h->saddr,
161 int i; 134 sizeof(ip6h->saddr) +
162 135 sizeof(ip6h->daddr),
163 crypto_cipher_encrypt_one(tfm, tmp.val, 136 (const siphash_key_t *)key);
164 (void *)&ip6h->saddr);
165 buf = &tmp.addr;
166 for (i = 0; i < 4; i++)
167 buf->s6_addr32[i] ^= ip6h->daddr.s6_addr32[i];
168 crypto_cipher_encrypt_one(tfm, foc->val, (void *)buf);
169 foc->len = TCP_FASTOPEN_COOKIE_SIZE; 137 foc->len = TCP_FASTOPEN_COOKIE_SIZE;
170 return true; 138 return true;
171 } 139 }
@@ -173,11 +141,8 @@ static bool __tcp_fastopen_cookie_gen_cipher(struct request_sock *req,
173 return false; 141 return false;
174} 142}
175 143
176/* Generate the fastopen cookie by doing aes128 encryption on both 144/* Generate the fastopen cookie by applying SipHash to both the source and
177 * the source and destination addresses. Pad 0s for IPv4 or IPv4-mapped-IPv6 145 * destination addresses.
178 * addresses. For the longer IPv6 addresses use CBC-MAC.
179 *
180 * XXX (TFO) - refactor when TCP_FASTOPEN_COOKIE_SIZE != AES_BLOCK_SIZE.
181 */ 146 */
182static void tcp_fastopen_cookie_gen(struct sock *sk, 147static void tcp_fastopen_cookie_gen(struct sock *sk,
183 struct request_sock *req, 148 struct request_sock *req,
@@ -189,7 +154,7 @@ static void tcp_fastopen_cookie_gen(struct sock *sk,
189 rcu_read_lock(); 154 rcu_read_lock();
190 ctx = tcp_fastopen_get_ctx(sk); 155 ctx = tcp_fastopen_get_ctx(sk);
191 if (ctx) 156 if (ctx)
192 __tcp_fastopen_cookie_gen_cipher(req, syn, ctx->tfm[0], foc); 157 __tcp_fastopen_cookie_gen_cipher(req, syn, ctx->key[0], foc);
193 rcu_read_unlock(); 158 rcu_read_unlock();
194} 159}
195 160
@@ -253,7 +218,7 @@ static int tcp_fastopen_cookie_gen_check(struct sock *sk,
253 if (!ctx) 218 if (!ctx)
254 goto out; 219 goto out;
255 for (i = 0; i < tcp_fastopen_context_len(ctx); i++) { 220 for (i = 0; i < tcp_fastopen_context_len(ctx); i++) {
256 __tcp_fastopen_cookie_gen_cipher(req, syn, ctx->tfm[i], foc); 221 __tcp_fastopen_cookie_gen_cipher(req, syn, ctx->key[i], foc);
257 if (tcp_fastopen_cookie_match(foc, orig)) { 222 if (tcp_fastopen_cookie_match(foc, orig)) {
258 ret = i + 1; 223 ret = i + 1;
259 goto out; 224 goto out;