Skip to content

Commit 65492c5

Browse files
Paolo Abenidavem330
authored andcommitted
mptcp: move from sha1 (v0) to sha256 (v1)
For simplicity's sake use directly sha256 primitives (and pull them as a required build dep). Add optional, boot-time self-tests for the hmac function. Signed-off-by: Paolo Abeni <[email protected]> Signed-off-by: Christoph Paasch <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 048d19d commit 65492c5

File tree

4 files changed

+104
-59
lines changed

4 files changed

+104
-59
lines changed

net/mptcp/Kconfig

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ config MPTCP
33
bool "MPTCP: Multipath TCP"
44
depends on INET
55
select SKB_EXTENSIONS
6+
select CRYPTO_LIB_SHA256
67
help
78
Multipath TCP (MPTCP) connections send and receive data over multiple
89
subflows in order to utilize multiple network paths. Each subflow
@@ -14,3 +15,12 @@ config MPTCP_IPV6
1415
depends on MPTCP
1516
select IPV6
1617
default y
18+
19+
config MPTCP_HMAC_TEST
20+
bool "Tests for MPTCP HMAC implementation"
21+
default n
22+
help
23+
This option enable boot time self-test for the HMAC implementation
24+
used by the MPTCP code
25+
26+
Say N if you are unsure.

net/mptcp/crypto.c

Lines changed: 85 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -21,67 +21,36 @@
2121
*/
2222

2323
#include <linux/kernel.h>
24-
#include <linux/cryptohash.h>
24+
#include <crypto/sha.h>
2525
#include <asm/unaligned.h>
2626

2727
#include "protocol.h"
2828

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-
}
29+
#define SHA256_DIGEST_WORDS (SHA256_DIGEST_SIZE / 4)
6330

6431
void mptcp_crypto_key_sha(u64 key, u32 *token, u64 *idsn)
6532
{
66-
__be32 mptcp_hashed_key[SHA_DIGEST_WORDS];
67-
u8 input[SHA_MESSAGE_BYTES];
68-
struct sha1_state state;
33+
__be32 mptcp_hashed_key[SHA256_DIGEST_WORDS];
34+
__be64 input = cpu_to_be64(key);
35+
struct sha256_state state;
6936

70-
sha1_init(&state);
71-
put_unaligned_be64(key, input);
72-
sha1_pad_final(&state, input, 8, mptcp_hashed_key);
37+
sha256_init(&state);
38+
sha256_update(&state, (__force u8 *)&input, sizeof(input));
39+
sha256_final(&state, (u8 *)mptcp_hashed_key);
7340

7441
if (token)
7542
*token = be32_to_cpu(mptcp_hashed_key[0]);
7643
if (idsn)
77-
*idsn = be64_to_cpu(*((__be64 *)&mptcp_hashed_key[3]));
44+
*idsn = be64_to_cpu(*((__be64 *)&mptcp_hashed_key[6]));
7845
}
7946

8047
void mptcp_crypto_hmac_sha(u64 key1, u64 key2, u32 nonce1, u32 nonce2,
81-
u32 *hash_out)
48+
void *hmac)
8249
{
83-
u8 input[SHA_MESSAGE_BYTES * 2];
84-
struct sha1_state state;
50+
u8 input[SHA256_BLOCK_SIZE + SHA256_DIGEST_SIZE];
51+
__be32 mptcp_hashed_key[SHA256_DIGEST_WORDS];
52+
__be32 *hash_out = (__force __be32 *)hmac;
53+
struct sha256_state state;
8554
u8 key1be[8];
8655
u8 key2be[8];
8756
int i;
@@ -96,17 +65,16 @@ void mptcp_crypto_hmac_sha(u64 key1, u64 key2, u32 nonce1, u32 nonce2,
9665
for (i = 0; i < 8; i++)
9766
input[i + 8] ^= key2be[i];
9867

99-
put_unaligned_be32(nonce1, &input[SHA_MESSAGE_BYTES]);
100-
put_unaligned_be32(nonce2, &input[SHA_MESSAGE_BYTES + 4]);
68+
put_unaligned_be32(nonce1, &input[SHA256_BLOCK_SIZE]);
69+
put_unaligned_be32(nonce2, &input[SHA256_BLOCK_SIZE + 4]);
10170

102-
sha1_init(&state);
103-
sha1_update(&state, input);
71+
sha256_init(&state);
72+
sha256_update(&state, input, SHA256_BLOCK_SIZE + 8);
10473

10574
/* emit sha256(K1 || msg) on the second input block, so we can
10675
* reuse 'input' for the last hashing
10776
*/
108-
sha1_pad_final(&state, &input[SHA_MESSAGE_BYTES], 8,
109-
(__force __be32 *)&input[SHA_MESSAGE_BYTES]);
77+
sha256_final(&state, &input[SHA256_BLOCK_SIZE]);
11078

11179
/* Prepare second part of hmac */
11280
memset(input, 0x5C, SHA_MESSAGE_BYTES);
@@ -115,8 +83,70 @@ void mptcp_crypto_hmac_sha(u64 key1, u64 key2, u32 nonce1, u32 nonce2,
11583
for (i = 0; i < 8; i++)
11684
input[i + 8] ^= key2be[i];
11785

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);
86+
sha256_init(&state);
87+
sha256_update(&state, input, SHA256_BLOCK_SIZE + SHA256_DIGEST_SIZE);
88+
sha256_final(&state, (u8 *)mptcp_hashed_key);
89+
90+
/* takes only first 160 bits */
91+
for (i = 0; i < 5; i++)
92+
hash_out[i] = mptcp_hashed_key[i];
93+
}
94+
95+
#ifdef CONFIG_MPTCP_HMAC_TEST
96+
struct test_cast {
97+
char *key;
98+
char *msg;
99+
char *result;
100+
};
101+
102+
/* we can't reuse RFC 4231 test vectors, as we have constraint on the
103+
* input and key size, and we truncate the output.
104+
*/
105+
static struct test_cast tests[] = {
106+
{
107+
.key = "0b0b0b0b0b0b0b0b",
108+
.msg = "48692054",
109+
.result = "8385e24fb4235ac37556b6b886db106284a1da67",
110+
},
111+
{
112+
.key = "aaaaaaaaaaaaaaaa",
113+
.msg = "dddddddd",
114+
.result = "2c5e219164ff1dca1c4a92318d847bb6b9d44492",
115+
},
116+
{
117+
.key = "0102030405060708",
118+
.msg = "cdcdcdcd",
119+
.result = "e73b9ba9969969cefb04aa0d6df18ec2fcc075b6",
120+
},
121+
};
122+
123+
static int __init test_mptcp_crypto(void)
124+
{
125+
char hmac[20], hmac_hex[41];
126+
u32 nonce1, nonce2;
127+
u64 key1, key2;
128+
int i, j;
129+
130+
for (i = 0; i < ARRAY_SIZE(tests); ++i) {
131+
/* mptcp hmap will convert to be before computing the hmac */
132+
key1 = be64_to_cpu(*((__be64 *)&tests[i].key[0]));
133+
key2 = be64_to_cpu(*((__be64 *)&tests[i].key[8]));
134+
nonce1 = be32_to_cpu(*((__be32 *)&tests[i].msg[0]));
135+
nonce2 = be32_to_cpu(*((__be32 *)&tests[i].msg[4]));
136+
137+
mptcp_crypto_hmac_sha(key1, key2, nonce1, nonce2, hmac);
138+
for (j = 0; j < 20; ++j)
139+
sprintf(&hmac_hex[j << 1], "%02x", hmac[j] & 0xff);
140+
hmac_hex[40] = 0;
141+
142+
if (memcmp(hmac_hex, tests[i].result, 40))
143+
pr_err("test %d failed, got %s expected %s", i,
144+
hmac_hex, tests[i].result);
145+
else
146+
pr_info("test %d [ ok ]", i);
147+
}
148+
return 0;
122149
}
150+
151+
late_initcall(test_mptcp_crypto);
152+
#endif

net/mptcp/options.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@
99
#include <net/mptcp.h>
1010
#include "protocol.h"
1111

12+
static bool mptcp_cap_flag_sha256(u8 flags)
13+
{
14+
return (flags & MPTCP_CAP_FLAG_MASK) == MPTCP_CAP_HMAC_SHA256;
15+
}
16+
1217
void mptcp_parse_option(const unsigned char *ptr, int opsize,
1318
struct tcp_options_received *opt_rx)
1419
{
@@ -29,7 +34,7 @@ void mptcp_parse_option(const unsigned char *ptr, int opsize,
2934
break;
3035

3136
flags = *ptr++;
32-
if (!((flags & MPTCP_CAP_FLAG_MASK) == MPTCP_CAP_HMAC_SHA1) ||
37+
if (!mptcp_cap_flag_sha256(flags) ||
3338
(flags & MPTCP_CAP_EXTENSIBILITY))
3439
break;
3540

@@ -399,7 +404,7 @@ void mptcp_write_options(__be32 *ptr, struct mptcp_out_options *opts)
399404
*ptr++ = htonl((TCPOPT_MPTCP << 24) | (len << 16) |
400405
(MPTCPOPT_MP_CAPABLE << 12) |
401406
(MPTCP_SUPPORTED_VERSION << 8) |
402-
MPTCP_CAP_HMAC_SHA1);
407+
MPTCP_CAP_HMAC_SHA256);
403408
put_unaligned_be64(opts->sndr_key, ptr);
404409
ptr += 2;
405410
if (OPTION_MPTCP_MPC_ACK & opts->suboptions) {

net/mptcp/protocol.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343
#define MPTCP_VERSION_MASK (0x0F)
4444
#define MPTCP_CAP_CHECKSUM_REQD BIT(7)
4545
#define MPTCP_CAP_EXTENSIBILITY BIT(6)
46-
#define MPTCP_CAP_HMAC_SHA1 BIT(0)
46+
#define MPTCP_CAP_HMAC_SHA256 BIT(0)
4747
#define MPTCP_CAP_FLAG_MASK (0x3F)
4848

4949
/* MPTCP DSS flags */
@@ -216,7 +216,7 @@ static inline void mptcp_crypto_key_gen_sha(u64 *key, u32 *token, u64 *idsn)
216216
}
217217

218218
void mptcp_crypto_hmac_sha(u64 key1, u64 key2, u32 nonce1, u32 nonce2,
219-
u32 *hash_out);
219+
void *hash_out);
220220

221221
static inline struct mptcp_ext *mptcp_get_ext(struct sk_buff *skb)
222222
{

0 commit comments

Comments
 (0)