// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * Copyright (c) 2016, Intel Corporation
 * Authors: Salvatore Benedetto <salvatore.benedetto@intel.com>
 */
#include <linux/kernel.h>
#include <linux/export.h>
#include <linux/err.h>
#include <linux/string.h>
#include <crypto/dh.h>
#include <crypto/kpp.h>

#define DH_KPP_SECRET_MIN_SIZE (sizeof(struct kpp_secret) + 3 * sizeof(int))

static inline u8 *dh_pack_data(u8 *dst, u8 *end, const void *src, size_t size)
{
	if (!dst || size > end - dst)
		return NULL;
	memcpy(dst, src, size);
	return dst + size;
}

static inline const u8 *dh_unpack_data(void *dst, const void *src, size_t size)
{
	memcpy(dst, src, size);
	return src + size;
}

static inline unsigned int dh_data_size(const struct dh *p)
{
	return p->key_size + p->p_size + p->g_size;
}

unsigned int crypto_dh_key_len(const struct dh *p)
{
	return DH_KPP_SECRET_MIN_SIZE + dh_data_size(p);
}
EXPORT_SYMBOL_GPL(crypto_dh_key_len);

int crypto_dh_encode_key(char *buf, unsigned int len, const struct dh *params)
{
	u8 *ptr = buf;
	u8 * const end = ptr + len;
	struct kpp_secret secret = {
		.type = CRYPTO_KPP_SECRET_TYPE_DH,
		.len = len
	};

	if (unlikely(!len))
		return -EINVAL;

	ptr = dh_pack_data(ptr, end, &secret, sizeof(secret));
	ptr = dh_pack_data(ptr, end, &params->key_size,
			   sizeof(params->key_size));
	ptr = dh_pack_data(ptr, end, &params->p_size, sizeof(params->p_size));
	ptr = dh_pack_data(ptr, end, &params->g_size, sizeof(params->g_size));
	ptr = dh_pack_data(ptr, end, params->key, params->key_size);
	ptr = dh_pack_data(ptr, end, params->p, params->p_size);
	ptr = dh_pack_data(ptr, end, params->g, params->g_size);
	if (ptr != end)
		return -EINVAL;
	return 0;
}
EXPORT_SYMBOL_GPL(crypto_dh_encode_key);

int __crypto_dh_decode_key(const char *buf, unsigned int len, struct dh *params)
{
	const u8 *ptr = buf;
	struct kpp_secret secret;

	if (unlikely(!buf || len < DH_KPP_SECRET_MIN_SIZE))
		return -EINVAL;

	ptr = dh_unpack_data(&secret, ptr, sizeof(secret));
	if (secret.type != CRYPTO_KPP_SECRET_TYPE_DH)
		return -EINVAL;

	ptr = dh_unpack_data(&params->key_size, ptr, sizeof(params->key_size));
	ptr = dh_unpack_data(&params->p_size, ptr, sizeof(params->p_size));
	ptr = dh_unpack_data(&params->g_size, ptr, sizeof(params->g_size));
	if (secret.len != crypto_dh_key_len(params))
		return -EINVAL;

	/* Don't allocate memory. Set pointers to data within
	 * the given buffer
	 */
	params->key = (void *)ptr;
	params->p = (void *)(ptr + params->key_size);
	params->g = (void *)(ptr + params->key_size + params->p_size);

	return 0;
}

int crypto_dh_decode_key(const char *buf, unsigned int len, struct dh *params)
{
	int err;

	err = __crypto_dh_decode_key(buf, len, params);
	if (err)
		return err;

	/*
	 * Don't permit the buffer for 'key' or 'g' to be larger than 'p', since
	 * some drivers assume otherwise.
	 */
	if (params->key_size > params->p_size ||
	    params->g_size > params->p_size)
		return -EINVAL;

	/*
	 * Don't permit 'p' to be 0.  It's not a prime number, and it's subject
	 * to corner cases such as 'mod 0' being undefined or
	 * crypto_kpp_maxsize() returning 0.
	 */
	if (memchr_inv(params->p, 0, params->p_size) == NULL)
		return -EINVAL;

	return 0;
}
EXPORT_SYMBOL_GPL(crypto_dh_decode_key);
