* [PATCHv2 11/27] crypto: omap-aes: Add fallback support
From: Tero Kristo @ 2016-06-22 13:23 UTC (permalink / raw)
To: linux-omap, linux-crypto, tony, herbert, davem, lokeshvutla
Cc: linux-arm-kernel
In-Reply-To: <1466601840-18486-1-git-send-email-t-kristo@ti.com>
From: Lokesh Vutla <lokeshvutla@ti.com>
As setting up the DMA operations is quite costly, add software fallback
support for requests smaller than 200 bytes. This change gives some 10%
extra performance in ipsec use case.
Signed-off-by: Lokesh Vutla <lokeshvutla@ti.com>
Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
drivers/crypto/Kconfig | 3 +++
drivers/crypto/omap-aes.c | 45 ++++++++++++++++++++++++++++++++++++++++++---
2 files changed, 45 insertions(+), 3 deletions(-)
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index d77ba2f..0c57ac9 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -305,6 +305,9 @@ config CRYPTO_DEV_OMAP_AES
select CRYPTO_AES
select CRYPTO_BLKCIPHER
select CRYPTO_ENGINE
+ select CRYPTO_CBC
+ select CRYPTO_ECB
+ select CRYPTO_CTR
help
OMAP processors have AES module accelerator. Select this if you
want to use the OMAP module for AES algorithms.
diff --git a/drivers/crypto/omap-aes.c b/drivers/crypto/omap-aes.c
index f710602..867e56a 100644
--- a/drivers/crypto/omap-aes.c
+++ b/drivers/crypto/omap-aes.c
@@ -103,6 +103,7 @@ struct omap_aes_ctx {
int keylen;
u32 key[AES_KEYSIZE_256 / sizeof(u32)];
unsigned long flags;
+ struct crypto_ablkcipher *fallback;
};
struct omap_aes_reqctx {
@@ -680,15 +681,28 @@ static void omap_aes_done_task(unsigned long data)
static int omap_aes_crypt(struct ablkcipher_request *req, unsigned long mode)
{
+ struct crypto_tfm *tfm =
+ crypto_ablkcipher_tfm(crypto_ablkcipher_reqtfm(req));
struct omap_aes_ctx *ctx = crypto_ablkcipher_ctx(
crypto_ablkcipher_reqtfm(req));
struct omap_aes_reqctx *rctx = ablkcipher_request_ctx(req);
struct omap_aes_dev *dd;
+ int ret;
pr_debug("nbytes: %d, enc: %d, cbc: %d\n", req->nbytes,
!!(mode & FLAGS_ENCRYPT),
!!(mode & FLAGS_CBC));
+ if (req->nbytes < 200) {
+ ablkcipher_request_set_tfm(req, ctx->fallback);
+
+ if (mode & FLAGS_ENCRYPT)
+ ret = crypto_ablkcipher_encrypt(req);
+ else
+ ret = crypto_ablkcipher_decrypt(req);
+ ablkcipher_request_set_tfm(req, __crypto_ablkcipher_cast(tfm));
+ return ret;
+ }
dd = omap_aes_find_dev(ctx);
if (!dd)
return -ENODEV;
@@ -704,6 +718,7 @@ static int omap_aes_setkey(struct crypto_ablkcipher *tfm, const u8 *key,
unsigned int keylen)
{
struct omap_aes_ctx *ctx = crypto_ablkcipher_ctx(tfm);
+ int ret;
if (keylen != AES_KEYSIZE_128 && keylen != AES_KEYSIZE_192 &&
keylen != AES_KEYSIZE_256)
@@ -714,6 +729,14 @@ static int omap_aes_setkey(struct crypto_ablkcipher *tfm, const u8 *key,
memcpy(ctx->key, key, keylen);
ctx->keylen = keylen;
+ ctx->fallback->base.crt_flags &= ~CRYPTO_TFM_REQ_MASK;
+ ctx->fallback->base.crt_flags |=
+ tfm->base.crt_flags & CRYPTO_TFM_REQ_MASK;
+
+ ret = crypto_ablkcipher_setkey(ctx->fallback, key, keylen);
+ if (!ret)
+ return 0;
+
return 0;
}
@@ -751,6 +774,11 @@ static int omap_aes_cra_init(struct crypto_tfm *tfm)
{
struct omap_aes_dev *dd = NULL;
int err;
+ const char *name = crypto_tfm_alg_name(tfm);
+ const u32 flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK;
+ struct omap_aes_ctx *ctx = crypto_tfm_ctx(tfm);
+ struct crypto_ablkcipher *blk;
+
list_for_each_entry(dd, &dev_list, list) {
err = pm_runtime_get_sync(dd->dev);
@@ -761,6 +789,12 @@ static int omap_aes_cra_init(struct crypto_tfm *tfm)
}
}
+ blk = crypto_alloc_ablkcipher(name, 0, flags);
+ if (IS_ERR(blk))
+ return PTR_ERR(blk);
+
+ ctx->fallback = blk;
+
tfm->crt_ablkcipher.reqsize = sizeof(struct omap_aes_reqctx);
return 0;
@@ -769,11 +803,16 @@ static int omap_aes_cra_init(struct crypto_tfm *tfm)
static void omap_aes_cra_exit(struct crypto_tfm *tfm)
{
struct omap_aes_dev *dd = NULL;
+ struct omap_aes_ctx *ctx = crypto_tfm_ctx(tfm);
list_for_each_entry(dd, &dev_list, list) {
pm_runtime_put_sync(dd->dev);
}
+ if (ctx->fallback)
+ crypto_free_ablkcipher(ctx->fallback);
+
+ ctx->fallback = NULL;
}
/* ********************** ALGS ************************************ */
@@ -785,7 +824,7 @@ static struct crypto_alg algs_ecb_cbc[] = {
.cra_priority = 300,
.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
CRYPTO_ALG_KERN_DRIVER_ONLY |
- CRYPTO_ALG_ASYNC,
+ CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK,
.cra_blocksize = AES_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct omap_aes_ctx),
.cra_alignmask = 0,
@@ -807,7 +846,7 @@ static struct crypto_alg algs_ecb_cbc[] = {
.cra_priority = 300,
.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
CRYPTO_ALG_KERN_DRIVER_ONLY |
- CRYPTO_ALG_ASYNC,
+ CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK,
.cra_blocksize = AES_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct omap_aes_ctx),
.cra_alignmask = 0,
@@ -833,7 +872,7 @@ static struct crypto_alg algs_ctr[] = {
.cra_priority = 300,
.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
CRYPTO_ALG_KERN_DRIVER_ONLY |
- CRYPTO_ALG_ASYNC,
+ CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK,
.cra_blocksize = AES_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct omap_aes_ctx),
.cra_alignmask = 0,
--
1.9.1
^ permalink raw reply related
* [PATCHv2 10/27] crypto: omap-aes: Add support for multiple cores
From: Tero Kristo @ 2016-06-22 13:23 UTC (permalink / raw)
To: linux-omap, linux-crypto, tony, herbert, davem, lokeshvutla
Cc: linux-arm-kernel
In-Reply-To: <1466601840-18486-1-git-send-email-t-kristo@ti.com>
From: Lokesh Vutla <lokeshvutla@ti.com>
Some SoCs like omap4/omap5/dra7 contain multiple AES crypto accelerator
cores. Adapt the driver to support this. The driver picks the last used
device from a list of AES devices.
Signed-off-by: Lokesh Vutla <lokeshvutla@ti.com>
[t-kristo@ti.com: forward ported to 4.7 kernel]
Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
drivers/crypto/omap-aes.c | 20 ++++++--------------
1 file changed, 6 insertions(+), 14 deletions(-)
diff --git a/drivers/crypto/omap-aes.c b/drivers/crypto/omap-aes.c
index cf53d3f..f710602 100644
--- a/drivers/crypto/omap-aes.c
+++ b/drivers/crypto/omap-aes.c
@@ -319,20 +319,12 @@ static void omap_aes_dma_stop(struct omap_aes_dev *dd)
static struct omap_aes_dev *omap_aes_find_dev(struct omap_aes_ctx *ctx)
{
- struct omap_aes_dev *dd = NULL, *tmp;
+ struct omap_aes_dev *dd;
spin_lock_bh(&list_lock);
- if (!ctx->dd) {
- list_for_each_entry(tmp, &dev_list, list) {
- /* FIXME: take fist available aes core */
- dd = tmp;
- break;
- }
- ctx->dd = dd;
- } else {
- /* already found before */
- dd = ctx->dd;
- }
+ dd = list_first_entry(&dev_list, struct omap_aes_dev, list);
+ list_move_tail(&dd->list, &dev_list);
+ ctx->dd = dd;
spin_unlock_bh(&list_lock);
return dd;
@@ -600,7 +592,7 @@ static int omap_aes_prepare_req(struct crypto_engine *engine,
{
struct omap_aes_ctx *ctx = crypto_ablkcipher_ctx(
crypto_ablkcipher_reqtfm(req));
- struct omap_aes_dev *dd = omap_aes_find_dev(ctx);
+ struct omap_aes_dev *dd = ctx->dd;
struct omap_aes_reqctx *rctx;
int len;
@@ -644,7 +636,7 @@ static int omap_aes_crypt_req(struct crypto_engine *engine,
{
struct omap_aes_ctx *ctx = crypto_ablkcipher_ctx(
crypto_ablkcipher_reqtfm(req));
- struct omap_aes_dev *dd = omap_aes_find_dev(ctx);
+ struct omap_aes_dev *dd = ctx->dd;
if (!dd)
return -ENODEV;
--
1.9.1
^ permalink raw reply related
* [PATCHv2 09/27] crypto: omap-aes - Fix enabling clocks
From: Tero Kristo @ 2016-06-22 13:23 UTC (permalink / raw)
To: linux-omap, linux-crypto, tony, herbert, davem, lokeshvutla
Cc: linux-arm-kernel
In-Reply-To: <1466601840-18486-1-git-send-email-t-kristo@ti.com>
From: Lokesh Vutla <lokeshvutla@ti.com>
Enable clocks for all cores before starting session.
Driver has to pic the aes core dynamically based on the queue length.
Signed-off-by: Lokesh Vutla <lokeshvutla@ti.com>
---
drivers/crypto/omap-aes.c | 23 +++++++----------------
1 file changed, 7 insertions(+), 16 deletions(-)
diff --git a/drivers/crypto/omap-aes.c b/drivers/crypto/omap-aes.c
index 8178632..cf53d3f 100644
--- a/drivers/crypto/omap-aes.c
+++ b/drivers/crypto/omap-aes.c
@@ -760,18 +760,13 @@ static int omap_aes_cra_init(struct crypto_tfm *tfm)
struct omap_aes_dev *dd = NULL;
int err;
- /* Find AES device, currently picks the first device */
- spin_lock_bh(&list_lock);
list_for_each_entry(dd, &dev_list, list) {
- break;
- }
- spin_unlock_bh(&list_lock);
-
- err = pm_runtime_get_sync(dd->dev);
- if (err < 0) {
- dev_err(dd->dev, "%s: failed to get_sync(%d)\n",
- __func__, err);
- return err;
+ err = pm_runtime_get_sync(dd->dev);
+ if (err < 0) {
+ dev_err(dd->dev, "%s: failed to get_sync(%d)\n",
+ __func__, err);
+ return err;
+ }
}
tfm->crt_ablkcipher.reqsize = sizeof(struct omap_aes_reqctx);
@@ -783,14 +778,10 @@ static void omap_aes_cra_exit(struct crypto_tfm *tfm)
{
struct omap_aes_dev *dd = NULL;
- /* Find AES device, currently picks the first device */
- spin_lock_bh(&list_lock);
list_for_each_entry(dd, &dev_list, list) {
- break;
+ pm_runtime_put_sync(dd->dev);
}
- spin_unlock_bh(&list_lock);
- pm_runtime_put_sync(dd->dev);
}
/* ********************** ALGS ************************************ */
--
1.9.1
^ permalink raw reply related
* [PATCHv2 08/27] crypto: omap-des: Fix support for unequal lengths
From: Tero Kristo @ 2016-06-22 13:23 UTC (permalink / raw)
To: linux-omap, linux-crypto, tony, herbert, davem, lokeshvutla
Cc: linux-arm-kernel
In-Reply-To: <1466601840-18486-1-git-send-email-t-kristo@ti.com>
From: Lokesh Vutla <a0131933@ti.com>
For cases where total length of an input SGs is not same as
length of the input data for encryption, omap-des driver
crashes. This happens in the case when IPsec is trying to use
omap-des driver.
To avoid this, we copy all the pages from the input SG list
into a contiguous buffer and prepare a single element SG list
for this buffer with length as the total bytes to crypt, which is
similar thing that is done in case of unaligned lengths.
Signed-off-by: Lokesh Vutla <lokeshvutla@ti.com>
Tested-by: Aparna Balasubramanian <aparnab@ti.com>
Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
drivers/crypto/omap-des.c | 27 +++++++++++++++++----------
1 file changed, 17 insertions(+), 10 deletions(-)
diff --git a/drivers/crypto/omap-des.c b/drivers/crypto/omap-des.c
index 3eedb03..e4c87bc 100644
--- a/drivers/crypto/omap-des.c
+++ b/drivers/crypto/omap-des.c
@@ -521,29 +521,36 @@ static int omap_des_crypt_dma_stop(struct omap_des_dev *dd)
return 0;
}
-static int omap_des_copy_needed(struct scatterlist *sg)
+static int omap_des_copy_needed(struct scatterlist *sg, int total)
{
+ int len = 0;
+
+ if (!IS_ALIGNED(total, DES_BLOCK_SIZE))
+ return -1;
+
while (sg) {
if (!IS_ALIGNED(sg->offset, 4))
return -1;
if (!IS_ALIGNED(sg->length, DES_BLOCK_SIZE))
return -1;
+
+ len += sg->length;
sg = sg_next(sg);
}
+
+ if (len != total)
+ return -1;
+
return 0;
}
static int omap_des_copy_sgs(struct omap_des_dev *dd)
{
void *buf_in, *buf_out;
- int pages;
-
- pages = dd->total >> PAGE_SHIFT;
-
- if (dd->total & (PAGE_SIZE-1))
- pages++;
+ int pages, total;
- BUG_ON(!pages);
+ total = ALIGN(dd->total, DES_BLOCK_SIZE);
+ pages = get_order(total);
buf_in = (void *)__get_free_pages(GFP_ATOMIC, pages);
buf_out = (void *)__get_free_pages(GFP_ATOMIC, pages);
@@ -595,8 +602,8 @@ static int omap_des_prepare_req(struct crypto_engine *engine,
dd->in_sg = req->src;
dd->out_sg = req->dst;
- if (omap_des_copy_needed(dd->in_sg) ||
- omap_des_copy_needed(dd->out_sg)) {
+ if (omap_des_copy_needed(dd->in_sg, dd->total) ||
+ omap_des_copy_needed(dd->out_sg, dd->total)) {
if (omap_des_copy_sgs(dd))
pr_err("Failed to copy SGs for unaligned cases\n");
dd->sgs_copied = 1;
--
1.9.1
^ permalink raw reply related
* [PATCHv2 07/27] crypto: omap-sham: implement context export/import APIs
From: Tero Kristo @ 2016-06-22 13:23 UTC (permalink / raw)
To: linux-omap, linux-crypto, tony, herbert, davem, lokeshvutla
Cc: linux-arm-kernel
In-Reply-To: <1466601840-18486-1-git-send-email-t-kristo@ti.com>
Context export/import are now required for ahash algorithms due to
required support in algif_hash. Implement these for OMAP SHA driver,
saving and restoring the internal state of the driver.
Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
drivers/crypto/omap-sham.c | 40 ++++++++++++++++++++++++++++++++++++++--
1 file changed, 38 insertions(+), 2 deletions(-)
diff --git a/drivers/crypto/omap-sham.c b/drivers/crypto/omap-sham.c
index 84a0027..683f825 100644
--- a/drivers/crypto/omap-sham.c
+++ b/drivers/crypto/omap-sham.c
@@ -1325,6 +1325,35 @@ static void omap_sham_cra_exit(struct crypto_tfm *tfm)
}
}
+static int omap_sham_export(struct ahash_request *req, void *out)
+{
+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+ struct omap_sham_reqctx *rctx = ahash_request_ctx(req);
+ struct omap_sham_ctx *ctx = crypto_ahash_ctx(tfm);
+ struct omap_sham_hmac_ctx *bctx = ctx->base;
+
+ memcpy(out, rctx, sizeof(*rctx) + BUFLEN);
+ memcpy(out + sizeof(*rctx) + BUFLEN, ctx, sizeof(*ctx));
+ memcpy(out + sizeof(*rctx) + BUFLEN + sizeof(*ctx), bctx,
+ sizeof(*bctx));
+
+ return 0;
+}
+
+static int omap_sham_import(struct ahash_request *req, const void *in)
+{
+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+ struct omap_sham_reqctx *rctx = ahash_request_ctx(req);
+ struct omap_sham_ctx *ctx = crypto_ahash_ctx(tfm);
+ struct omap_sham_hmac_ctx *bctx = ctx->base;
+
+ memcpy(rctx, in, sizeof(*rctx) + BUFLEN);
+ memcpy(ctx, in + sizeof(*rctx) + BUFLEN, sizeof(*ctx));
+ memcpy(bctx, in + sizeof(*rctx) + BUFLEN + sizeof(*ctx), sizeof(*bctx));
+
+ return 0;
+}
+
static struct ahash_alg algs_sha1_md5[] = {
{
.init = omap_sham_init,
@@ -1979,8 +2008,15 @@ static int omap_sham_probe(struct platform_device *pdev)
for (i = 0; i < dd->pdata->algs_info_size; i++) {
for (j = 0; j < dd->pdata->algs_info[i].size; j++) {
- err = crypto_register_ahash(
- &dd->pdata->algs_info[i].algs_list[j]);
+ struct ahash_alg *alg;
+
+ alg = &dd->pdata->algs_info[i].algs_list[j];
+ alg->export = omap_sham_export;
+ alg->import = omap_sham_import;
+ alg->halg.statesize = sizeof(struct omap_sham_reqctx) +
+ sizeof(struct omap_sham_ctx) +
+ sizeof(struct omap_sham_hmac_ctx) + BUFLEN;
+ err = crypto_register_ahash(alg);
if (err)
goto err_algs;
--
1.9.1
^ permalink raw reply related
* [PATCHv2 02/27] crypto: omap-sham: change queue size from 1 to 10
From: Tero Kristo @ 2016-06-22 13:23 UTC (permalink / raw)
To: linux-omap, linux-crypto, tony, herbert, davem, lokeshvutla
Cc: linux-arm-kernel
In-Reply-To: <1466601840-18486-1-git-send-email-t-kristo@ti.com>
Change crypto queue size from 1 to 10 for omap SHA driver. This should
allow clients to enqueue requests more effectively to avoid serializing
whole crypto sequences, giving extra performance.
Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
drivers/crypto/omap-sham.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/crypto/omap-sham.c b/drivers/crypto/omap-sham.c
index 8831613..2b0a1bd 100644
--- a/drivers/crypto/omap-sham.c
+++ b/drivers/crypto/omap-sham.c
@@ -175,7 +175,7 @@ struct omap_sham_ctx {
struct omap_sham_hmac_ctx base[0];
};
-#define OMAP_SHAM_QUEUE_LENGTH 1
+#define OMAP_SHAM_QUEUE_LENGTH 10
struct omap_sham_algs_info {
struct ahash_alg *algs_list;
--
1.9.1
^ permalink raw reply related
* [PATCHv2 03/27] crypto: omap: do not call dmaengine_terminate_all
From: Tero Kristo @ 2016-06-22 13:23 UTC (permalink / raw)
To: linux-omap, linux-crypto, tony, herbert, davem, lokeshvutla
Cc: linux-arm-kernel
In-Reply-To: <1466601840-18486-1-git-send-email-t-kristo@ti.com>
From: Lokesh Vutla <lokeshvutla@ti.com>
The extra call to dmaengine_terminate_all is not needed, as the DMA
is not running at this point. This improves performance slightly.
Signed-off-by: Lokesh Vutla <lokeshvutla@ti.com>
Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
drivers/crypto/omap-aes.c | 2 --
drivers/crypto/omap-sham.c | 1 -
2 files changed, 3 deletions(-)
diff --git a/drivers/crypto/omap-aes.c b/drivers/crypto/omap-aes.c
index 4a0e6a5..8178632 100644
--- a/drivers/crypto/omap-aes.c
+++ b/drivers/crypto/omap-aes.c
@@ -528,8 +528,6 @@ static int omap_aes_crypt_dma_stop(struct omap_aes_dev *dd)
omap_aes_dma_stop(dd);
- dmaengine_terminate_all(dd->dma_lch_in);
- dmaengine_terminate_all(dd->dma_lch_out);
return 0;
}
diff --git a/drivers/crypto/omap-sham.c b/drivers/crypto/omap-sham.c
index 2b0a1bd..fd3cac3 100644
--- a/drivers/crypto/omap-sham.c
+++ b/drivers/crypto/omap-sham.c
@@ -815,7 +815,6 @@ static int omap_sham_update_dma_stop(struct omap_sham_dev *dd)
{
struct omap_sham_reqctx *ctx = ahash_request_ctx(dd->req);
- dmaengine_terminate_all(dd->dma_lch);
if (ctx->flags & BIT(FLAGS_SG)) {
dma_unmap_sg(dd->dev, ctx->sg, 1, DMA_TO_DEVICE);
--
1.9.1
^ permalink raw reply related
* Re: [PATCH v4 0/5] /dev/random - a new approach
From: Stephan Mueller @ 2016-06-22 13:25 UTC (permalink / raw)
To: Austin S. Hemmelgarn
Cc: Theodore Ts'o, David Jaša, Andi Kleen, sandyinchina,
Jason Cooper, John Denker, H. Peter Anvin, Joe Perches,
Pavel Machek, George Spelvin, linux-crypto, linux-kernel
In-Reply-To: <5df01797-ccf2-f7fb-5d39-15602a4a306a@gmail.com>
Am Mittwoch, 22. Juni 2016, 08:54:16 schrieb Austin S. Hemmelgarn:
Hi Austin,
> You're not demonstrating it's inherently present in the architecture,
I am not demonstrating it, interesting statement. I take different arches from
different vendors which were developed independently from each other and I see
the phenomenon to an equal degree in all of them.
So, this is no demonstration in your eyes? Interesting conclusion.
Yes, I do not have the statement that gate X or function Y in a CPU is the
trigger point. Thus the absolute root cause to the unpredictable phenomenon is
yet unknown to me. I am hunting that -- I spoke with hardware folks from 3
different major chip vendors yet and they all have difficulties in explaining
it. One vendor is currently helping me dissecting the issue.
>
> > I do not care about the form factor of the test system server, desktop or
> > embedded systems nor do I care about the number of attached devices -- the
> > form factor and number of attached devices is the differentiator of what
> > you call embedded vs server vs desktop.
>
> I don't care about form factor, I care about the CPU, and embedded
> systems almost always have simpler CPU designs (not including all the
> peripherals they love to add in on-die). Your own analysis indicates
> that your getting entropy from the complex interaction of the different
> parts of the CPU. Such complexities are less present in simpler CPU
> designs.
My RNG has two safety measures to detect noise source failures (again, they
are documented): during startup and at runtime. In both cases, no data will be
produced. But for chips where the self tests pass, we can surely harvest that
unpredictable phenomenon.
And funnily: these health tests would scream loudly in dmesg if the noise
source would not work. Note, in more recent kernels, the RNG is used in a lot
of configurations and I have only received one complaint that the health test
indicated a bad noise source. That was a very special system where a
separation kernel did funky things.
So, as of now, it rather makes sense that you refer me to some embedded
devices that you think will be a challenge. I do not like to theorize.
For me, embedded devices are something like a Rasperry PI or the MIPS system
which are tested.
> >> Android barely counts as an embedded system anymore, as many Android
> >
> > Then read F.28ff -- these are truly embedded systems (i.e. the routers
> > that I have on my desk)
>
> 1. I'm actually rather curious what router you managed to get Android
> running on.
> 2. This is still an insanely small sample size compared to the rest of
> your results.
I think this will be the last answer for now from my side: I ask you to read
my document as I really do not want to restate 150+ pages here!
This machine is no Android system but an AVM FritzBox router system that is
very popular in Germany, as referenced in the document. It runs with highly
modified Linux system -- as documented.
And instead of complaining about the test sample, you should help us by doing
more testing, if you feel that the health tests in the RNG are insufficient.
Besides, if you really worried about the lower bound I mentioned in the
appendix F, use the oversampling rate turning knob
jent_entropy_collector_alloc as documented. Finally, if that is not of your
liking, generate a bit more data with the Jitter RNG than you think you need
entropy wise.
Ciao
Stephan
^ permalink raw reply
* [PATCHv2 04/27] crypto: omap-sham: set sw fallback to 240 bytes
From: Tero Kristo @ 2016-06-22 13:23 UTC (permalink / raw)
To: linux-omap, linux-crypto, tony, herbert, davem, lokeshvutla
Cc: linux-arm-kernel
In-Reply-To: <1466601840-18486-1-git-send-email-t-kristo@ti.com>
From: Bin Liu <b-liu@ti.com>
Adds software fallback support for small crypto requests. In these cases,
it is undesirable to use DMA, as setting it up itself is rather heavy
operation. Gives about 40% extra performance in ipsec usecase.
Signed-off-by: Bin Liu <b-liu@ti.com>
[t-kristo@ti.com: dropped the extra traces, updated some comments
on the code]
Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
drivers/crypto/omap-sham.c | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/drivers/crypto/omap-sham.c b/drivers/crypto/omap-sham.c
index fd3cac3..6247887 100644
--- a/drivers/crypto/omap-sham.c
+++ b/drivers/crypto/omap-sham.c
@@ -1095,7 +1095,7 @@ static int omap_sham_update(struct ahash_request *req)
ctx->offset = 0;
if (ctx->flags & BIT(FLAGS_FINUP)) {
- if ((ctx->digcnt + ctx->bufcnt + ctx->total) < 9) {
+ if ((ctx->digcnt + ctx->bufcnt + ctx->total) < 240) {
/*
* OMAP HW accel works only with buffers >= 9
* will switch to bypass in final()
@@ -1151,9 +1151,13 @@ static int omap_sham_final(struct ahash_request *req)
if (ctx->flags & BIT(FLAGS_ERROR))
return 0; /* uncompleted hash is not needed */
- /* OMAP HW accel works only with buffers >= 9 */
- /* HMAC is always >= 9 because ipad == block size */
- if ((ctx->digcnt + ctx->bufcnt) < 9)
+ /*
+ * OMAP HW accel works only with buffers >= 9.
+ * HMAC is always >= 9 because ipad == block size.
+ * If buffersize is less than 240, we use fallback SW encoding,
+ * as using DMA + HW in this case doesn't provide any benefit.
+ */
+ if ((ctx->digcnt + ctx->bufcnt) < 240)
return omap_sham_final_shash(req);
else if (ctx->bufcnt)
return omap_sham_enqueue(req, OP_FINAL);
--
1.9.1
^ permalink raw reply related
* [PATCHv2 00/27] crypto: fixes for omap family of devices
From: Tero Kristo @ 2016-06-22 13:23 UTC (permalink / raw)
To: linux-omap, linux-crypto, tony, herbert, davem, lokeshvutla
Cc: linux-arm-kernel
Hi,
Changes compared to v1 of the series:
- dropped first patch from the series (crypto: omap-aes: Fix registration of
algorithms) as it was queued by Herbert already
- modified the second (now first) patch of the series to use runtime auto-
suspend instead of getting static sync over a cra lifetime
- re-ordered the DTS / hwmod changes in the series, the merge order of
these must be maintained to avoid issues
Patches #01 .. #14 should be merged via crypto tree, the rest should be
handled by Tony.
Merging the omap / dts parts can be done safely separately, assuming
you just use omap2plus_defconfig (enabling crypto features will
cause some issues without the driver level fixes.)
- Tero
^ permalink raw reply
* [PATCHv2 01/27] crypto: omap-sham: use runtime_pm autosuspend for clock handling
From: Tero Kristo @ 2016-06-22 13:23 UTC (permalink / raw)
To: linux-omap, linux-crypto, tony, herbert, davem, lokeshvutla
Cc: linux-arm-kernel
In-Reply-To: <1466601840-18486-1-git-send-email-t-kristo@ti.com>
Calling runtime PM API for every block causes serious performance hit to
crypto operations that are done on a long buffer. As crypto is performed
on a page boundary, encrypting large buffers can cause a series of crypto
operations divided by page. The runtime PM API is also called those many
times.
Convert the driver to use runtime_pm autosuspend instead, with a default
timeout value of 1 second. This results in upto ~50% speedup.
Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
drivers/crypto/omap-sham.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/drivers/crypto/omap-sham.c b/drivers/crypto/omap-sham.c
index 6eefaa2..8831613 100644
--- a/drivers/crypto/omap-sham.c
+++ b/drivers/crypto/omap-sham.c
@@ -100,6 +100,8 @@
#define DEFAULT_TIMEOUT_INTERVAL HZ
+#define DEFAULT_AUTOSUSPEND_DELAY 1000
+
/* mostly device flags */
#define FLAGS_BUSY 0
#define FLAGS_FINAL 1
@@ -999,7 +1001,8 @@ static void omap_sham_finish_req(struct ahash_request *req, int err)
dd->flags &= ~(BIT(FLAGS_BUSY) | BIT(FLAGS_FINAL) | BIT(FLAGS_CPU) |
BIT(FLAGS_DMA_READY) | BIT(FLAGS_OUTPUT_READY));
- pm_runtime_put(dd->dev);
+ pm_runtime_mark_last_busy(dd->dev);
+ pm_runtime_put_autosuspend(dd->dev);
if (req->base.complete)
req->base.complete(&req->base, err);
@@ -1946,6 +1949,9 @@ static int omap_sham_probe(struct platform_device *pdev)
dd->flags |= dd->pdata->flags;
+ pm_runtime_use_autosuspend(dev);
+ pm_runtime_set_autosuspend_delay(dev, DEFAULT_AUTOSUSPEND_DELAY);
+
pm_runtime_enable(dev);
pm_runtime_irq_safe(dev);
--
1.9.1
^ permalink raw reply related
* [PATCHv2 06/27] crypto: ahash: increase the maximum allowed statesize
From: Tero Kristo @ 2016-06-22 13:23 UTC (permalink / raw)
To: linux-omap, linux-crypto, tony, herbert, davem, lokeshvutla
Cc: linux-arm-kernel
In-Reply-To: <1466601840-18486-1-git-send-email-t-kristo@ti.com>
The statesize is used to determine the maximum size for saved ahash
context. In some cases, this can be much larger than what is currently
allocated for it, for example omap-sham driver uses a buffer size of
PAGE_SIZE. Increase the statesize to accommodate this.
Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
crypto/ahash.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/crypto/ahash.c b/crypto/ahash.c
index 3887a98..375bbd7 100644
--- a/crypto/ahash.c
+++ b/crypto/ahash.c
@@ -536,7 +536,7 @@ static int ahash_prepare_alg(struct ahash_alg *alg)
struct crypto_alg *base = &alg->halg.base;
if (alg->halg.digestsize > PAGE_SIZE / 8 ||
- alg->halg.statesize > PAGE_SIZE / 8 ||
+ alg->halg.statesize > PAGE_SIZE * 2 ||
alg->halg.statesize == 0)
return -EINVAL;
--
1.9.1
^ permalink raw reply related
* [PATCHv2 05/27] crypto: omap-sham: avoid executing tasklet where not needed
From: Tero Kristo @ 2016-06-22 13:23 UTC (permalink / raw)
To: linux-omap, linux-crypto, tony, herbert, davem, lokeshvutla
Cc: linux-arm-kernel
In-Reply-To: <1466601840-18486-1-git-send-email-t-kristo@ti.com>
Some of the call paths of OMAP SHA driver can avoid executing the next
step of the crypto queue under tasklet; instead, execute the next step
directly via function call. This avoids a costly round-trip via the
scheduler giving a slight performance boost.
Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
drivers/crypto/omap-sham.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/crypto/omap-sham.c b/drivers/crypto/omap-sham.c
index 6247887..84a0027 100644
--- a/drivers/crypto/omap-sham.c
+++ b/drivers/crypto/omap-sham.c
@@ -242,6 +242,8 @@ static struct omap_sham_drv sham = {
.lock = __SPIN_LOCK_UNLOCKED(sham.lock),
};
+static void omap_sham_done_task(unsigned long data);
+
static inline u32 omap_sham_read(struct omap_sham_dev *dd, u32 offset)
{
return __raw_readl(dd->io_base + offset);
@@ -1007,7 +1009,7 @@ static void omap_sham_finish_req(struct ahash_request *req, int err)
req->base.complete(&req->base, err);
/* handle new request */
- tasklet_schedule(&dd->done_task);
+ omap_sham_done_task((unsigned long)dd);
}
static int omap_sham_handle_queue(struct omap_sham_dev *dd,
--
1.9.1
^ permalink raw reply related
* Re: [PATCH 4/8] crypto: rsa-pkcs1pad - Require hash to be present
From: Andrzej Zaborowski @ 2016-06-22 13:20 UTC (permalink / raw)
To: Herbert Xu
Cc: Tadeusz Struk, Linux Crypto Mailing List, Tudor Ambarus,
Stephan Mueller
In-Reply-To: <E1bFfDK-0007yq-FV@gondolin.me.apana.org.au>
Hi Herbert,
On 22 June 2016 at 12:16, Herbert Xu <herbert@gondor.apana.org.au> wrote:
> The only user of rsa-pkcs1pad always uses the hash so there is
> no reason to support the case of not having a hash.
We use pkcs1pad with AF_ALG to implement lightweight TLS. TLS
versions < 1.2 use a non-standard hash so we'd have to move the PKCS#1
padding back to userspace if this is changed.
The remaining patches make sense, I think there was some reason there
were those PAGE_SIZE checks in every operation but it's probably no
longer valid.
Best regards
^ permalink raw reply
* Re: [PATCH v4 0/5] /dev/random - a new approach
From: Austin S. Hemmelgarn @ 2016-06-22 12:54 UTC (permalink / raw)
To: Stephan Mueller
Cc: Theodore Ts'o, David Jaša, Andi Kleen, sandyinchina,
Jason Cooper, John Denker, H. Peter Anvin, Joe Perches,
Pavel Machek, George Spelvin, linux-crypto, linux-kernel
In-Reply-To: <2650602.0p6Dj5APxb@positron.chronox.de>
On 2016-06-22 01:16, Stephan Mueller wrote:
> Am Dienstag, 21. Juni 2016, 15:31:07 schrieb Austin S. Hemmelgarn:
>
> Hi Austin,
>
>>> Little data, interesting statement for results on 200+ systems including
>>> all major CPU arches all showing information leading in the same
>>> directions.
>> Let me try rephrasing this to make it a bit clearer:
>> 1. You have lots of data on server systems.
>> 2. You have a significant amount of data on desktop/workstation type
>> systems.
>> 3. You have very little data on embedded systems.
>>
>> and here are your arguments:
>> A. This works well on server systems.
>> B. This works well on desktop systems.
>> C. This works well on embedded systems.
>>
>> Arguments A and B are substantiated directly by points 1 and 2.
>> Argument C is not substantiated thoroughly because of point 3.
>> My complaint is about argument C given point 3.
>
> Then let me rephrase what I try to say: my RNG rests on the intrinsic
> functionality of CPUs. When I show that such intrinsic behavior is present in
> various architectures I show that there is a common ground for the basis of
> the RNG.
You're not demonstrating it's inherently present in the architecture,
your demonstrating that it's present for those particular
micro-architectures you have tested. You're dealing with effects
resulting from such low-level details of the CPU that you can't assume
it happens for the whole architecture. In fact, your own results
regarding the weak values from Pentium Celeron Mobile system reinforce
that it's not an architectural effect at the ISA level, but results from
low level designs. Given the naming of that particular CPU, it's almost
certainly a P6 or NetBurst micro-arch, neither of which had particularly
complex branch-prediction or pipelining or similar things, and more
significantly, probably did not have HyperThreading, which I'd be
willing to bet is a significant contributing factor on the Xeon and Core
processors you've got results for.
>
> I tested on all CPUs of all large scale architectures (including the
> architectures that are commonly used for embedded devices) and demonstrated
> that the fundamental phenomenon the RNG rests on is present in all
> architectures.
In all architectures you've tested. Note that technically, from a
low-level perspective of something like this, different revisions of an
ISA are different architectures, and when you start talking about
licensed IP cores like ARM and PPC (and MIPS, and SPARC), different
manufacturer's designs almost count separately. You're relying on
complexities inherent in the CPU itself, which will be different between
micro-architectures, and possibly even individual revisions of a
specific model number. Just because the test gives good results on an
ARMv6 or ARMv7 does not mean it will on an ARMv4, because there are
enough differences in typical designs of ARM CPU's that you can't
directly draw conclusions based on such a small sample size (you've
tested at most 4 manufacturer's designs, and even then only one from
each, and there are about 10 different companies making ARM chips, each
selling dozens of slightly different CPU's).
>
> I do not care about the form factor of the test system server, desktop or
> embedded systems nor do I care about the number of attached devices -- the
> form factor and number of attached devices is the differentiator of what you
> call embedded vs server vs desktop.
I don't care about form factor, I care about the CPU, and embedded
systems almost always have simpler CPU designs (not including all the
peripherals they love to add in on-die). Your own analysis indicates
that your getting entropy from the complex interaction of the different
parts of the CPU. Such complexities are less present in simpler CPU
designs.
>
> Heck, I have written a test that executes the RNG on bare metal (without OS
> and with only a keyboard as device present -- i.e no interrupts are received
> apart from a keyboard), which demonstrates that the phenomenon is present.
>
> Furthermore, chapter 6 of my document analyzes the root cause of the RNG and
> here you see clearly that it has nothing to do with the size of the CPU or its
> attached devices or the size of RAM.
And yet averages are higher for systems that have more CPU cores, and
thus more complex CPU's. Prime examples of this are the UltraSPARC
CPU's you've tested. Those have more SMP cores (and threads of
execution) than just about anything else you've listed, and they have
significantly higher values than almost anything else you list.
>
> The massive number of x86 tests shall demonstrate the common theme I see: the
> newer the CPU the larger the phenomenon is the RNG rests on.
Except each iteration of x86 grows more complex branch-prediction and
pipe-lining and other tricks to try and make the CPU process data
faster. That is the source of almost all of the increase your seeing in
entropy for newer revisions. The same is not inherently true of
embedded processors, especially ones designed for hard-real-time usage
(while I don't have the resources to do this myself, I'd love to see
test results for this from a couple of Blackfin DSP's, I'd be willing to
bet that you see extremely low entropy there because they're designed
for real-time processing).
>
> I use different OSes (including microkernel systems) for testing to
> demonstrate that the OS does not materially change the test results.
>>
>> I'm not saying you have insufficient data to support argument A or B,
>> only that you have insufficient data to support argument C.
>
> And I think that this statement is not correct. But I would always welcome
> more testing.
>>
>> Android barely counts as an embedded system anymore, as many Android
>
> Then read F.28ff -- these are truly embedded systems (i.e. the routers that I
> have on my desk)
1. I'm actually rather curious what router you managed to get Android
running on.
2. This is still an insanely small sample size compared to the rest of
your results.
>
>> phones can outperform most inexpensive desktop and laptop systems, and
>> even some rather expensive laptops. This leaves the only systems that
>> can be assumed without further information to be representative of
>> embedded boards to be the ones running Genode, and possibly the MIPS
>> systems, which is a total of about 10 results out of hundreds for
>> servers and desktops/workstations.
^ permalink raw reply
* Re: [PATCH v10 2/3] crypto: kpp - Add DH software implementation
From: Herbert Xu @ 2016-06-22 10:08 UTC (permalink / raw)
To: Benedetto, Salvatore; +Cc: linux-crypto@vger.kernel.org
In-Reply-To: <309B30E91F5E2846B79BD9AA9711D0319367A3@IRSMSX102.ger.corp.intel.com>
On Wed, Jun 22, 2016 at 10:06:32AM +0000, Benedetto, Salvatore wrote:
>
> It is pointless because it will only be used for the testmanager.
> I can merge the test functions but I'll still have two set_secret functions
> based on the alg value. Would that be enough for you?
I have made myself perfectly clear, I don't want to see anything
specific to DH or ECDH in testmgr.
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
* [PATCH 3/8] lib/mpi: Do not do sg_virt
From: Herbert Xu @ 2016-06-22 10:16 UTC (permalink / raw)
To: Andrzej Zaborowski, Tadeusz Struk, Linux Crypto Mailing List,
Tudor Ambarus, Stephan Mueller
In-Reply-To: <20160622101432.GA30454@gondor.apana.org.au>
Currently the mpi SG helpers use sg_virt which is completely
broken. It happens to work with normal kernel memory but will
fail with anything that is not linearly mapped.
This patch fixes this by using the SG iterator helpers.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---
lib/mpi/mpicoder.c | 86 ++++++++++++++++++++++++++++++-----------------------
1 file changed, 50 insertions(+), 36 deletions(-)
diff --git a/lib/mpi/mpicoder.c b/lib/mpi/mpicoder.c
index 7150e5c..c6272ae 100644
--- a/lib/mpi/mpicoder.c
+++ b/lib/mpi/mpicoder.c
@@ -21,6 +21,7 @@
#include <linux/bitops.h>
#include <linux/count_zeros.h>
#include <linux/byteorder/generic.h>
+#include <linux/scatterlist.h>
#include <linux/string.h>
#include "mpi-internal.h"
@@ -255,7 +256,9 @@ int mpi_write_to_sgl(MPI a, struct scatterlist *sgl, unsigned nbytes,
#error please implement for this limb size.
#endif
unsigned int n = mpi_get_size(a);
+ struct sg_mapping_iter miter;
int i, x, buf_len;
+ int nents;
if (sign)
*sign = a->sign;
@@ -263,23 +266,27 @@ int mpi_write_to_sgl(MPI a, struct scatterlist *sgl, unsigned nbytes,
if (nbytes < n)
return -EOVERFLOW;
- buf_len = sgl->length;
- p2 = sg_virt(sgl);
+ nents = sg_nents_for_len(sgl, nbytes);
+ if (nents < 0)
+ return -EINVAL;
- while (nbytes > n) {
- if (!buf_len) {
- sgl = sg_next(sgl);
- if (!sgl)
- return -EINVAL;
- buf_len = sgl->length;
- p2 = sg_virt(sgl);
- }
+ sg_miter_start(&miter, sgl, nents, SG_MITER_ATOMIC | SG_MITER_TO_SG);
+ sg_miter_next(&miter);
+ buf_len = miter.length;
+ p2 = miter.addr;
+ while (nbytes > n) {
i = min_t(unsigned, nbytes - n, buf_len);
memset(p2, 0, i);
p2 += i;
- buf_len -= i;
nbytes -= i;
+
+ buf_len -= i;
+ if (!buf_len) {
+ sg_miter_next(&miter);
+ buf_len = miter.length;
+ p2 = miter.addr;
+ }
}
for (i = a->nlimbs - 1; i >= 0; i--) {
@@ -293,17 +300,16 @@ int mpi_write_to_sgl(MPI a, struct scatterlist *sgl, unsigned nbytes,
p = (u8 *)&alimb;
for (x = 0; x < sizeof(alimb); x++) {
- if (!buf_len) {
- sgl = sg_next(sgl);
- if (!sgl)
- return -EINVAL;
- buf_len = sgl->length;
- p2 = sg_virt(sgl);
- }
*p2++ = *p++;
- buf_len--;
+ if (!--buf_len) {
+ sg_miter_next(&miter);
+ buf_len = miter.length;
+ p2 = miter.addr;
+ }
}
}
+
+ sg_miter_stop(&miter);
return 0;
}
EXPORT_SYMBOL_GPL(mpi_write_to_sgl);
@@ -323,19 +329,23 @@ EXPORT_SYMBOL_GPL(mpi_write_to_sgl);
*/
MPI mpi_read_raw_from_sgl(struct scatterlist *sgl, unsigned int nbytes)
{
- struct scatterlist *sg;
- int x, i, j, z, lzeros, ents;
+ struct sg_mapping_iter miter;
unsigned int nbits, nlimbs;
+ int x, j, z, lzeros, ents;
+ unsigned int len;
+ const u8 *buff;
mpi_limb_t a;
MPI val = NULL;
- lzeros = 0;
- ents = sg_nents(sgl);
+ ents = sg_nents_for_len(sgl, nbytes);
+ if (ents < 0)
+ return NULL;
- for_each_sg(sgl, sg, ents, i) {
- const u8 *buff = sg_virt(sg);
- int len = sg->length;
+ sg_miter_start(&miter, sgl, ents, SG_MITER_ATOMIC | SG_MITER_FROM_SG);
+ lzeros = 0;
+ len = 0;
+ while (nbytes > 0) {
while (len && !*buff) {
lzeros++;
len--;
@@ -345,12 +355,14 @@ MPI mpi_read_raw_from_sgl(struct scatterlist *sgl, unsigned int nbytes)
if (len && *buff)
break;
- ents--;
+ sg_miter_next(&miter);
+ buff = miter.addr;
+ len = miter.length;
+
nbytes -= lzeros;
lzeros = 0;
}
- sgl = sg;
nbytes -= lzeros;
nbits = nbytes * 8;
if (nbits > MAX_EXTERN_MPI_BITS) {
@@ -359,8 +371,7 @@ MPI mpi_read_raw_from_sgl(struct scatterlist *sgl, unsigned int nbytes)
}
if (nbytes > 0)
- nbits -= count_leading_zeros(*(u8 *)(sg_virt(sgl) + lzeros)) -
- (BITS_PER_LONG - 8);
+ nbits -= count_leading_zeros(*buff) - (BITS_PER_LONG - 8);
nlimbs = DIV_ROUND_UP(nbytes, BYTES_PER_MPI_LIMB);
val = mpi_alloc(nlimbs);
@@ -379,21 +390,24 @@ MPI mpi_read_raw_from_sgl(struct scatterlist *sgl, unsigned int nbytes)
z = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB;
z %= BYTES_PER_MPI_LIMB;
- for_each_sg(sgl, sg, ents, i) {
- const u8 *buffer = sg_virt(sg) + lzeros;
- int len = sg->length - lzeros;
-
+ for (;;) {
for (x = 0; x < len; x++) {
a <<= 8;
- a |= *buffer++;
+ a |= *buff++;
if (((z + x + 1) % BYTES_PER_MPI_LIMB) == 0) {
val->d[j--] = a;
a = 0;
}
}
z += x;
- lzeros = 0;
+
+ if (!sg_miter_next(&miter))
+ break;
+
+ buff = miter.addr;
+ len = miter.length;
}
+
return val;
}
EXPORT_SYMBOL_GPL(mpi_read_raw_from_sgl);
^ permalink raw reply related
* [PATCH 2/8] crypto: rsa - Generate fixed-length output
From: Herbert Xu @ 2016-06-22 10:16 UTC (permalink / raw)
To: Andrzej Zaborowski, Tadeusz Struk, Linux Crypto Mailing List,
Tudor Ambarus, Stephan Mueller
In-Reply-To: <20160622101432.GA30454@gondor.apana.org.au>
Every implementation of RSA that we have naturally generates
output with leading zeroes. The one and only user of RSA,
pkcs1pad wants to have those leading zeroes in place, in fact
because they are currently absent it has to write those zeroes
itself.
So we shouldn't be stripping leading zeroes in the first place.
In fact this patch makes rsa-generic produce output with fixed
length so that pkcs1pad does not need to do any extra work.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---
crypto/rsa.c | 8 +++----
include/linux/mpi.h | 2 -
lib/mpi/mpicoder.c | 55 ++++++++++++++++++++++++----------------------------
3 files changed, 31 insertions(+), 34 deletions(-)
diff --git a/crypto/rsa.c b/crypto/rsa.c
index dc692d4..4c280b6 100644
--- a/crypto/rsa.c
+++ b/crypto/rsa.c
@@ -108,7 +108,7 @@ static int rsa_enc(struct akcipher_request *req)
if (ret)
goto err_free_m;
- ret = mpi_write_to_sgl(c, req->dst, &req->dst_len, &sign);
+ ret = mpi_write_to_sgl(c, req->dst, req->dst_len, &sign);
if (ret)
goto err_free_m;
@@ -147,7 +147,7 @@ static int rsa_dec(struct akcipher_request *req)
if (ret)
goto err_free_c;
- ret = mpi_write_to_sgl(m, req->dst, &req->dst_len, &sign);
+ ret = mpi_write_to_sgl(m, req->dst, req->dst_len, &sign);
if (ret)
goto err_free_c;
@@ -185,7 +185,7 @@ static int rsa_sign(struct akcipher_request *req)
if (ret)
goto err_free_m;
- ret = mpi_write_to_sgl(s, req->dst, &req->dst_len, &sign);
+ ret = mpi_write_to_sgl(s, req->dst, req->dst_len, &sign);
if (ret)
goto err_free_m;
@@ -226,7 +226,7 @@ static int rsa_verify(struct akcipher_request *req)
if (ret)
goto err_free_s;
- ret = mpi_write_to_sgl(m, req->dst, &req->dst_len, &sign);
+ ret = mpi_write_to_sgl(m, req->dst, req->dst_len, &sign);
if (ret)
goto err_free_s;
diff --git a/include/linux/mpi.h b/include/linux/mpi.h
index f219559..1cc5ffb 100644
--- a/include/linux/mpi.h
+++ b/include/linux/mpi.h
@@ -80,7 +80,7 @@ void *mpi_get_buffer(MPI a, unsigned *nbytes, int *sign);
int mpi_read_buffer(MPI a, uint8_t *buf, unsigned buf_len, unsigned *nbytes,
int *sign);
void *mpi_get_secure_buffer(MPI a, unsigned *nbytes, int *sign);
-int mpi_write_to_sgl(MPI a, struct scatterlist *sg, unsigned *nbytes,
+int mpi_write_to_sgl(MPI a, struct scatterlist *sg, unsigned nbytes,
int *sign);
#define log_mpidump g10_log_mpidump
diff --git a/lib/mpi/mpicoder.c b/lib/mpi/mpicoder.c
index 823cf5f..7150e5c 100644
--- a/lib/mpi/mpicoder.c
+++ b/lib/mpi/mpicoder.c
@@ -237,16 +237,13 @@ EXPORT_SYMBOL_GPL(mpi_get_buffer);
* @a: a multi precision integer
* @sgl: scatterlist to write to. Needs to be at least
* mpi_get_size(a) long.
- * @nbytes: in/out param - it has the be set to the maximum number of
- * bytes that can be written to sgl. This has to be at least
- * the size of the integer a. On return it receives the actual
- * length of the data written on success or the data that would
- * be written if buffer was too small.
+ * @nbytes: the number of bytes to write. Leading bytes will be
+ * filled with zero.
* @sign: if not NULL, it will be set to the sign of a.
*
* Return: 0 on success or error code in case of error
*/
-int mpi_write_to_sgl(MPI a, struct scatterlist *sgl, unsigned *nbytes,
+int mpi_write_to_sgl(MPI a, struct scatterlist *sgl, unsigned nbytes,
int *sign)
{
u8 *p, *p2;
@@ -258,43 +255,44 @@ int mpi_write_to_sgl(MPI a, struct scatterlist *sgl, unsigned *nbytes,
#error please implement for this limb size.
#endif
unsigned int n = mpi_get_size(a);
- int i, x, y = 0, lzeros, buf_len;
-
- if (!nbytes)
- return -EINVAL;
+ int i, x, buf_len;
if (sign)
*sign = a->sign;
- lzeros = count_lzeros(a);
-
- if (*nbytes < n - lzeros) {
- *nbytes = n - lzeros;
+ if (nbytes < n)
return -EOVERFLOW;
- }
- *nbytes = n - lzeros;
buf_len = sgl->length;
p2 = sg_virt(sgl);
- for (i = a->nlimbs - 1 - lzeros / BYTES_PER_MPI_LIMB,
- lzeros %= BYTES_PER_MPI_LIMB;
- i >= 0; i--) {
+ while (nbytes > n) {
+ if (!buf_len) {
+ sgl = sg_next(sgl);
+ if (!sgl)
+ return -EINVAL;
+ buf_len = sgl->length;
+ p2 = sg_virt(sgl);
+ }
+
+ i = min_t(unsigned, nbytes - n, buf_len);
+ memset(p2, 0, i);
+ p2 += i;
+ buf_len -= i;
+ nbytes -= i;
+ }
+
+ for (i = a->nlimbs - 1; i >= 0; i--) {
#if BYTES_PER_MPI_LIMB == 4
- alimb = cpu_to_be32(a->d[i]);
+ alimb = a->d[i] ? cpu_to_be32(a->d[i]) : 0;
#elif BYTES_PER_MPI_LIMB == 8
- alimb = cpu_to_be64(a->d[i]);
+ alimb = a->d[i] ? cpu_to_be64(a->d[i]) : 0;
#else
#error please implement for this limb size.
#endif
- if (lzeros) {
- y = lzeros;
- lzeros = 0;
- }
-
- p = (u8 *)&alimb + y;
+ p = (u8 *)&alimb;
- for (x = 0; x < sizeof(alimb) - y; x++) {
+ for (x = 0; x < sizeof(alimb); x++) {
if (!buf_len) {
sgl = sg_next(sgl);
if (!sgl)
@@ -305,7 +303,6 @@ int mpi_write_to_sgl(MPI a, struct scatterlist *sgl, unsigned *nbytes,
*p2++ = *p++;
buf_len--;
}
- y = 0;
}
return 0;
}
^ permalink raw reply related
* crypto: rsa - Do not gratuitously drop leading zeroes
From: Herbert Xu @ 2016-06-22 10:14 UTC (permalink / raw)
To: Andrzej Zaborowski, Tadeusz Struk, Linux Crypto Mailing List
Cc: Tudor Ambarus, Stephan Mueller
This was prompted by the caam RSA submission where a lot of work
was done just to strip the RSA output of leading zeroes. This is
in fact completely pointless because the only user of RSA in the
kernel then promptly puts them back.
This patch series resolves this madness by simply leaving any
leading zeroes in place. Note that we're not requiring authors
to add leading zeroes, even though that is encouraged if it is
easy to do. In practice you'd only run into this every 2^32 or
2^64 operations so please don't overdo it.
I've also taken the opportunity to cleanup the pkcs1pad code.
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
* [PATCH 8/8] crypto: rsa-pkcs1pad - Avoid copying output when possible
From: Herbert Xu @ 2016-06-22 10:16 UTC (permalink / raw)
To: Andrzej Zaborowski, Tadeusz Struk, Linux Crypto Mailing List,
Tudor Ambarus, Stephan Mueller
In-Reply-To: <20160622101432.GA30454@gondor.apana.org.au>
In the vast majority of cases (2^-32 on 32-bit and 2^-64 on 64-bit)
cases, the result from encryption/signing will require no padding.
This patch makes these two operations write their output directly
to the final destination. Only in the exceedingly rare cases where
fixup is needed to we copy it out and back to add the leading zeroes.
This patch also makes use of the crypto_akcipher_set_crypt API
instead of writing the akcipher request directly.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---
crypto/rsa-pkcs1pad.c | 112 ++++++++++++++++++++------------------------------
1 file changed, 45 insertions(+), 67 deletions(-)
diff --git a/crypto/rsa-pkcs1pad.c b/crypto/rsa-pkcs1pad.c
index ebd8514..8ccfdd7 100644
--- a/crypto/rsa-pkcs1pad.c
+++ b/crypto/rsa-pkcs1pad.c
@@ -185,37 +185,36 @@ static int pkcs1pad_encrypt_sign_complete(struct akcipher_request *req, int err)
struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
struct pkcs1pad_ctx *ctx = akcipher_tfm_ctx(tfm);
struct pkcs1pad_request *req_ctx = akcipher_request_ctx(req);
- size_t pad_len = ctx->key_size - req_ctx->child_req.dst_len;
- size_t chunk_len, pad_left;
- struct sg_mapping_iter miter;
-
- if (!err) {
- if (pad_len) {
- sg_miter_start(&miter, req->dst,
- sg_nents_for_len(req->dst, pad_len),
- SG_MITER_ATOMIC | SG_MITER_TO_SG);
-
- pad_left = pad_len;
- while (pad_left) {
- sg_miter_next(&miter);
-
- chunk_len = min(miter.length, pad_left);
- memset(miter.addr, 0, chunk_len);
- pad_left -= chunk_len;
- }
-
- sg_miter_stop(&miter);
- }
-
- sg_pcopy_from_buffer(req->dst,
- sg_nents_for_len(req->dst, ctx->key_size),
- req_ctx->out_buf, req_ctx->child_req.dst_len,
- pad_len);
- }
+ unsigned int pad_len;
+ unsigned int len;
+ u8 *out_buf;
+
+ if (err)
+ goto out;
+
+ len = req_ctx->child_req.dst_len;
+ pad_len = ctx->key_size - len;
+
+ /* Four billion to one */
+ if (likely(!pad_len))
+ goto out;
+
+ out_buf = kzalloc(ctx->key_size, GFP_ATOMIC);
+ err = -ENOMEM;
+ if (!out_buf)
+ goto out;
+
+ sg_copy_to_buffer(req->dst, sg_nents_for_len(req->dst, len),
+ out_buf + pad_len, len);
+ sg_copy_from_buffer(req->dst,
+ sg_nents_for_len(req->dst, ctx->key_size),
+ out_buf, ctx->key_size);
+ kzfree(out_buf);
+
+out:
req->dst_len = ctx->key_size;
kfree(req_ctx->in_buf);
- kzfree(req_ctx->out_buf);
return err;
}
@@ -255,15 +254,6 @@ static int pkcs1pad_encrypt(struct akcipher_request *req)
return -EOVERFLOW;
}
- /*
- * Replace both input and output to add the padding in the input and
- * the potential missing leading zeros in the output.
- */
- req_ctx->child_req.src = req_ctx->in_sg;
- req_ctx->child_req.src_len = ctx->key_size - 1;
- req_ctx->child_req.dst = req_ctx->out_sg;
- req_ctx->child_req.dst_len = ctx->key_size;
-
req_ctx->in_buf = kmalloc(ctx->key_size - 1 - req->src_len,
GFP_KERNEL);
if (!req_ctx->in_buf)
@@ -291,6 +281,10 @@ static int pkcs1pad_encrypt(struct akcipher_request *req)
akcipher_request_set_callback(&req_ctx->child_req, req->base.flags,
pkcs1pad_encrypt_sign_complete_cb, req);
+ /* Reuse output buffer */
+ akcipher_request_set_crypt(&req_ctx->child_req, req_ctx->in_sg,
+ req->dst, ctx->key_size - 1, req->dst_len);
+
err = crypto_akcipher_encrypt(&req_ctx->child_req);
if (err != -EINPROGRESS &&
(err != -EBUSY ||
@@ -372,12 +366,6 @@ static int pkcs1pad_decrypt(struct akcipher_request *req)
if (!ctx->key_size || req->src_len != ctx->key_size)
return -EINVAL;
- /* Reuse input buffer, output to a new buffer */
- req_ctx->child_req.src = req->src;
- req_ctx->child_req.src_len = req->src_len;
- req_ctx->child_req.dst = req_ctx->out_sg;
- req_ctx->child_req.dst_len = ctx->key_size ;
-
req_ctx->out_buf = kmalloc(ctx->key_size, GFP_KERNEL);
if (!req_ctx->out_buf)
return -ENOMEM;
@@ -389,6 +377,11 @@ static int pkcs1pad_decrypt(struct akcipher_request *req)
akcipher_request_set_callback(&req_ctx->child_req, req->base.flags,
pkcs1pad_decrypt_complete_cb, req);
+ /* Reuse input buffer, output to a new buffer */
+ akcipher_request_set_crypt(&req_ctx->child_req, req->src,
+ req_ctx->out_sg, req->src_len,
+ ctx->key_size);
+
err = crypto_akcipher_decrypt(&req_ctx->child_req);
if (err != -EINPROGRESS &&
(err != -EBUSY ||
@@ -422,15 +415,6 @@ static int pkcs1pad_sign(struct akcipher_request *req)
return -EOVERFLOW;
}
- /*
- * Replace both input and output to add the padding in the input and
- * the potential missing leading zeros in the output.
- */
- req_ctx->child_req.src = req_ctx->in_sg;
- req_ctx->child_req.src_len = ctx->key_size - 1;
- req_ctx->child_req.dst = req_ctx->out_sg;
- req_ctx->child_req.dst_len = ctx->key_size;
-
req_ctx->in_buf = kmalloc(ctx->key_size - 1 - req->src_len,
GFP_KERNEL);
if (!req_ctx->in_buf)
@@ -447,19 +431,14 @@ static int pkcs1pad_sign(struct akcipher_request *req)
pkcs1pad_sg_set_buf(req_ctx->in_sg, req_ctx->in_buf,
ctx->key_size - 1 - req->src_len, req->src);
- req_ctx->out_buf = kmalloc(ctx->key_size, GFP_KERNEL);
- if (!req_ctx->out_buf) {
- kfree(req_ctx->in_buf);
- return -ENOMEM;
- }
-
- pkcs1pad_sg_set_buf(req_ctx->out_sg, req_ctx->out_buf,
- ctx->key_size, NULL);
-
akcipher_request_set_tfm(&req_ctx->child_req, ctx->child);
akcipher_request_set_callback(&req_ctx->child_req, req->base.flags,
pkcs1pad_encrypt_sign_complete_cb, req);
+ /* Reuse output buffer */
+ akcipher_request_set_crypt(&req_ctx->child_req, req_ctx->in_sg,
+ req->dst, ctx->key_size - 1, req->dst_len);
+
err = crypto_akcipher_sign(&req_ctx->child_req);
if (err != -EINPROGRESS &&
(err != -EBUSY ||
@@ -559,12 +538,6 @@ static int pkcs1pad_verify(struct akcipher_request *req)
if (!ctx->key_size || req->src_len < ctx->key_size)
return -EINVAL;
- /* Reuse input buffer, output to a new buffer */
- req_ctx->child_req.src = req->src;
- req_ctx->child_req.src_len = req->src_len;
- req_ctx->child_req.dst = req_ctx->out_sg;
- req_ctx->child_req.dst_len = ctx->key_size;
-
req_ctx->out_buf = kmalloc(ctx->key_size, GFP_KERNEL);
if (!req_ctx->out_buf)
return -ENOMEM;
@@ -576,6 +549,11 @@ static int pkcs1pad_verify(struct akcipher_request *req)
akcipher_request_set_callback(&req_ctx->child_req, req->base.flags,
pkcs1pad_verify_complete_cb, req);
+ /* Reuse input buffer, output to a new buffer */
+ akcipher_request_set_crypt(&req_ctx->child_req, req->src,
+ req_ctx->out_sg, req->src_len,
+ ctx->key_size);
+
err = crypto_akcipher_verify(&req_ctx->child_req);
if (err != -EINPROGRESS &&
(err != -EBUSY ||
^ permalink raw reply related
* [PATCH 4/8] crypto: rsa-pkcs1pad - Require hash to be present
From: Herbert Xu @ 2016-06-22 10:16 UTC (permalink / raw)
To: Andrzej Zaborowski, Tadeusz Struk, Linux Crypto Mailing List,
Tudor Ambarus, Stephan Mueller
In-Reply-To: <20160622101432.GA30454@gondor.apana.org.au>
The only user of rsa-pkcs1pad always uses the hash so there is
no reason to support the case of not having a hash.
This patch also changes the digest info lookup so that it is
only done once during template instantiation rather than on each
operation.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---
crypto/rsa-pkcs1pad.c | 83 ++++++++++++++++++--------------------------------
1 file changed, 30 insertions(+), 53 deletions(-)
diff --git a/crypto/rsa-pkcs1pad.c b/crypto/rsa-pkcs1pad.c
index ead8dc0..5c1c78e 100644
--- a/crypto/rsa-pkcs1pad.c
+++ b/crypto/rsa-pkcs1pad.c
@@ -92,13 +92,12 @@ static const struct rsa_asn1_template *rsa_lookup_asn1(const char *name)
struct pkcs1pad_ctx {
struct crypto_akcipher *child;
- const char *hash_name;
unsigned int key_size;
};
struct pkcs1pad_inst_ctx {
struct crypto_akcipher_spawn spawn;
- const char *hash_name;
+ const struct rsa_asn1_template *digest_info;
};
struct pkcs1pad_request {
@@ -416,20 +415,16 @@ static int pkcs1pad_sign(struct akcipher_request *req)
struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
struct pkcs1pad_ctx *ctx = akcipher_tfm_ctx(tfm);
struct pkcs1pad_request *req_ctx = akcipher_request_ctx(req);
- const struct rsa_asn1_template *digest_info = NULL;
+ struct akcipher_instance *inst = akcipher_alg_instance(tfm);
+ struct pkcs1pad_inst_ctx *ictx = akcipher_instance_ctx(inst);
+ const struct rsa_asn1_template *digest_info = ictx->digest_info;
int err;
unsigned int ps_end, digest_size = 0;
if (!ctx->key_size)
return -EINVAL;
- if (ctx->hash_name) {
- digest_info = rsa_lookup_asn1(ctx->hash_name);
- if (!digest_info)
- return -EINVAL;
-
- digest_size = digest_info->size;
- }
+ digest_size = digest_info->size;
if (req->src_len + digest_size > ctx->key_size - 11)
return -EOVERFLOW;
@@ -462,10 +457,8 @@ static int pkcs1pad_sign(struct akcipher_request *req)
memset(req_ctx->in_buf + 1, 0xff, ps_end - 1);
req_ctx->in_buf[ps_end] = 0x00;
- if (digest_info) {
- memcpy(req_ctx->in_buf + ps_end + 1, digest_info->data,
- digest_info->size);
- }
+ memcpy(req_ctx->in_buf + ps_end + 1, digest_info->data,
+ digest_info->size);
pkcs1pad_sg_set_buf(req_ctx->in_sg, req_ctx->in_buf,
ctx->key_size - 1 - req->src_len, req->src);
@@ -499,7 +492,9 @@ static int pkcs1pad_verify_complete(struct akcipher_request *req, int err)
struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
struct pkcs1pad_ctx *ctx = akcipher_tfm_ctx(tfm);
struct pkcs1pad_request *req_ctx = akcipher_request_ctx(req);
- const struct rsa_asn1_template *digest_info;
+ struct akcipher_instance *inst = akcipher_alg_instance(tfm);
+ struct pkcs1pad_inst_ctx *ictx = akcipher_instance_ctx(inst);
+ const struct rsa_asn1_template *digest_info = ictx->digest_info;
unsigned int pos;
if (err == -EOVERFLOW)
@@ -527,17 +522,11 @@ static int pkcs1pad_verify_complete(struct akcipher_request *req, int err)
goto done;
pos++;
- if (ctx->hash_name) {
- digest_info = rsa_lookup_asn1(ctx->hash_name);
- if (!digest_info)
- goto done;
+ if (memcmp(req_ctx->out_buf + pos, digest_info->data,
+ digest_info->size))
+ goto done;
- if (memcmp(req_ctx->out_buf + pos, digest_info->data,
- digest_info->size))
- goto done;
-
- pos += digest_info->size;
- }
+ pos += digest_info->size;
err = 0;
@@ -626,12 +615,11 @@ static int pkcs1pad_init_tfm(struct crypto_akcipher *tfm)
struct pkcs1pad_ctx *ctx = akcipher_tfm_ctx(tfm);
struct crypto_akcipher *child_tfm;
- child_tfm = crypto_spawn_akcipher(akcipher_instance_ctx(inst));
+ child_tfm = crypto_spawn_akcipher(&ictx->spawn);
if (IS_ERR(child_tfm))
return PTR_ERR(child_tfm);
ctx->child = child_tfm;
- ctx->hash_name = ictx->hash_name;
return 0;
}
@@ -648,12 +636,12 @@ static void pkcs1pad_free(struct akcipher_instance *inst)
struct crypto_akcipher_spawn *spawn = &ctx->spawn;
crypto_drop_akcipher(spawn);
- kfree(ctx->hash_name);
kfree(inst);
}
static int pkcs1pad_create(struct crypto_template *tmpl, struct rtattr **tb)
{
+ const struct rsa_asn1_template *digest_info;
struct crypto_attr_type *algt;
struct akcipher_instance *inst;
struct pkcs1pad_inst_ctx *ctx;
@@ -676,7 +664,11 @@ static int pkcs1pad_create(struct crypto_template *tmpl, struct rtattr **tb)
hash_name = crypto_attr_alg_name(tb[2]);
if (IS_ERR(hash_name))
- hash_name = NULL;
+ return PTR_ERR(hash_name);
+
+ digest_info = rsa_lookup_asn1(hash_name);
+ if (!digest_info)
+ return -EINVAL;
inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL);
if (!inst)
@@ -684,7 +676,7 @@ static int pkcs1pad_create(struct crypto_template *tmpl, struct rtattr **tb)
ctx = akcipher_instance_ctx(inst);
spawn = &ctx->spawn;
- ctx->hash_name = hash_name ? kstrdup(hash_name, GFP_KERNEL) : NULL;
+ ctx->digest_info = digest_info;
crypto_set_spawn(&spawn->base, akcipher_crypto_instance(inst));
err = crypto_grab_akcipher(spawn, rsa_alg_name, 0,
@@ -696,27 +688,14 @@ static int pkcs1pad_create(struct crypto_template *tmpl, struct rtattr **tb)
err = -ENAMETOOLONG;
- if (!hash_name) {
- if (snprintf(inst->alg.base.cra_name,
- CRYPTO_MAX_ALG_NAME, "pkcs1pad(%s)",
- rsa_alg->base.cra_name) >=
- CRYPTO_MAX_ALG_NAME ||
- snprintf(inst->alg.base.cra_driver_name,
- CRYPTO_MAX_ALG_NAME, "pkcs1pad(%s)",
- rsa_alg->base.cra_driver_name) >=
- CRYPTO_MAX_ALG_NAME)
+ if (snprintf(inst->alg.base.cra_name, CRYPTO_MAX_ALG_NAME,
+ "pkcs1pad(%s,%s)", rsa_alg->base.cra_name, hash_name) >=
+ CRYPTO_MAX_ALG_NAME ||
+ snprintf(inst->alg.base.cra_driver_name, CRYPTO_MAX_ALG_NAME,
+ "pkcs1pad(%s,%s)",
+ rsa_alg->base.cra_driver_name, hash_name) >=
+ CRYPTO_MAX_ALG_NAME)
goto out_drop_alg;
- } else {
- if (snprintf(inst->alg.base.cra_name,
- CRYPTO_MAX_ALG_NAME, "pkcs1pad(%s,%s)",
- rsa_alg->base.cra_name, hash_name) >=
- CRYPTO_MAX_ALG_NAME ||
- snprintf(inst->alg.base.cra_driver_name,
- CRYPTO_MAX_ALG_NAME, "pkcs1pad(%s,%s)",
- rsa_alg->base.cra_driver_name, hash_name) >=
- CRYPTO_MAX_ALG_NAME)
- goto out_free_hash;
- }
inst->alg.base.cra_flags = rsa_alg->base.cra_flags & CRYPTO_ALG_ASYNC;
inst->alg.base.cra_priority = rsa_alg->base.cra_priority;
@@ -738,12 +717,10 @@ static int pkcs1pad_create(struct crypto_template *tmpl, struct rtattr **tb)
err = akcipher_register_instance(tmpl, inst);
if (err)
- goto out_free_hash;
+ goto out_drop_alg;
return 0;
-out_free_hash:
- kfree(ctx->hash_name);
out_drop_alg:
crypto_drop_akcipher(spawn);
out_free_inst:
^ permalink raw reply related
* [PATCH 1/8] crypto: testmgr - Allow leading zeros in RSA
From: Herbert Xu @ 2016-06-22 10:16 UTC (permalink / raw)
To: Andrzej Zaborowski, Tadeusz Struk, Linux Crypto Mailing List,
Tudor Ambarus, Stephan Mueller
In-Reply-To: <20160622101432.GA30454@gondor.apana.org.au>
This patch allows RSA implementations to produce output with
leading zeroes. testmgr will skip leading zeroes when comparing
the output.
This patch also tries to make the RSA test function generic enough
to potentially handle other akcipher algorithms.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---
crypto/testmgr.c | 51 ++++++++++++++++++++++++---------------------------
1 file changed, 24 insertions(+), 27 deletions(-)
diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index b773a56..f4982da 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -1777,8 +1777,8 @@ static int alg_test_drbg(const struct alg_test_desc *desc, const char *driver,
}
-static int do_test_rsa(struct crypto_akcipher *tfm,
- struct akcipher_testvec *vecs)
+static int test_akcipher_one(struct crypto_akcipher *tfm,
+ struct akcipher_testvec *vecs)
{
char *xbuf[XBUFSIZE];
struct akcipher_request *req;
@@ -1829,17 +1829,18 @@ static int do_test_rsa(struct crypto_akcipher *tfm,
/* Run RSA encrypt - c = m^e mod n;*/
err = wait_async_op(&result, crypto_akcipher_encrypt(req));
if (err) {
- pr_err("alg: rsa: encrypt test failed. err %d\n", err);
+ pr_err("alg: akcipher: encrypt test failed. err %d\n", err);
goto free_all;
}
if (req->dst_len != vecs->c_size) {
- pr_err("alg: rsa: encrypt test failed. Invalid output len\n");
+ pr_err("alg: akcipher: encrypt test failed. Invalid output len\n");
err = -EINVAL;
goto free_all;
}
/* verify that encrypted message is equal to expected */
if (memcmp(vecs->c, outbuf_enc, vecs->c_size)) {
- pr_err("alg: rsa: encrypt test failed. Invalid output\n");
+ pr_err("alg: akcipher: encrypt test failed. Invalid output\n");
+ hexdump(outbuf_enc, vecs->c_size);
err = -EINVAL;
goto free_all;
}
@@ -1867,18 +1868,22 @@ static int do_test_rsa(struct crypto_akcipher *tfm,
/* Run RSA decrypt - m = c^d mod n;*/
err = wait_async_op(&result, crypto_akcipher_decrypt(req));
if (err) {
- pr_err("alg: rsa: decrypt test failed. err %d\n", err);
+ pr_err("alg: akcipher: decrypt test failed. err %d\n", err);
goto free_all;
}
out_len = req->dst_len;
- if (out_len != vecs->m_size) {
- pr_err("alg: rsa: decrypt test failed. Invalid output len\n");
+ if (out_len < vecs->m_size) {
+ pr_err("alg: akcipher: decrypt test failed. "
+ "Invalid output len %u\n", out_len);
err = -EINVAL;
goto free_all;
}
/* verify that decrypted message is equal to the original msg */
- if (memcmp(vecs->m, outbuf_dec, vecs->m_size)) {
- pr_err("alg: rsa: decrypt test failed. Invalid output\n");
+ if (memchr_inv(outbuf_dec, 0, out_len - vecs->m_size) ||
+ memcmp(vecs->m, outbuf_dec + out_len - vecs->m_size,
+ vecs->m_size)) {
+ pr_err("alg: akcipher: decrypt test failed. Invalid output\n");
+ hexdump(outbuf_dec, out_len);
err = -EINVAL;
}
free_all:
@@ -1891,28 +1896,20 @@ free_xbuf:
return err;
}
-static int test_rsa(struct crypto_akcipher *tfm, struct akcipher_testvec *vecs,
- unsigned int tcount)
+static int test_akcipher(struct crypto_akcipher *tfm, const char *alg,
+ struct akcipher_testvec *vecs, unsigned int tcount)
{
int ret, i;
for (i = 0; i < tcount; i++) {
- ret = do_test_rsa(tfm, vecs++);
- if (ret) {
- pr_err("alg: rsa: test failed on vector %d, err=%d\n",
- i + 1, ret);
- return ret;
- }
- }
- return 0;
-}
-
-static int test_akcipher(struct crypto_akcipher *tfm, const char *alg,
- struct akcipher_testvec *vecs, unsigned int tcount)
-{
- if (strncmp(alg, "rsa", 3) == 0)
- return test_rsa(tfm, vecs, tcount);
+ ret = test_akcipher_one(tfm, vecs++);
+ if (!ret)
+ continue;
+ pr_err("alg: akcipher: test failed on vector %d, err=%d\n",
+ i + 1, ret);
+ return ret;
+ }
return 0;
}
^ permalink raw reply related
* [PATCH 6/8] crypto: rsa-pkcs1pad - Always use GFP_KERNEL
From: Herbert Xu @ 2016-06-22 10:16 UTC (permalink / raw)
To: Andrzej Zaborowski, Tadeusz Struk, Linux Crypto Mailing List,
Tudor Ambarus, Stephan Mueller
In-Reply-To: <20160622101432.GA30454@gondor.apana.org.au>
We don't currently support using akcipher in atomic contexts,
so GFP_KERNEL should always be used.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---
crypto/rsa-pkcs1pad.c | 22 ++++++----------------
1 file changed, 6 insertions(+), 16 deletions(-)
diff --git a/crypto/rsa-pkcs1pad.c b/crypto/rsa-pkcs1pad.c
index d9baefb..db19284 100644
--- a/crypto/rsa-pkcs1pad.c
+++ b/crypto/rsa-pkcs1pad.c
@@ -260,8 +260,7 @@ static int pkcs1pad_encrypt(struct akcipher_request *req)
req_ctx->child_req.dst_len = ctx->key_size;
req_ctx->in_buf = kmalloc(ctx->key_size - 1 - req->src_len,
- (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ?
- GFP_KERNEL : GFP_ATOMIC);
+ GFP_KERNEL);
if (!req_ctx->in_buf)
return -ENOMEM;
@@ -274,9 +273,7 @@ static int pkcs1pad_encrypt(struct akcipher_request *req)
pkcs1pad_sg_set_buf(req_ctx->in_sg, req_ctx->in_buf,
ctx->key_size - 1 - req->src_len, req->src);
- req_ctx->out_buf = kmalloc(ctx->key_size,
- (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ?
- GFP_KERNEL : GFP_ATOMIC);
+ req_ctx->out_buf = kmalloc(ctx->key_size, GFP_KERNEL);
if (!req_ctx->out_buf) {
kfree(req_ctx->in_buf);
return -ENOMEM;
@@ -379,9 +376,7 @@ static int pkcs1pad_decrypt(struct akcipher_request *req)
req_ctx->child_req.dst = req_ctx->out_sg;
req_ctx->child_req.dst_len = ctx->key_size ;
- req_ctx->out_buf = kmalloc(ctx->key_size,
- (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ?
- GFP_KERNEL : GFP_ATOMIC);
+ req_ctx->out_buf = kmalloc(ctx->key_size, GFP_KERNEL);
if (!req_ctx->out_buf)
return -ENOMEM;
@@ -438,8 +433,7 @@ static int pkcs1pad_sign(struct akcipher_request *req)
req_ctx->child_req.dst_len = ctx->key_size;
req_ctx->in_buf = kmalloc(ctx->key_size - 1 - req->src_len,
- (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ?
- GFP_KERNEL : GFP_ATOMIC);
+ GFP_KERNEL);
if (!req_ctx->in_buf)
return -ENOMEM;
@@ -454,9 +448,7 @@ static int pkcs1pad_sign(struct akcipher_request *req)
pkcs1pad_sg_set_buf(req_ctx->in_sg, req_ctx->in_buf,
ctx->key_size - 1 - req->src_len, req->src);
- req_ctx->out_buf = kmalloc(ctx->key_size,
- (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ?
- GFP_KERNEL : GFP_ATOMIC);
+ req_ctx->out_buf = kmalloc(ctx->key_size, GFP_KERNEL);
if (!req_ctx->out_buf) {
kfree(req_ctx->in_buf);
return -ENOMEM;
@@ -577,9 +569,7 @@ static int pkcs1pad_verify(struct akcipher_request *req)
req_ctx->child_req.dst = req_ctx->out_sg;
req_ctx->child_req.dst_len = ctx->key_size;
- req_ctx->out_buf = kmalloc(ctx->key_size,
- (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ?
- GFP_KERNEL : GFP_ATOMIC);
+ req_ctx->out_buf = kmalloc(ctx->key_size, GFP_KERNEL);
if (!req_ctx->out_buf)
return -ENOMEM;
^ permalink raw reply related
* Re: [[PATCH v2] 11/11] hwrng: exynos - fixup IO accesors
From: Ben Dooks @ 2016-06-22 11:53 UTC (permalink / raw)
To: Herbert Xu
Cc: linux-kernel, k.kozlowski, linux-samsung-soc, matthew.leach,
linux-crypto, mpm, linux-arm-kernel
In-Reply-To: <20160622103705.GA30967@gondor.apana.org.au>
On 22/06/16 11:37, Herbert Xu wrote:
> Ben Dooks <ben.dooks@codethink.co.uk> wrote:
>> The __raw IO functions are not endian safe, so use the readl_relaxed
>> and writel_relaxed versions of these.
>>
>> Signed-off-by: Ben Dooks <ben.dooks@codethink.co.uk>
>
> This patch has already been merged.
>
> Cheers,
Apologies, only meant to repost the core patches.
--
Ben Dooks http://www.codethink.co.uk/
Senior Engineer Codethink - Providing Genius
^ permalink raw reply
* Re: [PATCH v3 02/10] crypto: marvell: Check engine is not already running when enabling a req
From: Romain Perier @ 2016-06-22 11:23 UTC (permalink / raw)
To: Herbert Xu
Cc: thomas.petazzoni, boris.brezillon, linux, arno, linux-crypto,
gregory.clement, davem, linux-arm-kernel
In-Reply-To: <20160622103324.GA30918@gondor.apana.org.au>
Hello,
Le 22/06/2016 12:33, Herbert Xu a écrit :
> Romain Perier <romain.perier@free-electrons.com> wrote:
>> Add a BUG_ON() call when the driver tries to launch a crypto request
>> while the engine is still processing the previous one. This replaces
>> a silent system hang by a verbose kernel panic with the associated
>> backtrace to let the user know that something went wrong in the CESA
>> driver.
>
> Hmm, so how can this happen?
If it is triggerable then we better
> try to recover from it more gracefully. If it is not triggerable
> then why bother?
>
Well, It does not happen with the current driver (in mainline). This is
bug I had when I added support to chain requests. Take a look at the
patch 008/010, it changes the way the requests are "prepared". If you
really enable a request while the engine is running, that's very hard to
debug. This is more useful to have a backtrace to let the user know that
something is wrong instead of having a silent system hang. That's easier
to debug and you can detect regressions.
Regards,
Romain
--
Romain Perier, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
^ permalink raw reply
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