diff mbox series

[1/3] mptcp: move from sha1 (v0) to sha256 (v1)

Message ID 20191202171504.88739-2-cpaasch@apple.com
State Superseded, archived
Headers show
Series mptcp: support for rfc6824 MP CAPABLE hanshake | expand

Commit Message

Christoph Paasch Dec. 2, 2019, 5:15 p.m. UTC
From: Paolo Abeni <pabeni@redhat.com>

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 <pabeni@redhat.com>
Signed-off-by: Christoph Paasch <cpaasch@apple.com>
---
 net/mptcp/Kconfig    |  10 ++++
 net/mptcp/crypto.c   | 139 ++++++++++++++++++++++++++-----------------
 net/mptcp/options.c  |   9 ++-
 net/mptcp/protocol.h |   4 +-
 4 files changed, 103 insertions(+), 59 deletions(-)

Comments

Matthieu Baerts Dec. 3, 2019, 7:54 a.m. UTC | #1
Hi Christoph, Paolo,

On 02/12/2019 18:15, Christoph Paasch wrote:
> From: Paolo Abeni <pabeni@redhat.com>
> 
> 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 <pabeni@redhat.com>
> Signed-off-by: Christoph Paasch <cpaasch@apple.com>

Sorry for this detail but regarding the Signed-off-by, should I write 
this instead?

   Co-developed-by: Christoph Paasch <cpaasch@apple.com>
   Signed-off-by: Christoph Paasch <cpaasch@apple.com>
   Signed-off-by: Paolo Abeni <pabeni@redhat.com>

Or do we have a "Signed-off-by" here from Christoph because you 
(Christoph) are the sender of this patch here? But can we keep it if you 
are not the one who will send this patch to netdev? :)

The rest looks good to me!

Cheers,
Matt
Paolo Abeni Dec. 3, 2019, 9:09 a.m. UTC | #2
On Tue, 2019-12-03 at 08:54 +0100, Matthieu Baerts wrote:
> Hi Christoph, Paolo,
> 
> On 02/12/2019 18:15, Christoph Paasch wrote:
> > From: Paolo Abeni <pabeni@redhat.com>
> > 
> > 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 <pabeni@redhat.com>
> > Signed-off-by: Christoph Paasch <cpaasch@apple.com>
> 
> Sorry for this detail but regarding the Signed-off-by, should I write 
> this instead?
> 
>    Co-developed-by: Christoph Paasch <cpaasch@apple.com>
>    Signed-off-by: Christoph Paasch <cpaasch@apple.com>
>    Signed-off-by: Paolo Abeni <pabeni@redhat.com>
> 
> Or do we have a "Signed-off-by" here from Christoph because you 
> (Christoph) are the sender of this patch here? 

Likely the 2nd option ;)

> But can we keep it if you 
> are not the one who will send this patch to netdev? :)

Not a big deal to me, but strictly speaking I think keeping it for
netdev submission would be correct only if Christoph will do the netdev
submission, too.

Note: before the submission it would be good to review once again the
tag correctness.

Cheers,

Paolo
Matthieu Baerts Dec. 3, 2019, 10:45 a.m. UTC | #3
Hi Paolo,

On 03/12/2019 10:09, Paolo Abeni wrote:
> On Tue, 2019-12-03 at 08:54 +0100, Matthieu Baerts wrote:
>> Hi Christoph, Paolo,
>>
>> On 02/12/2019 18:15, Christoph Paasch wrote:
>>> From: Paolo Abeni <pabeni@redhat.com>
>>>
>>> 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 <pabeni@redhat.com>
>>> Signed-off-by: Christoph Paasch <cpaasch@apple.com>
>>
>> Sorry for this detail but regarding the Signed-off-by, should I write
>> this instead?
>>
>>     Co-developed-by: Christoph Paasch <cpaasch@apple.com>
>>     Signed-off-by: Christoph Paasch <cpaasch@apple.com>
>>     Signed-off-by: Paolo Abeni <pabeni@redhat.com>
>>
>> Or do we have a "Signed-off-by" here from Christoph because you
>> (Christoph) are the sender of this patch here?
> 
> Likely the 2nd option ;)
> 
>> But can we keep it if you
>> are not the one who will send this patch to netdev? :)
> 
> Not a big deal to me, but strictly speaking I think keeping it for
> netdev submission would be correct only if Christoph will do the netdev
> submission, too.

