162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/* Multipath TCP cryptographic functions
362306a36Sopenharmony_ci * Copyright (c) 2017 - 2019, Intel Corporation.
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Note: This code is based on mptcp_ctrl.c, mptcp_ipv4.c, and
662306a36Sopenharmony_ci *       mptcp_ipv6 from multipath-tcp.org, authored by:
762306a36Sopenharmony_ci *
862306a36Sopenharmony_ci *       Sébastien Barré <sebastien.barre@uclouvain.be>
962306a36Sopenharmony_ci *       Christoph Paasch <christoph.paasch@uclouvain.be>
1062306a36Sopenharmony_ci *       Jaakko Korkeaniemi <jaakko.korkeaniemi@aalto.fi>
1162306a36Sopenharmony_ci *       Gregory Detal <gregory.detal@uclouvain.be>
1262306a36Sopenharmony_ci *       Fabien Duchêne <fabien.duchene@uclouvain.be>
1362306a36Sopenharmony_ci *       Andreas Seelinger <Andreas.Seelinger@rwth-aachen.de>
1462306a36Sopenharmony_ci *       Lavkesh Lahngir <lavkesh51@gmail.com>
1562306a36Sopenharmony_ci *       Andreas Ripke <ripke@neclab.eu>
1662306a36Sopenharmony_ci *       Vlad Dogaru <vlad.dogaru@intel.com>
1762306a36Sopenharmony_ci *       Octavian Purdila <octavian.purdila@intel.com>
1862306a36Sopenharmony_ci *       John Ronan <jronan@tssg.org>
1962306a36Sopenharmony_ci *       Catalin Nicutar <catalin.nicutar@gmail.com>
2062306a36Sopenharmony_ci *       Brandon Heller <brandonh@stanford.edu>
2162306a36Sopenharmony_ci */
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_ci#include <linux/kernel.h>
2462306a36Sopenharmony_ci#include <crypto/sha2.h>
2562306a36Sopenharmony_ci#include <asm/unaligned.h>
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci#include "protocol.h"
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci#define SHA256_DIGEST_WORDS (SHA256_DIGEST_SIZE / 4)
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_civoid mptcp_crypto_key_sha(u64 key, u32 *token, u64 *idsn)
3262306a36Sopenharmony_ci{
3362306a36Sopenharmony_ci	__be32 mptcp_hashed_key[SHA256_DIGEST_WORDS];
3462306a36Sopenharmony_ci	__be64 input = cpu_to_be64(key);
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ci	sha256((__force u8 *)&input, sizeof(input), (u8 *)mptcp_hashed_key);
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci	if (token)
3962306a36Sopenharmony_ci		*token = be32_to_cpu(mptcp_hashed_key[0]);
4062306a36Sopenharmony_ci	if (idsn)
4162306a36Sopenharmony_ci		*idsn = be64_to_cpu(*((__be64 *)&mptcp_hashed_key[6]));
4262306a36Sopenharmony_ci}
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_civoid mptcp_crypto_hmac_sha(u64 key1, u64 key2, u8 *msg, int len, void *hmac)
4562306a36Sopenharmony_ci{
4662306a36Sopenharmony_ci	u8 input[SHA256_BLOCK_SIZE + SHA256_DIGEST_SIZE];
4762306a36Sopenharmony_ci	u8 key1be[8];
4862306a36Sopenharmony_ci	u8 key2be[8];
4962306a36Sopenharmony_ci	int i;
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_ci	if (WARN_ON_ONCE(len > SHA256_DIGEST_SIZE))
5262306a36Sopenharmony_ci		len = SHA256_DIGEST_SIZE;
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ci	put_unaligned_be64(key1, key1be);
5562306a36Sopenharmony_ci	put_unaligned_be64(key2, key2be);
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci	/* Generate key xored with ipad */
5862306a36Sopenharmony_ci	memset(input, 0x36, SHA256_BLOCK_SIZE);
5962306a36Sopenharmony_ci	for (i = 0; i < 8; i++)
6062306a36Sopenharmony_ci		input[i] ^= key1be[i];
6162306a36Sopenharmony_ci	for (i = 0; i < 8; i++)
6262306a36Sopenharmony_ci		input[i + 8] ^= key2be[i];
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ci	memcpy(&input[SHA256_BLOCK_SIZE], msg, len);
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_ci	/* emit sha256(K1 || msg) on the second input block, so we can
6762306a36Sopenharmony_ci	 * reuse 'input' for the last hashing
6862306a36Sopenharmony_ci	 */
6962306a36Sopenharmony_ci	sha256(input, SHA256_BLOCK_SIZE + len, &input[SHA256_BLOCK_SIZE]);
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ci	/* Prepare second part of hmac */
7262306a36Sopenharmony_ci	memset(input, 0x5C, SHA256_BLOCK_SIZE);
7362306a36Sopenharmony_ci	for (i = 0; i < 8; i++)
7462306a36Sopenharmony_ci		input[i] ^= key1be[i];
7562306a36Sopenharmony_ci	for (i = 0; i < 8; i++)
7662306a36Sopenharmony_ci		input[i + 8] ^= key2be[i];
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_ci	sha256(input, SHA256_BLOCK_SIZE + SHA256_DIGEST_SIZE, hmac);
7962306a36Sopenharmony_ci}
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_ci#if IS_MODULE(CONFIG_MPTCP_KUNIT_TEST)
8262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(mptcp_crypto_hmac_sha);
8362306a36Sopenharmony_ci#endif
84