diff mbox

[02/10] crypto: rsa_helper - add raw integer parser actions

Message ID 1458325927-14737-2-git-send-email-tudor-dan.ambarus@nxp.com (mailing list archive)
State Changes Requested
Delegated to: Herbert Xu
Headers show

Commit Message

Tudor Ambarus March 18, 2016, 6:31 p.m. UTC
Dedicated to RSA (hardware) implementations that want to use
raw integers instead of MPI keys.

Signed-off-by: Tudor Ambarus <tudor-dan.ambarus@nxp.com>
---
 crypto/rsa.c                  |  15 ----
 crypto/rsa_helper.c           | 158 ++++++++++++++++++++++++++++++++++++++++++
 include/crypto/internal/rsa.h |  24 +++++++
 3 files changed, 182 insertions(+), 15 deletions(-)

Comments

Stephan Mueller March 18, 2016, 7:46 p.m. UTC | #1
Am Freitag, 18. März 2016, 20:31:59 schrieb Tudor Ambarus:

Hi Tudor,

> Dedicated to RSA (hardware) implementations that want to use
> raw integers instead of MPI keys.
> 
> Signed-off-by: Tudor Ambarus <tudor-dan.ambarus@nxp.com>
> ---
>  crypto/rsa.c                  |  15 ----
>  crypto/rsa_helper.c           | 158
> ++++++++++++++++++++++++++++++++++++++++++ include/crypto/internal/rsa.h | 
> 24 +++++++
>  3 files changed, 182 insertions(+), 15 deletions(-)
> 
> diff --git a/crypto/rsa.c b/crypto/rsa.c
> index 2d53ad8..44baccf 100644
> --- a/crypto/rsa.c
> +++ b/crypto/rsa.c
> @@ -235,21 +235,6 @@ err_free_m:
>  	return ret;
>  }
> 
> -static int rsa_check_key_length(unsigned int len)
> -{
> -	switch (len) {
> -	case 512:
> -	case 1024:
> -	case 1536:
> -	case 2048:
> -	case 3072:
> -	case 4096:
> -		return 0;
> -	}
> -
> -	return -EINVAL;
> -}
> -
>  static int rsa_set_pub_key(struct crypto_akcipher *tfm, const void *key,
>  			   unsigned int keylen)
>  {
> diff --git a/crypto/rsa_helper.c b/crypto/rsa_helper.c
> index 1ed32af..1708db8 100644
> --- a/crypto/rsa_helper.c
> +++ b/crypto/rsa_helper.c
> @@ -14,6 +14,9 @@
>  #include <linux/export.h>
>  #include <linux/err.h>
>  #include <linux/fips.h>
> +#include <linux/slab.h>
> +#include <linux/dma-mapping.h>
> +#include <linux/device.h>
>  #include <crypto/internal/rsa.h>
>  #include "rsapubkey-asn1.h"
>  #include "rsaprivkey-asn1.h"
> @@ -190,3 +193,158 @@ void set_rsa_priv_action(struct rsa_asn1_action
> *action) action->get_n = rsa_get_mpi_n;
>  }
>  EXPORT_SYMBOL_GPL(set_rsa_priv_action);
> +
> +int rsa_check_key_length(unsigned int len)
> +{
> +	switch (len) {
> +	case 512:
> +	case 1024:
> +	case 1536:
> +	case 2048:
> +	case 3072:
> +	case 4096:
> +		return 0;
> +	}

I know that you copied the code to a new location that was there already. But 
based on the discussion we had for DH, does it make sense that the kernel adds 
such (artificial) limits?
> +
> +	return -EINVAL;
> +}
> +EXPORT_SYMBOL_GPL(rsa_check_key_length);
> +
> +int raw_rsa_get_n(void *context, size_t hdrlen, unsigned char tag,
> +		  const void *value, size_t vlen)
> +{
> +	struct rsa_raw_ctx *ctx = context;
> +	struct rsa_raw_key *key = &ctx->key;
> +	const char *ptr = value;
> +	int ret = -EINVAL;
> +
> +	while (!*ptr && vlen) {
> +		ptr++;
> +		vlen--;
> +	}
> +
> +	key->n_sz = vlen;
> +	/* In FIPS mode only allow key size 2K & 3K */
> +	if (fips_enabled && (key->n_sz != 256 && key->n_sz != 384)) {

Again, you copied that code that used to be there . But very very recently, 
NIST allowed 4k keys too. May I ask to allow it here?

> +		dev_err(ctx->dev, "RSA: key size not allowed in FIPS mode\n");
> +		goto err;
> +	}
> +	/* invalid key size provided */
> +	ret = rsa_check_key_length(key->n_sz << 3);
> +	if (ret)
> +		goto err;
> +
> +	if (key->is_coherent)
> +		key->n = kzalloc(key->n_sz, key->flags);
> +	else
> +		key->n = dma_zalloc_coherent(ctx->dev, key->n_sz, &key->dma_n,
> +					     key->flags);
> +
> +	if (!key->n) {
> +		ret = -ENOMEM;
> +		goto err;
> +	}
> +
> +	memcpy(key->n, ptr, key->n_sz);
> +
> +	return 0;
> +err:
> +	key->n_sz = 0;
> +	key->n = NULL;
> +	return ret;
> +}
> +
> +int raw_rsa_get_e(void *context, size_t hdrlen, unsigned char tag,
> +		  const void *value, size_t vlen)
> +{
> +	struct rsa_raw_ctx *ctx = context;
> +	struct rsa_raw_key *key = &ctx->key;
> +	const char *ptr = value;
> +
> +	while (!*ptr && vlen) {
> +		ptr++;
> +		vlen--;
> +	}
> +
> +	key->e_sz = vlen;
> +
> +	if (!key->n_sz || !vlen || vlen > key->n_sz) {
> +		key->e = NULL;
> +		return -EINVAL;
> +	}
> +
> +	if (key->is_coherent)
> +		key->e = kzalloc(key->e_sz, key->flags);
> +	else
> +		key->e = dma_zalloc_coherent(ctx->dev, key->n_sz, &key->dma_e,
> +					     key->flags);
> +
> +	if (!key->e)
> +		return -ENOMEM;
> +
> +	if (key->is_coherent)
> +		memcpy(key->e, ptr, key->e_sz);
> +	else
> +		memcpy(key->e + (key->n_sz - vlen), ptr, vlen);
> +
> +	return 0;
> +}
> +
> +int raw_rsa_get_d(void *context, size_t hdrlen, unsigned char tag,
> +		  const void *value, size_t vlen)
> +{
> +	struct rsa_raw_ctx *ctx = context;
> +	struct rsa_raw_key *key = &ctx->key;
> +	const char *ptr = value;
> +	int ret = -EINVAL;
> +
> +	while (!*ptr && vlen) {
> +		ptr++;
> +		vlen--;
> +	}
> +
> +	if (!key->n_sz || !vlen || vlen > key->n_sz)
> +		goto err;
> +
> +	/* In FIPS mode only allow key size 2K & 3K */
> +	if (fips_enabled && (vlen != 256 && vlen != 384)) {
> +		dev_err(ctx->dev, "RSA: key size not allowed in FIPS mode\n");
> +		goto err;
> +	}
> +
> +	if (key->is_coherent)
> +		key->d = kzalloc(key->n_sz, key->flags);
> +	else
> +		key->d = dma_zalloc_coherent(ctx->dev, key->n_sz, &key->dma_d,
> +					     key->flags);
> +
> +	if (!key->n) {
> +		ret = -ENOMEM;
> +		goto err;
> +	}
> +
> +	if (key->is_coherent)
> +		memcpy(key->d, ptr, vlen);
> +	else
> +		memcpy(key->d + (key->n_sz - vlen), ptr, vlen);
> +
> +	return 0;
> +err:
> +	key->d = NULL;
> +	return ret;
> +}
> +
> +void set_raw_rsa_pub_action(struct rsa_asn1_action *action)
> +{
> +	action->get_e = raw_rsa_get_e;
> +	action->get_n = raw_rsa_get_n;
> +}
> +EXPORT_SYMBOL_GPL(set_raw_rsa_pub_action);
> +
> +void set_raw_rsa_priv_action(struct rsa_asn1_action *action)
> +{
> +	action->get_d = raw_rsa_get_d;
> +	action->get_e = raw_rsa_get_e;
> +	action->get_n = raw_rsa_get_n;
> +}
> +EXPORT_SYMBOL_GPL(set_raw_rsa_priv_action);
> diff --git a/include/crypto/internal/rsa.h b/include/crypto/internal/rsa.h
> index bf0f49d..7820e83 100644
> --- a/include/crypto/internal/rsa.h
> +++ b/include/crypto/internal/rsa.h
> @@ -20,6 +20,19 @@ struct rsa_mpi_key {
>  	MPI d;
>  };
> 
> +struct rsa_raw_key {
> +	u8 *n;
> +	u8 *e;
> +	u8 *d;
> +	dma_addr_t dma_n;
> +	dma_addr_t dma_e;
> +	dma_addr_t dma_d;
> +	size_t n_sz;
> +	size_t e_sz;
> +	bool is_coherent;
> +	gfp_t flags;
> +};
> +
>  struct rsa_asn1_action {
>  	int (*get_n)(void *context, size_t hdrlen, unsigned char tag,
>  		     const void *value, size_t vlen);
> @@ -34,6 +47,12 @@ struct rsa_ctx {
>  	struct rsa_mpi_key key;
>  };
> 
> +struct rsa_raw_ctx {
> +	struct rsa_asn1_action action;
> +	struct rsa_raw_key key;
> +	struct device *dev;
> +};
> +
>  void rsa_free_mpi_key(struct rsa_mpi_key *key);
> 
>  int rsa_parse_mpi_pub_key(struct rsa_ctx *ctx, const void *key,
> @@ -44,5 +63,10 @@ int rsa_parse_mpi_priv_key(struct rsa_ctx *ctx, const
> void *key, void set_rsa_pub_action(struct rsa_asn1_action *action);
>  void set_rsa_priv_action(struct rsa_asn1_action *action);
> 
> +int rsa_check_key_length(unsigned int len);
> +
> +void set_raw_rsa_pub_action(struct rsa_asn1_action *action);
> +void set_raw_rsa_priv_action(struct rsa_asn1_action *action);
> +
>  extern struct crypto_template rsa_pkcs1pad_tmpl;
>  #endif


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
Tudor Ambarus March 21, 2016, 3:17 p.m. UTC | #2
Hi Stephan,


> -----Original Message-----
> From: Stephan Mueller [mailto:smueller@chronox.de]
> Sent: Friday, March 18, 2016 9:47 PM
> To: Tudor-Dan Ambarus
> Cc: herbert@gondor.apana.org.au; tadeusz.struk@intel.com; linux-
> crypto@vger.kernel.org; Horia Ioan Geanta Neag
> Subject: Re: [PATCH 02/10] crypto: rsa_helper - add raw integer parser
> actions
> 
> > +int rsa_check_key_length(unsigned int len)
> > +{
> > +	switch (len) {
> > +	case 512:
> > +	case 1024:
> > +	case 1536:
> > +	case 2048:
> > +	case 3072:
> > +	case 4096:
> > +		return 0;
> > +	}
> 
> I know that you copied the code to a new location that was there already.
> But
> based on the discussion we had for DH, does it make sense that the kernel
> adds
> such (artificial) limits?

[ta] This is not within the scope of this patch set, but we can remove the restrictions in a subsequent patch. Marcel has suggested to not impose limits on the minimum length of the key. What about the maximum?

> > +
> > +	return -EINVAL;
> > +}
> > +EXPORT_SYMBOL_GPL(rsa_check_key_length);
> > +
> > +int raw_rsa_get_n(void *context, size_t hdrlen, unsigned char tag,
> > +		  const void *value, size_t vlen)
> > +{
> > +	struct rsa_raw_ctx *ctx = context;
> > +	struct rsa_raw_key *key = &ctx->key;
> > +	const char *ptr = value;
> > +	int ret = -EINVAL;
> > +
> > +	while (!*ptr && vlen) {
> > +		ptr++;
> > +		vlen--;
> > +	}
> > +
> > +	key->n_sz = vlen;
> > +	/* In FIPS mode only allow key size 2K & 3K */
> > +	if (fips_enabled && (key->n_sz != 256 && key->n_sz != 384)) {
> 
> Again, you copied that code that used to be there . But very very recently,
> NIST allowed 4k keys too. May I ask to allow it here?
> 

I suggest to do this in a separate patch. Can you send us a pointer to the NIST specification?

Thank you,
ta
--
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
Stephan Mueller March 21, 2016, 7:14 p.m. UTC | #3
Am Montag, 21. März 2016, 15:17:20 schrieb Tudor-Dan Ambarus:

Hi Tudor,

> Hi Stephan,
> 
> > -----Original Message-----
> > From: Stephan Mueller [mailto:smueller@chronox.de]
> > Sent: Friday, March 18, 2016 9:47 PM
> > To: Tudor-Dan Ambarus
> > Cc: herbert@gondor.apana.org.au; tadeusz.struk@intel.com; linux-
> > crypto@vger.kernel.org; Horia Ioan Geanta Neag
> > Subject: Re: [PATCH 02/10] crypto: rsa_helper - add raw integer parser
> > actions
> > 
> > > +int rsa_check_key_length(unsigned int len)
> > > +{
> > > +	switch (len) {
> > > +	case 512:
> > > +	case 1024:
> > > +	case 1536:
> > > +	case 2048:
> > > +	case 3072:
> > > +	case 4096:
> > > +		return 0;
> > > +	}
> > 
> > I know that you copied the code to a new location that was there already.
> > But
> > based on the discussion we had for DH, does it make sense that the kernel
> > adds
> > such (artificial) limits?
> 
> [ta] This is not within the scope of this patch set, but we can remove the
> restrictions in a subsequent patch. Marcel has suggested to not impose
> limits on the minimum length of the key. What about the maximum?

Why any restrictions at all? There is no mathematical reason. There is only a 
technical reason which depends on the implementation.

I am not sure how large the keys can be for the software fallback. But maybe 
it would make sense to have a general cap like 32k where the software fallback 
can handle all key sizes up to that point.

> > > +
> > > +	return -EINVAL;
> > > +}
> > > +EXPORT_SYMBOL_GPL(rsa_check_key_length);
> > > +
> > > +int raw_rsa_get_n(void *context, size_t hdrlen, unsigned char tag,
> > > +		  const void *value, size_t vlen)
> > > +{
> > > +	struct rsa_raw_ctx *ctx = context;
> > > +	struct rsa_raw_key *key = &ctx->key;
> > > +	const char *ptr = value;
> > > +	int ret = -EINVAL;
> > > +
> > > +	while (!*ptr && vlen) {
> > > +		ptr++;
> > > +		vlen--;
> > > +	}
> > > +
> > > +	key->n_sz = vlen;
> > > +	/* In FIPS mode only allow key size 2K & 3K */
> > > +	if (fips_enabled && (key->n_sz != 256 && key->n_sz != 384)) {
> > 
> > Again, you copied that code that used to be there . But very very
> > recently,
> > NIST allowed 4k keys too. May I ask to allow it here?
> 
> I suggest to do this in a separate patch. Can you send us a pointer to the
> NIST specification?

Sure, just let us not forget about it.
> 
> Thank you,
> ta


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
diff mbox

Patch

diff --git a/crypto/rsa.c b/crypto/rsa.c
index 2d53ad8..44baccf 100644
--- a/crypto/rsa.c
+++ b/crypto/rsa.c
@@ -235,21 +235,6 @@  err_free_m:
 	return ret;
 }
 
-static int rsa_check_key_length(unsigned int len)
-{
-	switch (len) {
-	case 512:
-	case 1024:
-	case 1536:
-	case 2048:
-	case 3072:
-	case 4096:
-		return 0;
-	}
-
-	return -EINVAL;
-}
-
 static int rsa_set_pub_key(struct crypto_akcipher *tfm, const void *key,
 			   unsigned int keylen)
 {
diff --git a/crypto/rsa_helper.c b/crypto/rsa_helper.c
index 1ed32af..1708db8 100644
--- a/crypto/rsa_helper.c
+++ b/crypto/rsa_helper.c
@@ -14,6 +14,9 @@ 
 #include <linux/export.h>
 #include <linux/err.h>
 #include <linux/fips.h>
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+#include <linux/device.h>
 #include <crypto/internal/rsa.h>
 #include "rsapubkey-asn1.h"
 #include "rsaprivkey-asn1.h"
@@ -190,3 +193,158 @@  void set_rsa_priv_action(struct rsa_asn1_action *action)
 	action->get_n = rsa_get_mpi_n;
 }
 EXPORT_SYMBOL_GPL(set_rsa_priv_action);
+
+int rsa_check_key_length(unsigned int len)
+{
+	switch (len) {
+	case 512:
+	case 1024:
+	case 1536:
+	case 2048:
+	case 3072:
+	case 4096:
+		return 0;
+	}
+
+	return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(rsa_check_key_length);
+
+int raw_rsa_get_n(void *context, size_t hdrlen, unsigned char tag,
+		  const void *value, size_t vlen)
+{
+	struct rsa_raw_ctx *ctx = context;
+	struct rsa_raw_key *key = &ctx->key;
+	const char *ptr = value;
+	int ret = -EINVAL;
+
+	while (!*ptr && vlen) {
+		ptr++;
+		vlen--;
+	}
+
+	key->n_sz = vlen;
+	/* In FIPS mode only allow key size 2K & 3K */
+	if (fips_enabled && (key->n_sz != 256 && key->n_sz != 384)) {
+		dev_err(ctx->dev, "RSA: key size not allowed in FIPS mode\n");
+		goto err;
+	}
+	/* invalid key size provided */
+	ret = rsa_check_key_length(key->n_sz << 3);
+	if (ret)
+		goto err;
+
+	if (key->is_coherent)
+		key->n = kzalloc(key->n_sz, key->flags);
+	else
+		key->n = dma_zalloc_coherent(ctx->dev, key->n_sz, &key->dma_n,
+					     key->flags);
+
+	if (!key->n) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	memcpy(key->n, ptr, key->n_sz);
+
+	return 0;
+err:
+	key->n_sz = 0;
+	key->n = NULL;
+	return ret;
+}
+
+int raw_rsa_get_e(void *context, size_t hdrlen, unsigned char tag,
+		  const void *value, size_t vlen)
+{
+	struct rsa_raw_ctx *ctx = context;
+	struct rsa_raw_key *key = &ctx->key;
+	const char *ptr = value;
+
+	while (!*ptr && vlen) {
+		ptr++;
+		vlen--;
+	}
+
+	key->e_sz = vlen;
+
+	if (!key->n_sz || !vlen || vlen > key->n_sz) {
+		key->e = NULL;
+		return -EINVAL;
+	}
+
+	if (key->is_coherent)
+		key->e = kzalloc(key->e_sz, key->flags);
+	else
+		key->e = dma_zalloc_coherent(ctx->dev, key->n_sz, &key->dma_e,
+					     key->flags);
+
+	if (!key->e)
+		return -ENOMEM;
+
+	if (key->is_coherent)
+		memcpy(key->e, ptr, key->e_sz);
+	else
+		memcpy(key->e + (key->n_sz - vlen), ptr, vlen);
+
+	return 0;
+}
+
+int raw_rsa_get_d(void *context, size_t hdrlen, unsigned char tag,
+		  const void *value, size_t vlen)
+{
+	struct rsa_raw_ctx *ctx = context;
+	struct rsa_raw_key *key = &ctx->key;
+	const char *ptr = value;
+	int ret = -EINVAL;
+
+	while (!*ptr && vlen) {
+		ptr++;
+		vlen--;
+	}
+
+	if (!key->n_sz || !vlen || vlen > key->n_sz)
+		goto err;
+
+	/* In FIPS mode only allow key size 2K & 3K */
+	if (fips_enabled && (vlen != 256 && vlen != 384)) {
+		dev_err(ctx->dev, "RSA: key size not allowed in FIPS mode\n");
+		goto err;
+	}
+
+	if (key->is_coherent)
+		key->d = kzalloc(key->n_sz, key->flags);
+	else
+		key->d = dma_zalloc_coherent(ctx->dev, key->n_sz, &key->dma_d,
+					     key->flags);
+
+	if (!key->n) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	if (key->is_coherent)
+		memcpy(key->d, ptr, vlen);
+	else
+		memcpy(key->d + (key->n_sz - vlen), ptr, vlen);
+
+	return 0;
+err:
+	key->d = NULL;
+	return ret;
+}
+
+void set_raw_rsa_pub_action(struct rsa_asn1_action *action)
+{
+	action->get_e = raw_rsa_get_e;
+	action->get_n = raw_rsa_get_n;
+}
+EXPORT_SYMBOL_GPL(set_raw_rsa_pub_action);
+
+void set_raw_rsa_priv_action(struct rsa_asn1_action *action)
+{
+	action->get_d = raw_rsa_get_d;
+	action->get_e = raw_rsa_get_e;
+	action->get_n = raw_rsa_get_n;
+}
+EXPORT_SYMBOL_GPL(set_raw_rsa_priv_action);
diff --git a/include/crypto/internal/rsa.h b/include/crypto/internal/rsa.h
index bf0f49d..7820e83 100644
--- a/include/crypto/internal/rsa.h
+++ b/include/crypto/internal/rsa.h
@@ -20,6 +20,19 @@  struct rsa_mpi_key {
 	MPI d;
 };
 
+struct rsa_raw_key {
+	u8 *n;
+	u8 *e;
+	u8 *d;
+	dma_addr_t dma_n;
+	dma_addr_t dma_e;
+	dma_addr_t dma_d;
+	size_t n_sz;
+	size_t e_sz;
+	bool is_coherent;
+	gfp_t flags;
+};
+
 struct rsa_asn1_action {
 	int (*get_n)(void *context, size_t hdrlen, unsigned char tag,
 		     const void *value, size_t vlen);
@@ -34,6 +47,12 @@  struct rsa_ctx {
 	struct rsa_mpi_key key;
 };
 
+struct rsa_raw_ctx {
+	struct rsa_asn1_action action;
+	struct rsa_raw_key key;
+	struct device *dev;
+};
+
 void rsa_free_mpi_key(struct rsa_mpi_key *key);
 
 int rsa_parse_mpi_pub_key(struct rsa_ctx *ctx, const void *key,
@@ -44,5 +63,10 @@  int rsa_parse_mpi_priv_key(struct rsa_ctx *ctx, const void *key,
 void set_rsa_pub_action(struct rsa_asn1_action *action);
 void set_rsa_priv_action(struct rsa_asn1_action *action);
 
+int rsa_check_key_length(unsigned int len);
+
+void set_raw_rsa_pub_action(struct rsa_asn1_action *action);
+void set_raw_rsa_priv_action(struct rsa_asn1_action *action);
+
 extern struct crypto_template rsa_pkcs1pad_tmpl;
 #endif