2016-03-18 18:48:13

by Tudor-Dan Ambarus

[permalink] [raw]
Subject: [PATCH 01/10] 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 struct rsa_asn1_action with 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 | 48 +++++++++--------
crypto/rsa_helper.c | 117 +++++++++++++++++++++++++++++-------------
include/crypto/internal/rsa.h | 28 +++++++---
3 files changed, 130 insertions(+), 63 deletions(-)

diff --git a/crypto/rsa.c b/crypto/rsa.c
index 77d737f..2d53ad8 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,18 @@ 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);
+ set_rsa_pub_action(&ctx->action);
+
+ 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 +273,18 @@ 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);
+ set_rsa_priv_action(&ctx->action);
+
+ 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 +292,16 @@ 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 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 = {
@@ -310,7 +318,7 @@ static struct akcipher_alg 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..1ed32af 100644
--- a/crypto/rsa_helper.c
+++ b/crypto/rsa_helper.c
@@ -21,7 +21,32 @@
int rsa_get_n(void *context, size_t hdrlen, unsigned char tag,
const void *value, size_t vlen)
{
- struct rsa_key *key = context;
+ struct rsa_asn1_action *action = (struct rsa_asn1_action *)context;
+
+ return action->get_n(context, hdrlen, tag, value, vlen);
+}
+
+int rsa_get_e(void *context, size_t hdrlen, unsigned char tag,
+ const void *value, size_t vlen)
+{
+ struct rsa_asn1_action *action = (struct rsa_asn1_action *)context;
+
+ return action->get_e(context, hdrlen, tag, value, vlen);
+}
+
+int rsa_get_d(void *context, size_t hdrlen, unsigned char tag,
+ const void *value, size_t vlen)
+{
+ struct rsa_asn1_action *action = (struct rsa_asn1_action *)context;
+
+ return action->get_d(context, hdrlen, tag, value, vlen);
+}
+
+int rsa_get_mpi_n(void *context, size_t hdrlen, unsigned char tag,
+ 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);

@@ -39,10 +64,11 @@ int rsa_get_n(void *context, size_t hdrlen, unsigned char tag,
return 0;
}

-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, size_t hdrlen, unsigned char tag,
+ 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);

@@ -52,10 +78,11 @@ int rsa_get_e(void *context, size_t hdrlen, unsigned char tag,
return 0;
}

-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, size_t hdrlen, unsigned char tag,
+ 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);

@@ -73,7 +100,12 @@ int rsa_get_d(void *context, size_t hdrlen, unsigned char tag,
return 0;
}

-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 +114,79 @@ 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_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_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
+ * @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);
+
+void set_rsa_pub_action(struct rsa_asn1_action *action)
+{
+ action->get_e = rsa_get_mpi_e;
+ action->get_n = rsa_get_mpi_n;
+}
+EXPORT_SYMBOL_GPL(set_rsa_pub_action);
+
+void set_rsa_priv_action(struct rsa_asn1_action *action)
+{
+ action->get_d = rsa_get_mpi_d;
+ action->get_e = rsa_get_mpi_e;
+ action->get_n = rsa_get_mpi_n;
+}
+EXPORT_SYMBOL_GPL(set_rsa_priv_action);
diff --git a/include/crypto/internal/rsa.h b/include/crypto/internal/rsa.h
index c7585bd..bf0f49d 100644
--- a/include/crypto/internal/rsa.h
+++ b/include/crypto/internal/rsa.h
@@ -14,19 +14,35 @@
#define _RSA_HELPER_
#include <linux/mpi.h>

-struct rsa_key {
+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_asn1_action {
+ int (*get_n)(void *context, size_t hdrlen, unsigned char tag,
+ const void *value, size_t vlen);
+ int (*get_e)(void *context, size_t hdrlen, unsigned char tag,
+ const void *value, size_t vlen);
+ int (*get_d)(void *context, size_t hdrlen, unsigned char tag,
+ const void *value, size_t vlen);
+};
+
+struct rsa_ctx {
+ struct rsa_asn1_action action;
+ struct rsa_mpi_key key;
+};
+
+void rsa_free_mpi_key(struct rsa_mpi_key *key);

-int rsa_parse_priv_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);
+int rsa_parse_mpi_priv_key(struct rsa_ctx *ctx, const void *key,
+ unsigned int key_len);

-void rsa_free_key(struct rsa_key *rsa_key);
+void set_rsa_pub_action(struct rsa_asn1_action *action);
+void set_rsa_priv_action(struct rsa_asn1_action *action);

extern struct crypto_template rsa_pkcs1pad_tmpl;
#endif
--
1.8.3.1


2016-03-18 18:32:19

by Tudor-Dan Ambarus

[permalink] [raw]
Subject: [PATCH 02/10] 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]>
---
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;
+ }
+
+ 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
--
1.8.3.1

2016-03-18 18:32:23

by Tudor-Dan Ambarus

[permalink] [raw]
Subject: [PATCH 04/10] 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]>
---
crypto/rsa_helper.c | 3 +++
1 file changed, 3 insertions(+)

diff --git a/crypto/rsa_helper.c b/crypto/rsa_helper.c
index 1708db8..14aef69 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

2016-03-18 18:32:32

by Tudor-Dan Ambarus

[permalink] [raw]
Subject: [PATCH 09/10] crypto: scatterwalk - export scatterwalk_pagedone

Used in caam driver. Export the symbol since the caam driver
can be built as a module.

Signed-off-by: Tudor Ambarus <[email protected]>
---
crypto/scatterwalk.c | 5 +++--
include/crypto/scatterwalk.h | 2 ++
2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/crypto/scatterwalk.c b/crypto/scatterwalk.c
index bc3222d..03d34f9 100644
--- a/crypto/scatterwalk.c
+++ b/crypto/scatterwalk.c
@@ -47,8 +47,8 @@ void *scatterwalk_map(struct scatter_walk *walk)
}
EXPORT_SYMBOL_GPL(scatterwalk_map);

