Re: [PATCH RFC v6 2/3] crypto: rsa: add a new rsa generic implementation

2015-06-16 Thread Herbert Xu
On Tue, Jun 16, 2015 at 01:02:05AM -0700, Tadeusz Struk wrote:
>
> + if (!pkey->n || !pkey->e || !req->dst_len)
> + return -EINVAL;

You leaked m.

> + if (*req->dst_len < mpi_get_size(pkey->n)) {
> + *req->dst_len = mpi_get_size(pkey->n);
> + return -EINVAL;
> + }

This needs to be an error that's distinct from real errors.  So
perhaps pick EOVERFLOW.

> +static int rsa_init_tfm(struct crypto_tfm *_tfm)
> +{
> + return 0;
> +}

The init function is optional.  So just drop it if there is nothing
to be done.

> + .encrypt = rsa_enc,
> + .decrypt = rsa_dec,
> + .sign = rsa_sign,
> + .verify = rsa_verify,
> + .setkey = rsa_setkey,
> + .base = {
> + .cra_name = "rsa",
> + .cra_driver_name = "rsa-generic",
> + .cra_priority = 100,
> + .cra_ctxsize = 0,
> + .cra_alignmask = 0,
> + .cra_module = THIS_MODULE,
> + .cra_ctxsize = sizeof(struct rsa_key),

You're initialising cra_ctxsize twice.  Also please drop the
alignmask since the default is zero.

> + .cra_init = rsa_init_tfm,
> + .cra_exit = rsa_exit_tfm,
> + },
> +};

Please drop cra_init/cra_exit and add type-safe init/exit functions
like I did in 5eb8ec6dc857d5027bc8cf7268a199107a583ae5

> diff --git a/crypto/rsa_helper.c b/crypto/rsa_helper.c
> new file mode 100644
> index 000..103dd2e
> --- /dev/null
> +++ b/crypto/rsa_helper.c
> @@ -0,0 +1,124 @@
> +/*
> + * RSA key extract helper
> + *
> + * Copyright (c) 2015, Intel Corporation
> + * Authors: Tadeusz Struk 
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License as published by the Free
> + * Software Foundation; either version 2 of the License, or (at your option)
> + * any later version.
> + *
> + */
> +#include 
> +#include 
> +#include "rsakey-asn1.h"

Need export.h.

> +static void free_mpis(struct rsa_key *key)
> +{
> + if (key->n)
> + mpi_free(key->n);

mpi_free already checks for NULL, so you can remove the check
here.

> diff --git a/include/crypto/internal/rsa.h b/include/crypto/internal/rsa.h
> new file mode 100644
> index 000..018f373
> --- /dev/null
> +++ b/include/crypto/internal/rsa.h
> @@ -0,0 +1,28 @@
> +/*
> + * RSA internal helpers
> + *
> + * Copyright (c) 2015, Intel Corporation
> + * Authors: Tadeusz Struk 
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License as published by the Free
> + * Software Foundation; either version 2 of the License, or (at your option)
> + * any later version.
> + *
> + */
> +#ifndef _RSA_HELPER_
> +#define _RSA_HELPER_
> +#include 
> +#include 

You should drop akcipher.h since nothing in this file uses it.

Thanks,
-- 
Email: Herbert Xu 
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH RFC v6 2/3] crypto: rsa: add a new rsa generic implementation

2015-06-16 Thread Tadeusz Struk
Add a new rsa generic SW implementation.
This implements only cryptographic primitives.

Signed-off-by: Tadeusz Struk 
---
 crypto/Kconfig|7 +
 crypto/Makefile   |8 +
 crypto/rsa.c  |  313 +
 crypto/rsa_helper.c   |  124 
 crypto/rsakey.asn1|5 +
 include/crypto/internal/rsa.h |   28 
 6 files changed, 485 insertions(+)
 create mode 100644 crypto/rsa.c
 create mode 100644 crypto/rsa_helper.c
 create mode 100644 crypto/rsakey.asn1
 create mode 100644 include/crypto/internal/rsa.h

diff --git a/crypto/Kconfig b/crypto/Kconfig
index 264dadb..52467cf 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -102,6 +102,13 @@ config CRYPTO_AKCIPHER
help
  Crypto API interface for public key algorithms.
 
+config CRYPTO_RSA
+   tristate "RSA algorithm"
+   select AKCIPHER
+   select MPILIB
+   help
+ Generic implementation of the RSA public key algorithm.
+
 config CRYPTO_MANAGER
tristate "Cryptographic algorithm manager"
select CRYPTO_MANAGER2
diff --git a/crypto/Makefile b/crypto/Makefile
index 6f2940a..c6217ea 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -30,6 +30,14 @@ obj-$(CONFIG_CRYPTO_HASH2) += crypto_hash.o
 obj-$(CONFIG_CRYPTO_PCOMP2) += pcompress.o
 obj-$(CONFIG_CRYPTO_AKCIPHER) += akcipher.o
 
+$(obj)/rsakey-asn1.o: $(obj)/rsakey-asn1.c $(obj)/rsakey-asn1.h
+clean-files += rsakey-asn1.c rsakey-asn1.h
+
+rsa_generic-y := rsakey-asn1.o
+rsa_generic-y += rsa.o
+rsa_generic-y += rsa_helper.o
+obj-$(CONFIG_CRYPTO_RSA) += rsa_generic.o
+
 cryptomgr-y := algboss.o testmgr.o
 
 obj-$(CONFIG_CRYPTO_MANAGER2) += cryptomgr.o
diff --git a/crypto/rsa.c b/crypto/rsa.c
new file mode 100644
index 000..33bb7f0
--- /dev/null
+++ b/crypto/rsa.c
@@ -0,0 +1,313 @@
+/* RSA asymmetric public-key algorithm [RFC3447]
+ *
+ * Copyright (c) 2015, Intel Corporation
+ * Authors: Tadeusz Struk 
+ *
+ * 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 
+#include 
+#include 
+#include 
+
+/*
+ * RSAEP function [RFC3447 sec 5.1.1]
+ * c = m^e mod n;
+ */
+static int _rsa_enc(const struct rsa_key *key, MPI c, MPI m)
+{
+   /* (1) Validate 0 <= m < n */
+   if (mpi_cmp_ui(m, 0) < 0 || mpi_cmp(m, key->n) >= 0)
+   return -EINVAL;
+
+   /* (2) c = m^e mod n */
+   return mpi_powm(c, m, key->e, key->n);
+}
+
+/*
+ * RSADP function [RFC3447 sec 5.1.2]
+ * m = c^d mod n;
+ */
+static int _rsa_dec(const struct rsa_key *key, MPI m, MPI c)
+{
+   /* (1) Validate 0 <= c < n */
+   if (mpi_cmp_ui(c, 0) < 0 || mpi_cmp(c, key->n) >= 0)
+   return -EINVAL;
+
+   /* (2) m = c^d mod n */
+   return mpi_powm(m, c, key->d, key->n);
+}
+
+/*
+ * RSASP1 function [RFC3447 sec 5.2.1]
+ * s = m^d mod n
+ */
+static int _rsa_sign(const struct rsa_key *key, MPI s, MPI m)
+{
+   /* (1) Validate 0 <= m < n */
+   if (mpi_cmp_ui(m, 0) < 0 || mpi_cmp(m, key->n) >= 0)
+   return -EINVAL;
+
+   /* (2) s = m^d mod n */
+   return mpi_powm(s, m, key->d, key->n);
+}
+
+/*
+ * RSAVP1 function [RFC3447 sec 5.2.2]
+ * m = s^e mod n;
+ */
+static int _rsa_verify(const struct rsa_key *key, MPI m, MPI s)
+{
+   /* (1) Validate 0 <= s < n */
+   if (mpi_cmp_ui(s, 0) < 0 || mpi_cmp(s, key->n) >= 0)
+   return -EINVAL;
+
+   /* (2) m = s^e mod n */
+   return mpi_powm(m, s, key->e, key->n);
+}
+
+static struct rsa_key *rsa_get_key(struct crypto_akcipher *tfm)
+{
+   return akcipher_tfm_ctx(tfm);
+}
+
+static int rsa_enc(struct akcipher_request *req)
+{
+   struct crypto_akcipher *tfm = akcipher_request_get_tfm(req);
+   const struct rsa_key *pkey = rsa_get_key(tfm);
+   MPI m, c = mpi_alloc(0);
+   int ret = 0;
+   int sign;
+
+   if (!c)
+   return -ENOMEM;
+
+   if (!pkey->n || !pkey->e || !req->dst_len)
+   return -EINVAL;
+
+   if (*req->dst_len < mpi_get_size(pkey->n)) {
+   *req->dst_len = mpi_get_size(pkey->n);
+   return -EINVAL;
+   }
+
+   m = mpi_read_raw_data(req->src, req->src_len);
+   if (!m) {
+   ret = -ENOMEM;
+   goto err_free_c;
+   }
+
+   ret = _rsa_enc(pkey, c, m);
+   if (ret)
+   goto err_free_m;
+
+   ret = mpi_read_buffer(c, req->dst, *req->dst_len, req->dst_len, );
+   if (ret)
+   goto err_free_m;
+
+   if (sign < 0) {
+   ret = -EBADMSG;
+   goto err_free_m;
+   }
+
+err_free_m:
+   mpi_free(m);
+err_free_c:
+   mpi_free(c);
+   return ret;
+}
+
+static int rsa_dec(struct akcipher_request *req)
+{
+   struct 

Re: [PATCH RFC v6 2/3] crypto: rsa: add a new rsa generic implementation

2015-06-16 Thread Herbert Xu
On Tue, Jun 16, 2015 at 01:02:05AM -0700, Tadeusz Struk wrote:

 + if (!pkey-n || !pkey-e || !req-dst_len)
 + return -EINVAL;

You leaked m.

 + if (*req-dst_len  mpi_get_size(pkey-n)) {
 + *req-dst_len = mpi_get_size(pkey-n);
 + return -EINVAL;
 + }

This needs to be an error that's distinct from real errors.  So
perhaps pick EOVERFLOW.

 +static int rsa_init_tfm(struct crypto_tfm *_tfm)
 +{
 + return 0;
 +}

The init function is optional.  So just drop it if there is nothing
to be done.

 + .encrypt = rsa_enc,
 + .decrypt = rsa_dec,
 + .sign = rsa_sign,
 + .verify = rsa_verify,
 + .setkey = rsa_setkey,
 + .base = {
 + .cra_name = rsa,
 + .cra_driver_name = rsa-generic,
 + .cra_priority = 100,
 + .cra_ctxsize = 0,
 + .cra_alignmask = 0,
 + .cra_module = THIS_MODULE,
 + .cra_ctxsize = sizeof(struct rsa_key),

You're initialising cra_ctxsize twice.  Also please drop the
alignmask since the default is zero.

 + .cra_init = rsa_init_tfm,
 + .cra_exit = rsa_exit_tfm,
 + },
 +};

Please drop cra_init/cra_exit and add type-safe init/exit functions
like I did in 5eb8ec6dc857d5027bc8cf7268a199107a583ae5

 diff --git a/crypto/rsa_helper.c b/crypto/rsa_helper.c
 new file mode 100644
 index 000..103dd2e
 --- /dev/null
 +++ b/crypto/rsa_helper.c
 @@ -0,0 +1,124 @@
 +/*
 + * RSA key extract helper
 + *
 + * Copyright (c) 2015, Intel Corporation
 + * Authors: Tadeusz Struk tadeusz.st...@intel.com
 + *
 + * This program is free software; you can redistribute it and/or modify it
 + * under the terms of the GNU General Public License as published by the Free
 + * Software Foundation; either version 2 of the License, or (at your option)
 + * any later version.
 + *
 + */
 +#include linux/fips.h
 +#include crypto/internal/rsa.h
 +#include rsakey-asn1.h

Need export.h.

 +static void free_mpis(struct rsa_key *key)
 +{
 + if (key-n)
 + mpi_free(key-n);

mpi_free already checks for NULL, so you can remove the check
here.

 diff --git a/include/crypto/internal/rsa.h b/include/crypto/internal/rsa.h
 new file mode 100644
 index 000..018f373
 --- /dev/null
 +++ b/include/crypto/internal/rsa.h
 @@ -0,0 +1,28 @@
 +/*
 + * RSA internal helpers
 + *
 + * Copyright (c) 2015, Intel Corporation
 + * Authors: Tadeusz Struk tadeusz.st...@intel.com
 + *
 + * This program is free software; you can redistribute it and/or modify it
 + * under the terms of the GNU General Public License as published by the Free
 + * Software Foundation; either version 2 of the License, or (at your option)
 + * any later version.
 + *
 + */
 +#ifndef _RSA_HELPER_
 +#define _RSA_HELPER_
 +#include linux/mpi.h
 +#include crypto/akcipher.h

You should drop akcipher.h since nothing in this file uses it.

Thanks,
-- 
Email: Herbert Xu herb...@gondor.apana.org.au
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH RFC v6 2/3] crypto: rsa: add a new rsa generic implementation

2015-06-16 Thread Tadeusz Struk
Add a new rsa generic SW implementation.
This implements only cryptographic primitives.

Signed-off-by: Tadeusz Struk tadeusz.st...@intel.com
---
 crypto/Kconfig|7 +
 crypto/Makefile   |8 +
 crypto/rsa.c  |  313 +
 crypto/rsa_helper.c   |  124 
 crypto/rsakey.asn1|5 +
 include/crypto/internal/rsa.h |   28 
 6 files changed, 485 insertions(+)
 create mode 100644 crypto/rsa.c
 create mode 100644 crypto/rsa_helper.c
 create mode 100644 crypto/rsakey.asn1
 create mode 100644 include/crypto/internal/rsa.h

diff --git a/crypto/Kconfig b/crypto/Kconfig
index 264dadb..52467cf 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -102,6 +102,13 @@ config CRYPTO_AKCIPHER
help
  Crypto API interface for public key algorithms.
 
+config CRYPTO_RSA
+   tristate RSA algorithm
+   select AKCIPHER
+   select MPILIB
+   help
+ Generic implementation of the RSA public key algorithm.
+
 config CRYPTO_MANAGER
tristate Cryptographic algorithm manager
select CRYPTO_MANAGER2
diff --git a/crypto/Makefile b/crypto/Makefile
index 6f2940a..c6217ea 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -30,6 +30,14 @@ obj-$(CONFIG_CRYPTO_HASH2) += crypto_hash.o
 obj-$(CONFIG_CRYPTO_PCOMP2) += pcompress.o
 obj-$(CONFIG_CRYPTO_AKCIPHER) += akcipher.o
 
+$(obj)/rsakey-asn1.o: $(obj)/rsakey-asn1.c $(obj)/rsakey-asn1.h
+clean-files += rsakey-asn1.c rsakey-asn1.h
+
+rsa_generic-y := rsakey-asn1.o
+rsa_generic-y += rsa.o
+rsa_generic-y += rsa_helper.o
+obj-$(CONFIG_CRYPTO_RSA) += rsa_generic.o
+
 cryptomgr-y := algboss.o testmgr.o
 
 obj-$(CONFIG_CRYPTO_MANAGER2) += cryptomgr.o
diff --git a/crypto/rsa.c b/crypto/rsa.c
new file mode 100644
index 000..33bb7f0
--- /dev/null
+++ b/crypto/rsa.c
@@ -0,0 +1,313 @@
+/* RSA asymmetric public-key algorithm [RFC3447]
+ *
+ * Copyright (c) 2015, Intel Corporation
+ * Authors: Tadeusz Struk tadeusz.st...@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/rsa.h
+#include crypto/internal/akcipher.h
+#include crypto/akcipher.h
+
+/*
+ * RSAEP function [RFC3447 sec 5.1.1]
+ * c = m^e mod n;
+ */
+static int _rsa_enc(const struct rsa_key *key, MPI c, MPI m)
+{
+   /* (1) Validate 0 = m  n */
+   if (mpi_cmp_ui(m, 0)  0 || mpi_cmp(m, key-n) = 0)
+   return -EINVAL;
+
+   /* (2) c = m^e mod n */
+   return mpi_powm(c, m, key-e, key-n);
+}
+
+/*
+ * RSADP function [RFC3447 sec 5.1.2]
+ * m = c^d mod n;
+ */
+static int _rsa_dec(const struct rsa_key *key, MPI m, MPI c)
+{
+   /* (1) Validate 0 = c  n */
+   if (mpi_cmp_ui(c, 0)  0 || mpi_cmp(c, key-n) = 0)
+   return -EINVAL;
+
+   /* (2) m = c^d mod n */
+   return mpi_powm(m, c, key-d, key-n);
+}
+
+/*
+ * RSASP1 function [RFC3447 sec 5.2.1]
+ * s = m^d mod n
+ */
+static int _rsa_sign(const struct rsa_key *key, MPI s, MPI m)
+{
+   /* (1) Validate 0 = m  n */
+   if (mpi_cmp_ui(m, 0)  0 || mpi_cmp(m, key-n) = 0)
+   return -EINVAL;
+
+   /* (2) s = m^d mod n */
+   return mpi_powm(s, m, key-d, key-n);
+}
+
+/*
+ * RSAVP1 function [RFC3447 sec 5.2.2]
+ * m = s^e mod n;
+ */
+static int _rsa_verify(const struct rsa_key *key, MPI m, MPI s)
+{
+   /* (1) Validate 0 = s  n */
+   if (mpi_cmp_ui(s, 0)  0 || mpi_cmp(s, key-n) = 0)
+   return -EINVAL;
+
+   /* (2) m = s^e mod n */
+   return mpi_powm(m, s, key-e, key-n);
+}
+
+static struct rsa_key *rsa_get_key(struct crypto_akcipher *tfm)
+{
+   return akcipher_tfm_ctx(tfm);
+}
+
+static int rsa_enc(struct akcipher_request *req)
+{
+   struct crypto_akcipher *tfm = akcipher_request_get_tfm(req);
+   const struct rsa_key *pkey = rsa_get_key(tfm);
+   MPI m, c = mpi_alloc(0);
+   int ret = 0;
+   int sign;
+
+   if (!c)
+   return -ENOMEM;
+
+   if (!pkey-n || !pkey-e || !req-dst_len)
+   return -EINVAL;
+
+   if (*req-dst_len  mpi_get_size(pkey-n)) {
+   *req-dst_len = mpi_get_size(pkey-n);
+   return -EINVAL;
+   }
+
+   m = mpi_read_raw_data(req-src, req-src_len);
+   if (!m) {
+   ret = -ENOMEM;
+   goto err_free_c;
+   }
+
+   ret = _rsa_enc(pkey, c, m);
+   if (ret)
+   goto err_free_m;
+
+   ret = mpi_read_buffer(c, req-dst, *req-dst_len, req-dst_len, sign);
+   if (ret)
+   goto err_free_m;
+
+   if (sign  0) {
+   ret = -EBADMSG;
+   goto err_free_m;
+   }
+
+err_free_m:
+   mpi_free(m);
+err_free_c:
+   mpi_free(c);
+   return ret;