Skip to content

Commit

Permalink
mptcp: use untruncated hash in ADD_ADDR HMAC
Browse files Browse the repository at this point in the history
There is some ambiguity in the RFC as to whether the ADD_ADDR HMAC is
the rightmost 64 bits of the entire hash or of the leftmost 160 bits
of the hash.  The intention, as clarified with the author of the RFC,
is the entire hash.

This change returns the entire hash from
mptcp_crypto_hmac_sha (instead of only the first 160 bits), and moves
any truncation/selection operation on the hash to the caller.

Fixes: 12555a2 ("mptcp: use rightmost 64 bits in ADD_ADDR HMAC")
Reviewed-by: Christoph Paasch <cpaasch@apple.com>
Reviewed-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: Todd Malsbary <todd.malsbary@linux.intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Todd Malsbary authored and David S. Miller committed May 22, 2020
1 parent a765421 commit bd69722
Show file tree
Hide file tree
Showing 4 changed files with 24 additions and 25 deletions.
24 changes: 9 additions & 15 deletions net/mptcp/crypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,6 @@ void mptcp_crypto_key_sha(u64 key, u32 *token, u64 *idsn)
void mptcp_crypto_hmac_sha(u64 key1, u64 key2, u8 *msg, int len, void *hmac)
{
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];
Expand Down Expand Up @@ -86,11 +84,7 @@ void mptcp_crypto_hmac_sha(u64 key1, u64 key2, u8 *msg, int len, void *hmac)

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];
sha256_final(&state, (u8 *)hmac);
}

#ifdef CONFIG_MPTCP_HMAC_TEST
Expand All @@ -101,29 +95,29 @@ struct test_cast {
};

/* we can't reuse RFC 4231 test vectors, as we have constraint on the
* input and key size, and we truncate the output.
* input and key size.
*/
static struct test_cast tests[] = {
{
.key = "0b0b0b0b0b0b0b0b",
.msg = "48692054",
.result = "8385e24fb4235ac37556b6b886db106284a1da67",
.result = "8385e24fb4235ac37556b6b886db106284a1da671699f46db1f235ec622dcafa",
},
{
.key = "aaaaaaaaaaaaaaaa",
.msg = "dddddddd",
.result = "2c5e219164ff1dca1c4a92318d847bb6b9d44492",
.result = "2c5e219164ff1dca1c4a92318d847bb6b9d44492984e1eb71aff9022f71046e9",
},
{
.key = "0102030405060708",
.msg = "cdcdcdcd",
.result = "e73b9ba9969969cefb04aa0d6df18ec2fcc075b6",
.result = "e73b9ba9969969cefb04aa0d6df18ec2fcc075b6f23b4d8c4da736a5dbbc6e7d",
},
};

static int __init test_mptcp_crypto(void)
{
char hmac[20], hmac_hex[41];
char hmac[32], hmac_hex[65];
u32 nonce1, nonce2;
u64 key1, key2;
u8 msg[8];
Expand All @@ -140,11 +134,11 @@ static int __init test_mptcp_crypto(void)
put_unaligned_be32(nonce2, &msg[4]);

mptcp_crypto_hmac_sha(key1, key2, msg, 8, hmac);
for (j = 0; j < 20; ++j)
for (j = 0; j < 32; ++j)
sprintf(&hmac_hex[j << 1], "%02x", hmac[j] & 0xff);
hmac_hex[40] = 0;
hmac_hex[64] = 0;

if (memcmp(hmac_hex, tests[i].result, 40))
if (memcmp(hmac_hex, tests[i].result, 64))
pr_err("test %d failed, got %s expected %s", i,
hmac_hex, tests[i].result);
else
Expand Down
9 changes: 5 additions & 4 deletions net/mptcp/options.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#define pr_fmt(fmt) "MPTCP: " fmt

#include <linux/kernel.h>
#include <crypto/sha.h>
#include <net/tcp.h>
#include <net/mptcp.h>
#include "protocol.h"
Expand Down Expand Up @@ -535,7 +536,7 @@ static bool mptcp_established_options_dss(struct sock *sk, struct sk_buff *skb,
static u64 add_addr_generate_hmac(u64 key1, u64 key2, u8 addr_id,
struct in_addr *addr)
{
u8 hmac[MPTCP_ADDR_HMAC_LEN];
u8 hmac[SHA256_DIGEST_SIZE];
u8 msg[7];

msg[0] = addr_id;
Expand All @@ -545,14 +546,14 @@ static u64 add_addr_generate_hmac(u64 key1, u64 key2, u8 addr_id,

mptcp_crypto_hmac_sha(key1, key2, msg, 7, hmac);

return get_unaligned_be64(&hmac[MPTCP_ADDR_HMAC_LEN - sizeof(u64)]);
return get_unaligned_be64(&hmac[SHA256_DIGEST_SIZE - sizeof(u64)]);
}

#if IS_ENABLED(CONFIG_MPTCP_IPV6)
static u64 add_addr6_generate_hmac(u64 key1, u64 key2, u8 addr_id,
struct in6_addr *addr)
{
u8 hmac[MPTCP_ADDR_HMAC_LEN];
u8 hmac[SHA256_DIGEST_SIZE];
u8 msg[19];

msg[0] = addr_id;
Expand All @@ -562,7 +563,7 @@ static u64 add_addr6_generate_hmac(u64 key1, u64 key2, u8 addr_id,

mptcp_crypto_hmac_sha(key1, key2, msg, 19, hmac);

return get_unaligned_be64(&hmac[MPTCP_ADDR_HMAC_LEN - sizeof(u64)]);
return get_unaligned_be64(&hmac[SHA256_DIGEST_SIZE - sizeof(u64)]);
}
#endif

Expand Down
1 change: 0 additions & 1 deletion net/mptcp/protocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,6 @@

/* MPTCP ADD_ADDR flags */
#define MPTCP_ADDR_ECHO BIT(0)
#define MPTCP_ADDR_HMAC_LEN 20
#define MPTCP_ADDR_IPVERSION_4 4
#define MPTCP_ADDR_IPVERSION_6 6

Expand Down
15 changes: 10 additions & 5 deletions net/mptcp/subflow.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <linux/module.h>
#include <linux/netdevice.h>
#include <crypto/algapi.h>
#include <crypto/sha.h>
#include <net/sock.h>
#include <net/inet_common.h>
#include <net/inet_hashtables.h>
Expand Down Expand Up @@ -89,7 +90,7 @@ static bool subflow_token_join_request(struct request_sock *req,
const struct sk_buff *skb)
{
struct mptcp_subflow_request_sock *subflow_req = mptcp_subflow_rsk(req);
u8 hmac[MPTCPOPT_HMAC_LEN];
u8 hmac[SHA256_DIGEST_SIZE];
struct mptcp_sock *msk;
int local_id;

Expand Down Expand Up @@ -201,7 +202,7 @@ static void subflow_v6_init_req(struct request_sock *req,
/* validate received truncated hmac and create hmac for third ACK */
static bool subflow_thmac_valid(struct mptcp_subflow_context *subflow)
{
u8 hmac[MPTCPOPT_HMAC_LEN];
u8 hmac[SHA256_DIGEST_SIZE];
u64 thmac;

subflow_generate_hmac(subflow->remote_key, subflow->local_key,
Expand Down Expand Up @@ -267,6 +268,8 @@ static void subflow_finish_connect(struct sock *sk, const struct sk_buff *skb)
subflow->ssn_offset = TCP_SKB_CB(skb)->seq;
}
} else if (subflow->mp_join) {
u8 hmac[SHA256_DIGEST_SIZE];

pr_debug("subflow=%p, thmac=%llu, remote_nonce=%u",
subflow, subflow->thmac,
subflow->remote_nonce);
Expand All @@ -279,7 +282,9 @@ static void subflow_finish_connect(struct sock *sk, const struct sk_buff *skb)
subflow_generate_hmac(subflow->local_key, subflow->remote_key,
subflow->local_nonce,
subflow->remote_nonce,
subflow->hmac);
hmac);

memcpy(subflow->hmac, hmac, MPTCPOPT_HMAC_LEN);

if (skb)
subflow->ssn_offset = TCP_SKB_CB(skb)->seq;
Expand Down Expand Up @@ -347,7 +352,7 @@ static bool subflow_hmac_valid(const struct request_sock *req,
const struct mptcp_options_received *mp_opt)
{
const struct mptcp_subflow_request_sock *subflow_req;
u8 hmac[MPTCPOPT_HMAC_LEN];
u8 hmac[SHA256_DIGEST_SIZE];
struct mptcp_sock *msk;
bool ret;

Expand All @@ -361,7 +366,7 @@ static bool subflow_hmac_valid(const struct request_sock *req,
subflow_req->local_nonce, hmac);

ret = true;
if (crypto_memneq(hmac, mp_opt->hmac, sizeof(hmac)))
if (crypto_memneq(hmac, mp_opt->hmac, MPTCPOPT_HMAC_LEN))
ret = false;

sock_put((struct sock *)msk);
Expand Down

0 comments on commit bd69722

Please sign in to comment.