mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	crypto: ecdh - Add ECDH software support
* Implement ECDH under kpp API * Provide ECC software support for curve P-192 and P-256. * Add kpp test for ECDH with data generated by OpenSSL Signed-off-by: Salvatore Benedetto <salvatore.benedetto@intel.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
This commit is contained in:
		
							parent
							
								
									802c7f1c84
								
							
						
					
					
						commit
						3c4b23901a
					
				
					 11 changed files with 1538 additions and 0 deletions
				
			
		| 
						 | 
				
			
			@ -118,6 +118,11 @@ config CRYPTO_DH
 | 
			
		|||
	help
 | 
			
		||||
	  Generic implementation of the Diffie-Hellman algorithm.
 | 
			
		||||
 | 
			
		||||
config CRYPTO_ECDH
 | 
			
		||||
	tristate "ECDH algorithm"
 | 
			
		||||
	select CRYTPO_KPP
 | 
			
		||||
	help
 | 
			
		||||
	  Generic implementation of the ECDH algorithm
 | 
			
		||||
 | 
			
		||||
config CRYPTO_MANAGER
 | 
			
		||||
	tristate "Cryptographic algorithm manager"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -35,6 +35,10 @@ obj-$(CONFIG_CRYPTO_KPP2) += kpp.o
 | 
			
		|||
dh_generic-y := dh.o
 | 
			
		||||
dh_generic-y += dh_helper.o
 | 
			
		||||
obj-$(CONFIG_CRYPTO_DH) += dh_generic.o
 | 
			
		||||
ecdh_generic-y := ecc.o
 | 
			
		||||
ecdh_generic-y += ecdh.o
 | 
			
		||||
ecdh_generic-y += ecdh_helper.o
 | 
			
		||||
obj-$(CONFIG_CRYPTO_ECDH) += ecdh_generic.o
 | 
			
		||||
 | 
			
		||||
$(obj)/rsapubkey-asn1.o: $(obj)/rsapubkey-asn1.c $(obj)/rsapubkey-asn1.h
 | 
			
		||||
$(obj)/rsaprivkey-asn1.o: $(obj)/rsaprivkey-asn1.c $(obj)/rsaprivkey-asn1.h
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										1018
									
								
								crypto/ecc.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1018
									
								
								crypto/ecc.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										83
									
								
								crypto/ecc.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								crypto/ecc.h
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,83 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2013, Kenneth MacKay
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions are
 | 
			
		||||
 * met:
 | 
			
		||||
 *  * Redistributions of source code must retain the above copyright
 | 
			
		||||
 *   notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *  * Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *    documentation and/or other materials provided with the distribution.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
			
		||||
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
			
		||||
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | 
			
		||||
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | 
			
		||||
 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
			
		||||
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | 
			
		||||
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | 
			
		||||
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | 
			
		||||
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
			
		||||
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | 
			
		||||
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 */
 | 
			
		||||
#ifndef _CRYPTO_ECC_H
 | 
			
		||||
#define _CRYPTO_ECC_H
 | 
			
		||||
 | 
			
		||||
#define ECC_MAX_DIGITS	4 /* 256 */
 | 
			
		||||
 | 
			
		||||
#define ECC_DIGITS_TO_BYTES_SHIFT 3
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * ecc_is_key_valid() - Validate a given ECDH private key
 | 
			
		||||
 *
 | 
			
		||||
 * @curve_id:		id representing the curve to use
 | 
			
		||||
 * @ndigits:		curve number of digits
 | 
			
		||||
 * @private_key:	private key to be used for the given curve
 | 
			
		||||
 * @private_key_len:	private key len
 | 
			
		||||
 *
 | 
			
		||||
 * Returns 0 if the key is acceptable, a negative value otherwise
 | 
			
		||||
 */
 | 
			
		||||
