xref: /openbmc/linux/net/mptcp/crypto.c (revision ac0ad93df7136e27d2a9c5ec554547695f581d0e)
179c0949eSPeter Krystad // SPDX-License-Identifier: GPL-2.0
279c0949eSPeter Krystad /* Multipath TCP cryptographic functions
379c0949eSPeter Krystad  * Copyright (c) 2017 - 2019, Intel Corporation.
479c0949eSPeter Krystad  *
579c0949eSPeter Krystad  * Note: This code is based on mptcp_ctrl.c, mptcp_ipv4.c, and
679c0949eSPeter Krystad  *       mptcp_ipv6 from multipath-tcp.org, authored by:
779c0949eSPeter Krystad  *
879c0949eSPeter Krystad  *       Sébastien Barré <sebastien.barre@uclouvain.be>
979c0949eSPeter Krystad  *       Christoph Paasch <christoph.paasch@uclouvain.be>
1079c0949eSPeter Krystad  *       Jaakko Korkeaniemi <jaakko.korkeaniemi@aalto.fi>
1179c0949eSPeter Krystad  *       Gregory Detal <gregory.detal@uclouvain.be>
1279c0949eSPeter Krystad  *       Fabien Duchêne <fabien.duchene@uclouvain.be>
1379c0949eSPeter Krystad  *       Andreas Seelinger <Andreas.Seelinger@rwth-aachen.de>
1479c0949eSPeter Krystad  *       Lavkesh Lahngir <lavkesh51@gmail.com>
1579c0949eSPeter Krystad  *       Andreas Ripke <ripke@neclab.eu>
1679c0949eSPeter Krystad  *       Vlad Dogaru <vlad.dogaru@intel.com>
1779c0949eSPeter Krystad  *       Octavian Purdila <octavian.purdila@intel.com>
1879c0949eSPeter Krystad  *       John Ronan <jronan@tssg.org>
1979c0949eSPeter Krystad  *       Catalin Nicutar <catalin.nicutar@gmail.com>
2079c0949eSPeter Krystad  *       Brandon Heller <brandonh@stanford.edu>
2179c0949eSPeter Krystad  */
2279c0949eSPeter Krystad 
2379c0949eSPeter Krystad #include <linux/kernel.h>
2465492c5aSPaolo Abeni #include <crypto/sha.h>
2579c0949eSPeter Krystad #include <asm/unaligned.h>
2679c0949eSPeter Krystad 
2779c0949eSPeter Krystad #include "protocol.h"
2879c0949eSPeter Krystad 
2965492c5aSPaolo Abeni #define SHA256_DIGEST_WORDS (SHA256_DIGEST_SIZE / 4)
3079c0949eSPeter Krystad 
3179c0949eSPeter Krystad void mptcp_crypto_key_sha(u64 key, u32 *token, u64 *idsn)
3279c0949eSPeter Krystad {
3365492c5aSPaolo Abeni 	__be32 mptcp_hashed_key[SHA256_DIGEST_WORDS];
3465492c5aSPaolo Abeni 	__be64 input = cpu_to_be64(key);
3565492c5aSPaolo Abeni 	struct sha256_state state;
3679c0949eSPeter Krystad 
3765492c5aSPaolo Abeni 	sha256_init(&state);
3865492c5aSPaolo Abeni 	sha256_update(&state, (__force u8 *)&input, sizeof(input));
3965492c5aSPaolo Abeni 	sha256_final(&state, (u8 *)mptcp_hashed_key);
4079c0949eSPeter Krystad 
4179c0949eSPeter Krystad 	if (token)
4279c0949eSPeter Krystad 		*token = be32_to_cpu(mptcp_hashed_key[0]);
4379c0949eSPeter Krystad 	if (idsn)
4465492c5aSPaolo Abeni 		*idsn = be64_to_cpu(*((__be64 *)&mptcp_hashed_key[6]));
4579c0949eSPeter Krystad }
4679c0949eSPeter Krystad 
473df523abSPeter Krystad void mptcp_crypto_hmac_sha(u64 key1, u64 key2, u8 *msg, int len, void *hmac)
4879c0949eSPeter Krystad {
4965492c5aSPaolo Abeni 	u8 input[SHA256_BLOCK_SIZE + SHA256_DIGEST_SIZE];
5065492c5aSPaolo Abeni 	__be32 mptcp_hashed_key[SHA256_DIGEST_WORDS];
5165492c5aSPaolo Abeni 	__be32 *hash_out = (__force __be32 *)hmac;
5265492c5aSPaolo Abeni 	struct sha256_state state;
5379c0949eSPeter Krystad 	u8 key1be[8];
5479c0949eSPeter Krystad 	u8 key2be[8];
5579c0949eSPeter Krystad 	int i;
5679c0949eSPeter Krystad 
573df523abSPeter Krystad 	if (WARN_ON_ONCE(len > SHA256_DIGEST_SIZE))
583df523abSPeter Krystad 		len = SHA256_DIGEST_SIZE;
593df523abSPeter Krystad 
6079c0949eSPeter Krystad 	put_unaligned_be64(key1, key1be);
6179c0949eSPeter Krystad 	put_unaligned_be64(key2, key2be);
6279c0949eSPeter Krystad 
6379c0949eSPeter Krystad 	/* Generate key xored with ipad */
64*ac0ad93dSEric Biggers 	memset(input, 0x36, SHA256_BLOCK_SIZE);
6579c0949eSPeter Krystad 	for (i = 0; i < 8; i++)
6679c0949eSPeter Krystad 		input[i] ^= key1be[i];
6779c0949eSPeter Krystad 	for (i = 0; i < 8; i++)
6879c0949eSPeter Krystad 		input[i + 8] ^= key2be[i];
6979c0949eSPeter Krystad 
703df523abSPeter Krystad 	memcpy(&input[SHA256_BLOCK_SIZE], msg, len);
7179c0949eSPeter Krystad 
7265492c5aSPaolo Abeni 	sha256_init(&state);
733df523abSPeter Krystad 	sha256_update(&state, input, SHA256_BLOCK_SIZE + len);
7479c0949eSPeter Krystad 
7579c0949eSPeter Krystad 	/* emit sha256(K1 || msg) on the second input block, so we can
7679c0949eSPeter Krystad 	 * reuse 'input' for the last hashing
7779c0949eSPeter Krystad 	 */
7865492c5aSPaolo Abeni 	sha256_final(&state, &input[SHA256_BLOCK_SIZE]);
7979c0949eSPeter Krystad 
8079c0949eSPeter Krystad 	/* Prepare second part of hmac */
81*ac0ad93dSEric Biggers 	memset(input, 0x5C, SHA256_BLOCK_SIZE);
8279c0949eSPeter Krystad 	for (i = 0; i < 8; i++)
8379c0949eSPeter Krystad 		input[i] ^= key1be[i];
8479c0949eSPeter Krystad 	for (i = 0; i < 8; i++)
8579c0949eSPeter Krystad 		input[i + 8] ^= key2be[i];
8679c0949eSPeter Krystad 
8765492c5aSPaolo Abeni 	sha256_init(&state);
8865492c5aSPaolo Abeni 	sha256_update(&state, input, SHA256_BLOCK_SIZE + SHA256_DIGEST_SIZE);
8965492c5aSPaolo Abeni 	sha256_final(&state, (u8 *)mptcp_hashed_key);
9065492c5aSPaolo Abeni 
9165492c5aSPaolo Abeni 	/* takes only first 160 bits */
9265492c5aSPaolo Abeni 	for (i = 0; i < 5; i++)
9365492c5aSPaolo Abeni 		hash_out[i] = mptcp_hashed_key[i];
9479c0949eSPeter Krystad }
9565492c5aSPaolo Abeni 
9665492c5aSPaolo Abeni #ifdef CONFIG_MPTCP_HMAC_TEST
9765492c5aSPaolo Abeni struct test_cast {
9865492c5aSPaolo Abeni 	char *key;
9965492c5aSPaolo Abeni 	char *msg;
10065492c5aSPaolo Abeni 	char *result;
10165492c5aSPaolo Abeni };
10265492c5aSPaolo Abeni 
10365492c5aSPaolo Abeni /* we can't reuse RFC 4231 test vectors, as we have constraint on the
10465492c5aSPaolo Abeni  * input and key size, and we truncate the output.
10565492c5aSPaolo Abeni  */
10665492c5aSPaolo Abeni static struct test_cast tests[] = {
10765492c5aSPaolo Abeni 	{
10865492c5aSPaolo Abeni 		.key = "0b0b0b0b0b0b0b0b",
10965492c5aSPaolo Abeni 		.msg = "48692054",
11065492c5aSPaolo Abeni 		.result = "8385e24fb4235ac37556b6b886db106284a1da67",
11165492c5aSPaolo Abeni 	},
11265492c5aSPaolo Abeni 	{
11365492c5aSPaolo Abeni 		.key = "aaaaaaaaaaaaaaaa",
11465492c5aSPaolo Abeni 		.msg = "dddddddd",
11565492c5aSPaolo Abeni 		.result = "2c5e219164ff1dca1c4a92318d847bb6b9d44492",
11665492c5aSPaolo Abeni 	},
11765492c5aSPaolo Abeni 	{
11865492c5aSPaolo Abeni 		.key = "0102030405060708",
11965492c5aSPaolo Abeni 		.msg = "cdcdcdcd",
12065492c5aSPaolo Abeni 		.result = "e73b9ba9969969cefb04aa0d6df18ec2fcc075b6",
12165492c5aSPaolo Abeni 	},
12265492c5aSPaolo Abeni };
12365492c5aSPaolo Abeni 
12465492c5aSPaolo Abeni static int __init test_mptcp_crypto(void)
12565492c5aSPaolo Abeni {
12665492c5aSPaolo Abeni 	char hmac[20], hmac_hex[41];
12765492c5aSPaolo Abeni 	u32 nonce1, nonce2;
12865492c5aSPaolo Abeni 	u64 key1, key2;
1293df523abSPeter Krystad 	u8 msg[8];
13065492c5aSPaolo Abeni 	int i, j;
13165492c5aSPaolo Abeni 
13265492c5aSPaolo Abeni 	for (i = 0; i < ARRAY_SIZE(tests); ++i) {
13365492c5aSPaolo Abeni 		/* mptcp hmap will convert to be before computing the hmac */
13465492c5aSPaolo Abeni 		key1 = be64_to_cpu(*((__be64 *)&tests[i].key[0]));
13565492c5aSPaolo Abeni 		key2 = be64_to_cpu(*((__be64 *)&tests[i].key[8]));
13665492c5aSPaolo Abeni 		nonce1 = be32_to_cpu(*((__be32 *)&tests[i].msg[0]));
13765492c5aSPaolo Abeni 		nonce2 = be32_to_cpu(*((__be32 *)&tests[i].msg[4]));
13865492c5aSPaolo Abeni 
1393df523abSPeter Krystad 		put_unaligned_be32(nonce1, &msg[0]);
1403df523abSPeter Krystad 		put_unaligned_be32(nonce2, &msg[4]);
1413df523abSPeter Krystad 
1423df523abSPeter Krystad 		mptcp_crypto_hmac_sha(key1, key2, msg, 8, hmac);
14365492c5aSPaolo Abeni 		for (j = 0; j < 20; ++j)
14465492c5aSPaolo Abeni 			sprintf(&hmac_hex[j << 1], "%02x", hmac[j] & 0xff);
14565492c5aSPaolo Abeni 		hmac_hex[40] = 0;
14665492c5aSPaolo Abeni 
14765492c5aSPaolo Abeni 		if (memcmp(hmac_hex, tests[i].result, 40))
14865492c5aSPaolo Abeni 			pr_err("test %d failed, got %s expected %s", i,
14965492c5aSPaolo Abeni 			       hmac_hex, tests[i].result);
15065492c5aSPaolo Abeni 		else
15165492c5aSPaolo Abeni 			pr_info("test %d [ ok ]", i);
15265492c5aSPaolo Abeni 	}
15365492c5aSPaolo Abeni 	return 0;
15465492c5aSPaolo Abeni }
15565492c5aSPaolo Abeni 
15665492c5aSPaolo Abeni late_initcall(test_mptcp_crypto);
15765492c5aSPaolo Abeni #endif
158