Branch data Line data Source code
1 : : #include <linux/err.h>
2 : : #include <linux/init.h>
3 : : #include <linux/kernel.h>
4 : : #include <linux/list.h>
5 : : #include <linux/tcp.h>
6 : : #include <linux/rcupdate.h>
7 : : #include <linux/rculist.h>
8 : : #include <net/inetpeer.h>
9 : : #include <net/tcp.h>
10 : :
11 : : int sysctl_tcp_fastopen __read_mostly = TFO_CLIENT_ENABLE;
12 : :
13 : : struct tcp_fastopen_context __rcu *tcp_fastopen_ctx;
14 : :
15 : : static DEFINE_SPINLOCK(tcp_fastopen_ctx_lock);
16 : :
17 : 0 : void tcp_fastopen_init_key_once(bool publish)
18 : : {
19 : : static u8 key[TCP_FASTOPEN_KEY_LENGTH];
20 : :
21 : : /* tcp_fastopen_reset_cipher publishes the new context
22 : : * atomically, so we allow this race happening here.
23 : : *
24 : : * All call sites of tcp_fastopen_cookie_gen also check
25 : : * for a valid cookie, so this is an acceptable risk.
26 : : */
27 [ # # ][ # # ]: 0 : if (net_get_random_once(key, sizeof(key)) && publish)
[ # # ]
28 : 0 : tcp_fastopen_reset_cipher(key, sizeof(key));
29 : 0 : }
30 : :
31 : 0 : static void tcp_fastopen_ctx_free(struct rcu_head *head)
32 : : {
33 : 0 : struct tcp_fastopen_context *ctx =
34 : : container_of(head, struct tcp_fastopen_context, rcu);
35 : 0 : crypto_free_cipher(ctx->tfm);
36 : 0 : kfree(ctx);
37 : 0 : }
38 : :
39 : 0 : int tcp_fastopen_reset_cipher(void *key, unsigned int len)
40 : : {
41 : : int err;
42 : : struct tcp_fastopen_context *ctx, *octx;
43 : :
44 : : ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
45 [ # # ]: 0 : if (!ctx)
46 : : return -ENOMEM;
47 : 0 : ctx->tfm = crypto_alloc_cipher("aes", 0, 0);
48 : :
49 [ # # ]: 0 : if (IS_ERR(ctx->tfm)) {
50 : : err = PTR_ERR(ctx->tfm);
51 : 0 : error: kfree(ctx);
52 : 0 : pr_err("TCP: TFO aes cipher alloc error: %d\n", err);
53 : 0 : return err;
54 : : }
55 : : err = crypto_cipher_setkey(ctx->tfm, key, len);
56 [ # # ]: 0 : if (err) {
57 : 0 : pr_err("TCP: TFO cipher key error: %d\n", err);
58 : 0 : crypto_free_cipher(ctx->tfm);
59 : : goto error;
60 : : }
61 : 0 : memcpy(ctx->key, key, len);
62 : :
63 : : spin_lock(&tcp_fastopen_ctx_lock);
64 : :
65 : 0 : octx = rcu_dereference_protected(tcp_fastopen_ctx,
66 : : lockdep_is_held(&tcp_fastopen_ctx_lock));
67 : 0 : rcu_assign_pointer(tcp_fastopen_ctx, ctx);
68 : : spin_unlock(&tcp_fastopen_ctx_lock);
69 : :
70 [ # # ]: 0 : if (octx)
71 : 0 : call_rcu(&octx->rcu, tcp_fastopen_ctx_free);
72 : 0 : return err;
73 : : }
74 : :
75 : : /* Computes the fastopen cookie for the IP path.
76 : : * The path is a 128 bits long (pad with zeros for IPv4).
77 : : *
78 : : * The caller must check foc->len to determine if a valid cookie
79 : : * has been generated successfully.
80 : : */
81 : 0 : void tcp_fastopen_cookie_gen(__be32 src, __be32 dst,
82 : : struct tcp_fastopen_cookie *foc)
83 : : {
84 : 0 : __be32 path[4] = { src, dst, 0, 0 };
85 : : struct tcp_fastopen_context *ctx;
86 : :
87 : 0 : tcp_fastopen_init_key_once(true);
88 : :
89 : : rcu_read_lock();
90 : 0 : ctx = rcu_dereference(tcp_fastopen_ctx);
91 [ # # ]: 0 : if (ctx) {
92 : 0 : crypto_cipher_encrypt_one(ctx->tfm, foc->val, (__u8 *)path);
93 : 0 : foc->len = TCP_FASTOPEN_COOKIE_SIZE;
94 : : }
95 : : rcu_read_unlock();
96 : 0 : }
|