2015-09-09 16:16:59

by Tadeusz Struk

[permalink] [raw]
Subject: [PATCH 0/8] crypto: Updates to akcipher API

This series introduce updates to the akcipher API.
setkey function has been split into set_pub_key and
set_priv_key.
Input and output buffers are now sgl instread of void *
It also includes some minor updates like status check
from crypto_unregister_akcipher which was not checked
before.

---

Tadeusz Struk (8):
crypto: akcipher - return status from crypto_unregister_alg
crypto: rsa - check status returned from crypto_unregister_akcipher
crypto: qat - check status returned from crypto_unregister_akcipher
crypto: akcipher - Changes to asymmetric key API
lib/scatterlist: Add sg_len helper
crypto: rsa - update accoring to akcipher API changes
crypto: qat - update accoring to akcipher API changes
crypto: testmgr - update test mgr


crypto/Makefile | 9 +
crypto/akcipher.c | 4
crypto/rsa.c | 191 ++++++++++++++---
crypto/rsa_helper.c | 42 +++-
crypto/rsakey.asn1 | 5
crypto/rsaprivkey.asn1 | 11 +
crypto/rsapubkey.asn1 | 4
crypto/testmgr.c | 40 ++--
crypto/testmgr.h | 36 ++-
drivers/crypto/qat/qat_common/Makefile | 12 +
drivers/crypto/qat/qat_common/adf_common_drv.h | 2
drivers/crypto/qat/qat_common/adf_init.c | 6 -
drivers/crypto/qat/qat_common/qat_asym_algs.c | 232 +++++++++++++++------
drivers/crypto/qat/qat_common/qat_rsakey.asn1 | 5
drivers/crypto/qat/qat_common/qat_rsaprivkey.asn1 | 11 +
drivers/crypto/qat/qat_common/qat_rsapubkey.asn1 | 4
include/crypto/akcipher.h | 99 ++++++---
include/crypto/internal/akcipher.h | 4
include/crypto/internal/rsa.h | 7 -
include/linux/scatterlist.h | 1
lib/scatterlist.c | 17 ++
21 files changed, 552 insertions(+), 190 deletions(-)
delete mode 100644 crypto/rsakey.asn1
create mode 100644 crypto/rsaprivkey.asn1
create mode 100644 crypto/rsapubkey.asn1
delete mode 100644 drivers/crypto/qat/qat_common/qat_rsakey.asn1
create mode 100644 drivers/crypto/qat/qat_common/qat_rsaprivkey.asn1
create mode 100644 drivers/crypto/qat/qat_common/qat_rsapubkey.asn1

--
Signature


2015-09-09 16:16:58

by Tadeusz Struk

[permalink] [raw]
Subject: [PATCH 1/8] crypto: akcipher - return status from crypto_unregister_alg

Return status from crypto_unregister_alg to the caller.

Signed-off-by: Tadeusz Struk <[email protected]>
---
crypto/akcipher.c | 4 ++--
include/crypto/internal/akcipher.h | 4 +++-
2 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/crypto/akcipher.c b/crypto/akcipher.c
index 528ae6a..9cd84f7 100644
--- a/crypto/akcipher.c
+++ b/crypto/akcipher.c
@@ -107,9 +107,9 @@ int crypto_register_akcipher(struct akcipher_alg *alg)
}
EXPORT_SYMBOL_GPL(crypto_register_akcipher);

-void crypto_unregister_akcipher(struct akcipher_alg *alg)
+int crypto_unregister_akcipher(struct akcipher_alg *alg)
{
- crypto_unregister_alg(&alg->base);
+ return crypto_unregister_alg(&alg->base);
}
EXPORT_SYMBOL_GPL(crypto_unregister_akcipher);

diff --git a/include/crypto/internal/akcipher.h b/include/crypto/internal/akcipher.h
index 9a2bda1..9ea7bc9 100644
--- a/include/crypto/internal/akcipher.h
+++ b/include/crypto/internal/akcipher.h
@@ -55,6 +55,8 @@ int crypto_register_akcipher(struct akcipher_alg *alg);
* Function unregisters an implementation of a public key verify algorithm
*
* @alg: algorithm definition
+ *
+ * Return: zero on success; error code in case of error
*/
-void crypto_unregister_akcipher(struct akcipher_alg *alg);
+int crypto_unregister_akcipher(struct akcipher_alg *alg);
#endif

2015-09-09 16:17:03

by Tadeusz Struk

[permalink] [raw]
Subject: [PATCH 3/8] crypto: qat - check status returned from crypto_unregister_akcipher

Add status check returned from crypto_unregister_akcipher.

Signed-off-by: Tadeusz Struk <[email protected]>
---
drivers/crypto/qat/qat_common/adf_common_drv.h | 2 +-
drivers/crypto/qat/qat_common/adf_init.c | 6 ++----
drivers/crypto/qat/qat_common/qat_asym_algs.c | 7 +++++--
3 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/drivers/crypto/qat/qat_common/adf_common_drv.h b/drivers/crypto/qat/qat_common/adf_common_drv.h
index 7836dff..6882c52 100644
--- a/drivers/crypto/qat/qat_common/adf_common_drv.h
+++ b/drivers/crypto/qat/qat_common/adf_common_drv.h
@@ -168,7 +168,7 @@ void qat_algs_exit(void);
int qat_algs_register(void);
int qat_algs_unregister(void);
int qat_asym_algs_register(void);
-void qat_asym_algs_unregister(void);
+int qat_asym_algs_unregister(void);

int qat_hal_init(struct adf_accel_dev *accel_dev);
void qat_hal_deinit(struct icp_qat_fw_loader_handle *handle);
diff --git a/drivers/crypto/qat/qat_common/adf_init.c b/drivers/crypto/qat/qat_common/adf_init.c
index ac37a89..e9d52a8 100644
--- a/drivers/crypto/qat/qat_common/adf_init.c
+++ b/drivers/crypto/qat/qat_common/adf_init.c
@@ -272,13 +272,11 @@ int adf_dev_stop(struct adf_accel_dev *accel_dev)
clear_bit(ADF_STATUS_STARTING, &accel_dev->status);
clear_bit(ADF_STATUS_STARTED, &accel_dev->status);

- if (!list_empty(&accel_dev->crypto_list) && qat_algs_unregister())
+ if (!list_empty(&accel_dev->crypto_list) &&
+ (qat_algs_unregister() || qat_asym_algs_unregister()))
dev_err(&GET_DEV(accel_dev),
"Failed to unregister crypto algs\n");

- if (!list_empty(&accel_dev->crypto_list))
- qat_asym_algs_unregister();
-
list_for_each(list_itr, &service_table) {
service = list_entry(list_itr, struct service_hndl, list);
if (!test_bit(accel_dev->accel_id, &service->start_status))
diff --git a/drivers/crypto/qat/qat_common/qat_asym_algs.c b/drivers/crypto/qat/qat_common/qat_asym_algs.c
index e87f510..7de765d 100644
--- a/drivers/crypto/qat/qat_common/qat_asym_algs.c
+++ b/drivers/crypto/qat/qat_common/qat_asym_algs.c
@@ -643,10 +643,13 @@ int qat_asym_algs_register(void)
return ret;
}

-void qat_asym_algs_unregister(void)
+int qat_asym_algs_unregister(void)
{
+ int ret = 0;
+
mutex_lock(&algs_lock);
if (--active_devs == 0)
- crypto_unregister_akcipher(&rsa);
+ ret = crypto_unregister_akcipher(&rsa);
mutex_unlock(&algs_lock);
+ return ret;
}

2015-09-09 16:17:06

by Tadeusz Struk

[permalink] [raw]
Subject: [PATCH 2/8] crypto: rsa - check status returned from crypto_unregister_akcipher

Add status check returned from crypto_unregister_akcipher function.

Signed-off-by: Tadeusz Struk <[email protected]>
---
crypto/rsa.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/crypto/rsa.c b/crypto/rsa.c
index 466003e..93feae2 100644
--- a/crypto/rsa.c
+++ b/crypto/rsa.c
@@ -329,7 +329,7 @@ static int rsa_init(void)

static void rsa_exit(void)
{
- crypto_unregister_akcipher(&rsa);
+ WARN_ON(crypto_unregister_akcipher(&rsa));
}

module_init(rsa_init);

2015-09-09 16:17:09

by Tadeusz Struk

[permalink] [raw]
Subject: [PATCH 4/8] crypto: akcipher - Changes to asymmetric key API

Setkey function has been split into set_priv_key and set_pub_key.
Akcipher requests takes sgl for src and dst instead of void *.
Users of the API need to be disabled so that the build works fine
after this patch.
They will be enabled in subsequent patches.

Signed-off-by: Tadeusz Struk <[email protected]>
---
crypto/Makefile | 5 --
crypto/testmgr.c | 4 +
drivers/crypto/qat/qat_common/Makefile | 2 -
include/crypto/akcipher.h | 99 ++++++++++++++++++++++----------
4 files changed, 71 insertions(+), 39 deletions(-)

diff --git a/crypto/Makefile b/crypto/Makefile
index e2c5981..65e91da 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -34,11 +34,6 @@ obj-$(CONFIG_CRYPTO_AKCIPHER2) += akcipher.o
$(obj)/rsakey-asn1.o: $(obj)/rsakey-asn1.c $(obj)/rsakey-asn1.h
clean-files += rsakey-asn1.c rsakey-asn1.h

-rsa_generic-y := rsakey-asn1.o
-rsa_generic-y += rsa.o
-rsa_generic-y += rsa_helper.o
-obj-$(CONFIG_CRYPTO_RSA) += rsa_generic.o
-
cryptomgr-y := algboss.o testmgr.o

obj-$(CONFIG_CRYPTO_MANAGER2) += cryptomgr.o
diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index 35c2de1..2f2b66e 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -1835,6 +1835,7 @@ static int alg_test_drbg(const struct alg_test_desc *desc, const char *driver,

}

+#if 0
static int do_test_rsa(struct crypto_akcipher *tfm,
struct akcipher_testvec *vecs)
{
@@ -1975,6 +1976,7 @@ static int alg_test_akcipher(const struct alg_test_desc *desc,
crypto_free_akcipher(tfm);
return err;
}
+#endif

static int alg_test_null(const struct alg_test_desc *desc,
const char *driver, u32 type, u32 mask)
@@ -3611,7 +3613,7 @@ static const struct alg_test_desc alg_test_descs[] = {
}
}, {
.alg = "rsa",
- .test = alg_test_akcipher,
+ .test = alg_test_null,
.fips_allowed = 1,
.suite = {
.akcipher = {
diff --git a/drivers/crypto/qat/qat_common/Makefile b/drivers/crypto/qat/qat_common/Makefile
index df20a9d..ba5abdb 100644
--- a/drivers/crypto/qat/qat_common/Makefile
+++ b/drivers/crypto/qat/qat_common/Makefile
@@ -13,8 +13,6 @@ intel_qat-objs := adf_cfg.o \
adf_hw_arbiter.o \
qat_crypto.o \
qat_algs.o \
- qat_rsakey-asn1.o \
- qat_asym_algs.o \
qat_uclo.o \
qat_hal.o

diff --git a/include/crypto/akcipher.h b/include/crypto/akcipher.h
index 69d163e..7380e25 100644
--- a/include/crypto/akcipher.h
+++ b/include/crypto/akcipher.h
@@ -13,28 +13,25 @@
#ifndef _CRYPTO_AKCIPHER_H
#define _CRYPTO_AKCIPHER_H
#include <linux/crypto.h>
+#include <linux/scatterlist.h>

/**
* struct akcipher_request - public key request
*
* @base: Common attributes for async crypto requests
- * @src: Pointer to memory containing the input parameters
- * The format of the parameter(s) is expeted to be Octet String
- * @dst: Pointer to memory whare the result will be stored
- * @src_len: Size of the input parameter
- * @dst_len: Size of the output buffer. It needs to be at leaset
- * as big as the expected result depending on the operation
- * After operation it will be updated with the acctual size of the
- * result. In case of error, where the dst_len was insufficient,
+ * @src: Source data
+ * @dst: Destination data
+ * @out_len: Size of the result. After operation it will be updated with
+ * the acctual size of the data stored in the dst.
+ * In case of error, where the dst sgl size was insufficient,
* it will be updated to the size required for the operation.
* @__ctx: Start of private context data
*/
struct akcipher_request {
struct crypto_async_request base;
- void *src;
- void *dst;
- unsigned int src_len;
- unsigned int dst_len;
+ struct scatterlist *src;
+ struct scatterlist *dst;
+ unsigned int out_len;
void *__ctx[] CRYPTO_MINALIGN_ATTR;
};

@@ -67,8 +64,13 @@ struct crypto_akcipher {
* algorithm. In case of error, where the dst_len was insufficient,
* the req->dst_len will be updated to the size required for the
* operation
- * @setkey: Function invokes the algorithm specific set key function, which
- * knows how to decode and interpret the BER encoded key
+ * @set_pub_key: Function invokes the algorithm specific set public key
+ * function, which knows how to decode and interpret
+ * the BER encoded public key
+ * @set_priv_key: Function invokes the algorithm specific set private key
+ * function, which knows how to decode and interpret
+ * the BER encoded private key
+ * @get_len: Function returns minimum dest buffer size for a given key.
* @init: Initialize the cryptographic transformation object.
* This function is used to initialize the cryptographic
* transformation object. This function is called only once at
@@ -89,8 +91,11 @@ struct akcipher_alg {
int (*verify)(struct akcipher_request *req);
int (*encrypt)(struct akcipher_request *req);
int (*decrypt)(struct akcipher_request *req);
- int (*setkey)(struct crypto_akcipher *tfm, const void *key,
- unsigned int keylen);
+ int (*set_pub_key)(struct crypto_akcipher *tfm, const void *key,
+ unsigned int keylen);
+ int (*set_priv_key)(struct crypto_akcipher *tfm, const void *key,
+ unsigned int keylen);
+ int (*get_len)(struct crypto_akcipher *tfm);
int (*init)(struct crypto_akcipher *tfm);
void (*exit)(struct crypto_akcipher *tfm);

@@ -229,21 +234,31 @@ static inline void akcipher_request_set_callback(struct akcipher_request *req,
* Sets parameters required by crypto operation
*
* @req: public key request
- * @src: ptr to input parameter
- * @dst: ptr of output parameter
- * @src_len: size of the input buffer
- * @dst_len: size of the output buffer. It will be updated by the
- * implementation to reflect the acctual size of the result
+ * @src: ptr to input scatter list
+ * @dst: ptr to output scatter list
*/
static inline void akcipher_request_set_crypt(struct akcipher_request *req,
- void *src, void *dst,
- unsigned int src_len,
- unsigned int dst_len)
+ struct scatterlist *src,
+ struct scatterlist *dst)
{
req->src = src;
req->dst = dst;
- req->src_len = src_len;
- req->dst_len = dst_len;
+}
+
+/**
+ * crypto_akcipher_get_len() -- Get minimum len for output buffer
+ *
+ * Function returns minimum dest buffer size for a given key
+ *
+ * @tfm: AKCIPHER tfm handle allocated with crypto_alloc_akcipher()
+ *
+ * Return: minimum len for output buffer or error code in key hasn't been set
+ */
+static inline int crypto_akcipher_get_len(struct crypto_akcipher *tfm)
+{
+ struct akcipher_alg *alg = crypto_akcipher_alg(tfm);
+
+ return alg->get_len(tfm);
}

/**
@@ -319,22 +334,44 @@ static inline int crypto_akcipher_verify(struct akcipher_request *req)
}

/**
- * crypto_akcipher_setkey() -- Invoke public key setkey operation
+ * crypto_akcipher_set_pub_key() -- Invoke set public key operation
+ *
+ * Function invokes the algorithm specific set key function, which knows
+ * how to decode and interpret the encoded key
+ *
+ * @tfm: tfm handle
+ * @key: BER encoded public key
+ * @keylen: length of the key
+ *
+ * Return: zero on success; error code in case of error
+ */
+static inline int crypto_akcipher_set_pub_key(struct crypto_akcipher *tfm,
+ const void *key,
+ unsigned int keylen)
+{
+ struct akcipher_alg *alg = crypto_akcipher_alg(tfm);
+
+ return alg->set_pub_key(tfm, key, keylen);
+}
+
+/**
+ * crypto_akcipher_set_priv_key() -- Invoke set private key operation
*
* Function invokes the algorithm specific set key function, which knows
* how to decode and interpret the encoded key
*
* @tfm: tfm handle
- * @key: BER encoded private or public key
+ * @key: BER encoded private key
* @keylen: length of the key
*
* Return: zero on success; error code in case of error
*/
-static inline int crypto_akcipher_setkey(struct crypto_akcipher *tfm, void *key,
- unsigned int keylen)
+static inline int crypto_akcipher_set_priv_key(struct crypto_akcipher *tfm,
+ const void *key,
+ unsigned int keylen)
{
struct akcipher_alg *alg = crypto_akcipher_alg(tfm);

- return alg->setkey(tfm, key, keylen);
+ return alg->set_priv_key(tfm, key, keylen);
}
#endif

2015-09-09 16:17:31

by Tadeusz Struk

[permalink] [raw]
Subject: [PATCH 7/8] crypto: qat - update accoring to akcipher API changes

QAT updates to reflect akcipher API changes.

Signed-off-by: Tadeusz Struk <[email protected]>
---
drivers/crypto/qat/qat_common/Makefile | 12 +
drivers/crypto/qat/qat_common/qat_asym_algs.c | 225 +++++++++++++++------
drivers/crypto/qat/qat_common/qat_rsakey.asn1 | 5
drivers/crypto/qat/qat_common/qat_rsaprivkey.asn1 | 11 +
drivers/crypto/qat/qat_common/qat_rsapubkey.asn1 | 4
5 files changed, 189 insertions(+), 68 deletions(-)
delete mode 100644 drivers/crypto/qat/qat_common/qat_rsakey.asn1
create mode 100644 drivers/crypto/qat/qat_common/qat_rsaprivkey.asn1
create mode 100644 drivers/crypto/qat/qat_common/qat_rsapubkey.asn1

diff --git a/drivers/crypto/qat/qat_common/Makefile b/drivers/crypto/qat/qat_common/Makefile
index ba5abdb..9e9e196 100644
--- a/drivers/crypto/qat/qat_common/Makefile
+++ b/drivers/crypto/qat/qat_common/Makefile
@@ -1,5 +1,10 @@
-$(obj)/qat_rsakey-asn1.o: $(obj)/qat_rsakey-asn1.c $(obj)/qat_rsakey-asn1.h
-clean-files += qat_rsakey-asn1.c qat_rsakey-asn1.h
+$(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_rsapvivkey-asn1.h

obj-$(CONFIG_CRYPTO_DEV_QAT) += intel_qat.o
intel_qat-objs := adf_cfg.o \
@@ -13,6 +18,9 @@ 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 7de765d..d0c6e9c 100644
--- a/drivers/crypto/qat/qat_common/qat_asym_algs.c
+++ b/drivers/crypto/qat/qat_common/qat_asym_algs.c
@@ -51,7 +51,9 @@
#include <crypto/akcipher.h>
#include <linux/dma-mapping.h>
#include <linux/fips.h>
-#include "qat_rsakey-asn1.h"
+#include <crypto/scatterwalk.h>
+#include "qat_rsapubkey-asn1.h"
+#include "qat_rsaprivkey-asn1.h"
#include "icp_qat_fw_pke.h"
#include "adf_accel_devices.h"
#include "adf_transport.h"
@@ -106,6 +108,7 @@ struct qat_rsa_request {
dma_addr_t phy_in;
dma_addr_t phy_out;
char *src_align;
+ char *dst_align;
struct icp_qat_fw_pke_request req;
struct qat_rsa_ctx *ctx;
int err;
@@ -118,7 +121,6 @@ static void qat_rsa_cb(struct icp_qat_fw_pke_resp *resp)
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);
- char *ptr = areq->dst;

err = (err == ICP_QAT_FW_COMN_STATUS_FLAG_OK) ? 0 : -EINVAL;

@@ -129,24 +131,44 @@ static void qat_rsa_cb(struct icp_qat_fw_pke_resp *resp)
dma_unmap_single(dev, req->in.enc.m, req->ctx->key_sz,
DMA_TO_DEVICE);

- dma_unmap_single(dev, req->out.enc.c, req->ctx->key_sz,
- DMA_FROM_DEVICE);
+ areq->out_len = req->ctx->key_sz;
+ if (req->dst_align) {
+ char *ptr = req->dst_align;
+
+ while (!(*ptr) && areq->out_len) {
+ areq->out_len--;
+ ptr++;
+ }
+
+ if (areq->out_len != req->ctx->key_sz)
+ memmove(req->dst_align, ptr, areq->out_len);
+
+ scatterwalk_map_and_copy(req->dst_align, areq->dst, 0,
+ areq->out_len, 1);
+
+ dma_free_coherent(dev, req->ctx->key_sz, req->dst_align,
+ req->out.enc.c);
+ } else {
+ char *ptr = sg_virt(areq->dst);
+
+ while (!(*ptr) && areq->out_len) {
+ areq->out_len--;
+ ptr++;
+ }
+
+ if (sg_virt(areq->dst) != ptr && areq->out_len)
+ memmove(sg_virt(areq->dst), ptr, areq->out_len);
+
+ dma_unmap_single(dev, req->out.enc.c, req->ctx->key_sz,
+ DMA_FROM_DEVICE);
+ }
+
dma_unmap_single(dev, req->phy_in, sizeof(struct qat_rsa_input_params),
DMA_TO_DEVICE);
dma_unmap_single(dev, req->phy_out,
sizeof(struct qat_rsa_output_params),
DMA_TO_DEVICE);

- areq->dst_len = req->ctx->key_sz;
- /* Need to set the corect length of the output */
- while (!(*ptr) && areq->dst_len) {
- areq->dst_len--;
- ptr++;
- }
-
- if (areq->dst_len != req->ctx->key_sz)
- memmove(areq->dst, ptr, areq->dst_len);
-
akcipher_request_complete(areq, err);
}

@@ -224,13 +246,14 @@ static int qat_rsa_enc(struct akcipher_request *req)
struct qat_rsa_request *qat_req =
PTR_ALIGN(akcipher_request_ctx(req), 64);
struct icp_qat_fw_pke_request *msg = &qat_req->req;
+ int src_len = sg_len(req->src), dst_len = sg_len(req->dst);
int ret, ctr = 0;

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

- if (req->dst_len < ctx->key_sz) {
- req->dst_len = ctx->key_sz;
+ if (dst_len < ctx->key_sz) {
+ req->out_len = ctx->key_sz;
return -EOVERFLOW;
}
memset(msg, '\0', sizeof(*msg));
@@ -255,9 +278,17 @@ static int qat_rsa_enc(struct akcipher_request *req)
* same as modulo n so in case it is different we need to allocate a
* new buf and copy src data.
* In other case we just need to map the user provided buffer.
+ * Also need to make sure that it is in contiguous buffer.
*/
- if (req->src_len < ctx->key_sz) {
- int shift = ctx->key_sz - req->src_len;
+ if (sg_is_last(req->src) && src_len == ctx->key_sz) {
+ qat_req->src_align = NULL;
+ qat_req->in.enc.m = dma_map_single(dev, sg_virt(req->src),
+ src_len, DMA_TO_DEVICE);
+ if (unlikely(dma_mapping_error(dev, qat_req->in.enc.m)))
+ return ret;
+
+ } else {
+ int shift = ctx->key_sz - src_len;

qat_req->src_align = dma_zalloc_coherent(dev, ctx->key_sz,
&qat_req->in.enc.m,
@@ -265,29 +296,38 @@ static int qat_rsa_enc(struct akcipher_request *req)
if (unlikely(!qat_req->src_align))
return ret;

- memcpy(qat_req->src_align + shift, req->src, req->src_len);
+ scatterwalk_map_and_copy(qat_req->src_align + shift, req->src,
+ 0, src_len, 0);
+ }
+ if (sg_is_last(req->dst) && dst_len == ctx->key_sz) {
+ qat_req->dst_align = NULL;
+ qat_req->out.enc.c = dma_map_single(dev, sg_virt(req->dst),
+ dst_len, DMA_FROM_DEVICE);
+
+ if (unlikely(dma_mapping_error(dev, qat_req->out.enc.c)))
+ goto unmap_src;
+
} else {
- qat_req->src_align = NULL;
- qat_req->in.enc.m = dma_map_single(dev, req->src, req->src_len,
- DMA_TO_DEVICE);
+ qat_req->dst_align = dma_zalloc_coherent(dev, ctx->key_sz,
+ &qat_req->out.enc.c,
+ GFP_KERNEL);
+ if (unlikely(!qat_req->dst_align))
+ goto unmap_src;
+
}
qat_req->in.in_tab[3] = 0;
- qat_req->out.enc.c = dma_map_single(dev, req->dst, req->dst_len,
- DMA_FROM_DEVICE);
qat_req->out.out_tab[1] = 0;
qat_req->phy_in = dma_map_single(dev, &qat_req->in.enc.m,
sizeof(struct qat_rsa_input_params),
DMA_TO_DEVICE);
+ if (unlikely(dma_mapping_error(dev, qat_req->phy_in)))
+ goto unmap_dst;
+
qat_req->phy_out = dma_map_single(dev, &qat_req->out.enc.c,
sizeof(struct qat_rsa_output_params),
- DMA_TO_DEVICE);
-
- if (unlikely((!qat_req->src_align &&
- dma_mapping_error(dev, qat_req->in.enc.m)) ||
- dma_mapping_error(dev, qat_req->out.enc.c) ||
- dma_mapping_error(dev, qat_req->phy_in) ||
- dma_mapping_error(dev, qat_req->phy_out)))
- goto unmap;
+ DMA_TO_DEVICE);
+ if (unlikely(dma_mapping_error(dev, qat_req->phy_out)))
+ goto unmap_in_params;

msg->pke_mid.src_data_addr = qat_req->phy_in;
msg->pke_mid.dest_data_addr = qat_req->phy_out;
@@ -300,7 +340,7 @@ static int qat_rsa_enc(struct akcipher_request *req)

if (!ret)
return -EINPROGRESS;
-unmap:
+unmap_src:
if (qat_req->src_align)
dma_free_coherent(dev, ctx->key_sz, qat_req->src_align,
qat_req->in.enc.m);
@@ -308,9 +348,15 @@ unmap:
if (!dma_mapping_error(dev, qat_req->in.enc.m))
dma_unmap_single(dev, qat_req->in.enc.m, ctx->key_sz,
DMA_TO_DEVICE);
- if (!dma_mapping_error(dev, qat_req->out.enc.c))
- dma_unmap_single(dev, qat_req->out.enc.c, ctx->key_sz,
- DMA_FROM_DEVICE);
+unmap_dst:
+ if (qat_req->dst_align)
+ dma_free_coherent(dev, ctx->key_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_FROM_DEVICE);
+unmap_in_params:
if (!dma_mapping_error(dev, qat_req->phy_in))
dma_unmap_single(dev, qat_req->phy_in,
sizeof(struct qat_rsa_input_params),
@@ -331,13 +377,14 @@ static int qat_rsa_dec(struct akcipher_request *req)
struct qat_rsa_request *qat_req =
PTR_ALIGN(akcipher_request_ctx(req), 64);
struct icp_qat_fw_pke_request *msg = &qat_req->req;
+ int src_len = sg_len(req->src), dst_len = sg_len(req->dst);
int ret, ctr = 0;

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

- if (req->dst_len < ctx->key_sz) {
- req->dst_len = ctx->key_sz;
+ if (dst_len < ctx->key_sz) {
+ req->out_len = ctx->key_sz;
return -EOVERFLOW;
}
memset(msg, '\0', sizeof(*msg));
@@ -362,9 +409,17 @@ static int qat_rsa_dec(struct akcipher_request *req)
* same as modulo n so in case it is different we need to allocate a
* new buf and copy src data.
* In other case we just need to map the user provided buffer.
+ * Also need to make sure that it is in contiguous buffer.
*/
- if (req->src_len < ctx->key_sz) {
- int shift = ctx->key_sz - req->src_len;
+ if (sg_is_last(req->src) && src_len == ctx->key_sz) {
+ qat_req->src_align = NULL;
+ qat_req->in.dec.c = dma_map_single(dev, sg_virt(req->src),
+ dst_len, DMA_TO_DEVICE);
+ if (unlikely(dma_mapping_error(dev, qat_req->in.dec.c)))
+ return ret;
+
+ } else {
+ int shift = ctx->key_sz - src_len;

qat_req->src_align = dma_zalloc_coherent(dev, ctx->key_sz,
&qat_req->in.dec.c,
@@ -372,29 +427,39 @@ static int qat_rsa_dec(struct akcipher_request *req)
if (unlikely(!qat_req->src_align))
return ret;

- memcpy(qat_req->src_align + shift, req->src, req->src_len);
+ scatterwalk_map_and_copy(qat_req->src_align + shift, req->src,
+ 0, src_len, 0);
+ }
+ if (sg_is_last(req->dst) && dst_len == ctx->key_sz) {
+ qat_req->dst_align = NULL;
+ qat_req->out.dec.m = dma_map_single(dev, sg_virt(req->dst),
+ dst_len, DMA_FROM_DEVICE);
+
+ if (unlikely(dma_mapping_error(dev, qat_req->out.dec.m)))
+ goto unmap_src;
+
} else {
- qat_req->src_align = NULL;
- qat_req->in.dec.c = dma_map_single(dev, req->src, req->src_len,
- DMA_TO_DEVICE);
+ qat_req->dst_align = dma_zalloc_coherent(dev, ctx->key_sz,
+ &qat_req->out.dec.m,
+ GFP_KERNEL);
+ if (unlikely(!qat_req->dst_align))
+ goto unmap_src;
+
}
+
qat_req->in.in_tab[3] = 0;
- qat_req->out.dec.m = dma_map_single(dev, req->dst, req->dst_len,
- DMA_FROM_DEVICE);
qat_req->out.out_tab[1] = 0;
qat_req->phy_in = dma_map_single(dev, &qat_req->in.dec.c,
sizeof(struct qat_rsa_input_params),
DMA_TO_DEVICE);
+ if (unlikely(dma_mapping_error(dev, qat_req->phy_in)))
+ goto unmap_dst;
+
qat_req->phy_out = dma_map_single(dev, &qat_req->out.dec.m,
sizeof(struct qat_rsa_output_params),
- DMA_TO_DEVICE);
-
- if (unlikely((!qat_req->src_align &&
- dma_mapping_error(dev, qat_req->in.dec.c)) ||
- dma_mapping_error(dev, qat_req->out.dec.m) ||
- dma_mapping_error(dev, qat_req->phy_in) ||
- dma_mapping_error(dev, qat_req->phy_out)))
- goto unmap;
+ DMA_TO_DEVICE);
+ if (unlikely(dma_mapping_error(dev, qat_req->phy_out)))
+ goto unmap_in_params;

msg->pke_mid.src_data_addr = qat_req->phy_in;
msg->pke_mid.dest_data_addr = qat_req->phy_out;
@@ -407,7 +472,7 @@ static int qat_rsa_dec(struct akcipher_request *req)

if (!ret)
return -EINPROGRESS;
-unmap:
+unmap_src:
if (qat_req->src_align)
dma_free_coherent(dev, ctx->key_sz, qat_req->src_align,
qat_req->in.dec.c);
@@ -415,9 +480,15 @@ unmap:
if (!dma_mapping_error(dev, qat_req->in.dec.c))
dma_unmap_single(dev, qat_req->in.dec.c, ctx->key_sz,
DMA_TO_DEVICE);
- if (!dma_mapping_error(dev, qat_req->out.dec.m))
- dma_unmap_single(dev, qat_req->out.dec.m, ctx->key_sz,
- DMA_FROM_DEVICE);
+unmap_dst:
+ if (qat_req->dst_align)
+ dma_free_coherent(dev, ctx->key_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_FROM_DEVICE);
+unmap_in_params:
if (!dma_mapping_error(dev, qat_req->phy_in))
dma_unmap_single(dev, qat_req->phy_in,
sizeof(struct qat_rsa_input_params),
@@ -531,7 +602,7 @@ err:
}

static int qat_rsa_setkey(struct crypto_akcipher *tfm, const void *key,
- unsigned int keylen)
+ unsigned int keylen, bool private)
{
struct qat_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
struct device *dev = &GET_DEV(ctx->inst->accel_dev);
@@ -550,7 +621,13 @@ static int qat_rsa_setkey(struct crypto_akcipher *tfm, const void *key,
ctx->n = NULL;
ctx->e = NULL;
ctx->d = NULL;
- ret = asn1_ber_decoder(&qat_rsakey_decoder, ctx, key, keylen);
+
+ if (private)
+ ret = asn1_ber_decoder(&qat_rsaprivkey_decoder, ctx, key,
+ keylen);
+ else
+ ret = asn1_ber_decoder(&qat_rsapubkey_decoder, ctx, key,
+ keylen);
if (ret < 0)
goto free;

@@ -559,6 +636,11 @@ static int qat_rsa_setkey(struct crypto_akcipher *tfm, const void *key,
ret = -EINVAL;
goto free;
}
+ if (private && !ctx->d) {
+ /* invalid private key provided */
+ ret = -EINVAL;
+ goto free;
+ }

return 0;
free:
@@ -579,6 +661,25 @@ free:
return ret;
}

+static int qat_rsa_setpubkey(struct crypto_akcipher *tfm, const void *key,
+ unsigned int keylen)
+{
+ return qat_rsa_setkey(tfm, key, keylen, false);
+}
+
+static int qat_rsa_setprivkey(struct crypto_akcipher *tfm, const void *key,
+ unsigned int keylen)
+{
+ return qat_rsa_setkey(tfm, key, keylen, true);
+}
+
+static int qat_rsa_get_len(struct crypto_akcipher *tfm)
+{
+ struct qat_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
+
+ return (ctx->n) ? ctx->key_sz : -EINVAL;
+}
+
static int qat_rsa_init_tfm(struct crypto_akcipher *tfm)
{
struct qat_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
@@ -617,7 +718,9 @@ static struct akcipher_alg rsa = {
.decrypt = qat_rsa_dec,
.sign = qat_rsa_dec,
.verify = qat_rsa_enc,
- .setkey = qat_rsa_setkey,
+ .set_pub_key = qat_rsa_setpubkey,
+ .set_priv_key = qat_rsa_setprivkey,
+ .get_len = qat_rsa_get_len,
.init = qat_rsa_init_tfm,
.exit = qat_rsa_exit_tfm,
.reqsize = sizeof(struct qat_rsa_request) + 64,
diff --git a/drivers/crypto/qat/qat_common/qat_rsakey.asn1 b/drivers/crypto/qat/qat_common/qat_rsakey.asn1
deleted file mode 100644
index 97b0e02..0000000
--- a/drivers/crypto/qat/qat_common/qat_rsakey.asn1
+++ /dev/null
@@ -1,5 +0,0 @@
-RsaKey ::= SEQUENCE {
- n INTEGER ({ qat_rsa_get_n }),
- e INTEGER ({ qat_rsa_get_e }),
- d INTEGER ({ qat_rsa_get_d })
-}
diff --git a/drivers/crypto/qat/qat_common/qat_rsaprivkey.asn1 b/drivers/crypto/qat/qat_common/qat_rsaprivkey.asn1
new file mode 100644
index 0000000..f0066ad
--- /dev/null
+++ b/drivers/crypto/qat/qat_common/qat_rsaprivkey.asn1
@@ -0,0 +1,11 @@
+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
new file mode 100644
index 0000000..bd667b3
--- /dev/null
+++ b/drivers/crypto/qat/qat_common/qat_rsapubkey.asn1
@@ -0,0 +1,4 @@
+RsaPubKey ::= SEQUENCE {
+ n INTEGER ({ qat_rsa_get_n }),
+ e INTEGER ({ qat_rsa_get_e })
+}

2015-09-09 16:17:14

by Tadeusz Struk

[permalink] [raw]
Subject: [PATCH 5/8] lib/scatterlist: Add sg_len helper

Add sg_len function which returns the total number of bytes in sg.

Signed-off-by: Tadeusz Struk <[email protected]>
---
include/linux/scatterlist.h | 1 +
lib/scatterlist.c | 18 ++++++++++++++++++
2 files changed, 19 insertions(+)

diff --git a/include/linux/scatterlist.h b/include/linux/scatterlist.h
index 9b1ef0c..7c82fc1 100644
--- a/include/linux/scatterlist.h
+++ b/include/linux/scatterlist.h
@@ -246,6 +246,7 @@ static inline void *sg_virt(struct scatterlist *sg)
}

int sg_nents(struct scatterlist *sg);
+int sg_len(struct scatterlist *sg);
int sg_nents_for_len(struct scatterlist *sg, u64 len);
struct scatterlist *sg_next(struct scatterlist *);
struct scatterlist *sg_last(struct scatterlist *s, unsigned int);
diff --git a/lib/scatterlist.c b/lib/scatterlist.c
index d105a9f..71324bb 100644
--- a/lib/scatterlist.c
+++ b/lib/scatterlist.c
@@ -57,6 +57,24 @@ int sg_nents(struct scatterlist *sg)
EXPORT_SYMBOL(sg_nents);

/**
+ * sg_len - return total size of bytes in the scatterlist
+ * @sg: The scatterlist
+ *
+ * Description:
+ * Allows to know how the total size of bytes in sg, taking into acount
+ * chaining as well
+ **/
+int sg_len(struct scatterlist *sg)
+{
+ int len;
+
+ for (len = 0; sg; sg = sg_next(sg))
+ len += sg->length;
+ return len;
+}
+EXPORT_SYMBOL(sg_len);
+
+/**
* sg_nents_for_len - return total count of entries in scatterlist
* needed to satisfy the supplied length
* @sg: The scatterlist

2015-09-09 16:17:38

by Tadeusz Struk

[permalink] [raw]
Subject: [PATCH 8/8] crypto: testmgr - update test mgr according to API changes

Signed-off-by: Tadeusz Struk <[email protected]>
---
crypto/testmgr.c | 44 +++++++++++++++++++++-----------------------
crypto/testmgr.h | 36 +++++++++++++++++++++++++++---------
2 files changed, 48 insertions(+), 32 deletions(-)

diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index 2f2b66e..f268707 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -1835,7 +1835,6 @@ static int alg_test_drbg(const struct alg_test_desc *desc, const char *driver,

}

-#if 0
static int do_test_rsa(struct crypto_akcipher *tfm,
struct akcipher_testvec *vecs)
{
@@ -1845,34 +1844,33 @@ static int do_test_rsa(struct crypto_akcipher *tfm,
struct tcrypt_result result;
unsigned int out_len_max, out_len = 0;
int err = -ENOMEM;
+ struct scatterlist src, dst, src_tab[2];

req = akcipher_request_alloc(tfm, GFP_KERNEL);
if (!req)
return err;

init_completion(&result.completion);
- err = crypto_akcipher_setkey(tfm, vecs->key, vecs->key_len);
- if (err)
- goto free_req;

- akcipher_request_set_crypt(req, vecs->m, outbuf_enc, vecs->m_size,
- out_len);
- /* expect this to fail, and update the required buf len */
- crypto_akcipher_encrypt(req);
- out_len = req->dst_len;
- if (!out_len) {
- err = -EINVAL;
+ if (vecs->public_key_vec)
+ err = crypto_akcipher_set_pub_key(tfm, vecs->key,
+ vecs->key_len);
+ else
+ err = crypto_akcipher_set_priv_key(tfm, vecs->key,
+ vecs->key_len);
+ if (err)
goto free_req;
- }

- out_len_max = out_len;
- err = -ENOMEM;
+ out_len_max = crypto_akcipher_get_len(tfm);
outbuf_enc = kzalloc(out_len_max, GFP_KERNEL);
if (!outbuf_enc)
goto free_req;

- akcipher_request_set_crypt(req, vecs->m, outbuf_enc, vecs->m_size,
- out_len);
+ sg_init_table(src_tab, 2);
+ sg_set_buf(&src_tab[0], vecs->m, 8);
+ sg_set_buf(&src_tab[1], vecs->m + 8, vecs->m_size - 8);
+ sg_init_one(&dst, outbuf_enc, out_len_max);
+ akcipher_request_set_crypt(req, src_tab, &dst);
akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
tcrypt_complete, &result);

@@ -1882,13 +1880,13 @@ static int do_test_rsa(struct crypto_akcipher *tfm,
pr_err("alg: rsa: encrypt test failed. err %d\n", err);
goto free_all;
}
- if (out_len != vecs->c_size) {
+ if (req->out_len != vecs->c_size) {
pr_err("alg: rsa: encrypt test failed. Invalid output len\n");
err = -EINVAL;
goto free_all;
}
/* verify that encrypted message is equal to expected */
- if (memcmp(vecs->c, outbuf_enc, vecs->c_size)) {
+ if (memcmp(vecs->c, sg_virt(req->dst), vecs->c_size)) {
pr_err("alg: rsa: encrypt test failed. Invalid output\n");
err = -EINVAL;
goto free_all;
@@ -1903,9 +1901,10 @@ static int do_test_rsa(struct crypto_akcipher *tfm,
err = -ENOMEM;
goto free_all;
}
+ sg_init_one(&src, vecs->c, vecs->c_size);
+ sg_init_one(&dst, outbuf_dec, out_len_max);
init_completion(&result.completion);
- akcipher_request_set_crypt(req, outbuf_enc, outbuf_dec, vecs->c_size,
- out_len);
+ akcipher_request_set_crypt(req, &src, &dst);

/* Run RSA decrypt - m = c^d mod n;*/
err = wait_async_op(&result, crypto_akcipher_decrypt(req));
@@ -1913,7 +1912,7 @@ static int do_test_rsa(struct crypto_akcipher *tfm,
pr_err("alg: rsa: decrypt test failed. err %d\n", err);
goto free_all;
}
- out_len = req->dst_len;
+ out_len = req->out_len;
if (out_len != vecs->m_size) {
pr_err("alg: rsa: decrypt test failed. Invalid output len\n");
err = -EINVAL;
@@ -1976,7 +1975,6 @@ static int alg_test_akcipher(const struct alg_test_desc *desc,
crypto_free_akcipher(tfm);
return err;
}
-#endif

static int alg_test_null(const struct alg_test_desc *desc,
const char *driver, u32 type, u32 mask)
@@ -3613,7 +3611,7 @@ static const struct alg_test_desc alg_test_descs[] = {
}
}, {
.alg = "rsa",
- .test = alg_test_null,
+ .test = alg_test_akcipher,
.fips_allowed = 1,
.suite = {
.akcipher = {
diff --git a/crypto/testmgr.h b/crypto/testmgr.h
index 64b8a80..e10582d 100644
--- a/crypto/testmgr.h
+++ b/crypto/testmgr.h
@@ -149,7 +149,8 @@ static struct akcipher_testvec rsa_tv_template[] = {
{
#ifndef CONFIG_CRYPTO_FIPS
.key =
- "\x30\x81\x88" /* sequence of 136 bytes */
+ "\x30\x81\x9A" /* sequence of 154 bytes */
+ "\x02\x01\x01" /* version - integer of 1 byte */
"\x02\x41" /* modulus - integer of 65 bytes */
"\x00\xAA\x36\xAB\xCE\x88\xAC\xFD\xFF\x55\x52\x3C\x7F\xC4\x52\x3F"
"\x90\xEF\xA0\x0D\xF3\x77\x4A\x25\x9F\x2E\x62\xB4\xC5\xD9\x9C\xB5"
@@ -161,19 +162,25 @@ static struct akcipher_testvec rsa_tv_template[] = {
"\x0A\x03\x37\x48\x62\x64\x87\x69\x5F\x5F\x30\xBC\x38\xB9\x8B\x44"
"\xC2\xCD\x2D\xFF\x43\x40\x98\xCD\x20\xD8\xA1\x38\xD0\x90\xBF\x64"
"\x79\x7C\x3F\xA7\xA2\xCD\xCB\x3C\xD1\xE0\xBD\xBA\x26\x54\xB4\xF9"
- "\xDF\x8E\x8A\xE5\x9D\x73\x3D\x9F\x33\xB3\x01\x62\x4A\xFD\x1D\x51",
+ "\xDF\x8E\x8A\xE5\x9D\x73\x3D\x9F\x33\xB3\x01\x62\x4A\xFD\x1D\x51"
+ "\x02\x01\x00" /* prime1 - integer of 1 byte */
+ "\x02\x01\x00" /* prime2 - integer of 1 byte */
+ "\x02\x01\x00" /* exponent1 - integer of 1 byte */
+ "\x02\x01\x00" /* exponent2 - integer of 1 byte */
+ "\x02\x01\x00", /* coefficient - integer of 1 byte */
.m = "\x54\x85\x9b\x34\x2c\x49\xea\x2a",
.c =
"\x63\x1c\xcd\x7b\xe1\x7e\xe4\xde\xc9\xa8\x89\xa1\x74\xcb\x3c\x63"
"\x7d\x24\xec\x83\xc3\x15\xe4\x7f\x73\x05\x34\xd1\xec\x22\xbb\x8a"
"\x5e\x32\x39\x6d\xc1\x1d\x7d\x50\x3b\x9f\x7a\xad\xf0\x2e\x25\x53"
"\x9f\x6e\xbd\x4c\x55\x84\x0c\x9b\xcf\x1a\x4b\x51\x1e\x9e\x0c\x06",
- .key_len = 139,
+ .key_len = 157,
.m_size = 8,
.c_size = 64,
}, {
.key =
- "\x30\x82\x01\x0B" /* sequence of 267 bytes */
+ "\x30\x82\x01\x1D" /* sequence of 285 bytes */
+ "\x02\x01\x01" /* version - integer of 1 byte */
"\x02\x81\x81" /* modulus - integer of 129 bytes */
"\x00\xBB\xF8\x2F\x09\x06\x82\xCE\x9C\x23\x38\xAC\x2B\x9D\xA8\x71"
"\xF7\x36\x8D\x07\xEE\xD4\x10\x43\xA4\x40\xD6\xB6\xF0\x74\x54\xF5"
@@ -194,8 +201,13 @@ static struct akcipher_testvec rsa_tv_template[] = {
"\x44\xE5\x6A\xAF\x68\xC5\x6C\x09\x2C\xD3\x8D\xC3\xBE\xF5\xD2\x0A"
"\x93\x99\x26\xED\x4F\x74\xA1\x3E\xDD\xFB\xE1\xA1\xCE\xCC\x48\x94"
"\xAF\x94\x28\xC2\xB7\xB8\x88\x3F\xE4\x46\x3A\x4B\xC8\x5B\x1C\xB3"
- "\xC1",
- .key_len = 271,
+ "\xC1"
+ "\x02\x01\x00" /* prime1 - integer of 1 byte */
+ "\x02\x01\x00" /* prime2 - integer of 1 byte */
+ "\x02\x01\x00" /* exponent1 - integer of 1 byte */
+ "\x02\x01\x00" /* exponent2 - integer of 1 byte */
+ "\x02\x01\x00", /* coefficient - integer of 1 byte */
+ .key_len = 289,
.m = "\x54\x85\x9b\x34\x2c\x49\xea\x2a",
.c =
"\x74\x1b\x55\xac\x47\xb5\x08\x0a\x6e\x2b\x2d\xf7\x94\xb8\x8a\x95"
@@ -211,7 +223,8 @@ static struct akcipher_testvec rsa_tv_template[] = {
}, {
#endif
.key =
- "\x30\x82\x02\x0D" /* sequence of 525 bytes */
+ "\x30\x82\x02\x1F" /* sequence of 543 bytes */
+ "\x02\x01\x01" /* version - integer of 1 byte */
"\x02\x82\x01\x00" /* modulus - integer of 256 bytes */
"\xDB\x10\x1A\xC2\xA3\xF1\xDC\xFF\x13\x6B\xED\x44\xDF\xF0\x02\x6D"
"\x13\xC7\x88\xDA\x70\x6B\x54\xF1\xE8\x27\xDC\xC3\x0F\x99\x6A\xFA"
@@ -246,8 +259,13 @@ static struct akcipher_testvec rsa_tv_template[] = {
"\x77\xAF\x51\x27\x5B\x5E\x69\xB8\x81\xE6\x11\xC5\x43\x23\x81\x04"
"\x62\xFF\xE9\x46\xB8\xD8\x44\xDB\xA5\xCC\x31\x54\x34\xCE\x3E\x82"
"\xD6\xBF\x7A\x0B\x64\x21\x6D\x88\x7E\x5B\x45\x12\x1E\x63\x8D\x49"
- "\xA7\x1D\xD9\x1E\x06\xCD\xE8\xBA\x2C\x8C\x69\x32\xEA\xBE\x60\x71",
- .key_len = 529,
+ "\xA7\x1D\xD9\x1E\x06\xCD\xE8\xBA\x2C\x8C\x69\x32\xEA\xBE\x60\x71"
+ "\x02\x01\x00" /* prime1 - integer of 1 byte */
+ "\x02\x01\x00" /* prime2 - integer of 1 byte */
+ "\x02\x01\x00" /* exponent1 - integer of 1 byte */
+ "\x02\x01\x00" /* exponent2 - integer of 1 byte */
+ "\x02\x01\x00", /* coefficient - integer of 1 byte */
+ .key_len = 547,
.m = "\x54\x85\x9b\x34\x2c\x49\xea\x2a",
.c =
"\xb2\x97\x76\xb4\xae\x3e\x38\x3c\x7e\x64\x1f\xcc\xa2\x7f\xf6\xbe"

2015-09-09 16:17:20

by Tadeusz Struk

[permalink] [raw]
Subject: [PATCH 6/8] crypto: rsa - update accoring to akcipher API changes

Rsa updates to reflect the API changes.

Signed-off-by: Tadeusz Struk <[email protected]>
---
crypto/Makefile | 12 ++-
crypto/rsa.c | 188 ++++++++++++++++++++++++++++++++++-------
crypto/rsa_helper.c | 42 ++++++++-
crypto/rsakey.asn1 | 5 -
crypto/rsaprivkey.asn1 | 11 ++
crypto/rsapubkey.asn1 | 4 +
include/crypto/internal/rsa.h | 7 +-
7 files changed, 220 insertions(+), 49 deletions(-)
delete mode 100644 crypto/rsakey.asn1
create mode 100644 crypto/rsaprivkey.asn1
create mode 100644 crypto/rsapubkey.asn1

diff --git a/crypto/Makefile b/crypto/Makefile
index 65e91da..d897e0b 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -31,8 +31,16 @@ obj-$(CONFIG_CRYPTO_HASH2) += crypto_hash.o
obj-$(CONFIG_CRYPTO_PCOMP2) += pcompress.o
obj-$(CONFIG_CRYPTO_AKCIPHER2) += akcipher.o

-$(obj)/rsakey-asn1.o: $(obj)/rsakey-asn1.c $(obj)/rsakey-asn1.h
-clean-files += rsakey-asn1.c rsakey-asn1.h
+$(obj)/rsapubkey-asn1.o: $(obj)/rsapubkey-asn1.c $(obj)/rsapubkey-asn1.h
+$(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
+rsa_generic-y += rsa.o
+rsa_generic-y += rsa_helper.o
+obj-$(CONFIG_CRYPTO_RSA) += rsa_generic.o

cryptomgr-y := algboss.o testmgr.o

diff --git a/crypto/rsa.c b/crypto/rsa.c
index 93feae2..f5b956c 100644
--- a/crypto/rsa.c
+++ b/crypto/rsa.c
@@ -13,6 +13,7 @@
#include <crypto/internal/rsa.h>
#include <crypto/internal/akcipher.h>
#include <crypto/akcipher.h>
+#include <crypto/scatterwalk.h>

/*
* RSAEP function [RFC3447 sec 5.1.1]
@@ -80,34 +81,57 @@ 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);
MPI m, c = mpi_alloc(0);
+ int src_len = sg_len(req->src), dst_len = sg_len(req->dst);
int ret = 0;
int sign;

if (!c)
return -ENOMEM;

- if (unlikely(!pkey->n || !pkey->e)) {
+ if (unlikely(!pkey->n || !pkey->e || !src_len)) {
ret = -EINVAL;
goto err_free_c;
}

- if (req->dst_len < mpi_get_size(pkey->n)) {
- req->dst_len = mpi_get_size(pkey->n);
+ if (dst_len < mpi_get_size(pkey->n)) {
+ req->out_len = mpi_get_size(pkey->n);
ret = -EOVERFLOW;
goto err_free_c;
}

- m = mpi_read_raw_data(req->src, req->src_len);
- if (!m) {
- ret = -ENOMEM;
- goto err_free_c;
+ ret = -ENOMEM;
+ if (sg_is_last(req->src)) {
+ m = mpi_read_raw_data(sg_virt(req->src), src_len);
+ } else {
+ void *ptr = kmalloc(src_len, GFP_KERNEL);
+
+ if (!ptr)
+ goto err_free_c;
+
+ scatterwalk_map_and_copy(ptr, req->src, 0, src_len, 0);
+ m = mpi_read_raw_data(ptr, src_len);
+ kfree(ptr);
}
+ if (!m)
+ goto err_free_c;

ret = _rsa_enc(pkey, c, m);
if (ret)
goto err_free_m;

- ret = mpi_read_buffer(c, req->dst, req->dst_len, &req->dst_len, &sign);
+ if (sg_is_last(req->dst)) {
+ ret = mpi_read_buffer(c, sg_virt(req->dst), dst_len,
+ &req->out_len, &sign);
+ } else {
+ void *ptr = kmalloc(dst_len, GFP_KERNEL);
+
+ if (!ptr)
+ goto err_free_m;
+
+ ret = mpi_read_buffer(c, ptr, dst_len, &req->out_len, &sign);
+ scatterwalk_map_and_copy(ptr, req->dst, 0, dst_len, 1);
+ kfree(ptr);
+ }
if (ret)
goto err_free_m;

@@ -128,34 +152,57 @@ 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);
MPI c, m = mpi_alloc(0);
+ int src_len = sg_len(req->src), dst_len = sg_len(req->dst);
int ret = 0;
int sign;

if (!m)
return -ENOMEM;

- if (unlikely(!pkey->n || !pkey->d)) {
+ if (unlikely(!pkey->n || !pkey->d || !src_len)) {
ret = -EINVAL;
goto err_free_m;
}

- if (req->dst_len < mpi_get_size(pkey->n)) {
- req->dst_len = mpi_get_size(pkey->n);
+ if (dst_len < mpi_get_size(pkey->n)) {
+ req->out_len = mpi_get_size(pkey->n);
ret = -EOVERFLOW;
goto err_free_m;
}

- c = mpi_read_raw_data(req->src, req->src_len);
- if (!c) {
- ret = -ENOMEM;
- goto err_free_m;
+ ret = -ENOMEM;
+ if (sg_is_last(req->src)) {
+ c = mpi_read_raw_data(sg_virt(req->src), src_len);
+ } else {
+ void *ptr = kmalloc(src_len, GFP_KERNEL);
+
+ if (!ptr)
+ goto err_free_m;
+
+ scatterwalk_map_and_copy(ptr, req->src, 0, src_len, 0);
+ c = mpi_read_raw_data(ptr, src_len);
+ kfree(ptr);
}
+ if (!c)
+ goto err_free_m;

ret = _rsa_dec(pkey, m, c);
if (ret)
goto err_free_c;

- ret = mpi_read_buffer(m, req->dst, req->dst_len, &req->dst_len, &sign);
+ if (sg_is_last(req->dst)) {
+ ret = mpi_read_buffer(m, sg_virt(req->dst), dst_len,
+ &req->out_len, &sign);
+ } else {
+ void *ptr = kmalloc(dst_len, GFP_KERNEL);
+
+ if (!ptr)
+ goto err_free_c;
+
+ ret = mpi_read_buffer(m, ptr, dst_len, &req->out_len, &sign);
+ scatterwalk_map_and_copy(ptr, req->dst, 0, dst_len, 1);
+ kfree(ptr);
+ }
if (ret)
goto err_free_c;

@@ -176,34 +223,58 @@ 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);
MPI m, s = mpi_alloc(0);
+ int src_len = sg_len(req->src), dst_len = sg_len(req->dst);
int ret = 0;
int sign;

if (!s)
return -ENOMEM;

- if (unlikely(!pkey->n || !pkey->d)) {
+ if (unlikely(!pkey->n || !pkey->d || !src_len)) {
ret = -EINVAL;
goto err_free_s;
}

- if (req->dst_len < mpi_get_size(pkey->n)) {
- req->dst_len = mpi_get_size(pkey->n);
+ if (dst_len < mpi_get_size(pkey->n)) {
+ req->out_len = mpi_get_size(pkey->n);
ret = -EOVERFLOW;
goto err_free_s;
}

- m = mpi_read_raw_data(req->src, req->src_len);
- if (!m) {
- ret = -ENOMEM;
- goto err_free_s;
+ ret = -ENOMEM;
+ if (sg_is_last(req->src)) {
+ m = mpi_read_raw_data(sg_virt(req->src), src_len);
+ } else {
+ void *ptr = kmalloc(src_len, GFP_KERNEL);
+
+ if (!ptr)
+ goto err_free_s;
+
+ scatterwalk_map_and_copy(ptr, req->src, 0, src_len, 0);
+ m = mpi_read_raw_data(ptr, src_len);
+ kfree(ptr);
+
}
+ if (!m)
+ goto err_free_s;

ret = _rsa_sign(pkey, s, m);
if (ret)
goto err_free_m;

- ret = mpi_read_buffer(s, req->dst, req->dst_len, &req->dst_len, &sign);
+ if (sg_is_last(req->dst)) {
+ ret = mpi_read_buffer(s, sg_virt(req->dst), dst_len,
+ &req->out_len, &sign);
+ } else {
+ void *ptr = kmalloc(dst_len, GFP_KERNEL);
+
+ if (!ptr)
+ goto err_free_m;
+
+ ret = mpi_read_buffer(s, ptr, dst_len, &req->out_len, &sign);
+ scatterwalk_map_and_copy(ptr, req->dst, 0, dst_len, 1);
+ kfree(ptr);
+ }
if (ret)
goto err_free_m;

@@ -224,24 +295,37 @@ 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);
MPI s, m = mpi_alloc(0);
+ int src_len = sg_len(req->src), dst_len = sg_len(req->dst);
int ret = 0;
int sign;

if (!m)
return -ENOMEM;

- if (unlikely(!pkey->n || !pkey->e)) {
+ if (unlikely(!pkey->n || !pkey->e || !src_len)) {
ret = -EINVAL;
goto err_free_m;
}

- if (req->dst_len < mpi_get_size(pkey->n)) {
- req->dst_len = mpi_get_size(pkey->n);
+ if (dst_len < mpi_get_size(pkey->n)) {
+ req->out_len = mpi_get_size(pkey->n);
ret = -EOVERFLOW;
goto err_free_m;
}

- s = mpi_read_raw_data(req->src, req->src_len);
+ ret = -ENOMEM;
+ if (sg_is_last(req->src)) {
+ s = mpi_read_raw_data(sg_virt(req->src), src_len);
+ } else {
+ void *ptr = kmalloc(src_len, GFP_KERNEL);
+
+ if (!ptr)
+ goto err_free_m;
+
+ scatterwalk_map_and_copy(ptr, req->src, 0, src_len, 0);
+ s = mpi_read_raw_data(ptr, src_len);
+ kfree(ptr);
+ }
if (!s) {
ret = -ENOMEM;
goto err_free_m;
@@ -251,7 +335,19 @@ static int rsa_verify(struct akcipher_request *req)
if (ret)
goto err_free_s;

- ret = mpi_read_buffer(m, req->dst, req->dst_len, &req->dst_len, &sign);
+ if (sg_is_last(req->dst)) {
+ ret = mpi_read_buffer(m, sg_virt(req->dst), dst_len,
+ &req->out_len, &sign);
+ } else {
+ void *ptr = kmalloc(dst_len, GFP_KERNEL);
+
+ if (!ptr)
+ goto err_free_s;
+
+ ret = mpi_read_buffer(m, ptr, dst_len, &req->out_len, &sign);
+ scatterwalk_map_and_copy(ptr, req->dst, 0, dst_len, 1);
+ kfree(ptr);
+ }
if (ret)
goto err_free_s;

@@ -282,13 +378,30 @@ static int rsa_check_key_length(unsigned int len)
return -EINVAL;
}

-static int rsa_setkey(struct crypto_akcipher *tfm, const void *key,
- unsigned int keylen)
+static int rsa_set_pub_key(struct crypto_akcipher *tfm, const void *key,
+ unsigned int keylen)
+{
+ struct rsa_key *pkey = akcipher_tfm_ctx(tfm);
+ int ret;
+
+ ret = rsa_parse_pub_key(pkey, key, keylen);
+ if (ret)
+ return ret;
+
+ if (rsa_check_key_length(mpi_get_size(pkey->n) << 3)) {
+ rsa_free_key(pkey);
+ ret = -EINVAL;
+ }
+ return ret;
+}
+
+static int rsa_set_priv_key(struct crypto_akcipher *tfm, const void *key,
+ unsigned int keylen)
{
struct rsa_key *pkey = akcipher_tfm_ctx(tfm);
int ret;

- ret = rsa_parse_key(pkey, key, keylen);
+ ret = rsa_parse_priv_key(pkey, key, keylen);
if (ret)
return ret;

@@ -299,6 +412,13 @@ static int rsa_setkey(struct crypto_akcipher *tfm, const void *key,
return ret;
}

+static int rsa_get_len(struct crypto_akcipher *tfm)
+{
+ struct rsa_key *pkey = akcipher_tfm_ctx(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);
@@ -311,7 +431,9 @@ static struct akcipher_alg rsa = {
.decrypt = rsa_dec,
.sign = rsa_sign,
.verify = rsa_verify,
- .setkey = rsa_setkey,
+ .set_priv_key = rsa_set_priv_key,
+ .set_pub_key = rsa_set_pub_key,
+ .get_len = rsa_get_len,
.exit = rsa_exit_tfm,
.base = {
.cra_name = "rsa",
diff --git a/crypto/rsa_helper.c b/crypto/rsa_helper.c
index 8d96ce9..d226f48 100644
--- a/crypto/rsa_helper.c
+++ b/crypto/rsa_helper.c
@@ -15,7 +15,8 @@
#include <linux/err.h>
#include <linux/fips.h>
#include <crypto/internal/rsa.h>
-#include "rsakey-asn1.h"
+#include "rsapubkey-asn1.h"
+#include "rsaprivkey-asn1.h"

int rsa_get_n(void *context, size_t hdrlen, unsigned char tag,
const void *value, size_t vlen)
@@ -94,8 +95,8 @@ void rsa_free_key(struct rsa_key *key)
EXPORT_SYMBOL_GPL(rsa_free_key);

/**
- * rsa_parse_key() - extracts an rsa key from BER encoded buffer
- * and stores it in the provided struct rsa_key
+ * rsa_parse_pub_key() - extracts an rsa public key from BER encoded buffer
+ * and stores it in the provided struct rsa_key
*
* @rsa_key: struct rsa_key key representation
* @key: key in BER format
@@ -103,13 +104,13 @@ EXPORT_SYMBOL_GPL(rsa_free_key);
*
* Return: 0 on success or error code in case of error
*/
-int rsa_parse_key(struct rsa_key *rsa_key, const void *key,
- unsigned int key_len)
+int rsa_parse_pub_key(struct rsa_key *rsa_key, const void *key,
+ unsigned int key_len)
{
int ret;

free_mpis(rsa_key);
- ret = asn1_ber_decoder(&rsakey_decoder, rsa_key, key, key_len);
+ ret = asn1_ber_decoder(&rsapubkey_decoder, rsa_key, key, key_len);
if (ret < 0)
goto error;

@@ -118,4 +119,31 @@ error:
free_mpis(rsa_key);
return ret;
}
-EXPORT_SYMBOL_GPL(rsa_parse_key);
+EXPORT_SYMBOL_GPL(rsa_parse_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_key: struct rsa_key key representation
+ * @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 ret;
+
+ free_mpis(rsa_key);
+ ret = asn1_ber_decoder(&rsaprivkey_decoder, rsa_key, key, key_len);
+ if (ret < 0)
+ goto error;
+
+ return 0;
+error:
+ free_mpis(rsa_key);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(rsa_parse_priv_key);
diff --git a/crypto/rsakey.asn1 b/crypto/rsakey.asn1
deleted file mode 100644
index 3c7b5df..0000000
--- a/crypto/rsakey.asn1
+++ /dev/null
@@ -1,5 +0,0 @@
-RsaKey ::= SEQUENCE {
- n INTEGER ({ rsa_get_n }),
- e INTEGER ({ rsa_get_e }),
- d INTEGER ({ rsa_get_d })
-}
diff --git a/crypto/rsaprivkey.asn1 b/crypto/rsaprivkey.asn1
new file mode 100644
index 0000000..731aea5
--- /dev/null
+++ b/crypto/rsaprivkey.asn1
@@ -0,0 +1,11 @@
+RsaPrivKey ::= SEQUENCE {
+ version INTEGER,
+ n INTEGER ({ rsa_get_n }),
+ e INTEGER ({ rsa_get_e }),
+ d INTEGER ({ rsa_get_d }),
+ prime1 INTEGER,
+ prime2 INTEGER,
+ exponent1 INTEGER,
+ exponent2 INTEGER,
+ coefficient INTEGER
+}
diff --git a/crypto/rsapubkey.asn1 b/crypto/rsapubkey.asn1
new file mode 100644
index 0000000..725498e
--- /dev/null
+++ b/crypto/rsapubkey.asn1
@@ -0,0 +1,4 @@
+RsaPubKey ::= SEQUENCE {
+ n INTEGER ({ rsa_get_n }),
+ e INTEGER ({ rsa_get_e })
+}
diff --git a/include/crypto/internal/rsa.h b/include/crypto/internal/rsa.h
index a8c8636..f997e2d 100644
--- a/include/crypto/internal/rsa.h
+++ b/include/crypto/internal/rsa.h
@@ -20,8 +20,11 @@ struct rsa_key {
MPI d;
};

-int rsa_parse_key(struct rsa_key *rsa_key, const void *key,
- unsigned int key_len);
+int rsa_parse_pub_key(struct rsa_key *rsa_key, const void *key,
+ unsigned int key_len);
+
+int rsa_parse_priv_key(struct rsa_key *rsa_key, const void *key,
+ unsigned int key_len);

void rsa_free_key(struct rsa_key *rsa_key);
#endif

2015-09-09 16:25:24

by Stephan Müller

[permalink] [raw]
Subject: Re: [PATCH 4/8] crypto: akcipher - Changes to asymmetric key API

Am Mittwoch, 9. September 2015, 09:15:20 schrieb Tadeusz Struk:

Hi Tadeusz,

>Setkey function has been split into set_priv_key and set_pub_key.
>Akcipher requests takes sgl for src and dst instead of void *.
>Users of the API need to be disabled so that the build works fine
>after this patch.
>They will be enabled in subsequent patches.
>
>Signed-off-by: Tadeusz Struk <[email protected]>
>---
> crypto/Makefile | 5 --
> crypto/testmgr.c | 4 +
> drivers/crypto/qat/qat_common/Makefile | 2 -
> include/crypto/akcipher.h | 99
>++++++++++++++++++++++---------- 4 files changed, 71 insertions(+), 39
>deletions(-)
>
>diff --git a/crypto/Makefile b/crypto/Makefile
>index e2c5981..65e91da 100644
>--- a/crypto/Makefile
>+++ b/crypto/Makefile
>@@ -34,11 +34,6 @@ obj-$(CONFIG_CRYPTO_AKCIPHER2) += akcipher.o
> $(obj)/rsakey-asn1.o: $(obj)/rsakey-asn1.c $(obj)/rsakey-asn1.h
> clean-files += rsakey-asn1.c rsakey-asn1.h
>
>-rsa_generic-y := rsakey-asn1.o
>-rsa_generic-y += rsa.o
>-rsa_generic-y += rsa_helper.o
>-obj-$(CONFIG_CRYPTO_RSA) += rsa_generic.o
>-
> cryptomgr-y := algboss.o testmgr.o
>
> obj-$(CONFIG_CRYPTO_MANAGER2) += cryptomgr.o
>diff --git a/crypto/testmgr.c b/crypto/testmgr.c
>index 35c2de1..2f2b66e 100644
>--- a/crypto/testmgr.c
>+++ b/crypto/testmgr.c
>@@ -1835,6 +1835,7 @@ static int alg_test_drbg(const struct alg_test_desc
>*desc, const char *driver,
>
> }
>
>+#if 0
> static int do_test_rsa(struct crypto_akcipher *tfm,
> struct akcipher_testvec *vecs)
> {
>@@ -1975,6 +1976,7 @@ static int alg_test_akcipher(const struct alg_test_desc
>*desc, crypto_free_akcipher(tfm);
> return err;
> }
>+#endif

Just to check: is the ifdef 0 intentional?
>
> static int alg_test_null(const struct alg_test_desc *desc,
> const char *driver, u32 type, u32 mask)
>@@ -3611,7 +3613,7 @@ static const struct alg_test_desc alg_test_descs[] = {
> }
> }, {
> .alg = "rsa",
>- .test = alg_test_akcipher,
>+ .test = alg_test_null,
> .fips_allowed = 1,
> .suite = {
> .akcipher = {
>diff --git a/drivers/crypto/qat/qat_common/Makefile
>b/drivers/crypto/qat/qat_common/Makefile index df20a9d..ba5abdb 100644
>--- a/drivers/crypto/qat/qat_common/Makefile
>+++ b/drivers/crypto/qat/qat_common/Makefile
>@@ -13,8 +13,6 @@ intel_qat-objs := adf_cfg.o \
> adf_hw_arbiter.o \
> qat_crypto.o \
> qat_algs.o \
>- qat_rsakey-asn1.o \
>- qat_asym_algs.o \
> qat_uclo.o \
> qat_hal.o
>
>diff --git a/include/crypto/akcipher.h b/include/crypto/akcipher.h
>index 69d163e..7380e25 100644
>--- a/include/crypto/akcipher.h
>+++ b/include/crypto/akcipher.h
>@@ -13,28 +13,25 @@
> #ifndef _CRYPTO_AKCIPHER_H
> #define _CRYPTO_AKCIPHER_H
> #include <linux/crypto.h>
>+#include <linux/scatterlist.h>
>
> /**
> * struct akcipher_request - public key request
> *
> * @base: Common attributes for async crypto requests
>- * @src: Pointer to memory containing the input parameters
>- * The format of the parameter(s) is expeted to be Octet String
>- * @dst: Pointer to memory whare the result will be stored
>- * @src_len: Size of the input parameter
>- * @dst_len: Size of the output buffer. It needs to be at leaset
>- * as big as the expected result depending on the operation
>- * After operation it will be updated with the acctual size of
the
>- * result. In case of error, where the dst_len was insufficient,
>+ * @src: Source data
>+ * @dst: Destination data
>+ * @out_len: Size of the result. After operation it will be updated with
>+ * the acctual size of the data stored in the dst.
>+ * In case of error, where the dst sgl size was insufficient,
> * it will be updated to the size required for the operation.
> * @__ctx: Start of private context data
> */
> struct akcipher_request {
> struct crypto_async_request base;
>- void *src;
>- void *dst;
>- unsigned int src_len;
>- unsigned int dst_len;
>+ struct scatterlist *src;
>+ struct scatterlist *dst;
>+ unsigned int out_len;
> void *__ctx[] CRYPTO_MINALIGN_ATTR;
> };
>
>@@ -67,8 +64,13 @@ struct crypto_akcipher {
> * algorithm. In case of error, where the dst_len was
insufficient,
> * the req->dst_len will be updated to the size required for the
> * operation
>- * @setkey: Function invokes the algorithm specific set key function,
which
>- * knows how to decode and interpret the BER encoded key
>+ * @set_pub_key: Function invokes the algorithm specific set public key
>+ * function, which knows how to decode and interpret
>+ * the BER encoded public key
>+ * @set_priv_key: Function invokes the algorithm specific set private key
>+ * function, which knows how to decode and interpret
>+ * the BER encoded private key
>+ * @get_len: Function returns minimum dest buffer size for a given key.
> * @init: Initialize the cryptographic transformation object.
> * This function is used to initialize the cryptographic
> * transformation object. This function is called only once at
>@@ -89,8 +91,11 @@ struct akcipher_alg {
> int (*verify)(struct akcipher_request *req);
> int (*encrypt)(struct akcipher_request *req);
> int (*decrypt)(struct akcipher_request *req);
>- int (*setkey)(struct crypto_akcipher *tfm, const void *key,
>- unsigned int keylen);
>+ int (*set_pub_key)(struct crypto_akcipher *tfm, const void *key,
>+ unsigned int keylen);
>+ int (*set_priv_key)(struct crypto_akcipher *tfm, const void *key,
>+ unsigned int keylen);
>+ int (*get_len)(struct crypto_akcipher *tfm);
> int (*init)(struct crypto_akcipher *tfm);
> void (*exit)(struct crypto_akcipher *tfm);
>
>@@ -229,21 +234,31 @@ static inline void akcipher_request_set_callback(struct
>akcipher_request *req, * Sets parameters required by crypto operation
> *
> * @req: public key request
>- * @src: ptr to input parameter
>- * @dst: ptr of output parameter
>- * @src_len: size of the input buffer
>- * @dst_len: size of the output buffer. It will be updated by the
>- * implementation to reflect the acctual size of the result
>+ * @src: ptr to input scatter list
>+ * @dst: ptr to output scatter list
> */
> static inline void akcipher_request_set_crypt(struct akcipher_request *req,
>- void *src, void *dst,
>- unsigned int src_len,
>- unsigned int dst_len)
>+ struct scatterlist *src,
>+ struct scatterlist *dst)
> {
> req->src = src;
> req->dst = dst;
>- req->src_len = src_len;
>- req->dst_len = dst_len;
>+}
>+
>+/**
>+ * crypto_akcipher_get_len() -- Get minimum len for output buffer
>+ *
>+ * Function returns minimum dest buffer size for a given key
>+ *
>+ * @tfm: AKCIPHER tfm handle allocated with crypto_alloc_akcipher()
>+ *
>+ * Return: minimum len for output buffer or error code in key hasn't been
>set + */
>+static inline int crypto_akcipher_get_len(struct crypto_akcipher *tfm)
>+{
>+ struct akcipher_alg *alg = crypto_akcipher_alg(tfm);
>+
>+ return alg->get_len(tfm);
> }
>
> /**
>@@ -319,22 +334,44 @@ static inline int crypto_akcipher_verify(struct
>akcipher_request *req) }
>
> /**
>- * crypto_akcipher_setkey() -- Invoke public key setkey operation
>+ * crypto_akcipher_set_pub_key() -- Invoke set public key operation
>+ *
>+ * Function invokes the algorithm specific set key function, which knows
>+ * how to decode and interpret the encoded key
>+ *
>+ * @tfm: tfm handle
>+ * @key: BER encoded public key

DER encoded?

>+ * @keylen: length of the key
>+ *
>+ * Return: zero on success; error code in case of error
>+ */
>+static inline int crypto_akcipher_set_pub_key(struct crypto_akcipher *tfm,
>+ const void *key,
>+ unsigned int keylen)
>+{
>+ struct akcipher_alg *alg = crypto_akcipher_alg(tfm);
>+
>+ return alg->set_pub_key(tfm, key, keylen);
>+}
>+
>+/**
>+ * crypto_akcipher_set_priv_key() -- Invoke set private key operation
> *
> * Function invokes the algorithm specific set key function, which knows
> * how to decode and interpret the encoded key
> *
> * @tfm: tfm handle
>- * @key: BER encoded private or public key
>+ * @key: BER encoded private key

DER encoded?

> * @keylen: length of the key
> *
> * Return: zero on success; error code in case of error
> */
>-static inline int crypto_akcipher_setkey(struct crypto_akcipher *tfm, void
>*key, - unsigned int keylen)
>+static inline int crypto_akcipher_set_priv_key(struct crypto_akcipher *tfm,
>+ const void *key,
>+ unsigned int keylen)
> {
> struct akcipher_alg *alg = crypto_akcipher_alg(tfm);
>
>- return alg->setkey(tfm, key, keylen);
>+ return alg->set_priv_key(tfm, key, keylen);
> }
> #endif
>
>--
>To unsubscribe from this list: send the line "unsubscribe linux-crypto" in
>the body of a message to [email protected]
>More majordomo info at http://vger.kernel.org/majordomo-info.html


Ciao
Stephan

2015-09-09 16:27:11

by Stephan Müller

[permalink] [raw]
Subject: Re: [PATCH 5/8] lib/scatterlist: Add sg_len helper

Am Mittwoch, 9. September 2015, 09:15:26 schrieb Tadeusz Struk:

Hi Tadeusz,

>Add sg_len function which returns the total number of bytes in sg.
>
>Signed-off-by: Tadeusz Struk <[email protected]>
>---
> include/linux/scatterlist.h | 1 +
> lib/scatterlist.c | 18 ++++++++++++++++++
> 2 files changed, 19 insertions(+)
>
>diff --git a/include/linux/scatterlist.h b/include/linux/scatterlist.h
>index 9b1ef0c..7c82fc1 100644
>--- a/include/linux/scatterlist.h
>+++ b/include/linux/scatterlist.h
>@@ -246,6 +246,7 @@ static inline void *sg_virt(struct scatterlist *sg)
> }
>
> int sg_nents(struct scatterlist *sg);
>+int sg_len(struct scatterlist *sg);
> int sg_nents_for_len(struct scatterlist *sg, u64 len);
> struct scatterlist *sg_next(struct scatterlist *);
> struct scatterlist *sg_last(struct scatterlist *s, unsigned int);
>diff --git a/lib/scatterlist.c b/lib/scatterlist.c
>index d105a9f..71324bb 100644
>--- a/lib/scatterlist.c
>+++ b/lib/scatterlist.c
>@@ -57,6 +57,24 @@ int sg_nents(struct scatterlist *sg)
> EXPORT_SYMBOL(sg_nents);
>
> /**
>+ * sg_len - return total size of bytes in the scatterlist
>+ * @sg: The scatterlist
>+ *
>+ * Description:
>+ * Allows to know how the total size of bytes in sg, taking into acount
>+ * chaining as well
>+ **/
>+int sg_len(struct scatterlist *sg)

unsigned int?
>+{
>+ int len;
>+
>+ for (len = 0; sg; sg = sg_next(sg))
>+ len += sg->length;
>+ return len;
>+}
>+EXPORT_SYMBOL(sg_len);
>+
>+/**
> * sg_nents_for_len - return total count of entries in scatterlist
> * needed to satisfy the supplied length
> * @sg: The scatterlist
>
>--
>To unsubscribe from this list: send the line "unsubscribe linux-crypto" in
>the body of a message to [email protected]
>More majordomo info at http://vger.kernel.org/majordomo-info.html


Ciao
Stephan

2015-09-09 16:31:24

by Tadeusz Struk

[permalink] [raw]
Subject: Re: [PATCH 4/8] crypto: akcipher - Changes to asymmetric key API

Hi Stephan,
On 09/09/2015 09:25 AM, Stephan Mueller wrote:
>> >+#if 0
>> > static int do_test_rsa(struct crypto_akcipher *tfm,
>> > struct akcipher_testvec *vecs)
>> > {
>> >@@ -1975,6 +1976,7 @@ static int alg_test_akcipher(const struct alg_test_desc
>> >*desc, crypto_free_akcipher(tfm);
>> > return err;
>> > }
>> >+#endif
> Just to check: is the ifdef 0 intentional?

Yes, it is otherwise it will break the build. It is enabled in subsequent patch.

>> + * @key: BER encoded public key
> DER encoded?
>

It is BER (Basic Encoding Rules), which is also valid DER (Distinguished Encoding Rules)

Regards
T

2015-09-09 16:32:41

by Tadeusz Struk

[permalink] [raw]
Subject: Re: [PATCH 5/8] lib/scatterlist: Add sg_len helper

On 09/09/2015 09:27 AM, Stephan Mueller wrote:
>> +int sg_len(struct scatterlist *sg)
> unsigned int?

No, because it can return -EINVAL if you call it before you set the key.

2015-09-09 16:36:00

by Stephan Müller

[permalink] [raw]
Subject: Re: [PATCH 6/8] crypto: rsa - update accoring to akcipher API changes

Am Mittwoch, 9. September 2015, 09:15:32 schrieb Tadeusz Struk:

Hi Tadeusz,

>Rsa updates to reflect the API changes.
>
>Signed-off-by: Tadeusz Struk <[email protected]>
>---
> crypto/Makefile | 12 ++-
> crypto/rsa.c | 188
>++++++++++++++++++++++++++++++++++------- crypto/rsa_helper.c |
>42 ++++++++-
> crypto/rsakey.asn1 | 5 -
> crypto/rsaprivkey.asn1 | 11 ++
> crypto/rsapubkey.asn1 | 4 +
> include/crypto/internal/rsa.h | 7 +-
> 7 files changed, 220 insertions(+), 49 deletions(-)
> delete mode 100644 crypto/rsakey.asn1
> create mode 100644 crypto/rsaprivkey.asn1
> create mode 100644 crypto/rsapubkey.asn1
>
>diff --git a/crypto/Makefile b/crypto/Makefile
>index 65e91da..d897e0b 100644
>--- a/crypto/Makefile
>+++ b/crypto/Makefile
>@@ -31,8 +31,16 @@ obj-$(CONFIG_CRYPTO_HASH2) += crypto_hash.o
> obj-$(CONFIG_CRYPTO_PCOMP2) += pcompress.o
> obj-$(CONFIG_CRYPTO_AKCIPHER2) += akcipher.o
>
>-$(obj)/rsakey-asn1.o: $(obj)/rsakey-asn1.c $(obj)/rsakey-asn1.h
>-clean-files += rsakey-asn1.c rsakey-asn1.h
>+$(obj)/rsapubkey-asn1.o: $(obj)/rsapubkey-asn1.c $(obj)/rsapubkey-asn1.h
>+$(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
>+rsa_generic-y += rsa.o
>+rsa_generic-y += rsa_helper.o
>+obj-$(CONFIG_CRYPTO_RSA) += rsa_generic.o
>
> cryptomgr-y := algboss.o testmgr.o
>
>diff --git a/crypto/rsa.c b/crypto/rsa.c
>index 93feae2..f5b956c 100644
>--- a/crypto/rsa.c
>+++ b/crypto/rsa.c
>@@ -13,6 +13,7 @@
> #include <crypto/internal/rsa.h>
> #include <crypto/internal/akcipher.h>
> #include <crypto/akcipher.h>
>+#include <crypto/scatterwalk.h>
>
> /*
> * RSAEP function [RFC3447 sec 5.1.1]
>@@ -80,34 +81,57 @@ 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);
> MPI m, c = mpi_alloc(0);
>+ int src_len = sg_len(req->src), dst_len = sg_len(req->dst);

unsigned int?

> int ret = 0;
> int sign;
>
> if (!c)
> return -ENOMEM;
>
>- if (unlikely(!pkey->n || !pkey->e)) {
>+ if (unlikely(!pkey->n || !pkey->e || !src_len)) {
> ret = -EINVAL;
> goto err_free_c;
> }
>
>- if (req->dst_len < mpi_get_size(pkey->n)) {
>- req->dst_len = mpi_get_size(pkey->n);
>+ if (dst_len < mpi_get_size(pkey->n)) {
>+ req->out_len = mpi_get_size(pkey->n);
> ret = -EOVERFLOW;
> goto err_free_c;
> }
>
>- m = mpi_read_raw_data(req->src, req->src_len);
>- if (!m) {
>- ret = -ENOMEM;
>- goto err_free_c;
>+ ret = -ENOMEM;
>+ if (sg_is_last(req->src)) {
>+ m = mpi_read_raw_data(sg_virt(req->src), src_len);
>+ } else {
>+ void *ptr = kmalloc(src_len, GFP_KERNEL);
>+
>+ if (!ptr)
>+ goto err_free_c;
>+
>+ scatterwalk_map_and_copy(ptr, req->src, 0, src_len, 0);
>+ m = mpi_read_raw_data(ptr, src_len);
>+ kfree(ptr);
> }
>+ if (!m)
>+ goto err_free_c;
>
> ret = _rsa_enc(pkey, c, m);
> if (ret)
> goto err_free_m;
>
>- ret = mpi_read_buffer(c, req->dst, req->dst_len, &req->dst_len,
&sign);
>+ if (sg_is_last(req->dst)) {
>+ ret = mpi_read_buffer(c, sg_virt(req->dst), dst_len,
>+ &req->out_len, &sign);
>+ } else {
>+ void *ptr = kmalloc(dst_len, GFP_KERNEL);
>+
>+ if (!ptr)
>+ goto err_free_m;
>+
>+ ret = mpi_read_buffer(c, ptr, dst_len, &req->out_len, &sign);
>+ scatterwalk_map_and_copy(ptr, req->dst, 0, dst_len, 1);
>+ kfree(ptr);

Just a question: this code is present 4 times, can that be put into a separate
inline?

>+ }
> if (ret)
> goto err_free_m;
>
>@@ -128,34 +152,57 @@ 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);
> MPI c, m = mpi_alloc(0);
>+ int src_len = sg_len(req->src), dst_len = sg_len(req->dst);

unsigned int?

> int ret = 0;
> int sign;
>
> if (!m)
> return -ENOMEM;
>
>- if (unlikely(!pkey->n || !pkey->d)) {
>+ if (unlikely(!pkey->n || !pkey->d || !src_len)) {
> ret = -EINVAL;
> goto err_free_m;
> }
>
>- if (req->dst_len < mpi_get_size(pkey->n)) {
>- req->dst_len = mpi_get_size(pkey->n);
>+ if (dst_len < mpi_get_size(pkey->n)) {
>+ req->out_len = mpi_get_size(pkey->n);
> ret = -EOVERFLOW;
> goto err_free_m;
> }
>
>- c = mpi_read_raw_data(req->src, req->src_len);
>- if (!c) {
>- ret = -ENOMEM;
>- goto err_free_m;
>+ ret = -ENOMEM;
>+ if (sg_is_last(req->src)) {
>+ c = mpi_read_raw_data(sg_virt(req->src), src_len);
>+ } else {
>+ void *ptr = kmalloc(src_len, GFP_KERNEL);
>+
>+ if (!ptr)
>+ goto err_free_m;
>+
>+ scatterwalk_map_and_copy(ptr, req->src, 0, src_len, 0);
>+ c = mpi_read_raw_data(ptr, src_len);
>+ kfree(ptr);
> }
>+ if (!c)
>+ goto err_free_m;
>
> ret = _rsa_dec(pkey, m, c);
> if (ret)
> goto err_free_c;
>
>- ret = mpi_read_buffer(m, req->dst, req->dst_len, &req->dst_len,
&sign);
>+ if (sg_is_last(req->dst)) {
>+ ret = mpi_read_buffer(m, sg_virt(req->dst), dst_len,
>+ &req->out_len, &sign);
>+ } else {
>+ void *ptr = kmalloc(dst_len, GFP_KERNEL);
>+
>+ if (!ptr)
>+ goto err_free_c;
>+
>+ ret = mpi_read_buffer(m, ptr, dst_len, &req->out_len, &sign);
>+ scatterwalk_map_and_copy(ptr, req->dst, 0, dst_len, 1);
>+ kfree(ptr);
>+ }
> if (ret)
> goto err_free_c;
>
>@@ -176,34 +223,58 @@ 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);
> MPI m, s = mpi_alloc(0);
>+ int src_len = sg_len(req->src), dst_len = sg_len(req->dst);

unsigned int?

> int ret = 0;
> int sign;
>
> if (!s)
> return -ENOMEM;
>
>- if (unlikely(!pkey->n || !pkey->d)) {
>+ if (unlikely(!pkey->n || !pkey->d || !src_len)) {
> ret = -EINVAL;
> goto err_free_s;
> }
>
>- if (req->dst_len < mpi_get_size(pkey->n)) {
>- req->dst_len = mpi_get_size(pkey->n);
>+ if (dst_len < mpi_get_size(pkey->n)) {
>+ req->out_len = mpi_get_size(pkey->n);
> ret = -EOVERFLOW;
> goto err_free_s;
> }
>
>- m = mpi_read_raw_data(req->src, req->src_len);
>- if (!m) {
>- ret = -ENOMEM;
>- goto err_free_s;
>+ ret = -ENOMEM;
>+ if (sg_is_last(req->src)) {
>+ m = mpi_read_raw_data(sg_virt(req->src), src_len);
>+ } else {
>+ void *ptr = kmalloc(src_len, GFP_KERNEL);
>+
>+ if (!ptr)
>+ goto err_free_s;
>+
>+ scatterwalk_map_and_copy(ptr, req->src, 0, src_len, 0);
>+ m = mpi_read_raw_data(ptr, src_len);
>+ kfree(ptr);
>+
> }
>+ if (!m)
>+ goto err_free_s;
>
> ret = _rsa_sign(pkey, s, m);
> if (ret)
> goto err_free_m;
>
>- ret = mpi_read_buffer(s, req->dst, req->dst_len, &req->dst_len,
&sign);
>+ if (sg_is_last(req->dst)) {
>+ ret = mpi_read_buffer(s, sg_virt(req->dst), dst_len,
>+ &req->out_len, &sign);
>+ } else {
>+ void *ptr = kmalloc(dst_len, GFP_KERNEL);
>+
>+ if (!ptr)
>+ goto err_free_m;
>+
>+ ret = mpi_read_buffer(s, ptr, dst_len, &req->out_len, &sign);
>+ scatterwalk_map_and_copy(ptr, req->dst, 0, dst_len, 1);
>+ kfree(ptr);
>+ }
> if (ret)
> goto err_free_m;
>
>@@ -224,24 +295,37 @@ 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);
> MPI s, m = mpi_alloc(0);
>+ int src_len = sg_len(req->src), dst_len = sg_len(req->dst);

unsigned int?

> int ret = 0;
> int sign;
>
> if (!m)
> return -ENOMEM;
>
>- if (unlikely(!pkey->n || !pkey->e)) {
>+ if (unlikely(!pkey->n || !pkey->e || !src_len)) {
> ret = -EINVAL;
> goto err_free_m;
> }
>
>- if (req->dst_len < mpi_get_size(pkey->n)) {
>- req->dst_len = mpi_get_size(pkey->n);
>+ if (dst_len < mpi_get_size(pkey->n)) {
>+ req->out_len = mpi_get_size(pkey->n);
> ret = -EOVERFLOW;
> goto err_free_m;
> }
>
>- s = mpi_read_raw_data(req->src, req->src_len);
>+ ret = -ENOMEM;
>+ if (sg_is_last(req->src)) {
>+ s = mpi_read_raw_data(sg_virt(req->src), src_len);
>+ } else {
>+ void *ptr = kmalloc(src_len, GFP_KERNEL);
>+
>+ if (!ptr)
>+ goto err_free_m;
>+
>+ scatterwalk_map_and_copy(ptr, req->src, 0, src_len, 0);
>+ s = mpi_read_raw_data(ptr, src_len);
>+ kfree(ptr);
>+ }
> if (!s) {
> ret = -ENOMEM;
> goto err_free_m;
>@@ -251,7 +335,19 @@ static int rsa_verify(struct akcipher_request *req)
> if (ret)
> goto err_free_s;
>
>- ret = mpi_read_buffer(m, req->dst, req->dst_len, &req->dst_len,
&sign);
>+ if (sg_is_last(req->dst)) {
>+ ret = mpi_read_buffer(m, sg_virt(req->dst), dst_len,
>+ &req->out_len, &sign);
>+ } else {
>+ void *ptr = kmalloc(dst_len, GFP_KERNEL);
>+
>+ if (!ptr)
>+ goto err_free_s;
>+
>+ ret = mpi_read_buffer(m, ptr, dst_len, &req->out_len, &sign);
>+ scatterwalk_map_and_copy(ptr, req->dst, 0, dst_len, 1);
>+ kfree(ptr);
>+ }
> if (ret)
> goto err_free_s;
>
>@@ -282,13 +378,30 @@ static int rsa_check_key_length(unsigned int len)
> return -EINVAL;
> }
>
>-static int rsa_setkey(struct crypto_akcipher *tfm, const void *key,
>- unsigned int keylen)
>+static int rsa_set_pub_key(struct crypto_akcipher *tfm, const void *key,
>+ unsigned int keylen)
>+{
>+ struct rsa_key *pkey = akcipher_tfm_ctx(tfm);
>+ int ret;
>+
>+ ret = rsa_parse_pub_key(pkey, key, keylen);
>+ if (ret)
>+ return ret;
>+
>+ if (rsa_check_key_length(mpi_get_size(pkey->n) << 3)) {
>+ rsa_free_key(pkey);
>+ ret = -EINVAL;
>+ }
>+ return ret;
>+}
>+
>+static int rsa_set_priv_key(struct crypto_akcipher *tfm, const void *key,
>+ unsigned int keylen)
> {
> struct rsa_key *pkey = akcipher_tfm_ctx(tfm);
> int ret;
>
>- ret = rsa_parse_key(pkey, key, keylen);
>+ ret = rsa_parse_priv_key(pkey, key, keylen);
> if (ret)
> return ret;
>
>@@ -299,6 +412,13 @@ static int rsa_setkey(struct crypto_akcipher *tfm, const
>void *key, return ret;
> }
>
>+static int rsa_get_len(struct crypto_akcipher *tfm)
>+{
>+ struct rsa_key *pkey = akcipher_tfm_ctx(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);
>@@ -311,7 +431,9 @@ static struct akcipher_alg rsa = {
> .decrypt = rsa_dec,
> .sign = rsa_sign,
> .verify = rsa_verify,
>- .setkey = rsa_setkey,
>+ .set_priv_key = rsa_set_priv_key,
>+ .set_pub_key = rsa_set_pub_key,
>+ .get_len = rsa_get_len,
> .exit = rsa_exit_tfm,
> .base = {
> .cra_name = "rsa",
>diff --git a/crypto/rsa_helper.c b/crypto/rsa_helper.c
>index 8d96ce9..d226f48 100644
>--- a/crypto/rsa_helper.c
>+++ b/crypto/rsa_helper.c
>@@ -15,7 +15,8 @@
> #include <linux/err.h>
> #include <linux/fips.h>
> #include <crypto/internal/rsa.h>
>-#include "rsakey-asn1.h"
>+#include "rsapubkey-asn1.h"
>+#include "rsaprivkey-asn1.h"
>
> int rsa_get_n(void *context, size_t hdrlen, unsigned char tag,
> const void *value, size_t vlen)
>@@ -94,8 +95,8 @@ void rsa_free_key(struct rsa_key *key)
> EXPORT_SYMBOL_GPL(rsa_free_key);
>
> /**
>- * rsa_parse_key() - extracts an rsa key from BER encoded buffer
>- * and stores it in the provided struct rsa_key
>+ * rsa_parse_pub_key() - extracts an rsa public key from BER encoded buffer
>+ * and stores it in the provided struct rsa_key
> *
> * @rsa_key: struct rsa_key key representation
> * @key: key in BER format
>@@ -103,13 +104,13 @@ EXPORT_SYMBOL_GPL(rsa_free_key);
> *
> * Return: 0 on success or error code in case of error
> */
>-int rsa_parse_key(struct rsa_key *rsa_key, const void *key,
>- unsigned int key_len)
>+int rsa_parse_pub_key(struct rsa_key *rsa_key, const void *key,
>+ unsigned int key_len)
> {
> int ret;
>
> free_mpis(rsa_key);
>- ret = asn1_ber_decoder(&rsakey_decoder, rsa_key, key, key_len);
>+ ret = asn1_ber_decoder(&rsapubkey_decoder, rsa_key, key, key_len);
> if (ret < 0)
> goto error;
>
>@@ -118,4 +119,31 @@ error:
> free_mpis(rsa_key);
> return ret;
> }
>-EXPORT_SYMBOL_GPL(rsa_parse_key);
>+EXPORT_SYMBOL_GPL(rsa_parse_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_*priv*_key

>+ *
>+ * @rsa_key: struct rsa_key key representation
>+ * @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 ret;
>+
>+ free_mpis(rsa_key);
>+ ret = asn1_ber_decoder(&rsaprivkey_decoder, rsa_key, key, key_len);
>+ if (ret < 0)
>+ goto error;
>+
>+ return 0;
>+error:
>+ free_mpis(rsa_key);
>+ return ret;
>+}
>+EXPORT_SYMBOL_GPL(rsa_parse_priv_key);
>diff --git a/crypto/rsakey.asn1 b/crypto/rsakey.asn1
>deleted file mode 100644
>index 3c7b5df..0000000
>--- a/crypto/rsakey.asn1
>+++ /dev/null
>@@ -1,5 +0,0 @@
>-RsaKey ::= SEQUENCE {
>- n INTEGER ({ rsa_get_n }),
>- e INTEGER ({ rsa_get_e }),
>- d INTEGER ({ rsa_get_d })
>-}
>diff --git a/crypto/rsaprivkey.asn1 b/crypto/rsaprivkey.asn1
>new file mode 100644
>index 0000000..731aea5
>--- /dev/null
>+++ b/crypto/rsaprivkey.asn1
>@@ -0,0 +1,11 @@
>+RsaPrivKey ::= SEQUENCE {
>+ version INTEGER,
>+ n INTEGER ({ rsa_get_n }),
>+ e INTEGER ({ rsa_get_e }),
>+ d INTEGER ({ rsa_get_d }),
>+ prime1 INTEGER,
>+ prime2 INTEGER,
>+ exponent1 INTEGER,
>+ exponent2 INTEGER,
>+ coefficient INTEGER
>+}
>diff --git a/crypto/rsapubkey.asn1 b/crypto/rsapubkey.asn1
>new file mode 100644
>index 0000000..725498e
>--- /dev/null
>+++ b/crypto/rsapubkey.asn1
>@@ -0,0 +1,4 @@
>+RsaPubKey ::= SEQUENCE {
>+ n INTEGER ({ rsa_get_n }),
>+ e INTEGER ({ rsa_get_e })
>+}
>diff --git a/include/crypto/internal/rsa.h b/include/crypto/internal/rsa.h
>index a8c8636..f997e2d 100644
>--- a/include/crypto/internal/rsa.h
>+++ b/include/crypto/internal/rsa.h
>@@ -20,8 +20,11 @@ struct rsa_key {
> MPI d;
> };
>
>-int rsa_parse_key(struct rsa_key *rsa_key, const void *key,
>- unsigned int key_len);
>+int rsa_parse_pub_key(struct rsa_key *rsa_key, const void *key,
>+ unsigned int key_len);
>+
>+int rsa_parse_priv_key(struct rsa_key *rsa_key, const void *key,
>+ unsigned int key_len);
>
> void rsa_free_key(struct rsa_key *rsa_key);
> #endif
>
>--
>To unsubscribe from this list: send the line "unsubscribe linux-crypto" in
>the body of a message to [email protected]
>More majordomo info at http://vger.kernel.org/majordomo-info.html


Ciao
Stephan

2015-09-09 16:39:17

by Stephan Müller

[permalink] [raw]
Subject: Re: [PATCH 5/8] lib/scatterlist: Add sg_len helper

Am Mittwoch, 9. September 2015, 09:31:00 schrieb Tadeusz Struk:

Hi Tadeusz,

>On 09/09/2015 09:27 AM, Stephan Mueller wrote:
>>> +int sg_len(struct scatterlist *sg)
>>
>> unsigned int?
>
>No, because it can return -EINVAL if you call it before you set the key.

I see.

But, shouldn't there be an overflow check? Maybe not here, but in the cases
where the function is invoked. There is a kmalloc(src_len) without a check for
negative values.


Ciao
Stephan

2015-09-09 16:41:31

by Stephan Müller

[permalink] [raw]
Subject: Re: [PATCH 4/8] crypto: akcipher - Changes to asymmetric key API

Am Mittwoch, 9. September 2015, 09:29:28 schrieb Tadeusz Struk:

Hi Tadeusz,

>>> + * @key: BER encoded public key
>>
>> DER encoded?
>
>It is BER (Basic Encoding Rules), which is also valid DER (Distinguished
>Encoding Rules)

I was just mentioning that since the ASN.1 structure now is equivalent to
OpenSSL and what DER specifies. I just wanted to suggest to allow readers to
establish a connection between OpenSSL DER encoded keys and the keys we use
here.


Ciao
Stephan

2015-09-09 16:46:47

by Tadeusz Struk

[permalink] [raw]
Subject: Re: [PATCH 4/8] crypto: akcipher - Changes to asymmetric key API

On 09/09/2015 09:41 AM, Stephan Mueller wrote:
>> >It is BER (Basic Encoding Rules), which is also valid DER (Distinguished
>> >Encoding Rules)
> I was just mentioning that since the ASN.1 structure now is equivalent to
> OpenSSL and what DER specifies. I just wanted to suggest to allow readers to
> establish a connection between OpenSSL DER encoded keys and the keys we use

Since DER is a valid BER it will work for both.

2015-09-09 16:48:18

by Tadeusz Struk

[permalink] [raw]
Subject: Re: [PATCH 5/8] lib/scatterlist: Add sg_len helper

On 09/09/2015 09:39 AM, Stephan Mueller wrote:
>> No, because it can return -EINVAL if you call it before you set the key.
> I see.
>
> But, shouldn't there be an overflow check? Maybe not here, but in the cases
> where the function is invoked. There is a kmalloc(src_len) without a check for
> negative values.

Right, but because testmgr.c calls setkey before this I skipped the check.

2015-09-09 16:49:47

by Stephan Müller

[permalink] [raw]
Subject: Re: [PATCH 5/8] lib/scatterlist: Add sg_len helper

Am Mittwoch, 9. September 2015, 09:46:36 schrieb Tadeusz Struk:

Hi Tadeusz,

>On 09/09/2015 09:39 AM, Stephan Mueller wrote:
>>> No, because it can return -EINVAL if you call it before you set the key.
>>
>> I see.
>>
>> But, shouldn't there be an overflow check? Maybe not here, but in the cases
>> where the function is invoked. There is a kmalloc(src_len) without a check
>> for negative values.
>
>Right, but because testmgr.c calls setkey before this I skipped the check.

But in the rsa.c enc/dec/verify/sign functions, there should be such check, I
would guess.


Ciao
Stephan

2015-09-09 16:53:21

by Tadeusz Struk

[permalink] [raw]
Subject: Re: [PATCH 5/8] lib/scatterlist: Add sg_len helper

On 09/09/2015 09:49 AM, Stephan Mueller wrote:
>>> >> But, shouldn't there be an overflow check? Maybe not here, but in the cases
>>> >> where the function is invoked. There is a kmalloc(src_len) without a check
>>> >> for negative values.
>> >
>> >Right, but because testmgr.c calls setkey before this I skipped the check.
> But in the rsa.c enc/dec/verify/sign functions, there should be such check, I
> would guess.

There is see line 419:
return pkey->n ? mpi_get_size(pkey->n) : -EINVAL;

2015-09-09 16:54:35

by Stephan Müller

[permalink] [raw]
Subject: Re: [PATCH 5/8] lib/scatterlist: Add sg_len helper

Am Mittwoch, 9. September 2015, 09:31:00 schrieb Tadeusz Struk:

Hi Tadeusz,

>On 09/09/2015 09:27 AM, Stephan Mueller wrote:
>>> +int sg_len(struct scatterlist *sg)
>>
>> unsigned int?
>
>No, because it can return -EINVAL if you call it before you set the key.

Just re-reading the code: where would the -EINVAL be generated?

Ciao
Stephan

2015-09-09 16:56:36

by Stephan Müller

[permalink] [raw]
Subject: Re: [PATCH 5/8] lib/scatterlist: Add sg_len helper

Am Mittwoch, 9. September 2015, 09:51:40 schrieb Tadeusz Struk:

Hi Tadeusz,

>On 09/09/2015 09:49 AM, Stephan Mueller wrote:
>>>> >> But, shouldn't there be an overflow check? Maybe not here, but in the
>>>> >> cases
>>>> >> where the function is invoked. There is a kmalloc(src_len) without a
>>>> >> check
>>>> >> for negative values.
>>> >
>>> >Right, but because testmgr.c calls setkey before this I skipped the
>>> >check.
>>
>> But in the rsa.c enc/dec/verify/sign functions, there should be such check,
>> I would guess.
>
>There is see line 419:
>return pkey->n ? mpi_get_size(pkey->n) : -EINVAL;

I feel we are not talking about the same issue. I refer to your patch in
rsa.c:

+ int src_len = sg_len(req->src), dst_len = sg_len(req->dst);

===> can be negative according to your statement

...

+ void *ptr = kmalloc(dst_len, GFP_KERNEL);

===> with a negative number, I guess we have a problem here.


Ciao
Stephan

2015-09-09 17:04:56

by Tadeusz Struk

[permalink] [raw]
Subject: Re: [PATCH 5/8] lib/scatterlist: Add sg_len helper

On 09/09/2015 09:56 AM, Stephan Mueller wrote:
>>> But in the rsa.c enc/dec/verify/sign functions, there should be such check,
>>> >> I would guess.
>> >
>> >There is see line 419:
>> >return pkey->n ? mpi_get_size(pkey->n) : -EINVAL;
> I feel we are not talking about the same issue. I refer to your patch in
> rsa.c:
>
> + int src_len = sg_len(req->src), dst_len = sg_len(req->dst);
>
> ===> can be negative according to your statement
>
> ...
>
> + void *ptr = kmalloc(dst_len, GFP_KERNEL);
>
> ===> with a negative number, I guess we have a problem here.

Yes, sorry, you are right. sg_len() will only return positive numbers or zero.
rsa.c checks it in all four operations:
if (unlikely(!pkey->n || !pkey->d || !src_len))

2015-09-09 17:06:05

by Stephan Müller

[permalink] [raw]
Subject: Re: [PATCH 5/8] lib/scatterlist: Add sg_len helper

Am Mittwoch, 9. September 2015, 10:02:17 schrieb Tadeusz Struk:

Hi Tadeusz,

>On 09/09/2015 09:56 AM, Stephan Mueller wrote:
>>>> But in the rsa.c enc/dec/verify/sign functions, there should be such
>>>> check,
>>>>
>>>> >> I would guess.
>>> >
>>> >There is see line 419:
>>> >return pkey->n ? mpi_get_size(pkey->n) : -EINVAL;
>>
>> I feel we are not talking about the same issue. I refer to your patch in
>> rsa.c:
>>
>> + int src_len = sg_len(req->src), dst_len = sg_len(req->dst);
>>
>> ===> can be negative according to your statement
>>
>> ...
>>
>> + void *ptr = kmalloc(dst_len, GFP_KERNEL);
>>
>> ===> with a negative number, I guess we have a problem here.
>
>Yes, sorry, you are right. sg_len() will only return positive numbers or
>zero. rsa.c checks it in all four operations:
>if (unlikely(!pkey->n || !pkey->d || !src_len))

Great, I am not disputing the check for 0, I just want an unsigned int,
because sg->length is unsigned int too. :-)


Ciao
Stephan

2015-09-09 17:17:59

by Tadeusz Struk

[permalink] [raw]
Subject: Re: [PATCH 5/8] lib/scatterlist: Add sg_len helper

On 09/09/2015 10:05 AM, Stephan Mueller wrote:
>> Yes, sorry, you are right. sg_len() will only return positive numbers or
>> >zero. rsa.c checks it in all four operations:
>> >if (unlikely(!pkey->n || !pkey->d || !src_len))
> Great, I am not disputing the check for 0, I just want an unsigned int,
> because sg->length is unsigned int too. :-)

I see, maybe we can check for negative numbers in PF_ALG?

2015-09-09 17:37:32

by Stephan Müller

[permalink] [raw]
Subject: Re: [PATCH 5/8] lib/scatterlist: Add sg_len helper

Am Mittwoch, 9. September 2015, 10:16:16 schrieb Tadeusz Struk:

Hi Tadeusz,

>On 09/09/2015 10:05 AM, Stephan Mueller wrote:
>>> Yes, sorry, you are right. sg_len() will only return positive numbers or
>>>
>>> >zero. rsa.c checks it in all four operations:
>>> >if (unlikely(!pkey->n || !pkey->d || !src_len))
>>
>> Great, I am not disputing the check for 0, I just want an unsigned int,
>> because sg->length is unsigned int too. :-)
>
>I see, maybe we can check for negative numbers in PF_ALG?

My request for turning the implementation of sg_len and the callers of it to
use unsigned int is simply to avoid overflows of the counter.

Note, I usually am very zealous about using the correct data types, especially
with integers. I have seen way to many security related bugs by overflowing a
signed integer.

Surely, PF_ALG will ensure that user space will only provide buffers up to a
max number (PAGE_SIZE * ALG_MAX_PAGES is the maximum user space can provide at
all considering my current user space approach). So, we have at most 65536
bytes from user space in one request. This boundary is to allow at most
ALG_MAX_PAGES individual SGL members (i.e. at most ALG_MAX_PAGES individual
calls to splice) but also tries to squeeze the data coming with sendmsg into
one page. But, surely we can discuss these limits once I post algif_akcipher.

Considering that, I do not feel that the code we discuss here should have a
check for the maximum size of the SGL.


Ciao
Stephan

2015-09-09 18:09:58

by Tadeusz Struk

[permalink] [raw]
Subject: Re: [PATCH 6/8] crypto: rsa - update accoring to akcipher API changes

On 09/09/2015 09:35 AM, Stephan Mueller wrote:
>> + if (sg_is_last(req->dst)) {
>> >+ ret = mpi_read_buffer(c, sg_virt(req->dst), dst_len,
>> >+ &req->out_len, &sign);
>> >+ } else {
>> >+ void *ptr = kmalloc(dst_len, GFP_KERNEL);
>> >+
>> >+ if (!ptr)
>> >+ goto err_free_m;
>> >+
>> >+ ret = mpi_read_buffer(c, ptr, dst_len, &req->out_len, &sign);
>> >+ scatterwalk_map_and_copy(ptr, req->dst, 0, dst_len, 1);
>> >+ kfree(ptr);
> Just a question: this code is present 4 times, can that be put into a separate
> inline?
>

I have put it like this because it is easier to read.
All 4 functions use different variable names according to the spec.

2015-09-09 18:53:24

by Andrew Zaborowski

[permalink] [raw]
Subject: Re: [PATCH 4/8] crypto: akcipher - Changes to asymmetric key API

Hi,

On 9 September 2015 at 18:41, Stephan Mueller <[email protected]> wrote:
> Am Mittwoch, 9. September 2015, 09:29:28 schrieb Tadeusz Struk:
>>>> + * @key: BER encoded public key
>>>
>>> DER encoded?
>>
>>It is BER (Basic Encoding Rules), which is also valid DER (Distinguished
>>Encoding Rules)
>
> I was just mentioning that since the ASN.1 structure now is equivalent to
> OpenSSL and what DER specifies. I just wanted to suggest to allow readers to
> establish a connection between OpenSSL DER encoded keys and the keys we use
> here.

Shouldn't the BER/DER requirement be only mentioned in rsa.c? For
other asymmetric key ciphers there may, in theory, be a completely
different established key encoding and no point in using DER on top.

Also a question regarding .get_len: for RSA with padding the minimum
dest buffer length depends on the input. What is that call supposed
to return in that case?

Best regards

2015-09-09 19:13:44

by Stephan Müller

[permalink] [raw]
Subject: Re: [PATCH 4/8] crypto: akcipher - Changes to asymmetric key API

Am Mittwoch, 9. September 2015, 20:53:23 schrieb Andrzej Zaborowski:

Hi Andrzej,
>
>Also a question regarding .get_len: for RSA with padding the minimum
>dest buffer length depends on the input. What is that call supposed
>to return in that case?

I would guess that the destination buffer minimum size should be RSA size
minus the minimum padding size. This way, the caller is always sure to get all
data without error.

Ciao
Stephan

2015-09-09 19:37:37

by Tadeusz Struk

[permalink] [raw]
Subject: Re: [PATCH 4/8] crypto: akcipher - Changes to asymmetric key API

On 09/09/2015 12:13 PM, Stephan Mueller wrote:
>> >Also a question regarding .get_len: for RSA with padding the minimum
>> >dest buffer length depends on the input. What is that call supposed
>> >to return in that case?
> I would guess that the destination buffer minimum size should be RSA size
> minus the minimum padding size. This way, the caller is always sure to get all
> data without error.

I think it should always be the size of modulo.

2015-09-18 11:29:38

by Herbert Xu

[permalink] [raw]
Subject: Re: [PATCH 1/8] crypto: akcipher - return status from crypto_unregister_alg

On Wed, Sep 09, 2015 at 09:15:01AM -0700, Tadeusz Struk wrote:
> Return status from crypto_unregister_alg to the caller.

Why? My plan is to turn crypto_unregister_alg into a void function.

Cheers,
--
Email: Herbert Xu <[email protected]>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

2015-09-18 11:35:15

by Herbert Xu

[permalink] [raw]
Subject: Re: [PATCH 4/8] crypto: akcipher - Changes to asymmetric key API

On Wed, Sep 09, 2015 at 09:15:20AM -0700, Tadeusz Struk wrote:
> Setkey function has been split into set_priv_key and set_pub_key.
> Akcipher requests takes sgl for src and dst instead of void *.
> Users of the API need to be disabled so that the build works fine
> after this patch.
> They will be enabled in subsequent patches.
>
> Signed-off-by: Tadeusz Struk <[email protected]>

Either do everything as a single patch (patches 4,6-8) or do it
properly by making incremental changes like what I did with AEAD
and RNG.

In this case I think a single patch is probably the best option.

Thanks,
--
Email: Herbert Xu <[email protected]>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt