* [PATCH v7 0/3] crypto: caam - add support for RSA algorithm
From: Tudor Ambarus @ 2016-06-07 14:24 UTC (permalink / raw)
To: herbert; +Cc: linux-crypto, horia.geanta, Tudor Ambarus
Depends on:
[PATCH v3] crypto: rsa - return raw integers for the ASN.1 parser
Changes in v7:
- sync with ASN.1 parser
Changes in v6:
- write descriptor PDB fields with inline append
- move Protocol Data Block (pdb) structures to pdb.h
- move setting of PDB fields in new functions
- unmap sec4_sg_dma on done callback
- remove redundant clean code on error path
- fix doc typos
Changes in v5:
- sync with ASN.1 parser
Changes in v4:
- sync with ASN.1 parser
Changes in v3:
- sync with ASN.1 parser
Changes in v2:
- fix memory leaks on error path
- rename struct akcipher_alg rsa to caam_rsa
Tudor Ambarus (3):
crypto: scatterwak - Add scatterwalk_sg_copychunks
crypto: scatterwalk - export scatterwalk_pagedone
crypto: caam - add support for RSA algorithm
crypto/scatterwalk.c | 31 +-
drivers/crypto/caam/Kconfig | 12 +
drivers/crypto/caam/Makefile | 4 +
drivers/crypto/caam/caampkc.c | 637 ++++++++++++++++++++++++++++++++++++++
drivers/crypto/caam/caampkc.h | 72 +++++
drivers/crypto/caam/compat.h | 3 +
drivers/crypto/caam/desc.h | 2 +
drivers/crypto/caam/desc_constr.h | 7 +
drivers/crypto/caam/pdb.h | 51 ++-
drivers/crypto/caam/pkc_desc.c | 36 +++
include/crypto/scatterwalk.h | 4 +
11 files changed, 856 insertions(+), 3 deletions(-)
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
--
1.8.3.1
^ permalink raw reply
* [PATCH 1/3] crypto: scatterwak - Add scatterwalk_sg_copychunks
From: Tudor Ambarus @ 2016-06-07 14:24 UTC (permalink / raw)
To: herbert; +Cc: linux-crypto, horia.geanta, Tudor Ambarus
In-Reply-To: <1465309483-2703-1-git-send-email-tudor-dan.ambarus@nxp.com>
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
for the output data of the RSA algorithm, after the computation completes.
Signed-off-by: Tudor Ambarus <tudor-dan.ambarus@nxp.com>
---
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
^ permalink raw reply related
* [PATCH 2/3] crypto: scatterwalk - export scatterwalk_pagedone
From: Tudor Ambarus @ 2016-06-07 14:24 UTC (permalink / raw)
To: herbert; +Cc: linux-crypto, horia.geanta, Tudor Ambarus
In-Reply-To: <1465309483-2703-1-git-send-email-tudor-dan.ambarus@nxp.com>
Used in caam driver. Export the symbol since the caam driver
can be built as a module.
Signed-off-by: Tudor Ambarus <tudor-dan.ambarus@nxp.com>
---
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
^ permalink raw reply related
* [PATCH 3/3] crypto: caam - add support for RSA algorithm
From: Tudor Ambarus @ 2016-06-07 14:24 UTC (permalink / raw)
To: herbert; +Cc: linux-crypto, horia.geanta, Tudor Ambarus
In-Reply-To: <1465309483-2703-1-git-send-email-tudor-dan.ambarus@nxp.com>
Add RSA support to caam driver.
Coauthored-by: Yashpal Dutta <yashpal.dutta@freescale.com>
Signed-off-by: Tudor Ambarus <tudor-dan.ambarus@nxp.com>
---
drivers/crypto/caam/Kconfig | 12 +
drivers/crypto/caam/Makefile | 4 +
drivers/crypto/caam/caampkc.c | 637 ++++++++++++++++++++++++++++++++++++++
drivers/crypto/caam/caampkc.h | 72 +++++
drivers/crypto/caam/compat.h | 3 +
drivers/crypto/caam/desc.h | 2 +
drivers/crypto/caam/desc_constr.h | 7 +
drivers/crypto/caam/pdb.h | 51 ++-
drivers/crypto/caam/pkc_desc.c | 36 +++
9 files changed, 823 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..44449ba 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
+ 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..38a004d
--- /dev/null
+++ b/drivers/crypto/caam/caampkc.c
@@ -0,0 +1,637 @@
+/*
+ * 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 "compat.h"
+#include "regs.h"
+#include "intern.h"
+#include "jr.h"
+#include "error.h"
+#include "desc_constr.h"
+#include "sg_sw_sec4.h"
+#include "caampkc.h"
+#include "rsapubkey-asn1.h"
+#include "rsaprivkey-asn1.h"
+
+#define DESC_RSA_PUB_LEN (2 * CAAM_CMD_SZ + sizeof(struct rsa_pub_pdb))
+#define DESC_RSA_PRIV_F1_LEN (2 * CAAM_CMD_SZ + \
+ sizeof(struct rsa_priv_f1_pdb))
+
+static void rsa_io_unmap(struct device *dev, struct rsa_edesc *edesc,
+ struct akcipher_request *req)
+{
+ dma_unmap_sg(dev, req->dst, edesc->dst_nents, DMA_FROM_DEVICE);
+ dma_unmap_sg(dev, req->src, edesc->src_nents, DMA_TO_DEVICE);
+
+ if (edesc->sec4_sg_bytes)
+ dma_unmap_single(dev, edesc->sec4_sg_dma, edesc->sec4_sg_bytes,
+ DMA_TO_DEVICE);
+}
+
+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 caam_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
+ struct caam_rsa_key *key = &ctx->key;
+ struct rsa_pub_pdb *pdb = &edesc->pdb.pub;
+
+ dma_unmap_single(dev, pdb->n_dma, key->n_sz, DMA_TO_DEVICE);
+ dma_unmap_single(dev, pdb->e_dma, key->e_sz, 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 caam_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
+ struct caam_rsa_key *key = &ctx->key;
+ struct rsa_priv_f1_pdb *pdb = &edesc->pdb.priv_f1;
+
+ dma_unmap_single(dev, pdb->n_dma, key->n_sz, DMA_TO_DEVICE);
+ dma_unmap_single(dev, pdb->d_dma, key->n_sz, 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);
+ rsa_io_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);
+ rsa_io_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 caam_rsa_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;
+ }
+
+ edesc->sec4_sg_bytes = sec4_sg_bytes;
+
+ 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 set_rsa_pub_pdb(struct akcipher_request *req,
+ struct rsa_edesc *edesc)
+{
+ struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
+ struct caam_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
+ struct caam_rsa_key *key = &ctx->key;
+ struct device *dev = ctx->dev;
+ struct rsa_pub_pdb *pdb = &edesc->pdb.pub;
+ int sec4_sg_index = 0;
+
+ pdb->n_dma = dma_map_single(dev, key->n, key->n_sz, DMA_TO_DEVICE);
+ if (dma_mapping_error(dev, pdb->n_dma)) {
+ dev_err(dev, "Unable to map RSA modulus memory\n");
+ return -ENOMEM;
+ }
+
+ pdb->e_dma = dma_map_single(dev, key->e, key->e_sz, DMA_TO_DEVICE);
+ if (dma_mapping_error(dev, pdb->e_dma)) {
+ dev_err(dev, "Unable to map RSA public exponent memory\n");
+ dma_unmap_single(dev, pdb->n_dma, key->n_sz, DMA_TO_DEVICE);
+ return -ENOMEM;
+ }
+
+ if (edesc->src_nents > 1) {
+ pdb->sgf |= RSA_PDB_SGF_F;
+ pdb->f_dma = edesc->sec4_sg_dma;
+ sec4_sg_index += edesc->src_nents;
+ } else {
+ pdb->f_dma = sg_dma_address(req->src);
+ }
+
+ if (edesc->dst_nents > 1) {
+ pdb->sgf |= RSA_PDB_SGF_G;
+ pdb->g_dma = edesc->sec4_sg_dma +
+ sec4_sg_index * sizeof(struct sec4_sg_entry);
+ } else {
+ pdb->g_dma = sg_dma_address(req->dst);
+ }
+
+ pdb->sgf |= (key->e_sz << RSA_PDB_E_SHIFT) | key->n_sz;
+ pdb->f_len = req->src_len;
+
+ return 0;
+}
+
+static int set_rsa_priv_f1_pdb(struct akcipher_request *req,
+ struct rsa_edesc *edesc)
+{
+ struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
+ struct caam_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
+ struct caam_rsa_key *key = &ctx->key;
+ struct device *dev = ctx->dev;
+ struct rsa_priv_f1_pdb *pdb = &edesc->pdb.priv_f1;
+ int sec4_sg_index = 0;
+
+ pdb->n_dma = dma_map_single(dev, key->n, key->n_sz, DMA_TO_DEVICE);
+ if (dma_mapping_error(dev, pdb->n_dma)) {
+ dev_err(dev, "Unable to map modulus memory\n");
+ return -ENOMEM;
+ }
+
+ pdb->d_dma = dma_map_single(dev, key->d, key->n_sz, DMA_TO_DEVICE);
+ if (dma_mapping_error(dev, pdb->d_dma)) {
+ dev_err(dev, "Unable to map RSA private exponent memory\n");
+ dma_unmap_single(dev, pdb->n_dma, key->n_sz, DMA_TO_DEVICE);
+ return -ENOMEM;
+ }
+
+ if (edesc->src_nents > 1) {
+ pdb->sgf |= RSA_PRIV_PDB_SGF_G;
+ pdb->g_dma = edesc->sec4_sg_dma;
+ sec4_sg_index += edesc->src_nents;
+ } else {
+ pdb->g_dma = sg_dma_address(req->src);
+ }
+
+ if (edesc->dst_nents > 1) {
+ pdb->sgf |= RSA_PRIV_PDB_SGF_F;
+ pdb->f_dma = edesc->sec4_sg_dma +
+ sec4_sg_index * sizeof(struct sec4_sg_entry);
+ } else {
+ pdb->f_dma = sg_dma_address(req->dst);
+ }
+
+ pdb->sgf |= (key->n_sz << RSA_PDB_D_SHIFT) | key->n_sz;
+
+ return 0;
+}
+
+static int caam_rsa_enc(struct akcipher_request *req)
+{
+ struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
+ struct caam_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
+ struct caam_rsa_key *key = &ctx->key;
+ struct device *jrdev = ctx->dev;
+ struct rsa_edesc *edesc;
+ 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, DESC_RSA_PUB_LEN);
+ if (IS_ERR(edesc))
+ return PTR_ERR(edesc);
+
+ /* Set RSA Encrypt Protocol Data Block */
+ ret = set_rsa_pub_pdb(req, edesc);
+ if (ret)
+ goto init_fail;
+
+ /* Initialize Job Descriptor */
+ init_rsa_pub_desc(edesc->hw_desc, &edesc->pdb.pub);
+
+ ret = caam_jr_enqueue(jrdev, edesc->hw_desc, rsa_pub_done, req);
+ if (!ret)
+ return -EINPROGRESS;
+
+ rsa_pub_unmap(jrdev, edesc, req);
+
+init_fail:
+ rsa_io_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 caam_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
+ struct caam_rsa_key *key = &ctx->key;
+ struct device *jrdev = ctx->dev;
+ struct rsa_edesc *edesc;
+ int ret;
+
+ if (unlikely(!key->n || !key->d))
+ 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, DESC_RSA_PRIV_F1_LEN);
+ if (IS_ERR(edesc))
+ return PTR_ERR(edesc);
+
+ /* Set RSA Decrypt Protocol Data Block - Private Key Form #1 */
+ ret = set_rsa_priv_f1_pdb(req, edesc);
+ if (ret)
+ goto init_fail;
+
+ /* Initialize Job Descriptor */
+ init_rsa_priv_f1_desc(edesc->hw_desc, &edesc->pdb.priv_f1);
+
+ ret = caam_jr_enqueue(jrdev, edesc->hw_desc, rsa_priv_f1_done, req);
+ if (!ret)
+ return -EINPROGRESS;
+
+ rsa_priv_f1_unmap(jrdev, edesc, req);
+
+init_fail:
+ rsa_io_unmap(jrdev, edesc, req);
+ kfree(edesc);
+ return ret;
+}
+
+static void caam_rsa_free_key(struct caam_rsa_key *key)
+{
+ kzfree(key->d);
+ kfree(key->e);
+ kfree(key->n);
+ key->d = NULL;
+ key->e = NULL;
+ key->n = NULL;
+ key->d_sz = 0;
+ key->e_sz = 0;
+ key->n_sz = 0;
+}
+
+static int caam_rsa_set_pub_key(struct crypto_akcipher *tfm, const void *key,
+ unsigned int keylen)
+{
+ struct caam_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
+ struct rsa_key *raw_key = &ctx->raw_key;
+ struct caam_rsa_key *rsa_key = &ctx->key;
+ int ret;
+
+ /* Free the old RSA key if any */
+ caam_rsa_free_key(rsa_key);
+
+ ret = rsa_parse_pub_key(raw_key, key, keylen);
+ if (ret)
+ return ret;
+
+ /* Copy key in DMA zone */
+ rsa_key->e = kzalloc(raw_key->e_sz, GFP_DMA | GFP_KERNEL);
+ if (!rsa_key->e)
+ goto err;
+
+ rsa_key->n = kzalloc(raw_key->n_sz, GFP_DMA | GFP_KERNEL);
+ if (!rsa_key->n)
+ goto err;
+
+ rsa_key->e_sz = raw_key->e_sz;
+ rsa_key->n_sz = raw_key->n_sz;
+ memcpy(rsa_key->e, raw_key->e, raw_key->e_sz);
+ memcpy(rsa_key->n, raw_key->n, raw_key->n_sz);
+
+ return 0;
+err:
+ caam_rsa_free_key(rsa_key);
+ return -ENOMEM;
+}
+
+static int caam_rsa_set_priv_key(struct crypto_akcipher *tfm, const void *key,
+ unsigned int keylen)
+{
+ struct caam_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
+ struct rsa_key *raw_key = &ctx->raw_key;
+ struct caam_rsa_key *rsa_key = &ctx->key;
+ int ret;
+
+ /* Free the old RSA key if any */
+ caam_rsa_free_key(rsa_key);
+
+ ret = rsa_parse_priv_key(raw_key, key, keylen);
+ if (ret)
+ return ret;
+
+ /* Copy key in DMA zone */
+ rsa_key->d = kzalloc(raw_key->d_sz, GFP_DMA | GFP_KERNEL);
+ if (!rsa_key->d)
+ goto err;
+
+ rsa_key->e = kzalloc(raw_key->e_sz, GFP_DMA | GFP_KERNEL);
+ if (!rsa_key->e)
+ goto err;
+
+ rsa_key->n = kzalloc(raw_key->n_sz, GFP_DMA | GFP_KERNEL);
+ if (!rsa_key->n)
+ goto err;
+
+ rsa_key->d_sz = raw_key->d_sz;
+ rsa_key->e_sz = raw_key->e_sz;
+ rsa_key->n_sz = raw_key->n_sz;
+ memcpy(rsa_key->d, raw_key->d, raw_key->d_sz);
+ memcpy(rsa_key->e, raw_key->e, raw_key->e_sz);
+ memcpy(rsa_key->n, raw_key->n, raw_key->n_sz);
+
+ return 0;
+
+err:
+ caam_rsa_free_key(rsa_key);
+ return -ENOMEM;
+}
+
+static int caam_rsa_max_size(struct crypto_akcipher *tfm)
+{
+ struct caam_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
+ struct caam_rsa_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 caam_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
+
+ 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);
+ }
+
+ return 0;
+}
+
+/* Per session pkc's driver context cleanup function */
+static void caam_rsa_exit_tfm(struct crypto_akcipher *tfm)
+{
+ struct caam_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
+ struct caam_rsa_key *key = &ctx->key;
+
+ caam_rsa_free_key(key);
+ caam_jr_free(ctx->dev);
+}
+
+static struct akcipher_alg caam_rsa = {
+ .encrypt = caam_rsa_enc,
+ .decrypt = caam_rsa_dec,
+ .sign = caam_rsa_dec,
+ .verify = caam_rsa_enc,
+ .set_pub_key = caam_rsa_set_pub_key,
+ .set_priv_key = caam_rsa_set_priv_key,
+ .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_ctxsize = sizeof(struct caam_rsa_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;
+
+ 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;
+
+ err = crypto_register_akcipher(&caam_rsa);
+ if (err)
+ dev_warn(ctrldev, "%s alg registration failed\n",
+ caam_rsa.base.cra_driver_name);
+ else
+ dev_info(ctrldev, "caam pkc algorithms registered in /proc/crypto\n");
+
+ return err;
+}
+
+static void __exit caam_pkc_exit(void)
+{
+ crypto_unregister_akcipher(&caam_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..a9bed48
--- /dev/null
+++ b/drivers/crypto/caam/caampkc.h
@@ -0,0 +1,72 @@
+/*
+ * 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 "compat.h"
+#include "pdb.h"
+
+/**
+ * caam_rsa_key - CAAM RSA key structure. Keys are allocated in DMA zone.
+ * @n : RSA modulus raw byte stream
+ * @e : RSA public exponent raw byte stream
+ * @d : RSA private exponent raw byte stream
+ * @n_sz : length in bytes of RSA modulus n
+ * @e_sz : length in bytes of RSA public exponent
+ * @d_sz : length in bytes of RSA private exponent
+ */
+struct caam_rsa_key {
+ u8 *n;
+ u8 *e;
+ u8 *d;
+ size_t n_sz;
+ size_t e_sz;
+ size_t d_sz;
+};
+
+/**
+ * caam_rsa_ctx - per session context.
+ * @raw_key : raw RSA key parsed by the ASN.1 decoder
+ * @key : CAAM RSA key in DMA zone
+ * @dev : device structure
+ */
+struct caam_rsa_ctx {
+ struct rsa_key raw_key;
+ struct caam_rsa_key key;
+ struct device *dev;
+};
+
+/**
+ * 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_bytes : length of h/w link table
+ * @sec4_sg_dma : dma address of h/w link table
+ * @sec4_sg : pointer to h/w link table
+ * @pdb : specific RSA Protocol Data Block (PDB)
+ * @hw_desc : descriptor followed by link tables if any
+ */
+struct rsa_edesc {
+ int src_nents;
+ int dst_nents;
+ int sec4_sg_bytes;
+ dma_addr_t sec4_sg_dma;
+ struct sec4_sg_entry *sec4_sg;
+ union {
+ struct rsa_pub_pdb pub;
+ struct rsa_priv_f1_pdb priv_f1;
+ } pdb;
+ u32 hw_desc[];
+};
+
+/* Descriptor construction primitives. */
+void init_rsa_pub_desc(u32 *desc, struct rsa_pub_pdb *pdb);
+void init_rsa_priv_f1_desc(u32 *desc, struct rsa_priv_f1_pdb *pdb);
+
+#endif
diff --git a/drivers/crypto/caam/compat.h b/drivers/crypto/caam/compat.h
index b6955ec..7149cd2 100644
--- a/drivers/crypto/caam/compat.h
+++ b/drivers/crypto/caam/compat.h
@@ -35,8 +35,11 @@
#include <crypto/md5.h>
#include <crypto/internal/aead.h>
#include <crypto/authenc.h>
+#include <crypto/akcipher.h>
#include <crypto/scatterwalk.h>
#include <crypto/internal/skcipher.h>
#include <crypto/internal/hash.h>
+#include <crypto/internal/rsa.h>
+#include <crypto/internal/akcipher.h>
#endif /* !defined(CAAM_COMPAT_H) */
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/desc_constr.h b/drivers/crypto/caam/desc_constr.h
index 98d07de..3ff47b9 100644
--- a/drivers/crypto/caam/desc_constr.h
+++ b/drivers/crypto/caam/desc_constr.h
@@ -74,6 +74,13 @@ static inline void init_job_desc(u32 *desc, u32 options)
init_desc(desc, CMD_DESC_HDR | options);
}
+static inline void init_job_desc_pdb(u32 *desc, u32 options, size_t pdb_bytes)
+{
+ u32 pdb_len = (pdb_bytes + CAAM_CMD_SZ - 1) / CAAM_CMD_SZ;
+
+ init_job_desc(desc, (((pdb_len + 1) << HDR_START_IDX_SHIFT)) | options);
+}
+
static inline void append_ptr(u32 *desc, dma_addr_t ptr)
{
dma_addr_t *offset = (dma_addr_t *)desc_end(desc);
diff --git a/drivers/crypto/caam/pdb.h b/drivers/crypto/caam/pdb.h
index 3a87c0c..d0a5db2 100644
--- a/drivers/crypto/caam/pdb.h
+++ b/drivers/crypto/caam/pdb.h
@@ -1,12 +1,13 @@
/*
* CAAM Protocol Data Block (PDB) definition header file
*
- * Copyright 2008-2012 Freescale Semiconductor, Inc.
+ * Copyright 2008-2016 Freescale Semiconductor, Inc.
*
*/
#ifndef CAAM_PDB_H
#define CAAM_PDB_H
+#include "compat.h"
/*
* PDB- IPSec ESP Header Modification Options
@@ -399,4 +400,52 @@ 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
+
+/**
+ * RSA Encrypt Protocol Data Block
+ * @sgf: scatter-gather field
+ * @f_dma: dma address of input data
+ * @g_dma: dma address of encrypted output data
+ * @n_dma: dma address of RSA modulus
+ * @e_dma: dma address of RSA public exponent
+ * @f_len: length in octets of the input data
+ */
+struct rsa_pub_pdb {
+ 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;
+} __packed;
+
+/**
+ * RSA Decrypt PDB - Private Key Form #1
+ * @sgf: scatter-gather field
+ * @g_dma: dma address of encrypted input data
+ * @f_dma: dma address of output data
+ * @n_dma: dma address of RSA modulus
+ * @d_dma: dma address of RSA private exponent
+ */
+struct rsa_priv_f1_pdb {
+ u32 sgf;
+ dma_addr_t g_dma;
+ dma_addr_t f_dma;
+ dma_addr_t n_dma;
+ dma_addr_t d_dma;
+} __packed;
+
#endif
diff --git a/drivers/crypto/caam/pkc_desc.c b/drivers/crypto/caam/pkc_desc.c
new file mode 100644
index 0000000..4e4183e
--- /dev/null
+++ b/drivers/crypto/caam/pkc_desc.c
@@ -0,0 +1,36 @@
+/*
+ * 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"
+#include "desc_constr.h"
+
+/* Descriptor for RSA Public operation */
+void init_rsa_pub_desc(u32 *desc, struct rsa_pub_pdb *pdb)
+{
+ init_job_desc_pdb(desc, 0, sizeof(*pdb));
+ append_cmd(desc, pdb->sgf);
+ append_ptr(desc, pdb->f_dma);
+ append_ptr(desc, pdb->g_dma);
+ append_ptr(desc, pdb->n_dma);
+ append_ptr(desc, pdb->e_dma);
+ append_cmd(desc, pdb->f_len);
+ append_operation(desc, OP_TYPE_UNI_PROTOCOL | OP_PCLID_RSAENC_PUBKEY);
+}
+
+/* Descriptor for RSA Private operation - Private Key Form #1 */
+void init_rsa_priv_f1_desc(u32 *desc, struct rsa_priv_f1_pdb *pdb)
+{
+ init_job_desc_pdb(desc, 0, sizeof(*pdb));
+ append_cmd(desc, pdb->sgf);
+ append_ptr(desc, pdb->g_dma);
+ append_ptr(desc, pdb->f_dma);
+ append_ptr(desc, pdb->n_dma);
+ append_ptr(desc, pdb->d_dma);
+ append_operation(desc, OP_TYPE_UNI_PROTOCOL | OP_PCLID_RSADEC_PRVKEY |
+ RSA_PRIV_KEY_FRM_1);
+}
--
1.8.3.1
^ permalink raw reply related
* Re: [PATCH v3] crypto: rsa - return raw integers for the ASN.1 parser
From: Stephan Mueller @ 2016-06-07 14:33 UTC (permalink / raw)
To: Tudor Ambarus; +Cc: herbert, linux-crypto
In-Reply-To: <1465309269-2214-1-git-send-email-tudor-dan.ambarus@nxp.com>
Am Dienstag, 7. Juni 2016, 17:21:09 schrieb Tudor Ambarus:
Hi Tudor,
> Return the raw key with no other processing so that the caller
> can copy it or MPI parse it, etc.
>
> The scope is to have only one ANS.1 parser for all RSA
> implementations.
>
> Update the RSA software implementation so that it does
> the MPI conversion on top.
>
> Signed-off-by: Tudor Ambarus <tudor-dan.ambarus@nxp.com>
> ---
> crypto/rsa.c | 119 ++++++++++++++++++++++++++-------------
> crypto/rsa_helper.c | 128
> +++++++++++++++++++++--------------------- include/crypto/internal/rsa.h |
> 22 ++++++--
> 3 files changed, 161 insertions(+), 108 deletions(-)
>
> diff --git a/crypto/rsa.c b/crypto/rsa.c
> index 77d737f..ea78d61 100644
> --- a/crypto/rsa.c
> +++ b/crypto/rsa.c
> @@ -14,12 +14,24 @@
> #include <crypto/internal/akcipher.h>
> #include <crypto/akcipher.h>
> #include <crypto/algapi.h>
> +#include <linux/mpi.h>
> +
> +struct rsa_mpi_key {
> + MPI n;
> + MPI e;
> + MPI d;
> +};
> +
> +struct rsa_ctx {
> + struct rsa_key key;
> + struct rsa_mpi_key mpi_key;
> +};
>
> /*
> * 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 +45,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 +59,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 +73,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 +83,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->mpi_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 +132,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 +170,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 +209,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;
> @@ -233,67 +247,94 @@ err_free_m:
> return ret;
> }
>
> -static int rsa_check_key_length(unsigned int len)
> +static void rsa_free_mpi_key(struct rsa_mpi_key *key)
> {
> - switch (len) {
> - case 512:
> - case 1024:
> - case 1536:
> - case 2048:
> - case 3072:
> - case 4096:
> - return 0;
> - }
> -
> - return -EINVAL;
> + mpi_free(key->d);
> + mpi_free(key->e);
> + mpi_free(key->n);
> + key->d = NULL;
> + key->e = NULL;
> + key->n = NULL;
> }
>
> 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_key *pkey = &ctx->key;
> + struct rsa_mpi_key *mpi_key = &ctx->mpi_key;
> int ret;
>
> + /* Free the old MPI key if any */
> + rsa_free_mpi_key(mpi_key);
> +
> 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;
> + mpi_key->e = mpi_read_raw_data(pkey->e, pkey->e_sz);
> + if (!mpi_key->e)
> + goto err;
> +
> + mpi_key->n = mpi_read_raw_data(pkey->n, pkey->n_sz);
> + if (!mpi_key->n)
> + goto err;
> +
> + return 0;
> +
> +err:
> + rsa_free_mpi_key(mpi_key);
> + return -ENOMEM;
> }
>
> 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_key *pkey = &ctx->key;
> + struct rsa_mpi_key *mpi_key = &ctx->mpi_key;
> int ret;
>
> + /* Free the old MPI key if any */
> + rsa_free_mpi_key(mpi_key);
> +
> ret = rsa_parse_priv_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;
> + mpi_key->d = mpi_read_raw_data(pkey->d, pkey->n_sz);
> + if (!mpi_key->d)
> + goto err;
> +
> + mpi_key->e = mpi_read_raw_data(pkey->e, pkey->e_sz);
> + if (!mpi_key->e)
> + goto err;
> +
> + mpi_key->n = mpi_read_raw_data(pkey->n, pkey->n_sz);
> + if (!mpi_key->n)
> + goto err;
> +
> + return 0;
> +
> +err:
> + rsa_free_mpi_key(mpi_key);
> + return -ENOMEM;
> }
>
> static int rsa_max_size(struct crypto_akcipher *tfm)
> {
> - struct rsa_key *pkey = akcipher_tfm_ctx(tfm);
> + struct rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
> + struct rsa_key *pkey = &ctx->key;
>
> - return pkey->n ? mpi_get_size(pkey->n) : -EINVAL;
> + return pkey->n ? pkey->n_sz : -EINVAL;
> }
>
> static void rsa_exit_tfm(struct crypto_akcipher *tfm)
> {
> - struct rsa_key *pkey = akcipher_tfm_ctx(tfm);
> + struct rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
> + struct rsa_mpi_key *mpi_key = &ctx->mpi_key;
>
> - rsa_free_key(pkey);
> + rsa_free_mpi_key(mpi_key);
> }
>
> static struct akcipher_alg rsa = {
> @@ -310,7 +351,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..f0677b7 100644
> --- a/crypto/rsa_helper.c
> +++ b/crypto/rsa_helper.c
> @@ -18,24 +18,50 @@
> #include "rsapubkey-asn1.h"
> #include "rsaprivkey-asn1.h"
>
> +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;
> +}
> +
> int rsa_get_n(void *context, size_t hdrlen, unsigned char tag,
> const void *value, size_t vlen)
> {
> struct rsa_key *key = context;
> + const u8 *ptr = value;
> + int ret;
>
> - key->n = mpi_read_raw_data(value, vlen);
> + while (!*ptr && vlen) {
> + ptr++;
> + vlen--;
> + }
As you do this operation 3 times, isn't an inline better here?
>
> - if (!key->n)
> - return -ENOMEM;
> + /* invalid key provided */
> + if (!ptr)
> + return -EINVAL;
Hm, you check the pointer here, but you dereference it already above. So, I
guess you want to move that check to the beginning of the function?
>
> /* In FIPS mode only allow key size 2K & 3K */
> - if (fips_enabled && (mpi_get_size(key->n) != 256 &&
> - mpi_get_size(key->n) != 384)) {
> + if (fips_enabled && (vlen != 256 && vlen != 384)) {
> pr_err("RSA: key size not allowed in FIPS mode\n");
> - mpi_free(key->n);
> - key->n = NULL;
> return -EINVAL;
> }
> + /* invalid key size provided */
> + ret = rsa_check_key_length(vlen << 3);
> + if (ret)
> + return ret;
> +
> + key->n = ptr;
> + key->n_sz = vlen;
> +
> return 0;
> }
>
> @@ -43,11 +69,19 @@ int rsa_get_e(void *context, size_t hdrlen, unsigned
> char tag, const void *value, size_t vlen)
> {
> struct rsa_key *key = context;
> + const u8 *ptr = value;
> +
> + while (!*ptr && vlen) {
> + ptr++;
> + vlen--;
> + }
No NULL check for ptr? Is it always guaranteed that there is no NULL
considering that this may be exposed to user space?
>
> - key->e = mpi_read_raw_data(value, vlen);
> + /* invalid key provided */
> + if (!ptr || !key->n_sz || !vlen || vlen > key->n_sz)
> + return -EINVAL;
Ah, here we have that check -- again, I would assume it should move up.
>
> - if (!key->e)
> - return -ENOMEM;
> + key->e = ptr;
> + key->e_sz = vlen;
>
> return 0;
> }
> @@ -56,47 +90,33 @@ int rsa_get_d(void *context, size_t hdrlen, unsigned
> char tag, const void *value, size_t vlen)
> {
> struct rsa_key *key = context;
> + const u8 *ptr = value;
>
> - key->d = mpi_read_raw_data(value, vlen);
> + while (!*ptr && vlen) {
> + ptr++;
> + vlen--;
> + }
Same here.
>
> - if (!key->d)
> - return -ENOMEM;
> + /* invalid key provided */
> + if (!ptr || !key->n_sz || !vlen || vlen > key->n_sz)
> + return -EINVAL;
>
> /* In FIPS mode only allow key size 2K & 3K */
> - if (fips_enabled && (mpi_get_size(key->d) != 256 &&
> - mpi_get_size(key->d) != 384)) {
> + if (fips_enabled && (vlen != 256 && vlen != 384)) {
> pr_err("RSA: key size not allowed in FIPS mode\n");
> - mpi_free(key->d);
> - key->d = NULL;
> return -EINVAL;
> }
> - return 0;
> -}
>
> -static void free_mpis(struct rsa_key *key)
> -{
> - mpi_free(key->n);
> - mpi_free(key->e);
> - mpi_free(key->d);
> - key->n = NULL;
> - key->e = NULL;
> - key->d = NULL;
> -}
> + key->d = ptr;
> + key->d_sz = vlen;
>
> -/**
> - * 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);
> + return 0;
> }
> -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_pub_key() - decodes the BER encoded buffer and stores in the
> + * provided struct rsa_key, pointers to the raw key
> as is, + * so that the caller can copy it or MPI
> parse it, etc. *
> * @rsa_key: struct rsa_key key representation
> * @key: key in BER format
> @@ -107,23 +127,15 @@ EXPORT_SYMBOL_GPL(rsa_free_key);
> 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(&rsapubkey_decoder, rsa_key, key, key_len);
> - if (ret < 0)
> - goto error;
> -
> - return 0;
> -error:
> - free_mpis(rsa_key);
> - return ret;
> + return asn1_ber_decoder(&rsapubkey_decoder, rsa_key, key, key_len);
> }
> 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() - decodes the BER encoded buffer and stores in the
> + * provided struct rsa_key, pointers to the raw key
> + * as is, so that the caller can copy it or MPI
> parse it, + * etc.
> *
> * @rsa_key: struct rsa_key key representation
> * @key: key in BER format
> @@ -134,16 +146,6 @@ EXPORT_SYMBOL_GPL(rsa_parse_pub_key);
> 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;
> + return asn1_ber_decoder(&rsaprivkey_decoder, rsa_key, key, key_len);
> }
> EXPORT_SYMBOL_GPL(rsa_parse_priv_key);
> diff --git a/include/crypto/internal/rsa.h b/include/crypto/internal/rsa.h
> index c7585bd..d6c042a 100644
> --- a/include/crypto/internal/rsa.h
> +++ b/include/crypto/internal/rsa.h
> @@ -12,12 +12,24 @@
> */
> #ifndef _RSA_HELPER_
> #define _RSA_HELPER_
> -#include <linux/mpi.h>
> +#include <linux/types.h>
>
> +/**
> + * rsa_key - RSA key structure
> + * @n : RSA modulus raw byte stream
> + * @e : RSA public exponent raw byte stream
> + * @d : RSA private exponent raw byte stream
> + * @n_sz : length in bytes of RSA modulus n
> + * @e_sz : length in bytes of RSA public exponent
> + * @d_sz : length in bytes of RSA private exponent
> + */
> struct rsa_key {
> - MPI n;
> - MPI e;
> - MPI d;
> + const u8 *n;
> + const u8 *e;
> + const u8 *d;
> + size_t n_sz;
> + size_t e_sz;
> + size_t d_sz;
> };
>
> int rsa_parse_pub_key(struct rsa_key *rsa_key, const void *key,
> @@ -26,7 +38,5 @@ int rsa_parse_pub_key(struct rsa_key *rsa_key, const void
> *key, 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);
> -
> extern struct crypto_template rsa_pkcs1pad_tmpl;
> #endif
Ciao
Stephan
^ permalink raw reply
* RE: [PATCH V2 2/2] crypto : async implementation for sha1-mb
From: Dey, Megha @ 2016-06-07 18:10 UTC (permalink / raw)
To: Herbert Xu
Cc: tim.c.chen@linux.intel.com, davem@davemloft.net,
linux-crypto@vger.kernel.org, linux-kernel@vger.kernel.org,
Yu, Fenghua, Megha Dey
In-Reply-To: <20160607103515.GB325@gondor.apana.org.au>
-----Original Message-----
From: Herbert Xu [mailto:herbert@gondor.apana.org.au]
Sent: Tuesday, June 7, 2016 3:35 AM
To: Dey, Megha <megha.dey@intel.com>
Cc: tim.c.chen@linux.intel.com; davem@davemloft.net; linux-crypto@vger.kernel.org; linux-kernel@vger.kernel.org; Yu, Fenghua <fenghua.yu@intel.com>; Megha Dey <megha.dey@linux.intel.com>
Subject: Re: [PATCH V2 2/2] crypto : async implementation for sha1-mb
On Thu, Jun 02, 2016 at 07:53:50PM -0700, Megha Dey wrote:
>
> + struct ahash_alg *shash = crypto_ahash_alg(tfm);
>
> /* alignment is to be done by multi-buffer crypto algorithm if
> needed */
>
> - return shash->finup(desc, NULL, 0, req->result);
> + return shash->finup(desc);
You're still poking in the guts of the API. Now that it's a real ahash you don't need to do that.
Just do crypto_ahash_finup. That way you don't need to export crypto_ahsh_alg either.
> I have made these changes and re-sent the patch.
Thanks,
--
Email: Herbert Xu <herbert@gondor.apana.org.au> Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply
* [PATCH] crypto : async implementation for sha1-mb
From: Megha Dey @ 2016-06-07 18:14 UTC (permalink / raw)
To: herbert
Cc: tim.c.chen, davem, linux-crypto, linux-kernel, megha.dey,
fenghua.yu, Megha Dey
From: Megha Dey <megha.dey@linux.intel.com>
Herbert wants the sha1-mb algorithm to have an async implementation:
https://lkml.org/lkml/2016/4/5/286.
Currently, sha1-mb uses an async interface for the outer algorithm
and a sync interface for the inner algorithm. This patch introduces
a async interface for even the inner algorithm.
Signed-off-by: Megha Dey <megha.dey@linux.intel.com>
Signed-off-by: Tim Chen <tim.c.chen@linux.intel.com>
---
arch/x86/crypto/sha-mb/sha1_mb.c | 187 ++++++++++++++++++++++-----------------
crypto/mcryptd.c | 122 +++++++++++--------------
include/crypto/internal/hash.h | 12 +--
include/crypto/mcryptd.h | 8 +-
4 files changed, 166 insertions(+), 163 deletions(-)
diff --git a/arch/x86/crypto/sha-mb/sha1_mb.c b/arch/x86/crypto/sha-mb/sha1_mb.c
index 0a46491..c76d1ba 100644
--- a/arch/x86/crypto/sha-mb/sha1_mb.c
+++ b/arch/x86/crypto/sha-mb/sha1_mb.c
@@ -80,10 +80,10 @@ struct sha1_mb_ctx {
static inline struct mcryptd_hash_request_ctx
*cast_hash_to_mcryptd_ctx(struct sha1_hash_ctx *hash_ctx)
{
- struct shash_desc *desc;
+ struct ahash_request *areq;
- desc = container_of((void *) hash_ctx, struct shash_desc, __ctx);
- return container_of(desc, struct mcryptd_hash_request_ctx, desc);
+ areq = container_of((void *) hash_ctx, struct ahash_request, __ctx);
+ return container_of(areq, struct mcryptd_hash_request_ctx, areq);
}
static inline struct ahash_request
@@ -93,7 +93,7 @@ static inline struct ahash_request
}
static void req_ctx_init(struct mcryptd_hash_request_ctx *rctx,
- struct shash_desc *desc)
+ struct ahash_request *areq)
{
rctx->flag = HASH_UPDATE;
}
@@ -375,9 +375,9 @@ static struct sha1_hash_ctx *sha1_ctx_mgr_flush(struct sha1_ctx_mgr *mgr)
}
}
-static int sha1_mb_init(struct shash_desc *desc)
+static int sha1_mb_init(struct ahash_request *areq)
{
- struct sha1_hash_ctx *sctx = shash_desc_ctx(desc);
+ struct sha1_hash_ctx *sctx = ahash_request_ctx(areq);
hash_ctx_init(sctx);
sctx->job.result_digest[0] = SHA1_H0;
@@ -395,7 +395,7 @@ static int sha1_mb_init(struct shash_desc *desc)
static int sha1_mb_set_results(struct mcryptd_hash_request_ctx *rctx)
{
int i;
- struct sha1_hash_ctx *sctx = shash_desc_ctx(&rctx->desc);
+ struct sha1_hash_ctx *sctx = ahash_request_ctx(&rctx->areq);
__be32 *dst = (__be32 *) rctx->out;
for (i = 0; i < 5; ++i)
@@ -427,7 +427,7 @@ static int sha_finish_walk(struct mcryptd_hash_request_ctx **ret_rctx,
}
sha_ctx = (struct sha1_hash_ctx *)
- shash_desc_ctx(&rctx->desc);
+ ahash_request_ctx(&rctx->areq);
kernel_fpu_begin();
sha_ctx = sha1_ctx_mgr_submit(cstate->mgr, sha_ctx,
rctx->walk.data, nbytes, flag);
@@ -519,11 +519,10 @@ static void sha1_mb_add_list(struct mcryptd_hash_request_ctx *rctx,
mcryptd_arm_flusher(cstate, delay);
}
-static int sha1_mb_update(struct shash_desc *desc, const u8 *data,
- unsigned int len)
+static int sha1_mb_update(struct ahash_request *areq)
{
struct mcryptd_hash_request_ctx *rctx =
- container_of(desc, struct mcryptd_hash_request_ctx, desc);
+ container_of(areq, struct mcryptd_hash_request_ctx, areq);
struct mcryptd_alg_cstate *cstate =
this_cpu_ptr(sha1_mb_alg_state.alg_cstate);
@@ -539,7 +538,7 @@ static int sha1_mb_update(struct shash_desc *desc, const u8 *data,
}
/* need to init context */
- req_ctx_init(rctx, desc);
+ req_ctx_init(rctx, areq);
nbytes = crypto_ahash_walk_first(req, &rctx->walk);
@@ -552,7 +551,7 @@ static int sha1_mb_update(struct shash_desc *desc, const u8 *data,
rctx->flag |= HASH_DONE;
/* submit */
- sha_ctx = (struct sha1_hash_ctx *) shash_desc_ctx(desc);
+ sha_ctx = (struct sha1_hash_ctx *) ahash_request_ctx(areq);
sha1_mb_add_list(rctx, cstate);
kernel_fpu_begin();
sha_ctx = sha1_ctx_mgr_submit(cstate->mgr, sha_ctx, rctx->walk.data,
@@ -579,11 +578,10 @@ done:
return ret;
}
-static int sha1_mb_finup(struct shash_desc *desc, const u8 *data,
- unsigned int len, u8 *out)
+static int sha1_mb_finup(struct ahash_request *areq)
{
struct mcryptd_hash_request_ctx *rctx =
- container_of(desc, struct mcryptd_hash_request_ctx, desc);
+ container_of(areq, struct mcryptd_hash_request_ctx, areq);
struct mcryptd_alg_cstate *cstate =
this_cpu_ptr(sha1_mb_alg_state.alg_cstate);
@@ -598,7 +596,7 @@ static int sha1_mb_finup(struct shash_desc *desc, const u8 *data,
}
/* need to init context */
- req_ctx_init(rctx, desc);
+ req_ctx_init(rctx, areq);
nbytes = crypto_ahash_walk_first(req, &rctx->walk);
@@ -611,11 +609,10 @@ static int sha1_mb_finup(struct shash_desc *desc, const u8 *data,
rctx->flag |= HASH_DONE;
flag = HASH_LAST;
}
- rctx->out = out;
/* submit */
rctx->flag |= HASH_FINAL;
- sha_ctx = (struct sha1_hash_ctx *) shash_desc_ctx(desc);
+ sha_ctx = (struct sha1_hash_ctx *) ahash_request_ctx(areq);
sha1_mb_add_list(rctx, cstate);
kernel_fpu_begin();
@@ -641,10 +638,10 @@ done:
return ret;
}
-static int sha1_mb_final(struct shash_desc *desc, u8 *out)
+static int sha1_mb_final(struct ahash_request *areq)
{
struct mcryptd_hash_request_ctx *rctx =
- container_of(desc, struct mcryptd_hash_request_ctx, desc);
+ container_of(areq, struct mcryptd_hash_request_ctx, areq);
struct mcryptd_alg_cstate *cstate =
this_cpu_ptr(sha1_mb_alg_state.alg_cstate);
@@ -659,12 +656,11 @@ static int sha1_mb_final(struct shash_desc *desc, u8 *out)
}
/* need to init context */
- req_ctx_init(rctx, desc);
+ req_ctx_init(rctx, areq);
- rctx->out = out;
rctx->flag |= HASH_DONE | HASH_FINAL;
- sha_ctx = (struct sha1_hash_ctx *) shash_desc_ctx(desc);
+ sha_ctx = (struct sha1_hash_ctx *) ahash_request_ctx(areq);
/* flag HASH_FINAL and 0 data size */
sha1_mb_add_list(rctx, cstate);
kernel_fpu_begin();
@@ -691,48 +687,98 @@ done:
return ret;
}
-static int sha1_mb_export(struct shash_desc *desc, void *out)
+static int sha1_mb_export(struct ahash_request *areq, void *out)
{
- struct sha1_hash_ctx *sctx = shash_desc_ctx(desc);
+ struct sha1_hash_ctx *sctx = ahash_request_ctx(areq);
memcpy(out, sctx, sizeof(*sctx));
return 0;
}
-static int sha1_mb_import(struct shash_desc *desc, const void *in)
+static int sha1_mb_import(struct ahash_request *areq, const void *in)
{
- struct sha1_hash_ctx *sctx = shash_desc_ctx(desc);
+ struct sha1_hash_ctx *sctx = ahash_request_ctx(areq);
memcpy(sctx, in, sizeof(*sctx));
return 0;
}
+static int sha1_mb_async_init_tfm(struct crypto_tfm *tfm)
+{
+ struct mcryptd_ahash *mcryptd_tfm;
+ struct sha1_mb_ctx *ctx = crypto_tfm_ctx(tfm);
+ struct mcryptd_hash_ctx *mctx;
-static struct shash_alg sha1_mb_shash_alg = {
- .digestsize = SHA1_DIGEST_SIZE,
+ mcryptd_tfm = mcryptd_alloc_ahash("__intel_sha1-mb",
+ CRYPTO_ALG_INTERNAL,
+ CRYPTO_ALG_INTERNAL);
+ if (IS_ERR(mcryptd_tfm))
+ return PTR_ERR(mcryptd_tfm);
+ mctx = crypto_ahash_ctx(&mcryptd_tfm->base);
+ mctx->alg_state = &sha1_mb_alg_state;
+ ctx->mcryptd_tfm = mcryptd_tfm;
+ crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm),
+ sizeof(struct ahash_request) +
+ crypto_ahash_reqsize(&mcryptd_tfm->base));
+
+ return 0;
+}
+
+static void sha1_mb_async_exit_tfm(struct crypto_tfm *tfm)
+{
+ struct sha1_mb_ctx *ctx = crypto_tfm_ctx(tfm);
+
+ mcryptd_free_ahash(ctx->mcryptd_tfm);
+}
+
+static int sha1_mb_areq_init_tfm(struct crypto_tfm *tfm)
+{
+ crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm),
+ sizeof(struct ahash_request) +
+ sizeof(struct sha1_hash_ctx));
+
+ return 0;
+}
+
+static void sha1_mb_areq_exit_tfm(struct crypto_tfm *tfm)
+{
+ struct sha1_mb_ctx *ctx = crypto_tfm_ctx(tfm);
+
+ mcryptd_free_ahash(ctx->mcryptd_tfm);
+}
+
+static struct ahash_alg sha1_mb_areq_alg = {
.init = sha1_mb_init,
.update = sha1_mb_update,
.final = sha1_mb_final,
.finup = sha1_mb_finup,
.export = sha1_mb_export,
.import = sha1_mb_import,
- .descsize = sizeof(struct sha1_hash_ctx),
- .statesize = sizeof(struct sha1_hash_ctx),
- .base = {
- .cra_name = "__sha1-mb",
- .cra_driver_name = "__intel_sha1-mb",
- .cra_priority = 100,
- /*
- * use ASYNC flag as some buffers in multi-buffer
- * algo may not have completed before hashing thread sleep
- */
- .cra_flags = CRYPTO_ALG_TYPE_SHASH | CRYPTO_ALG_ASYNC |
- CRYPTO_ALG_INTERNAL,
- .cra_blocksize = SHA1_BLOCK_SIZE,
- .cra_module = THIS_MODULE,
- .cra_list = LIST_HEAD_INIT(sha1_mb_shash_alg.base.cra_list),
+ .halg = {
+ .digestsize = SHA1_DIGEST_SIZE,
+ .statesize = sizeof(struct sha1_hash_ctx),
+ .base = {
+ .cra_name = "__sha1-mb",
+ .cra_driver_name = "__intel_sha1-mb",
+ .cra_priority = 100,
+ /*
+ * use ASYNC flag as some buffers in multi-buffer
+ * algo may not have completed before hashing thread
+ * sleep
+ */
+ .cra_flags = CRYPTO_ALG_TYPE_AHASH |
+ CRYPTO_ALG_ASYNC |
+ CRYPTO_ALG_INTERNAL,
+ .cra_blocksize = SHA1_BLOCK_SIZE,
+ .cra_module = THIS_MODULE,
+ .cra_list = LIST_HEAD_INIT
+ (sha1_mb_areq_alg.halg.base.cra_list),
+ .cra_init = sha1_mb_areq_init_tfm,
+ .cra_exit = sha1_mb_areq_exit_tfm,
+ .cra_ctxsize = sizeof(struct sha1_hash_ctx),
+ }
}
};
@@ -817,46 +863,19 @@ static int sha1_mb_async_import(struct ahash_request *req, const void *in)
struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
struct sha1_mb_ctx *ctx = crypto_ahash_ctx(tfm);
struct mcryptd_ahash *mcryptd_tfm = ctx->mcryptd_tfm;
- struct crypto_shash *child = mcryptd_ahash_child(mcryptd_tfm);
+ struct crypto_ahash *child = mcryptd_ahash_child(mcryptd_tfm);
struct mcryptd_hash_request_ctx *rctx;
- struct shash_desc *desc;
+ struct ahash_request *areq;
memcpy(mcryptd_req, req, sizeof(*req));
ahash_request_set_tfm(mcryptd_req, &mcryptd_tfm->base);
rctx = ahash_request_ctx(mcryptd_req);
- desc = &rctx->desc;
- desc->tfm = child;
- desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP;
-
- return crypto_ahash_import(mcryptd_req, in);
-}
-
-static int sha1_mb_async_init_tfm(struct crypto_tfm *tfm)
-{
- struct mcryptd_ahash *mcryptd_tfm;
- struct sha1_mb_ctx *ctx = crypto_tfm_ctx(tfm);
- struct mcryptd_hash_ctx *mctx;
+ areq = &rctx->areq;
- mcryptd_tfm = mcryptd_alloc_ahash("__intel_sha1-mb",
- CRYPTO_ALG_INTERNAL,
- CRYPTO_ALG_INTERNAL);
- if (IS_ERR(mcryptd_tfm))
- return PTR_ERR(mcryptd_tfm);
- mctx = crypto_ahash_ctx(&mcryptd_tfm->base);
- mctx->alg_state = &sha1_mb_alg_state;
- ctx->mcryptd_tfm = mcryptd_tfm;
- crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm),
- sizeof(struct ahash_request) +
- crypto_ahash_reqsize(&mcryptd_tfm->base));
-
- return 0;
-}
-
-static void sha1_mb_async_exit_tfm(struct crypto_tfm *tfm)
-{
- struct sha1_mb_ctx *ctx = crypto_tfm_ctx(tfm);
+ ahash_request_set_tfm(areq, child);
+ ahash_request_set_callback(areq, CRYPTO_TFM_REQ_MAY_SLEEP, NULL, NULL);
- mcryptd_free_ahash(ctx->mcryptd_tfm);
+ return crypto_ahash_import(mcryptd_req, in);
}
static struct ahash_alg sha1_mb_async_alg = {
@@ -874,11 +893,13 @@ static struct ahash_alg sha1_mb_async_alg = {
.cra_name = "sha1",
.cra_driver_name = "sha1_mb",
.cra_priority = 200,
- .cra_flags = CRYPTO_ALG_TYPE_AHASH | CRYPTO_ALG_ASYNC,
+ .cra_flags = CRYPTO_ALG_TYPE_AHASH |
+ CRYPTO_ALG_ASYNC,
.cra_blocksize = SHA1_BLOCK_SIZE,
.cra_type = &crypto_ahash_type,
.cra_module = THIS_MODULE,
- .cra_list = LIST_HEAD_INIT(sha1_mb_async_alg.halg.base.cra_list),
+ .cra_list = LIST_HEAD_INIT
+ (sha1_mb_async_alg.halg.base.cra_list),
.cra_init = sha1_mb_async_init_tfm,
.cra_exit = sha1_mb_async_exit_tfm,
.cra_ctxsize = sizeof(struct sha1_mb_ctx),
@@ -965,7 +986,7 @@ static int __init sha1_mb_mod_init(void)
}
sha1_mb_alg_state.flusher = &sha1_mb_flusher;
- err = crypto_register_shash(&sha1_mb_shash_alg);
+ err = crypto_register_ahash(&sha1_mb_areq_alg);
if (err)
goto err2;
err = crypto_register_ahash(&sha1_mb_async_alg);
@@ -975,7 +996,7 @@ static int __init sha1_mb_mod_init(void)
return 0;
err1:
- crypto_unregister_shash(&sha1_mb_shash_alg);
+ crypto_unregister_ahash(&sha1_mb_areq_alg);
err2:
for_each_possible_cpu(cpu) {
cpu_state = per_cpu_ptr(sha1_mb_alg_state.alg_cstate, cpu);
@@ -991,7 +1012,7 @@ static void __exit sha1_mb_mod_fini(void)
struct mcryptd_alg_cstate *cpu_state;
crypto_unregister_ahash(&sha1_mb_async_alg);
- crypto_unregister_shash(&sha1_mb_shash_alg);
+ crypto_unregister_ahash(&sha1_mb_areq_alg);
for_each_possible_cpu(cpu) {
cpu_state = per_cpu_ptr(sha1_mb_alg_state.alg_cstate, cpu);
kfree(cpu_state->mgr);
diff --git a/crypto/mcryptd.c b/crypto/mcryptd.c
index c4eb9da..3173ee8 100644
--- a/crypto/mcryptd.c
+++ b/crypto/mcryptd.c
@@ -41,7 +41,7 @@ struct mcryptd_flush_list {
static struct mcryptd_flush_list __percpu *mcryptd_flist;
struct hashd_instance_ctx {
- struct crypto_shash_spawn spawn;
+ struct crypto_ahash_spawn spawn;
struct mcryptd_queue *queue;
};
@@ -272,18 +272,18 @@ static int mcryptd_hash_init_tfm(struct crypto_tfm *tfm)
{
struct crypto_instance *inst = crypto_tfm_alg_instance(tfm);
struct hashd_instance_ctx *ictx = crypto_instance_ctx(inst);
- struct crypto_shash_spawn *spawn = &ictx->spawn;
+ struct crypto_ahash_spawn *spawn = &ictx->spawn;
struct mcryptd_hash_ctx *ctx = crypto_tfm_ctx(tfm);
- struct crypto_shash *hash;
+ struct crypto_ahash *hash;
- hash = crypto_spawn_shash(spawn);
+ hash = crypto_spawn_ahash(spawn);
if (IS_ERR(hash))
return PTR_ERR(hash);
ctx->child = hash;
crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm),
sizeof(struct mcryptd_hash_request_ctx) +
- crypto_shash_descsize(hash));
+ crypto_ahash_reqsize(hash));
return 0;
}
@@ -291,21 +291,21 @@ static void mcryptd_hash_exit_tfm(struct crypto_tfm *tfm)
{
struct mcryptd_hash_ctx *ctx = crypto_tfm_ctx(tfm);
- crypto_free_shash(ctx->child);
+ crypto_free_ahash(ctx->child);
}
static int mcryptd_hash_setkey(struct crypto_ahash *parent,
const u8 *key, unsigned int keylen)
{
struct mcryptd_hash_ctx *ctx = crypto_ahash_ctx(parent);
- struct crypto_shash *child = ctx->child;
+ struct crypto_ahash *child = ctx->child;
int err;
- crypto_shash_clear_flags(child, CRYPTO_TFM_REQ_MASK);
- crypto_shash_set_flags(child, crypto_ahash_get_flags(parent) &
+ crypto_ahash_clear_flags(child, CRYPTO_TFM_REQ_MASK);
+ crypto_ahash_set_flags(child, crypto_ahash_get_flags(parent) &
CRYPTO_TFM_REQ_MASK);
- err = crypto_shash_setkey(child, key, keylen);
- crypto_ahash_set_flags(parent, crypto_shash_get_flags(child) &
+ err = crypto_ahash_setkey(child, key, keylen);
+ crypto_ahash_set_flags(parent, crypto_ahash_get_flags(child) &
CRYPTO_TFM_RES_MASK);
return err;
}
@@ -331,20 +331,21 @@ static int mcryptd_hash_enqueue(struct ahash_request *req,
static void mcryptd_hash_init(struct crypto_async_request *req_async, int err)
{
struct mcryptd_hash_ctx *ctx = crypto_tfm_ctx(req_async->tfm);
- struct crypto_shash *child = ctx->child;
+ struct crypto_ahash *child = ctx->child;
struct ahash_request *req = ahash_request_cast(req_async);
struct mcryptd_hash_request_ctx *rctx = ahash_request_ctx(req);
- struct shash_desc *desc = &rctx->desc;
+ struct ahash_request *desc = &rctx->areq;
if (unlikely(err == -EINPROGRESS))
goto out;
- desc->tfm = child;
- desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP;
+ ahash_request_set_tfm(desc, child);
+ ahash_request_set_callback(desc, CRYPTO_TFM_REQ_MAY_SLEEP, NULL, NULL);
- err = crypto_shash_init(desc);
+ err = crypto_ahash_init(desc);
req->base.complete = rctx->complete;
+ rctx->out = req->result;
out:
local_bh_disable();
@@ -365,7 +366,8 @@ static void mcryptd_hash_update(struct crypto_async_request *req_async, int err)
if (unlikely(err == -EINPROGRESS))
goto out;
- err = shash_ahash_mcryptd_update(req, &rctx->desc);
+ rctx->out = req->result;
+ err = ahash_mcryptd_update(&rctx->areq);
if (err) {
req->base.complete = rctx->complete;
goto out;
@@ -391,7 +393,8 @@ static void mcryptd_hash_final(struct crypto_async_request *req_async, int err)
if (unlikely(err == -EINPROGRESS))
goto out;
- err = shash_ahash_mcryptd_final(req, &rctx->desc);
+ rctx->out = req->result;
+ err = ahash_mcryptd_final(&rctx->areq);
if (err) {
req->base.complete = rctx->complete;
goto out;
@@ -416,8 +419,8 @@ static void mcryptd_hash_finup(struct crypto_async_request *req_async, int err)
if (unlikely(err == -EINPROGRESS))
goto out;
-
- err = shash_ahash_mcryptd_finup(req, &rctx->desc);
+ rctx->out = req->result;
+ err = ahash_mcryptd_finup(&rctx->areq);
if (err) {
req->base.complete = rctx->complete;
@@ -439,18 +442,19 @@ static int mcryptd_hash_finup_enqueue(struct ahash_request *req)
static void mcryptd_hash_digest(struct crypto_async_request *req_async, int err)
{
struct mcryptd_hash_ctx *ctx = crypto_tfm_ctx(req_async->tfm);
- struct crypto_shash *child = ctx->child;
+ struct crypto_ahash *child = ctx->child;
struct ahash_request *req = ahash_request_cast(req_async);
struct mcryptd_hash_request_ctx *rctx = ahash_request_ctx(req);
- struct shash_desc *desc = &rctx->desc;
+ struct ahash_request *desc = &rctx->areq;
if (unlikely(err == -EINPROGRESS))
goto out;
- desc->tfm = child;
- desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP; /* check this again */
+ ahash_request_set_tfm(desc, child);
+ ahash_request_set_callback(desc, CRYPTO_TFM_REQ_MAY_SLEEP, NULL, NULL);
- err = shash_ahash_mcryptd_digest(req, desc);
+ rctx->out = req->result;
+ err = ahash_mcryptd_digest(desc);
if (err) {
req->base.complete = rctx->complete;
@@ -473,14 +477,14 @@ static int mcryptd_hash_export(struct ahash_request *req, void *out)
{
struct mcryptd_hash_request_ctx *rctx = ahash_request_ctx(req);
- return crypto_shash_export(&rctx->desc, out);
+ return crypto_ahash_export(&rctx->areq, out);
}
static int mcryptd_hash_import(struct ahash_request *req, const void *in)
{
struct mcryptd_hash_request_ctx *rctx = ahash_request_ctx(req);
- return crypto_shash_import(&rctx->desc, in);
+ return crypto_ahash_import(&rctx->areq, in);
}
static int mcryptd_create_hash(struct crypto_template *tmpl, struct rtattr **tb,
@@ -488,7 +492,7 @@ static int mcryptd_create_hash(struct crypto_template *tmpl, struct rtattr **tb,
{
struct hashd_instance_ctx *ctx;
struct ahash_instance *inst;
- struct shash_alg *salg;
+ struct hash_alg_common *halg;
struct crypto_alg *alg;
u32 type = 0;
u32 mask = 0;
@@ -496,11 +500,11 @@ static int mcryptd_create_hash(struct crypto_template *tmpl, struct rtattr **tb,
mcryptd_check_internal(tb, &type, &mask);
- salg = shash_attr_alg(tb[1], type, mask);
- if (IS_ERR(salg))
- return PTR_ERR(salg);
+ halg = ahash_attr_alg(tb[1], type, mask);
+ if (IS_ERR(halg))
+ return PTR_ERR(halg);
- alg = &salg->base;
+ alg = &halg->base;
pr_debug("crypto: mcryptd hash alg: %s\n", alg->cra_name);
inst = mcryptd_alloc_instance(alg, ahash_instance_headroom(),
sizeof(*ctx));
@@ -511,7 +515,7 @@ static int mcryptd_create_hash(struct crypto_template *tmpl, struct rtattr **tb,
ctx = ahash_instance_ctx(inst);
ctx->queue = queue;
- err = crypto_init_shash_spawn(&ctx->spawn, salg,
+ err = crypto_init_ahash_spawn(&ctx->spawn, halg,
ahash_crypto_instance(inst));
if (err)
goto out_free_inst;
@@ -521,8 +525,8 @@ static int mcryptd_create_hash(struct crypto_template *tmpl, struct rtattr **tb,
type |= CRYPTO_ALG_INTERNAL;
inst->alg.halg.base.cra_flags = type;
- inst->alg.halg.digestsize = salg->digestsize;
- inst->alg.halg.statesize = salg->statesize;
+ inst->alg.halg.digestsize = halg->digestsize;
+ inst->alg.halg.statesize = halg->statesize;
inst->alg.halg.base.cra_ctxsize = sizeof(struct mcryptd_hash_ctx);
inst->alg.halg.base.cra_init = mcryptd_hash_init_tfm;
@@ -539,7 +543,7 @@ static int mcryptd_create_hash(struct crypto_template *tmpl, struct rtattr **tb,
err = ahash_register_instance(tmpl, inst);
if (err) {
- crypto_drop_shash(&ctx->spawn);
+ crypto_drop_ahash(&ctx->spawn);
out_free_inst:
kfree(inst);
}
@@ -575,7 +579,7 @@ static void mcryptd_free(struct crypto_instance *inst)
switch (inst->alg.cra_flags & CRYPTO_ALG_TYPE_MASK) {
case CRYPTO_ALG_TYPE_AHASH:
- crypto_drop_shash(&hctx->spawn);
+ crypto_drop_ahash(&hctx->spawn);
kfree(ahash_instance(inst));
return;
default:
@@ -612,55 +616,38 @@ struct mcryptd_ahash *mcryptd_alloc_ahash(const char *alg_name,
}
EXPORT_SYMBOL_GPL(mcryptd_alloc_ahash);
-int shash_ahash_mcryptd_digest(struct ahash_request *req,
- struct shash_desc *desc)
+int ahash_mcryptd_digest(struct ahash_request *desc)
{
int err;
- err = crypto_shash_init(desc) ?:
- shash_ahash_mcryptd_finup(req, desc);
+ err = crypto_ahash_init(desc) ?:
+ ahash_mcryptd_finup(desc);
return err;
}
-EXPORT_SYMBOL_GPL(shash_ahash_mcryptd_digest);
-int shash_ahash_mcryptd_update(struct ahash_request *req,
- struct shash_desc *desc)
+int ahash_mcryptd_update(struct ahash_request *desc)
{
- struct crypto_shash *tfm = desc->tfm;
- struct shash_alg *shash = crypto_shash_alg(tfm);
-
/* alignment is to be done by multi-buffer crypto algorithm if needed */
- return shash->update(desc, NULL, 0);
+ return crypto_ahash_update(desc);
}
-EXPORT_SYMBOL_GPL(shash_ahash_mcryptd_update);
-int shash_ahash_mcryptd_finup(struct ahash_request *req,
- struct shash_desc *desc)
+int ahash_mcryptd_finup(struct ahash_request *desc)
{
- struct crypto_shash *tfm = desc->tfm;
- struct shash_alg *shash = crypto_shash_alg(tfm);
-
/* alignment is to be done by multi-buffer crypto algorithm if needed */
- return shash->finup(desc, NULL, 0, req->result);
+ return crypto_ahash_finup(desc);
}
-EXPORT_SYMBOL_GPL(shash_ahash_mcryptd_finup);
-int shash_ahash_mcryptd_final(struct ahash_request *req,
- struct shash_desc *desc)
+int ahash_mcryptd_final(struct ahash_request *desc)
{
- struct crypto_shash *tfm = desc->tfm;
- struct shash_alg *shash = crypto_shash_alg(tfm);
-
/* alignment is to be done by multi-buffer crypto algorithm if needed */
- return shash->final(desc, req->result);
+ return crypto_ahash_final(desc);
}
-EXPORT_SYMBOL_GPL(shash_ahash_mcryptd_final);
-struct crypto_shash *mcryptd_ahash_child(struct mcryptd_ahash *tfm)
+struct crypto_ahash *mcryptd_ahash_child(struct mcryptd_ahash *tfm)
{
struct mcryptd_hash_ctx *ctx = crypto_ahash_ctx(&tfm->base);
@@ -668,12 +655,12 @@ struct crypto_shash *mcryptd_ahash_child(struct mcryptd_ahash *tfm)
}
EXPORT_SYMBOL_GPL(mcryptd_ahash_child);
-struct shash_desc *mcryptd_shash_desc(struct ahash_request *req)
+struct ahash_request *mcryptd_ahash_desc(struct ahash_request *req)
{
struct mcryptd_hash_request_ctx *rctx = ahash_request_ctx(req);
- return &rctx->desc;
+ return &rctx->areq;
}
-EXPORT_SYMBOL_GPL(mcryptd_shash_desc);
+EXPORT_SYMBOL_GPL(mcryptd_ahash_desc);
void mcryptd_free_ahash(struct mcryptd_ahash *tfm)
{
@@ -681,7 +668,6 @@ void mcryptd_free_ahash(struct mcryptd_ahash *tfm)
}
EXPORT_SYMBOL_GPL(mcryptd_free_ahash);
-
static int __init mcryptd_init(void)
{
int err, cpu;
diff --git a/include/crypto/internal/hash.h b/include/crypto/internal/hash.h
index 49dae16..1d4f365 100644
--- a/include/crypto/internal/hash.h
+++ b/include/crypto/internal/hash.h
@@ -114,14 +114,10 @@ int shash_ahash_update(struct ahash_request *req, struct shash_desc *desc);
int shash_ahash_finup(struct ahash_request *req, struct shash_desc *desc);
int shash_ahash_digest(struct ahash_request *req, struct shash_desc *desc);
-int shash_ahash_mcryptd_update(struct ahash_request *req,
- struct shash_desc *desc);
-int shash_ahash_mcryptd_final(struct ahash_request *req,
- struct shash_desc *desc);
-int shash_ahash_mcryptd_finup(struct ahash_request *req,
- struct shash_desc *desc);
-int shash_ahash_mcryptd_digest(struct ahash_request *req,
- struct shash_desc *desc);
+int ahash_mcryptd_update(struct ahash_request *desc);
+int ahash_mcryptd_final(struct ahash_request *desc);
+int ahash_mcryptd_finup(struct ahash_request *desc);
+int ahash_mcryptd_digest(struct ahash_request *desc);
int crypto_init_shash_ops_async(struct crypto_tfm *tfm);
diff --git a/include/crypto/mcryptd.h b/include/crypto/mcryptd.h
index c23ee1f..4a53c0d 100644
--- a/include/crypto/mcryptd.h
+++ b/include/crypto/mcryptd.h
@@ -39,7 +39,7 @@ struct mcryptd_instance_ctx {
};
struct mcryptd_hash_ctx {
- struct crypto_shash *child;
+ struct crypto_ahash *child;
struct mcryptd_alg_state *alg_state;
};
@@ -59,13 +59,13 @@ struct mcryptd_hash_request_ctx {
struct crypto_hash_walk walk;
u8 *out;
int flag;
- struct shash_desc desc;
+ struct ahash_request areq;
};
struct mcryptd_ahash *mcryptd_alloc_ahash(const char *alg_name,
u32 type, u32 mask);
-struct crypto_shash *mcryptd_ahash_child(struct mcryptd_ahash *tfm);
-struct shash_desc *mcryptd_shash_desc(struct ahash_request *req);
+struct crypto_ahash *mcryptd_ahash_child(struct mcryptd_ahash *tfm);
+struct ahash_request *mcryptd_ahash_desc(struct ahash_request *req);
void mcryptd_free_ahash(struct mcryptd_ahash *tfm);
void mcryptd_flusher(struct work_struct *work);
--
1.9.1
^ permalink raw reply related
* [PATCH] crypto: qat: Remove deprecated create_workqueue
From: Bhaktipriya Shridhar @ 2016-06-07 21:17 UTC (permalink / raw)
To: Tadeusz Struk, Herbert Xu, David S. Miller, Julia Lawall,
Conor McLoughlin, Pingchao Yang, Ahsan Atta, John Griffin,
Wu Fengguang
Cc: Tejun Heo, qat-linux, linux-crypto, linux-kernel
alloc_workqueue replaces deprecated create_workqueue().
The workqueue device_reset_wq has workitem &reset_data->reset_work per
adf_reset_dev_data. The workqueue pf2vf_resp_wq is a workqueue for
PF2VF responses has workitem &pf2vf_resp->pf2vf_resp_work per pf2vf_resp.
The workqueue adf_vf_stop_wq is used to call adf_dev_stop()
asynchronously.
Dedicated workqueues have been used in all cases since the workitems
on the workqueues are involved in operation of crypto which can be used in
the IO path which is depended upon during memory reclaim. Hence,
WQ_MEM_RECLAIM has been set to gurantee forward progress under memory
pressure.
Since there are only a fixed number of work items, explicit concurrency
limit is unnecessary.
Signed-off-by: Bhaktipriya Shridhar <bhaktipriya96@gmail.com>
---
drivers/crypto/qat/qat_common/adf_aer.c | 3 ++-
drivers/crypto/qat/qat_common/adf_sriov.c | 2 +-
drivers/crypto/qat/qat_common/adf_vf_isr.c | 2 +-
3 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/drivers/crypto/qat/qat_common/adf_aer.c b/drivers/crypto/qat/qat_common/adf_aer.c
index b40d9c8..7bfb57f 100644
--- a/drivers/crypto/qat/qat_common/adf_aer.c
+++ b/drivers/crypto/qat/qat_common/adf_aer.c
@@ -243,7 +243,8 @@ EXPORT_SYMBOL_GPL(adf_disable_aer);
int adf_init_aer(void)
{
- device_reset_wq = create_workqueue("qat_device_reset_wq");
+ device_reset_wq = alloc_workqueue("qat_device_reset_wq",
+ WQ_MEM_RECLAIM, 0);
return !device_reset_wq ? -EFAULT : 0;
}
diff --git a/drivers/crypto/qat/qat_common/adf_sriov.c b/drivers/crypto/qat/qat_common/adf_sriov.c
index 4a526e2..9320ae1 100644
--- a/drivers/crypto/qat/qat_common/adf_sriov.c
+++ b/drivers/crypto/qat/qat_common/adf_sriov.c
@@ -292,7 +292,7 @@ EXPORT_SYMBOL_GPL(adf_sriov_configure);
int __init adf_init_pf_wq(void)
{
/* Workqueue for PF2VF responses */
- pf2vf_resp_wq = create_workqueue("qat_pf2vf_resp_wq");
+ pf2vf_resp_wq = alloc_workqueue("qat_pf2vf_resp_wq", WQ_MEM_RECLAIM, 0);
return !pf2vf_resp_wq ? -ENOMEM : 0;
}
diff --git a/drivers/crypto/qat/qat_common/adf_vf_isr.c b/drivers/crypto/qat/qat_common/adf_vf_isr.c
index aa689ca..bf99e11 100644
--- a/drivers/crypto/qat/qat_common/adf_vf_isr.c
+++ b/drivers/crypto/qat/qat_common/adf_vf_isr.c
@@ -321,7 +321,7 @@ EXPORT_SYMBOL_GPL(adf_vf_isr_resource_alloc);
int __init adf_init_vf_wq(void)
{
- adf_vf_stop_wq = create_workqueue("adf_vf_stop_wq");
+ adf_vf_stop_wq = alloc_workqueue("adf_vf_stop_wq", WQ_MEM_RECLAIM, 0);
return !adf_vf_stop_wq ? -EFAULT : 0;
}
^ permalink raw reply related
* Re: [PATCH 0/2] hwrng: chaoskey - Add support for Araneus Alea I USB RNG
From: Greg KH @ 2016-06-07 22:03 UTC (permalink / raw)
To: Herbert Xu
Cc: Bob Ham, linux-crypto, linux-usb, Keith Packard, Matt Mackall,
Clemens Ladisch
In-Reply-To: <20160607105345.GE520@gondor.apana.org.au>
On Tue, Jun 07, 2016 at 06:53:45PM +0800, Herbert Xu wrote:
> On Fri, Jun 03, 2016 at 12:13:06PM +0100, Bob Ham wrote:
> > Two patches to add support for the Araneus Alea I USB RNG to the
> > chaoskey driver. The first simply includes the Alea I as a device,
> > the second fixes an issue with the timeout on the first read.
> >
> > Bob Ham (2):
> > hwrng: chaoskey - Add support for Araneus Alea I USB RNG
> > hwrng: chaoskey - Fix URB warning due to timeout on Alea
> >
> > drivers/usb/misc/Kconfig | 11 ++++++-----
> > drivers/usb/misc/chaoskey.c | 21 +++++++++++++++++++--
> > 2 files changed, 25 insertions(+), 7 deletions(-)
>
> Both applied. Thanks.
Ok, but usually drivers/usb/misc/ patches go through my tree :)
^ permalink raw reply
* Re: [PATCH v6 3/6] crypto: AF_ALG -- add asymmetric cipher interface
From: Mat Martineau @ 2016-06-08 0:28 UTC (permalink / raw)
To: smueller
Cc: Tadeusz Struk, dhowells, herbert, linux-api, marcel, linux-kernel,
keyrings, linux-crypto, dwmw2, davem
In-Reply-To: <20160515041701.15888.53830.stgit@tstruk-mobl1>
Stephan,
On Sat, 14 May 2016, Tadeusz Struk wrote:
> From: Stephan Mueller <smueller@chronox.de>
>
> This patch adds the user space interface for asymmetric ciphers. The
> interface allows the use of sendmsg as well as vmsplice to provide data.
>
> This version has been rebased on top of 4.6 and a few chackpatch issues
> have been fixed.
>
> Signed-off-by: Stephan Mueller <smueller@chronox.de>
> Signed-off-by: Tadeusz Struk <tadeusz.struk@intel.com>
> ---
> diff --git a/crypto/algif_akcipher.c b/crypto/algif_akcipher.c
> new file mode 100644
> index 0000000..6342b6e
> --- /dev/null
> +++ b/crypto/algif_akcipher.c
> +
> +static int akcipher_recvmsg(struct socket *sock, struct msghdr *msg,
> + size_t ignored, int flags)
> +{
> + struct sock *sk = sock->sk;
> + struct alg_sock *ask = alg_sk(sk);
> + struct akcipher_ctx *ctx = ask->private;
> + struct akcipher_sg_list *sgl = &ctx->tsgl;
> + unsigned int i = 0;
> + int err;
> + unsigned long used = 0;
> + size_t usedpages = 0;
> + unsigned int cnt = 0;
> +
> + /* Limit number of IOV blocks to be accessed below */
> + if (msg->msg_iter.nr_segs > ALG_MAX_PAGES)
> + return -ENOMSG;
> +
> + lock_sock(sk);
> +
> + if (ctx->more) {
> + err = akcipher_wait_for_data(sk, flags);
> + if (err)
> + goto unlock;
> + }
> +
> + used = ctx->used;
> +
> + /* convert iovecs of output buffers into scatterlists */
> + while (iov_iter_count(&msg->msg_iter)) {
> + /* make one iovec available as scatterlist */
> + err = af_alg_make_sg(&ctx->rsgl[cnt], &msg->msg_iter,
> + iov_iter_count(&msg->msg_iter));
> + if (err < 0)
> + goto unlock;
> + usedpages += err;
> + /* chain the new scatterlist with previous one */
> + if (cnt)
> + af_alg_link_sg(&ctx->rsgl[cnt - 1], &ctx->rsgl[cnt]);
> +
> + iov_iter_advance(&msg->msg_iter, err);
> + cnt++;
> + }
> +
> + /* ensure output buffer is sufficiently large */
> + if (usedpages < akcipher_calcsize(ctx)) {
> + err = -EMSGSIZE;
> + goto unlock;
> + }
Why is the size of the output buffer enforced here instead of depending on
the algorithm implementation?
Thanks,
Mat
> + sg_mark_end(sgl->sg + sgl->cur - 1);
> +
> + akcipher_request_set_crypt(&ctx->req, sgl->sg, ctx->rsgl[0].sg, used,
> + usedpages);
> + switch (ctx->op) {
> + case ALG_OP_VERIFY:
> + err = crypto_akcipher_verify(&ctx->req);
> + break;
> + case ALG_OP_SIGN:
> + err = crypto_akcipher_sign(&ctx->req);
> + break;
> + case ALG_OP_ENCRYPT:
> + err = crypto_akcipher_encrypt(&ctx->req);
> + break;
> + case ALG_OP_DECRYPT:
> + err = crypto_akcipher_decrypt(&ctx->req);
> + break;
> + default:
> + err = -EFAULT;
> + goto unlock;
> + }
> +
> + err = af_alg_wait_for_completion(err, &ctx->completion);
> +
> + if (err) {
> + /* EBADMSG implies a valid cipher operation took place */
> + if (err == -EBADMSG)
> + akcipher_put_sgl(sk);
> + goto unlock;
> + }
> +
> + akcipher_put_sgl(sk);
> +
> +unlock:
> + for (i = 0; i < cnt; i++)
> + af_alg_free_sg(&ctx->rsgl[i]);
> +
> + akcipher_wmem_wakeup(sk);
> + release_sock(sk);
> +
> + return err ? err : ctx->req.dst_len;
> +}
--
Mat Martineau
Intel OTC
^ permalink raw reply
* Re: [PATCH 0/2] hwrng: chaoskey - Add support for Araneus Alea I USB RNG
From: Herbert Xu @ 2016-06-08 0:49 UTC (permalink / raw)
To: Greg KH
Cc: Bob Ham, linux-crypto-u79uwXL29TY76Z2rM5mHXA,
linux-usb-u79uwXL29TY76Z2rM5mHXA, Keith Packard, Matt Mackall,
Clemens Ladisch
In-Reply-To: <20160607220311.GB4744-U8xfFu+wG4EAvxtiuMwx3w@public.gmane.org>
On Tue, Jun 07, 2016 at 03:03:11PM -0700, Greg KH wrote:
>
> Ok, but usually drivers/usb/misc/ patches go through my tree :)
Sorry. But I do wonder whether this driver should be moved as
it is just an hwrng device like every other driver under hw_random,
except for the fact that it happens to be a USB physical device.
Cheers,
--
Email: Herbert Xu <herbert-lOAM2aK0SrRLBo1qDEOMRrpzq4S04n8Q@public.gmane.org>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH 0/2] hwrng: chaoskey - Add support for Araneus Alea I USB RNG
From: Greg KH @ 2016-06-08 1:34 UTC (permalink / raw)
To: Herbert Xu
Cc: Bob Ham, linux-crypto-u79uwXL29TY76Z2rM5mHXA,
linux-usb-u79uwXL29TY76Z2rM5mHXA, Keith Packard, Matt Mackall,
Clemens Ladisch
In-Reply-To: <20160608004954.GA11545-lOAM2aK0SrRLBo1qDEOMRrpzq4S04n8Q@public.gmane.org>
On Wed, Jun 08, 2016 at 08:49:55AM +0800, Herbert Xu wrote:
> On Tue, Jun 07, 2016 at 03:03:11PM -0700, Greg KH wrote:
> >
> > Ok, but usually drivers/usb/misc/ patches go through my tree :)
>
> Sorry. But I do wonder whether this driver should be moved as
> it is just an hwrng device like every other driver under hw_random,
> except for the fact that it happens to be a USB physical device.
That's fine with me, but it uses the usb misc device major number,
unlike other hw_random drivers, so that might get messy.
It's your call...
thanks,
greg k-h
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [RFC v4 2/4] crypto: Introduce CRYPTO_ALG_BULK flag
From: Baolin Wang @ 2016-06-08 2:00 UTC (permalink / raw)
To: Herbert Xu
Cc: Jens Axboe, Alasdair G Kergon, Mike Snitzer,
open list:DEVICE-MAPPER (LVM), David Miller, Eric Biggers,
Joonsoo Kim, tadeusz.struk, smueller, Masanari Iida, Shaohua Li,
Dan Williams, Martin K. Petersen, Sagi Grimberg, Kent Overstreet,
Keith Busch, Tejun Heo, Ming Lei, Mark Brown, Arnd Bergmann,
linux-crypto, linux-block,
open list:SOFTWARE RAID (Multiple Disks) SUPPORT, LKML
In-Reply-To: <20160607141613.GA2237@gondor.apana.org.au>
Hi Herbert,
On 7 June 2016 at 22:16, Herbert Xu <herbert@gondor.apana.org.au> wrote:
> On Tue, Jun 07, 2016 at 08:17:05PM +0800, Baolin Wang wrote:
>> Now some cipher hardware engines prefer to handle bulk block rather than one
>> sector (512 bytes) created by dm-crypt, cause these cipher engines can handle
>> the intermediate values (IV) by themselves in one bulk block. This means we
>> can increase the size of the request by merging request rather than always 512
>> bytes and thus increase the hardware engine processing speed.
>>
>> So introduce 'CRYPTO_ALG_BULK' flag to indicate this cipher can support bulk
>> mode.
>>
>> Signed-off-by: Baolin Wang <baolin.wang@linaro.org>
>
> Nack. As I said before, please do it using explicit IV generators
> like we do for IPsec.
OK. I would like to try your suggestion. Thanks.
> --
> Email: Herbert Xu <herbert@gondor.apana.org.au>
> Home Page: http://gondor.apana.org.au/~herbert/
> PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
--
Baolin.wang
Best Regards
^ permalink raw reply
* Re: [RFC] DRBG: which shall be default?
From: Herbert Xu @ 2016-06-08 2:41 UTC (permalink / raw)
To: Stephan Mueller; +Cc: linux-crypto
In-Reply-To: <1580741.tpUX5Z7OKy@tauon.atsec.com>
On Thu, Jun 02, 2016 at 02:06:55PM +0200, Stephan Mueller wrote:
>
> I am working on it. During the analysis, I saw, however, that the DRBG
> increments the counter before the encryption whereas the the CTR mode
> increments it after the encryption.
>
> I could of course adjust the handling in the code, but this would be a real
> hack IMHO.
Changing the order of increment is equivalent to changing the IV, no?
Cheers,
--
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply
* Re: [PATCH v5 1/3] crypto: Key-agreement Protocol Primitives API (KPP)
From: Herbert Xu @ 2016-06-08 2:54 UTC (permalink / raw)
To: Benedetto, Salvatore; +Cc: linux-crypto@vger.kernel.org
In-Reply-To: <309B30E91F5E2846B79BD9AA9711D031930814@IRSMSX102.ger.corp.intel.com>
On Thu, Jun 02, 2016 at 12:06:48PM +0000, Benedetto, Salvatore wrote:
>
> Off the top of my head, with ECDH when the user gets a EGAIN, he wants
> to reset the secret key only, not the params.
I don't see any performance benefit in changing one and not the
other. Besides, you could always check the params in the algo
and only update if necessary.
> > > * generate_public_key() - It generates the public key to be sent to
> > > the other counterpart involved in the key-agreement session. The
> > > function has to be called after set_params() and set_secret()
> > > * generate_secret() - It generates the shared secret for the session
> >
> > Ditto, we only need one operation and that is multiplication by the secret.
>
> Sorry, but I don't understand your point.
> We do always need one math operation with different params.
Look at your actual implementations of DH and ECDH, they are the
same except for the multiplicand, which is fixed to G for the
public key.
Now you could argue that having to reparse G every time could be
bad for performance, but that's easily fixed by making the case
of a zero-length input value an implicit request to use G.
Even better, just drop G from the params and you won't need to
reparse it or do anything special.
The point of all this is to make the lives of future driver authors
simpler, the less they have to do the less that could go wrong.
Cheers,
--
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply
* Re: [PATCH v2 3/4] crypto: kdf - SP800-108 Key Derivation Function
From: Herbert Xu @ 2016-06-08 3:13 UTC (permalink / raw)
To: Stephan Mueller; +Cc: linux-crypto, David Howells, Mat Martineau, keyrings
In-Reply-To: <20634336.6yV5j7Wfmz@tauon.atsec.com>
On Thu, Jun 02, 2016 at 05:12:20PM +0200, Stephan Mueller wrote:
>
> The KDFs are usually used for output sizes between one and 4 keys. So,
> commonly it is expected that not more than 200 or 300 bytes are generated by
> one call. But you cannot be sure how much data a user wants. The spec allows
> that the user generates up to 2^50 or so bytes. The implementation I offer is
> limited to unsigned int bytes.
>
> Note, if one would implement a key ladder, it can be expected that many keys
> are generated from one KDF seed.
>
> I tried to avoid memcpy for speed purposes. And all the user needs to do is to
> not invoke an in-place crypto operation.
>
> Maybe I should copy the input data into a private memory location so that the
> KDF can be used like any other cipher: the caller uses a reference to the
> instance to generate data where the caller does not need to ensure that some
> initial data must be left at some specific place.
OK. I don't think the RNG API really guarantees that you can do
in-place generation anyway. So don't even bother checking for
src == dst.
When you submit this again can you please send it along with a
user?
Thanks,
--
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply
* Re: [PATCH v2 3/4] crypto: kdf - SP800-108 Key Derivation Function
From: Stephan Mueller @ 2016-06-08 4:58 UTC (permalink / raw)
To: Herbert Xu; +Cc: linux-crypto, David Howells, Mat Martineau, keyrings
In-Reply-To: <20160608031334.GC12283@gondor.apana.org.au>
Am Mittwoch, 8. Juni 2016, 11:13:34 schrieb Herbert Xu:
Hi Herbert,
> OK. I don't think the RNG API really guarantees that you can do
> in-place generation anyway. So don't even bother checking for
> src == dst.
Ok, I will remove the check.
>
> When you submit this again can you please send it along with a
> user?
Yes, I will.
Ciao
Stephan
^ permalink raw reply
* Re: [PATCH v6 3/6] crypto: AF_ALG -- add asymmetric cipher interface
From: Stephan Mueller @ 2016-06-08 5:31 UTC (permalink / raw)
To: Mat Martineau
Cc: Tadeusz Struk, dhowells, herbert, linux-api, marcel, linux-kernel,
keyrings, linux-crypto, dwmw2, davem
In-Reply-To: <alpine.OSX.2.20.1606071719170.9891@mjmartin-mac01.local>
Am Dienstag, 7. Juni 2016, 17:28:07 schrieb Mat Martineau:
Hi Mat,
> > + used = ctx->used;
> > +
> > + /* convert iovecs of output buffers into scatterlists */
> > + while (iov_iter_count(&msg->msg_iter)) {
> > + /* make one iovec available as scatterlist */
> > + err = af_alg_make_sg(&ctx->rsgl[cnt], &msg->msg_iter,
> > + iov_iter_count(&msg->msg_iter));
> > + if (err < 0)
> > + goto unlock;
> > + usedpages += err;
> > + /* chain the new scatterlist with previous one */
> > + if (cnt)
> > + af_alg_link_sg(&ctx->rsgl[cnt - 1], &ctx->rsgl[cnt]);
> > +
> > + iov_iter_advance(&msg->msg_iter, err);
> > + cnt++;
> > + }
> > +
> > + /* ensure output buffer is sufficiently large */
> > + if (usedpages < akcipher_calcsize(ctx)) {
> > + err = -EMSGSIZE;
> > + goto unlock;
> > + }
>
> Why is the size of the output buffer enforced here instead of depending on
> the algorithm implementation?
akcipher_calcsize calls crypto_akcipher_maxsize to get the maximum size the
algorithm generates as output during its operation.
The code ensures that the caller provided at least that amount of memory for
the kernel to store its data in. This check therefore is present to ensure the
kernel does not overstep memory boundaries in user space.
What is your concern?
Thanks
Ciao
Stephan
^ permalink raw reply
* Re: [RFC] DRBG: which shall be default?
From: Stephan Mueller @ 2016-06-08 7:56 UTC (permalink / raw)
To: Herbert Xu; +Cc: linux-crypto
In-Reply-To: <20160608024140.GA12283@gondor.apana.org.au>
Am Mittwoch, 8. Juni 2016, 10:41:40 schrieb Herbert Xu:
Hi Herbert,
> On Thu, Jun 02, 2016 at 02:06:55PM +0200, Stephan Mueller wrote:
> > I am working on it. During the analysis, I saw, however, that the DRBG
> > increments the counter before the encryption whereas the the CTR mode
> > increments it after the encryption.
> >
> > I could of course adjust the handling in the code, but this would be a
> > real
> > hack IMHO.
>
> Changing the order of increment is equivalent to changing the IV, no?
I finally got it working. All I needed to do is to add a crypto_inc(V) after a
recalculation of V.
The performance with ctr-aes-aesni on 64 bit is as follows -- I used my LRNG
implementation for testing for which I already have performance measurements:
- generating smaller lengths (I tested up to 128 bytes) of random numbers
(which is the vast majority of random numbers to be generated), the
performance is even worse by 10 to 15%
- generating larger lengths (tested with 4096 bytes) of random numbers, the
performance increases by 3%
Using ctr(aes-aesni) on 32 bit, the numbers are generally worse by 5 to 10%.
So, with these numbers, I would conclude that switching to the CTR mode is not
worthwhile.
Ciao
Stephan
^ permalink raw reply
* Re: [RFC] DRBG: which shall be default?
From: Stephan Mueller @ 2016-06-08 8:00 UTC (permalink / raw)
To: Herbert Xu; +Cc: linux-crypto
In-Reply-To: <7330387.0ZS018HYJD@positron.chronox.de>
Am Mittwoch, 8. Juni 2016, 09:56:42 schrieb Stephan Mueller:
Hi Stephan,
> Am Mittwoch, 8. Juni 2016, 10:41:40 schrieb Herbert Xu:
>
> Hi Herbert,
>
> > On Thu, Jun 02, 2016 at 02:06:55PM +0200, Stephan Mueller wrote:
> > > I am working on it. During the analysis, I saw, however, that the DRBG
> > > increments the counter before the encryption whereas the the CTR mode
> > > increments it after the encryption.
> > >
> > > I could of course adjust the handling in the code, but this would be a
> > > real
> > > hack IMHO.
> >
> > Changing the order of increment is equivalent to changing the IV, no?
>
> I finally got it working. All I needed to do is to add a crypto_inc(V) after
> a recalculation of V.
One addition: my NULL vector is 128 bytes in size.
>
> The performance with ctr-aes-aesni on 64 bit is as follows -- I used my LRNG
> implementation for testing for which I already have performance
> measurements:
>
> - generating smaller lengths (I tested up to 128 bytes) of random numbers
> (which is the vast majority of random numbers to be generated), the
> performance is even worse by 10 to 15%
>
> - generating larger lengths (tested with 4096 bytes) of random numbers, the
> performance increases by 3%
>
> Using ctr(aes-aesni) on 32 bit, the numbers are generally worse by 5 to 10%.
>
> So, with these numbers, I would conclude that switching to the CTR mode is
> not worthwhile.
>
> Ciao
> Stephan
> --
> To unsubscribe from this list: send the line "unsubscribe linux-crypto" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
Ciao
Stephan
^ permalink raw reply
* Re: [RFC] DRBG: which shall be default?
From: Herbert Xu @ 2016-06-08 8:00 UTC (permalink / raw)
To: Stephan Mueller; +Cc: linux-crypto
In-Reply-To: <7330387.0ZS018HYJD@positron.chronox.de>
On Wed, Jun 08, 2016 at 09:56:42AM +0200, Stephan Mueller wrote:
>
> The performance with ctr-aes-aesni on 64 bit is as follows -- I used my LRNG
> implementation for testing for which I already have performance measurements:
>
> - generating smaller lengths (I tested up to 128 bytes) of random numbers
> (which is the vast majority of random numbers to be generated), the
> performance is even worse by 10 to 15%
>
> - generating larger lengths (tested with 4096 bytes) of random numbers, the
> performance increases by 3%
>
> Using ctr(aes-aesni) on 32 bit, the numbers are generally worse by 5 to 10%.
ctr(aes-aesni) is not the same thing as ctr-aes-aesni, the former
being just another way of doing what you were doing. So did you
actually test the real optimised version which is ctr-aes-aesni?
Thanks,
--
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply
* [PATCH v6 3/8] crypto: acomp - add support for lzo via scomp
From: Giovanni Cabiddu @ 2016-06-08 8:16 UTC (permalink / raw)
To: herbert; +Cc: linux-crypto, Giovanni Cabiddu
In-Reply-To: <1465373818-29720-1-git-send-email-giovanni.cabiddu@intel.com>
This patch implements an scomp backend for the lzo compression algorithm.
This way, lzo is exposed through the acomp api.
Signed-off-by: Giovanni Cabiddu <giovanni.cabiddu@intel.com>
---
crypto/Kconfig | 1 +
crypto/lzo.c | 97 +++++++++++++++++++++++++++++++++++++++++++++++---------
2 files changed, 83 insertions(+), 15 deletions(-)
diff --git a/crypto/Kconfig b/crypto/Kconfig
index 24fef55..08075c1 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -1513,6 +1513,7 @@ config CRYPTO_DEFLATE
config CRYPTO_LZO
tristate "LZO compression algorithm"
select CRYPTO_ALGAPI
+ select CRYPTO_ACOMP2
select LZO_COMPRESS
select LZO_DECOMPRESS
help
diff --git a/crypto/lzo.c b/crypto/lzo.c
index c3f3dd9..168df78 100644
--- a/crypto/lzo.c
+++ b/crypto/lzo.c
@@ -22,40 +22,55 @@
#include <linux/vmalloc.h>
#include <linux/mm.h>
#include <linux/lzo.h>
+#include <crypto/internal/scompress.h>
struct lzo_ctx {
void *lzo_comp_mem;
};
+static void *lzo_alloc_ctx(struct crypto_scomp *tfm)
+{
+ void *ctx;
+
+ ctx = kmalloc(LZO1X_MEM_COMPRESS, GFP_KERNEL | __GFP_NOWARN);
+ if (!ctx)
+ ctx = vmalloc(LZO1X_MEM_COMPRESS);
+ if (!ctx)
+ return ERR_PTR(-ENOMEM);
+
+ return ctx;
+}
+
static int lzo_init(struct crypto_tfm *tfm)
{
struct lzo_ctx *ctx = crypto_tfm_ctx(tfm);
- ctx->lzo_comp_mem = kmalloc(LZO1X_MEM_COMPRESS,
- GFP_KERNEL | __GFP_NOWARN);
- if (!ctx->lzo_comp_mem)
- ctx->lzo_comp_mem = vmalloc(LZO1X_MEM_COMPRESS);
- if (!ctx->lzo_comp_mem)
+ ctx->lzo_comp_mem = lzo_alloc_ctx(NULL);
+ if (IS_ERR(ctx->lzo_comp_mem))
return -ENOMEM;
return 0;
}
+static void lzo_free_ctx(struct crypto_scomp *tfm, void *ctx)
+{
+ kvfree(ctx);
+}
+
static void lzo_exit(struct crypto_tfm *tfm)
{
struct lzo_ctx *ctx = crypto_tfm_ctx(tfm);
- kvfree(ctx->lzo_comp_mem);
+ lzo_free_ctx(NULL, ctx->lzo_comp_mem);
}
-static int lzo_compress(struct crypto_tfm *tfm, const u8 *src,
- unsigned int slen, u8 *dst, unsigned int *dlen)
+static int __lzo_compress(const u8 *src, unsigned int slen,
+ u8 *dst, unsigned int *dlen, void *ctx)
{
- struct lzo_ctx *ctx = crypto_tfm_ctx(tfm);
size_t tmp_len = *dlen; /* size_t(ulong) <-> uint on 64 bit */
int err;
- err = lzo1x_1_compress(src, slen, dst, &tmp_len, ctx->lzo_comp_mem);
+ err = lzo1x_1_compress(src, slen, dst, &tmp_len, ctx);
if (err != LZO_E_OK)
return -EINVAL;
@@ -64,8 +79,23 @@ static int lzo_compress(struct crypto_tfm *tfm, const u8 *src,
return 0;
}
-static int lzo_decompress(struct crypto_tfm *tfm, const u8 *src,
- unsigned int slen, u8 *dst, unsigned int *dlen)
+static int lzo_compress(struct crypto_tfm *tfm, const u8 *src,
+ unsigned int slen, u8 *dst, unsigned int *dlen)
+{
+ struct lzo_ctx *ctx = crypto_tfm_ctx(tfm);
+
+ return __lzo_compress(src, slen, dst, dlen, ctx->lzo_comp_mem);
+}
+
+static int lzo_scompress(struct crypto_scomp *tfm, const u8 *src,
+ unsigned int slen, u8 *dst, unsigned int *dlen,
+ void *ctx)
+{
+ return __lzo_compress(src, slen, dst, dlen, ctx);
+}
+
+static int __lzo_decompress(const u8 *src, unsigned int slen,
+ u8 *dst, unsigned int *dlen)
{
int err;
size_t tmp_len = *dlen; /* size_t(ulong) <-> uint on 64 bit */
@@ -77,7 +107,19 @@ static int lzo_decompress(struct crypto_tfm *tfm, const u8 *src,
*dlen = tmp_len;
return 0;
+}
+static int lzo_decompress(struct crypto_tfm *tfm, const u8 *src,
+ unsigned int slen, u8 *dst, unsigned int *dlen)
+{
+ return __lzo_decompress(src, slen, dst, dlen);
+}
+
+static int lzo_sdecompress(struct crypto_scomp *tfm, const u8 *src,
+ unsigned int slen, u8 *dst, unsigned int *dlen,
+ void *ctx)
+{
+ return __lzo_decompress(src, slen, dst, dlen);
}
static struct crypto_alg alg = {
@@ -88,18 +130,43 @@ static struct crypto_alg alg = {
.cra_init = lzo_init,
.cra_exit = lzo_exit,
.cra_u = { .compress = {
- .coa_compress = lzo_compress,
- .coa_decompress = lzo_decompress } }
+ .coa_compress = lzo_compress,
+ .coa_decompress = lzo_decompress } }
+};
+
+static struct scomp_alg scomp = {
+ .alloc_ctx = lzo_alloc_ctx,
+ .free_ctx = lzo_free_ctx,
+ .compress = lzo_scompress,
+ .decompress = lzo_sdecompress,
+ .base = {
+ .cra_name = "lzo",
+ .cra_driver_name = "lzo-scomp",
+ .cra_module = THIS_MODULE,
+ }
};
static int __init lzo_mod_init(void)
{
- return crypto_register_alg(&alg);
+ int ret;
+
+ ret = crypto_register_alg(&alg);
+ if (ret)
+ return ret;
+
+ ret = crypto_register_scomp(&scomp);
+ if (ret) {
+ crypto_unregister_alg(&alg);
+ return ret;
+ }
+
+ return ret;
}
static void __exit lzo_mod_fini(void)
{
crypto_unregister_alg(&alg);
+ crypto_unregister_scomp(&scomp);
}
module_init(lzo_mod_init);
--
1.7.4.1
^ permalink raw reply related
* [PATCH v6 1/8] crypto: add asynchronous compression api
From: Giovanni Cabiddu @ 2016-06-08 8:16 UTC (permalink / raw)
To: herbert; +Cc: linux-crypto, Giovanni Cabiddu
In-Reply-To: <1465373818-29720-1-git-send-email-giovanni.cabiddu@intel.com>
This patch introduces acomp, an asynchronous compression api that uses
scatterlist buffers.
Signed-off-by: Giovanni Cabiddu <giovanni.cabiddu@intel.com>
---
crypto/Kconfig | 10 ++
crypto/Makefile | 2 +
crypto/acompress.c | 118 ++++++++++++++++
crypto/crypto_user.c | 21 +++
include/crypto/acompress.h | 261 +++++++++++++++++++++++++++++++++++
include/crypto/internal/acompress.h | 66 +++++++++
include/linux/crypto.h | 1 +
7 files changed, 479 insertions(+), 0 deletions(-)
create mode 100644 crypto/acompress.c
create mode 100644 include/crypto/acompress.h
create mode 100644 include/crypto/internal/acompress.h
diff --git a/crypto/Kconfig b/crypto/Kconfig
index 1d33beb..24fef55 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -93,6 +93,15 @@ config CRYPTO_AKCIPHER
select CRYPTO_AKCIPHER2
select CRYPTO_ALGAPI
+config CRYPTO_ACOMP
+ tristate
+ select CRYPTO_ACOMP2
+ select CRYPTO_ALGAPI
+
+config CRYPTO_ACOMP2
+ tristate
+ select CRYPTO_ALGAPI2
+
config CRYPTO_RSA
tristate "RSA algorithm"
select CRYPTO_AKCIPHER
@@ -115,6 +124,7 @@ config CRYPTO_MANAGER2
select CRYPTO_HASH2
select CRYPTO_BLKCIPHER2
select CRYPTO_AKCIPHER2
+ select CRYPTO_ACOMP2
config CRYPTO_USER
tristate "Userspace cryptographic algorithm configuration"
diff --git a/crypto/Makefile b/crypto/Makefile
index 4f4ef7e..e817b38 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -31,6 +31,8 @@ obj-$(CONFIG_CRYPTO_HASH2) += crypto_hash.o
obj-$(CONFIG_CRYPTO_AKCIPHER2) += akcipher.o
+obj-$(CONFIG_CRYPTO_ACOMP2) += acompress.o
+
$(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
diff --git a/crypto/acompress.c b/crypto/acompress.c
new file mode 100644
index 0000000..f24fef3
--- /dev/null
+++ b/crypto/acompress.c
@@ -0,0 +1,118 @@
+/*
+ * Asynchronous Compression operations
+ *
+ * Copyright (c) 2016, Intel Corporation
+ * Authors: Weigang Li <weigang.li@intel.com>
+ * Giovanni Cabiddu <giovanni.cabiddu@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ */
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/seq_file.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/crypto.h>
+#include <crypto/algapi.h>
+#include <linux/cryptouser.h>
+#include <net/netlink.h>
+#include <crypto/internal/acompress.h>
+#include "internal.h"
+
+#ifdef CONFIG_NET
+static int crypto_acomp_report(struct sk_buff *skb, struct crypto_alg *alg)
+{
+ struct crypto_report_comp racomp;
+
+ strncpy(racomp.type, "acomp", sizeof(racomp.type));
+
+ if (nla_put(skb, CRYPTOCFGA_REPORT_COMPRESS,
+ sizeof(struct crypto_report_comp), &racomp))
+ goto nla_put_failure;
+ return 0;
+
+nla_put_failure:
+ return -EMSGSIZE;
+}
+#else
+static int crypto_acomp_report(struct sk_buff *skb, struct crypto_alg *alg)
+{
+ return -ENOSYS;
+}
+#endif
+
+static void crypto_acomp_show(struct seq_file *m, struct crypto_alg *alg)
+ __attribute__ ((unused));
+
+static void crypto_acomp_show(struct seq_file *m, struct crypto_alg *alg)
+{
+ seq_puts(m, "type : acomp\n");
+}
+
+static void crypto_acomp_exit_tfm(struct crypto_tfm *tfm)
+{
+ struct crypto_acomp *acomp = __crypto_acomp_tfm(tfm);
+ struct acomp_alg *alg = crypto_acomp_alg(acomp);
+
+ alg->exit(acomp);
+}
+
+static int crypto_acomp_init_tfm(struct crypto_tfm *tfm)
+{
+ struct crypto_acomp *acomp = __crypto_acomp_tfm(tfm);
+ struct acomp_alg *alg = crypto_acomp_alg(acomp);
+
+ if (alg->exit)
+ acomp->base.exit = crypto_acomp_exit_tfm;
+
+ if (alg->init)
+ return alg->init(acomp);
+
+ return 0;
+}
+
+static const struct crypto_type crypto_acomp_type = {
+ .extsize = crypto_alg_extsize,
+ .init_tfm = crypto_acomp_init_tfm,
+#ifdef CONFIG_PROC_FS
+ .show = crypto_acomp_show,
+#endif
+ .report = crypto_acomp_report,
+ .maskclear = ~CRYPTO_ALG_TYPE_MASK,
+ .maskset = CRYPTO_ALG_TYPE_MASK,
+ .type = CRYPTO_ALG_TYPE_ACOMPRESS,
+ .tfmsize = offsetof(struct crypto_acomp, base),
+};
+
+struct crypto_acomp *crypto_alloc_acomp(const char *alg_name, u32 type,
+ u32 mask)
+{
+ return crypto_alloc_tfm(alg_name, &crypto_acomp_type, type, mask);
+}
+EXPORT_SYMBOL_GPL(crypto_alloc_acomp);
+
+int crypto_register_acomp(struct acomp_alg *alg)
+{
+ struct crypto_alg *base = &alg->base;
+
+ base->cra_type = &crypto_acomp_type;
+ base->cra_flags &= ~CRYPTO_ALG_TYPE_MASK;
+ base->cra_flags |= CRYPTO_ALG_TYPE_ACOMPRESS;
+
+ return crypto_register_alg(base);
+}
+EXPORT_SYMBOL_GPL(crypto_register_acomp);
+
+int crypto_unregister_acomp(struct acomp_alg *alg)
+{
+ return crypto_unregister_alg(&alg->base);
+}
+EXPORT_SYMBOL_GPL(crypto_unregister_acomp);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Asynchronous compression type");
diff --git a/crypto/crypto_user.c b/crypto/crypto_user.c
index f71960d..80401d9 100644
--- a/crypto/crypto_user.c
+++ b/crypto/crypto_user.c
@@ -111,6 +111,21 @@ nla_put_failure:
return -EMSGSIZE;
}
+static int crypto_report_acomp(struct sk_buff *skb, struct crypto_alg *alg)
+{
+ struct crypto_report_acomp racomp;
+
+ strncpy(racomp.type, "acomp", sizeof(racomp.type));
+
+ if (nla_put(skb, CRYPTOCFGA_REPORT_ACOMPRESS,
+ sizeof(struct crypto_report_acomp), &racomp))
+ goto nla_put_failure;
+ return 0;
+
+nla_put_failure:
+ return -EMSGSIZE;
+}
+
static int crypto_report_akcipher(struct sk_buff *skb, struct crypto_alg *alg)
{
struct crypto_report_akcipher rakcipher;
@@ -171,6 +186,12 @@ static int crypto_report_one(struct crypto_alg *alg,
break;
+ case CRYPTO_ALG_TYPE_ACOMPRESS:
+ if (crypto_report_acomp(skb, alg))
+ goto nla_put_failure;
+
+ break;
+
case CRYPTO_ALG_TYPE_AKCIPHER:
if (crypto_report_akcipher(skb, alg))
goto nla_put_failure;
diff --git a/include/crypto/acompress.h b/include/crypto/acompress.h
new file mode 100644
index 0000000..f4e2f96
--- /dev/null
+++ b/include/crypto/acompress.h
@@ -0,0 +1,261 @@
+/*
+ * Asynchronous Compression operations
+ *
+ * Copyright (c) 2016, Intel Corporation
+ * Authors: Weigang Li <weigang.li@intel.com>
+ * Giovanni Cabiddu <giovanni.cabiddu@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ */
+#ifndef _CRYPTO_ACOMP_H
+#define _CRYPTO_ACOMP_H
+#include <linux/crypto.h>
+
+/**
+ * struct acomp_req - asynchronous (de)compression request
+ *
+ * @base: Common attributes for asynchronous crypto requests
+ * @src: Source Data
+ * @dst: Destination data
+ * @slen: Size of the input buffer
+ * @dlen: Size of the output buffer and number of bytes produced
+ * @__ctx: Start of private context data
+ */
+struct acomp_req {
+ struct crypto_async_request base;
+ struct scatterlist *src;
+ struct scatterlist *dst;
+ unsigned int slen;
+ unsigned int dlen;
+ void *__ctx[] CRYPTO_MINALIGN_ATTR;
+};
+
+/**
+ * struct crypto_acomp - user-instantiated objects which encapsulate
+ * algorithms and core processing logic
+ *
+ * @base: Common crypto API algorithm data structure
+ */
+struct crypto_acomp {
+ struct crypto_tfm base;
+};
+
+/**
+ * struct acomp_alg - asynchronous compression algorithm
+ *
+ * @compress: Function performs a compress operation
+ * @decompress: Function performs a de-compress operation
+ * @init: Initialize the cryptographic transformation object.
+ * This function is used to initialize the cryptographic
+ * transformation object. This function is called only once at
+ * the instantiation time, right after the transformation context
+ * was allocated. In case the cryptographic hardware has some
+ * special requirements which need to be handled by software, this
+ * function shall check for the precise requirement of the
+ * transformation and put any software fallbacks in place.
+ * @exit: Deinitialize the cryptographic transformation object. This is a
+ * counterpart to @init, used to remove various changes set in
+ * @init.
+ *
+ * @reqsize: Context size for (de)compression requests
+ * @base: Common crypto API algorithm data structure
+ */
+struct acomp_alg {
+ int (*compress)(struct acomp_req *req);
+ int (*decompress)(struct acomp_req *req);
+ int (*init)(struct crypto_acomp *tfm);
+ void (*exit)(struct crypto_acomp *tfm);
+ unsigned int reqsize;
+ struct crypto_alg base;
+};
+
+/**
+ * DOC: Asynchronous Compression API
+ *
+ * The Asynchronous Compression API is used with the algorithms of type
+ * CRYPTO_ALG_TYPE_ACOMPRESS (listed as type "acomp" in /proc/crypto)
+ */
+
+/**
+ * crypto_alloc_acomp() -- allocate ACOMPRESS tfm handle
+ * @alg_name: is the cra_name / name or cra_driver_name / driver name of the
+ * compression algorithm e.g. "deflate"
+ * @type: specifies the type of the algorithm
+ * @mask: specifies the mask for the algorithm
+ *
+ * Allocate a handle for a compression algorithm. The returned struct
+ * crypto_acomp is the handle that is required for any subsequent
+ * API invocation for the compression operations.
+ *
+ * Return: allocated handle in case of success; IS_ERR() is true in case
+ * of an error, PTR_ERR() returns the error code.
+ */
+struct crypto_acomp *crypto_alloc_acomp(const char *alg_name, u32 type,
+ u32 mask);
+
+static inline struct crypto_tfm *crypto_acomp_tfm(struct crypto_acomp *tfm)
+{
+ return &tfm->base;
+}
+
+static inline struct acomp_alg *__crypto_acomp_alg(struct crypto_alg *alg)
+{
+ return container_of(alg, struct acomp_alg, base);
+}
+
+static inline struct crypto_acomp *__crypto_acomp_tfm(struct crypto_tfm *tfm)
+{
+ return container_of(tfm, struct crypto_acomp, base);
+}
+
+static inline struct acomp_alg *crypto_acomp_alg(struct crypto_acomp *tfm)
+{
+ return __crypto_acomp_alg(crypto_acomp_tfm(tfm)->__crt_alg);
+}
+
+static inline unsigned int crypto_acomp_reqsize(struct crypto_acomp *tfm)
+{
+ return crypto_acomp_alg(tfm)->reqsize;
+}
+
+static inline void acomp_request_set_tfm(struct acomp_req *req,
+ struct crypto_acomp *tfm)
+{
+ req->base.tfm = crypto_acomp_tfm(tfm);
+}
+
+static inline struct crypto_acomp *crypto_acomp_reqtfm(struct acomp_req *req)
+{
+ return __crypto_acomp_tfm(req->base.tfm);
+}
+
+/**
+ * crypto_free_acomp() -- free ACOMPRESS tfm handle
+ *
+ * @tfm: ACOMPRESS tfm handle allocated with crypto_alloc_acomp()
+ */
+static inline void crypto_free_acomp(struct crypto_acomp *tfm)
+{
+ crypto_destroy_tfm(tfm, crypto_acomp_tfm(tfm));
+}
+
+static inline int crypto_has_acomp(const char *alg_name, u32 type, u32 mask)
+{
+ type &= ~CRYPTO_ALG_TYPE_MASK;
+ type |= CRYPTO_ALG_TYPE_ACOMPRESS;
+ mask |= CRYPTO_ALG_TYPE_MASK;
+
+ return crypto_has_alg(alg_name, type, mask);
+}
+
+/**
+ * acomp_request_alloc() -- allocates asynchronous (de)compression request
+ *
+ * @tfm: ACOMPRESS tfm handle allocated with crypto_alloc_acomp()
+ *
+ * Return: allocated handle in case of success or NULL in case of an error.
+ */
+static inline struct acomp_req *acomp_request_alloc(struct crypto_acomp *tfm)
+{
+ struct acomp_req *req;
+
+ req = kzalloc(sizeof(*req) + crypto_acomp_reqsize(tfm), GFP_KERNEL);
+ if (likely(req))
+ acomp_request_set_tfm(req, tfm);
+
+ return req;
+}
+
+/**
+ * acomp_request_free() -- zeroize and free asynchronous (de)compression request
+ *
+ * @req: request to free
+ */
+static inline void acomp_request_free(struct acomp_req *req)
+{
+ kzfree(req);
+}
+
+/**
+ * acomp_request_set_callback() -- Sets an asynchronous callback
+ *
+ * Callback will be called when an asynchronous operation on a given
+ * request is finished.
+ *
+ * @req: request that the callback will be set for
+ * @flgs: specify for instance if the operation may backlog
+ * @cmlp: callback which will be called
+ * @data: private data used by the caller
+ */
+static inline void acomp_request_set_callback(struct acomp_req *req,
+ u32 flgs,
+ crypto_completion_t cmpl,
+ void *data)
+{
+ req->base.complete = cmpl;
+ req->base.data = data;
+ req->base.flags = flgs;
+}
+
+/**
+ * acomp_request_set_params() -- Sets request parameters
+ *
+ * Sets parameters required by an acomp operation
+ *
+ * @req: asynchronous compress request
+ * @src: pointer to input buffer scatterlist
+ * @dst: pointer to output buffer scatterlist
+ * @slen: size of the input buffer
+ * @dlen: size of the output buffer
+ */
+static inline void acomp_request_set_params(struct acomp_req *req,
+ struct scatterlist *src,
+ struct scatterlist *dst,
+ unsigned int slen,
+ unsigned int dlen)
+{
+ req->src = src;
+ req->dst = dst;
+ req->slen = slen;
+ req->dlen = dlen;
+}
+
+/**
+ * crypto_acomp_compress() -- Invoke asynchronous compress operation
+ *
+ * Function invokes the asynchronous compress operation
+ *
+ * @req: asynchronous compress request
+ *
+ * Return: zero on success; error code in case of error
+ */
+static inline int crypto_acomp_compress(struct acomp_req *req)
+{
+ struct crypto_acomp *tfm = crypto_acomp_reqtfm(req);
+ struct acomp_alg *alg = crypto_acomp_alg(tfm);
+
+ return alg->compress(req);
+}
+
+/**
+ * crypto_acomp_decompress() -- Invoke asynchronous decompress operation
+ *
+ * Function invokes the asynchronous decompress operation
+ *
+ * @req: asynchronous compress request
+ *
+ * Return: zero on success; error code in case of error
+ */
+static inline int crypto_acomp_decompress(struct acomp_req *req)
+{
+ struct crypto_acomp *tfm = crypto_acomp_reqtfm(req);
+ struct acomp_alg *alg = crypto_acomp_alg(tfm);
+
+ return alg->decompress(req);
+}
+
+#endif
diff --git a/include/crypto/internal/acompress.h b/include/crypto/internal/acompress.h
new file mode 100644
index 0000000..294f2ee
--- /dev/null
+++ b/include/crypto/internal/acompress.h
@@ -0,0 +1,66 @@
+/*
+ * Asynchronous Compression operations
+ *
+ * Copyright (c) 2016, Intel Corporation
+ * Authors: Weigang Li <weigang.li@intel.com>
+ * Giovanni Cabiddu <giovanni.cabiddu@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ */
+#ifndef _CRYPTO_ACOMP_INT_H
+#define _CRYPTO_ACOMP_INT_H
+#include <crypto/acompress.h>
+
+/*
+ * Transform internal helpers.
+ */
+static inline void *acomp_request_ctx(struct acomp_req *req)
+{
+ return req->__ctx;
+}
+
+static inline void *acomp_tfm_ctx(struct crypto_acomp *tfm)
+{
+ return tfm->base.__crt_ctx;
+}
+
+static inline void acomp_request_complete(struct acomp_req *req,
+ int err)
+{
+ req->base.complete(&req->base, err);
+}
+
+static inline const char *acomp_alg_name(struct crypto_acomp *tfm)
+{
+ return crypto_acomp_tfm(tfm)->__crt_alg->cra_name;
+}
+
+/**
+ * crypto_register_acomp() -- Register asynchronous compression algorithm
+ *
+ * Function registers an implementation of an asynchronous
+ * compression algorithm
+ *
+ * @alg: algorithm definition
+ *
+ * Return: zero on success; error code in case of error
+ */
+int crypto_register_acomp(struct acomp_alg *alg);
+
+/**
+ * crypto_unregister_acomp() -- Unregister asynchronous compression algorithm
+ *
+ * Function unregisters an implementation of an asynchronous
+ * compression algorithm
+ *
+ * @alg: algorithm definition
+ *
+ * Return: zero on success; error code in case of error
+ */
+int crypto_unregister_acomp(struct acomp_alg *alg);
+
+#endif
diff --git a/include/linux/crypto.h b/include/linux/crypto.h
index d844cbc..7987323 100644
--- a/include/linux/crypto.h
+++ b/include/linux/crypto.h
@@ -48,6 +48,7 @@
#define CRYPTO_ALG_TYPE_BLKCIPHER 0x00000004
#define CRYPTO_ALG_TYPE_ABLKCIPHER 0x00000005
#define CRYPTO_ALG_TYPE_GIVCIPHER 0x00000006
+#define CRYPTO_ALG_TYPE_ACOMPRESS 0x00000008
#define CRYPTO_ALG_TYPE_RNG 0x0000000c
#define CRYPTO_ALG_TYPE_AKCIPHER 0x0000000d
#define CRYPTO_ALG_TYPE_DIGEST 0x0000000e
--
1.7.4.1
^ permalink raw reply related
* [PATCH v6 0/8] crypto: asynchronous compression api
From: Giovanni Cabiddu @ 2016-06-08 8:16 UTC (permalink / raw)
To: herbert; +Cc: linux-crypto, Giovanni Cabiddu
The following patch set introduces acomp, a generic asynchronous
(de)compression api with support for SG lists.
We propose a new crypto type called crypto_acomp_type, a new struct acomp_alg
and struct crypto_acomp, together with number of helper functions to register
acomp type algorithms and allocate tfm instances.
This interface will allow the following operations:
int (*compress)(struct acomp_req *req);
int (*decompress)(struct acomp_req *req);
Together with acomp we propose a new driver-side interface, scomp, which
handles compression implementations which use linear buffers. We converted all
compression algorithms available in LKCF to use this interface so that those
algorithms will be accessible through the acomp api.
Changes in v6:
- changed acomp_request_alloc prototype by removing gfp parameter,
acomp_request_alloc will always use GFP_KERNEL
Changes in v5:
- removed qdecompress api, no longer needed
- removed produced and consumed counters in acomp_req
- added crypto_has_acomp function
Changes in v4:
- added qdecompress api, a front-end for decompression algorithms which
do not need additional vmalloc work space
Changes in v3:
- added driver-side scomp interface
- provided support for lzo, lz4, lz4hc, 842, deflate compression algorithms
via the acomp api (through scomp)
- extended testmgr to support acomp
- removed extended acomp api for supporting deflate algorithm parameters
(will be enhanced and re-proposed in future)
Note that (2) to (7) are a rework of Joonsoo Kim's scomp patches.
Changes in v2:
- added compression and decompression request sizes in acomp_alg
in order to enable noctx support
- extended api with helpers to allocate compression and
decompression requests
Changes from initial submit:
- added consumed and produced fields to acomp_req
- extended api to support configuration of deflate compressors
---
Giovanni Cabiddu (8):
crypto: add asynchronous compression api
crypto: add driver-side scomp interface
crypto: acomp - add support for lzo via scomp
crypto: acomp - add support for lz4 via scomp
crypto: acomp - add support for lz4hc via scomp
crypto: acomp - add support for 842 via scomp
crypto: acomp - add support for deflate via scomp
crypto: acomp - update testmgr with support for acomp
crypto/842.c | 82 +++++++++++-
crypto/Kconfig | 15 ++
crypto/Makefile | 3 +
crypto/acompress.c | 163 ++++++++++++++++++++++
crypto/crypto_user.c | 21 +++
crypto/deflate.c | 111 ++++++++++++++--
crypto/lz4.c | 91 +++++++++++--
crypto/lz4hc.c | 92 +++++++++++--
crypto/lzo.c | 97 +++++++++++--
crypto/scompress.c | 252 ++++++++++++++++++++++++++++++++++
crypto/testmgr.c | 158 ++++++++++++++++++++--
include/crypto/acompress.h | 253 +++++++++++++++++++++++++++++++++++
include/crypto/internal/acompress.h | 81 +++++++++++
include/crypto/internal/scompress.h | 134 ++++++++++++++++++
include/linux/crypto.h | 3 +
15 files changed, 1495 insertions(+), 61 deletions(-)
create mode 100644 crypto/acompress.c
create mode 100644 crypto/scompress.c
create mode 100644 include/crypto/acompress.h
create mode 100644 include/crypto/internal/acompress.h
create mode 100644 include/crypto/internal/scompress.h
--
1.7.4.1
^ permalink raw reply
* [PATCH v6 2/8] crypto: add driver-side scomp interface
From: Giovanni Cabiddu @ 2016-06-08 8:16 UTC (permalink / raw)
To: herbert; +Cc: linux-crypto, Giovanni Cabiddu
In-Reply-To: <1465373818-29720-1-git-send-email-giovanni.cabiddu@intel.com>
Add a synchronous back-end (scomp) to acomp. This allows to easily expose
the already present compression algorithms in LKCF via acomp
Signed-off-by: Giovanni Cabiddu <giovanni.cabiddu@intel.com>
---
crypto/Makefile | 1 +
crypto/acompress.c | 49 +++++++-
crypto/scompress.c | 252 +++++++++++++++++++++++++++++++++++
include/crypto/acompress.h | 32 ++---
include/crypto/internal/acompress.h | 15 ++
include/crypto/internal/scompress.h | 134 +++++++++++++++++++
include/linux/crypto.h | 2 +
7 files changed, 463 insertions(+), 22 deletions(-)
create mode 100644 crypto/scompress.c
create mode 100644 include/crypto/internal/scompress.h
diff --git a/crypto/Makefile b/crypto/Makefile
index e817b38..fc8fcfe 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -32,6 +32,7 @@ obj-$(CONFIG_CRYPTO_HASH2) += crypto_hash.o
obj-$(CONFIG_CRYPTO_AKCIPHER2) += akcipher.o
obj-$(CONFIG_CRYPTO_ACOMP2) += acompress.o
+obj-$(CONFIG_CRYPTO_ACOMP2) += scompress.o
$(obj)/rsapubkey-asn1.o: $(obj)/rsapubkey-asn1.c $(obj)/rsapubkey-asn1.h
$(obj)/rsaprivkey-asn1.o: $(obj)/rsaprivkey-asn1.c $(obj)/rsaprivkey-asn1.h
diff --git a/crypto/acompress.c b/crypto/acompress.c
index f24fef3..a5e6cf1 100644
--- a/crypto/acompress.c
+++ b/crypto/acompress.c
@@ -22,8 +22,11 @@
#include <linux/cryptouser.h>
#include <net/netlink.h>
#include <crypto/internal/acompress.h>
+#include <crypto/internal/scompress.h>
#include "internal.h"
+static const struct crypto_type crypto_acomp_type;
+
#ifdef CONFIG_NET
static int crypto_acomp_report(struct sk_buff *skb, struct crypto_alg *alg)
{
@@ -67,6 +70,13 @@ static int crypto_acomp_init_tfm(struct crypto_tfm *tfm)
struct crypto_acomp *acomp = __crypto_acomp_tfm(tfm);
struct acomp_alg *alg = crypto_acomp_alg(acomp);
+ if (tfm->__crt_alg->cra_type != &crypto_acomp_type)
+ return crypto_init_scomp_ops_async(tfm);
+
+ acomp->compress = alg->compress;
+ acomp->decompress = alg->decompress;
+ acomp->reqsize = alg->reqsize;
+
if (alg->exit)
acomp->base.exit = crypto_acomp_exit_tfm;
@@ -76,15 +86,25 @@ static int crypto_acomp_init_tfm(struct crypto_tfm *tfm)
return 0;
}
+unsigned int crypto_acomp_extsize(struct crypto_alg *alg)
+{
+ int extsize = crypto_alg_extsize(alg);
+
+ if (alg->cra_type != &crypto_acomp_type)
+ extsize += sizeof(struct crypto_scomp *);
+
+ return extsize;
+}
+
static const struct crypto_type crypto_acomp_type = {
- .extsize = crypto_alg_extsize,
+ .extsize = crypto_acomp_extsize,
.init_tfm = crypto_acomp_init_tfm,
#ifdef CONFIG_PROC_FS
.show = crypto_acomp_show,
#endif
.report = crypto_acomp_report,
.maskclear = ~CRYPTO_ALG_TYPE_MASK,
- .maskset = CRYPTO_ALG_TYPE_MASK,
+ .maskset = CRYPTO_ALG_TYPE_ACOMPRESS_MASK,
.type = CRYPTO_ALG_TYPE_ACOMPRESS,
.tfmsize = offsetof(struct crypto_acomp, base),
};
@@ -96,6 +116,31 @@ struct crypto_acomp *crypto_alloc_acomp(const char *alg_name, u32 type,
}
EXPORT_SYMBOL_GPL(crypto_alloc_acomp);
+struct acomp_req *acomp_request_alloc(struct crypto_acomp *acomp)
+{
+ struct crypto_tfm *tfm = crypto_acomp_tfm(acomp);
+ struct acomp_req *req;
+
+ req = __acomp_request_alloc(acomp);
+ if (req && (tfm->__crt_alg->cra_type != &crypto_acomp_type))
+ return crypto_acomp_scomp_alloc_ctx(req);
+
+ return req;
+}
+EXPORT_SYMBOL_GPL(acomp_request_alloc);
+
+void acomp_request_free(struct acomp_req *req)
+{
+ struct crypto_acomp *acomp = crypto_acomp_reqtfm(req);
+ struct crypto_tfm *tfm = crypto_acomp_tfm(acomp);
+
+ if (tfm->__crt_alg->cra_type != &crypto_acomp_type)
+ crypto_acomp_scomp_free_ctx(req);
+
+ __acomp_request_free(req);
+}
+EXPORT_SYMBOL_GPL(acomp_request_free);
+
int crypto_register_acomp(struct acomp_alg *alg)
{
struct crypto_alg *base = &alg->base;
diff --git a/crypto/scompress.c b/crypto/scompress.c
new file mode 100644
index 0000000..850b427
--- /dev/null
+++ b/crypto/scompress.c
@@ -0,0 +1,252 @@
+/*
+ * Synchronous Compression operations
+ *
+ * Copyright 2015 LG Electronics Inc.
+ * Copyright (c) 2016, Intel Corporation
+ * Author: Giovanni Cabiddu <giovanni.cabiddu@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ */
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/seq_file.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/crypto.h>
+#include <crypto/algapi.h>
+#include <linux/cryptouser.h>
+#include <net/netlink.h>
+#include <crypto/scatterwalk.h>
+#include <crypto/internal/acompress.h>
+#include <crypto/internal/scompress.h>
+#include "internal.h"
+
+static const struct crypto_type crypto_scomp_type;
+
+#ifdef CONFIG_NET
+static int crypto_scomp_report(struct sk_buff *skb, struct crypto_alg *alg)
+{
+ struct crypto_report_comp rscomp;
+
+ strncpy(rscomp.type, "scomp", sizeof(rscomp.type));
+
+ if (nla_put(skb, CRYPTOCFGA_REPORT_COMPRESS,
+ sizeof(struct crypto_report_comp), &rscomp))
+ goto nla_put_failure;
+ return 0;
+
+nla_put_failure:
+ return -EMSGSIZE;
+}
+#else
+static int crypto_scomp_report(struct sk_buff *skb, struct crypto_alg *alg)
+{
+ return -ENOSYS;
+}
+#endif
+
+static void crypto_scomp_show(struct seq_file *m, struct crypto_alg *alg)
+ __attribute__ ((unused));
+
+static void crypto_scomp_show(struct seq_file *m, struct crypto_alg *alg)
+{
+ seq_puts(m, "type : scomp\n");
+}
+
+static int crypto_scomp_init_tfm(struct crypto_tfm *tfm)
+{
+ return 0;
+}
+
+static void *scomp_map(struct scatterlist *sg, unsigned int len,
+ gfp_t gfp_flags)
+{
+ void *buf;
+
+ if (sg_is_last(sg))
+ return kmap_atomic(sg_page(sg)) + sg->offset;
+
+ buf = kmalloc(len, gfp_flags);
+ if (!buf)
+ return NULL;
+
+ scatterwalk_map_and_copy(buf, sg, 0, len, 0);
+
+ return buf;
+}
+
+static void scomp_unmap(struct scatterlist *sg, void *buf, unsigned int len)
+{
+ if (!buf)
+ return;
+
+ if (sg_is_last(sg)) {
+ kunmap_atomic(buf);
+ return;
+ }
+
+ scatterwalk_map_and_copy(buf, sg, 0, len, 1);
+ kfree(buf);
+}
+
+static int scomp_acomp_comp_decomp(struct acomp_req *req, int comp_dir)
+{
+ struct crypto_acomp *tfm = crypto_acomp_reqtfm(req);
+ void **tfm_ctx = acomp_tfm_ctx(tfm);
+ struct crypto_scomp *scomp = *tfm_ctx;
+ gfp_t gfp_flags = (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ?
+ GFP_KERNEL : GFP_ATOMIC;
+ void **ctx = acomp_request_ctx(req);
+ unsigned int slen = req->slen;
+ unsigned int dlen = req->dlen;
+ u8 *src;
+ u8 *dst;
+ int ret;
+
+ src = scomp_map(req->src, slen, gfp_flags);
+ if (!src) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ dst = scomp_map(req->dst, dlen, gfp_flags);
+ if (!dst) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ if (comp_dir)
+ ret = crypto_scomp_compress(scomp, src, slen, dst, &dlen,
+ *ctx);
+ else
+ ret = crypto_scomp_decompress(scomp, src, slen, dst, &dlen,
+ *ctx);
+
+ req->dlen = dlen;
+
+out:
+ scomp_unmap(req->src, src, 0);
+ scomp_unmap(req->dst, dst, (ret < 0) ? 0 : dlen);
+
+ return ret;
+}
+
+static int scomp_acomp_compress(struct acomp_req *req)
+{
+ return scomp_acomp_comp_decomp(req, 1);
+}
+
+static int scomp_acomp_decompress(struct acomp_req *req)
+{
+ return scomp_acomp_comp_decomp(req, 0);
+}
+
+static void crypto_exit_scomp_ops_async(struct crypto_tfm *tfm)
+{
+ struct crypto_scomp **ctx = crypto_tfm_ctx(tfm);
+
+ crypto_free_scomp(*ctx);
+}
+
+int crypto_init_scomp_ops_async(struct crypto_tfm *tfm)
+{
+ struct crypto_alg *calg = tfm->__crt_alg;
+ struct crypto_acomp *crt = __crypto_acomp_tfm(tfm);
+ struct crypto_scomp **ctx = crypto_tfm_ctx(tfm);
+ struct crypto_scomp *scomp;
+
+ if (!crypto_mod_get(calg))
+ return -EAGAIN;
+
+ scomp = crypto_create_tfm(calg, &crypto_scomp_type);
+ if (IS_ERR(scomp)) {
+ crypto_mod_put(calg);
+ return PTR_ERR(scomp);
+ }
+
+ *ctx = scomp;
+ tfm->exit = crypto_exit_scomp_ops_async;
+
+ crt->compress = scomp_acomp_compress;
+ crt->decompress = scomp_acomp_decompress;
+ crt->reqsize = sizeof(void *);
+
+ return 0;
+}
+
+struct acomp_req *crypto_acomp_scomp_alloc_ctx(struct acomp_req *req)
+{
+ struct crypto_acomp *acomp = crypto_acomp_reqtfm(req);
+ struct crypto_tfm *tfm = crypto_acomp_tfm(acomp);
+ struct crypto_scomp **tfm_ctx = crypto_tfm_ctx(tfm);
+ struct crypto_scomp *scomp = *tfm_ctx;
+ void *ctx;
+
+ ctx = crypto_scomp_alloc_ctx(scomp);
+ if (IS_ERR(ctx)) {
+ kfree(req);
+ return NULL;
+ }
+
+ *req->__ctx = ctx;
+
+ return req;
+}
+
+void crypto_acomp_scomp_free_ctx(struct acomp_req *req)
+{
+ struct crypto_acomp *acomp = crypto_acomp_reqtfm(req);
+ struct crypto_tfm *tfm = crypto_acomp_tfm(acomp);
+ struct crypto_scomp **tfm_ctx = crypto_tfm_ctx(tfm);
+ struct crypto_scomp *scomp = *tfm_ctx;
+ void *ctx = *req->__ctx;
+
+ if (ctx)
+ crypto_scomp_free_ctx(scomp, ctx);
+}
+
+static const struct crypto_type crypto_scomp_type = {
+ .extsize = crypto_alg_extsize,
+ .init_tfm = crypto_scomp_init_tfm,
+#ifdef CONFIG_PROC_FS
+ .show = crypto_scomp_show,
+#endif
+ .report = crypto_scomp_report,
+ .maskclear = ~CRYPTO_ALG_TYPE_MASK,
+ .maskset = CRYPTO_ALG_TYPE_MASK,
+ .type = CRYPTO_ALG_TYPE_SCOMPRESS,
+ .tfmsize = offsetof(struct crypto_scomp, base),
+};
+
+struct crypto_scomp *crypto_alloc_scomp(const char *alg_name, u32 type,
+ u32 mask)
+{
+ return crypto_alloc_tfm(alg_name, &crypto_scomp_type, type, mask);
+}
+EXPORT_SYMBOL_GPL(crypto_alloc_scomp);
+
+int crypto_register_scomp(struct scomp_alg *alg)
+{
+ struct crypto_alg *base = &alg->base;
+
+ base->cra_type = &crypto_scomp_type;
+ base->cra_flags &= ~CRYPTO_ALG_TYPE_MASK;
+ base->cra_flags |= CRYPTO_ALG_TYPE_SCOMPRESS;
+
+ return crypto_register_alg(base);
+}
+EXPORT_SYMBOL_GPL(crypto_register_scomp);
+
+int crypto_unregister_scomp(struct scomp_alg *alg)
+{
+ return crypto_unregister_alg(&alg->base);
+}
+EXPORT_SYMBOL_GPL(crypto_unregister_scomp);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Synchronous compression type");
diff --git a/include/crypto/acompress.h b/include/crypto/acompress.h
index f4e2f96..93f938d 100644
--- a/include/crypto/acompress.h
+++ b/include/crypto/acompress.h
@@ -38,9 +38,15 @@ struct acomp_req {
* struct crypto_acomp - user-instantiated objects which encapsulate
* algorithms and core processing logic
*
- * @base: Common crypto API algorithm data structure
+ * @compress: Function performs a compress operation
+ * @decompress: Function performs a de-compress operation
+ * @reqsize: Context size for (de)compression requests
+ * @base: Common crypto API algorithm data structure
*/
struct crypto_acomp {
+ int (*compress)(struct acomp_req *req);
+ int (*decompress)(struct acomp_req *req);
+ unsigned int reqsize;
struct crypto_tfm base;
};
@@ -119,7 +125,7 @@ static inline struct acomp_alg *crypto_acomp_alg(struct crypto_acomp *tfm)
static inline unsigned int crypto_acomp_reqsize(struct crypto_acomp *tfm)
{
- return crypto_acomp_alg(tfm)->reqsize;
+ return tfm->reqsize;
}
static inline void acomp_request_set_tfm(struct acomp_req *req,
@@ -159,26 +165,14 @@ static inline int crypto_has_acomp(const char *alg_name, u32 type, u32 mask)
*
* Return: allocated handle in case of success or NULL in case of an error.
*/
-static inline struct acomp_req *acomp_request_alloc(struct crypto_acomp *tfm)
-{
- struct acomp_req *req;
-
- req = kzalloc(sizeof(*req) + crypto_acomp_reqsize(tfm), GFP_KERNEL);
- if (likely(req))
- acomp_request_set_tfm(req, tfm);
-
- return req;
-}
+struct acomp_req *acomp_request_alloc(struct crypto_acomp *tfm);
/**
* acomp_request_free() -- zeroize and free asynchronous (de)compression request
*
* @req: request to free
*/
-static inline void acomp_request_free(struct acomp_req *req)
-{
- kzfree(req);
-}
+void acomp_request_free(struct acomp_req *req);
/**
* acomp_request_set_callback() -- Sets an asynchronous callback
@@ -236,9 +230,8 @@ static inline void acomp_request_set_params(struct acomp_req *req,
static inline int crypto_acomp_compress(struct acomp_req *req)
{
struct crypto_acomp *tfm = crypto_acomp_reqtfm(req);
- struct acomp_alg *alg = crypto_acomp_alg(tfm);
- return alg->compress(req);
+ return tfm->compress(req);
}
/**
@@ -253,9 +246,8 @@ static inline int crypto_acomp_compress(struct acomp_req *req)
static inline int crypto_acomp_decompress(struct acomp_req *req)
{
struct crypto_acomp *tfm = crypto_acomp_reqtfm(req);
- struct acomp_alg *alg = crypto_acomp_alg(tfm);
- return alg->decompress(req);
+ return tfm->decompress(req);
}
#endif
diff --git a/include/crypto/internal/acompress.h b/include/crypto/internal/acompress.h
index 294f2ee..267afdd5 100644
--- a/include/crypto/internal/acompress.h
+++ b/include/crypto/internal/acompress.h
@@ -39,6 +39,21 @@ static inline const char *acomp_alg_name(struct crypto_acomp *tfm)
return crypto_acomp_tfm(tfm)->__crt_alg->cra_name;
}
+static inline struct acomp_req *__acomp_request_alloc(struct crypto_acomp *tfm)
+{
+ struct acomp_req *req;
+
+ req = kzalloc(sizeof(*req) + crypto_acomp_reqsize(tfm), GFP_KERNEL);
+ if (likely(req))
+ acomp_request_set_tfm(req, tfm);
+ return req;
+}
+
+static inline void __acomp_request_free(struct acomp_req *req)
+{
+ kzfree(req);
+}
+
/**
* crypto_register_acomp() -- Register asynchronous compression algorithm
*
diff --git a/include/crypto/internal/scompress.h b/include/crypto/internal/scompress.h
new file mode 100644
index 0000000..a88fc8d
--- /dev/null
+++ b/include/crypto/internal/scompress.h
@@ -0,0 +1,134 @@
+/*
+ * Synchronous Compression operations
+ *
+ * Copyright 2015 LG Electronics Inc.
+ * Copyright (c) 2016, Intel Corporation
+ * Author: Giovanni Cabiddu <giovanni.cabiddu@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ */
+#ifndef _CRYPTO_SCOMP_INT_H
+#define _CRYPTO_SCOMP_INT_H
+#include <linux/crypto.h>
+
+struct crypto_scomp {
+ struct crypto_tfm base;
+};
+
+/**
+ * struct scomp_alg - synchronous compression algorithm
+ *
+ * @alloc_ctx: Function allocates algorithm specific context
+ * @free_ctx: Function frees context allocated with alloc_ctx
+ * @compress: Function performs a compress operation
+ * @decompress: Function performs a de-compress operation
+ * @init: Initialize the cryptographic transformation object.
+ * This function is used to initialize the cryptographic
+ * transformation object. This function is called only once at
+ * the instantiation time, right after the transformation context
+ * was allocated. In case the cryptographic hardware has some
+ * special requirements which need to be handled by software, this
+ * function shall check for the precise requirement of the
+ * transformation and put any software fallbacks in place.
+ * @exit: Deinitialize the cryptographic transformation object. This is a
+ * counterpart to @init, used to remove various changes set in
+ * @init.
+ * @base: Common crypto API algorithm data structure
+ */
+struct scomp_alg {
+ void *(*alloc_ctx)(struct crypto_scomp *tfm);
+ void (*free_ctx)(struct crypto_scomp *tfm, void *ctx);
+ int (*compress)(struct crypto_scomp *tfm, const u8 *src,
+ unsigned int slen, u8 *dst, unsigned int *dlen,
+ void *ctx);
+ int (*decompress)(struct crypto_scomp *tfm, const u8 *src,
+ unsigned int slen, u8 *dst, unsigned int *dlen,
+ void *ctx);
+ struct crypto_alg base;
+};
+
+static inline struct scomp_alg *__crypto_scomp_alg(struct crypto_alg *alg)
+{
+ return container_of(alg, struct scomp_alg, base);
+}
+
+static inline struct crypto_scomp *__crypto_scomp_tfm(struct crypto_tfm *tfm)
+{
+ return container_of(tfm, struct crypto_scomp, base);
+}
+
+static inline struct crypto_tfm *crypto_scomp_tfm(struct crypto_scomp *tfm)
+{
+ return &tfm->base;
+}
+
+static inline void crypto_free_scomp(struct crypto_scomp *tfm)
+{
+ crypto_destroy_tfm(tfm, crypto_scomp_tfm(tfm));
+}
+
+static inline struct scomp_alg *crypto_scomp_alg(struct crypto_scomp *tfm)
+{
+ return __crypto_scomp_alg(crypto_scomp_tfm(tfm)->__crt_alg);
+}
+
+static inline void *crypto_scomp_alloc_ctx(struct crypto_scomp *tfm)
+{
+ return crypto_scomp_alg(tfm)->alloc_ctx(tfm);
+}
+
+static inline void crypto_scomp_free_ctx(struct crypto_scomp *tfm,
+ void *ctx)
+{
+ return crypto_scomp_alg(tfm)->free_ctx(tfm, ctx);
+}
+
+static inline int crypto_scomp_compress(struct crypto_scomp *tfm,
+ const u8 *src, unsigned int slen,
+ u8 *dst, unsigned int *dlen, void *ctx)
+{
+ return crypto_scomp_alg(tfm)->compress(tfm, src, slen, dst, dlen, ctx);
+}
+
+static inline int crypto_scomp_decompress(struct crypto_scomp *tfm,
+ const u8 *src, unsigned int slen,
+ u8 *dst, unsigned int *dlen,
+ void *ctx)
+{
+ return crypto_scomp_alg(tfm)->decompress(tfm, src, slen, dst, dlen,
+ ctx);
+}
+
+int crypto_init_scomp_ops_async(struct crypto_tfm *tfm);
+struct acomp_req *crypto_acomp_scomp_alloc_ctx(struct acomp_req *req);
+void crypto_acomp_scomp_free_ctx(struct acomp_req *req);
+
+/**
+ * crypto_register_scomp() -- Register synchronous compression algorithm
+ *
+ * Function registers an implementation of a synchronous
+ * compression algorithm
+ *
+ * @alg: algorithm definition
+ *
+ * Return: zero on success; error code in case of error
+ */
+int crypto_register_scomp(struct scomp_alg *alg);
+
+/**
+ * crypto_unregister_scomp() -- Unregister synchronous compression algorithm
+ *
+ * Function unregisters an implementation of a synchronous
+ * compression algorithm
+ *
+ * @alg: algorithm definition
+ *
+ * Return: zero on success; error code in case of error
+ */
+int crypto_unregister_scomp(struct scomp_alg *alg);
+
+#endif
diff --git a/include/linux/crypto.h b/include/linux/crypto.h
index 7987323..23ceb0b 100644
--- a/include/linux/crypto.h
+++ b/include/linux/crypto.h
@@ -49,6 +49,7 @@
#define CRYPTO_ALG_TYPE_ABLKCIPHER 0x00000005
#define CRYPTO_ALG_TYPE_GIVCIPHER 0x00000006
#define CRYPTO_ALG_TYPE_ACOMPRESS 0x00000008
+#define CRYPTO_ALG_TYPE_SCOMPRESS 0x0000000a
#define CRYPTO_ALG_TYPE_RNG 0x0000000c
#define CRYPTO_ALG_TYPE_AKCIPHER 0x0000000d
#define CRYPTO_ALG_TYPE_DIGEST 0x0000000e
@@ -59,6 +60,7 @@
#define CRYPTO_ALG_TYPE_HASH_MASK 0x0000000e
#define CRYPTO_ALG_TYPE_AHASH_MASK 0x0000000e
#define CRYPTO_ALG_TYPE_BLKCIPHER_MASK 0x0000000c
+#define CRYPTO_ALG_TYPE_ACOMPRESS_MASK 0x0000000c
#define CRYPTO_ALG_LARVAL 0x00000010
#define CRYPTO_ALG_DEAD 0x00000020
--
1.7.4.1
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox