All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] crypto: implement DH primitives under akcipher API
@ 2016-02-15  9:01 Salvatore Benedetto
  2016-02-15 13:57 ` Stephan Mueller
                   ` (2 more replies)
  0 siblings, 3 replies; 18+ messages in thread
From: Salvatore Benedetto @ 2016-02-15  9:01 UTC (permalink / raw)
  To: herbert; +Cc: salvatore.benedetto, linux-crypto

Implement Diffie-Hellman primitives required by the scheme under the
akcipher API. Here is how it works.
1) Call set_pub_key() by passing DH parameters (p,g) in PKCS3 format
2) Call set_priv_key() to set your own private key (xa) in raw format
3) Call decrypt() without passing any data as input to get back the
   public part which will be computed as g^xa mod p
4) Call encrypt() by passing the counter part public key (yb) in raw format
   as input to get back the shared secret calculated as zz = yb^xa mod p

A test is included in the patch. Test vector has been generated with
openssl

Signed-off-by: Salvatore Benedetto <salvatore.benedetto@intel.com>
---
 crypto/Kconfig    |   8 ++
 crypto/Makefile   |   7 ++
 crypto/dh.c       | 264 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 crypto/pkcs3.asn1 |   5 ++
 crypto/tcrypt.c   |   4 +
 crypto/testmgr.c  | 140 +++++++++++++++++++++++++++--
 crypto/testmgr.h  | 208 +++++++++++++++++++++++++++++++++++++++++-
 7 files changed, 627 insertions(+), 9 deletions(-)
 create mode 100644 crypto/dh.c
 create mode 100644 crypto/pkcs3.asn1

diff --git a/crypto/Kconfig b/crypto/Kconfig
index f6bfdda..fd5b78d 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -101,6 +101,14 @@ config CRYPTO_RSA
 	help
 	  Generic implementation of the RSA public key algorithm.
 
+config CRYPTO_DH
+	tristate "Diffie-Hellman algorithm"
+	select CRYPTO_AKCIPHER
+	select MPILIB
+	select ASN1
+	help
+	  Generic implementation of the Diffie-Hellman algorithm.
+
 config CRYPTO_MANAGER
 	tristate "Cryptographic algorithm manager"
 	select CRYPTO_MANAGER2
diff --git a/crypto/Makefile b/crypto/Makefile
index 4f4ef7e..ee73489 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -31,6 +31,13 @@ obj-$(CONFIG_CRYPTO_HASH2) += crypto_hash.o
 
 obj-$(CONFIG_CRYPTO_AKCIPHER2) += akcipher.o
 
+$(obj)/pkcs3-asn1.o: $(obj)/pkcs3-asn1.c $(obj)/pkcs3-asn1.h
+clean-files += pkcs3-asn1.c pkcs3-asn1.h
+
+dh_generic-y := pkcs3-asn1.o
+dh_generic-y += dh.o
+obj-$(CONFIG_CRYPTO_DH) += dh_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
 clean-files += rsapubkey-asn1.c rsapubkey-asn1.h
diff --git a/crypto/dh.c b/crypto/dh.c
new file mode 100644
index 0000000..614c4f1
--- /dev/null
+++ b/crypto/dh.c
@@ -0,0 +1,264 @@
+/*  Diffie-Hellman Key Agreement Method [RFC2631]
+ *
+ * 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/module.h>
+#include <crypto/internal/akcipher.h>
+#include <crypto/akcipher.h>
+#include <crypto/algapi.h>
+#include <linux/mpi.h>
+#include "pkcs3-asn1.h"
+
+struct dh_params {
+	MPI p;
+	MPI g;
+	MPI xa;
+};
+
+int dh_get_g(void *context, size_t hdrlen, unsigned char tag, const void *value,
+	     size_t vlen)
+{
+	struct dh_params *params = context;
+
+	params->g = mpi_read_raw_data(value, vlen);
+
+	if (!params->g)
+		return -ENOMEM;
+
+	return 0;
+}
+
+int dh_get_p(void *context, size_t hdrlen, unsigned char tag, const void *value,
+	     size_t vlen)
+{
+	struct dh_params *params = context;
+
+	params->p = mpi_read_raw_data(value, vlen);
+
+	if (!params->p)
+		return -ENOMEM;
+
+	return 0;
+}
+
+static int dh_parse_params(struct dh_params *params, const void *key,
+			   unsigned int keylen)
+{
+	int ret;
+
+	mpi_free(params->p);
+	mpi_free(params->g);
+
+	ret = asn1_ber_decoder(&pkcs3_decoder, params, key, keylen);
+
+	return ret;
+}
+
+static void dh_free_params(struct dh_params *params)
+{
+	mpi_free(params->p);
+	mpi_free(params->g);
+	mpi_free(params->xa);
+	params->p = NULL;
+	params->g = NULL;
+	params->xa = NULL;
+}
+
+/*
+ * Public key generation function [RFC2631 sec 2.1.1]
+ * ya = g^xa mod p;
+ */
+static int _generate_public_key(const struct dh_params *params, MPI ya)
+{
+	/* ya = g^xa mod p */
+	return mpi_powm(ya, params->g, params->xa, params->p);
+}
+
+/*
+ * ZZ generation function [RFC2631 sec 2.1.1]
+ * ZZ = yb^xa mod p;
+ */
+static int _compute_shared_secret(const struct dh_params *params, MPI yb,
+				  MPI zz)
+{
+	/* ZZ = yb^xa mod p */
+	return mpi_powm(zz, yb, params->xa, params->p);
+}
+
+static inline struct dh_params *dh_get_params(struct crypto_akcipher *tfm)
+{
+	return akcipher_tfm_ctx(tfm);
+}
+
+static int dh_generate_public_key(struct akcipher_request *req)
+{
+	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
+	const struct dh_params *params = dh_get_params(tfm);
+	MPI ya = mpi_alloc(0);
+	int ret = 0;
+	int sign;
+
+	if (!ya)
+		return -ENOMEM;
+
+	if (unlikely(!params->p || !params->g || !params->xa)) {
+		ret = -EINVAL;
+		goto err_free_ya;
+	}
+	ret = _generate_public_key(params, ya);
+	if (ret)
+		goto err_free_ya;
+
+	ret = mpi_write_to_sgl(ya, req->dst, &req->dst_len, &sign);
+	if (ret)
+		goto err_free_ya;
+
+	if (sign < 0)
+		ret = -EBADMSG;
+
+err_free_ya:
+	mpi_free(ya);
+	return ret;
+}
+
+static int dh_compute_shared_secret(struct akcipher_request *req)
+{
+	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
+	struct dh_params *params = dh_get_params(tfm);
+	MPI yb, zz = mpi_alloc(0);
+	int ret = 0;
+	int sign;
+
+	if (!zz)
+		return -ENOMEM;
+
+	if (unlikely(!params->p || !params->xa)) {
+		ret = -EINVAL;
+		goto err_free_zz;
+	}
+
+	yb = mpi_read_raw_from_sgl(req->src, req->src_len);
+	if (!yb) {
+		ret = EINVAL;
+		goto err_free_zz;
+	}
+
+	ret = _compute_shared_secret(params, yb, zz);
+	if (ret)
+		goto err_free_yb;
+
+	ret = mpi_write_to_sgl(zz, req->dst, &req->dst_len, &sign);
+	if (ret)
+		goto err_free_yb;
+
+	if (sign < 0)
+		ret = -EBADMSG;
+
+err_free_yb:
+	mpi_free(yb);
+err_free_zz:
+	mpi_free(zz);
+	return ret;
+}
+
+static int dh_check_params_length(unsigned int p_len)
+{
+	switch (p_len) {
+	case 768:
+	case 1024:
+	case 1536:
+	case 2048:
+	case 3072:
+	case 4096:
+		return 0;
+	}
+	return -EINVAL;
+}
+
+static int dh_no_op(struct akcipher_request *req)
+{
+	return -ENOPROTOOPT;
+}
+
+static int dh_set_priv_key(struct crypto_akcipher *tfm, const void *key,
+			   unsigned int keylen)
+{
+	struct dh_params *params = akcipher_tfm_ctx(tfm);
+
+	params->xa = mpi_read_raw_data(key, keylen);
+
+	if (!params->xa)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int dh_set_pub_key(struct crypto_akcipher *tfm, const void *key,
+			  unsigned int keylen)
+{
+	struct dh_params *params = akcipher_tfm_ctx(tfm);
+	int ret = 0;
+
+	ret = dh_parse_params(params, key, keylen);
+	if (ret)
+		return ret;
+	if (dh_check_params_length(mpi_get_size(params->p) << 3))
+		ret = -EINVAL;
+
+	return ret;
+}
+
+static int dh_max_size(struct crypto_akcipher *tfm)
+{
+	struct dh_params *params = akcipher_tfm_ctx(tfm);
+
+	return params->p ? mpi_get_size(params->p) : -EINVAL;
+}
+
+static void dh_exit_tfm(struct crypto_akcipher *tfm)
+{
+	struct dh_params *params = akcipher_tfm_ctx(tfm);
+
+	dh_free_params(params);
+}
+
+static struct akcipher_alg dh = {
+	.encrypt = dh_compute_shared_secret,
+	.decrypt = dh_generate_public_key,
+	.sign = dh_no_op,
+	.verify = dh_no_op,
+	.set_priv_key = dh_set_priv_key,
+	.set_pub_key = dh_set_pub_key,
+	.max_size = dh_max_size,
+	.exit = dh_exit_tfm,
+	.base = {
+		.cra_name = "dh",
+		.cra_driver_name = "dh-generic",
+		.cra_priority = 100,
+		.cra_module = THIS_MODULE,
+		.cra_ctxsize = sizeof(struct dh_params),
+	},
+};
+
+static int dh_init(void)
+{
+	return crypto_register_akcipher(&dh);
+}
+
+static void dh_exit(void)
+{
+	crypto_unregister_akcipher(&dh);
+}
+
+module_init(dh_init);
+module_exit(dh_exit);
+MODULE_ALIAS_CRYPTO("dh");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("DH generic algorithm");
diff --git a/crypto/pkcs3.asn1 b/crypto/pkcs3.asn1
new file mode 100644
index 0000000..3d4ba5c
--- /dev/null
+++ b/crypto/pkcs3.asn1
@@ -0,0 +1,5 @@
+DHParameter ::= SEQUENCE {
+    prime               INTEGER ({ dh_get_p }),
+    base                INTEGER ({ dh_get_g }),
+    private_len         INTEGER OPTIONAL
+}
diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c
index 579dce0..53c45f7 100644
--- a/crypto/tcrypt.c
+++ b/crypto/tcrypt.c
@@ -1981,6 +1981,10 @@ static int do_test(const char *alg, u32 type, u32 mask, int m)
 				   speed_template_8_32);
 		break;
 
+	case 600:
+		ret += tcrypt_test("dh");
+		break;
+
 	case 1000:
 		test_available();
 		break;
diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index 93f3527..adf6815 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -112,7 +112,7 @@ struct drbg_test_suite {
 };
 
 struct akcipher_test_suite {
-	struct akcipher_testvec *vecs;
+	struct akcipher_testvec vecs;
 	unsigned int count;
 };
 
@@ -1773,8 +1773,113 @@ static int alg_test_drbg(const struct alg_test_desc *desc, const char *driver,
 
 }
 
+static int do_test_dh(struct crypto_akcipher *tfm,
+		      struct akcipher_testvec_dh *vec)
+{
+	struct akcipher_request *req;
+	void *input_buf = NULL;
+	void *output_buf = NULL;
+	struct tcrypt_result result;
+	unsigned int out_len_max;
+	int err = -ENOMEM;
+	struct scatterlist src, dst;
+
+	req = akcipher_request_alloc(tfm, GFP_KERNEL);
+	if (!req)
+		return err;
+
+	init_completion(&result.completion);
+
+	/* Set p,g */
+	err = crypto_akcipher_set_pub_key(tfm, vec->pkcs3, vec->pkcs3_size);
+	if (err)
+		goto free_req;
+
+	/* Set A private Key */
+	err = crypto_akcipher_set_priv_key(tfm, vec->priv_key_A, vec->key_len);
+	if (err)
+		goto free_req;
+
+	out_len_max = crypto_akcipher_maxsize(tfm);
+	output_buf = kzalloc(out_len_max, GFP_KERNEL);
+	if (!output_buf) {
+		err = -ENOMEM;
+		goto free_req;
+	}
+
+	sg_init_one(&dst, output_buf, out_len_max);
+	akcipher_request_set_crypt(req, NULL, &dst, 0, out_len_max);
+	akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
+				      tcrypt_complete, &result);
+
+	/* Compute A public key = g^xa mod p */
+	err = wait_async_op(&result, crypto_akcipher_decrypt(req));
+	if (err) {
+		pr_err("alg: dh: decrypt test failed. err %d\n", err);
+		goto free_output;
+	}
+	/* Verify calculated public key */
+	if (memcmp(vec->expected_pub_key_A, sg_virt(req->dst), vec->key_len)) {
+		pr_err("alg: dh: decrypt test failed. Invalid output\n");
+		err = -EINVAL;
+		goto free_output;
+	}
+
+	/* Calculate shared secret key by using counter part public key. */
+	input_buf = kzalloc(vec->key_len, GFP_KERNEL);
+	if (!input_buf) {
+		err = -ENOMEM;
+		goto free_output;
+	}
+
+	memcpy(input_buf, vec->pub_key_B, vec->key_len);
+	sg_init_one(&src, input_buf, vec->key_len);
+	sg_init_one(&dst, output_buf, out_len_max);
+	akcipher_request_set_crypt(req, &src, &dst, vec->key_len, out_len_max);
+	akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
+				      tcrypt_complete, &result);
+	err = wait_async_op(&result, crypto_akcipher_encrypt(req));
+	if (err) {
+		pr_err("alg: dh: encrypt test failed. err %d\n", err);
+		goto free_all;
+	}
+	/*
+	 * verify shared secret from which the user will derive
+	 * secret key by executing whatever hash it has chosen
+	 */
+	if (memcmp(vec->expected_shared_secret, sg_virt(req->dst),
+		   vec->key_len)) {
+		pr_err("alg: dh: encrypt test failed. Invalid output\n");
+		err = -EINVAL;
+	}
+
+free_all:
+	kfree(input_buf);
+free_output:
+	kfree(output_buf);
+free_req:
+	akcipher_request_free(req);
+	return err;
+}
+
+static int test_dh(struct crypto_akcipher *tfm,
+		   struct akcipher_testvec_dh *vecs, unsigned int tcount)
+{
+	int ret, i;
+
+	for (i = 0; i < tcount; i++) {
+		ret = do_test_dh(tfm, vecs++);
+		if (ret) {
+			pr_err("alg: dh: test failed on vector %d, err=%d\n",
+			       i + 1, ret);
+			return ret;
+		}
+	}
+	return 0;
+}
+
 static int do_test_rsa(struct crypto_akcipher *tfm,
-		       struct akcipher_testvec *vecs)
+		       struct akcipher_testvec_rsa *vecs)
 {
 	struct akcipher_request *req;
 	void *outbuf_enc = NULL;
@@ -1870,7 +1975,8 @@ free_req:
 	return err;
 }
 
-static int test_rsa(struct crypto_akcipher *tfm, struct akcipher_testvec *vecs,
+static int test_rsa(struct crypto_akcipher *tfm,
+		    struct akcipher_testvec_rsa *vecs,
 		    unsigned int tcount)
 {
 	int ret, i;
@@ -1890,7 +1996,9 @@ static int test_akcipher(struct crypto_akcipher *tfm, const char *alg,
 			 struct akcipher_testvec *vecs, unsigned int tcount)
 {
 	if (strncmp(alg, "rsa", 3) == 0)
-		return test_rsa(tfm, vecs, tcount);
+		return test_rsa(tfm, vecs->a.rsa, tcount);
+	else if (strncmp(alg, "dh", 3) == 0)
+		return test_dh(tfm, vecs->a.dh, tcount);
 
 	return 0;
 }
@@ -1907,8 +2015,9 @@ static int alg_test_akcipher(const struct alg_test_desc *desc,
 		       driver, PTR_ERR(tfm));
 		return PTR_ERR(tfm);
 	}
-	if (desc->suite.akcipher.vecs)
-		err = test_akcipher(tfm, desc->alg, desc->suite.akcipher.vecs,
+	if (desc->suite.akcipher.vecs.a.rsa)
+		err = test_akcipher(tfm, desc->alg,
+				    &desc->suite.akcipher.vecs,
 				    desc->suite.akcipher.count);
 
 	crypto_free_akcipher(tfm);
@@ -2676,6 +2785,19 @@ static const struct alg_test_desc alg_test_descs[] = {
 			}
 		}
 	}, {
+		.alg = "dh",
+		.test = alg_test_akcipher,
+		.suite = {
+			.akcipher = {
+				.vecs = {
+					.a = {
+						.dh = dh_tv_template
+					},
+				},
+				.count = DH_TEST_VECTORS
+			}
+		}
+	}, {
 		.alg = "digest_null",
 		.test = alg_test_null,
 	}, {
@@ -3560,7 +3682,11 @@ static const struct alg_test_desc alg_test_descs[] = {
 		.fips_allowed = 1,
 		.suite = {
 			.akcipher = {
-				.vecs = rsa_tv_template,
+				.vecs = {
+					.a = {
+						.rsa = rsa_tv_template
+					},
+				},
 				.count = RSA_TEST_VECTORS
 			}
 		}
diff --git a/crypto/testmgr.h b/crypto/testmgr.h
index 487ec88..ba08ed6 100644
--- a/crypto/testmgr.h
+++ b/crypto/testmgr.h
@@ -123,7 +123,7 @@ struct drbg_testvec {
 	size_t expectedlen;
 };
 
-struct akcipher_testvec {
+struct akcipher_testvec_rsa {
 	unsigned char *key;
 	unsigned char *m;
 	unsigned char *c;
@@ -133,6 +133,23 @@ struct akcipher_testvec {
 	bool public_key_vec;
 };
 
+struct akcipher_testvec_dh {
+	unsigned char *pkcs3;
+	unsigned pkcs3_size;
+	unsigned char *priv_key_A;
+	unsigned char *pub_key_B;
+	unsigned char *expected_pub_key_A;
+	unsigned char *expected_shared_secret;
+	unsigned key_len;
+};
+
+struct akcipher_testvec {
+	union {
+		struct akcipher_testvec_rsa *rsa;
+		struct akcipher_testvec_dh *dh;
+	} a;
+};
+
 static char zeroed_string[48];
 
 /*
@@ -143,7 +160,7 @@ static char zeroed_string[48];
 #else
 #define RSA_TEST_VECTORS	4
 #endif
-static struct akcipher_testvec rsa_tv_template[] = {
+static struct akcipher_testvec_rsa rsa_tv_template[] = {
 	{
 #ifndef CONFIG_CRYPTO_FIPS
 	.key =
@@ -330,6 +347,193 @@ static struct akcipher_testvec rsa_tv_template[] = {
 	}
 };
 
+#define DH_TEST_VECTORS 2
+
+struct akcipher_testvec_dh dh_tv_template[] = {
+	{
+	/* p, g */
+	.pkcs3 =
+	"\x30\x82\x01\x08\x02\x82\x01\x01\x00\x9f\xab\x7c\xc2\x50\xa7\xdc"
+	"\x3c\x17\x2a\x5b\x9f\x76\x17\x8e\x92\xa6\xb0\x13\x1e\x6e\x7b\x9a"
+	"\x6b\x8d\x06\xcf\x9f\x90\xb8\x21\x6a\x30\x04\xe8\xda\xc0\x13\x27"
+	"\xc8\x40\xbf\x6c\x84\x1e\xe2\x9e\xf9\xd2\x48\x11\xc7\x06\xd3\x06"
+	"\xb8\xaa\xbe\x69\x3f\xf2\x60\x06\xa0\xd1\x55\x03\x63\xa1\xfd\x33"
+	"\x2c\x04\xe4\xf0\xe6\x02\x8a\x97\x1e\x22\x4f\x2b\x73\x15\x23\xa5"
+	"\x26\x97\xd6\x91\x11\xd8\x80\x35\xe7\x7f\x19\x29\x6c\x59\x64\x24"
+	"\x68\xc0\x40\x66\x5d\xa8\xcb\xda\x84\xce\xbc\xf7\x1b\x68\x81\xac"
+	"\xec\xe9\x84\xc1\x46\xef\xac\xe2\xb2\x85\xf2\x92\x06\x82\xbe\xe7"
+	"\x12\x53\x21\xfc\xc5\x82\xe5\xe3\x7f\x26\xe5\x53\x02\x58\xb1\xa9"
+	"\x26\x32\x5f\xb9\xa6\x23\x1d\xd8\x26\xda\x7a\x67\xab\x8a\x84\x97"
+	"\x2e\x78\xc1\x6d\xec\x67\x50\x27\x2d\x52\xf7\x67\xec\x5b\x2c\x9f"
+	"\x17\xb7\x81\xec\x47\x60\x65\xf5\x86\x20\x4f\x82\x84\xd9\xee\x62"
+	"\x6f\x49\x7d\x80\x9e\xaa\x8a\x7a\x82\x45\x65\x36\x0b\xf1\xfe\x01"
+	"\x06\x52\x3c\xa1\xdf\xc8\x84\x89\xb0\xee\xb6\xfa\x95\x12\x42\xb9"
+	"\x87\x53\x77\x1c\xe0\x56\x25\xf6\x96\x31\xec\x62\x82\x77\xb7\x52"
+	"\xac\x25\x71\x49\x97\x13\x83\x23\x63\x02\x01\x02",
+	.pkcs3_size = 268,
+	.priv_key_A =
+	"\x48\xed\x07\x3d\x49\x20\xf8\xa5\xcf\x90\xcd\xf9\x97\x63\xd2\x51"
+	"\x3d\xac\xbd\x2d\x49\x4a\xb8\x87\x06\x62\xd2\x0c\x13\x55\x73\x77"
+	"\x97\x15\xd3\x23\x8a\x3b\x3e\xb9\x14\xa6\xfb\x20\x7b\xd1\xea\x68"
+	"\x85\x9a\xc6\x8f\x66\x9a\x78\xf0\x26\xce\x8c\xe0\x66\x4e\x51\xc9"
+	"\xf5\xf9\x89\xc6\x0a\xc5\x4b\x99\xdc\xb0\x36\x3e\xf2\xc7\x7f\x52"
+	"\x60\x99\x12\xbd\x8f\x85\x7b\x0a\x99\xa9\x85\x21\xc6\x50\x66\xf6"
+	"\xde\x62\xc4\x08\x3f\x8c\x97\x91\xb0\x19\x72\x2a\x56\xc6\x85\x12"
+	"\x8e\x89\x65\xa7\x13\x34\x51\x53\x2e\xe0\x07\x6c\x01\xaa\xb1\x23"
+	"\x42\x54\xa5\x49\xfd\x01\x2a\xd8\xa7\xc3\xd6\x6a\x6f\x3c\x76\xc4"
+	"\x4b\x37\x55\x30\xb7\xbe\xb7\x87\x4e\x43\x68\x37\xd8\xa0\x6f\x53"
+	"\x59\xb6\x25\xd4\x44\xc9\x43\xcd\xb1\x20\x8c\xf9\x3a\xd5\xbc\x97"
+	"\x70\x8e\xad\x1a\x8b\x69\xbd\xae\xf9\xd0\x48\x70\x40\x4d\x3f\xdc"
+	"\xea\x10\xef\x61\x49\x1b\x87\x10\xff\x96\x36\x73\x4f\x75\xf5\x75"
+	"\x23\xbb\x5e\x48\xe8\x96\x57\xcf\x33\x76\x78\x2e\x86\x90\x5c\x2c"
+	"\x17\xe6\x70\x8a\x6c\x0c\x0d\xa8\x3e\x79\xa6\x9e\xe1\xbf\x18\x40"
+	"\xeb\x2c\x1a\xb9\x14\xf5\x02\xeb\x37\x66\x06\x1c\xe8\xb5\x75\x0d",
+	.pub_key_B =
+	"\x18\xd9\x78\xdd\x6a\xc9\x19\x4e\xe6\xa0\x83\xcc\x12\x00\x3b\x6c"
+	"\x4c\x8c\x11\x38\x94\x90\xd7\xc4\x1f\xa6\x64\x04\x35\x4a\xda\x48"
+	"\x5a\xeb\x38\xe7\xae\x44\x16\x4a\x94\xfe\x7c\xa9\x00\xff\x67\x20"
+	"\x4c\xef\x34\x45\xfe\x2d\xf5\xa9\xfb\xa8\xc0\x45\x09\xcd\xcd\xc0"
+	"\x4c\x20\xc0\x1e\x42\x41\x4b\x37\x6c\x90\xba\xef\xd6\x65\xab\xb1"
+	"\xec\x51\x30\xfa\x08\xfc\x22\xc6\x42\xce\x6a\x90\xb7\x27\xe4\x52"
+	"\x76\x28\x78\x17\x56\x71\x73\xeb\xaf\x6e\xbb\x61\x7a\x6b\x4b\xdb"
+	"\x8e\x2f\xaa\xfa\x9e\x40\xee\x84\xf6\x63\x9b\xb7\xe2\x22\x72\x6b"
+	"\x94\x58\x3f\x08\xa5\xbe\xd6\x87\x63\xe7\xbb\x5a\xfb\x52\x92\xd2"
+	"\xe6\x5e\x7e\x55\x78\x4b\xc0\x0e\x1a\xe5\xe6\x0f\x0e\x41\xd5\x05"
+	"\xb7\x71\x42\x78\x35\x74\xad\x33\x9f\x24\xc0\x3b\x09\xd5\xcf\x4d"
+	"\x6e\x20\x3a\xee\x04\x9f\x05\x2d\x8d\x77\x06\x2d\x9b\x67\xba\x39"
+	"\x2f\x6c\x1d\x7b\x75\x57\xed\x2f\xe2\xf1\xbc\x0b\x3a\x77\xf2\xba"
+	"\xb2\xb1\x98\x52\x34\x40\x53\x7b\x0e\xb6\x13\x6a\x5b\x91\xe4\x59"
+	"\x67\x2c\x45\x3a\x07\x1a\xa2\x3b\xdb\xa1\xa6\x08\xf0\x80\xe8\x61"
+	"\xca\xac\x95\xb3\x3e\xd6\x97\x98\x08\x7e\x50\x48\xc0\x25\x45\xd0",
+	.expected_pub_key_A =
+	"\x91\x9e\x52\xa3\xb8\x20\x25\x12\x17\xcc\x37\x82\x81\x22\x14\x7a"
+	"\x81\x88\xce\x9f\xf2\x46\xb1\x17\xaf\x41\x23\xc9\xb8\x93\x40\xfd"
+	"\xa9\x96\x05\x5a\x1a\xcc\xa6\x51\xe2\x9e\xca\x63\x2a\x67\x72\x4a"
+	"\xe1\x2b\xa7\xbe\xf9\xeb\x69\xc8\x2d\x29\xb6\x6b\x5f\xc0\xf2\x90"
+	"\xa9\x36\x49\xdb\xcc\x6b\x5e\xed\x76\x47\x9f\xc9\x2e\x91\x68\x75"
+	"\xa3\x39\x6c\x50\xa6\xaf\x81\xac\x23\x58\xa9\xc9\x71\xf3\x87\x97"
+	"\xef\x0c\x80\x19\xac\xb7\xf0\xa0\x83\x44\x4b\x1c\x08\xf1\x4f\x23"
+	"\xfb\xf1\x61\x39\x00\x59\xef\x83\xa5\xaf\x2f\x3f\xc0\x19\x2a\x5b"
+	"\x22\x53\xdb\x8b\x24\xbc\xe4\xaa\x9a\x19\x6b\xfd\x20\xbf\x1a\xe2"
+	"\xb5\xaf\x82\x3e\xb8\xea\xe7\x28\xcd\xad\xfe\x00\xee\x70\x52\x46"
+	"\x3d\x2c\x55\x81\x44\xed\x15\x21\xc8\x48\x75\x4d\x6f\xf0\xba\xe9"
+	"\xab\x4c\x65\xf3\x54\x2e\x74\xd9\xe7\xe2\xb7\xad\xec\x6d\xb2\x6e"
+	"\xc1\xe3\x2d\x0e\xb1\x18\x36\xd7\xb9\x42\x6b\x2f\xc9\x51\x2e\xff"
+	"\x5d\xd0\xca\x8c\x0d\x0d\x95\xd3\x16\xf3\xdb\xc1\x2b\xed\x00\x32"
+	"\xd7\x77\xb8\x0e\x86\x7a\x57\x48\x74\x23\x30\xae\xe0\x3c\x38\xa6"
+	"\xed\xf9\x0c\x16\xf2\xf2\xa0\xe0\x51\x80\x67\x92\xe4\xc7\x9a\x5e",
+	.expected_shared_secret =
+	"\x1d\x7d\x2e\x47\x06\xbe\x46\xd3\x69\xf6\xe7\x0e\x88\xdc\xe8\xe1"
+	"\xe6\x6a\xfc\x3c\xbc\xc1\x85\xe9\x24\xf0\x7b\x75\x0f\xa4\x04\xd6"
+	"\x9b\xef\x7b\x30\x55\xde\xbf\xd4\xb2\xcb\xce\x74\x53\xae\x72\x34"
+	"\x19\x36\x9e\xe9\x45\xb8\xda\x59\x22\x41\x9e\xa3\x8f\x02\xaa\x60"
+	"\xb1\x8b\xf9\x84\xd4\x8a\xeb\xea\xd1\xd9\x1a\x53\xe9\x5f\x01\xd1"
+	"\x40\xb4\x73\x63\xc5\x1a\x79\xf1\x08\xb6\xc0\x0c\x85\x9e\x3e\x70"
+	"\xea\x79\xd9\xc2\x5b\x17\xa7\x1e\xeb\x58\x3e\x1b\xca\x7a\x4d\xab"
+	"\x61\x5b\xdf\xa2\x6f\x1e\xd4\x36\xeb\xe3\xe9\x04\x10\x8e\x0b\xc9"
+	"\x18\x8c\x0d\x6e\x4f\x2e\xc5\xfc\x5b\x6a\xb5\x9f\xdf\x71\x50\x04"
+	"\x54\x62\x49\x57\xf3\xc6\x9e\x39\xc6\x56\xf1\x2d\x31\x59\x58\xdb"
+	"\x67\x94\x25\xbd\x47\xe2\xdd\x95\x0c\x39\xb1\xfa\x22\xc6\x94\xc4"
+	"\x75\xab\xff\xe2\xce\x52\xa2\xeb\x78\x26\x10\x0f\x2d\x8c\xf2\xad"
+	"\xd2\xc7\xaf\x85\xd9\x5c\x71\xfe\x9e\xe9\xeb\xbf\x20\x36\x1e\x9a"
+	"\x74\x43\xe6\x06\x00\x8a\x4d\x64\x41\x2a\x15\x6d\x60\x44\x3f\x2c"
+	"\xcd\x05\x16\x54\x6a\x48\x7c\x71\x0a\xe9\x33\x95\x16\xc7\xf4\x23"
+	"\xc2\x8d\xed\x8a\x24\x5d\x99\xc7\x8c\x8b\x07\x47\x8c\xe9\x0c\x10",
+	.key_len = 256
+	},
+	{
+	/* p, g */
+	.pkcs3 =
+	"\x30\x82\x01\x08\x02\x82\x01\x01\x00\x9f\xab\x7c\xc2\x50\xa7\xdc"
+	"\x3c\x17\x2a\x5b\x9f\x76\x17\x8e\x92\xa6\xb0\x13\x1e\x6e\x7b\x9a"
+	"\x6b\x8d\x06\xcf\x9f\x90\xb8\x21\x6a\x30\x04\xe8\xda\xc0\x13\x27"
+	"\xc8\x40\xbf\x6c\x84\x1e\xe2\x9e\xf9\xd2\x48\x11\xc7\x06\xd3\x06"
+	"\xb8\xaa\xbe\x69\x3f\xf2\x60\x06\xa0\xd1\x55\x03\x63\xa1\xfd\x33"
+	"\x2c\x04\xe4\xf0\xe6\x02\x8a\x97\x1e\x22\x4f\x2b\x73\x15\x23\xa5"
+	"\x26\x97\xd6\x91\x11\xd8\x80\x35\xe7\x7f\x19\x29\x6c\x59\x64\x24"
+	"\x68\xc0\x40\x66\x5d\xa8\xcb\xda\x84\xce\xbc\xf7\x1b\x68\x81\xac"
+	"\xec\xe9\x84\xc1\x46\xef\xac\xe2\xb2\x85\xf2\x92\x06\x82\xbe\xe7"
+	"\x12\x53\x21\xfc\xc5\x82\xe5\xe3\x7f\x26\xe5\x53\x02\x58\xb1\xa9"
+	"\x26\x32\x5f\xb9\xa6\x23\x1d\xd8\x26\xda\x7a\x67\xab\x8a\x84\x97"
+	"\x2e\x78\xc1\x6d\xec\x67\x50\x27\x2d\x52\xf7\x67\xec\x5b\x2c\x9f"
+	"\x17\xb7\x81\xec\x47\x60\x65\xf5\x86\x20\x4f\x82\x84\xd9\xee\x62"
+	"\x6f\x49\x7d\x80\x9e\xaa\x8a\x7a\x82\x45\x65\x36\x0b\xf1\xfe\x01"
+	"\x06\x52\x3c\xa1\xdf\xc8\x84\x89\xb0\xee\xb6\xfa\x95\x12\x42\xb9"
+	"\x87\x53\x77\x1c\xe0\x56\x25\xf6\x96\x31\xec\x62\x82\x77\xb7\x52"
+	"\xac\x25\x71\x49\x97\x13\x83\x23\x63\x02\x01\x02",
+	.pkcs3_size = 268,
+	.priv_key_A =
+	"\x7d\xfb\xa2\x51\x24\xa4\xfa\x65\x35\x1c\x3b\xef\x3f\x6b\x10\x27"
+	"\xde\x30\xcb\x2c\xa7\x5b\xfe\x1a\xec\x5f\x2b\x1c\x7b\xd8\xa7\xfd"
+	"\x37\x15\xec\x62\xbd\x64\x71\x57\x31\x48\xcc\x8c\xd9\x6f\xe9\x24"
+	"\x9d\x63\xff\x1f\xb6\x7d\xf7\x30\x23\x13\xdc\x0f\x27\xd9\x6e\x11"
+	"\x8b\x54\x80\xe4\x35\x52\x98\x5c\xac\x87\x56\xdf\x5e\xe2\xbe\x08"
+	"\x63\xfd\xb2\xe4\x06\x2b\x04\x68\xf6\x3a\x45\x3b\xb0\xf1\x81\x32"
+	"\x36\xa3\xde\xe4\xe7\xec\x8b\x87\x32\x09\x45\x87\x1c\x1c\x0e\x84"
+	"\xf7\x30\x09\x7d\x7f\x98\xf5\xbe\x92\x50\xbd\xa8\xc2\x35\x11\xe3"
+	"\x0a\xf2\x90\x1a\x18\xcb\x5a\xe5\x4e\x4a\x93\x3d\x6d\x26\xa6\x36"
+	"\x79\x45\x75\x12\xb4\x27\x95\xcd\x9e\x6b\x37\x57\x4d\x69\x21\xa9"
+	"\xff\x5d\xe2\xf2\xf8\x4f\xeb\x50\x79\xa4\xa7\x87\x59\x78\x23\xfa"
+	"\x67\xb5\xdc\x6e\xa6\x59\x81\xba\x65\x8e\x65\xfc\x7f\x51\xc8\xad"
+	"\x1d\x28\x50\x60\x92\x2a\xcc\x9c\x47\xc7\x13\xd2\xf4\xb8\xa2\xab"
+	"\x2c\x50\x4c\xf1\xcd\xef\xb7\x94\x1c\xe7\xd3\x2a\x55\x37\xff\xfa"
+	"\x6d\xe8\x43\x01\xb0\x9b\x24\x5d\xd4\x57\x7d\xb5\x30\xaa\x60\x97"
+	"\x33\xfe\xe7\x31\x39\x96\xe6\xb3\xf4\x11\xde\x3c\x57\x4b\xcb\xad",
+	.pub_key_B =
+	"\x91\x9e\x52\xa3\xb8\x20\x25\x12\x17\xcc\x37\x82\x81\x22\x14\x7a"
+	"\x81\x88\xce\x9f\xf2\x46\xb1\x17\xaf\x41\x23\xc9\xb8\x93\x40\xfd"
+	"\xa9\x96\x05\x5a\x1a\xcc\xa6\x51\xe2\x9e\xca\x63\x2a\x67\x72\x4a"
+	"\xe1\x2b\xa7\xbe\xf9\xeb\x69\xc8\x2d\x29\xb6\x6b\x5f\xc0\xf2\x90"
+	"\xa9\x36\x49\xdb\xcc\x6b\x5e\xed\x76\x47\x9f\xc9\x2e\x91\x68\x75"
+	"\xa3\x39\x6c\x50\xa6\xaf\x81\xac\x23\x58\xa9\xc9\x71\xf3\x87\x97"
+	"\xef\x0c\x80\x19\xac\xb7\xf0\xa0\x83\x44\x4b\x1c\x08\xf1\x4f\x23"
+	"\xfb\xf1\x61\x39\x00\x59\xef\x83\xa5\xaf\x2f\x3f\xc0\x19\x2a\x5b"
+	"\x22\x53\xdb\x8b\x24\xbc\xe4\xaa\x9a\x19\x6b\xfd\x20\xbf\x1a\xe2"
+	"\xb5\xaf\x82\x3e\xb8\xea\xe7\x28\xcd\xad\xfe\x00\xee\x70\x52\x46"
+	"\x3d\x2c\x55\x81\x44\xed\x15\x21\xc8\x48\x75\x4d\x6f\xf0\xba\xe9"
+	"\xab\x4c\x65\xf3\x54\x2e\x74\xd9\xe7\xe2\xb7\xad\xec\x6d\xb2\x6e"
+	"\xc1\xe3\x2d\x0e\xb1\x18\x36\xd7\xb9\x42\x6b\x2f\xc9\x51\x2e\xff"
+	"\x5d\xd0\xca\x8c\x0d\x0d\x95\xd3\x16\xf3\xdb\xc1\x2b\xed\x00\x32"
+	"\xd7\x77\xb8\x0e\x86\x7a\x57\x48\x74\x23\x30\xae\xe0\x3c\x38\xa6"
+	"\xed\xf9\x0c\x16\xf2\xf2\xa0\xe0\x51\x80\x67\x92\xe4\xc7\x9a\x5e",
+	.expected_pub_key_A =
+	"\x18\xd9\x78\xdd\x6a\xc9\x19\x4e\xe6\xa0\x83\xcc\x12\x00\x3b\x6c"
+	"\x4c\x8c\x11\x38\x94\x90\xd7\xc4\x1f\xa6\x64\x04\x35\x4a\xda\x48"
+	"\x5a\xeb\x38\xe7\xae\x44\x16\x4a\x94\xfe\x7c\xa9\x00\xff\x67\x20"
+	"\x4c\xef\x34\x45\xfe\x2d\xf5\xa9\xfb\xa8\xc0\x45\x09\xcd\xcd\xc0"
+	"\x4c\x20\xc0\x1e\x42\x41\x4b\x37\x6c\x90\xba\xef\xd6\x65\xab\xb1"
+	"\xec\x51\x30\xfa\x08\xfc\x22\xc6\x42\xce\x6a\x90\xb7\x27\xe4\x52"
+	"\x76\x28\x78\x17\x56\x71\x73\xeb\xaf\x6e\xbb\x61\x7a\x6b\x4b\xdb"
+	"\x8e\x2f\xaa\xfa\x9e\x40\xee\x84\xf6\x63\x9b\xb7\xe2\x22\x72\x6b"
+	"\x94\x58\x3f\x08\xa5\xbe\xd6\x87\x63\xe7\xbb\x5a\xfb\x52\x92\xd2"
+	"\xe6\x5e\x7e\x55\x78\x4b\xc0\x0e\x1a\xe5\xe6\x0f\x0e\x41\xd5\x05"
+	"\xb7\x71\x42\x78\x35\x74\xad\x33\x9f\x24\xc0\x3b\x09\xd5\xcf\x4d"
+	"\x6e\x20\x3a\xee\x04\x9f\x05\x2d\x8d\x77\x06\x2d\x9b\x67\xba\x39"
+	"\x2f\x6c\x1d\x7b\x75\x57\xed\x2f\xe2\xf1\xbc\x0b\x3a\x77\xf2\xba"
+	"\xb2\xb1\x98\x52\x34\x40\x53\x7b\x0e\xb6\x13\x6a\x5b\x91\xe4\x59"
+	"\x67\x2c\x45\x3a\x07\x1a\xa2\x3b\xdb\xa1\xa6\x08\xf0\x80\xe8\x61"
+	"\xca\xac\x95\xb3\x3e\xd6\x97\x98\x08\x7e\x50\x48\xc0\x25\x45\xd0",
+	.expected_shared_secret =
+	"\x1d\x7d\x2e\x47\x06\xbe\x46\xd3\x69\xf6\xe7\x0e\x88\xdc\xe8\xe1"
+	"\xe6\x6a\xfc\x3c\xbc\xc1\x85\xe9\x24\xf0\x7b\x75\x0f\xa4\x04\xd6"
+	"\x9b\xef\x7b\x30\x55\xde\xbf\xd4\xb2\xcb\xce\x74\x53\xae\x72\x34"
+	"\x19\x36\x9e\xe9\x45\xb8\xda\x59\x22\x41\x9e\xa3\x8f\x02\xaa\x60"
+	"\xb1\x8b\xf9\x84\xd4\x8a\xeb\xea\xd1\xd9\x1a\x53\xe9\x5f\x01\xd1"
+	"\x40\xb4\x73\x63\xc5\x1a\x79\xf1\x08\xb6\xc0\x0c\x85\x9e\x3e\x70"
+	"\xea\x79\xd9\xc2\x5b\x17\xa7\x1e\xeb\x58\x3e\x1b\xca\x7a\x4d\xab"
+	"\x61\x5b\xdf\xa2\x6f\x1e\xd4\x36\xeb\xe3\xe9\x04\x10\x8e\x0b\xc9"
+	"\x18\x8c\x0d\x6e\x4f\x2e\xc5\xfc\x5b\x6a\xb5\x9f\xdf\x71\x50\x04"
+	"\x54\x62\x49\x57\xf3\xc6\x9e\x39\xc6\x56\xf1\x2d\x31\x59\x58\xdb"
+	"\x67\x94\x25\xbd\x47\xe2\xdd\x95\x0c\x39\xb1\xfa\x22\xc6\x94\xc4"
+	"\x75\xab\xff\xe2\xce\x52\xa2\xeb\x78\x26\x10\x0f\x2d\x8c\xf2\xad"
+	"\xd2\xc7\xaf\x85\xd9\x5c\x71\xfe\x9e\xe9\xeb\xbf\x20\x36\x1e\x9a"
+	"\x74\x43\xe6\x06\x00\x8a\x4d\x64\x41\x2a\x15\x6d\x60\x44\x3f\x2c"
+	"\xcd\x05\x16\x54\x6a\x48\x7c\x71\x0a\xe9\x33\x95\x16\xc7\xf4\x23"
+	"\xc2\x8d\xed\x8a\x24\x5d\x99\xc7\x8c\x8b\x07\x47\x8c\xe9\x0c\x10",
+	.key_len = 256
+	}
+};
+
 /*
  * MD4 test vectors from RFC1320
  */
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* Re: [PATCH] crypto: implement DH primitives under akcipher API
  2016-02-15  9:01 [PATCH] crypto: implement DH primitives under akcipher API Salvatore Benedetto
@ 2016-02-15 13:57 ` Stephan Mueller
  2016-03-01 11:08   ` Salvatore Benedetto
  2016-02-16 20:19 ` Herbert Xu
  2016-03-01 20:25 ` Marcel Holtmann
  2 siblings, 1 reply; 18+ messages in thread
From: Stephan Mueller @ 2016-02-15 13:57 UTC (permalink / raw)
  To: Salvatore Benedetto; +Cc: herbert, linux-crypto

Am Montag, 15. Februar 2016, 09:01:55 schrieb Salvatore Benedetto:

Hi Salvatore, Herbert,

> Implement Diffie-Hellman primitives required by the scheme under the
> akcipher API. Here is how it works.
> 1) Call set_pub_key() by passing DH parameters (p,g) in PKCS3 format
> 2) Call set_priv_key() to set your own private key (xa) in raw format
> 3) Call decrypt() without passing any data as input to get back the
>    public part which will be computed as g^xa mod p
> 4) Call encrypt() by passing the counter part public key (yb) in raw format
>    as input to get back the shared secret calculated as zz = yb^xa mod p
> 
> A test is included in the patch. Test vector has been generated with
> openssl

Herbert, as this is a raw DH operation where the shared secret must be 
subjected to a KDF, I guess the KDF patch I provided some time ago may become 
of interest again?
> 
> Signed-off-by: Salvatore Benedetto <salvatore.benedetto@intel.com>
> ---
>  crypto/Kconfig    |   8 ++
>  crypto/Makefile   |   7 ++
>  crypto/dh.c       | 264
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++ crypto/pkcs3.asn1 | 
>  5 ++
>  crypto/tcrypt.c   |   4 +
>  crypto/testmgr.c  | 140 +++++++++++++++++++++++++++--
>  crypto/testmgr.h  | 208 +++++++++++++++++++++++++++++++++++++++++-
>  7 files changed, 627 insertions(+), 9 deletions(-)
>  create mode 100644 crypto/dh.c
>  create mode 100644 crypto/pkcs3.asn1
> 
> diff --git a/crypto/Kconfig b/crypto/Kconfig
> index f6bfdda..fd5b78d 100644
> --- a/crypto/Kconfig
> +++ b/crypto/Kconfig
> @@ -101,6 +101,14 @@ config CRYPTO_RSA
>  	help
>  	  Generic implementation of the RSA public key algorithm.
> 
> +config CRYPTO_DH
> +	tristate "Diffie-Hellman algorithm"
> +	select CRYPTO_AKCIPHER
> +	select MPILIB
> +	select ASN1
> +	help
> +	  Generic implementation of the Diffie-Hellman algorithm.
> +
>  config CRYPTO_MANAGER
>  	tristate "Cryptographic algorithm manager"
>  	select CRYPTO_MANAGER2
> diff --git a/crypto/Makefile b/crypto/Makefile
> index 4f4ef7e..ee73489 100644
> --- a/crypto/Makefile
> +++ b/crypto/Makefile
> @@ -31,6 +31,13 @@ obj-$(CONFIG_CRYPTO_HASH2) += crypto_hash.o
> 
>  obj-$(CONFIG_CRYPTO_AKCIPHER2) += akcipher.o
> 
> +$(obj)/pkcs3-asn1.o: $(obj)/pkcs3-asn1.c $(obj)/pkcs3-asn1.h
> +clean-files += pkcs3-asn1.c pkcs3-asn1.h
> +
> +dh_generic-y := pkcs3-asn1.o
> +dh_generic-y += dh.o
> +obj-$(CONFIG_CRYPTO_DH) += dh_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
> clean-files += rsapubkey-asn1.c rsapubkey-asn1.h
> diff --git a/crypto/dh.c b/crypto/dh.c
> new file mode 100644
> index 0000000..614c4f1
> --- /dev/null
> +++ b/crypto/dh.c
> @@ -0,0 +1,264 @@
> +/*  Diffie-Hellman Key Agreement Method [RFC2631]
> + *
> + * 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/module.h>
> +#include <crypto/internal/akcipher.h>
> +#include <crypto/akcipher.h>
> +#include <crypto/algapi.h>
> +#include <linux/mpi.h>
> +#include "pkcs3-asn1.h"
> +
> +struct dh_params {
> +	MPI p;
> +	MPI g;
> +	MPI xa;
> +};
> +
> +int dh_get_g(void *context, size_t hdrlen, unsigned char tag, const void
> *value, +	     size_t vlen)
> +{
> +	struct dh_params *params = context;
> +
> +	params->g = mpi_read_raw_data(value, vlen);
> +
> +	if (!params->g)
> +		return -ENOMEM;
> +
> +	return 0;
> +}
> +
> +int dh_get_p(void *context, size_t hdrlen, unsigned char tag, const void
> *value, +	     size_t vlen)
> +{
> +	struct dh_params *params = context;
> +
> +	params->p = mpi_read_raw_data(value, vlen);
> +
> +	if (!params->p)
> +		return -ENOMEM;
> +
> +	return 0;
> +}
> +
> +static int dh_parse_params(struct dh_params *params, const void *key,
> +			   unsigned int keylen)
> +{
> +	int ret;
> +
> +	mpi_free(params->p);
> +	mpi_free(params->g);
> +
> +	ret = asn1_ber_decoder(&pkcs3_decoder, params, key, keylen);
> +
> +	return ret;
> +}
> +
> +static void dh_free_params(struct dh_params *params)
> +{
> +	mpi_free(params->p);
> +	mpi_free(params->g);
> +	mpi_free(params->xa);
> +	params->p = NULL;
> +	params->g = NULL;
> +	params->xa = NULL;
> +}
> +
> +/*
> + * Public key generation function [RFC2631 sec 2.1.1]
> + * ya = g^xa mod p;
> + */
> +static int _generate_public_key(const struct dh_params *params, MPI ya)
> +{
> +	/* ya = g^xa mod p */
> +	return mpi_powm(ya, params->g, params->xa, params->p);
> +}
> +
> +/*
> + * ZZ generation function [RFC2631 sec 2.1.1]
> + * ZZ = yb^xa mod p;
> + */
> +static int _compute_shared_secret(const struct dh_params *params, MPI yb,
> +				  MPI zz)
> +{
> +	/* ZZ = yb^xa mod p */
> +	return mpi_powm(zz, yb, params->xa, params->p);
> +}
> +
> +static inline struct dh_params *dh_get_params(struct crypto_akcipher *tfm)
> +{
> +	return akcipher_tfm_ctx(tfm);
> +}
> +
> +static int dh_generate_public_key(struct akcipher_request *req)
> +{
> +	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
> +	const struct dh_params *params = dh_get_params(tfm);
> +	MPI ya = mpi_alloc(0);
> +	int ret = 0;
> +	int sign;
> +
> +	if (!ya)
> +		return -ENOMEM;
> +
> +	if (unlikely(!params->p || !params->g || !params->xa)) {
> +		ret = -EINVAL;
> +		goto err_free_ya;
> +	}
> +	ret = _generate_public_key(params, ya);
> +	if (ret)
> +		goto err_free_ya;
> +
> +	ret = mpi_write_to_sgl(ya, req->dst, &req->dst_len, &sign);
> +	if (ret)
> +		goto err_free_ya;
> +
> +	if (sign < 0)
> +		ret = -EBADMSG;
> +
> +err_free_ya:
> +	mpi_free(ya);
> +	return ret;
> +}
> +
> +static int dh_compute_shared_secret(struct akcipher_request *req)
> +{
> +	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
> +	struct dh_params *params = dh_get_params(tfm);
> +	MPI yb, zz = mpi_alloc(0);
> +	int ret = 0;
> +	int sign;
> +
> +	if (!zz)
> +		return -ENOMEM;
> +
> +	if (unlikely(!params->p || !params->xa)) {
> +		ret = -EINVAL;
> +		goto err_free_zz;
> +	}
> +
> +	yb = mpi_read_raw_from_sgl(req->src, req->src_len);
> +	if (!yb) {
> +		ret = EINVAL;
> +		goto err_free_zz;
> +	}
> +
> +	ret = _compute_shared_secret(params, yb, zz);
> +	if (ret)
> +		goto err_free_yb;
> +
> +	ret = mpi_write_to_sgl(zz, req->dst, &req->dst_len, &sign);
> +	if (ret)
> +		goto err_free_yb;
> +
> +	if (sign < 0)
> +		ret = -EBADMSG;
> +
> +err_free_yb:
> +	mpi_free(yb);
> +err_free_zz:
> +	mpi_free(zz);
> +	return ret;
> +}
> +
> +static int dh_check_params_length(unsigned int p_len)
> +{
> +	switch (p_len) {
> +	case 768:
> +	case 1024:
> +	case 1536:
> +	case 2048:
> +	case 3072:
> +	case 4096:
> +		return 0;
> +	}
> +	return -EINVAL;
> +}

What is the reason for restricting the size to 4096?
> +
> +static int dh_no_op(struct akcipher_request *req)
> +{
> +	return -ENOPROTOOPT;
> +}
> +
> +static int dh_set_priv_key(struct crypto_akcipher *tfm, const void *key,
> +			   unsigned int keylen)
> +{
> +	struct dh_params *params = akcipher_tfm_ctx(tfm);

dh_get_params?
> +
> +	params->xa = mpi_read_raw_data(key, keylen);
> +
> +	if (!params->xa)
> +		return -EINVAL;
> +
> +	return 0;
> +}
> +
> +static int dh_set_pub_key(struct crypto_akcipher *tfm, const void *key,
> +			  unsigned int keylen)
> +{
> +	struct dh_params *params = akcipher_tfm_ctx(tfm);

dh_get_params?

> +	int ret = 0;
> +
> +	ret = dh_parse_params(params, key, keylen);
> +	if (ret)
> +		return ret;
> +	if (dh_check_params_length(mpi_get_size(params->p) << 3))
> +		ret = -EINVAL;
> +
> +	return ret;
> +}
> +
> +static int dh_max_size(struct crypto_akcipher *tfm)
> +{
> +	struct dh_params *params = akcipher_tfm_ctx(tfm);

dh_get_params?
> +
> +	return params->p ? mpi_get_size(params->p) : -EINVAL;
> +}
> +
> +static void dh_exit_tfm(struct crypto_akcipher *tfm)
> +{
> +	struct dh_params *params = akcipher_tfm_ctx(tfm);

dh_get_params?

> +
> +	dh_free_params(params);
> +}
> +
> +static struct akcipher_alg dh = {
> +	.encrypt = dh_compute_shared_secret,
> +	.decrypt = dh_generate_public_key,

May I ask what purpose this function has? I thought a DH shall generate the 
shared secret only?

> +	.sign = dh_no_op,
> +	.verify = dh_no_op,
> +	.set_priv_key = dh_set_priv_key,
> +	.set_pub_key = dh_set_pub_key,
> +	.max_size = dh_max_size,
> +	.exit = dh_exit_tfm,
> +	.base = {
> +		.cra_name = "dh",
> +		.cra_driver_name = "dh-generic",
> +		.cra_priority = 100,
> +		.cra_module = THIS_MODULE,
> +		.cra_ctxsize = sizeof(struct dh_params),
> +	},
> +};
> +
> +static int dh_init(void)
> +{
> +	return crypto_register_akcipher(&dh);
> +}
> +
> +static void dh_exit(void)
> +{
> +	crypto_unregister_akcipher(&dh);
> +}
> +
> +module_init(dh_init);
> +module_exit(dh_exit);
> +MODULE_ALIAS_CRYPTO("dh");
> +MODULE_LICENSE("GPL");
> +MODULE_DESCRIPTION("DH generic algorithm");
> diff --git a/crypto/pkcs3.asn1 b/crypto/pkcs3.asn1
> new file mode 100644
> index 0000000..3d4ba5c
> --- /dev/null
> +++ b/crypto/pkcs3.asn1
> @@ -0,0 +1,5 @@
> +DHParameter ::= SEQUENCE {
> +    prime               INTEGER ({ dh_get_p }),
> +    base                INTEGER ({ dh_get_g }),
> +    private_len         INTEGER OPTIONAL
> +}
> diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c
> index 579dce0..53c45f7 100644
> --- a/crypto/tcrypt.c
> +++ b/crypto/tcrypt.c
> @@ -1981,6 +1981,10 @@ static int do_test(const char *alg, u32 type, u32
> mask, int m) speed_template_8_32);
>  		break;
> 
> +	case 600:
> +		ret += tcrypt_test("dh");
> +		break;
> +
>  	case 1000:
>  		test_available();
>  		break;
> diff --git a/crypto/testmgr.c b/crypto/testmgr.c
> index 93f3527..adf6815 100644
> --- a/crypto/testmgr.c
> +++ b/crypto/testmgr.c
> @@ -112,7 +112,7 @@ struct drbg_test_suite {
>  };
> 
>  struct akcipher_test_suite {
> -	struct akcipher_testvec *vecs;
> +	struct akcipher_testvec vecs;
>  	unsigned int count;
>  };
> 
> @@ -1773,8 +1773,113 @@ static int alg_test_drbg(const struct alg_test_desc
> *desc, const char *driver,
> 
>  }
> 
> +static int do_test_dh(struct crypto_akcipher *tfm,
> +		      struct akcipher_testvec_dh *vec)
> +{
> +	struct akcipher_request *req;
> +	void *input_buf = NULL;
> +	void *output_buf = NULL;
> +	struct tcrypt_result result;
> +	unsigned int out_len_max;
> +	int err = -ENOMEM;
> +	struct scatterlist src, dst;
> +
> +	req = akcipher_request_alloc(tfm, GFP_KERNEL);
> +	if (!req)
> +		return err;
> +
> +	init_completion(&result.completion);
> +
> +	/* Set p,g */
> +	err = crypto_akcipher_set_pub_key(tfm, vec->pkcs3, vec->pkcs3_size);
> +	if (err)
> +		goto free_req;
> +
> +	/* Set A private Key */
> +	err = crypto_akcipher_set_priv_key(tfm, vec->priv_key_A, vec-
>key_len);
> +	if (err)
> +		goto free_req;
> +
> +	out_len_max = crypto_akcipher_maxsize(tfm);
> +	output_buf = kzalloc(out_len_max, GFP_KERNEL);
> +	if (!output_buf) {
> +		err = -ENOMEM;
> +		goto free_req;
> +	}
> +
> +	sg_init_one(&dst, output_buf, out_len_max);
> +	akcipher_request_set_crypt(req, NULL, &dst, 0, out_len_max);
> +	akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
> +				      tcrypt_complete, &result);
> +
> +	/* Compute A public key = g^xa mod p */
> +	err = wait_async_op(&result, crypto_akcipher_decrypt(req));
> +	if (err) {
> +		pr_err("alg: dh: decrypt test failed. err %d\n", err);
> +		goto free_output;
> +	}
> +	/* Verify calculated public key */
> +	if (memcmp(vec->expected_pub_key_A, sg_virt(req->dst), vec->key_len)) 
{
> +		pr_err("alg: dh: decrypt test failed. Invalid output\n");
> +		err = -EINVAL;
> +		goto free_output;
> +	}
> +
> +	/* Calculate shared secret key by using counter part public key. */
> +	input_buf = kzalloc(vec->key_len, GFP_KERNEL);
> +	if (!input_buf) {
> +		err = -ENOMEM;
> +		goto free_output;
> +	}
> +
> +	memcpy(input_buf, vec->pub_key_B, vec->key_len);
> +	sg_init_one(&src, input_buf, vec->key_len);
> +	sg_init_one(&dst, output_buf, out_len_max);
> +	akcipher_request_set_crypt(req, &src, &dst, vec->key_len, 
out_len_max);
> +	akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
> +				      tcrypt_complete, &result);
> +	err = wait_async_op(&result, crypto_akcipher_encrypt(req));
> +	if (err) {
> +		pr_err("alg: dh: encrypt test failed. err %d\n", err);
> +		goto free_all;
> +	}
> +	/*
> +	 * verify shared secret from which the user will derive
> +	 * secret key by executing whatever hash it has chosen
> +	 */
> +	if (memcmp(vec->expected_shared_secret, sg_virt(req->dst),
> +		   vec->key_len)) {
> +		pr_err("alg: dh: encrypt test failed. Invalid output\n");
> +		err = -EINVAL;
> +	}
> +
> +free_all:
> +	kfree(input_buf);
> +free_output:
> +	kfree(output_buf);
> +free_req:
> +	akcipher_request_free(req);
> +	return err;
> +}
> +
> +static int test_dh(struct crypto_akcipher *tfm,
> +		   struct akcipher_testvec_dh *vecs, unsigned int tcount)
> +{
> +	int ret, i;
> +
> +	for (i = 0; i < tcount; i++) {
> +		ret = do_test_dh(tfm, vecs++);
> +		if (ret) {
> +			pr_err("alg: dh: test failed on vector %d, err=%d\n",
> +			       i + 1, ret);
> +			return ret;
> +		}
> +	}
> +	return 0;
> +}
> +
>  static int do_test_rsa(struct crypto_akcipher *tfm,
> -		       struct akcipher_testvec *vecs)
> +		       struct akcipher_testvec_rsa *vecs)
>  {
>  	struct akcipher_request *req;
>  	void *outbuf_enc = NULL;
> @@ -1870,7 +1975,8 @@ free_req:
>  	return err;
>  }
> 
> -static int test_rsa(struct crypto_akcipher *tfm, struct akcipher_testvec
> *vecs, +static int test_rsa(struct crypto_akcipher *tfm,
> +		    struct akcipher_testvec_rsa *vecs,
>  		    unsigned int tcount)
>  {
>  	int ret, i;
> @@ -1890,7 +1996,9 @@ static int test_akcipher(struct crypto_akcipher *tfm,
> const char *alg, struct akcipher_testvec *vecs, unsigned int tcount)
>  {
>  	if (strncmp(alg, "rsa", 3) == 0)
> -		return test_rsa(tfm, vecs, tcount);
> +		return test_rsa(tfm, vecs->a.rsa, tcount);
> +	else if (strncmp(alg, "dh", 3) == 0)
> +		return test_dh(tfm, vecs->a.dh, tcount);
> 
>  	return 0;
>  }
> @@ -1907,8 +2015,9 @@ static int alg_test_akcipher(const struct
> alg_test_desc *desc, driver, PTR_ERR(tfm));
>  		return PTR_ERR(tfm);
>  	}
> -	if (desc->suite.akcipher.vecs)
> -		err = test_akcipher(tfm, desc->alg, desc->suite.akcipher.vecs,
> +	if (desc->suite.akcipher.vecs.a.rsa)
> +		err = test_akcipher(tfm, desc->alg,
> +				    &desc->suite.akcipher.vecs,
>  				    desc->suite.akcipher.count);
> 
>  	crypto_free_akcipher(tfm);
> @@ -2676,6 +2785,19 @@ static const struct alg_test_desc alg_test_descs[] =
> { }
>  		}
>  	}, {
> +		.alg = "dh",
> +		.test = alg_test_akcipher,

fis_allowed=1 please

> +		.suite = {
> +			.akcipher = {
> +				.vecs = {
> +					.a = {
> +						.dh = dh_tv_template
> +					},
> +				},
> +				.count = DH_TEST_VECTORS
> +			}
> +		}
> +	}, {
>  		.alg = "digest_null",
>  		.test = alg_test_null,
>  	}, {
> @@ -3560,7 +3682,11 @@ static const struct alg_test_desc alg_test_descs[] =
> { .fips_allowed = 1,
>  		.suite = {
>  			.akcipher = {
> -				.vecs = rsa_tv_template,
> +				.vecs = {
> +					.a = {
> +						.rsa = rsa_tv_template
> +					},
> +				},
>  				.count = RSA_TEST_VECTORS
>  			}
>  		}
> diff --git a/crypto/testmgr.h b/crypto/testmgr.h
> index 487ec88..ba08ed6 100644
> --- a/crypto/testmgr.h
> +++ b/crypto/testmgr.h
> @@ -123,7 +123,7 @@ struct drbg_testvec {
>  	size_t expectedlen;
>  };
> 
> -struct akcipher_testvec {
> +struct akcipher_testvec_rsa {
>  	unsigned char *key;
>  	unsigned char *m;
>  	unsigned char *c;
> @@ -133,6 +133,23 @@ struct akcipher_testvec {
>  	bool public_key_vec;
>  };
> 
> +struct akcipher_testvec_dh {
> +	unsigned char *pkcs3;
> +	unsigned pkcs3_size;
> +	unsigned char *priv_key_A;
> +	unsigned char *pub_key_B;
> +	unsigned char *expected_pub_key_A;
> +	unsigned char *expected_shared_secret;
> +	unsigned key_len;
> +};
> +
> +struct akcipher_testvec {
> +	union {
> +		struct akcipher_testvec_rsa *rsa;
> +		struct akcipher_testvec_dh *dh;
> +	} a;
> +};
> +
>  static char zeroed_string[48];
> 
>  /*
> @@ -143,7 +160,7 @@ static char zeroed_string[48];
>  #else
>  #define RSA_TEST_VECTORS	4
>  #endif
> -static struct akcipher_testvec rsa_tv_template[] = {
> +static struct akcipher_testvec_rsa rsa_tv_template[] = {
>  	{
>  #ifndef CONFIG_CRYPTO_FIPS
>  	.key =
> @@ -330,6 +347,193 @@ static struct akcipher_testvec rsa_tv_template[] = {
>  	}
>  };
> 
> +#define DH_TEST_VECTORS 2
> +
> +struct akcipher_testvec_dh dh_tv_template[] = {
> +	{
> +	/* p, g */
> +	.pkcs3 =
> +	"\x30\x82\x01\x08\x02\x82\x01\x01\x00\x9f\xab\x7c\xc2\x50\xa7\xdc"
> +	"\x3c\x17\x2a\x5b\x9f\x76\x17\x8e\x92\xa6\xb0\x13\x1e\x6e\x7b\x9a"
> +	"\x6b\x8d\x06\xcf\x9f\x90\xb8\x21\x6a\x30\x04\xe8\xda\xc0\x13\x27"
> +	"\xc8\x40\xbf\x6c\x84\x1e\xe2\x9e\xf9\xd2\x48\x11\xc7\x06\xd3\x06"
> +	"\xb8\xaa\xbe\x69\x3f\xf2\x60\x06\xa0\xd1\x55\x03\x63\xa1\xfd\x33"
> +	"\x2c\x04\xe4\xf0\xe6\x02\x8a\x97\x1e\x22\x4f\x2b\x73\x15\x23\xa5"
> +	"\x26\x97\xd6\x91\x11\xd8\x80\x35\xe7\x7f\x19\x29\x6c\x59\x64\x24"
> +	"\x68\xc0\x40\x66\x5d\xa8\xcb\xda\x84\xce\xbc\xf7\x1b\x68\x81\xac"
> +	"\xec\xe9\x84\xc1\x46\xef\xac\xe2\xb2\x85\xf2\x92\x06\x82\xbe\xe7"
> +	"\x12\x53\x21\xfc\xc5\x82\xe5\xe3\x7f\x26\xe5\x53\x02\x58\xb1\xa9"
> +	"\x26\x32\x5f\xb9\xa6\x23\x1d\xd8\x26\xda\x7a\x67\xab\x8a\x84\x97"
> +	"\x2e\x78\xc1\x6d\xec\x67\x50\x27\x2d\x52\xf7\x67\xec\x5b\x2c\x9f"
> +	"\x17\xb7\x81\xec\x47\x60\x65\xf5\x86\x20\x4f\x82\x84\xd9\xee\x62"
> +	"\x6f\x49\x7d\x80\x9e\xaa\x8a\x7a\x82\x45\x65\x36\x0b\xf1\xfe\x01"
> +	"\x06\x52\x3c\xa1\xdf\xc8\x84\x89\xb0\xee\xb6\xfa\x95\x12\x42\xb9"
> +	"\x87\x53\x77\x1c\xe0\x56\x25\xf6\x96\x31\xec\x62\x82\x77\xb7\x52"
> +	"\xac\x25\x71\x49\x97\x13\x83\x23\x63\x02\x01\x02",
> +	.pkcs3_size = 268,
> +	.priv_key_A =
> +	"\x48\xed\x07\x3d\x49\x20\xf8\xa5\xcf\x90\xcd\xf9\x97\x63\xd2\x51"
> +	"\x3d\xac\xbd\x2d\x49\x4a\xb8\x87\x06\x62\xd2\x0c\x13\x55\x73\x77"
> +	"\x97\x15\xd3\x23\x8a\x3b\x3e\xb9\x14\xa6\xfb\x20\x7b\xd1\xea\x68"
> +	"\x85\x9a\xc6\x8f\x66\x9a\x78\xf0\x26\xce\x8c\xe0\x66\x4e\x51\xc9"
> +	"\xf5\xf9\x89\xc6\x0a\xc5\x4b\x99\xdc\xb0\x36\x3e\xf2\xc7\x7f\x52"
> +	"\x60\x99\x12\xbd\x8f\x85\x7b\x0a\x99\xa9\x85\x21\xc6\x50\x66\xf6"
> +	"\xde\x62\xc4\x08\x3f\x8c\x97\x91\xb0\x19\x72\x2a\x56\xc6\x85\x12"
> +	"\x8e\x89\x65\xa7\x13\x34\x51\x53\x2e\xe0\x07\x6c\x01\xaa\xb1\x23"
> +	"\x42\x54\xa5\x49\xfd\x01\x2a\xd8\xa7\xc3\xd6\x6a\x6f\x3c\x76\xc4"
> +	"\x4b\x37\x55\x30\xb7\xbe\xb7\x87\x4e\x43\x68\x37\xd8\xa0\x6f\x53"
> +	"\x59\xb6\x25\xd4\x44\xc9\x43\xcd\xb1\x20\x8c\xf9\x3a\xd5\xbc\x97"
> +	"\x70\x8e\xad\x1a\x8b\x69\xbd\xae\xf9\xd0\x48\x70\x40\x4d\x3f\xdc"
> +	"\xea\x10\xef\x61\x49\x1b\x87\x10\xff\x96\x36\x73\x4f\x75\xf5\x75"
> +	"\x23\xbb\x5e\x48\xe8\x96\x57\xcf\x33\x76\x78\x2e\x86\x90\x5c\x2c"
> +	"\x17\xe6\x70\x8a\x6c\x0c\x0d\xa8\x3e\x79\xa6\x9e\xe1\xbf\x18\x40"
> +	"\xeb\x2c\x1a\xb9\x14\xf5\x02\xeb\x37\x66\x06\x1c\xe8\xb5\x75\x0d",
> +	.pub_key_B =
> +	"\x18\xd9\x78\xdd\x6a\xc9\x19\x4e\xe6\xa0\x83\xcc\x12\x00\x3b\x6c"
> +	"\x4c\x8c\x11\x38\x94\x90\xd7\xc4\x1f\xa6\x64\x04\x35\x4a\xda\x48"
> +	"\x5a\xeb\x38\xe7\xae\x44\x16\x4a\x94\xfe\x7c\xa9\x00\xff\x67\x20"
> +	"\x4c\xef\x34\x45\xfe\x2d\xf5\xa9\xfb\xa8\xc0\x45\x09\xcd\xcd\xc0"
> +	"\x4c\x20\xc0\x1e\x42\x41\x4b\x37\x6c\x90\xba\xef\xd6\x65\xab\xb1"
> +	"\xec\x51\x30\xfa\x08\xfc\x22\xc6\x42\xce\x6a\x90\xb7\x27\xe4\x52"
> +	"\x76\x28\x78\x17\x56\x71\x73\xeb\xaf\x6e\xbb\x61\x7a\x6b\x4b\xdb"
> +	"\x8e\x2f\xaa\xfa\x9e\x40\xee\x84\xf6\x63\x9b\xb7\xe2\x22\x72\x6b"
> +	"\x94\x58\x3f\x08\xa5\xbe\xd6\x87\x63\xe7\xbb\x5a\xfb\x52\x92\xd2"
> +	"\xe6\x5e\x7e\x55\x78\x4b\xc0\x0e\x1a\xe5\xe6\x0f\x0e\x41\xd5\x05"
> +	"\xb7\x71\x42\x78\x35\x74\xad\x33\x9f\x24\xc0\x3b\x09\xd5\xcf\x4d"
> +	"\x6e\x20\x3a\xee\x04\x9f\x05\x2d\x8d\x77\x06\x2d\x9b\x67\xba\x39"
> +	"\x2f\x6c\x1d\x7b\x75\x57\xed\x2f\xe2\xf1\xbc\x0b\x3a\x77\xf2\xba"
> +	"\xb2\xb1\x98\x52\x34\x40\x53\x7b\x0e\xb6\x13\x6a\x5b\x91\xe4\x59"
> +	"\x67\x2c\x45\x3a\x07\x1a\xa2\x3b\xdb\xa1\xa6\x08\xf0\x80\xe8\x61"
> +	"\xca\xac\x95\xb3\x3e\xd6\x97\x98\x08\x7e\x50\x48\xc0\x25\x45\xd0",
> +	.expected_pub_key_A =
> +	"\x91\x9e\x52\xa3\xb8\x20\x25\x12\x17\xcc\x37\x82\x81\x22\x14\x7a"
> +	"\x81\x88\xce\x9f\xf2\x46\xb1\x17\xaf\x41\x23\xc9\xb8\x93\x40\xfd"
> +	"\xa9\x96\x05\x5a\x1a\xcc\xa6\x51\xe2\x9e\xca\x63\x2a\x67\x72\x4a"
> +	"\xe1\x2b\xa7\xbe\xf9\xeb\x69\xc8\x2d\x29\xb6\x6b\x5f\xc0\xf2\x90"
> +	"\xa9\x36\x49\xdb\xcc\x6b\x5e\xed\x76\x47\x9f\xc9\x2e\x91\x68\x75"
> +	"\xa3\x39\x6c\x50\xa6\xaf\x81\xac\x23\x58\xa9\xc9\x71\xf3\x87\x97"
> +	"\xef\x0c\x80\x19\xac\xb7\xf0\xa0\x83\x44\x4b\x1c\x08\xf1\x4f\x23"
> +	"\xfb\xf1\x61\x39\x00\x59\xef\x83\xa5\xaf\x2f\x3f\xc0\x19\x2a\x5b"
> +	"\x22\x53\xdb\x8b\x24\xbc\xe4\xaa\x9a\x19\x6b\xfd\x20\xbf\x1a\xe2"
> +	"\xb5\xaf\x82\x3e\xb8\xea\xe7\x28\xcd\xad\xfe\x00\xee\x70\x52\x46"
> +	"\x3d\x2c\x55\x81\x44\xed\x15\x21\xc8\x48\x75\x4d\x6f\xf0\xba\xe9"
> +	"\xab\x4c\x65\xf3\x54\x2e\x74\xd9\xe7\xe2\xb7\xad\xec\x6d\xb2\x6e"
> +	"\xc1\xe3\x2d\x0e\xb1\x18\x36\xd7\xb9\x42\x6b\x2f\xc9\x51\x2e\xff"
> +	"\x5d\xd0\xca\x8c\x0d\x0d\x95\xd3\x16\xf3\xdb\xc1\x2b\xed\x00\x32"
> +	"\xd7\x77\xb8\x0e\x86\x7a\x57\x48\x74\x23\x30\xae\xe0\x3c\x38\xa6"
> +	"\xed\xf9\x0c\x16\xf2\xf2\xa0\xe0\x51\x80\x67\x92\xe4\xc7\x9a\x5e",
> +	.expected_shared_secret =
> +	"\x1d\x7d\x2e\x47\x06\xbe\x46\xd3\x69\xf6\xe7\x0e\x88\xdc\xe8\xe1"
> +	"\xe6\x6a\xfc\x3c\xbc\xc1\x85\xe9\x24\xf0\x7b\x75\x0f\xa4\x04\xd6"
> +	"\x9b\xef\x7b\x30\x55\xde\xbf\xd4\xb2\xcb\xce\x74\x53\xae\x72\x34"
> +	"\x19\x36\x9e\xe9\x45\xb8\xda\x59\x22\x41\x9e\xa3\x8f\x02\xaa\x60"
> +	"\xb1\x8b\xf9\x84\xd4\x8a\xeb\xea\xd1\xd9\x1a\x53\xe9\x5f\x01\xd1"
> +	"\x40\xb4\x73\x63\xc5\x1a\x79\xf1\x08\xb6\xc0\x0c\x85\x9e\x3e\x70"
> +	"\xea\x79\xd9\xc2\x5b\x17\xa7\x1e\xeb\x58\x3e\x1b\xca\x7a\x4d\xab"
> +	"\x61\x5b\xdf\xa2\x6f\x1e\xd4\x36\xeb\xe3\xe9\x04\x10\x8e\x0b\xc9"
> +	"\x18\x8c\x0d\x6e\x4f\x2e\xc5\xfc\x5b\x6a\xb5\x9f\xdf\x71\x50\x04"
> +	"\x54\x62\x49\x57\xf3\xc6\x9e\x39\xc6\x56\xf1\x2d\x31\x59\x58\xdb"
> +	"\x67\x94\x25\xbd\x47\xe2\xdd\x95\x0c\x39\xb1\xfa\x22\xc6\x94\xc4"
> +	"\x75\xab\xff\xe2\xce\x52\xa2\xeb\x78\x26\x10\x0f\x2d\x8c\xf2\xad"
> +	"\xd2\xc7\xaf\x85\xd9\x5c\x71\xfe\x9e\xe9\xeb\xbf\x20\x36\x1e\x9a"
> +	"\x74\x43\xe6\x06\x00\x8a\x4d\x64\x41\x2a\x15\x6d\x60\x44\x3f\x2c"
> +	"\xcd\x05\x16\x54\x6a\x48\x7c\x71\x0a\xe9\x33\x95\x16\xc7\xf4\x23"
> +	"\xc2\x8d\xed\x8a\x24\x5d\x99\xc7\x8c\x8b\x07\x47\x8c\xe9\x0c\x10",
> +	.key_len = 256
> +	},
> +	{
> +	/* p, g */
> +	.pkcs3 =
> +	"\x30\x82\x01\x08\x02\x82\x01\x01\x00\x9f\xab\x7c\xc2\x50\xa7\xdc"
> +	"\x3c\x17\x2a\x5b\x9f\x76\x17\x8e\x92\xa6\xb0\x13\x1e\x6e\x7b\x9a"
> +	"\x6b\x8d\x06\xcf\x9f\x90\xb8\x21\x6a\x30\x04\xe8\xda\xc0\x13\x27"
> +	"\xc8\x40\xbf\x6c\x84\x1e\xe2\x9e\xf9\xd2\x48\x11\xc7\x06\xd3\x06"
> +	"\xb8\xaa\xbe\x69\x3f\xf2\x60\x06\xa0\xd1\x55\x03\x63\xa1\xfd\x33"
> +	"\x2c\x04\xe4\xf0\xe6\x02\x8a\x97\x1e\x22\x4f\x2b\x73\x15\x23\xa5"
> +	"\x26\x97\xd6\x91\x11\xd8\x80\x35\xe7\x7f\x19\x29\x6c\x59\x64\x24"
> +	"\x68\xc0\x40\x66\x5d\xa8\xcb\xda\x84\xce\xbc\xf7\x1b\x68\x81\xac"
> +	"\xec\xe9\x84\xc1\x46\xef\xac\xe2\xb2\x85\xf2\x92\x06\x82\xbe\xe7"
> +	"\x12\x53\x21\xfc\xc5\x82\xe5\xe3\x7f\x26\xe5\x53\x02\x58\xb1\xa9"
> +	"\x26\x32\x5f\xb9\xa6\x23\x1d\xd8\x26\xda\x7a\x67\xab\x8a\x84\x97"
> +	"\x2e\x78\xc1\x6d\xec\x67\x50\x27\x2d\x52\xf7\x67\xec\x5b\x2c\x9f"
> +	"\x17\xb7\x81\xec\x47\x60\x65\xf5\x86\x20\x4f\x82\x84\xd9\xee\x62"
> +	"\x6f\x49\x7d\x80\x9e\xaa\x8a\x7a\x82\x45\x65\x36\x0b\xf1\xfe\x01"
> +	"\x06\x52\x3c\xa1\xdf\xc8\x84\x89\xb0\xee\xb6\xfa\x95\x12\x42\xb9"
> +	"\x87\x53\x77\x1c\xe0\x56\x25\xf6\x96\x31\xec\x62\x82\x77\xb7\x52"
> +	"\xac\x25\x71\x49\x97\x13\x83\x23\x63\x02\x01\x02",
> +	.pkcs3_size = 268,
> +	.priv_key_A =
> +	"\x7d\xfb\xa2\x51\x24\xa4\xfa\x65\x35\x1c\x3b\xef\x3f\x6b\x10\x27"
> +	"\xde\x30\xcb\x2c\xa7\x5b\xfe\x1a\xec\x5f\x2b\x1c\x7b\xd8\xa7\xfd"
> +	"\x37\x15\xec\x62\xbd\x64\x71\x57\x31\x48\xcc\x8c\xd9\x6f\xe9\x24"
> +	"\x9d\x63\xff\x1f\xb6\x7d\xf7\x30\x23\x13\xdc\x0f\x27\xd9\x6e\x11"
> +	"\x8b\x54\x80\xe4\x35\x52\x98\x5c\xac\x87\x56\xdf\x5e\xe2\xbe\x08"
> +	"\x63\xfd\xb2\xe4\x06\x2b\x04\x68\xf6\x3a\x45\x3b\xb0\xf1\x81\x32"
> +	"\x36\xa3\xde\xe4\xe7\xec\x8b\x87\x32\x09\x45\x87\x1c\x1c\x0e\x84"
> +	"\xf7\x30\x09\x7d\x7f\x98\xf5\xbe\x92\x50\xbd\xa8\xc2\x35\x11\xe3"
> +	"\x0a\xf2\x90\x1a\x18\xcb\x5a\xe5\x4e\x4a\x93\x3d\x6d\x26\xa6\x36"
> +	"\x79\x45\x75\x12\xb4\x27\x95\xcd\x9e\x6b\x37\x57\x4d\x69\x21\xa9"
> +	"\xff\x5d\xe2\xf2\xf8\x4f\xeb\x50\x79\xa4\xa7\x87\x59\x78\x23\xfa"
> +	"\x67\xb5\xdc\x6e\xa6\x59\x81\xba\x65\x8e\x65\xfc\x7f\x51\xc8\xad"
> +	"\x1d\x28\x50\x60\x92\x2a\xcc\x9c\x47\xc7\x13\xd2\xf4\xb8\xa2\xab"
> +	"\x2c\x50\x4c\xf1\xcd\xef\xb7\x94\x1c\xe7\xd3\x2a\x55\x37\xff\xfa"
> +	"\x6d\xe8\x43\x01\xb0\x9b\x24\x5d\xd4\x57\x7d\xb5\x30\xaa\x60\x97"
> +	"\x33\xfe\xe7\x31\x39\x96\xe6\xb3\xf4\x11\xde\x3c\x57\x4b\xcb\xad",
> +	.pub_key_B =
> +	"\x91\x9e\x52\xa3\xb8\x20\x25\x12\x17\xcc\x37\x82\x81\x22\x14\x7a"
> +	"\x81\x88\xce\x9f\xf2\x46\xb1\x17\xaf\x41\x23\xc9\xb8\x93\x40\xfd"
> +	"\xa9\x96\x05\x5a\x1a\xcc\xa6\x51\xe2\x9e\xca\x63\x2a\x67\x72\x4a"
> +	"\xe1\x2b\xa7\xbe\xf9\xeb\x69\xc8\x2d\x29\xb6\x6b\x5f\xc0\xf2\x90"
> +	"\xa9\x36\x49\xdb\xcc\x6b\x5e\xed\x76\x47\x9f\xc9\x2e\x91\x68\x75"
> +	"\xa3\x39\x6c\x50\xa6\xaf\x81\xac\x23\x58\xa9\xc9\x71\xf3\x87\x97"
> +	"\xef\x0c\x80\x19\xac\xb7\xf0\xa0\x83\x44\x4b\x1c\x08\xf1\x4f\x23"
> +	"\xfb\xf1\x61\x39\x00\x59\xef\x83\xa5\xaf\x2f\x3f\xc0\x19\x2a\x5b"
> +	"\x22\x53\xdb\x8b\x24\xbc\xe4\xaa\x9a\x19\x6b\xfd\x20\xbf\x1a\xe2"
> +	"\xb5\xaf\x82\x3e\xb8\xea\xe7\x28\xcd\xad\xfe\x00\xee\x70\x52\x46"
> +	"\x3d\x2c\x55\x81\x44\xed\x15\x21\xc8\x48\x75\x4d\x6f\xf0\xba\xe9"
> +	"\xab\x4c\x65\xf3\x54\x2e\x74\xd9\xe7\xe2\xb7\xad\xec\x6d\xb2\x6e"
> +	"\xc1\xe3\x2d\x0e\xb1\x18\x36\xd7\xb9\x42\x6b\x2f\xc9\x51\x2e\xff"
> +	"\x5d\xd0\xca\x8c\x0d\x0d\x95\xd3\x16\xf3\xdb\xc1\x2b\xed\x00\x32"
> +	"\xd7\x77\xb8\x0e\x86\x7a\x57\x48\x74\x23\x30\xae\xe0\x3c\x38\xa6"
> +	"\xed\xf9\x0c\x16\xf2\xf2\xa0\xe0\x51\x80\x67\x92\xe4\xc7\x9a\x5e",
> +	.expected_pub_key_A =
> +	"\x18\xd9\x78\xdd\x6a\xc9\x19\x4e\xe6\xa0\x83\xcc\x12\x00\x3b\x6c"
> +	"\x4c\x8c\x11\x38\x94\x90\xd7\xc4\x1f\xa6\x64\x04\x35\x4a\xda\x48"
> +	"\x5a\xeb\x38\xe7\xae\x44\x16\x4a\x94\xfe\x7c\xa9\x00\xff\x67\x20"
> +	"\x4c\xef\x34\x45\xfe\x2d\xf5\xa9\xfb\xa8\xc0\x45\x09\xcd\xcd\xc0"
> +	"\x4c\x20\xc0\x1e\x42\x41\x4b\x37\x6c\x90\xba\xef\xd6\x65\xab\xb1"
> +	"\xec\x51\x30\xfa\x08\xfc\x22\xc6\x42\xce\x6a\x90\xb7\x27\xe4\x52"
> +	"\x76\x28\x78\x17\x56\x71\x73\xeb\xaf\x6e\xbb\x61\x7a\x6b\x4b\xdb"
> +	"\x8e\x2f\xaa\xfa\x9e\x40\xee\x84\xf6\x63\x9b\xb7\xe2\x22\x72\x6b"
> +	"\x94\x58\x3f\x08\xa5\xbe\xd6\x87\x63\xe7\xbb\x5a\xfb\x52\x92\xd2"
> +	"\xe6\x5e\x7e\x55\x78\x4b\xc0\x0e\x1a\xe5\xe6\x0f\x0e\x41\xd5\x05"
> +	"\xb7\x71\x42\x78\x35\x74\xad\x33\x9f\x24\xc0\x3b\x09\xd5\xcf\x4d"
> +	"\x6e\x20\x3a\xee\x04\x9f\x05\x2d\x8d\x77\x06\x2d\x9b\x67\xba\x39"
> +	"\x2f\x6c\x1d\x7b\x75\x57\xed\x2f\xe2\xf1\xbc\x0b\x3a\x77\xf2\xba"
> +	"\xb2\xb1\x98\x52\x34\x40\x53\x7b\x0e\xb6\x13\x6a\x5b\x91\xe4\x59"
> +	"\x67\x2c\x45\x3a\x07\x1a\xa2\x3b\xdb\xa1\xa6\x08\xf0\x80\xe8\x61"
> +	"\xca\xac\x95\xb3\x3e\xd6\x97\x98\x08\x7e\x50\x48\xc0\x25\x45\xd0",
> +	.expected_shared_secret =
> +	"\x1d\x7d\x2e\x47\x06\xbe\x46\xd3\x69\xf6\xe7\x0e\x88\xdc\xe8\xe1"
> +	"\xe6\x6a\xfc\x3c\xbc\xc1\x85\xe9\x24\xf0\x7b\x75\x0f\xa4\x04\xd6"
> +	"\x9b\xef\x7b\x30\x55\xde\xbf\xd4\xb2\xcb\xce\x74\x53\xae\x72\x34"
> +	"\x19\x36\x9e\xe9\x45\xb8\xda\x59\x22\x41\x9e\xa3\x8f\x02\xaa\x60"
> +	"\xb1\x8b\xf9\x84\xd4\x8a\xeb\xea\xd1\xd9\x1a\x53\xe9\x5f\x01\xd1"
> +	"\x40\xb4\x73\x63\xc5\x1a\x79\xf1\x08\xb6\xc0\x0c\x85\x9e\x3e\x70"
> +	"\xea\x79\xd9\xc2\x5b\x17\xa7\x1e\xeb\x58\x3e\x1b\xca\x7a\x4d\xab"
> +	"\x61\x5b\xdf\xa2\x6f\x1e\xd4\x36\xeb\xe3\xe9\x04\x10\x8e\x0b\xc9"
> +	"\x18\x8c\x0d\x6e\x4f\x2e\xc5\xfc\x5b\x6a\xb5\x9f\xdf\x71\x50\x04"
> +	"\x54\x62\x49\x57\xf3\xc6\x9e\x39\xc6\x56\xf1\x2d\x31\x59\x58\xdb"
> +	"\x67\x94\x25\xbd\x47\xe2\xdd\x95\x0c\x39\xb1\xfa\x22\xc6\x94\xc4"
> +	"\x75\xab\xff\xe2\xce\x52\xa2\xeb\x78\x26\x10\x0f\x2d\x8c\xf2\xad"
> +	"\xd2\xc7\xaf\x85\xd9\x5c\x71\xfe\x9e\xe9\xeb\xbf\x20\x36\x1e\x9a"
> +	"\x74\x43\xe6\x06\x00\x8a\x4d\x64\x41\x2a\x15\x6d\x60\x44\x3f\x2c"
> +	"\xcd\x05\x16\x54\x6a\x48\x7c\x71\x0a\xe9\x33\x95\x16\xc7\xf4\x23"
> +	"\xc2\x8d\xed\x8a\x24\x5d\x99\xc7\x8c\x8b\x07\x47\x8c\xe9\x0c\x10",
> +	.key_len = 256
> +	}
> +};
> +
>  /*
>   * MD4 test vectors from RFC1320
>   */


Ciao
Stephan

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH] crypto: implement DH primitives under akcipher API
  2016-02-15  9:01 [PATCH] crypto: implement DH primitives under akcipher API Salvatore Benedetto
  2016-02-15 13:57 ` Stephan Mueller
@ 2016-02-16 20:19 ` Herbert Xu
  2016-02-16 20:29   ` Tadeusz Struk
  2016-03-01 20:25 ` Marcel Holtmann
  2 siblings, 1 reply; 18+ messages in thread
From: Herbert Xu @ 2016-02-16 20:19 UTC (permalink / raw)
  To: Salvatore Benedetto; +Cc: linux-crypto

On Mon, Feb 15, 2016 at 09:01:55AM +0000, Salvatore Benedetto wrote:
> Implement Diffie-Hellman primitives required by the scheme under the
> akcipher API. Here is how it works.
> 1) Call set_pub_key() by passing DH parameters (p,g) in PKCS3 format
> 2) Call set_priv_key() to set your own private key (xa) in raw format
> 3) Call decrypt() without passing any data as input to get back the
>    public part which will be computed as g^xa mod p
> 4) Call encrypt() by passing the counter part public key (yb) in raw format
>    as input to get back the shared secret calculated as zz = yb^xa mod p
> 
> A test is included in the patch. Test vector has been generated with
> openssl
> 
> Signed-off-by: Salvatore Benedetto <salvatore.benedetto@intel.com>

Who is going to use this?

Thanks,
-- 
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH] crypto: implement DH primitives under akcipher API
  2016-02-16 20:19 ` Herbert Xu
@ 2016-02-16 20:29   ` Tadeusz Struk
  0 siblings, 0 replies; 18+ messages in thread
From: Tadeusz Struk @ 2016-02-16 20:29 UTC (permalink / raw)
  To: Herbert Xu, Salvatore Benedetto; +Cc: linux-crypto

On 02/16/2016 12:19 PM, Herbert Xu wrote:
> On Mon, Feb 15, 2016 at 09:01:55AM +0000, Salvatore Benedetto wrote:
>> > Implement Diffie-Hellman primitives required by the scheme under the
>> > akcipher API. Here is how it works.
>> > 1) Call set_pub_key() by passing DH parameters (p,g) in PKCS3 format
>> > 2) Call set_priv_key() to set your own private key (xa) in raw format
>> > 3) Call decrypt() without passing any data as input to get back the
>> >    public part which will be computed as g^xa mod p
>> > 4) Call encrypt() by passing the counter part public key (yb) in raw format
>> >    as input to get back the shared secret calculated as zz = yb^xa mod p
>> > 
>> > A test is included in the patch. Test vector has been generated with
>> > openssl
>> > 
>> > Signed-off-by: Salvatore Benedetto <salvatore.benedetto@intel.com>
> Who is going to use this?

OpenSSL via PF_ALG. The plan for this is to accelerate TLS handshakes in HW.
This is an RFC to get your opinion on the usage of the API.
Are you ok with the approach?
Thanks,

-- 
TS

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH] crypto: implement DH primitives under akcipher API
  2016-02-15 13:57 ` Stephan Mueller
@ 2016-03-01 11:08   ` Salvatore Benedetto
  2016-03-01 11:17     ` Stephan Mueller
  0 siblings, 1 reply; 18+ messages in thread
From: Salvatore Benedetto @ 2016-03-01 11:08 UTC (permalink / raw)
  To: Stephan Mueller; +Cc: tadeusz.struk, linux-crypto, herbert


Hi Stephan,

thanks for reviewing.

On Mon, Feb 15, 2016 at 02:57:08PM +0100, Stephan Mueller wrote:
> Am Montag, 15. Februar 2016, 09:01:55 schrieb Salvatore Benedetto:
> 
> Hi Salvatore, Herbert,
> 
> > Implement Diffie-Hellman primitives required by the scheme under the
> > akcipher API. Here is how it works.
> > 1) Call set_pub_key() by passing DH parameters (p,g) in PKCS3 format
> > 2) Call set_priv_key() to set your own private key (xa) in raw format
> > 3) Call decrypt() without passing any data as input to get back the
> >    public part which will be computed as g^xa mod p
> > 4) Call encrypt() by passing the counter part public key (yb) in raw format
> >    as input to get back the shared secret calculated as zz = yb^xa mod p
> > 
> > A test is included in the patch. Test vector has been generated with
> > openssl
> 
> Herbert, as this is a raw DH operation where the shared secret must be 
> subjected to a KDF, I guess the KDF patch I provided some time ago may become 
> of interest again?
> > 
> > Signed-off-by: Salvatore Benedetto <salvatore.benedetto@intel.com>
> > ---
> >  crypto/Kconfig    |   8 ++
> >  crypto/Makefile   |   7 ++
> >  crypto/dh.c       | 264
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++++ crypto/pkcs3.asn1 | 
> >  5 ++
> >  crypto/tcrypt.c   |   4 +
> >  crypto/testmgr.c  | 140 +++++++++++++++++++++++++++--
> >  crypto/testmgr.h  | 208 +++++++++++++++++++++++++++++++++++++++++-
> >  7 files changed, 627 insertions(+), 9 deletions(-)
> >  create mode 100644 crypto/dh.c
> >  create mode 100644 crypto/pkcs3.asn1
> > 
> > diff --git a/crypto/Kconfig b/crypto/Kconfig
> > index f6bfdda..fd5b78d 100644
> > --- a/crypto/Kconfig
> > +++ b/crypto/Kconfig
> > @@ -101,6 +101,14 @@ config CRYPTO_RSA
> >  	help
> >  	  Generic implementation of the RSA public key algorithm.
> > 
> > +config CRYPTO_DH
> > +	tristate "Diffie-Hellman algorithm"
> > +	select CRYPTO_AKCIPHER
> > +	select MPILIB
> > +	select ASN1
> > +	help
> > +	  Generic implementation of the Diffie-Hellman algorithm.
> > +
> >  config CRYPTO_MANAGER
> >  	tristate "Cryptographic algorithm manager"
> >  	select CRYPTO_MANAGER2
> > diff --git a/crypto/Makefile b/crypto/Makefile
> > index 4f4ef7e..ee73489 100644
> > --- a/crypto/Makefile
> > +++ b/crypto/Makefile
> > @@ -31,6 +31,13 @@ obj-$(CONFIG_CRYPTO_HASH2) += crypto_hash.o
> > 
> >  obj-$(CONFIG_CRYPTO_AKCIPHER2) += akcipher.o
> > 
> > +$(obj)/pkcs3-asn1.o: $(obj)/pkcs3-asn1.c $(obj)/pkcs3-asn1.h
> > +clean-files += pkcs3-asn1.c pkcs3-asn1.h
> > +
> > +dh_generic-y := pkcs3-asn1.o
> > +dh_generic-y += dh.o
> > +obj-$(CONFIG_CRYPTO_DH) += dh_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
> > clean-files += rsapubkey-asn1.c rsapubkey-asn1.h
> > diff --git a/crypto/dh.c b/crypto/dh.c
> > new file mode 100644
> > index 0000000..614c4f1
> > --- /dev/null
> > +++ b/crypto/dh.c
> > @@ -0,0 +1,264 @@
> > +/*  Diffie-Hellman Key Agreement Method [RFC2631]
> > + *
> > + * 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/module.h>
> > +#include <crypto/internal/akcipher.h>
> > +#include <crypto/akcipher.h>
> > +#include <crypto/algapi.h>
> > +#include <linux/mpi.h>
> > +#include "pkcs3-asn1.h"
> > +
> > +struct dh_params {
> > +	MPI p;
> > +	MPI g;
> > +	MPI xa;
> > +};
> > +
> > +int dh_get_g(void *context, size_t hdrlen, unsigned char tag, const void
> > *value, +	     size_t vlen)
> > +{
> > +	struct dh_params *params = context;
> > +
> > +	params->g = mpi_read_raw_data(value, vlen);
> > +
> > +	if (!params->g)
> > +		return -ENOMEM;
> > +
> > +	return 0;
> > +}
> > +
> > +int dh_get_p(void *context, size_t hdrlen, unsigned char tag, const void
> > *value, +	     size_t vlen)
> > +{
> > +	struct dh_params *params = context;
> > +
> > +	params->p = mpi_read_raw_data(value, vlen);
> > +
> > +	if (!params->p)
> > +		return -ENOMEM;
> > +
> > +	return 0;
> > +}
> > +
> > +static int dh_parse_params(struct dh_params *params, const void *key,
> > +			   unsigned int keylen)
> > +{
> > +	int ret;
> > +
> > +	mpi_free(params->p);
> > +	mpi_free(params->g);
> > +
> > +	ret = asn1_ber_decoder(&pkcs3_decoder, params, key, keylen);
> > +
> > +	return ret;
> > +}
> > +
> > +static void dh_free_params(struct dh_params *params)
> > +{
> > +	mpi_free(params->p);
> > +	mpi_free(params->g);
> > +	mpi_free(params->xa);
> > +	params->p = NULL;
> > +	params->g = NULL;
> > +	params->xa = NULL;
> > +}
> > +
> > +/*
> > + * Public key generation function [RFC2631 sec 2.1.1]
> > + * ya = g^xa mod p;
> > + */
> > +static int _generate_public_key(const struct dh_params *params, MPI ya)
> > +{
> > +	/* ya = g^xa mod p */
> > +	return mpi_powm(ya, params->g, params->xa, params->p);
> > +}
> > +
> > +/*
> > + * ZZ generation function [RFC2631 sec 2.1.1]
> > + * ZZ = yb^xa mod p;
> > + */
> > +static int _compute_shared_secret(const struct dh_params *params, MPI yb,
> > +				  MPI zz)
> > +{
> > +	/* ZZ = yb^xa mod p */
> > +	return mpi_powm(zz, yb, params->xa, params->p);
> > +}
> > +
> > +static inline struct dh_params *dh_get_params(struct crypto_akcipher *tfm)
> > +{
> > +	return akcipher_tfm_ctx(tfm);
> > +}
> > +
> > +static int dh_generate_public_key(struct akcipher_request *req)
> > +{
> > +	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
> > +	const struct dh_params *params = dh_get_params(tfm);
> > +	MPI ya = mpi_alloc(0);
> > +	int ret = 0;
> > +	int sign;
> > +
> > +	if (!ya)
> > +		return -ENOMEM;
> > +
> > +	if (unlikely(!params->p || !params->g || !params->xa)) {
> > +		ret = -EINVAL;
> > +		goto err_free_ya;
> > +	}
> > +	ret = _generate_public_key(params, ya);
> > +	if (ret)
> > +		goto err_free_ya;
> > +
> > +	ret = mpi_write_to_sgl(ya, req->dst, &req->dst_len, &sign);
> > +	if (ret)
> > +		goto err_free_ya;
> > +
> > +	if (sign < 0)
> > +		ret = -EBADMSG;
> > +
> > +err_free_ya:
> > +	mpi_free(ya);
> > +	return ret;
> > +}
> > +
> > +static int dh_compute_shared_secret(struct akcipher_request *req)
> > +{
> > +	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
> > +	struct dh_params *params = dh_get_params(tfm);
> > +	MPI yb, zz = mpi_alloc(0);
> > +	int ret = 0;
> > +	int sign;
> > +
> > +	if (!zz)
> > +		return -ENOMEM;
> > +
> > +	if (unlikely(!params->p || !params->xa)) {
> > +		ret = -EINVAL;
> > +		goto err_free_zz;
> > +	}
> > +
> > +	yb = mpi_read_raw_from_sgl(req->src, req->src_len);
> > +	if (!yb) {
> > +		ret = EINVAL;
> > +		goto err_free_zz;
> > +	}
> > +
> > +	ret = _compute_shared_secret(params, yb, zz);
> > +	if (ret)
> > +		goto err_free_yb;
> > +
> > +	ret = mpi_write_to_sgl(zz, req->dst, &req->dst_len, &sign);
> > +	if (ret)
> > +		goto err_free_yb;
> > +
> > +	if (sign < 0)
> > +		ret = -EBADMSG;
> > +
> > +err_free_yb:
> > +	mpi_free(yb);
> > +err_free_zz:
> > +	mpi_free(zz);
> > +	return ret;
> > +}
> > +
> > +static int dh_check_params_length(unsigned int p_len)
> > +{
> > +	switch (p_len) {
> > +	case 768:
> > +	case 1024:
> > +	case 1536:
> > +	case 2048:
> > +	case 3072:
> > +	case 4096:
> > +		return 0;
> > +	}
> > +	return -EINVAL;
> > +}
> 
> What is the reason for restricting the size to 4096?

Honestly no reason.
Could not find restrictions in the spec about the params length.

> > +
> > +static int dh_no_op(struct akcipher_request *req)
> > +{
> > +	return -ENOPROTOOPT;
> > +}
> > +
> > +static int dh_set_priv_key(struct crypto_akcipher *tfm, const void *key,
> > +			   unsigned int keylen)
> > +{
> > +	struct dh_params *params = akcipher_tfm_ctx(tfm);
> 
> dh_get_params?

You mean adding a helper function? OK.

> > +
> > +	params->xa = mpi_read_raw_data(key, keylen);
> > +
> > +	if (!params->xa)
> > +		return -EINVAL;
> > +
> > +	return 0;
> > +}
> > +
> > +static int dh_set_pub_key(struct crypto_akcipher *tfm, const void *key,
> > +			  unsigned int keylen)
> > +{
> > +	struct dh_params *params = akcipher_tfm_ctx(tfm);
> 
> dh_get_params?
> 
> > +	int ret = 0;
> > +
> > +	ret = dh_parse_params(params, key, keylen);
> > +	if (ret)
> > +		return ret;
> > +	if (dh_check_params_length(mpi_get_size(params->p) << 3))
> > +		ret = -EINVAL;
> > +
> > +	return ret;
> > +}
> > +
> > +static int dh_max_size(struct crypto_akcipher *tfm)
> > +{
> > +	struct dh_params *params = akcipher_tfm_ctx(tfm);
> 
> dh_get_params?
> > +
> > +	return params->p ? mpi_get_size(params->p) : -EINVAL;
> > +}
> > +
> > +static void dh_exit_tfm(struct crypto_akcipher *tfm)
> > +{
> > +	struct dh_params *params = akcipher_tfm_ctx(tfm);
> 
> dh_get_params?
> 
> > +
> > +	dh_free_params(params);
> > +}
> > +
> > +static struct akcipher_alg dh = {
> > +	.encrypt = dh_compute_shared_secret,
> > +	.decrypt = dh_generate_public_key,
> 
> May I ask what purpose this function has? I thought a DH shall generate the 
> shared secret only?

The public part is also generated like the shared secret, thus we want
to accelerate even that part.

> 
> > +	.sign = dh_no_op,
> > +	.verify = dh_no_op,
> > +	.set_priv_key = dh_set_priv_key,
> > +	.set_pub_key = dh_set_pub_key,
> > +	.max_size = dh_max_size,
> > +	.exit = dh_exit_tfm,
> > +	.base = {
> > +		.cra_name = "dh",
> > +		.cra_driver_name = "dh-generic",
> > +		.cra_priority = 100,
> > +		.cra_module = THIS_MODULE,
> > +		.cra_ctxsize = sizeof(struct dh_params),
> > +	},
> > +};
> > +
> > +static int dh_init(void)
> > +{
> > +	return crypto_register_akcipher(&dh);
> > +}
> > +
> > +static void dh_exit(void)
> > +{
> > +	crypto_unregister_akcipher(&dh);
> > +}
> > +
> > +module_init(dh_init);
> > +module_exit(dh_exit);
> > +MODULE_ALIAS_CRYPTO("dh");
> > +MODULE_LICENSE("GPL");
> > +MODULE_DESCRIPTION("DH generic algorithm");
> > diff --git a/crypto/pkcs3.asn1 b/crypto/pkcs3.asn1
> > new file mode 100644
> > index 0000000..3d4ba5c
> > --- /dev/null
> > +++ b/crypto/pkcs3.asn1
> > @@ -0,0 +1,5 @@
> > +DHParameter ::= SEQUENCE {
> > +    prime               INTEGER ({ dh_get_p }),
> > +    base                INTEGER ({ dh_get_g }),
> > +    private_len         INTEGER OPTIONAL
> > +}
> > diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c
> > index 579dce0..53c45f7 100644
> > --- a/crypto/tcrypt.c
> > +++ b/crypto/tcrypt.c
> > @@ -1981,6 +1981,10 @@ static int do_test(const char *alg, u32 type, u32
> > mask, int m) speed_template_8_32);
> >  		break;
> > 
> > +	case 600:
> > +		ret += tcrypt_test("dh");
> > +		break;
> > +
> >  	case 1000:
> >  		test_available();
> >  		break;
> > diff --git a/crypto/testmgr.c b/crypto/testmgr.c
> > index 93f3527..adf6815 100644
> > --- a/crypto/testmgr.c
> > +++ b/crypto/testmgr.c
> > @@ -112,7 +112,7 @@ struct drbg_test_suite {
> >  };
> > 
> >  struct akcipher_test_suite {
> > -	struct akcipher_testvec *vecs;
> > +	struct akcipher_testvec vecs;
> >  	unsigned int count;
> >  };
> > 
> > @@ -1773,8 +1773,113 @@ static int alg_test_drbg(const struct alg_test_desc
> > *desc, const char *driver,
> > 
> >  }
> > 
> > +static int do_test_dh(struct crypto_akcipher *tfm,
> > +		      struct akcipher_testvec_dh *vec)
> > +{
> > +	struct akcipher_request *req;
> > +	void *input_buf = NULL;
> > +	void *output_buf = NULL;
> > +	struct tcrypt_result result;
> > +	unsigned int out_len_max;
> > +	int err = -ENOMEM;
> > +	struct scatterlist src, dst;
> > +
> > +	req = akcipher_request_alloc(tfm, GFP_KERNEL);
> > +	if (!req)
> > +		return err;
> > +
> > +	init_completion(&result.completion);
> > +
> > +	/* Set p,g */
> > +	err = crypto_akcipher_set_pub_key(tfm, vec->pkcs3, vec->pkcs3_size);
> > +	if (err)
> > +		goto free_req;
> > +
> > +	/* Set A private Key */
> > +	err = crypto_akcipher_set_priv_key(tfm, vec->priv_key_A, vec-
> >key_len);
> > +	if (err)
> > +		goto free_req;
> > +
> > +	out_len_max = crypto_akcipher_maxsize(tfm);
> > +	output_buf = kzalloc(out_len_max, GFP_KERNEL);
> > +	if (!output_buf) {
> > +		err = -ENOMEM;
> > +		goto free_req;
> > +	}
> > +
> > +	sg_init_one(&dst, output_buf, out_len_max);
> > +	akcipher_request_set_crypt(req, NULL, &dst, 0, out_len_max);
> > +	akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
> > +				      tcrypt_complete, &result);
> > +
> > +	/* Compute A public key = g^xa mod p */
> > +	err = wait_async_op(&result, crypto_akcipher_decrypt(req));
> > +	if (err) {
> > +		pr_err("alg: dh: decrypt test failed. err %d\n", err);
> > +		goto free_output;
> > +	}
> > +	/* Verify calculated public key */
> > +	if (memcmp(vec->expected_pub_key_A, sg_virt(req->dst), vec->key_len)) 
> {
> > +		pr_err("alg: dh: decrypt test failed. Invalid output\n");
> > +		err = -EINVAL;
> > +		goto free_output;
> > +	}
> > +
> > +	/* Calculate shared secret key by using counter part public key. */
> > +	input_buf = kzalloc(vec->key_len, GFP_KERNEL);
> > +	if (!input_buf) {
> > +		err = -ENOMEM;
> > +		goto free_output;
> > +	}
> > +
> > +	memcpy(input_buf, vec->pub_key_B, vec->key_len);
> > +	sg_init_one(&src, input_buf, vec->key_len);
> > +	sg_init_one(&dst, output_buf, out_len_max);
> > +	akcipher_request_set_crypt(req, &src, &dst, vec->key_len, 
> out_len_max);
> > +	akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
> > +				      tcrypt_complete, &result);
> > +	err = wait_async_op(&result, crypto_akcipher_encrypt(req));
> > +	if (err) {
> > +		pr_err("alg: dh: encrypt test failed. err %d\n", err);
> > +		goto free_all;
> > +	}
> > +	/*
> > +	 * verify shared secret from which the user will derive
> > +	 * secret key by executing whatever hash it has chosen
> > +	 */
> > +	if (memcmp(vec->expected_shared_secret, sg_virt(req->dst),
> > +		   vec->key_len)) {
> > +		pr_err("alg: dh: encrypt test failed. Invalid output\n");
> > +		err = -EINVAL;
> > +	}
> > +
> > +free_all:
> > +	kfree(input_buf);
> > +free_output:
> > +	kfree(output_buf);
> > +free_req:
> > +	akcipher_request_free(req);
> > +	return err;
> > +}
> > +
> > +static int test_dh(struct crypto_akcipher *tfm,
> > +		   struct akcipher_testvec_dh *vecs, unsigned int tcount)
> > +{
> > +	int ret, i;
> > +
> > +	for (i = 0; i < tcount; i++) {
> > +		ret = do_test_dh(tfm, vecs++);
> > +		if (ret) {
> > +			pr_err("alg: dh: test failed on vector %d, err=%d\n",
> > +			       i + 1, ret);
> > +			return ret;
> > +		}
> > +	}
> > +	return 0;
> > +}
> > +
> >  static int do_test_rsa(struct crypto_akcipher *tfm,
> > -		       struct akcipher_testvec *vecs)
> > +		       struct akcipher_testvec_rsa *vecs)
> >  {
> >  	struct akcipher_request *req;
> >  	void *outbuf_enc = NULL;
> > @@ -1870,7 +1975,8 @@ free_req:
> >  	return err;
> >  }
> > 
> > -static int test_rsa(struct crypto_akcipher *tfm, struct akcipher_testvec
> > *vecs, +static int test_rsa(struct crypto_akcipher *tfm,
> > +		    struct akcipher_testvec_rsa *vecs,
> >  		    unsigned int tcount)
> >  {
> >  	int ret, i;
> > @@ -1890,7 +1996,9 @@ static int test_akcipher(struct crypto_akcipher *tfm,
> > const char *alg, struct akcipher_testvec *vecs, unsigned int tcount)
> >  {
> >  	if (strncmp(alg, "rsa", 3) == 0)
> > -		return test_rsa(tfm, vecs, tcount);
> > +		return test_rsa(tfm, vecs->a.rsa, tcount);
> > +	else if (strncmp(alg, "dh", 3) == 0)
> > +		return test_dh(tfm, vecs->a.dh, tcount);
> > 
> >  	return 0;
> >  }
> > @@ -1907,8 +2015,9 @@ static int alg_test_akcipher(const struct
> > alg_test_desc *desc, driver, PTR_ERR(tfm));
> >  		return PTR_ERR(tfm);
> >  	}
> > -	if (desc->suite.akcipher.vecs)
> > -		err = test_akcipher(tfm, desc->alg, desc->suite.akcipher.vecs,
> > +	if (desc->suite.akcipher.vecs.a.rsa)
> > +		err = test_akcipher(tfm, desc->alg,
> > +				    &desc->suite.akcipher.vecs,
> >  				    desc->suite.akcipher.count);
> > 
> >  	crypto_free_akcipher(tfm);
> > @@ -2676,6 +2785,19 @@ static const struct alg_test_desc alg_test_descs[] =
> > { }
> >  		}
> >  	}, {
> > +		.alg = "dh",
> > +		.test = alg_test_akcipher,
> 
> fis_allowed=1 please

OK.

> 
> > +		.suite = {
> > +			.akcipher = {
> > +				.vecs = {
> > +					.a = {
> > +						.dh = dh_tv_template
> > +					},
> > +				},
> > +				.count = DH_TEST_VECTORS
> > +			}
> > +		}
> > +	}, {
> >  		.alg = "digest_null",
> >  		.test = alg_test_null,
> >  	}, {
> > @@ -3560,7 +3682,11 @@ static const struct alg_test_desc alg_test_descs[] =
> > { .fips_allowed = 1,
> >  		.suite = {
> >  			.akcipher = {
> > -				.vecs = rsa_tv_template,
> > +				.vecs = {
> > +					.a = {
> > +						.rsa = rsa_tv_template
> > +					},
> > +				},
> >  				.count = RSA_TEST_VECTORS
> >  			}
> >  		}
> > diff --git a/crypto/testmgr.h b/crypto/testmgr.h
> > index 487ec88..ba08ed6 100644
> > --- a/crypto/testmgr.h
> > +++ b/crypto/testmgr.h
> > @@ -123,7 +123,7 @@ struct drbg_testvec {
> >  	size_t expectedlen;
> >  };
> > 
> > -struct akcipher_testvec {
> > +struct akcipher_testvec_rsa {
> >  	unsigned char *key;
> >  	unsigned char *m;
> >  	unsigned char *c;
> > @@ -133,6 +133,23 @@ struct akcipher_testvec {
> >  	bool public_key_vec;
> >  };
> > 
> > +struct akcipher_testvec_dh {
> > +	unsigned char *pkcs3;
> > +	unsigned pkcs3_size;
> > +	unsigned char *priv_key_A;
> > +	unsigned char *pub_key_B;
> > +	unsigned char *expected_pub_key_A;
> > +	unsigned char *expected_shared_secret;
> > +	unsigned key_len;
> > +};
> > +
> > +struct akcipher_testvec {
> > +	union {
> > +		struct akcipher_testvec_rsa *rsa;
> > +		struct akcipher_testvec_dh *dh;
> > +	} a;
> > +};
> > +
> >  static char zeroed_string[48];
> > 
> >  /*
> > @@ -143,7 +160,7 @@ static char zeroed_string[48];
> >  #else
> >  #define RSA_TEST_VECTORS	4
> >  #endif
> > -static struct akcipher_testvec rsa_tv_template[] = {
> > +static struct akcipher_testvec_rsa rsa_tv_template[] = {
> >  	{
> >  #ifndef CONFIG_CRYPTO_FIPS
> >  	.key =
> > @@ -330,6 +347,193 @@ static struct akcipher_testvec rsa_tv_template[] = {
> >  	}
> >  };
> > 
> > +#define DH_TEST_VECTORS 2
> > +
> > +struct akcipher_testvec_dh dh_tv_template[] = {
> > +	{
> > +	/* p, g */
> > +	.pkcs3 =
> > +	"\x30\x82\x01\x08\x02\x82\x01\x01\x00\x9f\xab\x7c\xc2\x50\xa7\xdc"
> > +	"\x3c\x17\x2a\x5b\x9f\x76\x17\x8e\x92\xa6\xb0\x13\x1e\x6e\x7b\x9a"
> > +	"\x6b\x8d\x06\xcf\x9f\x90\xb8\x21\x6a\x30\x04\xe8\xda\xc0\x13\x27"
> > +	"\xc8\x40\xbf\x6c\x84\x1e\xe2\x9e\xf9\xd2\x48\x11\xc7\x06\xd3\x06"
> > +	"\xb8\xaa\xbe\x69\x3f\xf2\x60\x06\xa0\xd1\x55\x03\x63\xa1\xfd\x33"
> > +	"\x2c\x04\xe4\xf0\xe6\x02\x8a\x97\x1e\x22\x4f\x2b\x73\x15\x23\xa5"
> > +	"\x26\x97\xd6\x91\x11\xd8\x80\x35\xe7\x7f\x19\x29\x6c\x59\x64\x24"
> > +	"\x68\xc0\x40\x66\x5d\xa8\xcb\xda\x84\xce\xbc\xf7\x1b\x68\x81\xac"
> > +	"\xec\xe9\x84\xc1\x46\xef\xac\xe2\xb2\x85\xf2\x92\x06\x82\xbe\xe7"
> > +	"\x12\x53\x21\xfc\xc5\x82\xe5\xe3\x7f\x26\xe5\x53\x02\x58\xb1\xa9"
> > +	"\x26\x32\x5f\xb9\xa6\x23\x1d\xd8\x26\xda\x7a\x67\xab\x8a\x84\x97"
> > +	"\x2e\x78\xc1\x6d\xec\x67\x50\x27\x2d\x52\xf7\x67\xec\x5b\x2c\x9f"
> > +	"\x17\xb7\x81\xec\x47\x60\x65\xf5\x86\x20\x4f\x82\x84\xd9\xee\x62"
> > +	"\x6f\x49\x7d\x80\x9e\xaa\x8a\x7a\x82\x45\x65\x36\x0b\xf1\xfe\x01"
> > +	"\x06\x52\x3c\xa1\xdf\xc8\x84\x89\xb0\xee\xb6\xfa\x95\x12\x42\xb9"
> > +	"\x87\x53\x77\x1c\xe0\x56\x25\xf6\x96\x31\xec\x62\x82\x77\xb7\x52"
> > +	"\xac\x25\x71\x49\x97\x13\x83\x23\x63\x02\x01\x02",
> > +	.pkcs3_size = 268,
> > +	.priv_key_A =
> > +	"\x48\xed\x07\x3d\x49\x20\xf8\xa5\xcf\x90\xcd\xf9\x97\x63\xd2\x51"
> > +	"\x3d\xac\xbd\x2d\x49\x4a\xb8\x87\x06\x62\xd2\x0c\x13\x55\x73\x77"
> > +	"\x97\x15\xd3\x23\x8a\x3b\x3e\xb9\x14\xa6\xfb\x20\x7b\xd1\xea\x68"
> > +	"\x85\x9a\xc6\x8f\x66\x9a\x78\xf0\x26\xce\x8c\xe0\x66\x4e\x51\xc9"
> > +	"\xf5\xf9\x89\xc6\x0a\xc5\x4b\x99\xdc\xb0\x36\x3e\xf2\xc7\x7f\x52"
> > +	"\x60\x99\x12\xbd\x8f\x85\x7b\x0a\x99\xa9\x85\x21\xc6\x50\x66\xf6"
> > +	"\xde\x62\xc4\x08\x3f\x8c\x97\x91\xb0\x19\x72\x2a\x56\xc6\x85\x12"
> > +	"\x8e\x89\x65\xa7\x13\x34\x51\x53\x2e\xe0\x07\x6c\x01\xaa\xb1\x23"
> > +	"\x42\x54\xa5\x49\xfd\x01\x2a\xd8\xa7\xc3\xd6\x6a\x6f\x3c\x76\xc4"
> > +	"\x4b\x37\x55\x30\xb7\xbe\xb7\x87\x4e\x43\x68\x37\xd8\xa0\x6f\x53"
> > +	"\x59\xb6\x25\xd4\x44\xc9\x43\xcd\xb1\x20\x8c\xf9\x3a\xd5\xbc\x97"
> > +	"\x70\x8e\xad\x1a\x8b\x69\xbd\xae\xf9\xd0\x48\x70\x40\x4d\x3f\xdc"
> > +	"\xea\x10\xef\x61\x49\x1b\x87\x10\xff\x96\x36\x73\x4f\x75\xf5\x75"
> > +	"\x23\xbb\x5e\x48\xe8\x96\x57\xcf\x33\x76\x78\x2e\x86\x90\x5c\x2c"
> > +	"\x17\xe6\x70\x8a\x6c\x0c\x0d\xa8\x3e\x79\xa6\x9e\xe1\xbf\x18\x40"
> > +	"\xeb\x2c\x1a\xb9\x14\xf5\x02\xeb\x37\x66\x06\x1c\xe8\xb5\x75\x0d",
> > +	.pub_key_B =
> > +	"\x18\xd9\x78\xdd\x6a\xc9\x19\x4e\xe6\xa0\x83\xcc\x12\x00\x3b\x6c"
> > +	"\x4c\x8c\x11\x38\x94\x90\xd7\xc4\x1f\xa6\x64\x04\x35\x4a\xda\x48"
> > +	"\x5a\xeb\x38\xe7\xae\x44\x16\x4a\x94\xfe\x7c\xa9\x00\xff\x67\x20"
> > +	"\x4c\xef\x34\x45\xfe\x2d\xf5\xa9\xfb\xa8\xc0\x45\x09\xcd\xcd\xc0"
> > +	"\x4c\x20\xc0\x1e\x42\x41\x4b\x37\x6c\x90\xba\xef\xd6\x65\xab\xb1"
> > +	"\xec\x51\x30\xfa\x08\xfc\x22\xc6\x42\xce\x6a\x90\xb7\x27\xe4\x52"
> > +	"\x76\x28\x78\x17\x56\x71\x73\xeb\xaf\x6e\xbb\x61\x7a\x6b\x4b\xdb"
> > +	"\x8e\x2f\xaa\xfa\x9e\x40\xee\x84\xf6\x63\x9b\xb7\xe2\x22\x72\x6b"
> > +	"\x94\x58\x3f\x08\xa5\xbe\xd6\x87\x63\xe7\xbb\x5a\xfb\x52\x92\xd2"
> > +	"\xe6\x5e\x7e\x55\x78\x4b\xc0\x0e\x1a\xe5\xe6\x0f\x0e\x41\xd5\x05"
> > +	"\xb7\x71\x42\x78\x35\x74\xad\x33\x9f\x24\xc0\x3b\x09\xd5\xcf\x4d"
> > +	"\x6e\x20\x3a\xee\x04\x9f\x05\x2d\x8d\x77\x06\x2d\x9b\x67\xba\x39"
> > +	"\x2f\x6c\x1d\x7b\x75\x57\xed\x2f\xe2\xf1\xbc\x0b\x3a\x77\xf2\xba"
> > +	"\xb2\xb1\x98\x52\x34\x40\x53\x7b\x0e\xb6\x13\x6a\x5b\x91\xe4\x59"
> > +	"\x67\x2c\x45\x3a\x07\x1a\xa2\x3b\xdb\xa1\xa6\x08\xf0\x80\xe8\x61"
> > +	"\xca\xac\x95\xb3\x3e\xd6\x97\x98\x08\x7e\x50\x48\xc0\x25\x45\xd0",
> > +	.expected_pub_key_A =
> > +	"\x91\x9e\x52\xa3\xb8\x20\x25\x12\x17\xcc\x37\x82\x81\x22\x14\x7a"
> > +	"\x81\x88\xce\x9f\xf2\x46\xb1\x17\xaf\x41\x23\xc9\xb8\x93\x40\xfd"
> > +	"\xa9\x96\x05\x5a\x1a\xcc\xa6\x51\xe2\x9e\xca\x63\x2a\x67\x72\x4a"
> > +	"\xe1\x2b\xa7\xbe\xf9\xeb\x69\xc8\x2d\x29\xb6\x6b\x5f\xc0\xf2\x90"
> > +	"\xa9\x36\x49\xdb\xcc\x6b\x5e\xed\x76\x47\x9f\xc9\x2e\x91\x68\x75"
> > +	"\xa3\x39\x6c\x50\xa6\xaf\x81\xac\x23\x58\xa9\xc9\x71\xf3\x87\x97"
> > +	"\xef\x0c\x80\x19\xac\xb7\xf0\xa0\x83\x44\x4b\x1c\x08\xf1\x4f\x23"
> > +	"\xfb\xf1\x61\x39\x00\x59\xef\x83\xa5\xaf\x2f\x3f\xc0\x19\x2a\x5b"
> > +	"\x22\x53\xdb\x8b\x24\xbc\xe4\xaa\x9a\x19\x6b\xfd\x20\xbf\x1a\xe2"
> > +	"\xb5\xaf\x82\x3e\xb8\xea\xe7\x28\xcd\xad\xfe\x00\xee\x70\x52\x46"
> > +	"\x3d\x2c\x55\x81\x44\xed\x15\x21\xc8\x48\x75\x4d\x6f\xf0\xba\xe9"
> > +	"\xab\x4c\x65\xf3\x54\x2e\x74\xd9\xe7\xe2\xb7\xad\xec\x6d\xb2\x6e"
> > +	"\xc1\xe3\x2d\x0e\xb1\x18\x36\xd7\xb9\x42\x6b\x2f\xc9\x51\x2e\xff"
> > +	"\x5d\xd0\xca\x8c\x0d\x0d\x95\xd3\x16\xf3\xdb\xc1\x2b\xed\x00\x32"
> > +	"\xd7\x77\xb8\x0e\x86\x7a\x57\x48\x74\x23\x30\xae\xe0\x3c\x38\xa6"
> > +	"\xed\xf9\x0c\x16\xf2\xf2\xa0\xe0\x51\x80\x67\x92\xe4\xc7\x9a\x5e",
> > +	.expected_shared_secret =
> > +	"\x1d\x7d\x2e\x47\x06\xbe\x46\xd3\x69\xf6\xe7\x0e\x88\xdc\xe8\xe1"
> > +	"\xe6\x6a\xfc\x3c\xbc\xc1\x85\xe9\x24\xf0\x7b\x75\x0f\xa4\x04\xd6"
> > +	"\x9b\xef\x7b\x30\x55\xde\xbf\xd4\xb2\xcb\xce\x74\x53\xae\x72\x34"
> > +	"\x19\x36\x9e\xe9\x45\xb8\xda\x59\x22\x41\x9e\xa3\x8f\x02\xaa\x60"
> > +	"\xb1\x8b\xf9\x84\xd4\x8a\xeb\xea\xd1\xd9\x1a\x53\xe9\x5f\x01\xd1"
> > +	"\x40\xb4\x73\x63\xc5\x1a\x79\xf1\x08\xb6\xc0\x0c\x85\x9e\x3e\x70"
> > +	"\xea\x79\xd9\xc2\x5b\x17\xa7\x1e\xeb\x58\x3e\x1b\xca\x7a\x4d\xab"
> > +	"\x61\x5b\xdf\xa2\x6f\x1e\xd4\x36\xeb\xe3\xe9\x04\x10\x8e\x0b\xc9"
> > +	"\x18\x8c\x0d\x6e\x4f\x2e\xc5\xfc\x5b\x6a\xb5\x9f\xdf\x71\x50\x04"
> > +	"\x54\x62\x49\x57\xf3\xc6\x9e\x39\xc6\x56\xf1\x2d\x31\x59\x58\xdb"
> > +	"\x67\x94\x25\xbd\x47\xe2\xdd\x95\x0c\x39\xb1\xfa\x22\xc6\x94\xc4"
> > +	"\x75\xab\xff\xe2\xce\x52\xa2\xeb\x78\x26\x10\x0f\x2d\x8c\xf2\xad"
> > +	"\xd2\xc7\xaf\x85\xd9\x5c\x71\xfe\x9e\xe9\xeb\xbf\x20\x36\x1e\x9a"
> > +	"\x74\x43\xe6\x06\x00\x8a\x4d\x64\x41\x2a\x15\x6d\x60\x44\x3f\x2c"
> > +	"\xcd\x05\x16\x54\x6a\x48\x7c\x71\x0a\xe9\x33\x95\x16\xc7\xf4\x23"
> > +	"\xc2\x8d\xed\x8a\x24\x5d\x99\xc7\x8c\x8b\x07\x47\x8c\xe9\x0c\x10",
> > +	.key_len = 256
> > +	},
> > +	{
> > +	/* p, g */
> > +	.pkcs3 =
> > +	"\x30\x82\x01\x08\x02\x82\x01\x01\x00\x9f\xab\x7c\xc2\x50\xa7\xdc"
> > +	"\x3c\x17\x2a\x5b\x9f\x76\x17\x8e\x92\xa6\xb0\x13\x1e\x6e\x7b\x9a"
> > +	"\x6b\x8d\x06\xcf\x9f\x90\xb8\x21\x6a\x30\x04\xe8\xda\xc0\x13\x27"
> > +	"\xc8\x40\xbf\x6c\x84\x1e\xe2\x9e\xf9\xd2\x48\x11\xc7\x06\xd3\x06"
> > +	"\xb8\xaa\xbe\x69\x3f\xf2\x60\x06\xa0\xd1\x55\x03\x63\xa1\xfd\x33"
> > +	"\x2c\x04\xe4\xf0\xe6\x02\x8a\x97\x1e\x22\x4f\x2b\x73\x15\x23\xa5"
> > +	"\x26\x97\xd6\x91\x11\xd8\x80\x35\xe7\x7f\x19\x29\x6c\x59\x64\x24"
> > +	"\x68\xc0\x40\x66\x5d\xa8\xcb\xda\x84\xce\xbc\xf7\x1b\x68\x81\xac"
> > +	"\xec\xe9\x84\xc1\x46\xef\xac\xe2\xb2\x85\xf2\x92\x06\x82\xbe\xe7"
> > +	"\x12\x53\x21\xfc\xc5\x82\xe5\xe3\x7f\x26\xe5\x53\x02\x58\xb1\xa9"
> > +	"\x26\x32\x5f\xb9\xa6\x23\x1d\xd8\x26\xda\x7a\x67\xab\x8a\x84\x97"
> > +	"\x2e\x78\xc1\x6d\xec\x67\x50\x27\x2d\x52\xf7\x67\xec\x5b\x2c\x9f"
> > +	"\x17\xb7\x81\xec\x47\x60\x65\xf5\x86\x20\x4f\x82\x84\xd9\xee\x62"
> > +	"\x6f\x49\x7d\x80\x9e\xaa\x8a\x7a\x82\x45\x65\x36\x0b\xf1\xfe\x01"
> > +	"\x06\x52\x3c\xa1\xdf\xc8\x84\x89\xb0\xee\xb6\xfa\x95\x12\x42\xb9"
> > +	"\x87\x53\x77\x1c\xe0\x56\x25\xf6\x96\x31\xec\x62\x82\x77\xb7\x52"
> > +	"\xac\x25\x71\x49\x97\x13\x83\x23\x63\x02\x01\x02",
> > +	.pkcs3_size = 268,
> > +	.priv_key_A =
> > +	"\x7d\xfb\xa2\x51\x24\xa4\xfa\x65\x35\x1c\x3b\xef\x3f\x6b\x10\x27"
> > +	"\xde\x30\xcb\x2c\xa7\x5b\xfe\x1a\xec\x5f\x2b\x1c\x7b\xd8\xa7\xfd"
> > +	"\x37\x15\xec\x62\xbd\x64\x71\x57\x31\x48\xcc\x8c\xd9\x6f\xe9\x24"
> > +	"\x9d\x63\xff\x1f\xb6\x7d\xf7\x30\x23\x13\xdc\x0f\x27\xd9\x6e\x11"
> > +	"\x8b\x54\x80\xe4\x35\x52\x98\x5c\xac\x87\x56\xdf\x5e\xe2\xbe\x08"
> > +	"\x63\xfd\xb2\xe4\x06\x2b\x04\x68\xf6\x3a\x45\x3b\xb0\xf1\x81\x32"
> > +	"\x36\xa3\xde\xe4\xe7\xec\x8b\x87\x32\x09\x45\x87\x1c\x1c\x0e\x84"
> > +	"\xf7\x30\x09\x7d\x7f\x98\xf5\xbe\x92\x50\xbd\xa8\xc2\x35\x11\xe3"
> > +	"\x0a\xf2\x90\x1a\x18\xcb\x5a\xe5\x4e\x4a\x93\x3d\x6d\x26\xa6\x36"
> > +	"\x79\x45\x75\x12\xb4\x27\x95\xcd\x9e\x6b\x37\x57\x4d\x69\x21\xa9"
> > +	"\xff\x5d\xe2\xf2\xf8\x4f\xeb\x50\x79\xa4\xa7\x87\x59\x78\x23\xfa"
> > +	"\x67\xb5\xdc\x6e\xa6\x59\x81\xba\x65\x8e\x65\xfc\x7f\x51\xc8\xad"
> > +	"\x1d\x28\x50\x60\x92\x2a\xcc\x9c\x47\xc7\x13\xd2\xf4\xb8\xa2\xab"
> > +	"\x2c\x50\x4c\xf1\xcd\xef\xb7\x94\x1c\xe7\xd3\x2a\x55\x37\xff\xfa"
> > +	"\x6d\xe8\x43\x01\xb0\x9b\x24\x5d\xd4\x57\x7d\xb5\x30\xaa\x60\x97"
> > +	"\x33\xfe\xe7\x31\x39\x96\xe6\xb3\xf4\x11\xde\x3c\x57\x4b\xcb\xad",
> > +	.pub_key_B =
> > +	"\x91\x9e\x52\xa3\xb8\x20\x25\x12\x17\xcc\x37\x82\x81\x22\x14\x7a"
> > +	"\x81\x88\xce\x9f\xf2\x46\xb1\x17\xaf\x41\x23\xc9\xb8\x93\x40\xfd"
> > +	"\xa9\x96\x05\x5a\x1a\xcc\xa6\x51\xe2\x9e\xca\x63\x2a\x67\x72\x4a"
> > +	"\xe1\x2b\xa7\xbe\xf9\xeb\x69\xc8\x2d\x29\xb6\x6b\x5f\xc0\xf2\x90"
> > +	"\xa9\x36\x49\xdb\xcc\x6b\x5e\xed\x76\x47\x9f\xc9\x2e\x91\x68\x75"
> > +	"\xa3\x39\x6c\x50\xa6\xaf\x81\xac\x23\x58\xa9\xc9\x71\xf3\x87\x97"
> > +	"\xef\x0c\x80\x19\xac\xb7\xf0\xa0\x83\x44\x4b\x1c\x08\xf1\x4f\x23"
> > +	"\xfb\xf1\x61\x39\x00\x59\xef\x83\xa5\xaf\x2f\x3f\xc0\x19\x2a\x5b"
> > +	"\x22\x53\xdb\x8b\x24\xbc\xe4\xaa\x9a\x19\x6b\xfd\x20\xbf\x1a\xe2"
> > +	"\xb5\xaf\x82\x3e\xb8\xea\xe7\x28\xcd\xad\xfe\x00\xee\x70\x52\x46"
> > +	"\x3d\x2c\x55\x81\x44\xed\x15\x21\xc8\x48\x75\x4d\x6f\xf0\xba\xe9"
> > +	"\xab\x4c\x65\xf3\x54\x2e\x74\xd9\xe7\xe2\xb7\xad\xec\x6d\xb2\x6e"
> > +	"\xc1\xe3\x2d\x0e\xb1\x18\x36\xd7\xb9\x42\x6b\x2f\xc9\x51\x2e\xff"
> > +	"\x5d\xd0\xca\x8c\x0d\x0d\x95\xd3\x16\xf3\xdb\xc1\x2b\xed\x00\x32"
> > +	"\xd7\x77\xb8\x0e\x86\x7a\x57\x48\x74\x23\x30\xae\xe0\x3c\x38\xa6"
> > +	"\xed\xf9\x0c\x16\xf2\xf2\xa0\xe0\x51\x80\x67\x92\xe4\xc7\x9a\x5e",
> > +	.expected_pub_key_A =
> > +	"\x18\xd9\x78\xdd\x6a\xc9\x19\x4e\xe6\xa0\x83\xcc\x12\x00\x3b\x6c"
> > +	"\x4c\x8c\x11\x38\x94\x90\xd7\xc4\x1f\xa6\x64\x04\x35\x4a\xda\x48"
> > +	"\x5a\xeb\x38\xe7\xae\x44\x16\x4a\x94\xfe\x7c\xa9\x00\xff\x67\x20"
> > +	"\x4c\xef\x34\x45\xfe\x2d\xf5\xa9\xfb\xa8\xc0\x45\x09\xcd\xcd\xc0"
> > +	"\x4c\x20\xc0\x1e\x42\x41\x4b\x37\x6c\x90\xba\xef\xd6\x65\xab\xb1"
> > +	"\xec\x51\x30\xfa\x08\xfc\x22\xc6\x42\xce\x6a\x90\xb7\x27\xe4\x52"
> > +	"\x76\x28\x78\x17\x56\x71\x73\xeb\xaf\x6e\xbb\x61\x7a\x6b\x4b\xdb"
> > +	"\x8e\x2f\xaa\xfa\x9e\x40\xee\x84\xf6\x63\x9b\xb7\xe2\x22\x72\x6b"
> > +	"\x94\x58\x3f\x08\xa5\xbe\xd6\x87\x63\xe7\xbb\x5a\xfb\x52\x92\xd2"
> > +	"\xe6\x5e\x7e\x55\x78\x4b\xc0\x0e\x1a\xe5\xe6\x0f\x0e\x41\xd5\x05"
> > +	"\xb7\x71\x42\x78\x35\x74\xad\x33\x9f\x24\xc0\x3b\x09\xd5\xcf\x4d"
> > +	"\x6e\x20\x3a\xee\x04\x9f\x05\x2d\x8d\x77\x06\x2d\x9b\x67\xba\x39"
> > +	"\x2f\x6c\x1d\x7b\x75\x57\xed\x2f\xe2\xf1\xbc\x0b\x3a\x77\xf2\xba"
> > +	"\xb2\xb1\x98\x52\x34\x40\x53\x7b\x0e\xb6\x13\x6a\x5b\x91\xe4\x59"
> > +	"\x67\x2c\x45\x3a\x07\x1a\xa2\x3b\xdb\xa1\xa6\x08\xf0\x80\xe8\x61"
> > +	"\xca\xac\x95\xb3\x3e\xd6\x97\x98\x08\x7e\x50\x48\xc0\x25\x45\xd0",
> > +	.expected_shared_secret =
> > +	"\x1d\x7d\x2e\x47\x06\xbe\x46\xd3\x69\xf6\xe7\x0e\x88\xdc\xe8\xe1"
> > +	"\xe6\x6a\xfc\x3c\xbc\xc1\x85\xe9\x24\xf0\x7b\x75\x0f\xa4\x04\xd6"
> > +	"\x9b\xef\x7b\x30\x55\xde\xbf\xd4\xb2\xcb\xce\x74\x53\xae\x72\x34"
> > +	"\x19\x36\x9e\xe9\x45\xb8\xda\x59\x22\x41\x9e\xa3\x8f\x02\xaa\x60"
> > +	"\xb1\x8b\xf9\x84\xd4\x8a\xeb\xea\xd1\xd9\x1a\x53\xe9\x5f\x01\xd1"
> > +	"\x40\xb4\x73\x63\xc5\x1a\x79\xf1\x08\xb6\xc0\x0c\x85\x9e\x3e\x70"
> > +	"\xea\x79\xd9\xc2\x5b\x17\xa7\x1e\xeb\x58\x3e\x1b\xca\x7a\x4d\xab"
> > +	"\x61\x5b\xdf\xa2\x6f\x1e\xd4\x36\xeb\xe3\xe9\x04\x10\x8e\x0b\xc9"
> > +	"\x18\x8c\x0d\x6e\x4f\x2e\xc5\xfc\x5b\x6a\xb5\x9f\xdf\x71\x50\x04"
> > +	"\x54\x62\x49\x57\xf3\xc6\x9e\x39\xc6\x56\xf1\x2d\x31\x59\x58\xdb"
> > +	"\x67\x94\x25\xbd\x47\xe2\xdd\x95\x0c\x39\xb1\xfa\x22\xc6\x94\xc4"
> > +	"\x75\xab\xff\xe2\xce\x52\xa2\xeb\x78\x26\x10\x0f\x2d\x8c\xf2\xad"
> > +	"\xd2\xc7\xaf\x85\xd9\x5c\x71\xfe\x9e\xe9\xeb\xbf\x20\x36\x1e\x9a"
> > +	"\x74\x43\xe6\x06\x00\x8a\x4d\x64\x41\x2a\x15\x6d\x60\x44\x3f\x2c"
> > +	"\xcd\x05\x16\x54\x6a\x48\x7c\x71\x0a\xe9\x33\x95\x16\xc7\xf4\x23"
> > +	"\xc2\x8d\xed\x8a\x24\x5d\x99\xc7\x8c\x8b\x07\x47\x8c\xe9\x0c\x10",
> > +	.key_len = 256
> > +	}
> > +};
> > +
> >  /*
> >   * MD4 test vectors from RFC1320
> >   */
>

I'll send a V2 if Herbert is OK with this approach.

Herbert, what do you think?

Thanks,
Salvatore

> 
> Ciao
> Stephan
> --
> To unsubscribe from this list: send the line "unsubscribe linux-crypto" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH] crypto: implement DH primitives under akcipher API
  2016-03-01 11:08   ` Salvatore Benedetto
@ 2016-03-01 11:17     ` Stephan Mueller
  2016-03-02  9:53       ` Salvatore Benedetto
  0 siblings, 1 reply; 18+ messages in thread
From: Stephan Mueller @ 2016-03-01 11:17 UTC (permalink / raw)
  To: Salvatore Benedetto; +Cc: tadeusz.struk, linux-crypto, herbert

Am Dienstag, 1. März 2016, 11:08:34 schrieb Salvatore Benedetto:

Hi Salvatore,

> > > +static int dh_check_params_length(unsigned int p_len)
> > > +{
> > > +	switch (p_len) {
> > > +	case 768:
> > > +	case 1024:
> > > +	case 1536:
> > > +	case 2048:
> > > +	case 3072:
> > > +	case 4096:
> > > +		return 0;
> > > +	}
> > > +	return -EINVAL;
> > > +}
> > 
> > What is the reason for restricting the size to 4096?
> 
> Honestly no reason.
> Could not find restrictions in the spec about the params length.

I am just wondering because other DH impls allow longer sizes.

And besides, I would like to disallow all < 2048 right from the start.
> 
> > > +
> > > +static int dh_no_op(struct akcipher_request *req)
> > > +{
> > > +	return -ENOPROTOOPT;
> > > +}
> > > +
> > > +static int dh_set_priv_key(struct crypto_akcipher *tfm, const void
> > > *key,
> > > +			   unsigned int keylen)
> > > +{
> > > +	struct dh_params *params = akcipher_tfm_ctx(tfm);
> > 
> > dh_get_params?
> 
> You mean adding a helper function? OK.

Not adding, but using your helper function -- why do you have it there in the 
first place? :-)

