forked from mirrors/linux
		
	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 | 	help | ||||||
| 	  Generic implementation of the Diffie-Hellman algorithm. | 	  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 | config CRYPTO_MANAGER | ||||||
| 	tristate "Cryptographic algorithm manager" | 	tristate "Cryptographic algorithm manager" | ||||||
|  |  | ||||||
|  | @ -35,6 +35,10 @@ obj-$(CONFIG_CRYPTO_KPP2) += kpp.o | ||||||
| dh_generic-y := dh.o | dh_generic-y := dh.o | ||||||
| dh_generic-y += dh_helper.o | dh_generic-y += dh_helper.o | ||||||
| obj-$(CONFIG_CRYPTO_DH) += dh_generic.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)/rsapubkey-asn1.o: $(obj)/rsapubkey-asn1.c $(obj)/rsapubkey-asn1.h | ||||||
| $(obj)/rsaprivkey-asn1.o: $(obj)/rsaprivkey-asn1.c $(obj)/rsaprivkey-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)", | 		.alg = "gcm(aes)", | ||||||
| 		.test = alg_test_aead, | 		.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 |  * 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 { | enum { | ||||||
| 	CRYPTO_KPP_SECRET_TYPE_UNKNOWN, | 	CRYPTO_KPP_SECRET_TYPE_UNKNOWN, | ||||||
| 	CRYPTO_KPP_SECRET_TYPE_DH, | 	CRYPTO_KPP_SECRET_TYPE_DH, | ||||||
|  | 	CRYPTO_KPP_SECRET_TYPE_ECDH, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 Salvatore Benedetto
						Salvatore Benedetto