Skip to content

Commit 79c0949

Browse files
Peter Krystaddavem330
authored andcommitted
mptcp: Add key generation and token tree
Generate the local keys, IDSN, and token when creating a new socket. Introduce the token tree to track all tokens in use using a radix tree with the MPTCP token itself as the index. Override the rebuild_header callback in inet_connection_sock_af_ops for creating the local key on a new outgoing connection. Override the init_req callback of tcp_request_sock_ops for creating the local key on a new incoming connection. Will be used to obtain the MPTCP parent socket to handle incoming joins. Co-developed-by: Davide Caratti <[email protected]> Signed-off-by: Davide Caratti <[email protected]> Co-developed-by: Florian Westphal <[email protected]> Signed-off-by: Florian Westphal <[email protected]> Co-developed-by: Paolo Abeni <[email protected]> Signed-off-by: Paolo Abeni <[email protected]> Signed-off-by: Peter Krystad <[email protected]> Signed-off-by: Christoph Paasch <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent cf7da0d commit 79c0949

File tree

6 files changed

+428
-8
lines changed

6 files changed

+428
-8
lines changed

net/mptcp/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
# SPDX-License-Identifier: GPL-2.0
22
obj-$(CONFIG_MPTCP) += mptcp.o
33

4-
mptcp-y := protocol.o subflow.o options.o
4+
mptcp-y := protocol.o subflow.o options.o token.o crypto.o

net/mptcp/crypto.c

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/* Multipath TCP cryptographic functions
3+
* Copyright (c) 2017 - 2019, Intel Corporation.
4+
*
5+
* Note: This code is based on mptcp_ctrl.c, mptcp_ipv4.c, and
6+
* mptcp_ipv6 from multipath-tcp.org, authored by:
7+
*
8+
* Sébastien Barré <[email protected]>
9+
* Christoph Paasch <[email protected]>
10+
* Jaakko Korkeaniemi <[email protected]>
11+
* Gregory Detal <[email protected]>
12+
* Fabien Duchêne <[email protected]>
13+
* Andreas Seelinger <[email protected]>
14+
* Lavkesh Lahngir <[email protected]>
15+
* Andreas Ripke <[email protected]>
16+
* Vlad Dogaru <[email protected]>
17+
* Octavian Purdila <[email protected]>
18+
* John Ronan <[email protected]>
19+
* Catalin Nicutar <[email protected]>
20+
* Brandon Heller <[email protected]>
21+
*/
22+
23+
#include <linux/kernel.h>
24+
#include <linux/cryptohash.h>
25+
#include <asm/unaligned.h>
26+
27+
#include "protocol.h"
28+
29+
struct sha1_state {
30+
u32 workspace[SHA_WORKSPACE_WORDS];
31+
u32 digest[SHA_DIGEST_WORDS];
32+
unsigned int count;
33+
};
34+
35+
static void sha1_init(struct sha1_state *state)
36+
{
37+
sha_init(state->digest);
38+
state->count = 0;
39+
}
40+
41+
static void sha1_update(struct sha1_state *state, u8 *input)
42+
{
43+
sha_transform(state->digest, input, state->workspace);
44+
state->count += SHA_MESSAGE_BYTES;
45+
}
46+
47+
static void sha1_pad_final(struct sha1_state *state, u8 *input,
48+
unsigned int length, __be32 *mptcp_hashed_key)
49+
{
50+
int i;
51+
52+
input[length] = 0x80;
53+
memset(&input[length + 1], 0, SHA_MESSAGE_BYTES - length - 9);
54+
put_unaligned_be64((length + state->count) << 3,
55+
&input[SHA_MESSAGE_BYTES - 8]);
56+
57+
sha_transform(state->digest, input, state->workspace);
58+
for (i = 0; i < SHA_DIGEST_WORDS; ++i)
59+
put_unaligned_be32(state->digest[i], &mptcp_hashed_key[i]);
60+
61+
memzero_explicit(state->workspace, SHA_WORKSPACE_WORDS << 2);
62+
}
63+
64+
void mptcp_crypto_key_sha(u64 key, u32 *token, u64 *idsn)
65+
{
66+
__be32 mptcp_hashed_key[SHA_DIGEST_WORDS];
67+
u8 input[SHA_MESSAGE_BYTES];
68+
struct sha1_state state;
69+
70+
sha1_init(&state);
71+
put_unaligned_be64(key, input);
72+
sha1_pad_final(&state, input, 8, mptcp_hashed_key);
73+
74+
if (token)
75+
*token = be32_to_cpu(mptcp_hashed_key[0]);
76+
if (idsn)
77+
*idsn = be64_to_cpu(*((__be64 *)&mptcp_hashed_key[3]));
78+
}
79+
80+
void mptcp_crypto_hmac_sha(u64 key1, u64 key2, u32 nonce1, u32 nonce2,
81+
u32 *hash_out)
82+
{
83+
u8 input[SHA_MESSAGE_BYTES * 2];
84+
struct sha1_state state;
85+
u8 key1be[8];
86+
u8 key2be[8];
87+
int i;
88+
89+
put_unaligned_be64(key1, key1be);
90+
put_unaligned_be64(key2, key2be);
91+
92+
/* Generate key xored with ipad */
93+
memset(input, 0x36, SHA_MESSAGE_BYTES);
94+
for (i = 0; i < 8; i++)
95+
input[i] ^= key1be[i];
96+
for (i = 0; i < 8; i++)
97+
input[i + 8] ^= key2be[i];
98+
99+
put_unaligned_be32(nonce1, &input[SHA_MESSAGE_BYTES]);
100+
put_unaligned_be32(nonce2, &input[SHA_MESSAGE_BYTES + 4]);
101+
102+
sha1_init(&state);
103+
sha1_update(&state, input);
104+
105+
/* emit sha256(K1 || msg) on the second input block, so we can
106+
* reuse 'input' for the last hashing
107+
*/
108+
sha1_pad_final(&state, &input[SHA_MESSAGE_BYTES], 8,
109+
(__force __be32 *)&input[SHA_MESSAGE_BYTES]);
110+
111+
/* Prepare second part of hmac */
112+
memset(input, 0x5C, SHA_MESSAGE_BYTES);
113+
for (i = 0; i < 8; i++)
114+
input[i] ^= key1be[i];
115+
for (i = 0; i < 8; i++)
116+
input[i + 8] ^= key2be[i];
117+
118+
sha1_init(&state);
119+
sha1_update(&state, input);
120+
sha1_pad_final(&state, &input[SHA_MESSAGE_BYTES], SHA_DIGEST_WORDS << 2,
121+
(__be32 *)hash_out);
122+
}