int ecc_is_key_valid(unsigned int curve_id, unsigned int ndigits,
 | 
			
		||||
		     const u8 *private_key, unsigned int private_key_len);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * ecdh_make_pub_key() - Compute an ECC public key
 | 
			
		||||
 *
 | 
			
		||||
 * @curve_id:		id representing the curve to use
 | 
			
		||||
 * @private_key:	pregenerated private key for the given curve
 | 
			
		||||
 * @private_key_len:	length of private_key
 | 
			
		||||
 * @public_key:		buffer for storing the public key generated
 | 
			
		||||
 * @public_key_len:	length of the public_key buffer
 | 
			
		||||
 *
 | 
			
		||||
 * Returns 0 if the public key was generated successfully, a negative value
 | 
			
		||||
 * if an error occurred.
 | 
			
		||||
 */
 | 
			
		||||
int ecdh_make_pub_key(const unsigned int curve_id, unsigned int ndigits,
 | 
			
		||||
		      const u8 *private_key, unsigned int private_key_len,
 | 
			
		||||
		      u8 *public_key, unsigned int public_key_len);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * ecdh_shared_secret() - Compute a shared secret
 | 
			
		||||
 *
 | 
			
		||||
 * @curve_id:		id representing the curve to use
 | 
			
		||||
 * @private_key:	private key of part A
 | 
			
		||||
 * @private_key_len:	length of private_key
 | 
			
		||||
 * @public_key:		public key of counterpart B
 | 
			
		||||
 * @public_key_len:	length of public_key
 | 
			
		||||
 * @secret:		buffer for storing the calculated shared secret
 | 
			
		||||
 * @secret_len:		length of the secret buffer
 | 
			
		||||
 *
 | 
			
		||||
 * Note: It is recommended that you hash the result of ecdh_shared_secret
 | 
			
		||||
 * before using it for symmetric encryption or HMAC.
 | 
			
		||||
 *
 | 
			
		||||
 * Returns 0 if the shared secret was generated successfully, a negative value
 | 
			
		||||
 * if an error occurred.
 | 
			
		||||
 */
 | 
			
		||||
int ecdh_shared_secret(unsigned int curve_id, unsigned int ndigits,
 | 
			
		||||
		       const u8 *private_key, unsigned int private_key_len,
 | 
			
		||||
		       const u8 *public_key, unsigned int public_key_len,
 | 
			
		||||
		       u8 *secret, unsigned int secret_len);
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										57
									
								
								crypto/ecc_curve_defs.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								crypto/ecc_curve_defs.h
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,57 @@
 | 
			
		|||
#ifndef _CRYTO_ECC_CURVE_DEFS_H
 | 
			
		||||
#define _CRYTO_ECC_CURVE_DEFS_H
 | 
			
		||||
 | 
			
		||||
struct ecc_point {
 | 
			
		||||
	u64 *x;
 | 
			
		||||
	u64 *y;
 | 
			