Ciao
Stephan

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH] crypto: implement DH primitives under akcipher API
  2016-02-15  9:01 [PATCH] crypto: implement DH primitives under akcipher API Salvatore Benedetto
  2016-02-15 13:57 ` Stephan Mueller
  2016-02-16 20:19 ` Herbert Xu
@ 2016-03-01 20:25 ` Marcel Holtmann
  2016-03-02  9:38   ` Salvatore Benedetto
  2 siblings, 1 reply; 18+ messages in thread
From: Marcel Holtmann @ 2016-03-01 20:25 UTC (permalink / raw)
  To: Salvatore Benedetto; +Cc: Herbert Xu, linux-crypto

Hi Salvatore,

> Implement Diffie-Hellman primitives required by the scheme under the
> akcipher API. Here is how it works.
> 1) Call set_pub_key() by passing DH parameters (p,g) in PKCS3 format
> 2) Call set_priv_key() to set your own private key (xa) in raw format

this combination seems odd since it is normally the remote public key and the local private key. Generally the public key and private key are both remote ones.

For using PKCS3 format is this standardized somewhere? I don't think it is a good idea to invent new ones here.

In addition, how would this work for ECDH?

> 3) Call decrypt() without passing any data as input to get back the
>   public part which will be computed as g^xa mod p
> 4) Call encrypt() by passing the counter part public key (yb) in raw format
>   as input to get back the shared secret calculated as zz = yb^xa mod p
> 
> A test is included in the patch. Test vector has been generated with
> openssl
> 
> Signed-off-by: Salvatore Benedetto <salvatore.benedetto@intel.com>
> ---
> crypto/Kconfig    |   8 ++
> crypto/Makefile   |   7 ++
> crypto/dh.c       | 264 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
> crypto/pkcs3.asn1 |   5 ++
> crypto/tcrypt.c   |   4 +
> crypto/testmgr.c  | 140 +++++++++++++++++++++++++++--
> crypto/testmgr.h  | 208 +++++++++++++++++++++++++++++++++++++++++-
> 7 files changed, 627 insertions(+), 9 deletions(-)
> create mode 100644 crypto/dh.c
> create mode 100644 crypto/pkcs3.asn1
> 
> diff --git a/crypto/Kconfig b/crypto/Kconfig
> index f6bfdda..fd5b78d 100644
> --- a/crypto/Kconfig
> +++ b/crypto/Kconfig
> @@ -101,6 +101,14 @@ config CRYPTO_RSA
> 	help
> 	  Generic implementation of the RSA public key algorithm.
> 
> +config CRYPTO_DH
> +	tristate "Diffie-Hellman algorithm"
> +	select CRYPTO_AKCIPHER
> +	select MPILIB
> +	select ASN1

I really wonder that depending on ASN1 is a good idea here. As mentioned above ECDH would make sense to actually have supported from the beginning. The Bluetooth subsystem could be then converted to utilize in kernel ECC key generation and ECDH shared secret computation. It would be good to show this is truly generic DH.

Regards

Marcel

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH] crypto: implement DH primitives under akcipher API
  2016-03-01 20:25 ` Marcel Holtmann
@ 2016-03-02  9:38   ` Salvatore Benedetto
  2016-03-02 13:46     ` Marcel Holtmann
  0 siblings, 1 reply; 18+ messages in thread
From: Salvatore Benedetto @ 2016-03-02  9:38 UTC (permalink / raw)
  To: Marcel Holtmann; +Cc: herbert, linux-crypto

On Tue, Mar 01, 2016 at 12:25:33PM -0800, Marcel Holtmann wrote:

Hi Marcel,

> Hi Salvatore,
> 
> > Implement Diffie-Hellman primitives required by the scheme under the
> > akcipher API. Here is how it works.
> > 1) Call set_pub_key() by passing DH parameters (p,g) in PKCS3 format
> > 2) Call set_priv_key() to set your own private key (xa) in raw format
> 
> this combination seems odd since it is normally the remote public key and the local private key. Generally the public key and private key are both remote ones.

I'm not sure I understand what you mean here. Usually the public key is
remote and the private key is local. How can the private key be remote?

> 
> For using PKCS3 format is this standardized somewhere? I don't think it is a good idea to invent new ones here.

PKCS3 is the format used by openssl for genating DH params, that's why I
used it.

> 
> In addition, how would this work for ECDH?

Don't know. There is not even ECC support right now.

> 
> > 3) Call decrypt() without passing any data as input to get back the
> >   public part which will be computed as g^xa mod p
> > 4) Call encrypt() by passing the counter part public key (yb) in raw format
> >   as input to get back the shared secret calculated as zz = yb^xa mod p
> > 
> > A test is included in the patch. Test vector has been generated with
> > openssl
> > 
> > Signed-off-by: Salvatore Benedetto <salvatore.benedetto@intel.com>
> > ---
> > crypto/Kconfig    |   8 ++
> > crypto/Makefile   |   7 ++
> > crypto/dh.c       | 264 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > crypto/pkcs3.asn1 |   5 ++
> > crypto/tcrypt.c   |   4 +
> > crypto/testmgr.c  | 140 +++++++++++++++++++++++++++--
> > crypto/testmgr.h  | 208 +++++++++++++++++++++++++++++++++++++++++-
> > 7 files changed, 627 insertions(+), 9 deletions(-)
> > create mode 100644 crypto/dh.c
> > create mode 100644 crypto/pkcs3.asn1
> > 
> > diff --git a/crypto/Kconfig b/crypto/Kconfig
> > index f6bfdda..fd5b78d 100644
> > --- a/crypto/Kconfig
> > +++ b/crypto/Kconfig
> > @@ -101,6 +101,14 @@ config CRYPTO_RSA
> > 	help
> > 	  Generic implementation of the RSA public key algorithm.
> > 
> > +config CRYPTO_DH
> > +	tristate "Diffie-Hellman algorithm"
> > +	select CRYPTO_AKCIPHER
> > +	select MPILIB
> > +	select ASN1
> 
> I really wonder that depending on ASN1 is a good idea here. As mentioned above ECDH would make sense to actually have supported from the beginning. The Bluetooth subsystem could be then converted to utilize in kernel ECC key generation and ECDH shared secret computation. It would be good to show this is truly generic DH.
> 

This is an RFC. I understand it is not the best approach, but
the idea behind was to try to reuse the akcipher for DH.

Thanks for your comments.

Regards,
Salvatore

> Regards
> 
> Marcel
> 

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH] crypto: implement DH primitives under akcipher API
  2016-03-01 11:17     ` Stephan Mueller
@ 2016-03-02  9:53       ` Salvatore Benedetto
  2016-03-02 13:03         ` Sandy Harris
  0 siblings, 1 reply; 18+ messages in thread
From: Salvatore Benedetto @ 2016-03-02  9:53 UTC (permalink / raw)
  To: Stephan Mueller; +Cc: herbert, tadeusz.struk, linux-crypto

On Tue, Mar 01, 2016 at 12:17:15PM +0100, Stephan Mueller wrote:

Hi Stephan,

> Am Dienstag, 1. März 2016, 11:08:34 schrieb Salvatore Benedetto:
> 
> Hi Salvatore,
> 
> > > > +static int dh_check_params_length(unsigned int p_len)
> > > > +{
> > > > +	switch (p_len) {
> > > > +	case 768:
> > > > +	case 1024:
> > > > +	case 1536:
> > > > +	case 2048:
> > > > +	case 3072:
> > > > +	case 4096:
> > > > +		return 0;
> > > > +	}
> > > > +	return -EINVAL;
> > > > +}
> > > 
> > > What is the reason for restricting the size to 4096?
> > 
> > Honestly no reason.
> > Could not find restrictions in the spec about the params length.
> 
> I am just wondering because other DH impls allow longer sizes.
> 
> And besides, I would like to disallow all < 2048 right from the start.
>

Hmm.. What range would you suggest?

I just thought that having the same range we support with RSA would be OK for now.

> > > > +
> > > > +static int dh_no_op(struct akcipher_request *req)
> > > > +{
> > > > +	return -ENOPROTOOPT;
> > > > +}
> > > > +
> > > > +static int dh_set_priv_key(struct crypto_akcipher *tfm, const void
> > > > *key,
> > > > +			   unsigned int keylen)
> > > > +{
> > > > +	struct dh_params *params = akcipher_tfm_ctx(tfm);
> > > 
> > > dh_get_params?
> > 
> > You mean adding a helper function? OK.
> 
> Not adding, but using your helper function -- why do you have it there in the 
> first place? :-)
>

True. I actually use it in dh_generate_public_key and
dh_compute_shared_secret. I'll fix that, thanks.

Regards,
Salvatore

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH] crypto: implement DH primitives under akcipher API
  2016-03-02  9:53       ` Salvatore Benedetto
@ 2016-03-02 13:03         ` Sandy Harris
  2016-03-02 14:20           ` Stephan Mueller
  0 siblings, 1 reply; 18+ messages in thread
From: Sandy Harris @ 2016-03-02 13:03 UTC (permalink / raw)
  To: Salvatore Benedetto
  Cc: Stephan Mueller, Herbert Xu, tadeusz.struk, linux-crypto

Salvatore Benedetto <salvatore.benedetto@intel.com> wrote:

>> > > > +static int dh_check_params_length(unsigned int p_len)
>> > > > +{
>> > > > +       switch (p_len) {
>> > > > +       case 768:
>> > > > +       case 1024:
>> > > > +       case 1536:
>> > > > +       case 2048:
>> > > > +       case 3072:
>> > > > +       case 4096:
>> > > > +               return 0;
>> > > > +       }
>> > > > +       return -EINVAL;
>> > > > +}
As far back as 1999, the FreeS/WAN project refused to
implement the 768-bit IPsec group 1 (even though it was
the only one required by the RFCs) because it was not thought
secure enough. I think the most-used group was 1536-bit
group 5; it wasn't in the original RFCs but nearly everyone
implemented it.

>> And besides, I would like to disallow all < 2048 right from the start.

I'm not up-to-date on the performance of attacks. You may be right,
or perhaps the minimum should be even higher. Certainly there is
no reason to support 768 or 1024-bit groups.

On the other hand, we should consider keeping the 1536-bit
group since it is very widely used, likely including by people
we'll want to interoperate with.

> Hmm.. What range would you suggest?

There are at least two RFCs which define additional groups.
Why not just add some or all of those?
https://tools.ietf.org/html/rfc3526
https://tools.ietf.org/html/rfc5114

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH] crypto: implement DH primitives under akcipher API
  2016-03-02  9:38   ` Salvatore Benedetto
@ 2016-03-02 13:46     ` Marcel Holtmann
  2016-03-07 21:45       ` Tadeusz Struk
  0 siblings, 1 reply; 18+ messages in thread
From: Marcel Holtmann @ 2016-03-02 13:46 UTC (permalink / raw)
  To: Salvatore Benedetto; +Cc: herbert, linux-crypto

Hi Salvatore,

>>> Implement Diffie-Hellman primitives required by the scheme under the
>>> akcipher API. Here is how it works.
>>> 1) Call set_pub_key() by passing DH parameters (p,g) in PKCS3 format
>>> 2) Call set_priv_key() to set your own private key (xa) in raw format
>> 
>> this combination seems odd since it is normally the remote public key and the local private key. Generally the public key and private key are both remote ones.
> 
> I'm not sure I understand what you mean here. Usually the public key is
> remote and the private key is local. How can the private key be remote?

I accidentally mistyped. I meant of course local.

>> 
>> For using PKCS3 format is this standardized somewhere? I don't think it is a good idea to invent new ones here.
> 
> PKCS3 is the format used by openssl for genating DH params, that's why I
> used it.

Is that OpenSSL specific or backed up by a RFC?

>> 
>> In addition, how would this work for ECDH?
> 
> Don't know. There is not even ECC support right now.

If you call something dh-generic, then we need to think about how it would work for all the other ciphers that it might be used with. Making this RSA specific is not a good idea.

> 
>> 
>>> 3) Call decrypt() without passing any data as input to get back the
>>>  public part which will be computed as g^xa mod p
>>> 4) Call encrypt() by passing the counter part public key (yb) in raw format
>>>  as input to get back the shared secret calculated as zz = yb^xa mod p
>>> 
>>> A test is included in the patch. Test vector has been generated with
>>> openssl
>>> 
>>> Signed-off-by: Salvatore Benedetto <salvatore.benedetto@intel.com>
>>> ---
>>> crypto/Kconfig    |   8 ++
>>> crypto/Makefile   |   7 ++
>>> crypto/dh.c       | 264 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
>>> crypto/pkcs3.asn1 |   5 ++
>>> crypto/tcrypt.c   |   4 +
>>> crypto/testmgr.c  | 140 +++++++++++++++++++++++++++--
>>> crypto/testmgr.h  | 208 +++++++++++++++++++++++++++++++++++++++++-
>>> 7 files changed, 627 insertions(+), 9 deletions(-)
>>> create mode 100644 crypto/dh.c
>>> create mode 100644 crypto/pkcs3.asn1
>>> 
>>> diff --git a/crypto/Kconfig b/crypto/Kconfig
>>> index f6bfdda..fd5b78d 100644
>>> --- a/crypto/Kconfig
>>> +++ b/crypto/Kconfig
>>> @@ -101,6 +101,14 @@ config CRYPTO_RSA
>>> 	help
>>> 	  Generic implementation of the RSA public key algorithm.
>>> 
>>> +config CRYPTO_DH
>>> +	tristate "Diffie-Hellman algorithm"
>>> +	select CRYPTO_AKCIPHER
>>> +	select MPILIB
>>> +	select ASN1
>> 
>> I really wonder that depending on ASN1 is a good idea here. As mentioned above ECDH would make sense to actually have supported from the beginning. The Bluetooth subsystem could be then converted to utilize in kernel ECC key generation and ECDH shared secret computation. It would be good to show this is truly generic DH.
>> 
> 
> This is an RFC. I understand it is not the best approach, but
> the idea behind was to try to reuse the akcipher for DH.

And I have the feeling that akcipher is not the best approach for adding a key exchange method. I think we need a new method for doing exactly that. At the base of it, the key exchange is fundamentally different.

>From an API point of view, I am also not convinced that it is a good idea to generate the private keys used on the fly. I think this all needs to be a lot more deterministic and flexible. In addition there are cases where you want to point to specific private / public key pair that you locally have. There are even protocols like Bluetooth that have defined fixed debug key pairs. If we can not support that, then this approach is not generic enough.

So my thinking actually is that we need a new key exchange abstraction in the crypto stack. However I am not sure that an userspace facing API should be done via AF_ALG. I think that does not fit. I think that doing it via keyctl is a lot more logical place.

It also means that we need a separate keyctl to actually generate the local private / public key pairs first. I think that makes sense no matter what. You can generate the keys, the private key stays in kernel memory forever and you can read out the public key. Some protocols will throw away the keys after single use, but others might actually reuse them. Or as mentioned above has fixed keys for debugging purposes. Using keyctl should then also make it easy to handle RSA vs ECC for the key generation since we need to be able to store both types at some point anyway. Also in cases where keys are RSA keys in ASN.1 format in the first place or are learned from certificates are already present and uniquely presented in the kernel. No need to invent yet another format for keys.

Especially in the case where you create a session key based out of certificates and existing public / private key pairs, it makes sense that keyctl can turn them directly into a new key. In most cases these are symmetric keys that can then be easily referenced by skcipher for ease of use.

And I did mention this before, this would also solve the problem where you might have to use a private key that is part of a TPM or secure enclave. The case where the kernel does not even know the key, just its existence. Use it to generate the session key and keep the session key in the kernel.

Regards

Marcel

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH] crypto: implement DH primitives under akcipher API
  2016-03-02 13:03         ` Sandy Harris
@ 2016-03-02 14:20           ` Stephan Mueller
  2016-03-02 14:54             ` Marcel Holtmann
  0 siblings, 1 reply; 18+ messages in thread
From: Stephan Mueller @ 2016-03-02 14:20 UTC (permalink / raw)
  To: Sandy Harris; +Cc: Salvatore Benedetto, Herbert Xu, tadeusz.struk, linux-crypto

Am Mittwoch, 2. März 2016, 08:03:44 schrieb Sandy Harris:

Hi Sandy,

> Salvatore Benedetto <salvatore.benedetto@intel.com> wrote:
> >> > > > +static int dh_check_params_length(unsigned int p_len)
> >> > > > +{
> >> > > > +       switch (p_len) {
> >> > > > +       case 768:
> >> > > > +       case 1024:
> >> > > > +       case 1536:
> >> > > > +       case 2048:
> >> > > > +       case 3072:
> >> > > > +       case 4096:
> >> > > > +               return 0;
> >> > > > +       }
> >> > > > +       return -EINVAL;
> >> > > > +}
> 
> As far back as 1999, the FreeS/WAN project refused to
> implement the 768-bit IPsec group 1 (even though it was
> the only one required by the RFCs) because it was not thought
> secure enough. I think the most-used group was 1536-bit
> group 5; it wasn't in the original RFCs but nearly everyone
> implemented it.
> 
> >> And besides, I would like to disallow all < 2048 right from the start.
> 
> I'm not up-to-date on the performance of attacks. You may be right,
> or perhaps the minimum should be even higher. Certainly there is
> no reason to support 768 or 1024-bit groups.
> 
> On the other hand, we should consider keeping the 1536-bit
> group since it is very widely used, likely including by people
> we'll want to interoperate with.

Considering the recent attacks which kind of broke DH <= 768, all smaller than 
1024 is not to be used any more. Even 1024 bit is not too far off from 768 so 
I would consider not using 1024 to keep a safety margin.

It is widely suggested to use 2048 and higher. But for compatibility, I agree 
with 1536.

However, that leaves us with the open question for the upper bound. I have no 
idea which sizes hardware may implement. But considering that OpenSSH uses DH 
up to and including 8192 these days (see /etc/ssh/moduli), I would suggest to 
allow 8192 too.

In addition, we should all be prepared to increase the limit with a reasonable 
effort. Thus, if we have implementations covering hardware support, they 
should cope with reasonable efforts.

Ciao
Stephan

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH] crypto: implement DH primitives under akcipher API
  2016-03-02 14:20           ` Stephan Mueller
@ 2016-03-02 14:54             ` Marcel Holtmann
  2016-03-02 15:09               ` Stephan Mueller
  0 siblings, 1 reply; 18+ messages in thread
From: Marcel Holtmann @ 2016-03-02 14:54 UTC (permalink / raw)
  To: Stephan Mueller
  Cc: Sandy Harris, Salvatore Benedetto, Herbert Xu, tadeusz.struk,
	linux-crypto

Hi Stephan,

