xref: /linux/net/ipv4/tcp_fastopen.c (revision 0d41cca490c274352211efac50e9598d39a9dc80)
110467163SJerry Chu #include <linux/err.h>
22100c8d2SYuchung Cheng #include <linux/init.h>
32100c8d2SYuchung Cheng #include <linux/kernel.h>
410467163SJerry Chu #include <linux/list.h>
510467163SJerry Chu #include <linux/tcp.h>
610467163SJerry Chu #include <linux/rcupdate.h>
710467163SJerry Chu #include <linux/rculist.h>
810467163SJerry Chu #include <net/inetpeer.h>
910467163SJerry Chu #include <net/tcp.h>
102100c8d2SYuchung Cheng 
11*0d41cca4SYuchung Cheng int sysctl_tcp_fastopen __read_mostly = TFO_CLIENT_ENABLE;
1210467163SJerry Chu 
1310467163SJerry Chu struct tcp_fastopen_context __rcu *tcp_fastopen_ctx;
1410467163SJerry Chu 
1510467163SJerry Chu static DEFINE_SPINLOCK(tcp_fastopen_ctx_lock);
1610467163SJerry Chu 
17222e83d2SHannes Frederic Sowa void tcp_fastopen_init_key_once(bool publish)
18222e83d2SHannes Frederic Sowa {
19222e83d2SHannes Frederic Sowa 	static u8 key[TCP_FASTOPEN_KEY_LENGTH];
20222e83d2SHannes Frederic Sowa 
21222e83d2SHannes Frederic Sowa 	/* tcp_fastopen_reset_cipher publishes the new context
22222e83d2SHannes Frederic Sowa 	 * atomically, so we allow this race happening here.
23222e83d2SHannes Frederic Sowa 	 *
24222e83d2SHannes Frederic Sowa 	 * All call sites of tcp_fastopen_cookie_gen also check
25222e83d2SHannes Frederic Sowa 	 * for a valid cookie, so this is an acceptable risk.
26222e83d2SHannes Frederic Sowa 	 */
27222e83d2SHannes Frederic Sowa 	if (net_get_random_once(key, sizeof(key)) && publish)
28222e83d2SHannes Frederic Sowa 		tcp_fastopen_reset_cipher(key, sizeof(key));
29222e83d2SHannes Frederic Sowa }
30222e83d2SHannes Frederic Sowa 
3110467163SJerry Chu static void tcp_fastopen_ctx_free(struct rcu_head *head)
3210467163SJerry Chu {
3310467163SJerry Chu 	struct tcp_fastopen_context *ctx =
3410467163SJerry Chu 	    container_of(head, struct tcp_fastopen_context, rcu);
3510467163SJerry Chu 	crypto_free_cipher(ctx->tfm);
3610467163SJerry Chu 	kfree(ctx);
3710467163SJerry Chu }
3810467163SJerry Chu 
3910467163SJerry Chu int tcp_fastopen_reset_cipher(void *key, unsigned int len)
4010467163SJerry Chu {
4110467163SJerry Chu 	int err;
4210467163SJerry Chu 	struct tcp_fastopen_context *ctx, *octx;
4310467163SJerry Chu 
4410467163SJerry Chu 	ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
4510467163SJerry Chu 	if (!ctx)
4610467163SJerry Chu 		return -ENOMEM;
4710467163SJerry Chu 	ctx->tfm = crypto_alloc_cipher("aes", 0, 0);
4810467163SJerry Chu 
4910467163SJerry Chu 	if (IS_ERR(ctx->tfm)) {
5010467163SJerry Chu 		err = PTR_ERR(ctx->tfm);
5110467163SJerry Chu error:		kfree(ctx);
5210467163SJerry Chu 		pr_err("TCP: TFO aes cipher alloc error: %d\n", err);
5310467163SJerry Chu 		return err;
5410467163SJerry Chu 	}
5510467163SJerry Chu 	err = crypto_cipher_setkey(ctx->tfm, key, len);
5610467163SJerry Chu 	if (err) {
5710467163SJerry Chu 		pr_err("TCP: TFO cipher key error: %d\n", err);
5810467163SJerry Chu 		crypto_free_cipher(ctx->tfm);
5910467163SJerry Chu 		goto error;
6010467163SJerry Chu 	}
6110467163SJerry Chu 	memcpy(ctx->key, key, len);
6210467163SJerry Chu 
6310467163SJerry Chu 	spin_lock(&tcp_fastopen_ctx_lock);
6410467163SJerry Chu 
6510467163SJerry Chu 	octx = rcu_dereference_protected(tcp_fastopen_ctx,
6610467163SJerry Chu 				lockdep_is_held(&tcp_fastopen_ctx_lock));
6710467163SJerry Chu 	rcu_assign_pointer(tcp_fastopen_ctx, ctx);
6810467163SJerry Chu 	spin_unlock(&tcp_fastopen_ctx_lock);
6910467163SJerry Chu 
7010467163SJerry Chu 	if (octx)
7110467163SJerry Chu 		call_rcu(&octx->rcu, tcp_fastopen_ctx_free);
7210467163SJerry Chu 	return err;
7310467163SJerry Chu }
7410467163SJerry Chu 
75149479d0SYuchung Cheng /* Computes the fastopen cookie for the IP path.
76149479d0SYuchung Cheng  * The path is a 128 bits long (pad with zeros for IPv4).
7710467163SJerry Chu  *
7810467163SJerry Chu  * The caller must check foc->len to determine if a valid cookie
7910467163SJerry Chu  * has been generated successfully.
8010467163SJerry Chu */
81149479d0SYuchung Cheng void tcp_fastopen_cookie_gen(__be32 src, __be32 dst,
82149479d0SYuchung Cheng 			     struct tcp_fastopen_cookie *foc)
8310467163SJerry Chu {
84149479d0SYuchung Cheng 	__be32 path[4] = { src, dst, 0, 0 };
8510467163SJerry Chu 	struct tcp_fastopen_context *ctx;
8610467163SJerry Chu 
87222e83d2SHannes Frederic Sowa 	tcp_fastopen_init_key_once(true);
88222e83d2SHannes Frederic Sowa 
8910467163SJerry Chu 	rcu_read_lock();
9010467163SJerry Chu 	ctx = rcu_dereference(tcp_fastopen_ctx);
9110467163SJerry Chu 	if (ctx) {
92149479d0SYuchung Cheng 		crypto_cipher_encrypt_one(ctx->tfm, foc->val, (__u8 *)path);
9310467163SJerry Chu 		foc->len = TCP_FASTOPEN_COOKIE_SIZE;
9410467163SJerry Chu 	}
9510467163SJerry Chu 	rcu_read_unlock();
9610467163SJerry Chu }
97