* [RFC PATCH v2 0/4] crypto: (ec)dh - add privkey generation support
@ 2017-05-17 15:26 Tudor Ambarus
2017-05-17 15:26 ` [RFC PATCH v2 1/4] crypto: ecc " Tudor Ambarus
` (3 more replies)
0 siblings, 4 replies; 14+ messages in thread
From: Tudor Ambarus @ 2017-05-17 15:26 UTC (permalink / raw)
To: herbert, davem
Cc: linux-crypto, smueller, marcel, Nicolas.Ferre, Tudor Ambarus
Hi,
This is an RFC to discuss how to support private key generation for dh and ecdh.
This is helpful in a user-space to kernel (ec)dh offload because the keys are
generated in kernel and never revealed to user-space.
Private key generation is also helpful to implement forward secrecy.
A public/private key system demonstrates the property of forward secrecy if it
creates new key pairs for each communication session. These key pairs are
generated on an as-needed basis and are destroyed after the session is over.
If an attacker were to record previous encrypted session data, they wouldn't be
able to decrypt it with possession of a long-term key.
There are crypto accelerators that are capable of generating and retaining
private keys without revealing them to software. This patch set is a
prerequisite for hardware private key generation support.
Changes in v2:
- free dh params in case of error
- code defensively in testmgr: use sizeof(*ptr) while in memcpy
v1 can be found at:
http://www.mail-archive.com/linux-crypto@vger.kernel.org/msg25176.html
Tudor Ambarus (4):
crypto: ecc - add privkey generation support
crypto: ecdh - allow user to provide NULL privkey
crypto: dh - allow user to provide NULL privkey
crypto: testmgr - add genkey kpp test
crypto/dh.c | 21 ++++++++
crypto/ecc.c | 20 +++++++
crypto/ecc.h | 14 +++++
crypto/ecdh.c | 4 ++
crypto/testmgr.c | 76 +++++++++++++++++++++++----
crypto/testmgr.h | 155 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
6 files changed, 279 insertions(+), 11 deletions(-)
--
2.7.4
^ permalink raw reply [flat|nested] 14+ messages in thread
* [RFC PATCH v2 1/4] crypto: ecc - add privkey generation support
2017-05-17 15:26 [RFC PATCH v2 0/4] crypto: (ec)dh - add privkey generation support Tudor Ambarus
@ 2017-05-17 15:26 ` Tudor Ambarus
2017-05-28 18:44 ` Stephan Müller
2017-05-17 15:26 ` [RFC PATCH v2 2/4] crypto: ecdh - allow user to provide NULL privkey Tudor Ambarus
` (2 subsequent siblings)
3 siblings, 1 reply; 14+ messages in thread
From: Tudor Ambarus @ 2017-05-17 15:26 UTC (permalink / raw)
To: herbert, davem
Cc: linux-crypto, smueller, marcel, Nicolas.Ferre, Tudor Ambarus
Add support for generating ecc private keys.
Generation of ecc private keys is helpful in a user-space to kernel
ecdh offload because the keys are not revealed to user-space. Private
key generation is also helpful to implement forward secrecy.
Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
---
crypto/ecc.c | 20 ++++++++++++++++++++
crypto/ecc.h | 14 ++++++++++++++
2 files changed, 34 insertions(+)
diff --git a/crypto/ecc.c b/crypto/ecc.c
index 414c78a..a591907 100644
--- a/crypto/ecc.c
+++ b/crypto/ecc.c
@@ -927,6 +927,26 @@ int ecc_is_key_valid(unsigned int curve_id, unsigned int ndigits,
return 0;
}
+int ecc_gen_privkey(unsigned int curve_id, unsigned int ndigits, u64 *privkey)
+{
+ const struct ecc_curve *curve = ecc_get_curve(curve_id);
+ u64 priv[ndigits];
+ unsigned int nbytes = ndigits << ECC_DIGITS_TO_BYTES_SHIFT;
+
+ get_random_bytes(priv, nbytes);
+
+ if (vli_is_zero(priv, ndigits))
+ return -EINVAL;
+
+ /* Make sure the private key is in the range [1, n-1]. */
+ if (vli_cmp(curve->n, priv, ndigits) != 1)
+ return -EINVAL;
+
+ ecc_swap_digits(priv, privkey, ndigits);
+
+ return 0;
+}
+
int ecdh_make_pub_key(unsigned int curve_id, unsigned int ndigits,
const u8 *private_key, unsigned int private_key_len,
u8 *public_key, unsigned int public_key_len)
diff --git a/crypto/ecc.h b/crypto/ecc.h
index 663d598..b94b7ce 100644
--- a/crypto/ecc.h
+++ b/crypto/ecc.h
@@ -44,6 +44,20 @@ int ecc_is_key_valid(unsigned int curve_id, unsigned int ndigits,
const u8 *private_key, unsigned int private_key_len);
/**
+ * ecc_gen_privkey() - Generates an ECC private key.
+ * The private key is a random integer in the range 0 < random < n, where n is a
+ * prime that is the order of the cyclic subgroup generated by the distinguished
+ * point G.
+ * @curve_id: id representing the curve to use
+ * @ndigits: curve number of digits
+ * @private_key: buffer for storing the generated private key
+ *
+ * Returns 0 if the private key was generated successfully, a negative value
+ * if an error occurred.
+ */
+int ecc_gen_privkey(unsigned int curve_id, unsigned int ndigits, u64 *privkey);
+
+/**
* ecdh_make_pub_key() - Compute an ECC public key
*
* @curve_id: id representing the curve to use
--
2.7.4
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [RFC PATCH v2 2/4] crypto: ecdh - allow user to provide NULL privkey
2017-05-17 15:26 [RFC PATCH v2 0/4] crypto: (ec)dh - add privkey generation support Tudor Ambarus
2017-05-17 15:26 ` [RFC PATCH v2 1/4] crypto: ecc " Tudor Ambarus
@ 2017-05-17 15:26 ` Tudor Ambarus
2017-05-17 15:26 ` [RFC PATCH v2 3/4] crypto: dh " Tudor Ambarus
2017-05-17 15:26 ` [RFC PATCH v2 4/4] crypto: testmgr - add genkey kpp test Tudor Ambarus
3 siblings, 0 replies; 14+ messages in thread
From: Tudor Ambarus @ 2017-05-17 15:26 UTC (permalink / raw)
To: herbert, davem
Cc: linux-crypto, smueller, marcel, Nicolas.Ferre, Tudor Ambarus
If the user provides a NULL ecc private key, the kernel will
generate it and further use it for ecdh.
Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
---
crypto/ecdh.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/crypto/ecdh.c b/crypto/ecdh.c
index 63ca337..f28f5b5 100644
--- a/crypto/ecdh.c
+++ b/crypto/ecdh.c
@@ -55,6 +55,10 @@ static int ecdh_set_secret(struct crypto_kpp *tfm, const void *buf,
ctx->curve_id = params.curve_id;
ctx->ndigits = ndigits;
+ if (!params.key || !params.key_size)
+ return ecc_gen_privkey(ctx->curve_id, ctx->ndigits,
+ ctx->private_key);
+
if (ecc_is_key_valid(ctx->curve_id, ctx->ndigits,
(const u8 *)params.key, params.key_size) < 0)
return -EINVAL;
--
2.7.4
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [RFC PATCH v2 3/4] crypto: dh - allow user to provide NULL privkey
2017-05-17 15:26 [RFC PATCH v2 0/4] crypto: (ec)dh - add privkey generation support Tudor Ambarus
2017-05-17 15:26 ` [RFC PATCH v2 1/4] crypto: ecc " Tudor Ambarus
2017-05-17 15:26 ` [RFC PATCH v2 2/4] crypto: ecdh - allow user to provide NULL privkey Tudor Ambarus
@ 2017-05-17 15:26 ` Tudor Ambarus
2017-05-28 18:50 ` Stephan Müller
2017-05-17 15:26 ` [RFC PATCH v2 4/4] crypto: testmgr - add genkey kpp test Tudor Ambarus
3 siblings, 1 reply; 14+ messages in thread
From: Tudor Ambarus @ 2017-05-17 15:26 UTC (permalink / raw)
To: herbert, davem
Cc: linux-crypto, smueller, marcel, Nicolas.Ferre, Tudor Ambarus
If the user provides a NULL private key, the kernel will
generate it and further use it for dh.
Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
---
crypto/dh.c | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
diff --git a/crypto/dh.c b/crypto/dh.c
index 87e3542..7b4ac5b 100644
--- a/crypto/dh.c
+++ b/crypto/dh.c
@@ -83,7 +83,9 @@ static int dh_set_secret(struct crypto_kpp *tfm, const void *buf,
unsigned int len)
{
struct dh_ctx *ctx = dh_get_ctx(tfm);
+ u8 *rndbuf = NULL;
struct dh params;
+ int maxsize;
if (crypto_dh_decode_key(buf, len, ¶ms) < 0)
return -EINVAL;
@@ -91,7 +93,26 @@ static int dh_set_secret(struct crypto_kpp *tfm, const void *buf,
if (dh_set_params(ctx, ¶ms) < 0)
return -EINVAL;
+ if (!params.key || !params.key_size) {
+ maxsize = crypto_kpp_maxsize(tfm);
+ if (maxsize < 0) {
+ dh_clear_params(ctx);
+ return maxsize;
+ }
+
+ rndbuf = kmalloc(maxsize, GFP_KERNEL);
+ if (!rndbuf) {
+ dh_clear_params(ctx);
+ return -ENOMEM;
+ }
+
+ get_random_bytes(rndbuf, maxsize);
+ params.key = rndbuf;
+ params.key_size = maxsize;
+ }
+
ctx->xa = mpi_read_raw_data(params.key, params.key_size);
+ kzfree(rndbuf);
if (!ctx->xa) {
dh_clear_params(ctx);
return -EINVAL;
--
2.7.4
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [RFC PATCH v2 4/4] crypto: testmgr - add genkey kpp test
2017-05-17 15:26 [RFC PATCH v2 0/4] crypto: (ec)dh - add privkey generation support Tudor Ambarus
` (2 preceding siblings ...)
2017-05-17 15:26 ` [RFC PATCH v2 3/4] crypto: dh " Tudor Ambarus
@ 2017-05-17 15:26 ` Tudor Ambarus
2017-05-26 13:44 ` Tudor Ambarus
2017-05-28 18:57 ` Stephan Müller
3 siblings, 2 replies; 14+ messages in thread
From: Tudor Ambarus @ 2017-05-17 15:26 UTC (permalink / raw)
To: herbert, davem
Cc: linux-crypto, smueller, marcel, Nicolas.Ferre, Tudor Ambarus
The test considers a party that already has a private-public
key pair and a party that provides a NULL key. The kernel will
generate the private-public key pair for the latter, computes
the shared secret on both ends and verifies it it's the same.
The explicit private-public key pairs were copied from
the previous test vectors.
Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
---
crypto/testmgr.c | 76 +++++++++++++++++++++++----
crypto/testmgr.h | 155 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 220 insertions(+), 11 deletions(-)
diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index 6f5f3ed..faf5fd8 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -1997,6 +1997,9 @@ static int do_test_kpp(struct crypto_kpp *tfm, const struct kpp_testvec *vec,
struct kpp_request *req;
void *input_buf = NULL;
void *output_buf = NULL;
+ void *a_public = NULL;
+ void *a_ss = NULL;
+ void *shared_secret = NULL;
struct tcrypt_result result;
unsigned int out_len_max;
int err = -ENOMEM;
@@ -2026,20 +2029,31 @@ static int do_test_kpp(struct crypto_kpp *tfm, const struct kpp_testvec *vec,
kpp_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
tcrypt_complete, &result);
- /* Compute public key */
+ /* Compute party A's public key */
err = wait_async_op(&result, crypto_kpp_generate_public_key(req));
if (err) {
- pr_err("alg: %s: generate public key test failed. err %d\n",
+ pr_err("alg: %s: Party A: generate public key test failed. err %d\n",
alg, err);
goto free_output;
}
- /* Verify calculated public key */
- if (memcmp(vec->expected_a_public, sg_virt(req->dst),
- vec->expected_a_public_size)) {
- pr_err("alg: %s: generate public key test failed. Invalid output\n",
- alg);
- err = -EINVAL;
- goto free_output;
+
+ if (vec->genkey) {
+ /* Save party A's public key */
+ a_public = kzalloc(out_len_max, GFP_KERNEL);
+ if (!a_public) {
+ err = -ENOMEM;
+ goto free_output;
+ }
+ memcpy(a_public, sg_virt(req->dst), sizeof(*a_public));
+ } else {
+ /* Verify calculated public key */
+ if (memcmp(vec->expected_a_public, sg_virt(req->dst),
+ vec->expected_a_public_size)) {
+ pr_err("alg: %s: Party A: generate public key test failed. Invalid output\n",
+ alg);
+ err = -EINVAL;
+ goto free_output;
+ }
}
/* Calculate shared secret key by using counter part (b) public key. */
@@ -2058,15 +2072,53 @@ static int do_test_kpp(struct crypto_kpp *tfm, const struct kpp_testvec *vec,
tcrypt_complete, &result);
err = wait_async_op(&result, crypto_kpp_compute_shared_secret(req));
if (err) {
- pr_err("alg: %s: compute shard secret test failed. err %d\n",
+ pr_err("alg: %s: Party A: compute shared secret test failed. err %d\n",
alg, err);
goto free_all;
}
+
+ if (vec->genkey) {
+ /* Save the shared secret obtained by party A */
+ a_ss = kzalloc(vec->expected_ss_size, GFP_KERNEL);
+ if (!a_ss) {
+ err = -ENOMEM;
+ goto free_all;
+ }
+ memcpy(a_ss, sg_virt(req->dst), sizeof(*a_ss));
+
+ /*
+ * Calculate party B's shared secret by using party A's
+ * public key.
+ */
+ err = crypto_kpp_set_secret(tfm, vec->b_secret,
+ vec->b_secret_size);
+ if (err < 0)
+ goto free_all;
+
+ sg_init_one(&src, a_public, vec->expected_a_public_size);
+ sg_init_one(&dst, output_buf, out_len_max);
+ kpp_request_set_input(req, &src, vec->expected_a_public_size);
+ kpp_request_set_output(req, &dst, out_len_max);
+ kpp_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
+ tcrypt_complete, &result);
+ err = wait_async_op(&result,
+ crypto_kpp_compute_shared_secret(req));
+ if (err) {
+ pr_err("alg: %s: Party B: compute shared secret failed. err %d\n",
+ alg, err);
+ goto free_all;
+ }
+
+ shared_secret = a_ss;
+ } else {
+ shared_secret = (void *)vec->expected_ss;
+ }
+
/*
* verify shared secret from which the user will derive
* secret key by executing whatever hash it has chosen
*/
- if (memcmp(vec->expected_ss, sg_virt(req->dst),
+ if (memcmp(shared_secret, sg_virt(req->dst),
vec->expected_ss_size)) {
pr_err("alg: %s: compute shared secret test failed. Invalid output\n",
alg);
@@ -2074,8 +2126,10 @@ static int do_test_kpp(struct crypto_kpp *tfm, const struct kpp_testvec *vec,
}
free_all:
+ kfree(a_ss);
kfree(input_buf);
free_output:
+ kfree(a_public);
kfree(output_buf);
free_req:
kpp_request_free(req);
diff --git a/crypto/testmgr.h b/crypto/testmgr.h
index 4293573..a6c6b24 100644
--- a/crypto/testmgr.h
+++ b/crypto/testmgr.h
@@ -137,13 +137,16 @@ struct akcipher_testvec {
struct kpp_testvec {
const unsigned char *secret;
+ const unsigned char *b_secret;
const unsigned char *b_public;
const unsigned char *expected_a_public;
const unsigned char *expected_ss;
unsigned short secret_size;
+ unsigned short b_secret_size;
unsigned short b_public_size;
unsigned short expected_a_public_size;
unsigned short expected_ss_size;
+ bool genkey;
};
static const char zeroed_string[48];
@@ -752,6 +755,114 @@ static const struct kpp_testvec dh_tv_template[] = {
.b_public_size = 256,
.expected_a_public_size = 256,
.expected_ss_size = 256,
+ },
+ {
+ .secret =
+#ifdef __LITTLE_ENDIAN
+ "\x01\x00" /* type */
+ "\x11\x01" /* len */
+ "\x00\x00\x00\x00" /* key_size */
+ "\x00\x01\x00\x00" /* p_size */
+ "\x01\x00\x00\x00" /* g_size */
+#else
+ "\x00\x01" /* type */
+ "\x01\x11" /* len */
+ "\x00\x00\x00\x00" /* key_size */
+ "\x00\x00\x01\x00" /* p_size */
+ "\x00\x00\x00\x01" /* g_size */
+#endif
+ /* p */
+ "\xb9\x36\x3a\xf1\x82\x1f\x60\xd3\x22\x47\xb8\xbc\x2d\x22\x6b\x81"
+ "\x7f\xe8\x20\x06\x09\x23\x73\x49\x9a\x59\x8b\x35\x25\xf8\x31\xbc"
+ "\x7d\xa8\x1c\x9d\x56\x0d\x1a\xf7\x4b\x4f\x96\xa4\x35\x77\x6a\x89"
+ "\xab\x42\x00\x49\x21\x71\xed\x28\x16\x1d\x87\x5a\x10\xa7\x9c\x64"
+ "\x94\xd4\x87\x3d\x28\xef\x44\xfe\x4b\xe2\xb4\x15\x8c\x82\xa6\xf3"
+ "\x50\x5f\xa8\xe8\xa2\x60\xe7\x00\x86\x78\x05\xd4\x78\x19\xa1\x98"
+ "\x62\x4e\x4a\x00\x78\x56\x96\xe6\xcf\xd7\x10\x1b\x74\x5d\xd0\x26"
+ "\x61\xdb\x6b\x32\x09\x51\xd8\xa5\xfd\x54\x16\x71\x01\xb3\x39\xe6"
+ "\x4e\x69\xb1\xd7\x06\x8f\xd6\x1e\xdc\x72\x25\x26\x74\xc8\x41\x06"
+ "\x5c\xd1\x26\x5c\xb0\x2f\xf9\x59\x13\xc1\x2a\x0f\x78\xea\x7b\xf7"
+ "\xbd\x59\xa0\x90\x1d\xfc\x33\x5b\x4c\xbf\x05\x9c\x3a\x3f\x69\xa2"
+ "\x45\x61\x4e\x10\x6a\xb3\x17\xc5\x68\x30\xfb\x07\x5f\x34\xc6\xfb"
+ "\x73\x07\x3c\x70\xf6\xae\xe7\x72\x84\xc3\x18\x81\x8f\xe8\x11\x1f"
+ "\x3d\x83\x83\x01\x2a\x14\x73\xbf\x32\x32\x2e\xc9\x4d\xdb\x2a\xca"
+ "\xee\x71\xf9\xda\xad\xe8\x82\x0b\x4d\x0c\x1f\xb6\x1d\xef\x00\x67"
+ "\x74\x3d\x95\xe0\xb7\xc4\x30\x8a\x24\x87\x12\x47\x27\x70\x0d\x73"
+ /* g */
+ "\x02",
+ .b_secret =
+#ifdef __LITTLE_ENDIAN
+ "\x01\x00" /* type */
+ "\x11\x02" /* len */
+ "\x00\x01\x00\x00" /* key_size */
+ "\x00\x01\x00\x00" /* p_size */
+ "\x01\x00\x00\x00" /* g_size */
+#else
+ "\x00\x01" /* type */
+ "\x02\x11" /* len */
+ "\x00\x00\x01\x00" /* key_size */
+ "\x00\x00\x01\x00" /* p_size */
+ "\x00\x00\x00\x01" /* g_size */
+#endif
+ /* xa */
+ "\x4d\x75\xa8\x6e\xba\x23\x3a\x0c\x63\x56\xc8\xc9\x5a\xa7\xd6\x0e"
+ "\xed\xae\x40\x78\x87\x47\x5f\xe0\xa7\x7b\xba\x84\x88\x67\x4e\xe5"
+ "\x3c\xcc\x5c\x6a\xe7\x4a\x20\xec\xbe\xcb\xf5\x52\x62\x9f\x37\x80"
+ "\x0c\x72\x7b\x83\x66\xa4\xf6\x7f\x95\x97\x1c\x6a\x5c\x7e\xf1\x67"
+ "\x37\xb3\x93\x39\x3d\x0b\x55\x35\xd9\xe5\x22\x04\x9f\xf8\xc1\x04"
+ "\xce\x13\xa5\xac\xe1\x75\x05\xd1\x2b\x53\xa2\x84\xef\xb1\x18\xf4"
+ "\x66\xdd\xea\xe6\x24\x69\x5a\x49\xe0\x7a\xd8\xdf\x1b\xb7\xf1\x6d"
+ "\x9b\x50\x2c\xc8\x1c\x1c\xa3\xb4\x37\xfb\x66\x3f\x67\x71\x73\xa9"
+ "\xff\x5f\xd9\xa2\x25\x6e\x25\x1b\x26\x54\xbf\x0c\xc6\xdb\xea\x0a"
+ "\x52\x6c\x16\x7c\x27\x68\x15\x71\x58\x73\x9d\xe6\xc2\x80\xaa\x97"
+ "\x31\x66\xfb\xa6\xfb\xfd\xd0\x9c\x1d\xbe\x81\x48\xf5\x9a\x32\xf1"
+ "\x69\x62\x18\x78\xae\x72\x36\xe6\x94\x27\xd1\xff\x18\x4f\x28\x6a"
+ "\x16\xbd\x6a\x60\xee\xe5\xf9\x6d\x16\xe4\xb8\xa6\x41\x9b\x23\x7e"
+ "\xf7\x9d\xd1\x1d\x03\x15\x66\x3a\xcf\xb6\x2c\x13\x96\x2c\x52\x21"
+ "\xe4\x2d\x48\x7a\x8a\x5d\xb2\x88\xed\x98\x61\x79\x8b\x6a\x1e\x5f"
+ "\xd0\x8a\x2d\x99\x5a\x2b\x0f\xbc\xef\x53\x8f\x32\xc1\xa2\x99\x26"
+ /* p */
+ "\xb9\x36\x3a\xf1\x82\x1f\x60\xd3\x22\x47\xb8\xbc\x2d\x22\x6b\x81"
+ "\x7f\xe8\x20\x06\x09\x23\x73\x49\x9a\x59\x8b\x35\x25\xf8\x31\xbc"
+ "\x7d\xa8\x1c\x9d\x56\x0d\x1a\xf7\x4b\x4f\x96\xa4\x35\x77\x6a\x89"
+ "\xab\x42\x00\x49\x21\x71\xed\x28\x16\x1d\x87\x5a\x10\xa7\x9c\x64"
+ "\x94\xd4\x87\x3d\x28\xef\x44\xfe\x4b\xe2\xb4\x15\x8c\x82\xa6\xf3"
+ "\x50\x5f\xa8\xe8\xa2\x60\xe7\x00\x86\x78\x05\xd4\x78\x19\xa1\x98"
+ "\x62\x4e\x4a\x00\x78\x56\x96\xe6\xcf\xd7\x10\x1b\x74\x5d\xd0\x26"
+ "\x61\xdb\x6b\x32\x09\x51\xd8\xa5\xfd\x54\x16\x71\x01\xb3\x39\xe6"
+ "\x4e\x69\xb1\xd7\x06\x8f\xd6\x1e\xdc\x72\x25\x26\x74\xc8\x41\x06"
+ "\x5c\xd1\x26\x5c\xb0\x2f\xf9\x59\x13\xc1\x2a\x0f\x78\xea\x7b\xf7"
+ "\xbd\x59\xa0\x90\x1d\xfc\x33\x5b\x4c\xbf\x05\x9c\x3a\x3f\x69\xa2"
+ "\x45\x61\x4e\x10\x6a\xb3\x17\xc5\x68\x30\xfb\x07\x5f\x34\xc6\xfb"
+ "\x73\x07\x3c\x70\xf6\xae\xe7\x72\x84\xc3\x18\x81\x8f\xe8\x11\x1f"
+ "\x3d\x83\x83\x01\x2a\x14\x73\xbf\x32\x32\x2e\xc9\x4d\xdb\x2a\xca"
+ "\xee\x71\xf9\xda\xad\xe8\x82\x0b\x4d\x0c\x1f\xb6\x1d\xef\x00\x67"
+ "\x74\x3d\x95\xe0\xb7\xc4\x30\x8a\x24\x87\x12\x47\x27\x70\x0d\x73"
+ /* g */
+ "\x02",
+ .b_public =
+ "\x90\x89\xe4\x82\xd6\x0a\xcf\x1a\xae\xce\x1b\x66\xa7\x19\x71\x18"
+ "\x8f\x95\x4b\x5b\x80\x45\x4a\x5a\x43\x99\x4d\x37\xcf\xa3\xa7\x28"
+ "\x9c\xc7\x73\xf1\xb2\x17\xf6\x99\xe3\x6b\x56\xcb\x3e\x35\x60\x7d"
+ "\x65\xc7\x84\x6b\x3e\x60\xee\xcd\xd2\x70\xe7\xc9\x32\x1c\xf0\xb4"
+ "\xf9\x52\xd9\x88\x75\xfd\x40\x2c\xa7\xbe\x19\x1c\x0a\xae\x93\xe1"
+ "\x71\xc7\xcd\x4f\x33\x5c\x10\x7d\x39\x56\xfc\x73\x84\xb2\x67\xc3"
+ "\x77\x26\x20\x97\x2b\xf8\x13\x43\x93\x9c\x9a\xa4\x08\xc7\x34\x83"
+ "\xe6\x98\x61\xe7\x16\x30\x2c\xb1\xdb\x2a\xb2\xcc\xc3\x02\xa5\x3c"
+ "\x71\x50\x14\x83\xc7\xbb\xa4\xbe\x98\x1b\xfe\xcb\x43\xe9\x97\x62"
+ "\xd6\xf0\x8c\xcb\x1c\xba\x1e\xa8\xa6\xa6\x50\xfc\x85\x7d\x47\xbf"
+ "\xf4\x3e\x23\xd3\x5f\xb2\x71\x3e\x40\x94\xaa\x87\x83\x2c\x6c\x8e"
+ "\x60\xfd\xdd\xf7\xf4\x76\x03\xd3\x1d\xec\x18\x51\xa3\xf2\x44\x1a"
+ "\x3f\xb4\x7c\x18\x0d\x68\x65\x92\x54\x0d\x2d\x81\x16\xf1\x84\x66"
+ "\x89\x92\xd0\x1a\x5e\x1f\x42\x46\x5b\xe5\x83\x86\x80\xd9\xcd\x3a"
+ "\x5a\x2f\xb9\x59\x9b\xe4\x43\x84\x64\xf3\x09\x1a\x0a\xa2\x64\x0f"
+ "\x77\x4e\x8d\x8b\xe6\x88\xd1\xfc\xaf\x8f\xdf\x1d\xbc\x31\xb3\xbd",
+ .secret_size = 273,
+ .b_secret_size = 529,
+ .b_public_size = 256,
+ .expected_a_public_size = 256,
+ .expected_ss_size = 256,
+ .genkey = true,
}
};
@@ -840,6 +951,50 @@ static const struct kpp_testvec ecdh_tv_template[] = {
.b_public_size = 64,
.expected_a_public_size = 64,
.expected_ss_size = 32
+ }, {
+ .secret =
+#ifdef __LITTLE_ENDIAN
+ "\x02\x00" /* type */
+ "\x08\x00" /* len */
+ "\x02\x00" /* curve_id */
+ "\x00\x00", /* key_size */
+#else
+ "\x00\x02" /* type */
+ "\x00\x08" /* len */
+ "\x00\x02" /* curve_id */
+ "\x00\x00", /* key_size */
+#endif
+ .b_secret =
+#ifdef __LITTLE_ENDIAN
+ "\x02\x00" /* type */
+ "\x28\x00" /* len */
+ "\x02\x00" /* curve_id */
+ "\x20\x00" /* key_size */
+#else
+ "\x00\x02" /* type */
+ "\x00\x28" /* len */
+ "\x00\x02" /* curve_id */
+ "\x00\x20" /* key_size */
+#endif
+ "\x24\xd1\x21\xeb\xe5\xcf\x2d\x83"
+ "\xf6\x62\x1b\x6e\x43\x84\x3a\xa3"
+ "\x8b\xe0\x86\xc3\x20\x19\xda\x92"
+ "\x50\x53\x03\xe1\xc0\xea\xb8\x82",
+ .b_public =
+ "\x1a\x7f\xeb\x52\x00\xbd\x3c\x31"
+ "\x7d\xb6\x70\xc1\x86\xa6\xc7\xc4"
+ "\x3b\xc5\x5f\x6c\x6f\x58\x3c\xf5"
+ "\xb6\x63\x82\x77\x33\x24\xa1\x5f"
+ "\x6a\xca\x43\x6f\xf7\x7e\xff\x02"
+ "\x37\x08\xcc\x40\x5e\x7a\xfd\x6a"
+ "\x6a\x02\x6e\x41\x87\x68\x38\x77"
+ "\xfa\xa9\x44\x43\x2d\xef\x09\xdf",
+ .secret_size = 8,
+ .b_secret_size = 40,
+ .b_public_size = 64,
+ .expected_a_public_size = 64,
+ .expected_ss_size = 32,
+ .genkey = true,
}
};
--
2.7.4
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [RFC PATCH v2 4/4] crypto: testmgr - add genkey kpp test
2017-05-17 15:26 ` [RFC PATCH v2 4/4] crypto: testmgr - add genkey kpp test Tudor Ambarus
@ 2017-05-26 13:44 ` Tudor Ambarus
2017-05-28 18:57 ` Stephan Müller
1 sibling, 0 replies; 14+ messages in thread
From: Tudor Ambarus @ 2017-05-26 13:44 UTC (permalink / raw)
To: herbert, davem; +Cc: linux-crypto, smueller, marcel, Nicolas.Ferre
On 17.05.2017 18:26, Tudor Ambarus wrote:
> The test considers a party that already has a private-public
> key pair and a party that provides a NULL key. The kernel will
> generate the private-public key pair for the latter, computes
> the shared secret on both ends and verifies it it's the same.
>
> The explicit private-public key pairs were copied from
> the previous test vectors.
>
> Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
> ---
> crypto/testmgr.c | 76 +++++++++++++++++++++++----
> crypto/testmgr.h | 155 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 220 insertions(+), 11 deletions(-)
>
> diff --git a/crypto/testmgr.c b/crypto/testmgr.c
> index 6f5f3ed..faf5fd8 100644
> --- a/crypto/testmgr.c
> +++ b/crypto/testmgr.c
> @@ -1997,6 +1997,9 @@ static int do_test_kpp(struct crypto_kpp *tfm, const struct kpp_testvec *vec,
> struct kpp_request *req;
> void *input_buf = NULL;
> void *output_buf = NULL;
> + void *a_public = NULL;
> + void *a_ss = NULL;
> + void *shared_secret = NULL;
> struct tcrypt_result result;
> unsigned int out_len_max;
> int err = -ENOMEM;
> @@ -2026,20 +2029,31 @@ static int do_test_kpp(struct crypto_kpp *tfm, const struct kpp_testvec *vec,
> kpp_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
> tcrypt_complete, &result);
>
> - /* Compute public key */
> + /* Compute party A's public key */
> err = wait_async_op(&result, crypto_kpp_generate_public_key(req));
> if (err) {
> - pr_err("alg: %s: generate public key test failed. err %d\n",
> + pr_err("alg: %s: Party A: generate public key test failed. err %d\n",
> alg, err);
> goto free_output;
> }
> - /* Verify calculated public key */
> - if (memcmp(vec->expected_a_public, sg_virt(req->dst),
> - vec->expected_a_public_size)) {
> - pr_err("alg: %s: generate public key test failed. Invalid output\n",
> - alg);
> - err = -EINVAL;
> - goto free_output;
> +
> + if (vec->genkey) {
> + /* Save party A's public key */
> + a_public = kzalloc(out_len_max, GFP_KERNEL);
> + if (!a_public) {
> + err = -ENOMEM;
> + goto free_output;
> + }
> + memcpy(a_public, sg_virt(req->dst), sizeof(*a_public));
The size is wrong, I'll correct it in the next version.
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [RFC PATCH v2 1/4] crypto: ecc - add privkey generation support
2017-05-17 15:26 ` [RFC PATCH v2 1/4] crypto: ecc " Tudor Ambarus
@ 2017-05-28 18:44 ` Stephan Müller
2017-05-29 9:08 ` Tudor Ambarus
0 siblings, 1 reply; 14+ messages in thread
From: Stephan Müller @ 2017-05-28 18:44 UTC (permalink / raw)
To: Tudor Ambarus; +Cc: herbert, davem, linux-crypto, marcel, Nicolas.Ferre
Am Mittwoch, 17. Mai 2017, 17:26:50 CEST schrieb Tudor Ambarus:
Hi Tudor,
> Add support for generating ecc private keys.
>
> Generation of ecc private keys is helpful in a user-space to kernel
> ecdh offload because the keys are not revealed to user-space. Private
> key generation is also helpful to implement forward secrecy.
>
> Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
> ---
> crypto/ecc.c | 20 ++++++++++++++++++++
> crypto/ecc.h | 14 ++++++++++++++
> 2 files changed, 34 insertions(+)
>
> diff --git a/crypto/ecc.c b/crypto/ecc.c
> index 414c78a..a591907 100644
> --- a/crypto/ecc.c
> +++ b/crypto/ecc.c
> @@ -927,6 +927,26 @@ int ecc_is_key_valid(unsigned int curve_id, unsigned
> int ndigits, return 0;
> }
>
> +int ecc_gen_privkey(unsigned int curve_id, unsigned int ndigits, u64
> *privkey) +{
> + const struct ecc_curve *curve = ecc_get_curve(curve_id);
Shouldn't there be a check that a curve is selected? I.e. a check for an error
should be added?
> + u64 priv[ndigits];
Shouldn't there be a size check of ndigits?
> + unsigned int nbytes = ndigits << ECC_DIGITS_TO_BYTES_SHIFT;
> +
> + get_random_bytes(priv, nbytes);
Can you please use crypto_get_default_rng / crypto_rng_get_bytes /
crypto_put_default_rng?
> +
> + if (vli_is_zero(priv, ndigits))
> + return -EINVAL;
> +
> + /* Make sure the private key is in the range [1, n-1]. */
> + if (vli_cmp(curve->n, priv, ndigits) != 1)
> + return -EINVAL;
> +
> + ecc_swap_digits(priv, privkey, ndigits);
Is a byteswap faster than a copy operation by looping through priv/privkey and
simply assinging the value?
> +
> + return 0;
> +}
> +
> int ecdh_make_pub_key(unsigned int curve_id, unsigned int ndigits,
> const u8 *private_key, unsigned int private_key_len,
> u8 *public_key, unsigned int public_key_len)
> diff --git a/crypto/ecc.h b/crypto/ecc.h
> index 663d598..b94b7ce 100644
> --- a/crypto/ecc.h
> +++ b/crypto/ecc.h
> @@ -44,6 +44,20 @@ int ecc_is_key_valid(unsigned int curve_id, unsigned int
> ndigits, const u8 *private_key, unsigned int private_key_len);
>
> /**
> + * ecc_gen_privkey() - Generates an ECC private key.
> + * The private key is a random integer in the range 0 < random < n, where n
> is a + * prime that is the order of the cyclic subgroup generated by the
> distinguished + * point G.
> + * @curve_id: id representing the curve to use
> + * @ndigits: curve number of digits
> + * @private_key: buffer for storing the generated private key
> + *
> + * Returns 0 if the private key was generated successfully, a negative
> value + * if an error occurred.
> + */
> +int ecc_gen_privkey(unsigned int curve_id, unsigned int ndigits, u64
> *privkey); +
> +/**
> * ecdh_make_pub_key() - Compute an ECC public key
> *
> * @curve_id: id representing the curve to use
Ciao
Stephan
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [RFC PATCH v2 3/4] crypto: dh - allow user to provide NULL privkey
2017-05-17 15:26 ` [RFC PATCH v2 3/4] crypto: dh " Tudor Ambarus
@ 2017-05-28 18:50 ` Stephan Müller
0 siblings, 0 replies; 14+ messages in thread
From: Stephan Müller @ 2017-05-28 18:50 UTC (permalink / raw)
To: Tudor Ambarus; +Cc: herbert, davem, linux-crypto, marcel, Nicolas.Ferre
Am Mittwoch, 17. Mai 2017, 17:26:52 CEST schrieb Tudor Ambarus:
Hi Tudor,
> If the user provides a NULL private key, the kernel will
> generate it and further use it for dh.
>
> Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
> ---
> crypto/dh.c | 21 +++++++++++++++++++++
> 1 file changed, 21 insertions(+)
>
> diff --git a/crypto/dh.c b/crypto/dh.c
> index 87e3542..7b4ac5b 100644
> --- a/crypto/dh.c
> +++ b/crypto/dh.c
> @@ -83,7 +83,9 @@ static int dh_set_secret(struct crypto_kpp *tfm, const
> void *buf, unsigned int len)
> {
> struct dh_ctx *ctx = dh_get_ctx(tfm);
> + u8 *rndbuf = NULL;
> struct dh params;
> + int maxsize;
>
> if (crypto_dh_decode_key(buf, len, ¶ms) < 0)
> return -EINVAL;
> @@ -91,7 +93,26 @@ static int dh_set_secret(struct crypto_kpp *tfm, const
> void *buf, if (dh_set_params(ctx, ¶ms) < 0)
> return -EINVAL;
>
> + if (!params.key || !params.key_size) {
> + maxsize = crypto_kpp_maxsize(tfm);
> + if (maxsize < 0) {
> + dh_clear_params(ctx);
> + return maxsize;
> + }
> +
> + rndbuf = kmalloc(maxsize, GFP_KERNEL);
> + if (!rndbuf) {
> + dh_clear_params(ctx);
> + return -ENOMEM;
> + }
> +
> + get_random_bytes(rndbuf, maxsize);
Could you please use again the kernel crypto API RNG as mentioned for ECC?
> + params.key = rndbuf;
> + params.key_size = maxsize;
> + }
> +
> ctx->xa = mpi_read_raw_data(params.key, params.key_size);
> + kzfree(rndbuf);
> if (!ctx->xa) {
> dh_clear_params(ctx);
> return -EINVAL;
Ciao
Stephan
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [RFC PATCH v2 4/4] crypto: testmgr - add genkey kpp test
2017-05-17 15:26 ` [RFC PATCH v2 4/4] crypto: testmgr - add genkey kpp test Tudor Ambarus
2017-05-26 13:44 ` Tudor Ambarus
@ 2017-05-28 18:57 ` Stephan Müller
1 sibling, 0 replies; 14+ messages in thread
From: Stephan Müller @ 2017-05-28 18:57 UTC (permalink / raw)
To: Tudor Ambarus; +Cc: herbert, davem, linux-crypto, marcel, Nicolas.Ferre
Am Mittwoch, 17. Mai 2017, 17:26:53 CEST schrieb Tudor Ambarus:
Hi Tudor,
> The test considers a party that already has a private-public
> key pair and a party that provides a NULL key. The kernel will
> generate the private-public key pair for the latter, computes
> the shared secret on both ends and verifies it it's the same.
>
> The explicit private-public key pairs were copied from
> the previous test vectors.
>
> Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
> ---
> crypto/testmgr.c | 76 +++++++++++++++++++++++----
> crypto/testmgr.h | 155
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed,
> 220 insertions(+), 11 deletions(-)
>
> diff --git a/crypto/testmgr.c b/crypto/testmgr.c
> index 6f5f3ed..faf5fd8 100644
> --- a/crypto/testmgr.c
> +++ b/crypto/testmgr.c
> @@ -1997,6 +1997,9 @@ static int do_test_kpp(struct crypto_kpp *tfm, const
> struct kpp_testvec *vec, struct kpp_request *req;
> void *input_buf = NULL;
> void *output_buf = NULL;
> + void *a_public = NULL;
> + void *a_ss = NULL;
> + void *shared_secret = NULL;
> struct tcrypt_result result;
> unsigned int out_len_max;
> int err = -ENOMEM;
> @@ -2026,20 +2029,31 @@ static int do_test_kpp(struct crypto_kpp *tfm, const
> struct kpp_testvec *vec, kpp_request_set_callback(req,
> CRYPTO_TFM_REQ_MAY_BACKLOG,
> tcrypt_complete, &result);
>
> - /* Compute public key */
> + /* Compute party A's public key */
> err = wait_async_op(&result, crypto_kpp_generate_public_key(req));
> if (err) {
> - pr_err("alg: %s: generate public key test failed. err %d\n",
> + pr_err("alg: %s: Party A: generate public key test failed. err %d\n",
> alg, err);
> goto free_output;
> }
> - /* Verify calculated public key */
> - if (memcmp(vec->expected_a_public, sg_virt(req->dst),
> - vec->expected_a_public_size)) {
> - pr_err("alg: %s: generate public key test failed. Invalid output\n",
> - alg);
> - err = -EINVAL;
> - goto free_output;
> +
> + if (vec->genkey) {
> + /* Save party A's public key */
> + a_public = kzalloc(out_len_max, GFP_KERNEL);
> + if (!a_public) {
> + err = -ENOMEM;
> + goto free_output;
> + }
> + memcpy(a_public, sg_virt(req->dst), sizeof(*a_public));
As you mentioned, sizeof() may not be the right length.
> + } else {
> + /* Verify calculated public key */
> + if (memcmp(vec->expected_a_public, sg_virt(req->dst),
> + vec->expected_a_public_size)) {
> + pr_err("alg: %s: Party A: generate public key test failed. Invalid
> output\n", + alg);
> + err = -EINVAL;
> + goto free_output;
> + }
> }
>
> /* Calculate shared secret key by using counter part (b) public key. */
> @@ -2058,15 +2072,53 @@ static int do_test_kpp(struct crypto_kpp *tfm, const
> struct kpp_testvec *vec, tcrypt_complete, &result);
> err = wait_async_op(&result, crypto_kpp_compute_shared_secret(req));
> if (err) {
> - pr_err("alg: %s: compute shard secret test failed. err %d\n",
> + pr_err("alg: %s: Party A: compute shared secret test failed. err %d
\n",
> alg, err);
> goto free_all;
> }
> +
> + if (vec->genkey) {
> + /* Save the shared secret obtained by party A */
> + a_ss = kzalloc(vec->expected_ss_size, GFP_KERNEL);
> + if (!a_ss) {
> + err = -ENOMEM;
> + goto free_all;
> + }
> + memcpy(a_ss, sg_virt(req->dst), sizeof(*a_ss));
Same here, sizeof(void *)?
> +
> + /*
> + * Calculate party B's shared secret by using party A's
> + * public key.
> + */
> + err = crypto_kpp_set_secret(tfm, vec->b_secret,
> + vec->b_secret_size);
> + if (err < 0)
> + goto free_all;
> +
> + sg_init_one(&src, a_public, vec->expected_a_public_size);
> + sg_init_one(&dst, output_buf, out_len_max);
> + kpp_request_set_input(req, &src, vec->expected_a_public_size);
> + kpp_request_set_output(req, &dst, out_len_max);
> + kpp_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
> + tcrypt_complete, &result);
> + err = wait_async_op(&result,
> + crypto_kpp_compute_shared_secret(req));
> + if (err) {
> + pr_err("alg: %s: Party B: compute shared secret failed. err %d\n",
> + alg, err);
> + goto free_all;
> + }
> +
> + shared_secret = a_ss;
> + } else {
> + shared_secret = (void *)vec->expected_ss;
> + }
> +
> /*
> * verify shared secret from which the user will derive
> * secret key by executing whatever hash it has chosen
> */
> - if (memcmp(vec->expected_ss, sg_virt(req->dst),
> + if (memcmp(shared_secret, sg_virt(req->dst),
> vec->expected_ss_size)) {
> pr_err("alg: %s: compute shared secret test failed. Invalid output\n",
> alg);
> @@ -2074,8 +2126,10 @@ static int do_test_kpp(struct crypto_kpp *tfm, const
> struct kpp_testvec *vec, }
>
> free_all:
> + kfree(a_ss);
> kfree(input_buf);
> free_output:
> + kfree(a_public);
> kfree(output_buf);
> free_req:
> kpp_request_free(req);
> diff --git a/crypto/testmgr.h b/crypto/testmgr.h
> index 4293573..a6c6b24 100644
> --- a/crypto/testmgr.h
> +++ b/crypto/testmgr.h
> @@ -137,13 +137,16 @@ struct akcipher_testvec {
>
> struct kpp_testvec {
> const unsigned char *secret;
> + const unsigned char *b_secret;
> const unsigned char *b_public;
> const unsigned char *expected_a_public;
> const unsigned char *expected_ss;
> unsigned short secret_size;
> + unsigned short b_secret_size;
> unsigned short b_public_size;
> unsigned short expected_a_public_size;
> unsigned short expected_ss_size;
> + bool genkey;
> };
>
> static const char zeroed_string[48];
> @@ -752,6 +755,114 @@ static const struct kpp_testvec dh_tv_template[] = {
> .b_public_size = 256,
> .expected_a_public_size = 256,
> .expected_ss_size = 256,
> + },
> + {
> + .secret =
> +#ifdef __LITTLE_ENDIAN
> + "\x01\x00" /* type */
> + "\x11\x01" /* len */
> + "\x00\x00\x00\x00" /* key_size */
> + "\x00\x01\x00\x00" /* p_size */
> + "\x01\x00\x00\x00" /* g_size */
> +#else
> + "\x00\x01" /* type */
> + "\x01\x11" /* len */
> + "\x00\x00\x00\x00" /* key_size */
> + "\x00\x00\x01\x00" /* p_size */
> + "\x00\x00\x00\x01" /* g_size */
> +#endif
> + /* p */
> + "\xb9\x36\x3a\xf1\x82\x1f\x60\xd3\x22\x47\xb8\xbc\x2d\x22\x6b\x81"
> + "\x7f\xe8\x20\x06\x09\x23\x73\x49\x9a\x59\x8b\x35\x25\xf8\x31\xbc"
> + "\x7d\xa8\x1c\x9d\x56\x0d\x1a\xf7\x4b\x4f\x96\xa4\x35\x77\x6a\x89"
> + "\xab\x42\x00\x49\x21\x71\xed\x28\x16\x1d\x87\x5a\x10\xa7\x9c\x64"
> + "\x94\xd4\x87\x3d\x28\xef\x44\xfe\x4b\xe2\xb4\x15\x8c\x82\xa6\xf3"
> + "\x50\x5f\xa8\xe8\xa2\x60\xe7\x00\x86\x78\x05\xd4\x78\x19\xa1\x98"
> + "\x62\x4e\x4a\x00\x78\x56\x96\xe6\xcf\xd7\x10\x1b\x74\x5d\xd0\x26"
> + "\x61\xdb\x6b\x32\x09\x51\xd8\xa5\xfd\x54\x16\x71\x01\xb3\x39\xe6"
> + "\x4e\x69\xb1\xd7\x06\x8f\xd6\x1e\xdc\x72\x25\x26\x74\xc8\x41\x06"
> + "\x5c\xd1\x26\x5c\xb0\x2f\xf9\x59\x13\xc1\x2a\x0f\x78\xea\x7b\xf7"
> + "\xbd\x59\xa0\x90\x1d\xfc\x33\x5b\x4c\xbf\x05\x9c\x3a\x3f\x69\xa2"
> + "\x45\x61\x4e\x10\x6a\xb3\x17\xc5\x68\x30\xfb\x07\x5f\x34\xc6\xfb"
> + "\x73\x07\x3c\x70\xf6\xae\xe7\x72\x84\xc3\x18\x81\x8f\xe8\x11\x1f"
> + "\x3d\x83\x83\x01\x2a\x14\x73\xbf\x32\x32\x2e\xc9\x4d\xdb\x2a\xca"
> + "\xee\x71\xf9\xda\xad\xe8\x82\x0b\x4d\x0c\x1f\xb6\x1d\xef\x00\x67"
> + "\x74\x3d\x95\xe0\xb7\xc4\x30\x8a\x24\x87\x12\x47\x27\x70\x0d\x73"
> + /* g */
> + "\x02",
> + .b_secret =
> +#ifdef __LITTLE_ENDIAN
> + "\x01\x00" /* type */
> + "\x11\x02" /* len */
> + "\x00\x01\x00\x00" /* key_size */
> + "\x00\x01\x00\x00" /* p_size */
> + "\x01\x00\x00\x00" /* g_size */
> +#else
> + "\x00\x01" /* type */
> + "\x02\x11" /* len */
> + "\x00\x00\x01\x00" /* key_size */
> + "\x00\x00\x01\x00" /* p_size */
> + "\x00\x00\x00\x01" /* g_size */
> +#endif
> + /* xa */
> + "\x4d\x75\xa8\x6e\xba\x23\x3a\x0c\x63\x56\xc8\xc9\x5a\xa7\xd6\x0e"
> + "\xed\xae\x40\x78\x87\x47\x5f\xe0\xa7\x7b\xba\x84\x88\x67\x4e\xe5"
> + "\x3c\xcc\x5c\x6a\xe7\x4a\x20\xec\xbe\xcb\xf5\x52\x62\x9f\x37\x80"
> + "\x0c\x72\x7b\x83\x66\xa4\xf6\x7f\x95\x97\x1c\x6a\x5c\x7e\xf1\x67"
> + "\x37\xb3\x93\x39\x3d\x0b\x55\x35\xd9\xe5\x22\x04\x9f\xf8\xc1\x04"
> + "\xce\x13\xa5\xac\xe1\x75\x05\xd1\x2b\x53\xa2\x84\xef\xb1\x18\xf4"
> + "\x66\xdd\xea\xe6\x24\x69\x5a\x49\xe0\x7a\xd8\xdf\x1b\xb7\xf1\x6d"
> + "\x9b\x50\x2c\xc8\x1c\x1c\xa3\xb4\x37\xfb\x66\x3f\x67\x71\x73\xa9"
> + "\xff\x5f\xd9\xa2\x25\x6e\x25\x1b\x26\x54\xbf\x0c\xc6\xdb\xea\x0a"
> + "\x52\x6c\x16\x7c\x27\x68\x15\x71\x58\x73\x9d\xe6\xc2\x80\xaa\x97"
> + "\x31\x66\xfb\xa6\xfb\xfd\xd0\x9c\x1d\xbe\x81\x48\xf5\x9a\x32\xf1"
> + "\x69\x62\x18\x78\xae\x72\x36\xe6\x94\x27\xd1\xff\x18\x4f\x28\x6a"
> + "\x16\xbd\x6a\x60\xee\xe5\xf9\x6d\x16\xe4\xb8\xa6\x41\x9b\x23\x7e"
> + "\xf7\x9d\xd1\x1d\x03\x15\x66\x3a\xcf\xb6\x2c\x13\x96\x2c\x52\x21"
> + "\xe4\x2d\x48\x7a\x8a\x5d\xb2\x88\xed\x98\x61\x79\x8b\x6a\x1e\x5f"
> + "\xd0\x8a\x2d\x99\x5a\x2b\x0f\xbc\xef\x53\x8f\x32\xc1\xa2\x99\x26"
> + /* p */
> + "\xb9\x36\x3a\xf1\x82\x1f\x60\xd3\x22\x47\xb8\xbc\x2d\x22\x6b\x81"
> + "\x7f\xe8\x20\x06\x09\x23\x73\x49\x9a\x59\x8b\x35\x25\xf8\x31\xbc"
> + "\x7d\xa8\x1c\x9d\x56\x0d\x1a\xf7\x4b\x4f\x96\xa4\x35\x77\x6a\x89"
> + "\xab\x42\x00\x49\x21\x71\xed\x28\x16\x1d\x87\x5a\x10\xa7\x9c\x64"
> + "\x94\xd4\x87\x3d\x28\xef\x44\xfe\x4b\xe2\xb4\x15\x8c\x82\xa6\xf3"
> + "\x50\x5f\xa8\xe8\xa2\x60\xe7\x00\x86\x78\x05\xd4\x78\x19\xa1\x98"
> + "\x62\x4e\x4a\x00\x78\x56\x96\xe6\xcf\xd7\x10\x1b\x74\x5d\xd0\x26"
> + "\x61\xdb\x6b\x32\x09\x51\xd8\xa5\xfd\x54\x16\x71\x01\xb3\x39\xe6"
> + "\x4e\x69\xb1\xd7\x06\x8f\xd6\x1e\xdc\x72\x25\x26\x74\xc8\x41\x06"
> + "\x5c\xd1\x26\x5c\xb0\x2f\xf9\x59\x13\xc1\x2a\x0f\x78\xea\x7b\xf7"
> + "\xbd\x59\xa0\x90\x1d\xfc\x33\x5b\x4c\xbf\x05\x9c\x3a\x3f\x69\xa2"
> + "\x45\x61\x4e\x10\x6a\xb3\x17\xc5\x68\x30\xfb\x07\x5f\x34\xc6\xfb"
> + "\x73\x07\x3c\x70\xf6\xae\xe7\x72\x84\xc3\x18\x81\x8f\xe8\x11\x1f"
> + "\x3d\x83\x83\x01\x2a\x14\x73\xbf\x32\x32\x2e\xc9\x4d\xdb\x2a\xca"
> + "\xee\x71\xf9\xda\xad\xe8\x82\x0b\x4d\x0c\x1f\xb6\x1d\xef\x00\x67"
> + "\x74\x3d\x95\xe0\xb7\xc4\x30\x8a\x24\x87\x12\x47\x27\x70\x0d\x73"
> + /* g */
> + "\x02",
> + .b_public =
> + "\x90\x89\xe4\x82\xd6\x0a\xcf\x1a\xae\xce\x1b\x66\xa7\x19\x71\x18"
> + "\x8f\x95\x4b\x5b\x80\x45\x4a\x5a\x43\x99\x4d\x37\xcf\xa3\xa7\x28"
> + "\x9c\xc7\x73\xf1\xb2\x17\xf6\x99\xe3\x6b\x56\xcb\x3e\x35\x60\x7d"
> + "\x65\xc7\x84\x6b\x3e\x60\xee\xcd\xd2\x70\xe7\xc9\x32\x1c\xf0\xb4"
> + "\xf9\x52\xd9\x88\x75\xfd\x40\x2c\xa7\xbe\x19\x1c\x0a\xae\x93\xe1"
> + "\x71\xc7\xcd\x4f\x33\x5c\x10\x7d\x39\x56\xfc\x73\x84\xb2\x67\xc3"
> + "\x77\x26\x20\x97\x2b\xf8\x13\x43\x93\x9c\x9a\xa4\x08\xc7\x34\x83"
> + "\xe6\x98\x61\xe7\x16\x30\x2c\xb1\xdb\x2a\xb2\xcc\xc3\x02\xa5\x3c"
> + "\x71\x50\x14\x83\xc7\xbb\xa4\xbe\x98\x1b\xfe\xcb\x43\xe9\x97\x62"
> + "\xd6\xf0\x8c\xcb\x1c\xba\x1e\xa8\xa6\xa6\x50\xfc\x85\x7d\x47\xbf"
> + "\xf4\x3e\x23\xd3\x5f\xb2\x71\x3e\x40\x94\xaa\x87\x83\x2c\x6c\x8e"
> + "\x60\xfd\xdd\xf7\xf4\x76\x03\xd3\x1d\xec\x18\x51\xa3\xf2\x44\x1a"
> + "\x3f\xb4\x7c\x18\x0d\x68\x65\x92\x54\x0d\x2d\x81\x16\xf1\x84\x66"
> + "\x89\x92\xd0\x1a\x5e\x1f\x42\x46\x5b\xe5\x83\x86\x80\xd9\xcd\x3a"
> + "\x5a\x2f\xb9\x59\x9b\xe4\x43\x84\x64\xf3\x09\x1a\x0a\xa2\x64\x0f"
> + "\x77\x4e\x8d\x8b\xe6\x88\xd1\xfc\xaf\x8f\xdf\x1d\xbc\x31\xb3\xbd",
> + .secret_size = 273,
> + .b_secret_size = 529,
> + .b_public_size = 256,
> + .expected_a_public_size = 256,
> + .expected_ss_size = 256,
> + .genkey = true,
> }
> };
>
> @@ -840,6 +951,50 @@ static const struct kpp_testvec ecdh_tv_template[] = {
> .b_public_size = 64,
> .expected_a_public_size = 64,
> .expected_ss_size = 32
> + }, {
> + .secret =
> +#ifdef __LITTLE_ENDIAN
> + "\x02\x00" /* type */
> + "\x08\x00" /* len */
> + "\x02\x00" /* curve_id */
> + "\x00\x00", /* key_size */
> +#else
> + "\x00\x02" /* type */
> + "\x00\x08" /* len */
> + "\x00\x02" /* curve_id */
> + "\x00\x00", /* key_size */
> +#endif
> + .b_secret =
> +#ifdef __LITTLE_ENDIAN
> + "\x02\x00" /* type */
> + "\x28\x00" /* len */
> + "\x02\x00" /* curve_id */
> + "\x20\x00" /* key_size */
> +#else
> + "\x00\x02" /* type */
> + "\x00\x28" /* len */
> + "\x00\x02" /* curve_id */
> + "\x00\x20" /* key_size */
> +#endif
> + "\x24\xd1\x21\xeb\xe5\xcf\x2d\x83"
> + "\xf6\x62\x1b\x6e\x43\x84\x3a\xa3"
> + "\x8b\xe0\x86\xc3\x20\x19\xda\x92"
> + "\x50\x53\x03\xe1\xc0\xea\xb8\x82",
> + .b_public =
> + "\x1a\x7f\xeb\x52\x00\xbd\x3c\x31"
> + "\x7d\xb6\x70\xc1\x86\xa6\xc7\xc4"
> + "\x3b\xc5\x5f\x6c\x6f\x58\x3c\xf5"
> + "\xb6\x63\x82\x77\x33\x24\xa1\x5f"
> + "\x6a\xca\x43\x6f\xf7\x7e\xff\x02"
> + "\x37\x08\xcc\x40\x5e\x7a\xfd\x6a"
> + "\x6a\x02\x6e\x41\x87\x68\x38\x77"
> + "\xfa\xa9\x44\x43\x2d\xef\x09\xdf",
> + .secret_size = 8,
> + .b_secret_size = 40,
> + .b_public_size = 64,
> + .expected_a_public_size = 64,
> + .expected_ss_size = 32,
> + .genkey = true,
> }
> };
Ciao
Stephan
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [RFC PATCH v2 1/4] crypto: ecc - add privkey generation support
2017-05-28 18:44 ` Stephan Müller
@ 2017-05-29 9:08 ` Tudor Ambarus
2017-05-29 9:23 ` Stephan Müller
0 siblings, 1 reply; 14+ messages in thread
From: Tudor Ambarus @ 2017-05-29 9:08 UTC (permalink / raw)
To: Stephan Müller; +Cc: herbert, davem, linux-crypto, marcel, Nicolas.Ferre
Hi, Stephan,
Thank you for the review. Please see inline.
On 28.05.2017 21:44, Stephan Müller wrote:
> Am Mittwoch, 17. Mai 2017, 17:26:50 CEST schrieb Tudor Ambarus:
>
> Hi Tudor,
>
>> Add support for generating ecc private keys.
>>
>> Generation of ecc private keys is helpful in a user-space to kernel
>> ecdh offload because the keys are not revealed to user-space. Private
>> key generation is also helpful to implement forward secrecy.
>>
>> Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
>> ---
>> crypto/ecc.c | 20 ++++++++++++++++++++
>> crypto/ecc.h | 14 ++++++++++++++
>> 2 files changed, 34 insertions(+)
>>
>> diff --git a/crypto/ecc.c b/crypto/ecc.c
>> index 414c78a..a591907 100644
>> --- a/crypto/ecc.c
>> +++ b/crypto/ecc.c
>> @@ -927,6 +927,26 @@ int ecc_is_key_valid(unsigned int curve_id, unsigned
>> int ndigits, return 0;
>> }
>>
>> +int ecc_gen_privkey(unsigned int curve_id, unsigned int ndigits, u64
>> *privkey) +{
>> + const struct ecc_curve *curve = ecc_get_curve(curve_id);
>
> Shouldn't there be a check that a curve is selected? I.e. a check for an error
> should be added?
We already checked the curve_id before generating the key. The function
assumes that curve_id is checked before calling it, like
ecc_is_key_valid() does.
>
>> + u64 priv[ndigits];
>
> Shouldn't there be a size check of ndigits?
Already checked when setting the secret. But FIPS 186-4, B.4.1
recommends to check the bit length of n. It should be greater or equal
with 160. I will add this check, thanks.
>
>> + unsigned int nbytes = ndigits << ECC_DIGITS_TO_BYTES_SHIFT;
>> +
>> + get_random_bytes(priv, nbytes);
>
> Can you please use crypto_get_default_rng / crypto_rng_get_bytes /
> crypto_put_default_rng?
Actually I tried this and I encountered some problems, I'm currently
debugging it.
When using the default rng and the run-time self tests are enabled,
the kernel is in a blocking state. What's worse is that the kernel
blocks before the console has the chance to be enabled and I can't see
anything :).
I suspect that the kernel blocks because the rng does not have enough
entropy. Could you please give me some hints?
>> +
>> + if (vli_is_zero(priv, ndigits))
>> + return -EINVAL;
>> +
>> + /* Make sure the private key is in the range [1, n-1]. */
>> + if (vli_cmp(curve->n, priv, ndigits) != 1)
>> + return -EINVAL;
>> +
>> + ecc_swap_digits(priv, privkey, ndigits);
>
> Is a byteswap faster than a copy operation by looping through priv/privkey and
> simply assinging the value?
Maybe not, but I am consistent with the rest of the code. Can we change
this in a latter patch, if necessary?
Thanks,
ta
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [RFC PATCH v2 1/4] crypto: ecc - add privkey generation support
2017-05-29 9:08 ` Tudor Ambarus
@ 2017-05-29 9:23 ` Stephan Müller
2017-05-29 9:47 ` Tudor Ambarus
0 siblings, 1 reply; 14+ messages in thread
From: Stephan Müller @ 2017-05-29 9:23 UTC (permalink / raw)
To: Tudor Ambarus; +Cc: herbert, davem, linux-crypto, marcel, Nicolas.Ferre
Am Montag, 29. Mai 2017, 11:08:38 CEST schrieb Tudor Ambarus:
Hi Tudor,
>
> >> + unsigned int nbytes = ndigits << ECC_DIGITS_TO_BYTES_SHIFT;
> >> +
> >> + get_random_bytes(priv, nbytes);
> >
> > Can you please use crypto_get_default_rng / crypto_rng_get_bytes /
> > crypto_put_default_rng?
>
> Actually I tried this and I encountered some problems, I'm currently
> debugging it.
>
> When using the default rng and the run-time self tests are enabled,
> the kernel is in a blocking state. What's worse is that the kernel
> blocks before the console has the chance to be enabled and I can't see
> anything :).
>
> I suspect that the kernel blocks because the rng does not have enough
> entropy. Could you please give me some hints?
Hm, there should be no blocking for the DRBG to initialize.
What happens if you compile that as a module and insmod it at runtime?
>
> >> +
> >> + if (vli_is_zero(priv, ndigits))
> >> + return -EINVAL;
> >> +
> >> + /* Make sure the private key is in the range [1, n-1]. */
> >> + if (vli_cmp(curve->n, priv, ndigits) != 1)
> >> + return -EINVAL;
> >> +
> >> + ecc_swap_digits(priv, privkey, ndigits);
> >
> > Is a byteswap faster than a copy operation by looping through priv/privkey
> > and simply assinging the value?
>
> Maybe not, but I am consistent with the rest of the code. Can we change
> this in a latter patch, if necessary?
Ok, fine with me.
Ciao
Stephan
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [RFC PATCH v2 1/4] crypto: ecc - add privkey generation support
2017-05-29 9:23 ` Stephan Müller
@ 2017-05-29 9:47 ` Tudor Ambarus
2017-05-29 9:56 ` Stephan Müller
0 siblings, 1 reply; 14+ messages in thread
From: Tudor Ambarus @ 2017-05-29 9:47 UTC (permalink / raw)
To: Stephan Müller; +Cc: herbert, davem, linux-crypto, marcel, Nicolas.Ferre
Hi, Stephan,
On 29.05.2017 12:23, Stephan Müller wrote:
> Am Montag, 29. Mai 2017, 11:08:38 CEST schrieb Tudor Ambarus:
>
> Hi Tudor,
>>
>>>> + unsigned int nbytes = ndigits << ECC_DIGITS_TO_BYTES_SHIFT;
>>>> +
>>>> + get_random_bytes(priv, nbytes);
>>>
>>> Can you please use crypto_get_default_rng / crypto_rng_get_bytes /
>>> crypto_put_default_rng?
>>
>> Actually I tried this and I encountered some problems, I'm currently
>> debugging it.
>>
>> When using the default rng and the run-time self tests are enabled,
>> the kernel is in a blocking state. What's worse is that the kernel
>> blocks before the console has the chance to be enabled and I can't see
>> anything :).
>>
>> I suspect that the kernel blocks because the rng does not have enough
>> entropy. Could you please give me some hints?
>
> Hm, there should be no blocking for the DRBG to initialize.
>
> What happens if you compile that as a module and insmod it at runtime?
We will have a nop:
#ifdef CONFIG_CRYPTO_MANAGER_DISABLE_TESTS
/* a perfect nop */
int alg_test(const char *driver, const char *alg, u32 type, u32 mask)
{
printk(KERN_ERR "no op in alg_test");
return 0;
}
#else
...
#endif
If I further mangle it and change #ifdef with #ifndef then the tests are
passing.
Thanks,
ta
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [RFC PATCH v2 1/4] crypto: ecc - add privkey generation support
2017-05-29 9:47 ` Tudor Ambarus
@ 2017-05-29 9:56 ` Stephan Müller
2017-05-29 13:27 ` Tudor Ambarus
0 siblings, 1 reply; 14+ messages in thread
From: Stephan Müller @ 2017-05-29 9:56 UTC (permalink / raw)
To: Tudor Ambarus; +Cc: herbert, davem, linux-crypto, marcel, Nicolas.Ferre
Am Montag, 29. Mai 2017, 11:47:48 CEST schrieb Tudor Ambarus:
Hi Tudor,
> > Hm, there should be no blocking for the DRBG to initialize.
> >
> > What happens if you compile that as a module and insmod it at runtime?
>
> We will have a nop:
>
> #ifdef CONFIG_CRYPTO_MANAGER_DISABLE_TESTS
>
> /* a perfect nop */
> int alg_test(const char *driver, const char *alg, u32 type, u32 mask)
> {
> printk(KERN_ERR "no op in alg_test");
> return 0;
> }
>
> #else
> ...
> #endif
>
> If I further mangle it and change #ifdef with #ifndef then the tests are
> passing.
Can you please enable the testmgr in the kernel config and compile the DH/ECDH
code as a module. Then I would insmod the dh/ecdh kernel module to see whether
the self tests work or not.
Note, if you use the calls of crypto_get_default_rng and friends, the DRBG
must be present in the kernel at the time of calling. I.e. if you statically
compile dh/ecdh but compile the RNG support as a module, the RNG will not load
during self test. If you compile dh/ecdh as a module, the RNG can stay as a
module.
Ciao
Stephan
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [RFC PATCH v2 1/4] crypto: ecc - add privkey generation support
2017-05-29 9:56 ` Stephan Müller
@ 2017-05-29 13:27 ` Tudor Ambarus
0 siblings, 0 replies; 14+ messages in thread
From: Tudor Ambarus @ 2017-05-29 13:27 UTC (permalink / raw)
To: Stephan Müller; +Cc: herbert, davem, linux-crypto, marcel, Nicolas.Ferre
Hi, Stephan,
On 29.05.2017 12:56, Stephan Müller wrote:
> Am Montag, 29. Mai 2017, 11:47:48 CEST schrieb Tudor Ambarus:
>
> Hi Tudor,
>
>>> Hm, there should be no blocking for the DRBG to initialize.
>>>
>>> What happens if you compile that as a module and insmod it at runtime?
>>
>> We will have a nop:
>>
>> #ifdef CONFIG_CRYPTO_MANAGER_DISABLE_TESTS
>>
>> /* a perfect nop */
>> int alg_test(const char *driver, const char *alg, u32 type, u32 mask)
>> {
>> printk(KERN_ERR "no op in alg_test");
>> return 0;
>> }
>>
>> #else
>> ...
>> #endif
>>
>> If I further mangle it and change #ifdef with #ifndef then the tests are
>> passing.
>
> Can you please enable the testmgr in the kernel config and compile the DH/ECDH
> code as a module. Then I would insmod the dh/ecdh kernel module to see whether
> the self tests work or not.
dh/ecdh self tests are passing when I insert dh/ecdh modules.
>
> Note, if you use the calls of crypto_get_default_rng and friends, the DRBG
> must be present in the kernel at the time of calling. I.e. if you statically
> compile dh/ecdh but compile the RNG support as a module, the RNG will not load
> during self test. If you compile dh/ecdh as a module, the RNG can stay as a
> module.
However, when the self tests are enabled and DH/ECDH code is built-in,
the kernel blocks.
I have to ensure that the drivers are loaded in the right order.
Deferring the probe or just simply changing the order of the object
files from crypto/Makefile solves the issue. I'll go with the second
approach.
Thanks,
ta
^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2017-05-29 13:27 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-05-17 15:26 [RFC PATCH v2 0/4] crypto: (ec)dh - add privkey generation support Tudor Ambarus
2017-05-17 15:26 ` [RFC PATCH v2 1/4] crypto: ecc " Tudor Ambarus
2017-05-28 18:44 ` Stephan Müller
2017-05-29 9:08 ` Tudor Ambarus
2017-05-29 9:23 ` Stephan Müller
2017-05-29 9:47 ` Tudor Ambarus
2017-05-29 9:56 ` Stephan Müller
2017-05-29 13:27 ` Tudor Ambarus
2017-05-17 15:26 ` [RFC PATCH v2 2/4] crypto: ecdh - allow user to provide NULL privkey Tudor Ambarus
2017-05-17 15:26 ` [RFC PATCH v2 3/4] crypto: dh " Tudor Ambarus
2017-05-28 18:50 ` Stephan Müller
2017-05-17 15:26 ` [RFC PATCH v2 4/4] crypto: testmgr - add genkey kpp test Tudor Ambarus
2017-05-26 13:44 ` Tudor Ambarus
2017-05-28 18:57 ` Stephan Müller
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.