>>>>>>> +static int dh_check_params_length(unsigned int p_len)
>>>>>>> +{
>>>>>>> +       switch (p_len) {
>>>>>>> +       case 768:
>>>>>>> +       case 1024:
>>>>>>> +       case 1536:
>>>>>>> +       case 2048:
>>>>>>> +       case 3072:
>>>>>>> +       case 4096:
>>>>>>> +               return 0;
>>>>>>> +       }
>>>>>>> +       return -EINVAL;
>>>>>>> +}
>> 
>> As far back as 1999, the FreeS/WAN project refused to
>> implement the 768-bit IPsec group 1 (even though it was
>> the only one required by the RFCs) because it was not thought
>> secure enough. I think the most-used group was 1536-bit
>> group 5; it wasn't in the original RFCs but nearly everyone
>> implemented it.
>> 
>>>> And besides, I would like to disallow all < 2048 right from the start.
>> 
>> I'm not up-to-date on the performance of attacks. You may be right,
>> or perhaps the minimum should be even higher. Certainly there is
>> no reason to support 768 or 1024-bit groups.
>> 
>> On the other hand, we should consider keeping the 1536-bit
>> group since it is very widely used, likely including by people
>> we'll want to interoperate with.
> 
> Considering the recent attacks which kind of broke DH <= 768, all smaller than 
> 1024 is not to be used any more. Even 1024 bit is not too far off from 768 so 
> I would consider not using 1024 to keep a safety margin.
> 
> It is widely suggested to use 2048 and higher. But for compatibility, I agree 
> with 1536.
> 
> However, that leaves us with the open question for the upper bound. I have no 
> idea which sizes hardware may implement. But considering that OpenSSH uses DH 
> up to and including 8192 these days (see /etc/ssh/moduli), I would suggest to 
> allow 8192 too.
> 
> In addition, we should all be prepared to increase the limit with a reasonable 
> effort. Thus, if we have implementations covering hardware support, they 
> should cope with reasonable efforts.

and why is this not an userspace policy decision on what minimum it allows? Why are we discussing this in the context of the kernel in the first place? The kernel should just expose the support for it.

Regards

Marcel

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH] crypto: implement DH primitives under akcipher API
  2016-03-02 14:54             ` Marcel Holtmann
@ 2016-03-02 15:09               ` Stephan Mueller
  0 siblings, 0 replies; 18+ messages in thread
From: Stephan Mueller @ 2016-03-02 15:09 UTC (permalink / raw)
  To: Marcel Holtmann
  Cc: Sandy Harris, Salvatore Benedetto, Herbert Xu, tadeusz.struk,
	linux-crypto

Am Mittwoch, 2. März 2016, 06:54:21 schrieb Marcel Holtmann:

Hi Marcel,

> 
> and why is this not an userspace policy decision on what minimum it allows?
> Why are we discussing this in the context of the kernel in the first place?
> The kernel should just expose the support for it.

You are right on the mark, this would be the best.
> 
> Regards
> 
> Marcel


Ciao
Stephan

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH] crypto: implement DH primitives under akcipher API
  2016-03-02 13:46     ` Marcel Holtmann
@ 2016-03-07 21:45       ` Tadeusz Struk
  2016-03-07 22:29         ` Marcel Holtmann
  0 siblings, 1 reply; 18+ messages in thread
From: Tadeusz Struk @ 2016-03-07 21:45 UTC (permalink / raw)
  To: Marcel Holtmann; +Cc: Salvatore Benedetto, herbert, linux-crypto, David Howells

Hi Marcel,
On 03/02/2016 05:46 AM, Marcel Holtmann wrote:
> And I have the feeling that akcipher is not the best approach for adding a key exchange method. I think we need a new method for doing exactly that. At the base of it, the key exchange is fundamentally different.

It is unfortunate that, unlike the symmetric ciphers, not all the
asymmetric ciphers have the same simple encrypt/decrypt interface.
As you said key exchange algorithms are different. To solve that we should
define new methods in akcipher.h for key exchange as follows:

diff --git a/include/crypto/akcipher.h b/include/crypto/akcipher.h
index c37cc59..d50d834 100644
--- a/include/crypto/akcipher.h
+++ b/include/crypto/akcipher.h
@@ -383,4 +383,41 @@ static inline int crypto_akcipher_set_priv_key(struct crypto_akcipher *tfm,
 
 	return alg->set_priv_key(tfm, key, keylen);
 }
+
+/**
+ * crypto_akcipher_gen_public() - Invoke appropriate key exchange function
+ *
+ * Function invokes the specific key exchange function, which calculates
+ * the public component.
+ *
+ * @req:	asymmetric key request
+ *
+ * Return: zero on success; error code in case of error
+ */
+static inline int crypto_akcipher_gen_public(struct akcipher_request *req)
+{
+	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
+	struct akcipher_alg *alg = crypto_akcipher_alg(tfm);
+
+	return alg->encrypt(req);
+}
+
+/**
+ * crypto_akcipher_gen_shared() - Invoke appropriate key exchange function
+ *
+ * Function invokes the specific key exchange function, which calculates
+ * the shared secret component.
+ *
+ * @req:	asymmetric key request
+ *
+ * Return: zero on success; error code in case of error
+ */
+static inline int crypto_akcipher_gen_shared(struct akcipher_request *req)
+{
+	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
+	struct akcipher_alg *alg = crypto_akcipher_alg(tfm);
+
+	return alg->decrypt(req);
+}
+
 #endif

In this way we can define a generic user side of the key exchange interface,
and on the the driver side of the akcipher, the implementations would overload
the existing akcipher encrypt(), decrypt(), set_pub_key(), set_priv_key() methods
and do what should be done for a given algorithm. We just need to agree on the
format of the input parameters to these operations.

> 
> From an API point of view, I am also not convinced that it is a good idea to generate the private keys used on the fly. I think this all needs to be a lot more deterministic and flexible. In addition there are cases where you want to point to specific private / public key pair that you locally have. There are even protocols like Bluetooth that have defined fixed debug key pairs. If we can not support that, then this approach is not generic enough.

Agree, we need to support all the cases, but dealing with different type of keys
needs to happen above this API. This API should solely be an interface to math
primitives of certain operations, which can be implemented in SW or can be HW
accelerated. Modules like public_key or afalg_akcipher need to be smart enough
and know what key types they deal with and do the right thing depending on that
knowledge.

> 
> So my thinking actually is that we need a new key exchange abstraction in the crypto stack. However I am not sure that an userspace facing API should be done via AF_ALG. I think that does not fit. I think that doing it via keyctl is a lot more logical place.

The advantage of exposing akcipher via AF_ALG is that we can support generic
applications like OpenSSL or web server. I agree that for some use cases keyctl
will make more sense, but this shouldn't prevent us from allowing the mentioned
applications using hardware crypto accelerators that implement e.g. RSA, and can
work with SW keys. The two interfaces should coexist, and they should work together.
Keyctl should internally use akcipher for SW keys instead of introducing its own
implementation, and algif_akcipher should use keyring to deal with HW keys.
I'm working with David Howells to try to find out how exactly this will work together.

Also please note that there already exists an af_alg engine for openSSL for
symmetric ciphers. It would be more logical to add support for asymmetric ciphers
to the existing engine, than to create a new one, which uses keyctl.

> 
> It also means that we need a separate keyctl to actually generate the local private / public key pairs first. I think that makes sense no matter what. You can generate the keys, the private key stays in kernel memory forever and you can read out the public key. Some protocols will throw away the keys after single use, but others might actually reuse them. Or as mentioned above has fixed keys for debugging purposes. Using keyctl should then also make it easy to handle RSA vs ECC for the key generation since we need to be able to store both types at some point anyway. Also in cases where keys are RSA keys in ASN.1 format in the first place or are learned from certificates are already present and uniquely presented in the kernel. No need to invent yet another format for keys.
> 
> Especially in the case where you create a session key based out of certificates and existing public / private key pairs, it makes sense that keyctl can turn them directly into a new key. In most cases these are symmetric keys that can then be easily referenced by skcipher for ease of use.
> 
> And I did mention this before, this would also solve the problem where you might have to use a private key that is part of a TPM or secure enclave. The case where the kernel does not even know the key, just its existence. Use it to generate the session key and keep the session key in the kernel.

Agree, and to make this work with afalg_akcipher, I have proposed new
ALG_SET_KEY_ID and ALG_SET_KEY_ID operations. See here: https://lkml.org/lkml/2015/12/26/65
The plan is that in this case the afalg_akcipher will not use akcipher api at all.
In this case the algif_akcipher will use the request_key() interface to retrieve
the key type info and will use the operations that the new TPM interface will define.
Thanks,
-- 
TS

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* Re: [PATCH] crypto: implement DH primitives under akcipher API
  2016-03-07 21:45       ` Tadeusz Struk
@ 2016-03-07 22:29         ` Marcel Holtmann
  2016-03-07 23:19           ` Tadeusz Struk
  0 siblings, 1 reply; 18+ messages in thread
From: Marcel Holtmann @ 2016-03-07 22:29 UTC (permalink / raw)
  To: Tadeusz Struk
  Cc: Salvatore Benedetto, Herbert Xu, Linux Crypto Mailing List,
	David Howells, David Woodhouse

Hi Tadeusz,

>> And I have the feeling that akcipher is not the best approach for adding a key exchange method. I think we need a new method for doing exactly that. At the base of it, the key exchange is fundamentally different.
> 
> It is unfortunate that, unlike the symmetric ciphers, not all the
> asymmetric ciphers have the same simple encrypt/decrypt interface.
> As you said key exchange algorithms are different. To solve that we should
> define new methods in akcipher.h for key exchange as follows:
> 
> diff --git a/include/crypto/akcipher.h b/include/crypto/akcipher.h
> index c37cc59..d50d834 100644
> --- a/include/crypto/akcipher.h
> +++ b/include/crypto/akcipher.h
> @@ -383,4 +383,41 @@ static inline int crypto_akcipher_set_priv_key(struct crypto_akcipher *tfm,
> 
> 	return alg->set_priv_key(tfm, key, keylen);
> }
> +
> +/**
> + * crypto_akcipher_gen_public() - Invoke appropriate key exchange function
> + *
> + * Function invokes the specific key exchange function, which calculates
> + * the public component.
> + *
> + * @req:	asymmetric key request
> + *
> + * Return: zero on success; error code in case of error
> + */
> +static inline int crypto_akcipher_gen_public(struct akcipher_request *req)
> +{
> +	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
> +	struct akcipher_alg *alg = crypto_akcipher_alg(tfm);
> +
> +	return alg->encrypt(req);
> +}
> +
> +/**
> + * crypto_akcipher_gen_shared() - Invoke appropriate key exchange function
> + *
> + * Function invokes the specific key exchange function, which calculates
> + * the shared secret component.
> + *
> + * @req:	asymmetric key request
> + *
> + * Return: zero on success; error code in case of error
> + */
> +static inline int crypto_akcipher_gen_shared(struct akcipher_request *req)
> +{
> +	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
> +	struct akcipher_alg *alg = crypto_akcipher_alg(tfm);
> +
> +	return alg->decrypt(req);
> +}
> +
> #endif
> 
> In this way we can define a generic user side of the key exchange interface,
> and on the the driver side of the akcipher, the implementations would overload
> the existing akcipher encrypt(), decrypt(), set_pub_key(), set_priv_key() methods
> and do what should be done for a given algorithm. We just need to agree on the
> format of the input parameters to these operations.

I think trying to heavily map this to encrypt and decrypt is a bad idea. These callbacks are not really designed to return what you need them to return. Key exchange is different.

So why are we trying to push this into akcipher in the first place? I mean lets just create a keyexch (or similar name) and design it explicitly for key exchange handling. We are also not trying to map hashes into skcipher. I think the clear distinction of semantics calls for a different API.

>> From an API point of view, I am also not convinced that it is a good idea to generate the private keys used on the fly. I think this all needs to be a lot more deterministic and flexible. In addition there are cases where you want to point to specific private / public key pair that you locally have. There are even protocols like Bluetooth that have defined fixed debug key pairs. If we can not support that, then this approach is not generic enough.
> 
> Agree, we need to support all the cases, but dealing with different type of keys
> needs to happen above this API. This API should solely be an interface to math
> primitives of certain operations, which can be implemented in SW or can be HW
> accelerated. Modules like public_key or afalg_akcipher need to be smart enough
> and know what key types they deal with and do the right thing depending on that
> knowledge.

I am not sure this can be that easily generalized. Just pushing the problem of key types and formats off to userspace just forces complexity and extra knowledge there. We need to be really carefully here. And I really dislike introducing custom ASN.1 structures that are not backed by an actual RFC document.

>> So my thinking actually is that we need a new key exchange abstraction in the crypto stack. However I am not sure that an userspace facing API should be done via AF_ALG. I think that does not fit. I think that doing it via keyctl is a lot more logical place.
> 
> The advantage of exposing akcipher via AF_ALG is that we can support generic
> applications like OpenSSL or web server. I agree that for some use cases keyctl
> will make more sense, but this shouldn't prevent us from allowing the mentioned
> applications using hardware crypto accelerators that implement e.g. RSA, and can
> work with SW keys. The two interfaces should coexist, and they should work together.
> Keyctl should internally use akcipher for SW keys instead of introducing its own
> implementation, and algif_akcipher should use keyring to deal with HW keys.
> I'm working with David Howells to try to find out how exactly this will work together.
> 
> Also please note that there already exists an af_alg engine for openSSL for
> symmetric ciphers. It would be more logical to add support for asymmetric ciphers
> to the existing engine, than to create a new one, which uses keyctl.

Of course keyctl should use akcipher and also a new keyexch to work with keys that do not have a hardware crypto backing them up.

>> It also means that we need a separate keyctl to actually generate the local private / public key pairs first. I think that makes sense no matter what. You can generate the keys, the private key stays in kernel memory forever and you can read out the public key. Some protocols will throw away the keys after single use, but others might actually reuse them. Or as mentioned above has fixed keys for debugging purposes. Using keyctl should then also make it easy to handle RSA vs ECC for the key generation since we need to be able to store both types at some point anyway. Also in cases where keys are RSA keys in ASN.1 format in the first place or are learned from certificates are already present and uniquely presented in the kernel. No need to invent yet another format for keys.
>> 
>> Especially in the case where you create a session key based out of certificates and existing public / private key pairs, it makes sense that keyctl can turn them directly into a new key. In most cases these are symmetric keys that can then be easily referenced by skcipher for ease of use.
>> 
>> And I did mention this before, this would also solve the problem where you might have to use a private key that is part of a TPM or secure enclave. The case where the kernel does not even know the key, just its existence. Use it to generate the session key and keep the session key in the kernel.
> 
> Agree, and to make this work with afalg_akcipher, I have proposed new
> ALG_SET_KEY_ID and ALG_SET_KEY_ID operations. See here: https://lkml.org/lkml/2015/12/26/65
> The plan is that in this case the afalg_akcipher will not use akcipher api at all.
> In this case the algif_akcipher will use the request_key() interface to retrieve
> the key type info and will use the operations that the new TPM interface will define.

The ALG_SET_KEY_ID is great for skcipher where you key is a fixed size blob. There is works really well. And you will need if we let keyctl derive the session key from a set of asymmetric keys.

I get that we want to enable OpenSSL and others to gain access to kernel crypto operations. We want the same actually for ELL as well. However what is dangerous here is that AF_ALG can never support hardware based keys. So that means support in OpenSSL is broken by design. See earlier emails from David Woodhouse. If you have your certificates / keys in hardware then you need to be able to make them work with OpenSSL. We can not ignore this. It is a design we need to consider from the beginning.

Regards

Marcel

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH] crypto: implement DH primitives under akcipher API
  2016-03-07 22:29         ` Marcel Holtmann
@ 2016-03-07 23:19           ` Tadeusz Struk
  2016-03-08 17:03             ` Marcel Holtmann
  0 siblings, 1 reply; 18+ messages in thread
From: Tadeusz Struk @ 2016-03-07 23:19 UTC (permalink / raw)
  To: Marcel Holtmann
  Cc: Salvatore Benedetto, Herbert Xu, Linux Crypto Mailing List,
	David Howells, David Woodhouse

Hi Marcel,
On 03/07/2016 02:29 PM, Marcel Holtmann wrote:
>> In this way we can define a generic user side of the key exchange interface,
>> > and on the the driver side of the akcipher, the implementations would overload
>> > the existing akcipher encrypt(), decrypt(), set_pub_key(), set_priv_key() methods
>> > and do what should be done for a given algorithm. We just need to agree on the
>> > format of the input parameters to these operations.
> I think trying to heavily map this to encrypt and decrypt is a bad idea. These callbacks are not really designed to return what you need them to return. Key exchange is different.
> 
> So why are we trying to push this into akcipher in the first place? I mean lets just create a keyexch (or similar name) and design it explicitly for key exchange handling. We are also not trying to map hashes into skcipher. I think the clear distinction of semantics calls for a different API.
> 

I just think that before introducing new API we should try to reuse what's already
there. Looking at RSA and DH, they basically perform x = a^b mod p, so we should
have what's needed for both and we just could overload the methods already defined.
I'm fine either way. Herbert, what's your preference?

>> Agree, we need to support all the cases, but dealing with different type of keys
>> > needs to happen above this API. This API should solely be an interface to math
>> > primitives of certain operations, which can be implemented in SW or can be HW
>> > accelerated. Modules like public_key or afalg_akcipher need to be smart enough
>> > and know what key types they deal with and do the right thing depending on that
>> > knowledge.
> I am not sure this can be that easily generalized. Just pushing the problem of key types and formats off to userspace just forces complexity and extra knowledge there. We need to be really carefully here. And I really dislike introducing custom ASN.1 structures that are not backed by an actual RFC document.

I'm not saying that we should push this to user space. I'm just saying this should
be handled above the crypto API.

>> Agree, and to make this work with afalg_akcipher, I have proposed new
>> > ALG_SET_KEY_ID and ALG_SET_KEY_ID operations. See here: https://lkml.org/lkml/2015/12/26/65
>> > The plan is that in this case the afalg_akcipher will not use akcipher api at all.
>> > In this case the algif_akcipher will use the request_key() interface to retrieve
>> > the key type info and will use the operations that the new TPM interface will define.
> The ALG_SET_KEY_ID is great for skcipher where you key is a fixed size blob. There is works really well. And you will need if we let keyctl derive the session key from a set of asymmetric keys.
> 
> I get that we want to enable OpenSSL and others to gain access to kernel crypto operations. We want the same actually for ELL as well. However what is dangerous here is that AF_ALG can never support hardware based keys. So that means support in OpenSSL is broken by design. See earlier emails from David Woodhouse. If you have your certificates / keys in hardware then you need to be able to make them work with OpenSSL. We can not ignore this. It is a design we need to consider from the beginning.

If we will have the TPM interface that allows to invoke functions for HW keys and
the *_KEY_ID, then I don't see why AF_ALG would not work. As I said, in case when
the keys will be in HW the algif_akcipher will not use akcipher api, but use the
TPM defined functions in the same way as the keyctl would use it.
So I think both AF_ALG and keyctl should work just fine.
Thanks,
-- 
TS

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH] crypto: implement DH primitives under akcipher API
  2016-03-07 23:19           ` Tadeusz Struk
@ 2016-03-08 17:03             ` Marcel Holtmann
  0 siblings, 0 replies; 18+ messages in thread
From: Marcel Holtmann @ 2016-03-08 17:03 UTC (permalink / raw)
  To: Tadeusz Struk
  Cc: Salvatore Benedetto, Herbert Xu, Linux Crypto Mailing List,
	David Howells, David Woodhouse

Hi Tadeusz,

>>> In this way we can define a generic user side of the key exchange interface,
>>>> and on the the driver side of the akcipher, the implementations would overload
>>>> the existing akcipher encrypt(), decrypt(), set_pub_key(), set_priv_key() methods
>>>> and do what should be done for a given algorithm. We just need to agree on the
>>>> format of the input parameters to these operations.
>> I think trying to heavily map this to encrypt and decrypt is a bad idea. These callbacks are not really designed to return what you need them to return. Key exchange is different.
>> 
>> So why are we trying to push this into akcipher in the first place? I mean lets just create a keyexch (or similar name) and design it explicitly for key exchange handling. We are also not trying to map hashes into skcipher. I think the clear distinction of semantics calls for a different API.
>> 
> 
> I just think that before introducing new API we should try to reuse what's already
> there. Looking at RSA and DH, they basically perform x = a^b mod p, so we should
> have what's needed for both and we just could overload the methods already defined.
> I'm fine either way. Herbert, what's your preference?

I do not think that it is a valid argument because the operations are the same to use akcipher. While operations are similar, the inputs are totally different. And it is really not performing encrypt or decrypt operations here. You use different inputs and get different outputs. You are not encrypting or decrypting anything. Especially key generation via decrypt is something I can not wrap my mind around.

>>> Agree, we need to support all the cases, but dealing with different type of keys
>>>> needs to happen above this API. This API should solely be an interface to math
>>>> primitives of certain operations, which can be implemented in SW or can be HW
>>>> accelerated. Modules like public_key or afalg_akcipher need to be smart enough
>>>> and know what key types they deal with and do the right thing depending on that
>>>> knowledge.
>> I am not sure this can be that easily generalized. Just pushing the problem of key types and formats off to userspace just forces complexity and extra knowledge there. We need to be really carefully here. And I really dislike introducing custom ASN.1 structures that are not backed by an actual RFC document.
> 
> I'm not saying that we should push this to user space. I'm just saying this should
> be handled above the crypto API.
> 
>>> Agree, and to make this work with afalg_akcipher, I have proposed new
>>>> ALG_SET_KEY_ID and ALG_SET_KEY_ID operations. See here: https://lkml.org/lkml/2015/12/26/65
>>>> The plan is that in this case the afalg_akcipher will not use akcipher api at all.
>>>> In this case the algif_akcipher will use the request_key() interface to retrieve
>>>> the key type info and will use the operations that the new TPM interface will define.
>> The ALG_SET_KEY_ID is great for skcipher where you key is a fixed size blob. There is works really well. And you will need if we let keyctl derive the session key from a set of asymmetric keys.
>> 
>> I get that we want to enable OpenSSL and others to gain access to kernel crypto operations. We want the same actually for ELL as well. However what is dangerous here is that AF_ALG can never support hardware based keys. So that means support in OpenSSL is broken by design. See earlier emails from David Woodhouse. If you have your certificates / keys in hardware then you need to be able to make them work with OpenSSL. We can not ignore this. It is a design we need to consider from the beginning.
> 
> If we will have the TPM interface that allows to invoke functions for HW keys and
> the *_KEY_ID, then I don't see why AF_ALG would not work. As I said, in case when
> the keys will be in HW the algif_akcipher will not use akcipher api, but use the
> TPM defined functions in the same way as the keyctl would use it.
> So I think both AF_ALG and keyctl should work just fine.

When David and I talked to Herbert at the kernel summit in Seoul, he said that the crypto subsystem (and with that AF_ALG) always needs to support software fallback crypto. In case of hardware based keys, there is no software fallback possible. If you have a hardware key, then it always needs to use the hardware crypto that comes with the key.

And that is precisely my point in going forward with keyctl for all of these. We need _one_ interface that can handle software and hardware keys / key pairs.

Regards

Marcel

^ permalink raw reply	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2016-03-08 17:03 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-02-15  9:01 [PATCH] crypto: implement DH primitives under akcipher API Salvatore Benedetto
2016-02-15 13:57 ` Stephan Mueller
2016-03-01 11:08   ` Salvatore Benedetto
2016-03-01 11:17     ` Stephan Mueller
2016-03-02  9:53       ` Salvatore Benedetto
2016-03-02 13:03         ` Sandy Harris
2016-03-02 14:20           ` Stephan Mueller
2016-03-02 14:54             ` Marcel Holtmann
2016-03-02 15:09               ` Stephan Mueller
2016-02-16 20:19 ` Herbert Xu
2016-02-16 20:29   ` Tadeusz Struk
2016-03-01 20:25 ` Marcel Holtmann
2016-03-02  9:38   ` Salvatore Benedetto
2016-03-02 13:46     ` Marcel Holtmann
2016-03-07 21:45       ` Tadeusz Struk
2016-03-07 22:29         ` Marcel Holtmann
2016-03-07 23:19           ` Tadeusz Struk
2016-03-08 17:03             ` Marcel Holtmann

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.