-static void scatterwalk_pagedone(struct scatter_walk *walk, int out,
- unsigned int more)
+void scatterwalk_pagedone(struct scatter_walk *walk, int out,
+ unsigned int more)
{
if (out) {
struct page *page;
@@ -69,6 +69,7 @@ static void scatterwalk_pagedone(struct scatter_walk *walk, int out,
scatterwalk_start(walk, sg_next(walk->sg));
}
}
+EXPORT_SYMBOL_GPL(scatterwalk_pagedone);

void scatterwalk_done(struct scatter_walk *walk, int out, int more)
{
diff --git a/include/crypto/scatterwalk.h b/include/crypto/scatterwalk.h
index 8b799c5..6535a20 100644
--- a/include/crypto/scatterwalk.h
+++ b/include/crypto/scatterwalk.h
@@ -89,6 +89,8 @@ void scatterwalk_copychunks(void *buf, struct scatter_walk *walk,
void scatterwalk_sg_copychunks(struct scatter_walk *dest,
struct scatter_walk *src, size_t nbytes);
void *scatterwalk_map(struct scatter_walk *walk);
+void scatterwalk_pagedone(struct scatter_walk *walk, int out,
+ unsigned int more);
void scatterwalk_done(struct scatter_walk *walk, int out, int more);

void scatterwalk_map_and_copy(void *buf, struct scatterlist *sg,
--
1.8.3.1

2016-03-18 18:32:30

by Tudor-Dan Ambarus

[permalink] [raw]
Subject: [PATCH 08/10] crypto: scatterwak - Add scatterwalk_sg_copychunks

This patch adds the function scatterwalk_sg_copychunks which writes
a chunk of data from a scatterwalk to another scatterwalk.
It will be used by caam driver to remove the leading zeros of RSA's
algorithm output.

Signed-off-by: Tudor Ambarus <[email protected]>
---
crypto/scatterwalk.c | 26 ++++++++++++++++++++++++++
include/crypto/scatterwalk.h | 2 ++
2 files changed, 28 insertions(+)

diff --git a/crypto/scatterwalk.c b/crypto/scatterwalk.c
index ea5815c..bc3222d 100644
--- a/crypto/scatterwalk.c
+++ b/crypto/scatterwalk.c
@@ -125,6 +125,32 @@ void scatterwalk_map_and_copy(void *buf, struct scatterlist *sg,
}
EXPORT_SYMBOL_GPL(scatterwalk_map_and_copy);

+void scatterwalk_sg_copychunks(struct scatter_walk *dest,
+ struct scatter_walk *src, size_t nbytes)
+{
+ for (;;) {
+ unsigned int len_this_page = scatterwalk_pagelen(dest);
+ u8 *vaddr;
+
+ if (len_this_page > nbytes)
+ len_this_page = nbytes;
+
+ vaddr = scatterwalk_map(dest);
+ scatterwalk_copychunks(vaddr, src, len_this_page, 0);
+ scatterwalk_unmap(vaddr);
+
+ scatterwalk_advance(dest, len_this_page);
+
+ if (nbytes == len_this_page)
+ break;
+
+ nbytes -= len_this_page;
+
+ scatterwalk_pagedone(dest, 0, 1);
+ }
+}
+EXPORT_SYMBOL_GPL(scatterwalk_sg_copychunks);
+
int scatterwalk_bytes_sglen(struct scatterlist *sg, int num_bytes)
{
int offset = 0, n = 0;
diff --git a/include/crypto/scatterwalk.h b/include/crypto/scatterwalk.h
index 35f99b6..8b799c5 100644
--- a/include/crypto/scatterwalk.h
+++ b/include/crypto/scatterwalk.h
@@ -86,6 +86,8 @@ static inline void scatterwalk_unmap(void *vaddr)
void scatterwalk_start(struct scatter_walk *walk, struct scatterlist *sg);
void scatterwalk_copychunks(void *buf, struct scatter_walk *walk,
size_t nbytes, int out);
+void scatterwalk_sg_copychunks(struct scatter_walk *dest,
+ struct scatter_walk *src, size_t nbytes);
void *scatterwalk_map(struct scatter_walk *walk);
void scatterwalk_done(struct scatter_walk *walk, int out, int more);

--
1.8.3.1

2016-03-18 18:32:33

by Tudor-Dan Ambarus

[permalink] [raw]
Subject: [PATCH 07/10] crypto: qat - remove duplicate ASN.1 parser

Use the RSA's software implementation parser with
raw integer actions.

Compile-tested only.

Signed-off-by: Tudor Ambarus <[email protected]>
---
drivers/crypto/qat/Kconfig | 3 +-
drivers/crypto/qat/qat_common/Makefile | 10 +-
drivers/crypto/qat/qat_common/qat_asym_algs.c | 265 +++++++---------------
drivers/crypto/qat/qat_common/qat_rsaprivkey.asn1 | 11 -
drivers/crypto/qat/qat_common/qat_rsapubkey.asn1 | 4 -
5 files changed, 83 insertions(+), 210 deletions(-)
delete mode 100644 drivers/crypto/qat/qat_common/qat_rsaprivkey.asn1
delete mode 100644 drivers/crypto/qat/qat_common/qat_rsapubkey.asn1

diff --git a/drivers/crypto/qat/Kconfig b/drivers/crypto/qat/Kconfig
index 85b44e5..59314e6 100644
--- a/drivers/crypto/qat/Kconfig
+++ b/drivers/crypto/qat/Kconfig
@@ -3,13 +3,12 @@ config CRYPTO_DEV_QAT
select CRYPTO_AEAD
select CRYPTO_AUTHENC
select CRYPTO_BLKCIPHER
- select CRYPTO_AKCIPHER
select CRYPTO_HMAC
select CRYPTO_SHA1
select CRYPTO_SHA256
select CRYPTO_SHA512
select FW_LOADER
- select ASN1
+ select CRYPTO_RSA_HELPER

config CRYPTO_DEV_QAT_DH895xCC
tristate "Support for Intel(R) DH895xCC"
diff --git a/drivers/crypto/qat/qat_common/Makefile b/drivers/crypto/qat/qat_common/Makefile
index 29c7c53..dd62918 100644
--- a/drivers/crypto/qat/qat_common/Makefile
+++ b/drivers/crypto/qat/qat_common/Makefile
@@ -1,10 +1,4 @@
-$(obj)/qat_rsapubkey-asn1.o: $(obj)/qat_rsapubkey-asn1.c \
- $(obj)/qat_rsapubkey-asn1.h
-$(obj)/qat_rsaprivkey-asn1.o: $(obj)/qat_rsaprivkey-asn1.c \
- $(obj)/qat_rsaprivkey-asn1.h
-
-clean-files += qat_rsapubkey-asn1.c qat_rsapubkey-asn1.h
-clean-files += qat_rsaprivkey-asn1.c qat_rsaprivkey-asn1.h
+ccflags-y += -I$(srctree)/crypto

obj-$(CONFIG_CRYPTO_DEV_QAT) += intel_qat.o
intel_qat-objs := adf_cfg.o \
@@ -20,8 +14,6 @@ intel_qat-objs := adf_cfg.o \
adf_hw_arbiter.o \
qat_crypto.o \
qat_algs.o \
- qat_rsapubkey-asn1.o \
- qat_rsaprivkey-asn1.o \
qat_asym_algs.o \
qat_uclo.o \
qat_hal.o
diff --git a/drivers/crypto/qat/qat_common/qat_asym_algs.c b/drivers/crypto/qat/qat_common/qat_asym_algs.c
index 05f49d4..196269c5 100644
--- a/drivers/crypto/qat/qat_common/qat_asym_algs.c
+++ b/drivers/crypto/qat/qat_common/qat_asym_algs.c
@@ -52,8 +52,8 @@
#include <linux/dma-mapping.h>
#include <linux/fips.h>
#include <crypto/scatterwalk.h>
-#include "qat_rsapubkey-asn1.h"
-#include "qat_rsaprivkey-asn1.h"
+#include "rsapubkey-asn1.h"
+#include "rsaprivkey-asn1.h"
#include "icp_qat_fw_pke.h"
#include "adf_accel_devices.h"
#include "adf_transport.h"
@@ -92,13 +92,7 @@ struct qat_rsa_output_params {
} __packed __aligned(64);

struct qat_rsa_ctx {
- char *n;
- char *e;
- char *d;
- dma_addr_t dma_n;
- dma_addr_t dma_e;
- dma_addr_t dma_d;
- unsigned int key_sz;
+ struct rsa_raw_ctx raw_key_ctx;
struct qat_crypto_instance *inst;
} __packed __aligned(64);

@@ -118,6 +112,7 @@ static void qat_rsa_cb(struct icp_qat_fw_pke_resp *resp)
{
struct akcipher_request *areq = (void *)(__force long)resp->opaque;
struct qat_rsa_request *req = PTR_ALIGN(akcipher_request_ctx(areq), 64);
+ struct rsa_raw_key *key = &req->ctx->raw_key_ctx.key;
struct device *dev = &GET_DEV(req->ctx->inst->accel_dev);
int err = ICP_QAT_FW_PKE_RESP_PKE_STAT_GET(
resp->pke_resp_hdr.comn_resp_flags);
@@ -125,13 +120,12 @@ static void qat_rsa_cb(struct icp_qat_fw_pke_resp *resp)
err = (err == ICP_QAT_FW_COMN_STATUS_FLAG_OK) ? 0 : -EINVAL;

if (req->src_align)
- dma_free_coherent(dev, req->ctx->key_sz, req->src_align,
+ dma_free_coherent(dev, key->n_sz, req->src_align,
req->in.enc.m);
else
- dma_unmap_single(dev, req->in.enc.m, req->ctx->key_sz,
- DMA_TO_DEVICE);
+ dma_unmap_single(dev, req->in.enc.m, key->n_sz, DMA_TO_DEVICE);

- areq->dst_len = req->ctx->key_sz;
+ areq->dst_len = key->n_sz;
if (req->dst_align) {
char *ptr = req->dst_align;

@@ -140,13 +134,13 @@ static void qat_rsa_cb(struct icp_qat_fw_pke_resp *resp)
ptr++;
}

- if (areq->dst_len != req->ctx->key_sz)
+ if (areq->dst_len != key->n_sz)
memmove(req->dst_align, ptr, areq->dst_len);

scatterwalk_map_and_copy(req->dst_align, areq->dst, 0,
areq->dst_len, 1);

- dma_free_coherent(dev, req->ctx->key_sz, req->dst_align,
+ dma_free_coherent(dev, key->n_sz, req->dst_align,
req->out.enc.c);
} else {
char *ptr = sg_virt(areq->dst);
@@ -159,7 +153,7 @@ static void qat_rsa_cb(struct icp_qat_fw_pke_resp *resp)
if (sg_virt(areq->dst) != ptr && areq->dst_len)
memmove(sg_virt(areq->dst), ptr, areq->dst_len);

- dma_unmap_single(dev, req->out.enc.c, req->ctx->key_sz,
+ dma_unmap_single(dev, req->out.enc.c, key->n_sz,
DMA_FROM_DEVICE);
}

@@ -241,6 +235,7 @@ static int qat_rsa_enc(struct akcipher_request *req)
{
struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
struct qat_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
+ struct rsa_raw_key *key = &ctx->raw_key_ctx.key;
struct qat_crypto_instance *inst = ctx->inst;
struct device *dev = &GET_DEV(inst->accel_dev);
struct qat_rsa_request *qat_req =
@@ -248,17 +243,17 @@ static int qat_rsa_enc(struct akcipher_request *req)
struct icp_qat_fw_pke_request *msg = &qat_req->req;
int ret, ctr = 0;

- if (unlikely(!ctx->n || !ctx->e))
+ if (unlikely(!key->n || !key->e))
return -EINVAL;

- if (req->dst_len < ctx->key_sz) {
- req->dst_len = ctx->key_sz;
+ if (req->dst_len < key->n_sz) {
+ req->dst_len = key->n_sz;
return -EOVERFLOW;
}
memset(msg, '\0', sizeof(*msg));
ICP_QAT_FW_PKE_HDR_VALID_FLAG_SET(msg->pke_hdr,
ICP_QAT_FW_COMN_REQ_FLAG_SET);
- msg->pke_hdr.cd_pars.func_id = qat_rsa_enc_fn_id(ctx->key_sz);
+ msg->pke_hdr.cd_pars.func_id = qat_rsa_enc_fn_id(key->n_sz);
if (unlikely(!msg->pke_hdr.cd_pars.func_id))
return -EINVAL;

@@ -268,8 +263,8 @@ static int qat_rsa_enc(struct akcipher_request *req)
ICP_QAT_FW_COMN_FLAGS_BUILD(QAT_COMN_PTR_TYPE_FLAT,
QAT_COMN_CD_FLD_TYPE_64BIT_ADR);

- qat_req->in.enc.e = ctx->dma_e;
- qat_req->in.enc.n = ctx->dma_n;
+ qat_req->in.enc.e = key->dma_e;
+ qat_req->in.enc.n = key->dma_n;
ret = -ENOMEM;

/*
@@ -279,7 +274,7 @@ static int qat_rsa_enc(struct akcipher_request *req)
* In other case we just need to map the user provided buffer.
* Also need to make sure that it is in contiguous buffer.
*/
- if (sg_is_last(req->src) && req->src_len == ctx->key_sz) {
+ if (sg_is_last(req->src) && req->src_len == key->n_sz) {
qat_req->src_align = NULL;
qat_req->in.enc.m = dma_map_single(dev, sg_virt(req->src),
req->src_len, DMA_TO_DEVICE);
@@ -287,9 +282,9 @@ static int qat_rsa_enc(struct akcipher_request *req)
return ret;

} else {
- int shift = ctx->key_sz - req->src_len;
+ int shift = key->n_sz - req->src_len;

- qat_req->src_align = dma_zalloc_coherent(dev, ctx->key_sz,
+ qat_req->src_align = dma_zalloc_coherent(dev, key->n_sz,
&qat_req->in.enc.m,
GFP_KERNEL);
if (unlikely(!qat_req->src_align))
@@ -298,7 +293,7 @@ static int qat_rsa_enc(struct akcipher_request *req)
scatterwalk_map_and_copy(qat_req->src_align + shift, req->src,
0, req->src_len, 0);
}
- if (sg_is_last(req->dst) && req->dst_len == ctx->key_sz) {
+ if (sg_is_last(req->dst) && req->dst_len == key->n_sz) {
qat_req->dst_align = NULL;
qat_req->out.enc.c = dma_map_single(dev, sg_virt(req->dst),
req->dst_len,
@@ -308,7 +303,7 @@ static int qat_rsa_enc(struct akcipher_request *req)
goto unmap_src;

} else {
- qat_req->dst_align = dma_zalloc_coherent(dev, ctx->key_sz,
+ qat_req->dst_align = dma_zalloc_coherent(dev, key->n_sz,
&qat_req->out.enc.c,
GFP_KERNEL);
if (unlikely(!qat_req->dst_align))
@@ -352,19 +347,19 @@ unmap_in_params:
DMA_TO_DEVICE);
unmap_dst:
if (qat_req->dst_align)
- dma_free_coherent(dev, ctx->key_sz, qat_req->dst_align,
+ dma_free_coherent(dev, key->n_sz, qat_req->dst_align,
qat_req->out.enc.c);
else
if (!dma_mapping_error(dev, qat_req->out.enc.c))
- dma_unmap_single(dev, qat_req->out.enc.c, ctx->key_sz,
+ dma_unmap_single(dev, qat_req->out.enc.c, key->n_sz,
DMA_FROM_DEVICE);
unmap_src:
if (qat_req->src_align)
- dma_free_coherent(dev, ctx->key_sz, qat_req->src_align,
+ dma_free_coherent(dev, key->n_sz, qat_req->src_align,
qat_req->in.enc.m);
else
if (!dma_mapping_error(dev, qat_req->in.enc.m))
- dma_unmap_single(dev, qat_req->in.enc.m, ctx->key_sz,
+ dma_unmap_single(dev, qat_req->in.enc.m, key->n_sz,
DMA_TO_DEVICE);
return ret;
}
@@ -373,6 +368,7 @@ static int qat_rsa_dec(struct akcipher_request *req)
{
struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
struct qat_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
+ struct rsa_raw_key *key = &ctx->raw_key_ctx.key;
struct qat_crypto_instance *inst = ctx->inst;
struct device *dev = &GET_DEV(inst->accel_dev);
struct qat_rsa_request *qat_req =
@@ -380,17 +376,17 @@ static int qat_rsa_dec(struct akcipher_request *req)
struct icp_qat_fw_pke_request *msg = &qat_req->req;
int ret, ctr = 0;

- if (unlikely(!ctx->n || !ctx->d))
+ if (unlikely(!key->n || !key->d))
return -EINVAL;

- if (req->dst_len < ctx->key_sz) {
- req->dst_len = ctx->key_sz;
+ if (req->dst_len < key->n_sz) {
+ req->dst_len = key->n_sz;
return -EOVERFLOW;
}
memset(msg, '\0', sizeof(*msg));
ICP_QAT_FW_PKE_HDR_VALID_FLAG_SET(msg->pke_hdr,
ICP_QAT_FW_COMN_REQ_FLAG_SET);
- msg->pke_hdr.cd_pars.func_id = qat_rsa_dec_fn_id(ctx->key_sz);
+ msg->pke_hdr.cd_pars.func_id = qat_rsa_dec_fn_id(key->n_sz);
if (unlikely(!msg->pke_hdr.cd_pars.func_id))
return -EINVAL;

@@ -400,8 +396,8 @@ static int qat_rsa_dec(struct akcipher_request *req)
ICP_QAT_FW_COMN_FLAGS_BUILD(QAT_COMN_PTR_TYPE_FLAT,
QAT_COMN_CD_FLD_TYPE_64BIT_ADR);

- qat_req->in.dec.d = ctx->dma_d;
- qat_req->in.dec.n = ctx->dma_n;
+ qat_req->in.dec.d = key->dma_d;
+ qat_req->in.dec.n = key->dma_n;
ret = -ENOMEM;

/*
@@ -411,7 +407,7 @@ static int qat_rsa_dec(struct akcipher_request *req)
* In other case we just need to map the user provided buffer.
* Also need to make sure that it is in contiguous buffer.
*/
- if (sg_is_last(req->src) && req->src_len == ctx->key_sz) {
+ if (sg_is_last(req->src) && req->src_len == key->n_sz) {
qat_req->src_align = NULL;
qat_req->in.dec.c = dma_map_single(dev, sg_virt(req->src),
req->dst_len, DMA_TO_DEVICE);
@@ -419,9 +415,9 @@ static int qat_rsa_dec(struct akcipher_request *req)
return ret;

} else {
- int shift = ctx->key_sz - req->src_len;
+ int shift = key->n_sz - req->src_len;

- qat_req->src_align = dma_zalloc_coherent(dev, ctx->key_sz,
+ qat_req->src_align = dma_zalloc_coherent(dev, key->n_sz,
&qat_req->in.dec.c,
GFP_KERNEL);
if (unlikely(!qat_req->src_align))
@@ -430,7 +426,7 @@ static int qat_rsa_dec(struct akcipher_request *req)
scatterwalk_map_and_copy(qat_req->src_align + shift, req->src,
0, req->src_len, 0);
}
- if (sg_is_last(req->dst) && req->dst_len == ctx->key_sz) {
+ if (sg_is_last(req->dst) && req->dst_len == key->n_sz) {
qat_req->dst_align = NULL;
qat_req->out.dec.m = dma_map_single(dev, sg_virt(req->dst),
req->dst_len,
@@ -440,7 +436,7 @@ static int qat_rsa_dec(struct akcipher_request *req)
goto unmap_src;

} else {
- qat_req->dst_align = dma_zalloc_coherent(dev, ctx->key_sz,
+ qat_req->dst_align = dma_zalloc_coherent(dev, key->n_sz,
&qat_req->out.dec.m,
GFP_KERNEL);
if (unlikely(!qat_req->dst_align))
@@ -485,160 +481,71 @@ unmap_in_params:
DMA_TO_DEVICE);
unmap_dst:
if (qat_req->dst_align)
- dma_free_coherent(dev, ctx->key_sz, qat_req->dst_align,
+ dma_free_coherent(dev, key->n_sz, qat_req->dst_align,
qat_req->out.dec.m);
else
if (!dma_mapping_error(dev, qat_req->out.dec.m))
- dma_unmap_single(dev, qat_req->out.dec.m, ctx->key_sz,
+ dma_unmap_single(dev, qat_req->out.dec.m, key->n_sz,
DMA_FROM_DEVICE);
unmap_src:
if (qat_req->src_align)
- dma_free_coherent(dev, ctx->key_sz, qat_req->src_align,
+ dma_free_coherent(dev, key->n_sz, qat_req->src_align,
qat_req->in.dec.c);
else
if (!dma_mapping_error(dev, qat_req->in.dec.c))
- dma_unmap_single(dev, qat_req->in.dec.c, ctx->key_sz,
+ dma_unmap_single(dev, qat_req->in.dec.c, key->n_sz,
DMA_TO_DEVICE);
return ret;
}

-int qat_rsa_get_n(void *context, size_t hdrlen, unsigned char tag,
- const void *value, size_t vlen)
+static void qat_free_rsa_key(struct rsa_raw_ctx *ctx)
{
- struct qat_rsa_ctx *ctx = context;
- struct qat_crypto_instance *inst = ctx->inst;
- struct device *dev = &GET_DEV(inst->accel_dev);
- const char *ptr = value;
- int ret;
+ struct rsa_raw_key *key = &ctx->key;
+ struct device *dev = ctx->dev;

- while (!*ptr && vlen) {
- ptr++;
- vlen--;
+ 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;
}

- ctx->key_sz = vlen;
- ret = -EINVAL;
- /* In FIPS mode only allow key size 2K & 3K */
- if (fips_enabled && (ctx->key_sz != 256 && ctx->key_sz != 384)) {
- pr_err("QAT: RSA: key size not allowed in FIPS mode\n");
- goto err;
+ if (key->e) {
+ dma_free_coherent(dev, key->n_sz, key->e, key->dma_e);
+ key->e = NULL;
}
- /* invalid key size provided */
- if (!qat_rsa_enc_fn_id(ctx->key_sz))
- goto err;

- ret = -ENOMEM;
- ctx->n = dma_zalloc_coherent(dev, ctx->key_sz, &ctx->dma_n, GFP_KERNEL);
- if (!ctx->n)
- goto err;
-
- memcpy(ctx->n, ptr, ctx->key_sz);
- return 0;
-err:
- ctx->key_sz = 0;
- ctx->n = NULL;
- return ret;
-}
-
-int qat_rsa_get_e(void *context, size_t hdrlen, unsigned char tag,
- const void *value, size_t vlen)
-{
- struct qat_rsa_ctx *ctx = context;
- struct qat_crypto_instance *inst = ctx->inst;
- struct device *dev = &GET_DEV(inst->accel_dev);
- const char *ptr = value;
-
- while (!*ptr && vlen) {
- ptr++;
- vlen--;
- }
-
- if (!ctx->key_sz || !vlen || vlen > ctx->key_sz) {
- ctx->e = NULL;
- return -EINVAL;
- }
-
- ctx->e = dma_zalloc_coherent(dev, ctx->key_sz, &ctx->dma_e, GFP_KERNEL);
- if (!ctx->e) {
- ctx->e = NULL;
- return -ENOMEM;
+ if (key->n) {
+ dma_free_coherent(dev, key->n_sz, key->n, key->dma_n);
+ key->n = NULL;
}
- memcpy(ctx->e + (ctx->key_sz - vlen), ptr, vlen);
- return 0;
-}
-
-int qat_rsa_get_d(void *context, size_t hdrlen, unsigned char tag,
- const void *value, size_t vlen)
-{
- struct qat_rsa_ctx *ctx = context;
- struct qat_crypto_instance *inst = ctx->inst;
- struct device *dev = &GET_DEV(inst->accel_dev);
- const char *ptr = value;
- int ret;
-
- while (!*ptr && vlen) {
- ptr++;
- vlen--;
- }
-
- ret = -EINVAL;
- if (!ctx->key_sz || !vlen || vlen > ctx->key_sz)
- goto err;
-
- /* In FIPS mode only allow key size 2K & 3K */
- if (fips_enabled && (vlen != 256 && vlen != 384)) {
- pr_err("QAT: RSA: key size not allowed in FIPS mode\n");
- goto err;
- }
-
- ret = -ENOMEM;
- ctx->d = dma_zalloc_coherent(dev, ctx->key_sz, &ctx->dma_d, GFP_KERNEL);
- if (!ctx->d)
- goto err;
-
- memcpy(ctx->d + (ctx->key_sz - vlen), ptr, vlen);
- return 0;
-err:
- ctx->d = NULL;
- return ret;
}

static int qat_rsa_setkey(struct crypto_akcipher *tfm, const void *key,
unsigned int keylen, bool private)
{
struct qat_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
- struct device *dev = &GET_DEV(ctx->inst->accel_dev);
+ struct rsa_raw_ctx *raw_ctx = &ctx->raw_key_ctx;
+ struct rsa_raw_key *raw_key = &raw_ctx->key;
int ret;

/* Free the old key if any */
- if (ctx->n)
- dma_free_coherent(dev, ctx->key_sz, ctx->n, ctx->dma_n);
- if (ctx->e)
- dma_free_coherent(dev, ctx->key_sz, ctx->e, ctx->dma_e);
- if (ctx->d) {
- memset(ctx->d, '\0', ctx->key_sz);
- dma_free_coherent(dev, ctx->key_sz, ctx->d, ctx->dma_d);
- }
-
- ctx->n = NULL;
- ctx->e = NULL;
- ctx->d = NULL;
+ qat_free_rsa_key(raw_ctx);

if (private)
- ret = asn1_ber_decoder(&qat_rsaprivkey_decoder, ctx, key,
+ ret = asn1_ber_decoder(&rsaprivkey_decoder, raw_ctx, key,
keylen);
else
- ret = asn1_ber_decoder(&qat_rsapubkey_decoder, ctx, key,
+ ret = asn1_ber_decoder(&rsapubkey_decoder, raw_ctx, key,
keylen);
if (ret < 0)
goto free;

- if (!ctx->n || !ctx->e) {
+ if (!raw_key->n || !raw_key->e) {
/* invalid key provided */
ret = -EINVAL;
goto free;
}
- if (private && !ctx->d) {
+ if (private && !raw_key->d) {
/* invalid private key provided */
ret = -EINVAL;
goto free;
@@ -646,73 +553,63 @@ static int qat_rsa_setkey(struct crypto_akcipher *tfm, const void *key,

return 0;
free:
- if (ctx->d) {
- memset(ctx->d, '\0', ctx->key_sz);
- dma_free_coherent(dev, ctx->key_sz, ctx->d, ctx->dma_d);
- ctx->d = NULL;
- }
- if (ctx->e) {
- dma_free_coherent(dev, ctx->key_sz, ctx->e, ctx->dma_e);
- ctx->e = NULL;
- }
- if (ctx->n) {
- dma_free_coherent(dev, ctx->key_sz, ctx->n, ctx->dma_n);
- ctx->n = NULL;
- ctx->key_sz = 0;
- }
+ qat_free_rsa_key(raw_ctx);
return ret;
}

static int qat_rsa_setpubkey(struct crypto_akcipher *tfm, const void *key,
unsigned int keylen)
{
+ struct qat_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
+
+ set_raw_rsa_pub_action(&ctx->raw_key_ctx.action);
return qat_rsa_setkey(tfm, key, keylen, false);
}

static int qat_rsa_setprivkey(struct crypto_akcipher *tfm, const void *key,
unsigned int keylen)
{
+ struct qat_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
+
+ set_raw_rsa_priv_action(&ctx->raw_key_ctx.action);
return qat_rsa_setkey(tfm, key, keylen, true);
}

static int qat_rsa_max_size(struct crypto_akcipher *tfm)
{
struct qat_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
+ struct rsa_raw_key *key = &ctx->raw_key_ctx.key;

- return (ctx->n) ? ctx->key_sz : -EINVAL;
+ return (key->n) ? key->n_sz : -EINVAL;
}

static int qat_rsa_init_tfm(struct crypto_akcipher *tfm)
{
struct qat_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
+ struct rsa_raw_key *key = &ctx->raw_key_ctx.key;
struct qat_crypto_instance *inst =
qat_crypto_get_instance_node(get_current_node());

if (!inst)
return -EINVAL;

- ctx->key_sz = 0;
+ key->n_sz = 0;
ctx->inst = inst;
+ ctx->raw_key_ctx.dev = &GET_DEV(ctx->inst->accel_dev);
+
+ /* alloc coherent key buffers */
+ key->is_coherent = false;
+ key->flags = GFP_KERNEL;
+
return 0;
}

static void qat_rsa_exit_tfm(struct crypto_akcipher *tfm)
{
struct qat_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
- struct device *dev = &GET_DEV(ctx->inst->accel_dev);
-
- if (ctx->n)
- dma_free_coherent(dev, ctx->key_sz, ctx->n, ctx->dma_n);
- if (ctx->e)
- dma_free_coherent(dev, ctx->key_sz, ctx->e, ctx->dma_e);
- if (ctx->d) {
- memset(ctx->d, '\0', ctx->key_sz);
- dma_free_coherent(dev, ctx->key_sz, ctx->d, ctx->dma_d);
- }
+
+ qat_free_rsa_key(&ctx->raw_key_ctx);
qat_crypto_put_instance(ctx->inst);
- ctx->n = NULL;
- ctx->e = NULL;
- ctx->d = NULL;
}

static struct akcipher_alg rsa = {
diff --git a/drivers/crypto/qat/qat_common/qat_rsaprivkey.asn1 b/drivers/crypto/qat/qat_common/qat_rsaprivkey.asn1
deleted file mode 100644
index f0066ad..0000000
--- a/drivers/crypto/qat/qat_common/qat_rsaprivkey.asn1
+++ /dev/null
@@ -1,11 +0,0 @@
-RsaPrivKey ::= SEQUENCE {
- version INTEGER,
- n INTEGER ({ qat_rsa_get_n }),
- e INTEGER ({ qat_rsa_get_e }),
- d INTEGER ({ qat_rsa_get_d }),
- prime1 INTEGER,
- prime2 INTEGER,
- exponent1 INTEGER,
- exponent2 INTEGER,
- coefficient INTEGER
-}
diff --git a/drivers/crypto/qat/qat_common/qat_rsapubkey.asn1 b/drivers/crypto/qat/qat_common/qat_rsapubkey.asn1
deleted file mode 100644
index bd667b3..0000000
--- a/drivers/crypto/qat/qat_common/qat_rsapubkey.asn1
+++ /dev/null
@@ -1,4 +0,0 @@
-RsaPubKey ::= SEQUENCE {
- n INTEGER ({ qat_rsa_get_n }),
- e INTEGER ({ qat_rsa_get_e })
-}
--
1.8.3.1

2016-03-18 18:32:34

by Tudor-Dan Ambarus

[permalink] [raw]
Subject: [PATCH 10/10] crypto: caam - add support for RSA algorithm

Add RSA support to caam driver.

Coauthored-by: Yashpal Dutta <[email protected]>

Signed-off-by: Tudor Ambarus <[email protected]>
---
drivers/crypto/caam/Kconfig | 12 +
drivers/crypto/caam/Makefile | 4 +
drivers/crypto/caam/caampkc.c | 513 +++++++++++++++++++++++++++++++++++++++++
drivers/crypto/caam/caampkc.h | 84 +++++++
drivers/crypto/caam/desc.h | 2 +
drivers/crypto/caam/pdb.h | 16 +-
drivers/crypto/caam/pkc_desc.c | 138 +++++++++++
7 files changed, 768 insertions(+), 1 deletion(-)
create mode 100644 drivers/crypto/caam/caampkc.c
create mode 100644 drivers/crypto/caam/caampkc.h
create mode 100644 drivers/crypto/caam/pkc_desc.c

diff --git a/drivers/crypto/caam/Kconfig b/drivers/crypto/caam/Kconfig
index 5652a53..5427e63 100644
--- a/drivers/crypto/caam/Kconfig
+++ b/drivers/crypto/caam/Kconfig
@@ -99,6 +99,18 @@ config CRYPTO_DEV_FSL_CAAM_AHASH_API
To compile this as a module, choose M here: the module
will be called caamhash.

+config CRYPTO_DEV_FSL_CAAM_PKC_API
+ tristate "Register public key cryptography implementations with Crypto API"
+ depends on CRYPTO_DEV_FSL_CAAM && CRYPTO_DEV_FSL_CAAM_JR
+ default y
+ select CRYPTO_RSA_HELPER
+ help
+ Selecting this will allow SEC Public key support for RSA.
+ Supported cryptographic primitives: encryption, decryption,
+ signature and verification.
+ To compile this as a module, choose M here: the module
+ will be called caam_pkc.
+
config CRYPTO_DEV_FSL_CAAM_RNG_API
tristate "Register caam device for hwrng API"
depends on CRYPTO_DEV_FSL_CAAM && CRYPTO_DEV_FSL_CAAM_JR
diff --git a/drivers/crypto/caam/Makefile b/drivers/crypto/caam/Makefile
index 550758a..399ad55 100644
--- a/drivers/crypto/caam/Makefile
+++ b/drivers/crypto/caam/Makefile
@@ -5,11 +5,15 @@ ifeq ($(CONFIG_CRYPTO_DEV_FSL_CAAM_DEBUG), y)
EXTRA_CFLAGS := -DDEBUG
endif

+ccflags-y += -I$(srctree)/crypto
+
obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM) += caam.o
obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_JR) += caam_jr.o
obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API) += caamalg.o
obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_AHASH_API) += caamhash.o
obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_API) += caamrng.o
+obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_PKC_API) += caam_pkc.o

caam-objs := ctrl.o
caam_jr-objs := jr.o key_gen.o error.o
+caam_pkc-y := caampkc.o pkc_desc.o
diff --git a/drivers/crypto/caam/caampkc.c b/drivers/crypto/caam/caampkc.c
new file mode 100644
index 0000000..1c53158
--- /dev/null
+++ b/drivers/crypto/caam/caampkc.c
@@ -0,0 +1,513 @@
+/*
+ * caam - Freescale FSL CAAM support for Public Key Cryptography
+ *
+ * Copyright 2016 Freescale Semiconductor, Inc.
+ *
+ * There is no Shared Descriptor for PKC so that the Job Descriptor must carry
+ * all the desired key parameters, input and output pointers.
+ */
+#include <linux/dma-mapping.h>
+#include <linux/fips.h>
+#include "compat.h"
+#include "caampkc.h"
+#include "sg_sw_sec4.h"
+#include "regs.h"
+#include "intern.h"
+#include "jr.h"
+#include "error.h"
+
+void 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;
+}
+
+static int caam_rsa_setpubkey(struct crypto_akcipher *tfm, const void *key,
+ unsigned int keylen)
+{
+ struct rsa_raw_ctx *ctx = akcipher_tfm_ctx(tfm);
+ struct rsa_raw_key *raw_key = &ctx->key;
+ int ret;
+
+ set_raw_rsa_pub_action(&ctx->action);
+
+ /* Free the old key if any */
+ rsa_free_key(raw_key);
+
+ ret = asn1_ber_decoder(&rsapubkey_decoder, ctx, key, keylen);
+ if (ret < 0)
+ goto free;
+
+ if (!raw_key->n || !raw_key->e) {
+ /* Invalid key provided */
+ ret = -EINVAL;
+ goto free;
+ }
+
+ return 0;
+free:
+ rsa_free_key(raw_key);
+ return ret;
+}
+
+static int caam_rsa_setprivkey(struct crypto_akcipher *tfm, const void *key,
+ unsigned int keylen)
+{
+ struct rsa_raw_ctx *ctx = akcipher_tfm_ctx(tfm);
+ struct rsa_raw_key *raw_key = &ctx->key;
+ int ret;
+
+ set_raw_rsa_priv_action(&ctx->action);
+
+ /* Free the old key if any */
+ rsa_free_key(raw_key);
+
+ ret = asn1_ber_decoder(&rsaprivkey_decoder, ctx, key, keylen);
+ if (ret < 0)
+ goto free;
+
+ if (!raw_key->n || !raw_key->e || !raw_key->d) {
+ /* Invalid key provided */
+ ret = -EINVAL;
+ goto free;
+ }
+
+ return 0;
+free:
+ rsa_free_key(raw_key);
+ return ret;
+}
+
+static void rsa_pub_unmap(struct device *dev, struct rsa_edesc *edesc,
+ struct akcipher_request *req)
+{
+ struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
+ struct rsa_raw_ctx *ctx = akcipher_tfm_ctx(tfm);
+ struct rsa_raw_key *key = &ctx->key;
+ struct rsa_pub_desc *hw_desc = (struct rsa_pub_desc *)edesc->hw_desc;
+
+ dma_unmap_single(dev, hw_desc->n_dma, key->n_sz, DMA_TO_DEVICE);
+ dma_unmap_single(dev, hw_desc->e_dma, key->e_sz, DMA_TO_DEVICE);
+ dma_unmap_sg(dev, req->dst, edesc->dst_nents, DMA_FROM_DEVICE);
+ dma_unmap_sg(dev, req->src, edesc->src_nents, DMA_TO_DEVICE);
+}
+
+static void rsa_priv_f1_unmap(struct device *dev, struct rsa_edesc *edesc,
+ struct akcipher_request *req)
+{
+ struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
+ struct rsa_raw_ctx *ctx = akcipher_tfm_ctx(tfm);
+ struct rsa_raw_key *key = &ctx->key;
+ struct rsa_priv_f1_desc *hw_desc =
+ (struct rsa_priv_f1_desc *)edesc->hw_desc;
+
+ dma_unmap_single(dev, hw_desc->n_dma, key->n_sz, DMA_TO_DEVICE);
+ dma_unmap_single(dev, hw_desc->d_dma, key->n_sz, DMA_TO_DEVICE);
+ dma_unmap_sg(dev, req->dst, edesc->dst_nents, DMA_FROM_DEVICE);
+ dma_unmap_sg(dev, req->src, edesc->src_nents, DMA_TO_DEVICE);
+}
+
+static size_t skip_to_nonzero(u8 *ptr, size_t nbytes)
+{
+ size_t nr_zeros = 0;
+
+ while (!(*ptr) && nbytes) {
+ nbytes--;
+ ptr++;
+ nr_zeros++;
+ }
+
+ return nr_zeros;
+}
+
+static size_t scatterwalk_skip_zeros(struct scatter_walk *walk, size_t nbytes)
+{
+ size_t len_this_page, nr_zeros, cnt = 0;
+ u8 *vaddr, *ptr;
+
+ for (;;) {
+ nr_zeros = 0;
+ len_this_page = scatterwalk_pagelen(walk);
+
+ if (len_this_page > nbytes)
+ len_this_page = nbytes;
+
+ vaddr = scatterwalk_map(walk);
+ ptr = vaddr;
+ nr_zeros = skip_to_nonzero(ptr, len_this_page);
+ scatterwalk_unmap(vaddr);
+
+ /* count total number of zeros */
+ cnt += nr_zeros;
+
+ /* advance scatterwalk to the nonzero data */
+ scatterwalk_advance(walk, nr_zeros);
+
+ if (nr_zeros < len_this_page || nbytes == len_this_page)
+ break;
+
+ nbytes -= len_this_page;
+
+ scatterwalk_pagedone(walk, 0, 1);
+ }
+
+ return cnt;
+}
+
+/*
+ * This function drops the leading zeros and copies the data to the initial
+ * pointer so that it can be freed later on. Returns the updated data length.
+ */
+static size_t drop_leading_zeros(struct scatterlist *sg, size_t nbytes)
+{
+ struct scatter_walk walk_src, walk_dst;
+ size_t nr_zeros = 0;
+
+ scatterwalk_start(&walk_src, sg);
+ nr_zeros = scatterwalk_skip_zeros(&walk_src, nbytes);
+
+ if (nr_zeros) {
+ nbytes = nbytes - nr_zeros;
+
+ scatterwalk_start(&walk_dst, sg);
+ scatterwalk_sg_copychunks(&walk_dst, &walk_src, nbytes);
+ scatterwalk_done(&walk_dst, 0, 0);
+ }
+
+ scatterwalk_done(&walk_src, 0, 0);
+
+ return nbytes;
+}
+
+/* RSA Job Completion handler */
+static void rsa_pub_done(struct device *dev, u32 *desc, u32 err, void *context)
+{
+ struct akcipher_request *req = context;
+ struct rsa_edesc *edesc;
+
+ if (err)
+ caam_jr_strstatus(dev, err);
+
+ /*
+ * RSA's output is expected to be a big integer. Drop the leading
+ * zeros since they are not meaningful in the world of numbers.
+ */
+ req->dst_len = drop_leading_zeros(req->dst, req->dst_len);
+
+ edesc = container_of(desc, struct rsa_edesc, hw_desc[0]);
+
+ rsa_pub_unmap(dev, edesc, req);
+ kfree(edesc);
+
+ akcipher_request_complete(req, err);
+}
+
+static void rsa_priv_f1_done(struct device *dev, u32 *desc, u32 err,
+ void *context)
+{
+ struct akcipher_request *req = context;
+ struct rsa_edesc *edesc;
+
+ if (err)
+ caam_jr_strstatus(dev, err);
+
+ /*
+ * RSA's output is expected to be a big integer. Drop the leading
+ * zeros since they are not meaningful in the world of numbers.
+ */
+ req->dst_len = drop_leading_zeros(req->dst, req->dst_len);
+
+ edesc = container_of(desc, struct rsa_edesc, hw_desc[0]);
+
+ rsa_priv_f1_unmap(dev, edesc, req);
+ kfree(edesc);
+
+ akcipher_request_complete(req, err);
+}
+
+static struct rsa_edesc *rsa_edesc_alloc(struct akcipher_request *req,
+ size_t desclen)
+{
+ struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
+ struct rsa_raw_ctx *ctx = akcipher_tfm_ctx(tfm);
+ struct device *dev = ctx->dev;
+ struct rsa_edesc *edesc;
+ gfp_t flags = (req->base.flags & (CRYPTO_TFM_REQ_MAY_BACKLOG |
+ CRYPTO_TFM_REQ_MAY_SLEEP)) ? GFP_KERNEL : GFP_ATOMIC;
+ int sgc;
+ int sec4_sg_index, sec4_sg_len = 0, sec4_sg_bytes;
+ int src_nents, dst_nents;
+
+ src_nents = sg_nents_for_len(req->src, req->src_len);
+ dst_nents = sg_nents_for_len(req->dst, req->dst_len);
+
+ if (src_nents > 1)
+ sec4_sg_len = src_nents;
+ if (dst_nents > 1)
+ sec4_sg_len += dst_nents;
+
+ sec4_sg_bytes = sec4_sg_len * sizeof(struct sec4_sg_entry);
+
+ /* allocate space for base edesc, hw desc commands and link tables */
+ edesc = kzalloc(sizeof(*edesc) + desclen + sec4_sg_bytes,
+ GFP_DMA | flags);
+ if (!edesc)
+ return ERR_PTR(-ENOMEM);
+
+ sgc = dma_map_sg(dev, req->src, src_nents, DMA_TO_DEVICE);
+ if (unlikely(!sgc)) {
+ dev_err(dev, "unable to map source\n");
+ goto src_fail;
+ }
+
+ sgc = dma_map_sg(dev, req->dst, dst_nents, DMA_FROM_DEVICE);
+ if (unlikely(!sgc)) {
+ dev_err(dev, "unable to map destination\n");
+ goto dst_fail;
+ }
+
+ edesc->sec4_sg = (void *)edesc + sizeof(*edesc) + desclen;
+
+ sec4_sg_index = 0;
+ if (src_nents > 1) {
+ sg_to_sec4_sg_last(req->src, src_nents, edesc->sec4_sg, 0);
+ sec4_sg_index += src_nents;
+ }
+ if (dst_nents > 1) {
+ sg_to_sec4_sg_last(req->dst, dst_nents,
+ edesc->sec4_sg + sec4_sg_index, 0);
+ }
+
+ /* Save nents for later use in Job Descriptor. */
+ edesc->src_nents = src_nents;
+ edesc->dst_nents = dst_nents;
+
+ if (!sec4_sg_bytes)
+ return edesc;
+
+ edesc->sec4_sg_dma = dma_map_single(dev, edesc->sec4_sg,
+ sec4_sg_bytes, DMA_TO_DEVICE);
+ if (dma_mapping_error(dev, edesc->sec4_sg_dma)) {
+ dev_err(dev, "unable to map S/G table\n");
+ goto sec4_sg_fail;
+ }
+
+ return edesc;
+
+sec4_sg_fail:
+ dma_unmap_sg(dev, req->dst, dst_nents, DMA_FROM_DEVICE);
+dst_fail:
+ dma_unmap_sg(dev, req->src, src_nents, DMA_TO_DEVICE);
+src_fail:
+ kfree(edesc);
+ return ERR_PTR(-ENOMEM);
+}
+
+static int caam_rsa_enc(struct akcipher_request *req)
+{
+ struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
+ struct rsa_raw_ctx *ctx = akcipher_tfm_ctx(tfm);
+ struct rsa_raw_key *key = &ctx->key;
+ struct device *jrdev = ctx->dev;
+ struct rsa_edesc *edesc = NULL;
+ size_t desclen = sizeof(struct rsa_pub_desc);
+ int ret;
+
+ if (unlikely(!key->n || !key->e))
+ return -EINVAL;
+
+ if (req->dst_len < key->n_sz) {
+ req->dst_len = key->n_sz;
+ dev_err(jrdev, "Output buffer length less than parameter n\n");
+ return -EOVERFLOW;
+ }
+
+ /* Allocate extended descriptor. */
+ edesc = rsa_edesc_alloc(req, desclen);
+ if (IS_ERR(edesc))
+ return PTR_ERR(edesc);
+
+ /* Initialize Job Descriptor. */
+ ret = init_rsa_pub_desc(req, edesc);
+ if (ret)
+ return ret;
+
+ ret = caam_jr_enqueue(jrdev, edesc->hw_desc, rsa_pub_done, req);
+ if (!ret) {
+ ret = -EINPROGRESS;
+ } else {
+ rsa_pub_unmap(jrdev, edesc, req);
+ kfree(edesc);
+ }
+
+ return ret;
+}
+
+static int caam_rsa_dec(struct akcipher_request *req)
+{
+ struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
+ struct rsa_raw_ctx *ctx = akcipher_tfm_ctx(tfm);
+ struct rsa_raw_key *key = &ctx->key;
+ struct device *jrdev = ctx->dev;
+ struct rsa_edesc *edesc = NULL;
+ size_t desclen = sizeof(struct rsa_priv_f1_desc);
+ int ret;
+
+ if (unlikely(!key->n || !key->d))
+ return -EINVAL;
+
+ if (req->dst_len < key->n_sz) {
+ req->dst_len = key->n_sz;
+ return -EOVERFLOW;
+ }
+
+ /* Allocate extended descriptor. */
+ edesc = rsa_edesc_alloc(req, desclen);
+ if (IS_ERR(edesc))
+ return PTR_ERR(edesc);
+
+ /* Initialize Job Descriptor. */
+ ret = init_rsa_priv_f1_desc(req, edesc);
+ if (ret)
+ return ret;
+
+ ret = caam_jr_enqueue(jrdev, edesc->hw_desc, rsa_priv_f1_done, req);
+ if (!ret) {
+ ret = -EINPROGRESS;
+ } else {
+ rsa_priv_f1_unmap(jrdev, edesc, req);
+ kfree(edesc);
+ }
+
+ return ret;
+}
+
+static int caam_rsa_max_size(struct crypto_akcipher *tfm)
+{
+ struct rsa_raw_ctx *ctx = akcipher_tfm_ctx(tfm);
+ struct rsa_raw_key *key = &ctx->key;
+
+ return (key->n) ? key->n_sz : -EINVAL;
+}
+
+/* Per session pkc's driver context creation function */
+static int caam_rsa_init_tfm(struct crypto_akcipher *tfm)
+{
+ struct rsa_raw_ctx *ctx = akcipher_tfm_ctx(tfm);
+ struct rsa_raw_key *key = &ctx->key;
+
+ ctx->dev = caam_jr_alloc();
+
+ if (IS_ERR(ctx->dev)) {
+ dev_err(ctx->dev, "Job Ring Device allocation for transform failed\n");
+ return PTR_ERR(ctx->dev);
+ }
+
+ key->is_coherent = true;
+ key->flags = GFP_DMA | GFP_KERNEL;
+ return 0;
+}
+
+/* Per session pkc's driver context cleanup function */
+static void caam_rsa_exit_tfm(struct crypto_akcipher *tfm)
+{
+ struct rsa_raw_ctx *ctx = akcipher_tfm_ctx(tfm);
+ struct rsa_raw_key *key = &ctx->key;
+
+ rsa_free_key(key);
+ caam_jr_free(ctx->dev);
+}
+
+static struct akcipher_alg rsa = {
+ .encrypt = caam_rsa_enc,
+ .decrypt = caam_rsa_dec,
+ .sign = caam_rsa_dec,
+ .verify = caam_rsa_enc,
+ .set_pub_key = caam_rsa_setpubkey,
+ .set_priv_key = caam_rsa_setprivkey,
+ .max_size = caam_rsa_max_size,
+ .init = caam_rsa_init_tfm,
+ .exit = caam_rsa_exit_tfm,
+ .base = {
+ .cra_name = "rsa",
+ .cra_driver_name = "rsa-caam",
+ .cra_priority = 3000,
+ .cra_module = THIS_MODULE,
+ .cra_alignmask = 0,
+ .cra_ctxsize = sizeof(struct rsa_raw_ctx),
+ },
+};
+
+/* Public Key Cryptography module initialization handler */
+static int __init caam_pkc_init(void)
+{
+ struct device_node *dev_node;
+ struct platform_device *pdev;
+ struct device *ctrldev;
+ struct caam_drv_private *priv;
+ u32 cha_inst, pk_inst;
+ int err = 0;
+
+ dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0");
+ if (!dev_node) {
+ dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec4.0");
+ if (!dev_node)
+ return -ENODEV;
+ }
+
+ pdev = of_find_device_by_node(dev_node);
+ if (!pdev) {
+ of_node_put(dev_node);
+ return -ENODEV;
+ }
+
+ ctrldev = &pdev->dev;
+ priv = dev_get_drvdata(ctrldev);
+ of_node_put(dev_node);
+
+ /*
+ * If priv is NULL, it's probably because the caam driver wasn't
+ * properly initialized (e.g. RNG4 init failed). Thus, bail out here.
+ */
+ if (!priv)
+ return -ENODEV;
+
+ /* Determine public key hardware accelerator presence. */
+ cha_inst = rd_reg32(&priv->ctrl->perfmon.cha_num_ls);
+ pk_inst = (cha_inst & CHA_ID_LS_PK_MASK) >> CHA_ID_LS_PK_SHIFT;
+
+ /* Do not register algorithms if PKHA is not present. */
+ if (!pk_inst)
+ return -ENODEV;
+
+ rsa.base.cra_flags = 0;
+ err = crypto_register_akcipher(&rsa);
+ if (err)
+ dev_warn(ctrldev, "%s alg registration failed\n",
+ rsa.base.cra_driver_name);
+ else
+ dev_info(ctrldev, "caam algorithms registered in /proc/crypto\n");
+
+ return err;
+}
+
+static void __exit caam_pkc_exit(void)
+{
+ crypto_unregister_akcipher(&rsa);
+}
+
+module_init(caam_pkc_init);
+module_exit(caam_pkc_exit);
+
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_DESCRIPTION("FSL CAAM support for PKC functions of crypto API");
+MODULE_AUTHOR("Freescale Semiconductor");
diff --git a/drivers/crypto/caam/caampkc.h b/drivers/crypto/caam/caampkc.h
new file mode 100644
index 0000000..a49d7da
--- /dev/null
+++ b/drivers/crypto/caam/caampkc.h
@@ -0,0 +1,84 @@
+/*
+ * caam - Freescale FSL CAAM support for Public Key Cryptography descriptors
+ *
+ * Copyright 2016 Freescale Semiconductor, Inc.
+ *
+ * There is no Shared Descriptor for PKC so that the Job Descriptor must carry
+ * all the desired key parameters, input and output pointers.
+ */
+
+#ifndef _PKC_DESC_H_
+#define _PKC_DESC_H_
+
+#include <crypto/internal/rsa.h>
+#include <crypto/akcipher.h>
+#include <crypto/internal/akcipher.h>
+#include "desc_constr.h"
+#include "pdb.h"
+#include "rsapubkey-asn1.h"
+#include "rsaprivkey-asn1.h"
+
+/**
+ * RSA Pub_Key Descriptor
+ * @desc_hdr: Job Descriptor Header command
+ * @sgf: scatter-gather field
+ * @f_dma: dma address of input data
+ * @g_dma: dma address of ecrypted output data
+ * @n_dma: dma address of RSA public exponent
+ * @dma_e: dma address of RSA public exponent
+ * @f_len: length in octets of the input data
+ * @op: RSA Operation command
+ */
+struct rsa_pub_desc {
+ u32 desc_hdr;
+ u32 sgf;
+ dma_addr_t f_dma;
+ dma_addr_t g_dma;
+ dma_addr_t n_dma;
+ dma_addr_t e_dma;
+ u32 f_len;
+ u32 op;
+} __packed;
+
+/**
+ * Form1 Priv_key Decryption Descriptor.
+ * Private key is represented by (n,d).
+ * @desc_hdr: Job Descriptor Header command
+ * @sgf: scatter-gather field
+ * @g_dma: dma address of ecrypted input data
+ * @f_dma: dma address of output data
+ * @n_dma: dma address of RSA public exponent
+ * @dma_d: dma address of RSA private exponent
+ * @op: RSA Operation command
+ */
+struct rsa_priv_f1_desc {
+ u32 desc_hdr;
+ u32 sgf;
+ dma_addr_t g_dma;
+ dma_addr_t f_dma;
+ dma_addr_t n_dma;
+ dma_addr_t d_dma;
+ u32 op;
+} __packed;
+
+/**
+ * rsa_edesc - s/w-extended rsa descriptor
+ * @src_nents: number of segments in input scatterlist
+ * @dst_nents: number of segments in output scatterlist
+ * @sec4_sg_dma: dma address of h/w link table
+ * @sec4_sg: pointer to h/w link table
+ * @hw_desc: descriptor followed by link tables if any
+ */
+struct rsa_edesc {
+ int src_nents;
+ int dst_nents;
+ dma_addr_t sec4_sg_dma;
+ struct sec4_sg_entry *sec4_sg;
+ u32 hw_desc[];
+};
+
+/* Descriptor construction primitives. */
+int init_rsa_pub_desc(struct akcipher_request *req, struct rsa_edesc *edesc);
+int init_rsa_priv_f1_desc(struct akcipher_request *req,
+ struct rsa_edesc *edesc);
+#endif
diff --git a/drivers/crypto/caam/desc.h b/drivers/crypto/caam/desc.h
index 1e93c6a..7e5c027 100644
--- a/drivers/crypto/caam/desc.h
+++ b/drivers/crypto/caam/desc.h
@@ -454,6 +454,8 @@ struct sec4_sg_entry {
#define OP_PCLID_PUBLICKEYPAIR (0x14 << OP_PCLID_SHIFT)
#define OP_PCLID_DSASIGN (0x15 << OP_PCLID_SHIFT)
#define OP_PCLID_DSAVERIFY (0x16 << OP_PCLID_SHIFT)
+#define OP_PCLID_RSAENC_PUBKEY (0x18 << OP_PCLID_SHIFT)
+#define OP_PCLID_RSADEC_PRVKEY (0x19 << OP_PCLID_SHIFT)

/* Assuming OP_TYPE = OP_TYPE_DECAP_PROTOCOL/ENCAP_PROTOCOL */
#define OP_PCLID_IPSEC (0x01 << OP_PCLID_SHIFT)
diff --git a/drivers/crypto/caam/pdb.h b/drivers/crypto/caam/pdb.h
index 3a87c0c..1c68d7b 100644
--- a/drivers/crypto/caam/pdb.h
+++ b/drivers/crypto/caam/pdb.h
@@ -1,7 +1,7 @@
/*
* CAAM Protocol Data Block (PDB) definition header file
*
- * Copyright 2008-2012 Freescale Semiconductor, Inc.
+ * Copyright 2008-2016 Freescale Semiconductor, Inc.
*
*/

@@ -399,4 +399,18 @@ struct dsa_verify_pdb {
u8 *ab; /* only used if ECC processing */
};

+/* RSA Protocol Data Block */
+#define RSA_PDB_SGF_SHIFT 28
+#define RSA_PDB_E_SHIFT 12
+#define RSA_PDB_E_MASK (0xFFF << RSA_PDB_E_SHIFT)
+#define RSA_PDB_D_SHIFT 12
+#define RSA_PDB_D_MASK (0xFFF << RSA_PDB_D_SHIFT)
+
+#define RSA_PDB_SGF_F (0x8 << RSA_PDB_SGF_SHIFT)
+#define RSA_PDB_SGF_G (0x4 << RSA_PDB_SGF_SHIFT)
+#define RSA_PRIV_PDB_SGF_F (0x4 << RSA_PDB_SGF_SHIFT)
+#define RSA_PRIV_PDB_SGF_G (0x8 << RSA_PDB_SGF_SHIFT)
+
+#define RSA_PRIV_KEY_FRM_1 0
+
#endif
diff --git a/drivers/crypto/caam/pkc_desc.c b/drivers/crypto/caam/pkc_desc.c
new file mode 100644
index 0000000..5ef4082
--- /dev/null
+++ b/drivers/crypto/caam/pkc_desc.c
@@ -0,0 +1,138 @@
+/*
+ * caam - Freescale FSL CAAM support for Public Key Cryptography descriptors
+ *
+ * Copyright 2016 Freescale Semiconductor, Inc.
+ *
+ * There is no Shared Descriptor for PKC so that the Job Descriptor must carry
+ * all the desired key parameters, input and output pointers.
+ */
+#include "caampkc.h"
+
+/* Descriptor for RSA Public operation */
+int init_rsa_pub_desc(struct akcipher_request *req, struct rsa_edesc *edesc)
+{
+ struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
+ struct rsa_raw_ctx *ctx = akcipher_tfm_ctx(tfm);
+ struct rsa_raw_key *key = &ctx->key;
+ struct device *dev = ctx->dev;
+ struct rsa_pub_desc *desc = (struct rsa_pub_desc *)edesc->hw_desc;
+ u32 start_idx, desc_size;
+ int sec4_sg_index = 0;
+
+ /*
+ * The PDB has static fields and can be initialized before writing
+ * a specific command. Map the memory first, since it can be a point
+ * of failure.
+ */
+ desc->n_dma = dma_map_single(dev, key->n, key->n_sz, DMA_TO_DEVICE);
+ if (dma_mapping_error(dev, desc->n_dma)) {
+ dev_err(dev, "Unable to map modulus memory\n");
+ goto n_fail;
+ }
+
+ desc->e_dma = dma_map_single(dev, key->e, key->e_sz, DMA_TO_DEVICE);
+ if (dma_mapping_error(dev, desc->e_dma)) {
+ dev_err(dev, "Unable to map exponent memory\n");
+ goto e_fail;
+ }
+
+ desc_size = sizeof(*desc) / CAAM_CMD_SZ;
+ start_idx = (desc_size - 1) & HDR_START_IDX_MASK;
+ init_job_desc(edesc->hw_desc, (start_idx << HDR_START_IDX_SHIFT) |
+ (start_idx & HDR_DESCLEN_MASK) | HDR_ONE);
+
+ sec4_sg_index = 0;
+ if (edesc->src_nents > 1) {
+ desc->sgf |= RSA_PDB_SGF_F;
+ desc->f_dma = edesc->sec4_sg_dma;
+ sec4_sg_index += edesc->src_nents;
+ } else {
+ desc->f_dma = sg_dma_address(req->src);
+ }
+
+ if (edesc->dst_nents > 1) {
+ desc->sgf |= RSA_PDB_SGF_G;
+ desc->g_dma = edesc->sec4_sg_dma +
+ sec4_sg_index * sizeof(struct sec4_sg_entry);
+ } else {
+ desc->g_dma = sg_dma_address(req->dst);
+ }
+
+ desc->sgf |= (key->e_sz << RSA_PDB_E_SHIFT) | key->n_sz;
+ desc->f_len = req->src_len;
+ desc->op = CMD_OPERATION | OP_TYPE_UNI_PROTOCOL |
+ OP_PCLID_RSAENC_PUBKEY;
+ return 0;
+
+e_fail:
+ dma_unmap_single(dev, desc->n_dma, key->n_sz, DMA_TO_DEVICE);
+n_fail:
+ dma_unmap_sg(dev, req->dst, edesc->dst_nents, DMA_FROM_DEVICE);
+ dma_unmap_sg(dev, req->src, edesc->src_nents, DMA_TO_DEVICE);
+ kfree(edesc);
+ return -ENOMEM;
+}
+
+/* Descriptor for RSA Private operation */
+int init_rsa_priv_f1_desc(struct akcipher_request *req, struct rsa_edesc *edesc)
+{
+ struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
+ struct rsa_raw_ctx *ctx = akcipher_tfm_ctx(tfm);
+ struct rsa_raw_key *key = &ctx->key;
+ struct device *dev = ctx->dev;
+ struct rsa_priv_f1_desc *desc =
+ (struct rsa_priv_f1_desc *)edesc->hw_desc;
+ int sec4_sg_index = 0;
+ u32 start_idx, desc_size;
+
+ /*
+ * The PDB has static fields and can be initialized before writing
+ * a specific command. Map the memory first, since it can be a point
+ * of failure.
+ */
+ desc->n_dma = dma_map_single(dev, key->n, key->n_sz, DMA_TO_DEVICE);
+ if (dma_mapping_error(dev, desc->n_dma)) {
+ dev_err(dev, "Unable to map modulus memory\n");
+ goto n_fail;
+ }
+
+ desc->d_dma = dma_map_single(dev, key->d, key->n_sz, DMA_TO_DEVICE);
+ if (dma_mapping_error(dev, desc->d_dma)) {
+ dev_err(dev, "Unable to map exponent memory\n");
+ goto d_fail;
+ }
+
+ desc_size = sizeof(*desc) / CAAM_CMD_SZ;
+ start_idx = (desc_size - 1) & HDR_START_IDX_MASK;
+ init_job_desc(edesc->hw_desc, (start_idx << HDR_START_IDX_SHIFT) |
+ (start_idx & HDR_DESCLEN_MASK) | HDR_ONE);
+
+ if (edesc->src_nents > 1) {
+ desc->sgf |= RSA_PRIV_PDB_SGF_G;
+ desc->g_dma = edesc->sec4_sg_dma;
+ sec4_sg_index += edesc->src_nents;
+ } else {
+ desc->g_dma = sg_dma_address(req->src);
+ }
+
+ if (edesc->dst_nents > 1) {
+ desc->sgf |= RSA_PRIV_PDB_SGF_F;
+ desc->f_dma = edesc->sec4_sg_dma +
+ sec4_sg_index * sizeof(struct sec4_sg_entry);
+ } else {
+ desc->f_dma = sg_dma_address(req->dst);
+ }
+
+ desc->sgf |= (key->n_sz << RSA_PDB_D_SHIFT) | key->n_sz;
+ desc->op = CMD_OPERATION | OP_TYPE_UNI_PROTOCOL |
+ OP_PCLID_RSADEC_PRVKEY | RSA_PRIV_KEY_FRM_1;
+ return 0;
+
+d_fail:
+ dma_unmap_single(dev, desc->n_dma, key->n_sz, DMA_TO_DEVICE);
+n_fail:
+ dma_unmap_sg(dev, req->dst, edesc->dst_nents, DMA_FROM_DEVICE);
+ dma_unmap_sg(dev, req->src, edesc->src_nents, DMA_TO_DEVICE);
+ kfree(edesc);
+ return -ENOMEM;
+}
--
1.8.3.1

2016-03-18 18:47:08

by Tudor-Dan Ambarus

[permalink] [raw]
Subject: [PATCH 06/10] crypto: qat - fix address leaking of RSA public exponent

Signed-off-by: Tudor Ambarus <[email protected]>
---
drivers/crypto/qat/qat_common/qat_asym_algs.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/crypto/qat/qat_common/qat_asym_algs.c b/drivers/crypto/qat/qat_common/qat_asym_algs.c
index 8dbbf084..05f49d4 100644
--- a/drivers/crypto/qat/qat_common/qat_asym_algs.c
+++ b/drivers/crypto/qat/qat_common/qat_asym_algs.c
@@ -711,7 +711,7 @@ static void qat_rsa_exit_tfm(struct crypto_akcipher *tfm)
}
qat_crypto_put_instance(ctx->inst);
ctx->n = NULL;
- ctx->d = NULL;
+ ctx->e = NULL;
ctx->d = NULL;
}

--
1.8.3.1

2016-03-18 18:47:17

by Tudor-Dan Ambarus

[permalink] [raw]
Subject: [PATCH 05/10] crypto: qat - avoid memory corruption or undefined behaviour

memcopying to a (null pointer + offset) will result
in memory corruption or undefined behaviour.

Signed-off-by: Tudor Ambarus <[email protected]>
---
drivers/crypto/qat/qat_common/qat_asym_algs.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/crypto/qat/qat_common/qat_asym_algs.c b/drivers/crypto/qat/qat_common/qat_asym_algs.c
index e5c0727..8dbbf084 100644
--- a/drivers/crypto/qat/qat_common/qat_asym_algs.c
+++ b/drivers/crypto/qat/qat_common/qat_asym_algs.c
@@ -593,7 +593,7 @@ int qat_rsa_get_d(void *context, size_t hdrlen, unsigned char tag,

ret = -ENOMEM;
ctx->d = dma_zalloc_coherent(dev, ctx->key_sz, &ctx->dma_d, GFP_KERNEL);
- if (!ctx->n)
+ if (!ctx->d)
goto err;

memcpy(ctx->d + (ctx->key_sz - vlen), ptr, vlen);
--
1.8.3.1

2016-03-18 18:48:04

by Tudor-Dan Ambarus

[permalink] [raw]
Subject: [PATCH 03/10] 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]>
---
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

2016-03-18 19:46:54

by Stephan Müller

[permalink] [raw]
Subject: Re: [PATCH 02/10] crypto: rsa_helper - add raw integer parser actions

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 <[email protected]>
> ---
> 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

2016-03-18 19:52:41

by Stephan Müller

[permalink] [raw]
Subject: Re: [PATCH 08/10] crypto: scatterwak - Add scatterwalk_sg_copychunks

Am Freitag, 18. M?rz 2016, 20:32:05 schrieb Tudor Ambarus:

Hi Tudor,

> This patch adds the function scatterwalk_sg_copychunks which writes
> a chunk of data from a scatterwalk to another scatterwalk.
> It will be used by caam driver to remove the leading zeros of RSA's
> algorithm output.

The following is unrelated to the patch, but regarding your statement: I
lately read that leading zeros are skipped for RSA. Why is that implemented
this way? The driver of my question is side channels. Don't we open ourselves
up to side channel attacks when forgetting about zeros?

Heck, by simply processing zeros in a modular exponentiation (of a private
key), we have side channels, because processing of zeros is faster than ones.
I am starting to wonder whether this magic with the leading zeros is going to
hurt us?

Ciao
Stephan

2016-03-19 16:59:23

by Stephan Müller

[permalink] [raw]
Subject: Re: [PATCH 10/10] crypto: caam - add support for RSA algorithm

Am Freitag, 18. M?rz 2016, 20:32:07 schrieb Tudor Ambarus:

Hi Tudor,

> Add RSA support to caam driver.
>
> Coauthored-by: Yashpal Dutta <[email protected]>
>
> Signed-off-by: Tudor Ambarus <[email protected]>
> ---
> drivers/crypto/caam/Kconfig | 12 +
> drivers/crypto/caam/Makefile | 4 +
> drivers/crypto/caam/caampkc.c | 513
> +++++++++++++++++++++++++++++++++++++++++ drivers/crypto/caam/caampkc.h |
> 84 +++++++
> drivers/crypto/caam/desc.h | 2 +
> drivers/crypto/caam/pdb.h | 16 +-
> drivers/crypto/caam/pkc_desc.c | 138 +++++++++++
> 7 files changed, 768 insertions(+), 1 deletion(-)
> create mode 100644 drivers/crypto/caam/caampkc.c
> create mode 100644 drivers/crypto/caam/caampkc.h
> create mode 100644 drivers/crypto/caam/pkc_desc.c
>
> diff --git a/drivers/crypto/caam/Kconfig b/drivers/crypto/caam/Kconfig
> index 5652a53..5427e63 100644
> --- a/drivers/crypto/caam/Kconfig
> +++ b/drivers/crypto/caam/Kconfig
> @@ -99,6 +99,18 @@ config CRYPTO_DEV_FSL_CAAM_AHASH_API
> To compile this as a module, choose M here: the module
> will be called caamhash.
>
> +config CRYPTO_DEV_FSL_CAAM_PKC_API
> + tristate "Register public key cryptography implementations with
> Crypto API" + depends on CRYPTO_DEV_FSL_CAAM &&
> CRYPTO_DEV_FSL_CAAM_JR
> + default y
> + select CRYPTO_RSA_HELPER
> + help
> + Selecting this will allow SEC Public key support for RSA.
> + Supported cryptographic primitives: encryption, decryption,
> + signature and verification.
> + To compile this as a module, choose M here: the module
> + will be called caam_pkc.
> +
> config CRYPTO_DEV_FSL_CAAM_RNG_API
> tristate "Register caam device for hwrng API"
> depends on CRYPTO_DEV_FSL_CAAM && CRYPTO_DEV_FSL_CAAM_JR
> diff --git a/drivers/crypto/caam/Makefile b/drivers/crypto/caam/Makefile
> index 550758a..399ad55 100644
> --- a/drivers/crypto/caam/Makefile
> +++ b/drivers/crypto/caam/Makefile
> @@ -5,11 +5,15 @@ ifeq ($(CONFIG_CRYPTO_DEV_FSL_CAAM_DEBUG), y)
> EXTRA_CFLAGS := -DDEBUG
> endif
>
> +ccflags-y += -I$(srctree)/crypto
> +
> obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM) += caam.o
> obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_JR) += caam_jr.o
> obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API) += caamalg.o
> obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_AHASH_API) += caamhash.o
> obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_API) += caamrng.o
> +obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_PKC_API) += caam_pkc.o
>
> caam-objs := ctrl.o
> caam_jr-objs := jr.o key_gen.o error.o
> +caam_pkc-y := caampkc.o pkc_desc.o
> diff --git a/drivers/crypto/caam/caampkc.c b/drivers/crypto/caam/caampkc.c
> new file mode 100644
> index 0000000..1c53158
> --- /dev/null
> +++ b/drivers/crypto/caam/caampkc.c
> @@ -0,0 +1,513 @@
> +/*
> + * caam - Freescale FSL CAAM support for Public Key Cryptography
> + *
> + * Copyright 2016 Freescale Semiconductor, Inc.
> + *
> + * There is no Shared Descriptor for PKC so that the Job Descriptor must
> carry + * all the desired key parameters, input and output pointers.
> + */
> +#include <linux/dma-mapping.h>
> +#include <linux/fips.h>
> +#include "compat.h"
> +#include "caampkc.h"
> +#include "sg_sw_sec4.h"
> +#include "regs.h"
> +#include "intern.h"
> +#include "jr.h"
> +#include "error.h"
> +
> +void 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;
> +}

As you implement raw key support for use in other drivers, shouldn't that
function go into some helper file like free_mpis().
> +
> +static int caam_rsa_setpubkey(struct crypto_akcipher *tfm, const void *key,
> + unsigned int keylen)
> +{
> + struct rsa_raw_ctx *ctx = akcipher_tfm_ctx(tfm);
> + struct rsa_raw_key *raw_key = &ctx->key;
> + int ret;
> +
> + set_raw_rsa_pub_action(&ctx->action);
> +
> + /* Free the old key if any */
> + rsa_free_key(raw_key);
> +
> + ret = asn1_ber_decoder(&rsapubkey_decoder, ctx, key, keylen);
> + if (ret < 0)
> + goto free;
> +
> + if (!raw_key->n || !raw_key->e) {
> + /* Invalid key provided */
> + ret = -EINVAL;
> + goto free;
> + }
> +
> + return 0;
> +free:
> + rsa_free_key(raw_key);
> + return ret;
> +}
> +
> +static int caam_rsa_setprivkey(struct crypto_akcipher *tfm, const void
> *key, + unsigned int keylen)
> +{
> + struct rsa_raw_ctx *ctx = akcipher_tfm_ctx(tfm);
> + struct rsa_raw_key *raw_key = &ctx->key;
> + int ret;
> +
> + set_raw_rsa_priv_action(&ctx->action);
> +
> + /* Free the old key if any */
> + rsa_free_key(raw_key);
> +
> + ret = asn1_ber_decoder(&rsaprivkey_decoder, ctx, key, keylen);
> + if (ret < 0)
> + goto free;
> +
> + if (!raw_key->n || !raw_key->e || !raw_key->d) {
> + /* Invalid key provided */
> + ret = -EINVAL;
> + goto free;
> + }
> +
> + return 0;
> +free:
> + rsa_free_key(raw_key);
> + return ret;
> +}
> +
> +static void rsa_pub_unmap(struct device *dev, struct rsa_edesc *edesc,
> + struct akcipher_request *req)
> +{
> + struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
> + struct rsa_raw_ctx *ctx = akcipher_tfm_ctx(tfm);
> + struct rsa_raw_key *key = &ctx->key;
> + struct rsa_pub_desc *hw_desc = (struct rsa_pub_desc *)edesc->hw_desc;
> +
> + dma_unmap_single(dev, hw_desc->n_dma, key->n_sz, DMA_TO_DEVICE);
> + dma_unmap_single(dev, hw_desc->e_dma, key->e_sz, DMA_TO_DEVICE);
> + dma_unmap_sg(dev, req->dst, edesc->dst_nents, DMA_FROM_DEVICE);
> + dma_unmap_sg(dev, req->src, edesc->src_nents, DMA_TO_DEVICE);
> +}
> +
> +static void rsa_priv_f1_unmap(struct device *dev, struct rsa_edesc *edesc,
> + struct akcipher_request *req)
> +{
> + struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
> + struct rsa_raw_ctx *ctx = akcipher_tfm_ctx(tfm);
> + struct rsa_raw_key *key = &ctx->key;
> + struct rsa_priv_f1_desc *hw_desc =
> + (struct rsa_priv_f1_desc *)edesc->hw_desc;
> +
> + dma_unmap_single(dev, hw_desc->n_dma, key->n_sz, DMA_TO_DEVICE);
> + dma_unmap_single(dev, hw_desc->d_dma, key->n_sz, DMA_TO_DEVICE);
> + dma_unmap_sg(dev, req->dst, edesc->dst_nents, DMA_FROM_DEVICE);
> + dma_unmap_sg(dev, req->src, edesc->src_nents, DMA_TO_DEVICE);
> +}
> +
> +static size_t skip_to_nonzero(u8 *ptr, size_t nbytes)
> +{
> + size_t nr_zeros = 0;
> +
> + while (!(*ptr) && nbytes) {
> + nbytes--;
> + ptr++;
> + nr_zeros++;
> + }
> +
> + return nr_zeros;
> +}
> +
> +static size_t scatterwalk_skip_zeros(struct scatter_walk *walk, size_t
> nbytes) +{
> + size_t len_this_page, nr_zeros, cnt = 0;
> + u8 *vaddr, *ptr;
> +
> + for (;;) {
> + nr_zeros = 0;
> + len_this_page = scatterwalk_pagelen(walk);
> +
> + if (len_this_page > nbytes)
> + len_this_page = nbytes;
> +
> + vaddr = scatterwalk_map(walk);
> + ptr = vaddr;
> + nr_zeros = skip_to_nonzero(ptr, len_this_page);
> + scatterwalk_unmap(vaddr);
> +
> + /* count total number of zeros */
> + cnt += nr_zeros;
> +
> + /* advance scatterwalk to the nonzero data */
> + scatterwalk_advance(walk, nr_zeros);
> +
> + if (nr_zeros < len_this_page || nbytes == len_this_page)
> + break;
> +
> + nbytes -= len_this_page;
> +
> + scatterwalk_pagedone(walk, 0, 1);
> + }
> +
> + return cnt;
> +}
> +
> +/*
> + * This function drops the leading zeros and copies the data to the initial
> + * pointer so that it can be freed later on. Returns the updated data
> length. + */
> +static size_t drop_leading_zeros(struct scatterlist *sg, size_t nbytes)
> +{
> + struct scatter_walk walk_src, walk_dst;
> + size_t nr_zeros = 0;
> +
> + scatterwalk_start(&walk_src, sg);
> + nr_zeros = scatterwalk_skip_zeros(&walk_src, nbytes);
> +
> + if (nr_zeros) {
> + nbytes = nbytes - nr_zeros;
> +
> + scatterwalk_start(&walk_dst, sg);
> + scatterwalk_sg_copychunks(&walk_dst, &walk_src, nbytes);
> + scatterwalk_done(&walk_dst, 0, 0);
> + }
> +
> + scatterwalk_done(&walk_src, 0, 0);
> +
> + return nbytes;
> +}
> +
> +/* RSA Job Completion handler */
> +static void rsa_pub_done(struct device *dev, u32 *desc, u32 err, void
> *context) +{
> + struct akcipher_request *req = context;
> + struct rsa_edesc *edesc;
> +
> + if (err)
> + caam_jr_strstatus(dev, err);
> +
> + /*
> + * RSA's output is expected to be a big integer. Drop the leading
> + * zeros since they are not meaningful in the world of numbers.
> + */
> + req->dst_len = drop_leading_zeros(req->dst, req->dst_len);
> +
> + edesc = container_of(desc, struct rsa_edesc, hw_desc[0]);
> +
> + rsa_pub_unmap(dev, edesc, req);
> + kfree(edesc);
> +
> + akcipher_request_complete(req, err);
> +}
> +
> +static void rsa_priv_f1_done(struct device *dev, u32 *desc, u32 err,
> + void *context)
> +{
> + struct akcipher_request *req = context;
> + struct rsa_edesc *edesc;
> +
> + if (err)
> + caam_jr_strstatus(dev, err);
> +
> + /*
> + * RSA's output is expected to be a big integer. Drop the leading
> + * zeros since they are not meaningful in the world of numbers.
> + */
> + req->dst_len = drop_leading_zeros(req->dst, req->dst_len);
> +
> + edesc = container_of(desc, struct rsa_edesc, hw_desc[0]);
> +
> + rsa_priv_f1_unmap(dev, edesc, req);
> + kfree(edesc);
> +
> + akcipher_request_complete(req, err);
> +}
> +
> +static struct rsa_edesc *rsa_edesc_alloc(struct akcipher_request *req,
> + size_t desclen)
> +{
> + struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
> + struct rsa_raw_ctx *ctx = akcipher_tfm_ctx(tfm);
> + struct device *dev = ctx->dev;
> + struct rsa_edesc *edesc;
> + gfp_t flags = (req->base.flags & (CRYPTO_TFM_REQ_MAY_BACKLOG |
> + CRYPTO_TFM_REQ_MAY_SLEEP)) ? GFP_KERNEL : GFP_ATOMIC;
> + int sgc;
> + int sec4_sg_index, sec4_sg_len = 0, sec4_sg_bytes;
> + int src_nents, dst_nents;
> +
> + src_nents = sg_nents_for_len(req->src, req->src_len);
> + dst_nents = sg_nents_for_len(req->dst, req->dst_len);
> +
> + if (src_nents > 1)
> + sec4_sg_len = src_nents;
> + if (dst_nents > 1)
> + sec4_sg_len += dst_nents;
> +
> + sec4_sg_bytes = sec4_sg_len * sizeof(struct sec4_sg_entry);
> +
> + /* allocate space for base edesc, hw desc commands and link tables */
> + edesc = kzalloc(sizeof(*edesc) + desclen + sec4_sg_bytes,
> + GFP_DMA | flags);
> + if (!edesc)
> + return ERR_PTR(-ENOMEM);
> +
> + sgc = dma_map_sg(dev, req->src, src_nents, DMA_TO_DEVICE);
> + if (unlikely(!sgc)) {
> + dev_err(dev, "unable to map source\n");
> + goto src_fail;
> + }
> +
> + sgc = dma_map_sg(dev, req->dst, dst_nents, DMA_FROM_DEVICE);
> + if (unlikely(!sgc)) {
> + dev_err(dev, "unable to map destination\n");
> + goto dst_fail;
> + }
> +
> + edesc->sec4_sg = (void *)edesc + sizeof(*edesc) + desclen;
> +
> + sec4_sg_index = 0;
> + if (src_nents > 1) {
> + sg_to_sec4_sg_last(req->src, src_nents, edesc->sec4_sg, 0);
> + sec4_sg_index += src_nents;
> + }
> + if (dst_nents > 1) {
> + sg_to_sec4_sg_last(req->dst, dst_nents,
> + edesc->sec4_sg + sec4_sg_index, 0);
> + }
> +
> + /* Save nents for later use in Job Descriptor. */
> + edesc->src_nents = src_nents;
> + edesc->dst_nents = dst_nents;
> +
> + if (!sec4_sg_bytes)
> + return edesc;
> +
> + edesc->sec4_sg_dma = dma_map_single(dev, edesc->sec4_sg,
> + sec4_sg_bytes, DMA_TO_DEVICE);
> + if (dma_mapping_error(dev, edesc->sec4_sg_dma)) {
> + dev_err(dev, "unable to map S/G table\n");
> + goto sec4_sg_fail;
> + }
> +
> + return edesc;
> +
> +sec4_sg_fail:
> + dma_unmap_sg(dev, req->dst, dst_nents, DMA_FROM_DEVICE);
> +dst_fail:
> + dma_unmap_sg(dev, req->src, src_nents, DMA_TO_DEVICE);
> +src_fail:
> + kfree(edesc);
> + return ERR_PTR(-ENOMEM);
> +}
> +
> +static int caam_rsa_enc(struct akcipher_request *req)
> +{
> + struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
> + struct rsa_raw_ctx *ctx = akcipher_tfm_ctx(tfm);
> + struct rsa_raw_key *key = &ctx->key;
> + struct device *jrdev = ctx->dev;
> + struct rsa_edesc *edesc = NULL;
> + size_t desclen = sizeof(struct rsa_pub_desc);
> + int ret;
> +
> + if (unlikely(!key->n || !key->e))
> + return -EINVAL;
> +
> + if (req->dst_len < key->n_sz) {
> + req->dst_len = key->n_sz;
> + dev_err(jrdev, "Output buffer length less than parameter
n\n");
> + return -EOVERFLOW;
> + }
> +
> + /* Allocate extended descriptor. */
> + edesc = rsa_edesc_alloc(req, desclen);
> + if (IS_ERR(edesc))
> + return PTR_ERR(edesc);
> +
> + /* Initialize Job Descriptor. */
> + ret = init_rsa_pub_desc(req, edesc);
> + if (ret)
> + return ret;
> +
> + ret = caam_jr_enqueue(jrdev, edesc->hw_desc, rsa_pub_done, req);
> + if (!ret) {
> + ret = -EINPROGRESS;
> + } else {
> + rsa_pub_unmap(jrdev, edesc, req);
> + kfree(edesc);
> + }
> +
> + return ret;
> +}
> +
> +static int caam_rsa_dec(struct akcipher_request *req)
> +{
> + struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
> + struct rsa_raw_ctx *ctx = akcipher_tfm_ctx(tfm);
> + struct rsa_raw_key *key = &ctx->key;
> + struct device *jrdev = ctx->dev;
> + struct rsa_edesc *edesc = NULL;
> + size_t desclen = sizeof(struct rsa_priv_f1_desc);
> + int ret;
> +
> + if (unlikely(!key->n || !key->d))
> + return -EINVAL;
> +
> + if (req->dst_len < key->n_sz) {
> + req->dst_len = key->n_sz;
> + return -EOVERFLOW;
> + }
> +
> + /* Allocate extended descriptor. */
> + edesc = rsa_edesc_alloc(req, desclen);
> + if (IS_ERR(edesc))
> + return PTR_ERR(edesc);
> +
> + /* Initialize Job Descriptor. */
> + ret = init_rsa_priv_f1_desc(req, edesc);
> + if (ret)
> + return ret;

Same here, kfree?
> +
> + ret = caam_jr_enqueue(jrdev, edesc->hw_desc, rsa_priv_f1_done, req);
> + if (!ret) {
> + ret = -EINPROGRESS;

dto

> + } else {
> + rsa_priv_f1_unmap(jrdev, edesc, req);
> + kfree(edesc);
> + }
> +
> + return ret;
> +}
> +
> +static int caam_rsa_max_size(struct crypto_akcipher *tfm)
> +{
> + struct rsa_raw_ctx *ctx = akcipher_tfm_ctx(tfm);
> + struct rsa_raw_key *key = &ctx->key;
> +
> + return (key->n) ? key->n_sz : -EINVAL;
> +}
> +
> +/* Per session pkc's driver context creation function */
> +static int caam_rsa_init_tfm(struct crypto_akcipher *tfm)
> +{
> + struct rsa_raw_ctx *ctx = akcipher_tfm_ctx(tfm);
> + struct rsa_raw_key *key = &ctx->key;
> +
> + ctx->dev = caam_jr_alloc();
> +
> + if (IS_ERR(ctx->dev)) {
> + dev_err(ctx->dev, "Job Ring Device allocation for transform
failed\n");
> + return PTR_ERR(ctx->dev);
> + }
> +
> + key->is_coherent = true;
> + key->flags = GFP_DMA | GFP_KERNEL;
> + return 0;
> +}
> +
> +/* Per session pkc's driver context cleanup function */
> +static void caam_rsa_exit_tfm(struct crypto_akcipher *tfm)
> +{
> + struct rsa_raw_ctx *ctx = akcipher_tfm_ctx(tfm);
> + struct rsa_raw_key *key = &ctx->key;
> +
> + rsa_free_key(key);
> + caam_jr_free(ctx->dev);
> +}
> +
> +static struct akcipher_alg rsa = {

can you please name that something else, like caam_rsa? It is a real hassle
when searching some symbol and I get such a generic name.

> + .encrypt = caam_rsa_enc,
> + .decrypt = caam_rsa_dec,
> + .sign = caam_rsa_dec,
> + .verify = caam_rsa_enc,
> + .set_pub_key = caam_rsa_setpubkey,
> + .set_priv_key = caam_rsa_setprivkey,
> + .max_size = caam_rsa_max_size,
> + .init = caam_rsa_init_tfm,
> + .exit = caam_rsa_exit_tfm,
> + .base = {
> + .cra_name = "rsa",
> + .cra_driver_name = "rsa-caam",
> + .cra_priority = 3000,
> + .cra_module = THIS_MODULE,
> + .cra_alignmask = 0,
> + .cra_ctxsize = sizeof(struct rsa_raw_ctx),
> + },
> +};
> +
> +/* Public Key Cryptography module initialization handler */
> +static int __init caam_pkc_init(void)
> +{
> + struct device_node *dev_node;
> + struct platform_device *pdev;
> + struct device *ctrldev;
> + struct caam_drv_private *priv;
> + u32 cha_inst, pk_inst;
> + int err = 0;
> +
> + dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0");
> + if (!dev_node) {
> + dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec4.0");
> + if (!dev_node)
> + return -ENODEV;
> + }
> +
> + pdev = of_find_device_by_node(dev_node);
> + if (!pdev) {
> + of_node_put(dev_node);
> + return -ENODEV;
> + }
> +
> + ctrldev = &pdev->dev;
> + priv = dev_get_drvdata(ctrldev);
> + of_node_put(dev_node);
> +
> + /*
> + * If priv is NULL, it's probably because the caam driver wasn't
> + * properly initialized (e.g. RNG4 init failed). Thus, bail out here.
> + */
> + if (!priv)
> + return -ENODEV;
> +
> + /* Determine public key hardware accelerator presence. */
> + cha_inst = rd_reg32(&priv->ctrl->perfmon.cha_num_ls);
> + pk_inst = (cha_inst & CHA_ID_LS_PK_MASK) >> CHA_ID_LS_PK_SHIFT;
> +
> + /* Do not register algorithms if PKHA is not present. */
> + if (!pk_inst)
> + return -ENODEV;
> +
> + rsa.base.cra_flags = 0;
> + err = crypto_register_akcipher(&rsa);
> + if (err)
> + dev_warn(ctrldev, "%s alg registration failed\n",
> + rsa.base.cra_driver_name);
> + else
> + dev_info(ctrldev, "caam algorithms registered in
/proc/crypto\n");
> +
> + return err;
> +}
> +
> +static void __exit caam_pkc_exit(void)
> +{
> + crypto_unregister_akcipher(&rsa);
> +}
> +
> +module_init(caam_pkc_init);
> +module_exit(caam_pkc_exit);
> +
> +MODULE_LICENSE("Dual BSD/GPL");
> +MODULE_DESCRIPTION("FSL CAAM support for PKC functions of crypto API");
> +MODULE_AUTHOR("Freescale Semiconductor");
> diff --git a/drivers/crypto/caam/caampkc.h b/drivers/crypto/caam/caampkc.h
> new file mode 100644
> index 0000000..a49d7da
> --- /dev/null
> +++ b/drivers/crypto/caam/caampkc.h
> @@ -0,0 +1,84 @@
> +/*
> + * caam - Freescale FSL CAAM support for Public Key Cryptography
> descriptors + *
> + * Copyright 2016 Freescale Semiconductor, Inc.
> + *
> + * There is no Shared Descriptor for PKC so that the Job Descriptor must
> carry + * all the desired key parameters, input and output pointers.
> + */
> +
> +#ifndef _PKC_DESC_H_
> +#define _PKC_DESC_H_
> +
> +#include <crypto/internal/rsa.h>
> +#include <crypto/akcipher.h>
> +#include <crypto/internal/akcipher.h>
> +#include "desc_constr.h"
> +#include "pdb.h"
> +#include "rsapubkey-asn1.h"
> +#include "rsaprivkey-asn1.h"
> +
> +/**
> + * RSA Pub_Key Descriptor
> + * @desc_hdr: Job Descriptor Header command
> + * @sgf: scatter-gather field
> + * @f_dma: dma address of input data
> + * @g_dma: dma address of ecrypted output data
> + * @n_dma: dma address of RSA public exponent
> + * @dma_e: dma address of RSA public exponent
> + * @f_len: length in octets of the input data
> + * @op: RSA Operation command
> + */
> +struct rsa_pub_desc {
> + u32 desc_hdr;
> + u32 sgf;
> + dma_addr_t f_dma;
> + dma_addr_t g_dma;
> + dma_addr_t n_dma;
> + dma_addr_t e_dma;
> + u32 f_len;
> + u32 op;
> +} __packed;
> +
> +/**
> + * Form1 Priv_key Decryption Descriptor.
> + * Private key is represented by (n,d).
> + * @desc_hdr: Job Descriptor Header command
> + * @sgf: scatter-gather field
> + * @g_dma: dma address of ecrypted input data
> + * @f_dma: dma address of output data
> + * @n_dma: dma address of RSA public exponent
> + * @dma_d: dma address of RSA private exponent
> + * @op: RSA Operation command
> + */
> +struct rsa_priv_f1_desc {
> + u32 desc_hdr;
> + u32 sgf;
> + dma_addr_t g_dma;
> + dma_addr_t f_dma;
> + dma_addr_t n_dma;
> + dma_addr_t d_dma;
> + u32 op;
> +} __packed;
> +
> +/**
> + * rsa_edesc - s/w-extended rsa descriptor
> + * @src_nents: number of segments in input scatterlist
> + * @dst_nents: number of segments in output scatterlist
> + * @sec4_sg_dma: dma address of h/w link table
> + * @sec4_sg: pointer to h/w link table
> + * @hw_desc: descriptor followed by link tables if any
> + */
> +struct rsa_edesc {
> + int src_nents;
> + int dst_nents;
> + dma_addr_t sec4_sg_dma;
> + struct sec4_sg_entry *sec4_sg;
> + u32 hw_desc[];
> +};
> +
> +/* Descriptor construction primitives. */
> +int init_rsa_pub_desc(struct akcipher_request *req, struct rsa_edesc
> *edesc); +int init_rsa_priv_f1_desc(struct akcipher_request *req,
> + struct rsa_edesc *edesc);
> +#endif
> diff --git a/drivers/crypto/caam/desc.h b/drivers/crypto/caam/desc.h
> index 1e93c6a..7e5c027 100644
> --- a/drivers/crypto/caam/desc.h
> +++ b/drivers/crypto/caam/desc.h
> @@ -454,6 +454,8 @@ struct sec4_sg_entry {
> #define OP_PCLID_PUBLICKEYPAIR (0x14 << OP_PCLID_SHIFT)
> #define OP_PCLID_DSASIGN (0x15 << OP_PCLID_SHIFT)
> #define OP_PCLID_DSAVERIFY (0x16 << OP_PCLID_SHIFT)
> +#define OP_PCLID_RSAENC_PUBKEY (0x18 << OP_PCLID_SHIFT)
> +#define OP_PCLID_RSADEC_PRVKEY (0x19 << OP_PCLID_SHIFT)
>
> /* Assuming OP_TYPE = OP_TYPE_DECAP_PROTOCOL/ENCAP_PROTOCOL */
> #define OP_PCLID_IPSEC (0x01 << OP_PCLID_SHIFT)
> diff --git a/drivers/crypto/caam/pdb.h b/drivers/crypto/caam/pdb.h
> index 3a87c0c..1c68d7b 100644
> --- a/drivers/crypto/caam/pdb.h
> +++ b/drivers/crypto/caam/pdb.h
> @@ -1,7 +1,7 @@
> /*
> * CAAM Protocol Data Block (PDB) definition header file
> *
> - * Copyright 2008-2012 Freescale Semiconductor, Inc.
> + * Copyright 2008-2016 Freescale Semiconductor, Inc.
> *
> */
>
> @@ -399,4 +399,18 @@ struct dsa_verify_pdb {
> u8 *ab; /* only used if ECC processing */
> };
>
> +/* RSA Protocol Data Block */
> +#define RSA_PDB_SGF_SHIFT 28
> +#define RSA_PDB_E_SHIFT 12
> +#define RSA_PDB_E_MASK (0xFFF << RSA_PDB_E_SHIFT)
> +#define RSA_PDB_D_SHIFT 12
> +#define RSA_PDB_D_MASK (0xFFF << RSA_PDB_D_SHIFT)
> +
> +#define RSA_PDB_SGF_F (0x8 << RSA_PDB_SGF_SHIFT)
> +#define RSA_PDB_SGF_G (0x4 << RSA_PDB_SGF_SHIFT)
> +#define RSA_PRIV_PDB_SGF_F (0x4 << RSA_PDB_SGF_SHIFT)
> +#define RSA_PRIV_PDB_SGF_G (0x8 << RSA_PDB_SGF_SHIFT)
> +
> +#define RSA_PRIV_KEY_FRM_1 0
> +
> #endif
> diff --git a/drivers/crypto/caam/pkc_desc.c b/drivers/crypto/caam/pkc_desc.c
> new file mode 100644
> index 0000000..5ef4082
> --- /dev/null
> +++ b/drivers/crypto/caam/pkc_desc.c
> @@ -0,0 +1,138 @@
> +/*
> + * caam - Freescale FSL CAAM support for Public Key Cryptography
> descriptors + *
> + * Copyright 2016 Freescale Semiconductor, Inc.
> + *
> + * There is no Shared Descriptor for PKC so that the Job Descriptor must
> carry + * all the desired key parameters, input and output pointers.
> + */
> +#include "caampkc.h"
> +
> +/* Descriptor for RSA Public operation */
> +int init_rsa_pub_desc(struct akcipher_request *req, struct rsa_edesc
> *edesc) +{
> + struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
> + struct rsa_raw_ctx *ctx = akcipher_tfm_ctx(tfm);
> + struct rsa_raw_key *key = &ctx->key;
> + struct device *dev = ctx->dev;
> + struct rsa_pub_desc *desc = (struct rsa_pub_desc *)edesc->hw_desc;
> + u32 start_idx, desc_size;
> + int sec4_sg_index = 0;
> +
> + /*
> + * The PDB has static fields and can be initialized before writing
> + * a specific command. Map the memory first, since it can be a point
> + * of failure.
> + */
> + desc->n_dma = dma_map_single(dev, key->n, key->n_sz, DMA_TO_DEVICE);
> + if (dma_mapping_error(dev, desc->n_dma)) {
> + dev_err(dev, "Unable to map modulus memory\n");
> + goto n_fail;
> + }
> +
> + desc->e_dma = dma_map_single(dev, key->e, key->e_sz, DMA_TO_DEVICE);
> + if (dma_mapping_error(dev, desc->e_dma)) {
> + dev_err(dev, "Unable to map exponent memory\n");
> + goto e_fail;
> + }
> +
> + desc_size = sizeof(*desc) / CAAM_CMD_SZ;
> + start_idx = (desc_size - 1) & HDR_START_IDX_MASK;
> + init_job_desc(edesc->hw_desc, (start_idx << HDR_START_IDX_SHIFT) |
> + (start_idx & HDR_DESCLEN_MASK) | HDR_ONE);
> +
> + sec4_sg_index = 0;
> + if (edesc->src_nents > 1) {
> + desc->sgf |= RSA_PDB_SGF_F;
> + desc->f_dma = edesc->sec4_sg_dma;
> + sec4_sg_index += edesc->src_nents;
> + } else {
> + desc->f_dma = sg_dma_address(req->src);
> + }
> +
> + if (edesc->dst_nents > 1) {
> + desc->sgf |= RSA_PDB_SGF_G;
> + desc->g_dma = edesc->sec4_sg_dma +
> + sec4_sg_index * sizeof(struct sec4_sg_entry);
> + } else {
> + desc->g_dma = sg_dma_address(req->dst);
> + }
> +
> + desc->sgf |= (key->e_sz << RSA_PDB_E_SHIFT) | key->n_sz;
> + desc->f_len = req->src_len;
> + desc->op = CMD_OPERATION | OP_TYPE_UNI_PROTOCOL |
> + OP_PCLID_RSAENC_PUBKEY;
> + return 0;
> +
> +e_fail:
> + dma_unmap_single(dev, desc->n_dma, key->n_sz, DMA_TO_DEVICE);
> +n_fail:
> + dma_unmap_sg(dev, req->dst, edesc->dst_nents, DMA_FROM_DEVICE);
> + dma_unmap_sg(dev, req->src, edesc->src_nents, DMA_TO_DEVICE);
> + kfree(edesc);
> + return -ENOMEM;
> +}
> +
> +/* Descriptor for RSA Private operation */
> +int init_rsa_priv_f1_desc(struct akcipher_request *req, struct rsa_edesc
> *edesc) +{
> + struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
> + struct rsa_raw_ctx *ctx = akcipher_tfm_ctx(tfm);
> + struct rsa_raw_key *key = &ctx->key;
> + struct device *dev = ctx->dev;
> + struct rsa_priv_f1_desc *desc =
> + (struct rsa_priv_f1_desc *)edesc->hw_desc;
> + int sec4_sg_index = 0;
> + u32 start_idx, desc_size;
> +
> + /*
> + * The PDB has static fields and can be initialized before writing
> + * a specific command. Map the memory first, since it can be a point
> + * of failure.
> + */
> + desc->n_dma = dma_map_single(dev, key->n, key->n_sz, DMA_TO_DEVICE);
> + if (dma_mapping_error(dev, desc->n_dma)) {
> + dev_err(dev, "Unable to map modulus memory\n");
> + goto n_fail;
> + }
> +
> + desc->d_dma = dma_map_single(dev, key->d, key->n_sz, DMA_TO_DEVICE);
> + if (dma_mapping_error(dev, desc->d_dma)) {
> + dev_err(dev, "Unable to map exponent memory\n");
> + goto d_fail;
> + }
> +
> + desc_size = sizeof(*desc) / CAAM_CMD_SZ;
> + start_idx = (desc_size - 1) & HDR_START_IDX_MASK;
> + init_job_desc(edesc->hw_desc, (start_idx << HDR_START_IDX_SHIFT) |
> + (start_idx & HDR_DESCLEN_MASK) | HDR_ONE);
> +
> + if (edesc->src_nents > 1) {
> + desc->sgf |= RSA_PRIV_PDB_SGF_G;
> + desc->g_dma = edesc->sec4_sg_dma;
> + sec4_sg_index += edesc->src_nents;
> + } else {
> + desc->g_dma = sg_dma_address(req->src);
> + }
> +
> + if (edesc->dst_nents > 1) {
> + desc->sgf |= RSA_PRIV_PDB_SGF_F;
> + desc->f_dma = edesc->sec4_sg_dma +
> + sec4_sg_index * sizeof(struct sec4_sg_entry);
> + } else {
> + desc->f_dma = sg_dma_address(req->dst);
> + }
> +
> + desc->sgf |= (key->n_sz << RSA_PDB_D_SHIFT) | key->n_sz;
> + desc->op = CMD_OPERATION | OP_TYPE_UNI_PROTOCOL |
> + OP_PCLID_RSADEC_PRVKEY | RSA_PRIV_KEY_FRM_1;
> + return 0;
> +
> +d_fail:
> + dma_unmap_single(dev, desc->n_dma, key->n_sz, DMA_TO_DEVICE);
> +n_fail:
> + dma_unmap_sg(dev, req->dst, edesc->dst_nents, DMA_FROM_DEVICE);
> + dma_unmap_sg(dev, req->src, edesc->src_nents, DMA_TO_DEVICE);
> + kfree(edesc);
> + return -ENOMEM;
> +}


Ciao
Stephan

2016-03-20 14:58:24

by Tadeusz Struk

[permalink] [raw]
Subject: Re: [PATCH 01/10] crypto: rsa - generalize ASN.1 sequences

Hi Tudor,
On 03/18/2016 11:31 AM, Tudor Ambarus wrote:
> 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 struct rsa_asn1_action with 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]>

I like the rsa_asn1_action idea, but I have some comments regarding
the proposed implementation.

> -int rsa_parse_pub_key(struct rsa_key *rsa_key, const void *key,
> - unsigned int key_len);
> +struct rsa_asn1_action {
> + int (*get_n)(void *context, size_t hdrlen, unsigned char tag,
> + const void *value, size_t vlen);
> + int (*get_e)(void *context, size_t hdrlen, unsigned char tag,
> + const void *value, size_t vlen);
> + int (*get_d)(void *context, size_t hdrlen, unsigned char tag,
> + const void *value, size_t vlen);
> +};

To be able to take advantage of the Chinese remainder algorithm the
generic rsa_asn1_action should allow to provide handlers to obtain all
components of the private key i.e. handlers for p,q,dp,dq,qinv should
also be provided.
Also I think we don't need the size_t hdrlen and unsigned char tag here.

> +
> +struct rsa_ctx {
> + struct rsa_asn1_action action;

This should be a pointer to struct rsa_asn1_action *action;
There is no need to have a separate instance per tfm.
Drives should be able to use similar concept to how struct file_operations
is used. Instead of set_rsa_priv_action they should do

static const struct rsa_asn1_action impl_action = {
.get_n = impl_get_n;
.get_e = impl_get_e;
.....
};

and then:

static int rsa_set_priv_key(struct crypto_akcipher *tfm, const void *key,
unsigned int keylen)
{
struct rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
struct rsa_mpi_key *pkey = &ctx->key;
int ret;

ctx->action = &impl_action;

ret = rsa_parse_mpi_priv_key(ctx, key, keylen);
return ret;
}

and the parser for each component will look as follows:

int rsa_get_<X>(void *context, size_t hdrlen, unsigned char tag,
const void *value, size_t vlen)
{
struct rsa_ctx *ctx = context;
struct const rsa_asn1_action *action = ctx->action;

if (action->get_<X>)
return action->get_<X>(context, value, vlen);

return 0;
}

This will allow all the drivers to get what then need.
Thanks,
--
TS

2016-03-20 15:00:20

by Tadeusz Struk

[permalink] [raw]
Subject: Re: [PATCH 07/10] crypto: qat - remove duplicate ASN.1 parser

On 03/18/2016 11:32 AM, Tudor Ambarus wrote:
> Use the RSA's software implementation parser with
> raw integer actions.
>
> Compile-tested only.
>
> Signed-off-by: Tudor Ambarus <[email protected]>
> ---
> drivers/crypto/qat/Kconfig | 3 +-
> drivers/crypto/qat/qat_common/Makefile | 10 +-
> drivers/crypto/qat/qat_common/qat_asym_algs.c | 265 +++++++---------------
> drivers/crypto/qat/qat_common/qat_rsaprivkey.asn1 | 11 -
> drivers/crypto/qat/qat_common/qat_rsapubkey.asn1 | 4 -
> 5 files changed, 83 insertions(+), 210 deletions(-)
> delete mode 100644 drivers/crypto/qat/qat_common/qat_rsaprivkey.asn1
> delete mode 100644 drivers/crypto/qat/qat_common/qat_rsapubkey.asn1

Thanks for converting qat, but I'm working on adding support for the Chinese
remainder algorithm, which gives us big performance improvement, so please
do not change the qat driver just yet.
Please just add a generic ANS.1 parser that would allow to obtain all
components of the private key and I'll use it to add the handlers
and remove the ASN.1 parsing from qat. I will then test it to make sure
that it works fine before it is committed.
Thanks,
--
TS

2016-03-21 10:11:56

by Tudor-Dan Ambarus

[permalink] [raw]
Subject: RE: [PATCH 01/10] crypto: rsa - generalize ASN.1 sequences

Hi Tadeusz,

> -----Original Message-----
> From: Tadeusz Struk [mailto:[email protected]]
> Sent: Sunday, March 20, 2016 4:54 PM
> To: Tudor-Dan Ambarus; [email protected]
> Cc: [email protected]; [email protected]; Horia Ioan Geanta
> Neag
> Subject: Re: [PATCH 01/10] crypto: rsa - generalize ASN.1 sequences


> static int rsa_set_priv_key(struct crypto_akcipher *tfm, const void *key,
> unsigned int keylen)
> {
> struct rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
> struct rsa_mpi_key *pkey = &ctx->key;
> int ret;
>
> ctx->action = &impl_action;

[ta] we can do this once, when initializing the tfm object.

I agree with all your suggestions, I will implement them.

Thank you for the review,
ta

2016-03-21 10:13:01

by Tudor-Dan Ambarus

[permalink] [raw]
Subject: RE: [PATCH 07/10] crypto: qat - remove duplicate ASN.1 parser



> -----Original Message-----
> From: Tadeusz Struk [mailto:[email protected]]
> Sent: Sunday, March 20, 2016 4:56 PM
> To: Tudor-Dan Ambarus; [email protected]
> Cc: [email protected]; [email protected]; Horia Ioan Geanta
> Neag
> Subject: Re: [PATCH 07/10] crypto: qat - remove duplicate ASN.1 parser
>
> On 03/18/2016 11:32 AM, Tudor Ambarus wrote:
> > Use the RSA's software implementation parser with
> > raw integer actions.
> >
> > Compile-tested only.
> >
> > Signed-off-by: Tudor Ambarus <[email protected]>
> > ---
> > drivers/crypto/qat/Kconfig | 3 +-
> > drivers/crypto/qat/qat_common/Makefile | 10 +-
> > drivers/crypto/qat/qat_common/qat_asym_algs.c | 265 +++++++---------
> ------
> > drivers/crypto/qat/qat_common/qat_rsaprivkey.asn1 | 11 -
> > drivers/crypto/qat/qat_common/qat_rsapubkey.asn1 | 4 -
> > 5 files changed, 83 insertions(+), 210 deletions(-)
> > delete mode 100644 drivers/crypto/qat/qat_common/qat_rsaprivkey.asn1
> > delete mode 100644 drivers/crypto/qat/qat_common/qat_rsapubkey.asn1
>
> Thanks for converting qat, but I'm working on adding support for the
> Chinese
> remainder algorithm, which gives us big performance improvement, so please
> do not change the qat driver just yet.
> Please just add a generic ANS.1 parser that would allow to obtain all
> components of the private key and I'll use it to add the handlers
> and remove the ASN.1 parsing from qat. I will then test it to make sure
> that it works fine before it is committed.

[ta] Ok.

> Thanks,
> --
> TS

2016-03-21 11:07:11

by Tudor-Dan Ambarus

[permalink] [raw]
Subject: RE: [PATCH 10/10] crypto: caam - add support for RSA algorithm

Hi Stephan,

> -----Original Message-----
> From: Stephan Mueller [mailto:[email protected]]
> Sent: Saturday, March 19, 2016 6:59 PM
> To: Tudor-Dan Ambarus
> Cc: [email protected]; [email protected]; linux-
> [email protected]; Horia Ioan Geanta Neag
> Subject: Re: [PATCH 10/10] crypto: caam - add support for RSA algorithm
>
> > +void 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;
> > +}
>
> As you implement raw key support for use in other drivers, shouldn't that
> function go into some helper file like free_mpis().
> > +

[ta] I should also add an rsa_free_coherent_key(struct device *dev, struct rsa_raw_key *key), for those implementations that use the DMA-coherent API.


> > +static int caam_rsa_dec(struct akcipher_request *req)
> > +{
> > + struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
> > + struct rsa_raw_ctx *ctx = akcipher_tfm_ctx(tfm);
> > + struct rsa_raw_key *key = &ctx->key;
> > + struct device *jrdev = ctx->dev;
> > + struct rsa_edesc *edesc = NULL;
> > + size_t desclen = sizeof(struct rsa_priv_f1_desc);
> > + int ret;
> > +
> > + if (unlikely(!key->n || !key->d))
> > + return -EINVAL;
> > +
> > + if (req->dst_len < key->n_sz) {
> > + req->dst_len = key->n_sz;
> > + return -EOVERFLOW;
> > + }
> > +
> > + /* Allocate extended descriptor. */
> > + edesc = rsa_edesc_alloc(req, desclen);
> > + if (IS_ERR(edesc))
> > + return PTR_ERR(edesc);
> > +
> > + /* Initialize Job Descriptor. */
> > + ret = init_rsa_priv_f1_desc(req, edesc);
> > + if (ret)
> > + return ret;
>
> Same here, kfree?

[ta] Sure, thanks.

> > +
> > + ret = caam_jr_enqueue(jrdev, edesc->hw_desc, rsa_priv_f1_done, req);
> > + if (!ret) {
> > + ret = -EINPROGRESS;
>
> dto
>

[ta] resources are freed on rsa_priv_f1_done callback.

> > +static struct akcipher_alg rsa = {
>
> can you please name that something else, like caam_rsa? It is a real hassle
> when searching some symbol and I get such a generic name.

[ta] ok.

Thank you for the review!
ta

2016-03-21 15:17:25

by Tudor-Dan Ambarus

[permalink] [raw]
Subject: RE: [PATCH 02/10] crypto: rsa_helper - add raw integer parser actions

Hi Stephan,


> -----Original Message-----
> From: Stephan Mueller [mailto:[email protected]]
> Sent: Friday, March 18, 2016 9:47 PM
> To: Tudor-Dan Ambarus
> Cc: [email protected]; [email protected]; linux-
> [email protected]; 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

2016-03-21 15:29:38

by Tadeusz Struk

[permalink] [raw]
Subject: Re: [PATCH 01/10] crypto: rsa - generalize ASN.1 sequences

On 03/21/2016 03:11 AM, Tudor-Dan Ambarus wrote:
> [ta] we can do this once, when initializing the tfm object.
>
> I agree with all your suggestions, I will implement them.
>
> Thank you for the review,

Great. Thank you Tudor.
--
TS

2016-03-21 19:23:03

by Stephan Müller

[permalink] [raw]
Subject: Re: [PATCH 02/10] crypto: rsa_helper - add raw integer parser actions

Am Montag, 21. M?rz 2016, 15:17:20 schrieb Tudor-Dan Ambarus:

Hi Tudor,

> Hi Stephan,
>
> > -----Original Message-----
> > From: Stephan Mueller [mailto:[email protected]]
> > Sent: Friday, March 18, 2016 9:47 PM
> > To: Tudor-Dan Ambarus
> > Cc: [email protected]; [email protected]; linux-
> > [email protected]; 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