So for you, when we apply this, better to only keep one your signed-off 
and add the signed-off of the submitter (probably Mat)?

> Note: before the submission it would be good to review once again the
> tag correctness.

Good idea!
I think we should also review the whole commit messages in general. 
Maybe some are no longer up to date after all the squashes we did :)

Cheers,
Matt
Paolo Abeni Dec. 3, 2019, 11:06 a.m. UTC | #4
On Tue, 2019-12-03 at 11:45 +0100, Matthieu Baerts wrote:
> Hi Paolo,
> 
> On 03/12/2019 10:09, Paolo Abeni wrote:
> > On Tue, 2019-12-03 at 08:54 +0100, Matthieu Baerts wrote:
> > > Hi Christoph, Paolo,
> > > 
> > > On 02/12/2019 18:15, Christoph Paasch wrote:
> > > > From: Paolo Abeni <pabeni@redhat.com>
> > > > 
> > > > 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 <pabeni@redhat.com>
> > > > Signed-off-by: Christoph Paasch <cpaasch@apple.com>
> > > 
> > > Sorry for this detail but regarding the Signed-off-by, should I write
> > > this instead?
> > > 
> > >     Co-developed-by: Christoph Paasch <cpaasch@apple.com>
> > >     Signed-off-by: Christoph Paasch <cpaasch@apple.com>
> > >     Signed-off-by: Paolo Abeni <pabeni@redhat.com>
> > > 
> > > Or do we have a "Signed-off-by" here from Christoph because you
> > > (Christoph) are the sender of this patch here?
> > 
> > Likely the 2nd option ;)
> > 
> > > But can we keep it if you
> > > are not the one who will send this patch to netdev? :)
> > 
> > Not a big deal to me, but strictly speaking I think keeping it for
> > netdev submission would be correct only if Christoph will do the netdev
> > submission, too.
> 
> So for you, when we apply this, better to only keep one your signed-off 
> and add the signed-off of the submitter (probably Mat)?

Exactly!

> > Note: before the submission it would be good to review once again the
> > tag correctness.
> 
> Good idea!
> I think we should also review the whole commit messages in general. 
> Maybe some are no longer up to date after all the squashes we did :)

+1!

Cheers,

Paolo
Christoph Paasch Dec. 3, 2019, 6:51 p.m. UTC | #5
On 03/12/19 - 10:09:56, Paolo Abeni wrote:
> On Tue, 2019-12-03 at 08:54 +0100, Matthieu Baerts wrote:
> > Hi Christoph, Paolo,
> > 
> > On 02/12/2019 18:15, Christoph Paasch wrote:
> > > From: Paolo Abeni <pabeni@redhat.com>
> > > 
> > > 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 <pabeni@redhat.com>
> > > Signed-off-by: Christoph Paasch <cpaasch@apple.com>
> > 
> > Sorry for this detail but regarding the Signed-off-by, should I write 
> > this instead?
> > 
> >    Co-developed-by: Christoph Paasch <cpaasch@apple.com>
> >    Signed-off-by: Christoph Paasch <cpaasch@apple.com>
> >    Signed-off-by: Paolo Abeni <pabeni@redhat.com>
> > 
> > Or do we have a "Signed-off-by" here from Christoph because you 
> > (Christoph) are the sender of this patch here? 
> 
> Likely the 2nd option ;)
> 
> > But can we keep it if you 
> > are not the one who will send this patch to netdev? :)
> 
> Not a big deal to me, but strictly speaking I think keeping it for
> netdev submission would be correct only if Christoph will do the netdev
> submission, too.
> 
> Note: before the submission it would be good to review once again the
> tag correctness.

Yes, sorry for the added Signed-off-by. My script applies patches from
e-mails with "-s" and I forgot to remove this one here.


Thanks,
Christoph
Peter Krystad Dec. 4, 2019, 9:26 p.m. UTC | #6
Hi -

This patch 1/3 looks good to me. Farewell mptcp.org interop!

Peter.


On Mon, 2019-12-02 at 09:15 -0800, Christoph Paasch wrote:
> From: Paolo Abeni <pabeni@redhat.com>
> 
> 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 <pabeni@redhat.com>
> Signed-off-by: Christoph Paasch <cpaasch@apple.com>
> ---
>  net/mptcp/Kconfig    |  10 ++++
>  net/mptcp/crypto.c   | 139 ++++++++++++++++++++++++++-----------------
>  net/mptcp/options.c  |   9 ++-
>  net/mptcp/protocol.h |   4 +-
>  4 files changed, 103 insertions(+), 59 deletions(-)
> 
> diff --git a/net/mptcp/Kconfig b/net/mptcp/Kconfig
> index c1a99f07a4cd..5db56d2218c5 100644
> --- a/net/mptcp/Kconfig
> +++ b/net/mptcp/Kconfig
> @@ -3,6 +3,7 @@ config MPTCP
>  	bool "MPTCP: Multipath TCP"
>  	depends on INET
>  	select SKB_EXTENSIONS
> +	select CRYPTO_LIB_SHA256
>  	help
>  	  Multipath TCP (MPTCP) connections send and receive data over multiple
>  	  subflows in order to utilize multiple network paths. Each subflow
> @@ -14,3 +15,12 @@ config MPTCP_IPV6
>  	depends on MPTCP
>  	select IPV6
>  	default y
> +
> +config MPTCP_HMAC_TEST
> +	bool "Tests for MPTCP HMAC implementation"
> +	default n
> +	help
> +	  This option enable boot time self-test for the HMAC implementation
> +	  used by the MPTCP code
> +
> +	  Say N if you are unsure.
> diff --git a/net/mptcp/crypto.c b/net/mptcp/crypto.c
> index ccb9f7effdcd..68f1758b96c2 100644
> --- a/net/mptcp/crypto.c
> +++ b/net/mptcp/crypto.c
> @@ -21,67 +21,36 @@
>   */
>  
>  #include <linux/kernel.h>
> -#include <linux/cryptohash.h>
> +#include <crypto/sha.h>
>  #include <asm/unaligned.h>
>  
>  #include "protocol.h"
>  
> -struct sha1_state {
> -	u32 workspace[SHA_WORKSPACE_WORDS];
> -	u32 digest[SHA_DIGEST_WORDS];
> -	unsigned int count;
> -};
> -
> -static void sha1_init(struct sha1_state *state)
> -{
> -	sha_init(state->digest);
> -	state->count = 0;
> -}
> -
> -static void sha1_update(struct sha1_state *state, u8 *input)
> -{
> -	sha_transform(state->digest, input, state->workspace);
> -	state->count += SHA_MESSAGE_BYTES;
> -}
> -
> -static void sha1_pad_final(struct sha1_state *state, u8 *input, unsigned length,
> -			   __be32 *mptcp_hashed_key)
> -{
> -	int i;
> -
> -	input[length] = 0x80;
> -	memset(&input[length + 1], 0, SHA_MESSAGE_BYTES - length - 9);
> -	put_unaligned_be64((length + state->count) << 3,
> -			   &input[SHA_MESSAGE_BYTES - 8]);
> -
> -	sha_transform(state->digest, input, state->workspace);
> -	for (i = 0; i < SHA_DIGEST_WORDS; ++i)
> -		put_unaligned_be32(state->digest[i], &mptcp_hashed_key[i]);
> -
> -	memzero_explicit(state->workspace, SHA_WORKSPACE_WORDS << 2);
> -}
> +#define SHA256_DIGEST_WORDS (SHA256_DIGEST_SIZE / 4)
>  
>  void mptcp_crypto_key_sha(u64 key, u32 *token, u64 *idsn)
>  {
> -	__be32 mptcp_hashed_key[SHA_DIGEST_WORDS];
> -	u8 input[SHA_MESSAGE_BYTES];
> -	struct sha1_state state;
> +	__be32 mptcp_hashed_key[SHA256_DIGEST_WORDS];
> +	__be64 input = cpu_to_be64(key);
> +	struct sha256_state state;
>  
> -	sha1_init(&state);
> -	put_unaligned_be64(key, input);
> -	sha1_pad_final(&state, input, 8, mptcp_hashed_key);
> +	sha256_init(&state);
> +	sha256_update(&state, (__force u8 *)&input, sizeof(input));
> +	sha256_final(&state, (u8 *)mptcp_hashed_key);
>  
>  	if (token)
>  		*token = be32_to_cpu(mptcp_hashed_key[0]);
>  	if (idsn)
> -		*idsn = be64_to_cpu(*((__be64 *)&mptcp_hashed_key[3]));
> +		*idsn = be64_to_cpu(*((__be64 *)&mptcp_hashed_key[6]));
>  }
>  
>  void mptcp_crypto_hmac_sha(u64 key1, u64 key2, u32 nonce1, u32 nonce2,
> -			    u32 *hash_out)
> +			   void *hmac)
>  {
> -	u8 input[SHA_MESSAGE_BYTES * 2];
> -	struct sha1_state state;
> +	u8 input[SHA256_BLOCK_SIZE + SHA256_DIGEST_SIZE];
> +	__be32 mptcp_hashed_key[SHA256_DIGEST_WORDS];
> +	__be32 *hash_out = (__force __be32 *)hmac;
> +	struct sha256_state state;
>  	u8 key1be[8];
>  	u8 key2be[8];
>  	int i;
> @@ -96,17 +65,16 @@ void mptcp_crypto_hmac_sha(u64 key1, u64 key2, u32 nonce1, u32 nonce2,
>  	for (i = 0; i < 8; i++)
>  		input[i + 8] ^= key2be[i];
>  
> -	put_unaligned_be32(nonce1, &input[SHA_MESSAGE_BYTES]);
> -	put_unaligned_be32(nonce2, &input[SHA_MESSAGE_BYTES + 4]);
> +	put_unaligned_be32(nonce1, &input[SHA256_BLOCK_SIZE]);
> +	put_unaligned_be32(nonce2, &input[SHA256_BLOCK_SIZE + 4]);
>  
> -	sha1_init(&state);
> -	sha1_update(&state, input);
> +	sha256_init(&state);
> +	sha256_update(&state, input, SHA256_BLOCK_SIZE + 8);
>  
>  	/* emit sha256(K1 || msg) on the second input block, so we can
>  	 * reuse 'input' for the last hashing
>  	 */
> -	sha1_pad_final(&state, &input[SHA_MESSAGE_BYTES], 8,
> -		       (__force __be32 *)&input[SHA_MESSAGE_BYTES]);
> +	sha256_final(&state, &input[SHA256_BLOCK_SIZE]);
>  
>  	/* Prepare second part of hmac */
>  	memset(input, 0x5C, SHA_MESSAGE_BYTES);
> @@ -115,8 +83,69 @@ void mptcp_crypto_hmac_sha(u64 key1, u64 key2, u32 nonce1, u32 nonce2,
>  	for (i = 0; i < 8; i++)
>  		input[i + 8] ^= key2be[i];
>  
> -	sha1_init(&state);
> -	sha1_update(&state, input);
> -	sha1_pad_final(&state, &input[SHA_MESSAGE_BYTES], SHA_DIGEST_WORDS << 2,
> -		      (__be32*)hash_out);
> +	sha256_init(&state);
> +	sha256_update(&state, input, SHA256_BLOCK_SIZE + SHA256_DIGEST_SIZE);
> +	sha256_final(&state, (u8 *)mptcp_hashed_key);
> +
> +	/* takes only first 160 bits */
> +	for (i = 0; i < 5; i++)
> +		hash_out[i] = mptcp_hashed_key[i];
> +}
> +
> +#ifdef CONFIG_MPTCP_HMAC_TEST
> +struct test_cast {
> +	char *key;
> +	char *msg;
> +	char *result;
> +};
> +
> +/* we can't reuse RFC 4231 test vectors, as we have constraint on the
> + * input and key size, and we truncate the output.
> + */
> +static struct test_cast tests[] = {
> +	{
> +		.key = "0b0b0b0b0b0b0b0b",
> +		.msg = "48692054",
> +		.result = "8385e24fb4235ac37556b6b886db106284a1da67",
> +	},
> +	{
> +		.key = "aaaaaaaaaaaaaaaa",
> +		.msg = "dddddddd",
> +		.result = "2c5e219164ff1dca1c4a92318d847bb6b9d44492",
> +	},
> +	{
> +		.key = "0102030405060708",
> +		.msg = "cdcdcdcd",
> +		.result = "e73b9ba9969969cefb04aa0d6df18ec2fcc075b6",
> +	},
> +};
> +
> +static void __init crypto_test(void)
> +{
> +	char hmac[20], hmac_hex[41];
> +	u32 nonce1, nonce2;
> +	u64 key1, key2;
> +	int i, j;
> +
> +	for (i = 0; i < ARRAY_SIZE(tests); ++i) {
> +		/* mptcp hmap will convert to be before computing the hmac */
> +		key1 = be64_to_cpu(*((__be64 *)&tests[i].key[0]));
> +		key2 = be64_to_cpu(*((__be64 *)&tests[i].key[8]));
> +		nonce1 = be32_to_cpu(*((__be32 *)&tests[i].msg[0]));
> +		nonce2 = be32_to_cpu(*((__be32 *)&tests[i].msg[4]));
> +
> +		mptcp_crypto_hmac_sha(key1, key2, nonce1, nonce2, hmac);
> +		for (j = 0; j < 20; ++j)
> +			sprintf(&hmac_hex[j << 1], "%02x", hmac[j] & 0xff);
> +		hmac_hex[40] = 0;
> +
> +		if (memcmp(hmac_hex, tests[i].result, 40))
> +			pr_err("test %d failed, got %s expected %s", i,
> +			       hmac_hex, tests[i].result);
> +		else
> +			pr_info("test %d [ ok ]", i);
> +	}
>  }
> +
> +late_initcall(crypto_test);
> +#endif
> diff --git a/net/mptcp/options.c b/net/mptcp/options.c
> index 2f014332cdef..1cb0bd687b6b 100644
> --- a/net/mptcp/options.c
> +++ b/net/mptcp/options.c
> @@ -9,6 +9,11 @@
>  #include <net/mptcp.h>
>  #include "protocol.h"
>  
> +static bool mptcp_cap_flag_sha256(u8 flags)
> +{
> +	return (flags & MPTCP_CAP_FLAG_MASK) == MPTCP_CAP_HMAC_SHA256;
> +}
> +
>  void mptcp_parse_option(const unsigned char *ptr, int opsize,
>  			struct tcp_options_received *opt_rx)
>  {
> @@ -33,7 +38,7 @@ void mptcp_parse_option(const unsigned char *ptr, int opsize,
>  			break;
>  
>  		mp_opt->flags = *ptr++;
> -		if (!((mp_opt->flags & MPTCP_CAP_FLAG_MASK) == MPTCP_CAP_HMAC_SHA1) ||
> +		if (!mptcp_cap_flag_sha256(mp_opt->flags) ||
>  		    (mp_opt->flags & MPTCP_CAP_EXTENSIBILITY))
>  			break;
>  
> @@ -434,7 +439,7 @@ void mptcp_write_options(__be32 *ptr, struct mptcp_out_options *opts)
>  		*ptr++ = htonl((TCPOPT_MPTCP << 24) | (len << 16) |
>  			       (MPTCPOPT_MP_CAPABLE << 12) |
>  			       ((MPTCP_VERSION_MASK & 0) << 8) |
> -			       MPTCP_CAP_HMAC_SHA1);
> +			       MPTCP_CAP_HMAC_SHA256);
>  		put_unaligned_be64(opts->sndr_key, ptr);
>  		ptr += 2;
>  		if ((OPTION_MPTCP_MPC_SYNACK |
> diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h
> index 542aa9b67a60..dcdd3dcd19c6 100644
> --- a/net/mptcp/protocol.h
> +++ b/net/mptcp/protocol.h
> @@ -41,7 +41,7 @@
>  #define MPTCP_VERSION_MASK	(0x0F)
>  #define MPTCP_CAP_CHECKSUM_REQD	BIT(7)
>  #define MPTCP_CAP_EXTENSIBILITY	BIT(6)
> -#define MPTCP_CAP_HMAC_SHA1	BIT(0)
> +#define MPTCP_CAP_HMAC_SHA256	BIT(0)
>  #define MPTCP_CAP_FLAG_MASK	(0x3F)
>  
>  /* MPTCP DSS flags */
> @@ -201,7 +201,7 @@ static inline void mptcp_crypto_key_gen_sha(u64 *key, u32 *token, u64 *idsn)
>  }
>  
>  void mptcp_crypto_hmac_sha(u64 key1, u64 key2, u32 nonce1, u32 nonce2,
> -			   u32 *hash_out);
> +			   void *hash_out);
>  
>  static inline struct mptcp_ext *mptcp_get_ext(struct sk_buff *skb)
>  {
diff mbox series

Patch

diff --git a/net/mptcp/Kconfig b/net/mptcp/Kconfig
index c1a99f07a4cd..5db56d2218c5 100644
--- a/net/mptcp/Kconfig
+++ b/net/mptcp/Kconfig
@@ -3,6 +3,7 @@  config MPTCP
 	bool "MPTCP: Multipath TCP"
 	depends on INET
 	select SKB_EXTENSIONS
+	select CRYPTO_LIB_SHA256
 	help
 	  Multipath TCP (MPTCP) connections send and receive data over multiple
 	  subflows in order to utilize multiple network paths. Each subflow
@@ -14,3 +15,12 @@  config MPTCP_IPV6
 	depends on MPTCP
 	select IPV6
 	default y
+
+config MPTCP_HMAC_TEST
+	bool "Tests for MPTCP HMAC implementation"
+	default n
+	help
+	  This option enable boot time self-test for the HMAC implementation
+	  used by the MPTCP code
+
+	  Say N if you are unsure.
diff --git a/net/mptcp/crypto.c b/net/mptcp/crypto.c
index ccb9f7effdcd..68f1758b96c2 100644
--- a/net/mptcp/crypto.c
+++ b/net/mptcp/crypto.c
@@ -21,67 +21,36 @@ 
  */
 
 #include <linux/kernel.h>
-#include <linux/cryptohash.h>
+#include <crypto/sha.h>
 #include <asm/unaligned.h>
 
 #include "protocol.h"
 
-struct sha1_state {
-	u32 workspace[SHA_WORKSPACE_WORDS];
-	u32 digest[SHA_DIGEST_WORDS];
-	unsigned int count;
-};
-
-static void sha1_init(struct sha1_state *state)
-{
-	sha_init(state->digest);
-	state->count = 0;
-}
-
-static void sha1_update(struct sha1_state *state, u8 *input)
-{
-	sha_transform(state->digest, input, state->workspace);
-	state->count += SHA_MESSAGE_BYTES;
-}
-
-static void sha1_pad_final(struct sha1_state *state, u8 *input, unsigned length,
-			   __be32 *mptcp_hashed_key)
-{
-	int i;
-
-	input[length] = 0x80;
-	memset(&input[length + 1], 0, SHA_MESSAGE_BYTES - length - 9);
-	put_unaligned_be64((length + state->count) << 3,
-			   &input[SHA_MESSAGE_BYTES - 8]);
-
-	sha_transform(state->digest, input, state->workspace);
-	for (i = 0; i < SHA_DIGEST_WORDS; ++i)
-		put_unaligned_be32(state->digest[i], &mptcp_hashed_key[i]);
-
-	memzero_explicit(state->workspace, SHA_WORKSPACE_WORDS << 2);
-}
+#define SHA256_DIGEST_WORDS (SHA256_DIGEST_SIZE / 4)
 
 void mptcp_crypto_key_sha(u64 key, u32 *token, u64 *idsn)
 {
-	__be32 mptcp_hashed_key[SHA_DIGEST_WORDS];
-	u8 input[SHA_MESSAGE_BYTES];
-	struct sha1_state state;
+	__be32 mptcp_hashed_key[SHA256_DIGEST_WORDS];
+	__be64 input = cpu_to_be64(key);
+	struct sha256_state state;
 
-	sha1_init(&state);
-	put_unaligned_be64(key, input);
-	sha1_pad_final(&state, input, 8, mptcp_hashed_key);
+	sha256_init(&state);
+	sha256_update(&state, (__force u8 *)&input, sizeof(input));
+	sha256_final(&state, (u8 *)mptcp_hashed_key);
 
 	if (token)
 		*token = be32_to_cpu(mptcp_hashed_key[0]);
 	if (idsn)
-		*idsn = be64_to_cpu(*((__be64 *)&mptcp_hashed_key[3]));
+		*idsn = be64_to_cpu(*((__be64 *)&mptcp_hashed_key[6]));
 }
 
 void mptcp_crypto_hmac_sha(u64 key1, u64 key2, u32 nonce1, u32 nonce2,
-			    u32 *hash_out)
+			   void *hmac)
 {
-	u8 input[SHA_MESSAGE_BYTES * 2];
-	struct sha1_state state;
+	u8 input[SHA256_BLOCK_SIZE + SHA256_DIGEST_SIZE];
+	__be32 mptcp_hashed_key[SHA256_DIGEST_WORDS];
+	__be32 *hash_out = (__force __be32 *)hmac;
+	struct sha256_state state;
 	u8 key1be[8];
 	u8 key2be[8];
 	int i;
@@ -96,17 +65,16 @@  void mptcp_crypto_hmac_sha(u64 key1, u64 key2, u32 nonce1, u32 nonce2,
 	for (i = 0; i < 8; i++)
 		input[i + 8] ^= key2be[i];
 
-	put_unaligned_be32(nonce1, &input[SHA_MESSAGE_BYTES]);
-	put_unaligned_be32(nonce2, &input[SHA_MESSAGE_BYTES + 4]);
+	put_unaligned_be32(nonce1, &input[SHA256_BLOCK_SIZE]);
+	put_unaligned_be32(nonce2, &input[SHA256_BLOCK_SIZE + 4]);
 
-	sha1_init(&state);
-	sha1_update(&state, input);
+	sha256_init(&state);
+	sha256_update(&state, input, SHA256_BLOCK_SIZE + 8);
 
 	/* emit sha256(K1 || msg) on the second input block, so we can
 	 * reuse 'input' for the last hashing
 	 */
-	sha1_pad_final(&state, &input[SHA_MESSAGE_BYTES], 8,
-		       (__force __be32 *)&input[SHA_MESSAGE_BYTES]);
+	sha256_final(&state, &input[SHA256_BLOCK_SIZE]);
 
 	/* Prepare second part of hmac */
 	memset(input, 0x5C, SHA_MESSAGE_BYTES);
@@ -115,8 +83,69 @@  void mptcp_crypto_hmac_sha(u64 key1, u64 key2, u32 nonce1, u32 nonce2,
 	for (i = 0; i < 8; i++)
 		input[i + 8] ^= key2be[i];
 
-	sha1_init(&state);
-	sha1_update(&state, input);
-	sha1_pad_final(&state, &input[SHA_MESSAGE_BYTES], SHA_DIGEST_WORDS << 2,
-		      (__be32*)hash_out);
+	sha256_init(&state);
+	sha256_update(&state, input, SHA256_BLOCK_SIZE + SHA256_DIGEST_SIZE);
+	sha256_final(&state, (u8 *)mptcp_hashed_key);
+
+	/* takes only first 160 bits */
+	for (i = 0; i < 5; i++)
+		hash_out[i] = mptcp_hashed_key[i];
+}
+
+#ifdef CONFIG_MPTCP_HMAC_TEST
+struct test_cast {
+	char *key;
+	char *msg;
+	char *result;
+};
+
+/* we can't reuse RFC 4231 test vectors, as we have constraint on the
+ * input and key size, and we truncate the output.
+ */
+static struct test_cast tests[] = {
+	{
+		.key = "0b0b0b0b0b0b0b0b",
+		.msg = "48692054",
+		.result = "8385e24fb4235ac37556b6b886db106284a1da67",
+	},
+	{
+		.key = "aaaaaaaaaaaaaaaa",
+		.msg = "dddddddd",
+		.result = "2c5e219164ff1dca1c4a92318d847bb6b9d44492",
+	},
+	{
+		.key = "0102030405060708",
+		.msg = "cdcdcdcd",
+		.result = "e73b9ba9969969cefb04aa0d6df18ec2fcc075b6",
+	},
+};
+
+static void __init crypto_test(void)
+{
+	char hmac[20], hmac_hex[41];
+	u32 nonce1, nonce2;
+	u64 key1, key2;
+	int i, j;
+
+	for (i = 0; i < ARRAY_SIZE(tests); ++i) {
+		/* mptcp hmap will convert to be before computing the hmac */
+		key1 = be64_to_cpu(*((__be64 *)&tests[i].key[0]));
+		key2 = be64_to_cpu(*((__be64 *)&tests[i].key[8]));
+		nonce1 = be32_to_cpu(*((__be32 *)&tests[i].msg[0]));
+		nonce2 = be32_to_cpu(*((__be32 *)&tests[i].msg[4]));
+
+		mptcp_crypto_hmac_sha(key1, key2, nonce1, nonce2, hmac);
+		for (j = 0; j < 20; ++j)
+			sprintf(&hmac_hex[j << 1], "%02x", hmac[j] & 0xff);
+		hmac_hex[40] = 0;
+
+		if (memcmp(hmac_hex, tests[i].result, 40))
+			pr_err("test %d failed, got %s expected %s", i,
+			       hmac_hex, tests[i].result);
+		else
+			pr_info("test %d [ ok ]", i);
+	}
 }
+
+late_initcall(crypto_test);
+#endif
diff --git a/net/mptcp/options.c b/net/mptcp/options.c
index 2f014332cdef..1cb0bd687b6b 100644
--- a/net/mptcp/options.c
+++ b/net/mptcp/options.c
@@ -9,6 +9,11 @@ 
 #include <net/mptcp.h>
 #include "protocol.h"
 
+static bool mptcp_cap_flag_sha256(u8 flags)
+{
+	return (flags & MPTCP_CAP_FLAG_MASK) == MPTCP_CAP_HMAC_SHA256;
+}
+
 void mptcp_parse_option(const unsigned char *ptr, int opsize,
 			struct tcp_options_received *opt_rx)
 {
@@ -33,7 +38,7 @@  void mptcp_parse_option(const unsigned char *ptr, int opsize,
 			break;
 
 		mp_opt->flags = *ptr++;
-		if (!((mp_opt->flags & MPTCP_CAP_FLAG_MASK) == MPTCP_CAP_HMAC_SHA1) ||
+		if (!mptcp_cap_flag_sha256(mp_opt->flags) ||
 		    (mp_opt->flags & MPTCP_CAP_EXTENSIBILITY))
 			break;
 
@@ -434,7 +439,7 @@  void mptcp_write_options(__be32 *ptr, struct mptcp_out_options *opts)
 		*ptr++ = htonl((TCPOPT_MPTCP << 24) | (len << 16) |
 			       (MPTCPOPT_MP_CAPABLE << 12) |
 			       ((MPTCP_VERSION_MASK & 0) << 8) |
-			       MPTCP_CAP_HMAC_SHA1);
+			       MPTCP_CAP_HMAC_SHA256);
 		put_unaligned_be64(opts->sndr_key, ptr);
 		ptr += 2;
 		if ((OPTION_MPTCP_MPC_SYNACK |
diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h
index 542aa9b67a60..dcdd3dcd19c6 100644
--- a/net/mptcp/protocol.h
+++ b/net/mptcp/protocol.h
@@ -41,7 +41,7 @@ 
 #define MPTCP_VERSION_MASK	(0x0F)
 #define MPTCP_CAP_CHECKSUM_REQD	BIT(7)
 #define MPTCP_CAP_EXTENSIBILITY	BIT(6)
-#define MPTCP_CAP_HMAC_SHA1	BIT(0)
+#define MPTCP_CAP_HMAC_SHA256	BIT(0)
 #define MPTCP_CAP_FLAG_MASK	(0x3F)
 
 /* MPTCP DSS flags */
@@ -201,7 +201,7 @@  static inline void mptcp_crypto_key_gen_sha(u64 *key, u32 *token, u64 *idsn)
 }
 
 void mptcp_crypto_hmac_sha(u64 key1, u64 key2, u32 nonce1, u32 nonce2,
-			   u32 *hash_out);
+			   void *hash_out);
 
 static inline struct mptcp_ext *mptcp_get_ext(struct sk_buff *skb)
 {