		||||
	u8 ndigits;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct ecc_curve {
 | 
			
		||||
	char *name;
 | 
			
		||||
	struct ecc_point g;
 | 
			
		||||
	u64 *p;
 | 
			
		||||
	u64 *n;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* NIST P-192 */
 | 
			
		||||
static u64 nist_p192_g_x[] = { 0xF4FF0AFD82FF1012ull, 0x7CBF20EB43A18800ull,
 | 
			
		||||
				0x188DA80EB03090F6ull };
 | 
			
		||||
static u64 nist_p192_g_y[] = { 0x73F977A11E794811ull, 0x631011ED6B24CDD5ull,
 | 
			
		||||
				0x07192B95FFC8DA78ull };
 | 
			
		||||
static u64 nist_p192_p[] = { 0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFEull,
 | 
			
		||||
				0xFFFFFFFFFFFFFFFFull };
 | 
			
		||||
static u64 nist_p192_n[] = { 0x146BC9B1B4D22831ull, 0xFFFFFFFF99DEF836ull,
 | 
			
		||||
				0xFFFFFFFFFFFFFFFFull };
 | 
			
		||||
static struct ecc_curve nist_p192 = {
 | 
			
		||||
	.name = "nist_192",
 | 
			
		||||
	.g = {
 | 
			
		||||
		.x = nist_p192_g_x,
 | 
			
		||||
		.y = nist_p192_g_y,
 | 
			
		||||
		.ndigits = 3,
 | 
			
		||||
	},
 | 
			
		||||
	.p = nist_p192_p,
 | 
			
		||||
	.n = nist_p192_n
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* NIST P-256 */
 | 
			
		||||
static u64 nist_p256_g_x[] = { 0xF4A13945D898C296ull, 0x77037D812DEB33A0ull,
 | 
			
		||||
				0xF8BCE6E563A440F2ull, 0x6B17D1F2E12C4247ull };
 | 
			
		||||
static u64 nist_p256_g_y[] = { 0xCBB6406837BF51F5ull, 0x2BCE33576B315ECEull,
 | 
			
		||||
				0x8EE7EB4A7C0F9E16ull, 0x4FE342E2FE1A7F9Bull };
 | 
			
		||||
static u64 nist_p256_p[] = { 0xFFFFFFFFFFFFFFFFull, 0x00000000FFFFFFFFull,
 | 
			
		||||
				0x0000000000000000ull, 0xFFFFFFFF00000001ull };
 | 
			
		||||
static u64 nist_p256_n[] = { 0xF3B9CAC2FC632551ull, 0xBCE6FAADA7179E84ull,
 | 
			
		||||
				0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFF00000000ull };
 | 
			
		||||
static struct ecc_curve nist_p256 = {
 | 
			
		||||
	.name = "nist_256",
 | 
			
		||||
	.g = {
 | 
			
		||||
		.x = nist_p256_g_x,
 | 
			
		||||
		.y = nist_p256_g_y,
 | 
			
		||||
		.ndigits = 4,
 | 
			
		||||
	},
 | 
			
		||||
	.p = nist_p256_p,
 | 
			
		||||
	.n = nist_p256_n
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										151
									
								
								crypto/ecdh.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										151
									
								
								crypto/ecdh.c
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,151 @@
 | 
			
		|||
/* ECDH key-agreement protocol
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (c) 2016, Intel Corporation
 | 
			
		||||
 * Authors: Salvator Benedetto <salvatore.benedetto@intel.com>
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or
 | 
			
		||||
 * modify it under the terms of the GNU General Public Licence
 | 
			
		||||
 * as published by the Free Software Foundation; either version
 | 
			
		||||
 * 2 of the Licence, or (at your option) any later version.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <linux/module.h>
 | 
			
		||||
#include <crypto/internal/kpp.h>
 | 
			
		||||
#include <crypto/kpp.h>
 | 
			
		||||
#include <crypto/ecdh.h>
 | 
			
		||||
#include <linux/scatterlist.h>
 | 
			
		||||
#include "ecc.h"
 | 
			
		||||
 | 
			
		||||
struct ecdh_ctx {
 | 
			
		||||
	unsigned int curve_id;
 | 
			
		||||
	unsigned int ndigits;
 | 
			
		||||
	u64 private_key[ECC_MAX_DIGITS];
 | 
			
		||||
	u64 public_key[2 * ECC_MAX_DIGITS];
 | 
			
		||||
	u64 shared_secret[ECC_MAX_DIGITS];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static inline struct ecdh_ctx *ecdh_get_ctx(struct crypto_kpp *tfm)
 | 
			
		||||
{
 | 
			
		||||
	return kpp_tfm_ctx(tfm);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static unsigned int ecdh_supported_curve(unsigned int curve_id)
 | 
			
		||||
{
 | 
			
		||||
	switch (curve_id) {
 | 
			
		||||
	case ECC_CURVE_NIST_P192: return 3;
 | 
			
		||||
	case ECC_CURVE_NIST_P256: return 4;
 | 
			
		||||
	default: return 0;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int ecdh_set_secret(struct crypto_kpp *tfm, void *buf, unsigned int len)
 | 
			
		||||
{
 | 
			
		||||
	struct ecdh_ctx *ctx = ecdh_get_ctx(tfm);
 | 
			
		||||
	struct ecdh params;
 | 
			
		||||
	unsigned int ndigits;
 | 
			
		||||
 | 
			
		||||
	if (crypto_ecdh_decode_key(buf, len, ¶ms) < 0)
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
 | 
			
		||||
	ndigits = ecdh_supported_curve(params.curve_id);
 | 
			
		||||
	if (!ndigits)
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
 | 
			
		||||
	ctx->curve_id = params.curve_id;
 | 
			
		||||
	ctx->ndigits = ndigits;
 | 
			
		||||
 | 
			
		||||
	if (ecc_is_key_valid(ctx->curve_id, ctx->ndigits,
 | 
			
		||||
			     (const u8 *)params.key, params.key_size) < 0)
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
 | 
			
		||||
	memcpy(ctx->private_key, params.key, params.key_size);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int ecdh_compute_value(struct kpp_request *req)
 | 
			
		||||
{
 | 
			
		||||
	int ret = 0;
 | 
			
		||||
	struct crypto_kpp *tfm = crypto_kpp_reqtfm(req);
 | 
			
		||||
	struct ecdh_ctx *ctx = ecdh_get_ctx(tfm);
 | 
			
		||||
	size_t copied, nbytes;
 | 
			
		||||
	void *buf;
 | 
			
		||||
 | 
			
		||||
	nbytes = ctx->ndigits << ECC_DIGITS_TO_BYTES_SHIFT;
 | 
			
		||||
 | 
			
		||||
	if (req->src) {
 | 
			
		||||
		copied = sg_copy_to_buffer(req->src, 1, ctx->public_key,
 | 
			
		||||
					   2 * nbytes);
 | 
			
		||||
		if (copied != 2 * nbytes)
 | 
			
		||||
			return -EINVAL;
 | 
			
		||||
 | 
			
		||||
		ret = ecdh_shared_secret(ctx->curve_id, ctx->ndigits,
 | 
			
		||||
					 (const u8 *)ctx->private_key, nbytes,
 | 
			
		||||
					 (const u8 *)ctx->public_key, 2 * nbytes,
 | 
			
		||||
					 (u8 *)ctx->shared_secret, nbytes);
 | 
			
		||||
 | 
			
		||||
		buf = ctx->shared_secret;
 | 
			
		||||
	} else {
 | 
			
		||||
		ret = ecdh_make_pub_key(ctx->curve_id, ctx->ndigits,
 | 
			
		||||
					(const u8 *)ctx->private_key, nbytes,
 | 
			
		||||
					(u8 *)ctx->public_key,
 | 
			
		||||
					sizeof(ctx->public_key));
 | 
			
		||||
		buf = ctx->public_key;
 | 
			
		||||
		/* Public part is a point thus it has both coordinates */
 | 
			
		||||
		nbytes *= 2;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (ret < 0)
 | 
			
		||||
		return ret;
 | 
			
		||||
 | 
			
		||||
	copied = sg_copy_from_buffer(req->dst, 1, buf, nbytes);
 | 
			
		||||
	if (copied != nbytes)
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int ecdh_max_size(struct crypto_kpp *tfm)
 | 
			
		||||
{
 | 
			
		||||
	struct ecdh_ctx *ctx = ecdh_get_ctx(tfm);
 | 
			
		||||
	int nbytes = ctx->ndigits << ECC_DIGITS_TO_BYTES_SHIFT;
 | 
			
		||||
 | 
			
		||||
	/* Public key is made of two coordinates */
 | 
			
		||||
	return 2 * nbytes;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void no_exit_tfm(struct crypto_kpp *tfm)
 | 
			
		||||
{
 | 
			
		||||
	return;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct kpp_alg ecdh = {
 | 
			
		||||
	.set_secret = ecdh_set_secret,
 | 
			
		||||
	.generate_public_key = ecdh_compute_value,
 | 
			
		||||
	.compute_shared_secret = ecdh_compute_value,
 | 
			
		||||
	.max_size = ecdh_max_size,
 | 
			
		||||
	.exit = no_exit_tfm,
 | 
			
		||||
	.base = {
 | 
			
		||||
		.cra_name = "ecdh",
 | 
			
		||||
		.cra_driver_name = "ecdh-generic",
 | 
			
		||||
		.cra_priority = 100,
 | 
			
		||||
		.cra_module = THIS_MODULE,
 | 
			
		||||
		.cra_ctxsize = sizeof(struct ecdh_ctx),
 | 
			
		||||
	},
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static int ecdh_init(void)
 | 
			
		||||
{
 | 
			
		||||
	return crypto_register_kpp(&ecdh);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void ecdh_exit(void)
 | 
			
		||||
{
 | 
			
		||||
	crypto_unregister_kpp(&ecdh);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module_init(ecdh_init);
 | 
			
		||||
module_exit(ecdh_exit);
 | 
			
		||||
MODULE_ALIAS_CRYPTO("ecdh");
 | 
			
		||||
MODULE_LICENSE("GPL");
 | 
			
		||||
MODULE_DESCRIPTION("ECDH generic algorithm");
 | 
			
		||||
							
								
								
									
										86
									
								
								crypto/ecdh_helper.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								crypto/ecdh_helper.c
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,86 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2016, Intel Corporation
 | 
			
		||||
 * Authors: Salvatore Benedetto <salvatore.benedetto@intel.com>
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or
 | 
			
		||||
 * modify it under the terms of the GNU General Public Licence
 | 
			
		||||
 * as published by the Free Software Foundation; either version
 | 
			
		||||
 * 2 of the Licence, or (at your option) any later version.
 | 
			
		||||
 */
 | 
			
		||||
#include <linux/kernel.h>
 | 
			
		||||
#include <linux/export.h>
 | 
			
		||||
#include <linux/err.h>
 | 
			
		||||
#include <linux/string.h>
 | 
			
		||||
#include <crypto/ecdh.h>
 | 
			
		||||
#include <crypto/kpp.h>
 | 
			
		||||
 | 
			
		||||
#define ECDH_KPP_SECRET_MIN_SIZE (sizeof(struct kpp_secret) + 2 * sizeof(short))
 | 
			
		||||
 | 
			
		||||
static inline u8 *ecdh_pack_data(void *dst, const void *src, size_t sz)
 | 
			
		||||
{
 | 
			
		||||
	memcpy(dst, src, sz);
 | 
			
		||||
	return dst + sz;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline const u8 *ecdh_unpack_data(void *dst, const void *src, size_t sz)
 | 
			
		||||
{
 | 
			
		||||
	memcpy(dst, src, sz);
 | 
			
		||||
	return src + sz;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int crypto_ecdh_key_len(const struct ecdh *params)
 | 
			
		||||
{
 | 
			
		||||
	return ECDH_KPP_SECRET_MIN_SIZE + params->key_size;
 | 
			
		||||
}
 | 
			
		||||
EXPORT_SYMBOL_GPL(crypto_ecdh_key_len);
 | 
			
		||||
 | 
			
		||||
int crypto_ecdh_encode_key(char *buf, unsigned int len,
 | 
			
		||||
			   const struct ecdh *params)
 | 
			
		||||
{
 | 
			
		||||
	u8 *ptr = buf;
 | 
			
		||||
	struct kpp_secret secret = {
 | 
			
		||||
		.type = CRYPTO_KPP_SECRET_TYPE_ECDH,
 | 
			
		||||
		.len = len
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	if (unlikely(!buf))
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
 | 
			
		||||
	if (len != crypto_ecdh_key_len(params))
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
 | 
			
		||||
	ptr = ecdh_pack_data(ptr, &secret, sizeof(secret));
 | 
			
		||||
	ptr = ecdh_pack_data(ptr, ¶ms->curve_id, sizeof(params->curve_id));
 | 
			
		||||
	ptr = ecdh_pack_data(ptr, ¶ms->key_size, sizeof(params->key_size));
 | 
			
		||||
	ecdh_pack_data(ptr, params->key, params->key_size);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
EXPORT_SYMBOL_GPL(crypto_ecdh_encode_key);
 | 
			
		||||
 | 
			
		||||
int crypto_ecdh_decode_key(const char *buf, unsigned int len,
 | 
			
		||||
			   struct ecdh *params)
 | 
			
		||||
{
 | 
			
		||||
	const u8 *ptr = buf;
 | 
			
		||||
	struct kpp_secret secret;
 | 
			
		||||
 | 
			
		||||
	if (unlikely(!buf || len < ECDH_KPP_SECRET_MIN_SIZE))
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
 | 
			
		||||
	ptr = ecdh_unpack_data(&secret, ptr, sizeof(secret));
 | 
			
		||||
	if (secret.type != CRYPTO_KPP_SECRET_TYPE_ECDH)
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
 | 
			
		||||
	ptr = ecdh_unpack_data(¶ms->curve_id, ptr, sizeof(params->curve_id));
 | 
			
		||||
	ptr = ecdh_unpack_data(¶ms->key_size, ptr, sizeof(params->key_size));
 | 
			
		||||
	if (secret.len != crypto_ecdh_key_len(params))
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
 | 
			
		||||
	/* Don't allocate memory. Set pointer to data
 | 
			
		||||
	 * within the given buffer
 | 
			
		||||
	 */
 | 
			
		||||
	params->key = (void *)ptr;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
EXPORT_SYMBOL_GPL(crypto_ecdh_decode_key);
 | 
			
		||||
| 
						 | 
				
			
			@ -3300,6 +3300,16 @@ static const struct alg_test_desc alg_test_descs[] = {
 | 
			
		|||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}, {
 | 
			
		||||
		.alg = "ecdh",
 | 
			
		||||
		.test = alg_test_kpp,
 | 
			
		||||
		.fips_allowed = 1,
 | 
			
		||||
		.suite = {
 | 
			
		||||
			.kpp = {
 | 
			
		||||
				.vecs = ecdh_tv_template,
 | 
			
		||||
				.count = ECDH_TEST_VECTORS
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}, {
 | 
			
		||||
		.alg = "gcm(aes)",
 | 
			
		||||
		.test = alg_test_aead,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -560,6 +560,99 @@ struct kpp_testvec dh_tv_template[] = {
 | 
			
		|||
	}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_CRYPTO_FIPS
 | 
			
		||||
#define ECDH_TEST_VECTORS 1
 | 
			
		||||
#else
 | 
			
		||||
#define ECDH_TEST_VECTORS 2
 | 
			
		||||
#endif
 | 
			
		||||
struct kpp_testvec ecdh_tv_template[] = {
 | 
			
		||||
	{
 | 
			
		||||
#ifndef CONFIG_CRYPTO_FIPS
 | 
			
		||||
	.secret =
 | 
			
		||||
#ifdef __LITTLE_ENDIAN
 | 
			
		||||
	"\x02\x00" /* type */
 | 
			
		||||
	"\x20\x00" /* len */
 | 
			
		||||
	"\x01\x00" /* curve_id */
 | 
			
		||||
	"\x18\x00" /* key_size */
 | 
			
		||||
#else
 | 
			
		||||
	"\x00\x02" /* type */
 | 
			
		||||
	"\x00\x20" /* len */
 | 
			
		||||
	"\x00\x01" /* curve_id */
 | 
			
		||||
	"\x00\x18" /* key_size */
 | 
			
		||||
#endif
 | 
			
		||||
	"\xb5\x05\xb1\x71\x1e\xbf\x8c\xda"
 | 
			
		||||
	"\x4e\x19\x1e\x62\x1f\x23\x23\x31"
 | 
			
		||||
	"\x36\x1e\xd3\x84\x2f\xcc\x21\x72",
 | 
			
		||||
	.b_public =
 | 
			
		||||
	"\xc3\xba\x67\x4b\x71\xec\xd0\x76"
 | 
			
		||||
	"\x7a\x99\x75\x64\x36\x13\x9a\x94"
 | 
			
		||||
	"\x5d\x8b\xdc\x60\x90\x91\xfd\x3f"
 | 
			
		||||
	"\xb0\x1f\x8a\x0a\x68\xc6\x88\x6e"
 | 
			
		||||
	"\x83\x87\xdd\x67\x09\xf8\x8d\x96"
 | 
			
		||||
	"\x07\xd6\xbd\x1c\xe6\x8d\x9d\x67",
 | 
			
		||||
	.expected_a_public =
 | 
			
		||||
	"\x1a\x04\xdb\xa5\xe1\xdd\x4e\x79"
 | 
			
		||||
	"\xa3\xe6\xef\x0e\x5c\x80\x49\x85"
 | 
			
		||||
	"\xfa\x78\xb4\xef\x49\xbd\x4c\x7c"
 | 
			
		||||
	"\x22\x90\x21\x02\xf9\x1b\x81\x5d"
 | 
			
		||||
	"\x0c\x8a\xa8\x98\xd6\x27\x69\x88"
 | 
			
		||||
	"\x5e\xbc\x94\xd8\x15\x9e\x21\xce",
 | 
			
		||||
	.expected_ss =
 | 
			
		||||
	"\xf4\x57\xcc\x4f\x1f\x4e\x31\xcc"
 | 
			
		||||
	"\xe3\x40\x60\xc8\x06\x93\xc6\x2e"
 | 
			
		||||
	"\x99\x80\x81\x28\xaf\xc5\x51\x74",
 | 
			
		||||
	.secret_size = 32,
 | 
			
		||||
	.b_public_size = 48,
 | 
			
		||||
	.expected_a_public_size = 48,
 | 
			
		||||
	.expected_ss_size = 24
 | 
			
		||||
	}, {
 | 
			
		||||
#endif
 | 
			
		||||
	.secret =
 | 
			
		||||
#ifdef __LITTLE_ENDIAN
 | 
			
		||||
	"\x02\x00" /* type */
 | 
			
		||||
	"\x28\x00" /* len */
 | 
			
		||||
	"\x02\x00" /* curve_id */
 | 
			
		||||
	"\x20\x00" /* key_size */
 | 
			
		||||
#else
 | 
			
		||||
	"\x00\x02" /* type */
 | 
			
		||||
	"\x00\x28" /* len */
 | 
			
		||||
	"\x00\x02" /* curve_id */
 | 
			
		||||
	"\x00\x20" /* key_size */
 | 
			
		||||
#endif
 | 
			
		||||
	"\x24\xd1\x21\xeb\xe5\xcf\x2d\x83"
 | 
			
		||||
	"\xf6\x62\x1b\x6e\x43\x84\x3a\xa3"
 | 
			
		||||
	"\x8b\xe0\x86\xc3\x20\x19\xda\x92"
 | 
			
		||||
	"\x50\x53\x03\xe1\xc0\xea\xb8\x82",
 | 
			
		||||
	.expected_a_public =
 | 
			
		||||
	"\x1a\x7f\xeb\x52\x00\xbd\x3c\x31"
 | 
			
		||||
	"\x7d\xb6\x70\xc1\x86\xa6\xc7\xc4"
 | 
			
		||||
	"\x3b\xc5\x5f\x6c\x6f\x58\x3c\xf5"
 | 
			
		||||
	"\xb6\x63\x82\x77\x33\x24\xa1\x5f"
 | 
			
		||||
	"\x6a\xca\x43\x6f\xf7\x7e\xff\x02"
 | 
			
		||||
	"\x37\x08\xcc\x40\x5e\x7a\xfd\x6a"
 | 
			
		||||
	"\x6a\x02\x6e\x41\x87\x68\x38\x77"
 | 
			
		||||
	"\xfa\xa9\x44\x43\x2d\xef\x09\xdf",
 | 
			
		||||
	.expected_ss =
 | 
			
		||||
	"\xea\x17\x6f\x7e\x6e\x57\x26\x38"
 | 
			
		||||
	"\x8b\xfb\x41\xeb\xba\xc8\x6d\xa5"
 | 
			
		||||
	"\xa8\x72\xd1\xff\xc9\x47\x3d\xaa"
 | 
			
		||||
	"\x58\x43\x9f\x34\x0f\x8c\xf3\xc9",
 | 
			
		||||
	.b_public =
 | 
			
		||||
	"\xcc\xb4\xda\x74\xb1\x47\x3f\xea"
 | 
			
		||||
	"\x6c\x70\x9e\x38\x2d\xc7\xaa\xb7"
 | 
			
		||||
	"\x29\xb2\x47\x03\x19\xab\xdd\x34"
 | 
			
		||||
	"\xbd\xa8\x2c\x93\xe1\xa4\x74\xd9"
 | 
			
		||||
	"\x64\x63\xf7\x70\x20\x2f\xa4\xe6"
 | 
			
		||||
	"\x9f\x4a\x38\xcc\xc0\x2c\x49\x2f"
 | 
			
		||||
	"\xb1\x32\xbb\xaf\x22\x61\xda\xcb"
 | 
			
		||||
	"\x6f\xdb\xa9\xaa\xfc\x77\x81\xf3",
 | 
			
		||||
	.secret_size = 40,
 | 
			
		||||
	.b_public_size = 64,
 | 
			
		||||
	.expected_a_public_size = 64,
 | 
			
		||||
	.expected_ss_size = 32
 | 
			
		||||
	}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * MD4 test vectors from RFC1320
 | 
			
		||||
 */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										30
									
								
								include/crypto/ecdh.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								include/crypto/ecdh.h
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,30 @@
 | 
			
		|||
/*
 | 
			
		||||
 * ECDH params to be used with kpp API
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (c) 2016, Intel Corporation
 | 
			
		||||
 * Authors: Salvatore Benedetto <salvatore.benedetto@intel.com>
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or modify it
 | 
			
		||||
 * under the terms of the GNU General Public License as published by the Free
 | 
			
		||||
 * Software Foundation; either version 2 of the License, or (at your option)
 | 
			
		||||
 * any later version.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
#ifndef _CRYPTO_ECDH_
 | 
			
		||||
#define _CRYPTO_ECDH_
 | 
			
		||||
 | 
			
		||||
/* Curves IDs */
 | 
			
		||||
#define ECC_CURVE_NIST_P192	0x0001
 | 
			
		||||
#define ECC_CURVE_NIST_P256	0x0002
 | 
			
		||||
 | 
			
		||||
struct ecdh {
 | 
			
		||||
	unsigned short curve_id;
 | 
			
		||||
	char *key;
 | 
			
		||||
	unsigned short key_size;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int crypto_ecdh_key_len(const struct ecdh *params);
 | 
			
		||||
int crypto_ecdh_encode_key(char *buf, unsigned int len, const struct ecdh *p);
 | 
			
		||||
int crypto_ecdh_decode_key(const char *buf, unsigned int len, struct ecdh *p);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -243,6 +243,7 @@ static inline void kpp_request_set_output(struct kpp_request *req,
 | 
			
		|||
enum {
 | 
			
		||||
	CRYPTO_KPP_SECRET_TYPE_UNKNOWN,
 | 
			
		||||
	CRYPTO_KPP_SECRET_TYPE_DH,
 | 
			
		||||
	CRYPTO_KPP_SECRET_TYPE_ECDH,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue