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