cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

dh_helper.c (3265B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * Copyright (c) 2016, Intel Corporation
      4 * Authors: Salvatore Benedetto <salvatore.benedetto@intel.com>
      5 */
      6#include <linux/kernel.h>
      7#include <linux/export.h>
      8#include <linux/err.h>
      9#include <linux/string.h>
     10#include <crypto/dh.h>
     11#include <crypto/kpp.h>
     12
     13#define DH_KPP_SECRET_MIN_SIZE (sizeof(struct kpp_secret) + 3 * sizeof(int))
     14
     15static inline u8 *dh_pack_data(u8 *dst, u8 *end, const void *src, size_t size)
     16{
     17	if (!dst || size > end - dst)
     18		return NULL;
     19	memcpy(dst, src, size);
     20	return dst + size;
     21}
     22
     23static inline const u8 *dh_unpack_data(void *dst, const void *src, size_t size)
     24{
     25	memcpy(dst, src, size);
     26	return src + size;
     27}
     28
     29static inline unsigned int dh_data_size(const struct dh *p)
     30{
     31	return p->key_size + p->p_size + p->g_size;
     32}
     33
     34unsigned int crypto_dh_key_len(const struct dh *p)
     35{
     36	return DH_KPP_SECRET_MIN_SIZE + dh_data_size(p);
     37}
     38EXPORT_SYMBOL_GPL(crypto_dh_key_len);
     39
     40int crypto_dh_encode_key(char *buf, unsigned int len, const struct dh *params)
     41{
     42	u8 *ptr = buf;
     43	u8 * const end = ptr + len;
     44	struct kpp_secret secret = {
     45		.type = CRYPTO_KPP_SECRET_TYPE_DH,
     46		.len = len
     47	};
     48
     49	if (unlikely(!len))
     50		return -EINVAL;
     51
     52	ptr = dh_pack_data(ptr, end, &secret, sizeof(secret));
     53	ptr = dh_pack_data(ptr, end, &params->key_size,
     54			   sizeof(params->key_size));
     55	ptr = dh_pack_data(ptr, end, &params->p_size, sizeof(params->p_size));
     56	ptr = dh_pack_data(ptr, end, &params->g_size, sizeof(params->g_size));
     57	ptr = dh_pack_data(ptr, end, params->key, params->key_size);
     58	ptr = dh_pack_data(ptr, end, params->p, params->p_size);
     59	ptr = dh_pack_data(ptr, end, params->g, params->g_size);
     60	if (ptr != end)
     61		return -EINVAL;
     62	return 0;
     63}
     64EXPORT_SYMBOL_GPL(crypto_dh_encode_key);
     65
     66int __crypto_dh_decode_key(const char *buf, unsigned int len, struct dh *params)
     67{
     68	const u8 *ptr = buf;
     69	struct kpp_secret secret;
     70
     71	if (unlikely(!buf || len < DH_KPP_SECRET_MIN_SIZE))
     72		return -EINVAL;
     73
     74	ptr = dh_unpack_data(&secret, ptr, sizeof(secret));
     75	if (secret.type != CRYPTO_KPP_SECRET_TYPE_DH)
     76		return -EINVAL;
     77
     78	ptr = dh_unpack_data(&params->key_size, ptr, sizeof(params->key_size));
     79	ptr = dh_unpack_data(&params->p_size, ptr, sizeof(params->p_size));
     80	ptr = dh_unpack_data(&params->g_size, ptr, sizeof(params->g_size));
     81	if (secret.len != crypto_dh_key_len(params))
     82		return -EINVAL;
     83
     84	/* Don't allocate memory. Set pointers to data within
     85	 * the given buffer
     86	 */
     87	params->key = (void *)ptr;
     88	params->p = (void *)(ptr + params->key_size);
     89	params->g = (void *)(ptr + params->key_size + params->p_size);
     90
     91	return 0;
     92}
     93
     94int crypto_dh_decode_key(const char *buf, unsigned int len, struct dh *params)
     95{
     96	int err;
     97
     98	err = __crypto_dh_decode_key(buf, len, params);
     99	if (err)
    100		return err;
    101
    102	/*
    103	 * Don't permit the buffer for 'key' or 'g' to be larger than 'p', since
    104	 * some drivers assume otherwise.
    105	 */
    106	if (params->key_size > params->p_size ||
    107	    params->g_size > params->p_size)
    108		return -EINVAL;
    109
    110	/*
    111	 * Don't permit 'p' to be 0.  It's not a prime number, and it's subject
    112	 * to corner cases such as 'mod 0' being undefined or
    113	 * crypto_kpp_maxsize() returning 0.
    114	 */
    115	if (memchr_inv(params->p, 0, params->p_size) == NULL)
    116		return -EINVAL;
    117
    118	return 0;
    119}
    120EXPORT_SYMBOL_GPL(crypto_dh_decode_key);