Initial patch set can be found here:
http://www.mail-archive.com/[email protected]/msg18185.html
Changes to initial patch set:
- ("crypto: rsa - generalize ASN.1 sequences")
- allow to provide handlers for the second representation
of the private key (p, q, dq, dq, qinv)
- remove unnecessary arguments on get_<X> functions
- use a single static const struct rsa_ans1_action instance
for all tfms.
- ("crypto: rsa_helper - add raw integer parser actions")
- add raw_rsa_free_key and raw_rsa_free_coherent_key functions
- export raw_rsa_get_<X> symbols
Tudor Ambarus (4):
crypto: rsa - generalize ASN.1 sequences
crypto: rsa_helper - add raw integer parser actions
crypto: add CONFIG_ symbol for rsa helper
crypto: rsa_helper - export symbols for asn1 structures
crypto/Kconfig | 8 +-
crypto/Makefile | 6 +-
crypto/rsa.c | 75 ++++-----
crypto/rsa_helper.c | 351 +++++++++++++++++++++++++++++++++++++-----
include/crypto/internal/rsa.h | 59 ++++++-
5 files changed, 416 insertions(+), 83 deletions(-)
--
1.8.3.1
Use common ASN.1 sequences for all RSA implementations.
Give hardware RSA implementations the chance to use
the RSA's software implementation parser even if they
are likely to want to use raw integers.
The parser expects a context that contains at the first address
a pointer to a struct rsa_asn1_action instance that has function
pointers to specific parser actions (return MPI or raw integer keys),
followed by a key representation structure (for MPI or raw integers).
This approach has the advantage that users can select specific
parser actions by using a general parser with function pointers
to specific actions.
Signed-off-by: Tudor Ambarus <[email protected]>
---
crypto/rsa.c | 60 ++++++++++-----
crypto/rsa_helper.c | 166 ++++++++++++++++++++++++++++++++----------
include/crypto/internal/rsa.h | 31 ++++++--
3 files changed, 194 insertions(+), 63 deletions(-)
diff --git a/crypto/rsa.c b/crypto/rsa.c
index 77d737f..7cb0153 100644
--- a/crypto/rsa.c
+++ b/crypto/rsa.c
@@ -19,7 +19,7 @@
* 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)
+static int _rsa_enc(const struct rsa_mpi_key *key, MPI c, MPI m)
{
/* (1) Validate 0 <= m < n */
if (mpi_cmp_ui(m, 0) < 0 || mpi_cmp(m, key->n) >= 0)
@@ -33,7 +33,7 @@ static int _rsa_enc(const struct rsa_key *key, MPI c, MPI m)
* 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)
+static int _rsa_dec(const struct rsa_mpi_key *key, MPI m, MPI c)
{
/* (1) Validate 0 <= c < n */
if (mpi_cmp_ui(c, 0) < 0 || mpi_cmp(c, key->n) >= 0)
@@ -47,7 +47,7 @@ static int _rsa_dec(const struct rsa_key *key, MPI m, MPI c)
* 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)
+static int _rsa_sign(const struct rsa_mpi_key *key, MPI s, MPI m)
{
/* (1) Validate 0 <= m < n */
if (mpi_cmp_ui(m, 0) < 0 || mpi_cmp(m, key->n) >= 0)
@@ -61,7 +61,7 @@ static int _rsa_sign(const struct rsa_key *key, MPI s, MPI m)
* 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)
+static int _rsa_verify(const struct rsa_mpi_key *key, MPI m, MPI s)
{
/* (1) Validate 0 <= s < n */
if (mpi_cmp_ui(s, 0) < 0 || mpi_cmp(s, key->n) >= 0)
@@ -71,15 +71,17 @@ static int _rsa_verify(const struct rsa_key *key, MPI m, MPI s)
return mpi_powm(m, s, key->e, key->n);
}
-static inline struct rsa_key *rsa_get_key(struct crypto_akcipher *tfm)
+static inline struct rsa_mpi_key *rsa_get_key(struct crypto_akcipher *tfm)
{
- return akcipher_tfm_ctx(tfm);
+ struct rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
+
+ return &ctx->key;
}
static int rsa_enc(struct akcipher_request *req)
{
struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
- const struct rsa_key *pkey = rsa_get_key(tfm);
+ const struct rsa_mpi_key *pkey = rsa_get_key(tfm);
MPI m, c = mpi_alloc(0);
int ret = 0;
int sign;
@@ -118,7 +120,7 @@ err_free_c:
static int rsa_dec(struct akcipher_request *req)
{
struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
- const struct rsa_key *pkey = rsa_get_key(tfm);
+ const struct rsa_mpi_key *pkey = rsa_get_key(tfm);
MPI c, m = mpi_alloc(0);
int ret = 0;
int sign;
@@ -156,7 +158,7 @@ err_free_m:
static int rsa_sign(struct akcipher_request *req)
{
struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
- const struct rsa_key *pkey = rsa_get_key(tfm);
+ const struct rsa_mpi_key *pkey = rsa_get_key(tfm);
MPI m, s = mpi_alloc(0);
int ret = 0;
int sign;
@@ -195,7 +197,7 @@ err_free_s:
static int rsa_verify(struct akcipher_request *req)
{
struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
- const struct rsa_key *pkey = rsa_get_key(tfm);
+ const struct rsa_mpi_key *pkey = rsa_get_key(tfm);
MPI s, m = mpi_alloc(0);
int ret = 0;
int sign;
@@ -251,15 +253,16 @@ static int rsa_check_key_length(unsigned int len)
static int rsa_set_pub_key(struct crypto_akcipher *tfm, const void *key,
unsigned int keylen)
{
- struct rsa_key *pkey = akcipher_tfm_ctx(tfm);
+ struct rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
+ struct rsa_mpi_key *pkey = &ctx->key;
int ret;
- ret = rsa_parse_pub_key(pkey, key, keylen);
+ ret = rsa_parse_mpi_pub_key(ctx, key, keylen);
if (ret)
return ret;
if (rsa_check_key_length(mpi_get_size(pkey->n) << 3)) {
- rsa_free_key(pkey);
+ rsa_free_mpi_key(pkey);
ret = -EINVAL;
}
return ret;
@@ -268,15 +271,16 @@ static int rsa_set_pub_key(struct crypto_akcipher *tfm, const void *key,
static int rsa_set_priv_key(struct crypto_akcipher *tfm, const void *key,
unsigned int keylen)
{
- struct rsa_key *pkey = akcipher_tfm_ctx(tfm);
+ struct rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
+ struct rsa_mpi_key *pkey = &ctx->key;
int ret;
- ret = rsa_parse_priv_key(pkey, key, keylen);
+ ret = rsa_parse_mpi_priv_key(ctx, key, keylen);
if (ret)
return ret;
if (rsa_check_key_length(mpi_get_size(pkey->n) << 3)) {
- rsa_free_key(pkey);
+ rsa_free_mpi_key(pkey);
ret = -EINVAL;
}
return ret;
@@ -284,16 +288,31 @@ static int rsa_set_priv_key(struct crypto_akcipher *tfm, const void *key,
static int rsa_max_size(struct crypto_akcipher *tfm)
{
- struct rsa_key *pkey = akcipher_tfm_ctx(tfm);
+ struct rsa_mpi_key *pkey = rsa_get_key(tfm);
return pkey->n ? mpi_get_size(pkey->n) : -EINVAL;
}
+static const struct rsa_asn1_action rsa_action = {
+ .get_n = rsa_get_mpi_n,
+ .get_e = rsa_get_mpi_e,
+ .get_d = rsa_get_mpi_d,
+};
+
+static int rsa_init_tfm(struct crypto_akcipher *tfm)
+{
+ struct rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
+
+ ctx->action = &rsa_action;
+
+ return 0;
+}
+
static void rsa_exit_tfm(struct crypto_akcipher *tfm)
{
- struct rsa_key *pkey = akcipher_tfm_ctx(tfm);
+ struct rsa_mpi_key *pkey = rsa_get_key(tfm);
- rsa_free_key(pkey);
+ rsa_free_mpi_key(pkey);
}
static struct akcipher_alg rsa = {
@@ -304,13 +323,14 @@ static struct akcipher_alg rsa = {
.set_priv_key = rsa_set_priv_key,
.set_pub_key = rsa_set_pub_key,
.max_size = rsa_max_size,
+ .init = rsa_init_tfm,
.exit = rsa_exit_tfm,
.base = {
.cra_name = "rsa",
.cra_driver_name = "rsa-generic",
.cra_priority = 100,
.cra_module = THIS_MODULE,
- .cra_ctxsize = sizeof(struct rsa_key),
+ .cra_ctxsize = sizeof(struct rsa_ctx),
},
};
diff --git a/crypto/rsa_helper.c b/crypto/rsa_helper.c
index d226f48..0149ed3 100644
--- a/crypto/rsa_helper.c
+++ b/crypto/rsa_helper.c
@@ -21,7 +21,95 @@
int rsa_get_n(void *context, size_t hdrlen, unsigned char tag,
const void *value, size_t vlen)
{
- struct rsa_key *key = context;
+ const struct rsa_asn1_action **action = context;
+
+ if ((*action)->get_n)
+ return (*action)->get_n(context, value, vlen);
+
+ return 0;
+}
+
+int rsa_get_e(void *context, size_t hdrlen, unsigned char tag,
+ const void *value, size_t vlen)
+{
+ const struct rsa_asn1_action **action = context;
+
+ if ((*action)->get_e)
+ return (*action)->get_e(context, value, vlen);
+
+ return 0;
+}
+
+int rsa_get_d(void *context, size_t hdrlen, unsigned char tag,
+ const void *value, size_t vlen)
+{
+ const struct rsa_asn1_action **action = context;
+
+ if ((*action)->get_d)
+ return (*action)->get_d(context, value, vlen);
+
+ return 0;
+}
+
+int rsa_get_p(void *context, size_t hdrlen, unsigned char tag,
+ const void *value, size_t vlen)
+{
+ const struct rsa_asn1_action **action = context;
+
+ if ((*action)->get_p)
+ return (*action)->get_p(context, value, vlen);
+
+ return 0;
+}
+
+int rsa_get_q(void *context, size_t hdrlen, unsigned char tag,
+ const void *value, size_t vlen)
+{
+ const struct rsa_asn1_action **action = context;
+
+ if ((*action)->get_q)
+ return (*action)->get_q(context, value, vlen);
+
+ return 0;
+}
+
+int rsa_get_dp(void *context, size_t hdrlen, unsigned char tag,
+ const void *value, size_t vlen)
+{
+ const struct rsa_asn1_action **action = context;
+
+ if ((*action)->get_dp)
+ return (*action)->get_dp(context, value, vlen);
+
+ return 0;
+}
+
+int rsa_get_dq(void *context, size_t hdrlen, unsigned char tag,
+ const void *value, size_t vlen)
+{
+ const struct rsa_asn1_action **action = context;
+
+ if ((*action)->get_dq)
+ return (*action)->get_dq(context, value, vlen);
+
+ return 0;
+}
+
+int rsa_get_qinv(void *context, size_t hdrlen, unsigned char tag,
+ const void *value, size_t vlen)
+{
+ const struct rsa_asn1_action **action = context;
+
+ if ((*action)->get_qinv)
+ return (*action)->get_qinv(context, value, vlen);
+
+ return 0;
+}
+
+int rsa_get_mpi_n(void *context, const void *value, size_t vlen)
+{
+ struct rsa_ctx *ctx = context;
+ struct rsa_mpi_key *key = &ctx->key;
key->n = mpi_read_raw_data(value, vlen);
@@ -38,11 +126,12 @@ int rsa_get_n(void *context, size_t hdrlen, unsigned char tag,
}
return 0;
}
+EXPORT_SYMBOL_GPL(rsa_get_mpi_n);
-int rsa_get_e(void *context, size_t hdrlen, unsigned char tag,
- const void *value, size_t vlen)
+int rsa_get_mpi_e(void *context, const void *value, size_t vlen)
{
- struct rsa_key *key = context;
+ struct rsa_ctx *ctx = context;
+ struct rsa_mpi_key *key = &ctx->key;
key->e = mpi_read_raw_data(value, vlen);
@@ -51,11 +140,12 @@ int rsa_get_e(void *context, size_t hdrlen, unsigned char tag,
return 0;
}
+EXPORT_SYMBOL_GPL(rsa_get_mpi_e);
-int rsa_get_d(void *context, size_t hdrlen, unsigned char tag,
- const void *value, size_t vlen)
+int rsa_get_mpi_d(void *context, const void *value, size_t vlen)
{
- struct rsa_key *key = context;
+ struct rsa_ctx *ctx = context;
+ struct rsa_mpi_key *key = &ctx->key;
key->d = mpi_read_raw_data(value, vlen);
@@ -72,8 +162,14 @@ int rsa_get_d(void *context, size_t hdrlen, unsigned char tag,
}
return 0;
}
+EXPORT_SYMBOL_GPL(rsa_get_mpi_d);
-static void free_mpis(struct rsa_key *key)
+/**
+ * rsa_free_mpi_key() - frees rsa key allocated by rsa_parse_key()
+ *
+ * @rsa_mpi_key: struct rsa_mpi_key key representation
+ */
+void rsa_free_mpi_key(struct rsa_mpi_key *key)
{
mpi_free(key->n);
mpi_free(key->e);
@@ -82,68 +178,64 @@ static void free_mpis(struct rsa_key *key)
key->e = NULL;
key->d = NULL;
}
+EXPORT_SYMBOL_GPL(rsa_free_mpi_key);
/**
- * rsa_free_key() - frees rsa key allocated by rsa_parse_key()
+ * rsa_parse_mpi_pub_key() - extracts an RSA public key from BER encoded buffer
+ * and stores it in the provided context.
*
- * @rsa_key: struct rsa_key key representation
- */
-void rsa_free_key(struct rsa_key *key)
-{
- free_mpis(key);
-}
-EXPORT_SYMBOL_GPL(rsa_free_key);
-
-/**
- * rsa_parse_pub_key() - extracts an rsa public key from BER encoded buffer
- * and stores it in the provided struct rsa_key
- *
- * @rsa_key: struct rsa_key key representation
+ * @rsa_ctx: RSA internal context
* @key: key in BER format
* @key_len: length of key
*
* Return: 0 on success or error code in case of error
*/
-int rsa_parse_pub_key(struct rsa_key *rsa_key, const void *key,
- unsigned int key_len)
+int rsa_parse_mpi_pub_key(struct rsa_ctx *ctx, const void *key,
+ unsigned int key_len)
{
+ struct rsa_mpi_key *rsa_key = &ctx->key;
int ret;
- free_mpis(rsa_key);
- ret = asn1_ber_decoder(&rsapubkey_decoder, rsa_key, key, key_len);
+ /* Free the old key if any */
+ rsa_free_mpi_key(rsa_key);
+
+ ret = asn1_ber_decoder(&rsapubkey_decoder, ctx, key, key_len);
if (ret < 0)
goto error;
return 0;
error:
- free_mpis(rsa_key);
+ rsa_free_mpi_key(rsa_key);
return ret;
}
-EXPORT_SYMBOL_GPL(rsa_parse_pub_key);
+EXPORT_SYMBOL_GPL(rsa_parse_mpi_pub_key);
/**
- * rsa_parse_pub_key() - extracts an rsa private key from BER encoded buffer
- * and stores it in the provided struct rsa_key
+ * rsa_parse_mpi_priv_key() - extracts an RSA private key from BER encoded
+ * buffer and stores it in the provided context.
*
- * @rsa_key: struct rsa_key key representation
+ * @rsa_ctx: RSA internal context
* @key: key in BER format
* @key_len: length of key
*
* Return: 0 on success or error code in case of error
*/
-int rsa_parse_priv_key(struct rsa_key *rsa_key, const void *key,
- unsigned int key_len)
+int rsa_parse_mpi_priv_key(struct rsa_ctx *ctx, const void *key,
+ unsigned int key_len)
{
+ struct rsa_mpi_key *rsa_key = &ctx->key;
int ret;
- free_mpis(rsa_key);
- ret = asn1_ber_decoder(&rsaprivkey_decoder, rsa_key, key, key_len);
+ /* Free the old key if any */
+ rsa_free_mpi_key(rsa_key);
+
+ ret = asn1_ber_decoder(&rsaprivkey_decoder, ctx, key, key_len);
if (ret < 0)
goto error;
return 0;
error:
- free_mpis(rsa_key);
+ rsa_free_mpi_key(rsa_key);
return ret;
}
-EXPORT_SYMBOL_GPL(rsa_parse_priv_key);
+EXPORT_SYMBOL_GPL(rsa_parse_mpi_priv_key);
diff --git a/include/crypto/internal/rsa.h b/include/crypto/internal/rsa.h
index c7585bd..f8ef7b1 100644
--- a/include/crypto/internal/rsa.h
+++ b/include/crypto/internal/rsa.h
@@ -14,19 +14,38 @@
#define _RSA_HELPER_
#include <linux/mpi.h>
-struct rsa_key {
+struct rsa_asn1_action {
+ int (*get_n)(void *context, const void *value, size_t vlen);
+ int (*get_e)(void *context, const void *value, size_t vlen);
+ int (*get_d)(void *context, const void *value, size_t vlen);
+ int (*get_p)(void *context, const void *value, size_t vlen);
+ int (*get_q)(void *context, const void *value, size_t vlen);
+ int (*get_dp)(void *context, const void *value, size_t vlen);
+ int (*get_dq)(void *context, const void *value, size_t vlen);
+ int (*get_qinv)(void *context, const void *value, size_t vlen);
+};
+
+struct rsa_mpi_key {
MPI n;
MPI e;
MPI d;
};
-int rsa_parse_pub_key(struct rsa_key *rsa_key, const void *key,
- unsigned int key_len);
+struct rsa_ctx {
+ const struct rsa_asn1_action *action;
+ struct rsa_mpi_key key;
+};
+
+int rsa_get_mpi_n(void *context, const void *value, size_t vlen);
+int rsa_get_mpi_e(void *context, const void *value, size_t vlen);
+int rsa_get_mpi_d(void *context, const void *value, size_t vlen);
-int rsa_parse_priv_key(struct rsa_key *rsa_key, const void *key,
- unsigned int key_len);
+void rsa_free_mpi_key(struct rsa_mpi_key *key);
-void rsa_free_key(struct rsa_key *rsa_key);
+int rsa_parse_mpi_pub_key(struct rsa_ctx *ctx, const void *key,
+ unsigned int key_len);
+int rsa_parse_mpi_priv_key(struct rsa_ctx *ctx, const void *key,
+ unsigned int key_len);
extern struct crypto_template rsa_pkcs1pad_tmpl;
#endif
--
1.8.3.1
Dedicated to RSA (hardware) implementations that want to use
raw integers instead of MPI keys.
Signed-off-by: Tudor Ambarus <[email protected]>
---
crypto/rsa.c | 15 ----
crypto/rsa_helper.c | 182 ++++++++++++++++++++++++++++++++++++++++++
include/crypto/internal/rsa.h | 28 +++++++
3 files changed, 210 insertions(+), 15 deletions(-)
diff --git a/crypto/rsa.c b/crypto/rsa.c
index 7cb0153..37ac189 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 0149ed3..df1f480 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"
@@ -239,3 +242,182 @@ error:
return ret;
}
EXPORT_SYMBOL_GPL(rsa_parse_mpi_priv_key);
+
+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);
+
+void raw_rsa_free_key(struct rsa_raw_key *key)
+{
+ kzfree(key->d);
+ key->d = NULL;
+
+ kfree(key->e);
+ key->e = NULL;
+
+ kfree(key->n);
+ key->n = NULL;
+
+ key->n_sz = 0;
+ key->e_sz = 0;
+}
+EXPORT_SYMBOL_GPL(raw_rsa_free_key);
+
+void raw_rsa_free_coherent_key(struct device *dev, struct rsa_raw_key *key)
+{
+ if (key->d) {
+ memset(key->d, '\0', key->n_sz);
+ dma_free_coherent(dev, key->n_sz, key->d, key->dma_d);
+ key->d = NULL;
+ }
+
+ if (key->e) {
+ dma_free_coherent(dev, key->n_sz, key->e, key->dma_e);
+ key->e = NULL;
+ }
+
+ if (key->n) {
+ dma_free_coherent(dev, key->n_sz, key->n, key->dma_n);
+ key->n = NULL;
+ }
+
+ key->n_sz = 0;
+ key->e_sz = 0;
+}
+EXPORT_SYMBOL_GPL(raw_rsa_free_coherent_key);
+
+int raw_rsa_get_n(void *context, 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;
+}
+EXPORT_SYMBOL_GPL(raw_rsa_get_n);
+
+int raw_rsa_get_e(void *context, const void *value, size_t vlen)
+{
+ struct rsa_raw_ctx *ctx = context;
+ struct rsa_raw_key *key = &ctx->key;
+ const char *ptr = value;
+ size_t offset = 0;
+
+ 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);
+ offset = key->n_sz - vlen;
+ }
+
+ if (!key->e)
+ return -ENOMEM;
+
+ memcpy(key->e + offset, ptr, vlen);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(raw_rsa_get_e);
+
+int raw_rsa_get_d(void *context, const void *value, size_t vlen)
+{
+ struct rsa_raw_ctx *ctx = context;
+ struct rsa_raw_key *key = &ctx->key;
+ const char *ptr = value;
+ size_t offset = 0;
+ 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);
+ offset = key->n_sz - vlen;
+ }
+
+ if (!key->d) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ memcpy(key->d + offset, ptr, vlen);
+
+ return 0;
+err:
+ key->d = NULL;
+ return ret;
+}
+EXPORT_SYMBOL_GPL(raw_rsa_get_d);
diff --git a/include/crypto/internal/rsa.h b/include/crypto/internal/rsa.h
index f8ef7b1..854b9b7 100644
--- a/include/crypto/internal/rsa.h
+++ b/include/crypto/internal/rsa.h
@@ -31,11 +31,30 @@ 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_ctx {
const struct rsa_asn1_action *action;
struct rsa_mpi_key key;
};
+struct rsa_raw_ctx {
+ const struct rsa_asn1_action *action;
+ struct rsa_raw_key key;
+ struct device *dev;
+};
+
int rsa_get_mpi_n(void *context, const void *value, size_t vlen);
int rsa_get_mpi_e(void *context, const void *value, size_t vlen);
int rsa_get_mpi_d(void *context, const void *value, size_t vlen);
@@ -47,5 +66,14 @@ int rsa_parse_mpi_pub_key(struct rsa_ctx *ctx, const void *key,
int rsa_parse_mpi_priv_key(struct rsa_ctx *ctx, const void *key,
unsigned int key_len);
+int rsa_check_key_length(unsigned int len);
+
+void raw_rsa_free_key(struct rsa_raw_key *key);
+void raw_rsa_free_coherent_key(struct device *dev, struct rsa_raw_key *key);
+
+int raw_rsa_get_n(void *context, const void *value, size_t vlen);
+int raw_rsa_get_e(void *context, const void *value, size_t vlen);
+int raw_rsa_get_d(void *context, const void *value, size_t vlen);
+
extern struct crypto_template rsa_pkcs1pad_tmpl;
#endif
--
1.8.3.1
All RSA implementations can now use the key extract symbols
by selecting CRYPTO_RSA_HELPER.
Signed-off-by: Tudor Ambarus <[email protected]>
---
crypto/Kconfig | 8 ++++++--
crypto/Makefile | 6 +++---
2 files changed, 9 insertions(+), 5 deletions(-)
diff --git a/crypto/Kconfig b/crypto/Kconfig
index f6bfdda..2bdf882 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -93,11 +93,15 @@ config CRYPTO_AKCIPHER
select CRYPTO_AKCIPHER2
select CRYPTO_ALGAPI
-config CRYPTO_RSA
- tristate "RSA algorithm"
+config CRYPTO_RSA_HELPER
+ bool "RSA key extract helper"
select CRYPTO_AKCIPHER
select MPILIB
select ASN1
+
+config CRYPTO_RSA
+ tristate "RSA algorithm"
+ select CRYPTO_RSA_HELPER
help
Generic implementation of the RSA public key algorithm.
diff --git a/crypto/Makefile b/crypto/Makefile
index 4f4ef7e..d336d83 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -36,10 +36,10 @@ $(obj)/rsaprivkey-asn1.o: $(obj)/rsaprivkey-asn1.c $(obj)/rsaprivkey-asn1.h
clean-files += rsapubkey-asn1.c rsapubkey-asn1.h
clean-files += rsaprivkey-asn1.c rsaprivkey-asn1.h
-rsa_generic-y := rsapubkey-asn1.o
-rsa_generic-y += rsaprivkey-asn1.o
+crypto_rsa_helper-y += rsapubkey-asn1.o rsaprivkey-asn1.o rsa_helper.o
+obj-$(CONFIG_CRYPTO_RSA_HELPER) += crypto_rsa_helper.o
+
rsa_generic-y += rsa.o
-rsa_generic-y += rsa_helper.o
rsa_generic-y += rsa-pkcs1pad.o
obj-$(CONFIG_CRYPTO_RSA) += rsa_generic.o
--
1.8.3.1
Export rsapubkey_decoder and rsaprivkey_decoder structures,
since they can (will) be used by caam and qat drivers.
Signed-off-by: Tudor Ambarus <[email protected]>
---
crypto/rsa_helper.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/crypto/rsa_helper.c b/crypto/rsa_helper.c
index df1f480..d81a0ec 100644
--- a/crypto/rsa_helper.c
+++ b/crypto/rsa_helper.c
@@ -21,6 +21,9 @@
#include "rsapubkey-asn1.h"
#include "rsaprivkey-asn1.h"
+EXPORT_SYMBOL_GPL(rsapubkey_decoder);
+EXPORT_SYMBOL_GPL(rsaprivkey_decoder);
+
int rsa_get_n(void *context, size_t hdrlen, unsigned char tag,
const void *value, size_t vlen)
{
--
1.8.3.1
> -----Original Message-----
> From: [email protected] [mailto:linux-crypto-
> [email protected]] On Behalf Of Tudor Ambarus
> Sent: Wednesday, March 23, 2016 5:04 PM
> To: [email protected]; [email protected]
> Cc: [email protected]; [email protected]; Horia Ioan Geanta
> Neag <[email protected]>; Tudor-Dan Ambarus <tudor-
> [email protected]>
> Subject: [PATCH v2 3/4] crypto: add CONFIG_ symbol for rsa helper
>
> All RSA implementations can now use the key extract symbols by selecting
> CRYPTO_RSA_HELPER.
>
> Signed-off-by: Tudor Ambarus <[email protected]>
Acked-by: Cristian Stoica <[email protected]>
> ---
> crypto/Kconfig | 8 ++++++--
> crypto/Makefile | 6 +++---
> 2 files changed, 9 insertions(+), 5 deletions(-)
>
> diff --git a/crypto/Kconfig b/crypto/Kconfig index f6bfdda..2bdf882 100644
> --- a/crypto/Kconfig
> +++ b/crypto/Kconfig
> @@ -93,11 +93,15 @@ config CRYPTO_AKCIPHER
> select CRYPTO_AKCIPHER2
> select CRYPTO_ALGAPI
>
> -config CRYPTO_RSA
> - tristate "RSA algorithm"
> +config CRYPTO_RSA_HELPER
> + bool "RSA key extract helper"
> select CRYPTO_AKCIPHER
> select MPILIB
> select ASN1
> +
> +config CRYPTO_RSA
> + tristate "RSA algorithm"
> + select CRYPTO_RSA_HELPER
> help
> Generic implementation of the RSA public key algorithm.
>
> diff --git a/crypto/Makefile b/crypto/Makefile index 4f4ef7e..d336d83
> 100644
> --- a/crypto/Makefile
> +++ b/crypto/Makefile
> @@ -36,10 +36,10 @@ $(obj)/rsaprivkey-asn1.o: $(obj)/rsaprivkey-asn1.c
> $(obj)/rsaprivkey-asn1.h clean-files += rsapubkey-asn1.c rsapubkey-asn1.h
> clean-files += rsaprivkey-asn1.c rsaprivkey-asn1.h
>
> -rsa_generic-y := rsapubkey-asn1.o
> -rsa_generic-y += rsaprivkey-asn1.o
> +crypto_rsa_helper-y += rsapubkey-asn1.o rsaprivkey-asn1.o rsa_helper.o
> +obj-$(CONFIG_CRYPTO_RSA_HELPER) += crypto_rsa_helper.o
> +
> rsa_generic-y += rsa.o
> -rsa_generic-y += rsa_helper.o
> rsa_generic-y += rsa-pkcs1pad.o
> obj-$(CONFIG_CRYPTO_RSA) += rsa_generic.o
>
> --
> 1.8.3.1
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-crypto" in the
> body of a message to [email protected] More majordomo info at
> http://vger.kernel.org/majordomo-info.html
> -----Original Message-----
> From: [email protected] [mailto:linux-crypto-
> [email protected]] On Behalf Of Tudor Ambarus
> Sent: Wednesday, March 23, 2016 5:04 PM
> To: [email protected]; [email protected]
> Cc: [email protected]; [email protected]; Horia Ioan Geanta
> Neag <[email protected]>; Tudor-Dan Ambarus <tudor-
> [email protected]>
> Subject: [PATCH v2 4/4] crypto: rsa_helper - export symbols for asn1
> structures
>
> Export rsapubkey_decoder and rsaprivkey_decoder structures, since they
> can (will) be used by caam and qat drivers.
>
> Signed-off-by: Tudor Ambarus <[email protected]>
Acked-by: Cristian Stoica <[email protected]>
> ---
> crypto/rsa_helper.c | 3 +++
> 1 file changed, 3 insertions(+)
>
> diff --git a/crypto/rsa_helper.c b/crypto/rsa_helper.c index df1f480..d81a0ec
> 100644
> --- a/crypto/rsa_helper.c
> +++ b/crypto/rsa_helper.c
> @@ -21,6 +21,9 @@
> #include "rsapubkey-asn1.h"
> #include "rsaprivkey-asn1.h"
>
> +EXPORT_SYMBOL_GPL(rsapubkey_decoder);
> +EXPORT_SYMBOL_GPL(rsaprivkey_decoder);
> +
> int rsa_get_n(void *context, size_t hdrlen, unsigned char tag,
> const void *value, size_t vlen)
> {
> --
> 1.8.3.1
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-crypto" in the
> body of a message to [email protected] More majordomo info at
> http://vger.kernel.org/majordomo-info.html
> -----Original Message-----
> From: [email protected] [mailto:linux-crypto-
> [email protected]] On Behalf Of Tudor Ambarus
> Sent: Wednesday, March 23, 2016 5:04 PM
> To: [email protected]; [email protected]
> Cc: [email protected]; [email protected]; Horia Ioan Geanta
> Neag <[email protected]>; Tudor-Dan Ambarus <tudor-
> [email protected]>
> Subject: [PATCH v2 1/4] crypto: rsa - generalize ASN.1 sequences
>
> Use common ASN.1 sequences for all RSA implementations.
>
> Give hardware RSA implementations the chance to use the RSA's software
> implementation parser even if they are likely to want to use raw integers.
>
> The parser expects a context that contains at the first address a pointer to a
> struct rsa_asn1_action instance that has function pointers to specific parser
> actions (return MPI or raw integer keys), followed by a key representation
> structure (for MPI or raw integers).
>
> This approach has the advantage that users can select specific parser actions
> by using a general parser with function pointers to specific actions.
>
> Signed-off-by: Tudor Ambarus <[email protected]>
Acked-by: Cristian Stoica <[email protected]>
> ---
> crypto/rsa.c | 60 ++++++++++-----
> crypto/rsa_helper.c | 166 ++++++++++++++++++++++++++++++++----
> ------
> include/crypto/internal/rsa.h | 31 ++++++--
> 3 files changed, 194 insertions(+), 63 deletions(-)
>
> diff --git a/crypto/rsa.c b/crypto/rsa.c index 77d737f..7cb0153 100644
> --- a/crypto/rsa.c
> +++ b/crypto/rsa.c
> @@ -19,7 +19,7 @@
> * 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)
> +static int _rsa_enc(const struct rsa_mpi_key *key, MPI c, MPI m)
> {
> /* (1) Validate 0 <= m < n */
> if (mpi_cmp_ui(m, 0) < 0 || mpi_cmp(m, key->n) >= 0) @@ -33,7
> +33,7 @@ static int _rsa_enc(const struct rsa_key *key, MPI c, MPI m)
> * 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)
> +static int _rsa_dec(const struct rsa_mpi_key *key, MPI m, MPI c)
> {
> /* (1) Validate 0 <= c < n */
> if (mpi_cmp_ui(c, 0) < 0 || mpi_cmp(c, key->n) >= 0) @@ -47,7 +47,7
> @@ static int _rsa_dec(const struct rsa_key *key, MPI m, MPI c)
> * 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)
> +static int _rsa_sign(const struct rsa_mpi_key *key, MPI s, MPI m)
> {
> /* (1) Validate 0 <= m < n */
> if (mpi_cmp_ui(m, 0) < 0 || mpi_cmp(m, key->n) >= 0) @@ -61,7
> +61,7 @@ static int _rsa_sign(const struct rsa_key *key, MPI s, MPI m)
> * 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)
> +static int _rsa_verify(const struct rsa_mpi_key *key, MPI m, MPI s)
> {
> /* (1) Validate 0 <= s < n */
> if (mpi_cmp_ui(s, 0) < 0 || mpi_cmp(s, key->n) >= 0) @@ -71,15
> +71,17 @@ static int _rsa_verify(const struct rsa_key *key, MPI m, MPI s)
> return mpi_powm(m, s, key->e, key->n); }
>
> -static inline struct rsa_key *rsa_get_key(struct crypto_akcipher *tfm)
> +static inline struct rsa_mpi_key *rsa_get_key(struct crypto_akcipher
> +*tfm)
> {
> - return akcipher_tfm_ctx(tfm);
> + struct rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
> +
> + return &ctx->key;
> }
>
> static int rsa_enc(struct akcipher_request *req) {
> struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
> - const struct rsa_key *pkey = rsa_get_key(tfm);
> + const struct rsa_mpi_key *pkey = rsa_get_key(tfm);
> MPI m, c = mpi_alloc(0);
> int ret = 0;
> int sign;
> @@ -118,7 +120,7 @@ err_free_c:
> static int rsa_dec(struct akcipher_request *req) {
> struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
> - const struct rsa_key *pkey = rsa_get_key(tfm);
> + const struct rsa_mpi_key *pkey = rsa_get_key(tfm);
> MPI c, m = mpi_alloc(0);
> int ret = 0;
> int sign;
> @@ -156,7 +158,7 @@ err_free_m:
> static int rsa_sign(struct akcipher_request *req) {
> struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
> - const struct rsa_key *pkey = rsa_get_key(tfm);
> + const struct rsa_mpi_key *pkey = rsa_get_key(tfm);
> MPI m, s = mpi_alloc(0);
> int ret = 0;
> int sign;
> @@ -195,7 +197,7 @@ err_free_s:
> static int rsa_verify(struct akcipher_request *req) {
> struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
> - const struct rsa_key *pkey = rsa_get_key(tfm);
> + const struct rsa_mpi_key *pkey = rsa_get_key(tfm);
> MPI s, m = mpi_alloc(0);
> int ret = 0;
> int sign;
> @@ -251,15 +253,16 @@ static int rsa_check_key_length(unsigned int len)
> static int rsa_set_pub_key(struct crypto_akcipher *tfm, const void *key,
> unsigned int keylen)
> {
> - struct rsa_key *pkey = akcipher_tfm_ctx(tfm);
> + struct rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
> + struct rsa_mpi_key *pkey = &ctx->key;
> int ret;
>
> - ret = rsa_parse_pub_key(pkey, key, keylen);
> + ret = rsa_parse_mpi_pub_key(ctx, key, keylen);
> if (ret)
> return ret;
>
> if (rsa_check_key_length(mpi_get_size(pkey->n) << 3)) {
> - rsa_free_key(pkey);
> + rsa_free_mpi_key(pkey);
> ret = -EINVAL;
> }
> return ret;
> @@ -268,15 +271,16 @@ static int rsa_set_pub_key(struct crypto_akcipher
> *tfm, const void *key, static int rsa_set_priv_key(struct crypto_akcipher
> *tfm, const void *key,
> unsigned int keylen)
> {
> - struct rsa_key *pkey = akcipher_tfm_ctx(tfm);
> + struct rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
> + struct rsa_mpi_key *pkey = &ctx->key;
> int ret;
>
> - ret = rsa_parse_priv_key(pkey, key, keylen);
> + ret = rsa_parse_mpi_priv_key(ctx, key, keylen);
> if (ret)
> return ret;
>
> if (rsa_check_key_length(mpi_get_size(pkey->n) << 3)) {
> - rsa_free_key(pkey);
> + rsa_free_mpi_key(pkey);
> ret = -EINVAL;
> }
> return ret;
> @@ -284,16 +288,31 @@ static int rsa_set_priv_key(struct crypto_akcipher
> *tfm, const void *key,
>
> static int rsa_max_size(struct crypto_akcipher *tfm) {
> - struct rsa_key *pkey = akcipher_tfm_ctx(tfm);
> + struct rsa_mpi_key *pkey = rsa_get_key(tfm);
>
> return pkey->n ? mpi_get_size(pkey->n) : -EINVAL; }
>
> +static const struct rsa_asn1_action rsa_action = {
> + .get_n = rsa_get_mpi_n,
> + .get_e = rsa_get_mpi_e,
> + .get_d = rsa_get_mpi_d,
> +};
> +
> +static int rsa_init_tfm(struct crypto_akcipher *tfm) {
> + struct rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
> +
> + ctx->action = &rsa_action;
> +
> + return 0;
> +}
> +
> static void rsa_exit_tfm(struct crypto_akcipher *tfm) {
> - struct rsa_key *pkey = akcipher_tfm_ctx(tfm);
> + struct rsa_mpi_key *pkey = rsa_get_key(tfm);
>
> - rsa_free_key(pkey);
> + rsa_free_mpi_key(pkey);
> }
>
> static struct akcipher_alg rsa = {
> @@ -304,13 +323,14 @@ static struct akcipher_alg rsa = {
> .set_priv_key = rsa_set_priv_key,
> .set_pub_key = rsa_set_pub_key,
> .max_size = rsa_max_size,
> + .init = rsa_init_tfm,
> .exit = rsa_exit_tfm,
> .base = {
> .cra_name = "rsa",
> .cra_driver_name = "rsa-generic",
> .cra_priority = 100,
> .cra_module = THIS_MODULE,
> - .cra_ctxsize = sizeof(struct rsa_key),
> + .cra_ctxsize = sizeof(struct rsa_ctx),
> },
> };
>
> diff --git a/crypto/rsa_helper.c b/crypto/rsa_helper.c index
> d226f48..0149ed3 100644
> --- a/crypto/rsa_helper.c
> +++ b/crypto/rsa_helper.c
> @@ -21,7 +21,95 @@
> int rsa_get_n(void *context, size_t hdrlen, unsigned char tag,
> const void *value, size_t vlen)
> {
> - struct rsa_key *key = context;
> + const struct rsa_asn1_action **action = context;
> +
> + if ((*action)->get_n)
> + return (*action)->get_n(context, value, vlen);
> +
> + return 0;
> +}
> +
> +int rsa_get_e(void *context, size_t hdrlen, unsigned char tag,
> + const void *value, size_t vlen)
> +{
> + const struct rsa_asn1_action **action = context;
> +
> + if ((*action)->get_e)
> + return (*action)->get_e(context, value, vlen);
> +
> + return 0;
> +}
> +
> +int rsa_get_d(void *context, size_t hdrlen, unsigned char tag,
> + const void *value, size_t vlen)
> +{
> + const struct rsa_asn1_action **action = context;
> +
> + if ((*action)->get_d)
> + return (*action)->get_d(context, value, vlen);
> +
> + return 0;
> +}
> +
> +int rsa_get_p(void *context, size_t hdrlen, unsigned char tag,
> + const void *value, size_t vlen)
> +{
> + const struct rsa_asn1_action **action = context;
> +
> + if ((*action)->get_p)
> + return (*action)->get_p(context, value, vlen);
> +
> + return 0;
> +}
> +
> +int rsa_get_q(void *context, size_t hdrlen, unsigned char tag,
> + const void *value, size_t vlen)
> +{
> + const struct rsa_asn1_action **action = context;
> +
> + if ((*action)->get_q)
> + return (*action)->get_q(context, value, vlen);
> +
> + return 0;
> +}
> +
> +int rsa_get_dp(void *context, size_t hdrlen, unsigned char tag,
> + const void *value, size_t vlen) {
> + const struct rsa_asn1_action **action = context;
> +
> + if ((*action)->get_dp)
> + return (*action)->get_dp(context, value, vlen);
> +
> + return 0;
> +}
> +
> +int rsa_get_dq(void *context, size_t hdrlen, unsigned char tag,
> + const void *value, size_t vlen) {
> + const struct rsa_asn1_action **action = context;
> +
> + if ((*action)->get_dq)
> + return (*action)->get_dq(context, value, vlen);
> +
> + return 0;
> +}
> +
> +int rsa_get_qinv(void *context, size_t hdrlen, unsigned char tag,
> + const void *value, size_t vlen)
> +{
> + const struct rsa_asn1_action **action = context;
> +
> + if ((*action)->get_qinv)
> + return (*action)->get_qinv(context, value, vlen);
> +
> + return 0;
> +}
> +
> +int rsa_get_mpi_n(void *context, const void *value, size_t vlen) {
> + struct rsa_ctx *ctx = context;
> + struct rsa_mpi_key *key = &ctx->key;
>
> key->n = mpi_read_raw_data(value, vlen);
>
> @@ -38,11 +126,12 @@ int rsa_get_n(void *context, size_t hdrlen, unsigned
> char tag,
> }
> return 0;
> }
> +EXPORT_SYMBOL_GPL(rsa_get_mpi_n);
>
> -int rsa_get_e(void *context, size_t hdrlen, unsigned char tag,
> - const void *value, size_t vlen)
> +int rsa_get_mpi_e(void *context, const void *value, size_t vlen)
> {
> - struct rsa_key *key = context;
> + struct rsa_ctx *ctx = context;
> + struct rsa_mpi_key *key = &ctx->key;
>
> key->e = mpi_read_raw_data(value, vlen);
>
> @@ -51,11 +140,12 @@ int rsa_get_e(void *context, size_t hdrlen, unsigned
> char tag,
>
> return 0;
> }
> +EXPORT_SYMBOL_GPL(rsa_get_mpi_e);
>
> -int rsa_get_d(void *context, size_t hdrlen, unsigned char tag,
> - const void *value, size_t vlen)
> +int rsa_get_mpi_d(void *context, const void *value, size_t vlen)
> {
> - struct rsa_key *key = context;
> + struct rsa_ctx *ctx = context;
> + struct rsa_mpi_key *key = &ctx->key;
>
> key->d = mpi_read_raw_data(value, vlen);
>
> @@ -72,8 +162,14 @@ int rsa_get_d(void *context, size_t hdrlen, unsigned
> char tag,
> }
> return 0;
> }
> +EXPORT_SYMBOL_GPL(rsa_get_mpi_d);
>
> -static void free_mpis(struct rsa_key *key)
> +/**
> + * rsa_free_mpi_key() - frees rsa key allocated by rsa_parse_key()
> + *
> + * @rsa_mpi_key: struct rsa_mpi_key key representation
> + */
> +void rsa_free_mpi_key(struct rsa_mpi_key *key)
> {
> mpi_free(key->n);
> mpi_free(key->e);
> @@ -82,68 +178,64 @@ static void free_mpis(struct rsa_key *key)
> key->e = NULL;
> key->d = NULL;
> }
> +EXPORT_SYMBOL_GPL(rsa_free_mpi_key);
>
> /**
> - * rsa_free_key() - frees rsa key allocated by rsa_parse_key()
> + * rsa_parse_mpi_pub_key() - extracts an RSA public key from BER encoded
> buffer
> + * and stores it in the provided context.
> *
> - * @rsa_key: struct rsa_key key representation
> - */
> -void rsa_free_key(struct rsa_key *key)
> -{
> - free_mpis(key);
> -}
> -EXPORT_SYMBOL_GPL(rsa_free_key);
> -
> -/**
> - * rsa_parse_pub_key() - extracts an rsa public key from BER encoded
> buffer
> - * and stores it in the provided struct rsa_key
> - *
> - * @rsa_key: struct rsa_key key representation
> + * @rsa_ctx: RSA internal context
> * @key: key in BER format
> * @key_len: length of key
> *
> * Return: 0 on success or error code in case of error
> */
> -int rsa_parse_pub_key(struct rsa_key *rsa_key, const void *key,
> - unsigned int key_len)
> +int rsa_parse_mpi_pub_key(struct rsa_ctx *ctx, const void *key,
> + unsigned int key_len)
> {
> + struct rsa_mpi_key *rsa_key = &ctx->key;
> int ret;
>
> - free_mpis(rsa_key);
> - ret = asn1_ber_decoder(&rsapubkey_decoder, rsa_key, key,
> key_len);
> + /* Free the old key if any */
> + rsa_free_mpi_key(rsa_key);
> +
> + ret = asn1_ber_decoder(&rsapubkey_decoder, ctx, key, key_len);
> if (ret < 0)
> goto error;
>
> return 0;
> error:
> - free_mpis(rsa_key);
> + rsa_free_mpi_key(rsa_key);
> return ret;
> }
> -EXPORT_SYMBOL_GPL(rsa_parse_pub_key);
> +EXPORT_SYMBOL_GPL(rsa_parse_mpi_pub_key);
>
> /**
> - * rsa_parse_pub_key() - extracts an rsa private key from BER encoded
> buffer
> - * and stores it in the provided struct rsa_key
> + * rsa_parse_mpi_priv_key() - extracts an RSA private key from BER
> encoded
> + * buffer and stores it in the provided context.
> *
> - * @rsa_key: struct rsa_key key representation
> + * @rsa_ctx: RSA internal context
> * @key: key in BER format
> * @key_len: length of key
> *
> * Return: 0 on success or error code in case of error
> */
> -int rsa_parse_priv_key(struct rsa_key *rsa_key, const void *key,
> - unsigned int key_len)
> +int rsa_parse_mpi_priv_key(struct rsa_ctx *ctx, const void *key,
> + unsigned int key_len)
> {
> + struct rsa_mpi_key *rsa_key = &ctx->key;
> int ret;
>
> - free_mpis(rsa_key);
> - ret = asn1_ber_decoder(&rsaprivkey_decoder, rsa_key, key,
> key_len);
> + /* Free the old key if any */
> + rsa_free_mpi_key(rsa_key);
> +
> + ret = asn1_ber_decoder(&rsaprivkey_decoder, ctx, key, key_len);
> if (ret < 0)
> goto error;
>
> return 0;
> error:
> - free_mpis(rsa_key);
> + rsa_free_mpi_key(rsa_key);
> return ret;
> }
> -EXPORT_SYMBOL_GPL(rsa_parse_priv_key);
> +EXPORT_SYMBOL_GPL(rsa_parse_mpi_priv_key);
> diff --git a/include/crypto/internal/rsa.h b/include/crypto/internal/rsa.h
> index c7585bd..f8ef7b1 100644
> --- a/include/crypto/internal/rsa.h
> +++ b/include/crypto/internal/rsa.h
> @@ -14,19 +14,38 @@
> #define _RSA_HELPER_
> #include <linux/mpi.h>
>
> -struct rsa_key {
> +struct rsa_asn1_action {
> + int (*get_n)(void *context, const void *value, size_t vlen);
> + int (*get_e)(void *context, const void *value, size_t vlen);
> + int (*get_d)(void *context, const void *value, size_t vlen);
> + int (*get_p)(void *context, const void *value, size_t vlen);
> + int (*get_q)(void *context, const void *value, size_t vlen);
> + int (*get_dp)(void *context, const void *value, size_t vlen);
> + int (*get_dq)(void *context, const void *value, size_t vlen);
> + int (*get_qinv)(void *context, const void *value, size_t vlen); };
> +
> +struct rsa_mpi_key {
> MPI n;
> MPI e;
> MPI d;
> };
>
> -int rsa_parse_pub_key(struct rsa_key *rsa_key, const void *key,
> - unsigned int key_len);
> +struct rsa_ctx {
> + const struct rsa_asn1_action *action;
> + struct rsa_mpi_key key;
> +};
> +
> +int rsa_get_mpi_n(void *context, const void *value, size_t vlen); int
> +rsa_get_mpi_e(void *context, const void *value, size_t vlen); int
> +rsa_get_mpi_d(void *context, const void *value, size_t vlen);
>
> -int rsa_parse_priv_key(struct rsa_key *rsa_key, const void *key,
> - unsigned int key_len);
> +void rsa_free_mpi_key(struct rsa_mpi_key *key);
>
> -void rsa_free_key(struct rsa_key *rsa_key);
> +int rsa_parse_mpi_pub_key(struct rsa_ctx *ctx, const void *key,
> + unsigned int key_len);
> +int rsa_parse_mpi_priv_key(struct rsa_ctx *ctx, const void *key,
> + unsigned int key_len);
>
> extern struct crypto_template rsa_pkcs1pad_tmpl; #endif
> --
> 1.8.3.1
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-crypto" in the
> body of a message to [email protected] More majordomo info at
> http://vger.kernel.org/majordomo-info.html
> -----Original Message-----
> From: [email protected] [mailto:linux-crypto-
> [email protected]] On Behalf Of Tudor Ambarus
> Sent: Wednesday, March 23, 2016 5:04 PM
> To: [email protected]; [email protected]
> Cc: [email protected]; [email protected]; Horia Ioan Geanta
> Neag <[email protected]>; Tudor-Dan Ambarus <tudor-
> [email protected]>
> Subject: [PATCH v2 2/4] crypto: rsa_helper - add raw integer parser actions
>
> Dedicated to RSA (hardware) implementations that want to use raw integers
> instead of MPI keys.
>
> Signed-off-by: Tudor Ambarus <[email protected]>
Acked-by: Cristian Stoica <[email protected]>
> ---
> crypto/rsa.c | 15 ----
> crypto/rsa_helper.c | 182
> ++++++++++++++++++++++++++++++++++++++++++
> include/crypto/internal/rsa.h | 28 +++++++
> 3 files changed, 210 insertions(+), 15 deletions(-)
>
> diff --git a/crypto/rsa.c b/crypto/rsa.c index 7cb0153..37ac189 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 0149ed3..df1f480
> 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"
> @@ -239,3 +242,182 @@ error:
> return ret;
> }
> EXPORT_SYMBOL_GPL(rsa_parse_mpi_priv_key);
> +
> +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);
> +
> +void raw_rsa_free_key(struct rsa_raw_key *key) {
> + kzfree(key->d);
> + key->d = NULL;
> +
> + kfree(key->e);
> + key->e = NULL;
> +
> + kfree(key->n);
> + key->n = NULL;
> +
> + key->n_sz = 0;
> + key->e_sz = 0;
> +}
> +EXPORT_SYMBOL_GPL(raw_rsa_free_key);
> +
> +void raw_rsa_free_coherent_key(struct device *dev, struct rsa_raw_key
> +*key) {
> + if (key->d) {
> + memset(key->d, '\0', key->n_sz);
> + dma_free_coherent(dev, key->n_sz, key->d, key->dma_d);
> + key->d = NULL;
> + }
> +
> + if (key->e) {
> + dma_free_coherent(dev, key->n_sz, key->e, key->dma_e);
> + key->e = NULL;
> + }
> +
> + if (key->n) {
> + dma_free_coherent(dev, key->n_sz, key->n, key->dma_n);
> + key->n = NULL;
> + }
> +
> + key->n_sz = 0;
> + key->e_sz = 0;
> +}
> +EXPORT_SYMBOL_GPL(raw_rsa_free_coherent_key);
> +
> +int raw_rsa_get_n(void *context, 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;
> +}
> +EXPORT_SYMBOL_GPL(raw_rsa_get_n);
> +
> +int raw_rsa_get_e(void *context, const void *value, size_t vlen) {
> + struct rsa_raw_ctx *ctx = context;
> + struct rsa_raw_key *key = &ctx->key;
> + const char *ptr = value;
> + size_t offset = 0;
> +
> + 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);
> + offset = key->n_sz - vlen;
> + }
> +
> + if (!key->e)
> + return -ENOMEM;
> +
> + memcpy(key->e + offset, ptr, vlen);
> +
> + return 0;
> +}
> +EXPORT_SYMBOL_GPL(raw_rsa_get_e);
> +
> +int raw_rsa_get_d(void *context, const void *value, size_t vlen) {
> + struct rsa_raw_ctx *ctx = context;
> + struct rsa_raw_key *key = &ctx->key;
> + const char *ptr = value;
> + size_t offset = 0;
> + 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);
> + offset = key->n_sz - vlen;
> + }
> +
> + if (!key->d) {
> + ret = -ENOMEM;
> + goto err;
> + }
> +
> + memcpy(key->d + offset, ptr, vlen);
> +
> + return 0;
> +err:
> + key->d = NULL;
> + return ret;
> +}
> +EXPORT_SYMBOL_GPL(raw_rsa_get_d);
> diff --git a/include/crypto/internal/rsa.h b/include/crypto/internal/rsa.h
> index f8ef7b1..854b9b7 100644
> --- a/include/crypto/internal/rsa.h
> +++ b/include/crypto/internal/rsa.h
> @@ -31,11 +31,30 @@ 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_ctx {
> const struct rsa_asn1_action *action;
> struct rsa_mpi_key key;
> };
>
> +struct rsa_raw_ctx {
> + const struct rsa_asn1_action *action;
> + struct rsa_raw_key key;
> + struct device *dev;
> +};
> +
> int rsa_get_mpi_n(void *context, const void *value, size_t vlen); int
> rsa_get_mpi_e(void *context, const void *value, size_t vlen); int
> rsa_get_mpi_d(void *context, const void *value, size_t vlen); @@ -47,5
> +66,14 @@ int rsa_parse_mpi_pub_key(struct rsa_ctx *ctx, const void *key,
> int rsa_parse_mpi_priv_key(struct rsa_ctx *ctx, const void *key,
> unsigned int key_len);
>
> +int rsa_check_key_length(unsigned int len);
> +
> +void raw_rsa_free_key(struct rsa_raw_key *key); void
> +raw_rsa_free_coherent_key(struct device *dev, struct rsa_raw_key *key);
> +
> +int raw_rsa_get_n(void *context, const void *value, size_t vlen); int
> +raw_rsa_get_e(void *context, const void *value, size_t vlen); int
> +raw_rsa_get_d(void *context, const void *value, size_t vlen);
> +
> extern struct crypto_template rsa_pkcs1pad_tmpl; #endif
> --
> 1.8.3.1
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-crypto" in the
> body of a message to [email protected] More majordomo info at
> http://vger.kernel.org/majordomo-info.html
On Wed, Mar 23, 2016 at 05:04:18PM +0200, Tudor Ambarus wrote:
> All RSA implementations can now use the key extract symbols
> by selecting CRYPTO_RSA_HELPER.
>
> Signed-off-by: Tudor Ambarus <[email protected]>
Please don't. Just keep it in the generic rsa module and have
the drivers depend on that instead.
Thanks,
--
Email: Herbert Xu <[email protected]>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt