Commit 149479d0 authored by Yuchung Cheng's avatar Yuchung Cheng Committed by David S. Miller

tcp: add server ip to encrypt cookie in fast open

Encrypt the cookie with both server and client IPv4 addresses,
such that multi-homed server will grant different cookies
based on both the source and destination IPs. No client change
is needed since cookie is opaque to the client.
Signed-off-by: default avatarYuchung Cheng <ycheng@google.com>
Reviewed-by: default avatarEric Dumazet <edumazet@google.com>
Acked-by: default avatarNeal Cardwell <ncardwell@google.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 469230d1
...@@ -1300,7 +1300,8 @@ void tcp_free_fastopen_req(struct tcp_sock *tp); ...@@ -1300,7 +1300,8 @@ void tcp_free_fastopen_req(struct tcp_sock *tp);
extern struct tcp_fastopen_context __rcu *tcp_fastopen_ctx; extern struct tcp_fastopen_context __rcu *tcp_fastopen_ctx;
int tcp_fastopen_reset_cipher(void *key, unsigned int len); int tcp_fastopen_reset_cipher(void *key, unsigned int len);
void tcp_fastopen_cookie_gen(__be32 addr, struct tcp_fastopen_cookie *foc); extern void tcp_fastopen_cookie_gen(__be32 src, __be32 dst,
struct tcp_fastopen_cookie *foc);
#define TCP_FASTOPEN_KEY_LENGTH 16 #define TCP_FASTOPEN_KEY_LENGTH 16
......
...@@ -58,23 +58,22 @@ error: kfree(ctx); ...@@ -58,23 +58,22 @@ error: kfree(ctx);
return err; return err;
} }
/* Computes the fastopen cookie for the peer. /* Computes the fastopen cookie for the IP path.
* The peer address is a 128 bits long (pad with zeros for IPv4). * The path is a 128 bits long (pad with zeros for IPv4).
* *
* The caller must check foc->len to determine if a valid cookie * The caller must check foc->len to determine if a valid cookie
* has been generated successfully. * has been generated successfully.
*/ */
void tcp_fastopen_cookie_gen(__be32 addr, struct tcp_fastopen_cookie *foc) void tcp_fastopen_cookie_gen(__be32 src, __be32 dst,
struct tcp_fastopen_cookie *foc)
{ {
__be32 peer_addr[4] = { addr, 0, 0, 0 }; __be32 path[4] = { src, dst, 0, 0 };
struct tcp_fastopen_context *ctx; struct tcp_fastopen_context *ctx;
rcu_read_lock(); rcu_read_lock();
ctx = rcu_dereference(tcp_fastopen_ctx); ctx = rcu_dereference(tcp_fastopen_ctx);
if (ctx) { if (ctx) {
crypto_cipher_encrypt_one(ctx->tfm, crypto_cipher_encrypt_one(ctx->tfm, foc->val, (__u8 *)path);
foc->val,
(__u8 *)peer_addr);
foc->len = TCP_FASTOPEN_COOKIE_SIZE; foc->len = TCP_FASTOPEN_COOKIE_SIZE;
} }
rcu_read_unlock(); rcu_read_unlock();
......
...@@ -1316,9 +1316,11 @@ static bool tcp_fastopen_check(struct sock *sk, struct sk_buff *skb, ...@@ -1316,9 +1316,11 @@ static bool tcp_fastopen_check(struct sock *sk, struct sk_buff *skb,
tcp_rsk(req)->rcv_nxt = TCP_SKB_CB(skb)->end_seq; tcp_rsk(req)->rcv_nxt = TCP_SKB_CB(skb)->end_seq;
return true; return true;
} }
if (foc->len == TCP_FASTOPEN_COOKIE_SIZE) { if (foc->len == TCP_FASTOPEN_COOKIE_SIZE) {
if ((sysctl_tcp_fastopen & TFO_SERVER_COOKIE_NOT_CHKED) == 0) { if ((sysctl_tcp_fastopen & TFO_SERVER_COOKIE_NOT_CHKED) == 0) {
tcp_fastopen_cookie_gen(ip_hdr(skb)->saddr, valid_foc); tcp_fastopen_cookie_gen(ip_hdr(skb)->saddr,
ip_hdr(skb)->daddr, valid_foc);
if ((valid_foc->len != TCP_FASTOPEN_COOKIE_SIZE) || if ((valid_foc->len != TCP_FASTOPEN_COOKIE_SIZE) ||
memcmp(&foc->val[0], &valid_foc->val[0], memcmp(&foc->val[0], &valid_foc->val[0],
TCP_FASTOPEN_COOKIE_SIZE) != 0) TCP_FASTOPEN_COOKIE_SIZE) != 0)
...@@ -1329,14 +1331,16 @@ static bool tcp_fastopen_check(struct sock *sk, struct sk_buff *skb, ...@@ -1329,14 +1331,16 @@ static bool tcp_fastopen_check(struct sock *sk, struct sk_buff *skb,
tcp_rsk(req)->rcv_nxt = TCP_SKB_CB(skb)->end_seq; tcp_rsk(req)->rcv_nxt = TCP_SKB_CB(skb)->end_seq;
return true; return true;
} else if (foc->len == 0) { /* Client requesting a cookie */ } else if (foc->len == 0) { /* Client requesting a cookie */
tcp_fastopen_cookie_gen(ip_hdr(skb)->saddr, valid_foc); tcp_fastopen_cookie_gen(ip_hdr(skb)->saddr,
ip_hdr(skb)->daddr, valid_foc);
NET_INC_STATS_BH(sock_net(sk), NET_INC_STATS_BH(sock_net(sk),
LINUX_MIB_TCPFASTOPENCOOKIEREQD); LINUX_MIB_TCPFASTOPENCOOKIEREQD);
} else { } else {
/* Client sent a cookie with wrong size. Treat it /* Client sent a cookie with wrong size. Treat it
* the same as invalid and return a valid one. * the same as invalid and return a valid one.
*/ */
tcp_fastopen_cookie_gen(ip_hdr(skb)->saddr, valid_foc); tcp_fastopen_cookie_gen(ip_hdr(skb)->saddr,
ip_hdr(skb)->daddr, valid_foc);
} }
return false; return false;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment