// 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, ¶ms->key_size,
sizeof (params->key_size));
ptr = dh_pack_data(ptr, end, ¶ms->p_size, sizeof (params->p_size));
ptr = dh_pack_data(ptr, end, ¶ms->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(¶ms->key_size, ptr, sizeof (params->key_size));
ptr = dh_unpack_data(¶ms->p_size, ptr, sizeof (params->p_size));
ptr = dh_unpack_data(¶ms->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);
Messung V0.5 in Prozent C=96 H=100 G=97
¤ Dauer der Verarbeitung: 0.9 Sekunden
(vorverarbeitet am 2026-09-29)
¤
*© Formatika GbR, Deutschland