net/mptcp/protocol.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,7 @@ static void mptcp_close(struct sock *sk, long timeout)
201201
struct mptcp_subflow_context *subflow, *tmp;
202202
struct mptcp_sock *msk = mptcp_sk(sk);
203203

204+
mptcp_token_destroy(msk->token);
204205
inet_sk_state_store(sk, TCP_CLOSE);
205206

206207
lock_sock(sk);
@@ -281,8 +282,10 @@ static struct sock *mptcp_accept(struct sock *sk, int flags, int *err,
281282
msk = mptcp_sk(new_mptcp_sock);
282283
msk->remote_key = subflow->remote_key;
283284
msk->local_key = subflow->local_key;
285+
msk->token = subflow->token;
284286
msk->subflow = NULL;
285287

288+
mptcp_token_update_accept(newsk, new_mptcp_sock);
286289
newsk = new_mptcp_sock;
287290
mptcp_copy_inaddrs(newsk, ssk);
288291
list_add(&subflow->node, &msk->conn_list);
@@ -299,6 +302,10 @@ static struct sock *mptcp_accept(struct sock *sk, int flags, int *err,
299302
return newsk;
300303
}
301304

305+
static void mptcp_destroy(struct sock *sk)
306+
{
307+
}
308+
302309
static int mptcp_get_port(struct sock *sk, unsigned short snum)
303310
{
304311
struct mptcp_sock *msk = mptcp_sk(sk);
@@ -331,6 +338,7 @@ void mptcp_finish_connect(struct sock *ssk)
331338
*/
332339
WRITE_ONCE(msk->remote_key, subflow->remote_key);
333340
WRITE_ONCE(msk->local_key, subflow->local_key);
341+
WRITE_ONCE(msk->token, subflow->token);
334342
}
335343

336344
static void mptcp_sock_graft(struct sock *sk, struct socket *parent)
@@ -349,6 +357,7 @@ static struct proto mptcp_prot = {
349357
.close = mptcp_close,
350358
.accept = mptcp_accept,
351359
.shutdown = tcp_shutdown,
360+
.destroy = mptcp_destroy,
352361
.sendmsg = mptcp_sendmsg,
353362
.recvmsg = mptcp_recvmsg,
354363
.hash = inet_hash,
@@ -568,6 +577,12 @@ void __init mptcp_init(void)
568577
static struct proto_ops mptcp_v6_stream_ops;
569578
static struct proto mptcp_v6_prot;
570579

580+
static void mptcp_v6_destroy(struct sock *sk)
581+
{
582+
mptcp_destroy(sk);
583+
inet6_destroy_sock(sk);
584+
}
585+
571586
static struct inet_protosw mptcp_v6_protosw = {
572587
.type = SOCK_STREAM,
573588
.protocol = IPPROTO_MPTCP,
@@ -583,6 +598,7 @@ int mptcpv6_init(void)
583598
mptcp_v6_prot = mptcp_prot;
584599
strcpy(mptcp_v6_prot.name, "MPTCPv6");
585600
mptcp_v6_prot.slab = NULL;
601+
mptcp_v6_prot.destroy = mptcp_v6_destroy;
586602
mptcp_v6_prot.obj_size = sizeof(struct mptcp_sock) +
587603
sizeof(struct ipv6_pinfo);
588604

net/mptcp/protocol.h

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@
77
#ifndef __MPTCP_PROTOCOL_H
88
#define __MPTCP_PROTOCOL_H
99

10+
#include <linux/random.h>
11+
#include <net/tcp.h>
12+
#include <net/inet_connection_sock.h>
13+
1014
#define MPTCP_SUPPORTED_VERSION 0
1115

1216
/* MPTCP option bits */
@@ -42,6 +46,7 @@ struct mptcp_sock {
4246
struct inet_connection_sock sk;
4347
u64 local_key;
4448
u64 remote_key;
49+
u32 token;
4550
struct list_head conn_list;
4651
struct socket *subflow; /* outgoing connect/listener/!mp_capable */
4752
};
@@ -61,6 +66,8 @@ struct mptcp_subflow_request_sock {
6166
backup : 1;
6267
u64 local_key;
6368
u64 remote_key;
69+
u64 idsn;
70+
u32 token;
6471
};
6572

6673
static inline struct mptcp_subflow_request_sock *
@@ -74,6 +81,8 @@ struct mptcp_subflow_context {
7481
struct list_head node;/* conn_list of subflows */
7582
u64 local_key;
7683
u64 remote_key;
84+
u64 idsn;
85+
u32 token;
7786
u32 request_mptcp : 1, /* send MP_CAPABLE */
7887
mp_capable : 1, /* remote is MPTCP capable */
7988
fourth_ack : 1, /* send initial DSS */
@@ -112,4 +121,27 @@ void mptcp_get_options(const struct sk_buff *skb,
112121

113122
void mptcp_finish_connect(struct sock *sk);
114123

124+
int mptcp_token_new_request(struct request_sock *req);
125+
void mptcp_token_destroy_request(u32 token);
126+
int mptcp_token_new_connect(struct sock *sk);
127+
int mptcp_token_new_accept(u32 token);
128+
void mptcp_token_update_accept(struct sock *sk, struct sock *conn);
129+
void mptcp_token_destroy(u32 token);
130+
131+
void mptcp_crypto_key_sha(u64 key, u32 *token, u64 *idsn);
132+
static inline void mptcp_crypto_key_gen_sha(u64 *key, u32 *token, u64 *idsn)
133+
{
134+
/* we might consider a faster version that computes the key as a
135+
* hash of some information available in the MPTCP socket. Use
136+
* random data at the moment, as it's probably the safest option
137+
* in case multiple sockets are opened in different namespaces at
138+
* the same time.
139+
*/
140+
get_random_bytes(key, sizeof(u64));
141+
mptcp_crypto_key_sha(*key, token, idsn);
142+
}
143+
144+
void mptcp_crypto_hmac_sha(u64 key1, u64 key2, u32 nonce1, u32 nonce2,
145+
u32 *hash_out);
146+
115147
#endif /* __MPTCP_PROTOCOL_H */

0 commit comments

Comments
 (0)