Mailing List Archive

[PATCH] crypto: add alignment handling to digest layer
Some hash modules load/store data words directly. The digest layer
should pass properly aligned buffer to update()/final() method. This
patch also add cra_alignmask to some hash modules.

Signed-off-by: Atsushi Nemoto <anemo@mba.ocn.ne.jp>

digest.c | 42 +++++++++++++++++++++++++++---------------
michael_mic.c | 1 +
sha1.c | 1 +
sha256.c | 1 +
sha512.c | 2 ++
tgr192.c | 3 +++
6 files changed, 35 insertions(+), 15 deletions(-)

diff --git a/crypto/digest.c b/crypto/digest.c
index d9b6ac9..062d0a5 100644
--- a/crypto/digest.c
+++ b/crypto/digest.c
@@ -27,6 +27,7 @@ static void update(struct crypto_tfm *tf
struct scatterlist *sg, unsigned int nsg)
{
unsigned int i;
+ unsigned int alignmask = crypto_tfm_alg_alignmask(tfm);

for (i = 0; i < nsg; i++) {

@@ -38,12 +39,24 @@ static void update(struct crypto_tfm *tf
unsigned int bytes_from_page = min(l, ((unsigned int)
(PAGE_SIZE)) -
offset);
- char *p = crypto_kmap(pg, 0) + offset;
+ char *src = crypto_kmap(pg, 0);
+ char *p = src + offset;

+ if (unlikely(offset & alignmask)) {
+ unsigned int bytes =
+ alignmask + 1 - (offset & alignmask);
+ bytes = min(bytes, bytes_from_page);
+ tfm->__crt_alg->cra_digest.dia_update
+ (crypto_tfm_ctx(tfm), p,
+ bytes);
+ p += bytes;
+ bytes_from_page -= bytes;
+ l -= bytes;
+ }
tfm->__crt_alg->cra_digest.dia_update
(crypto_tfm_ctx(tfm), p,
bytes_from_page);
- crypto_kunmap(p, 0);
+ crypto_kunmap(src, 0);
crypto_yield(tfm);
offset = 0;
pg++;
@@ -54,7 +67,15 @@ static void update(struct crypto_tfm *tf

static void final(struct crypto_tfm *tfm, u8 *out)
{
- tfm->__crt_alg->cra_digest.dia_final(crypto_tfm_ctx(tfm), out);
+ unsigned long alignmask = crypto_tfm_alg_alignmask(tfm);
+ if (unlikely((unsigned long)out & alignmask)) {
+ unsigned int size = crypto_tfm_alg_digestsize(tfm);
+ u8 buffer[size + alignmask];
+ u8 *dst = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1);
+ tfm->__crt_alg->cra_digest.dia_final(crypto_tfm_ctx(tfm), dst);
+ memcpy(out, dst, size);
+ } else
+ tfm->__crt_alg->cra_digest.dia_final(crypto_tfm_ctx(tfm), out);
}

static int setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen)
@@ -69,18 +90,9 @@ static int setkey(struct crypto_tfm *tfm
static void digest(struct crypto_tfm *tfm,
struct scatterlist *sg, unsigned int nsg, u8 *out)
{
- unsigned int i;
-
- tfm->crt_digest.dit_init(tfm);
-
- for (i = 0; i < nsg; i++) {
- char *p = crypto_kmap(sg[i].page, 0) + sg[i].offset;
- tfm->__crt_alg->cra_digest.dia_update(crypto_tfm_ctx(tfm),
- p, sg[i].length);
- crypto_kunmap(p, 0);
- crypto_yield(tfm);
- }
- crypto_digest_final(tfm, out);
+ init(tfm);
+ update(tfm, sg, nsg);
+ final(tfm, out);
}

int crypto_init_digest_flags(struct crypto_tfm *tfm, u32 flags)
diff --git a/crypto/michael_mic.c b/crypto/michael_mic.c
index 4f6ab23..701f859 100644
--- a/crypto/michael_mic.c
+++ b/crypto/michael_mic.c
@@ -145,6 +145,7 @@ static struct crypto_alg michael_mic_alg
.cra_blocksize = 8,
.cra_ctxsize = sizeof(struct michael_mic_ctx),
.cra_module = THIS_MODULE,
+ .cra_alignmask = 3,
.cra_list = LIST_HEAD_INIT(michael_mic_alg.cra_list),
.cra_u = { .digest = {
.dia_digestsize = 8,
diff --git a/crypto/sha1.c b/crypto/sha1.c
index 21571ed..b96f57d 100644
--- a/crypto/sha1.c
+++ b/crypto/sha1.c
@@ -112,6 +112,7 @@ static struct crypto_alg alg = {
.cra_blocksize = SHA1_HMAC_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct sha1_ctx),
.cra_module = THIS_MODULE,
+ .cra_alignmask = 3,
.cra_list = LIST_HEAD_INIT(alg.cra_list),
.cra_u = { .digest = {
.dia_digestsize = SHA1_DIGEST_SIZE,
diff --git a/crypto/sha256.c b/crypto/sha256.c
index 9d5ef67..d62264a 100644
--- a/crypto/sha256.c
+++ b/crypto/sha256.c
@@ -313,6 +313,7 @@ static struct crypto_alg alg = {
.cra_blocksize = SHA256_HMAC_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct sha256_ctx),
.cra_module = THIS_MODULE,
+ .cra_alignmask = 3,
.cra_list = LIST_HEAD_INIT(alg.cra_list),
.cra_u = { .digest = {
.dia_digestsize = SHA256_DIGEST_SIZE,
diff --git a/crypto/sha512.c b/crypto/sha512.c
index 3e6e939..7dbec4f 100644
--- a/crypto/sha512.c
+++ b/crypto/sha512.c
@@ -281,6 +281,7 @@ static struct crypto_alg sha512 = {
.cra_blocksize = SHA512_HMAC_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct sha512_ctx),
.cra_module = THIS_MODULE,
+ .cra_alignmask = 3,
.cra_list = LIST_HEAD_INIT(sha512.cra_list),
.cra_u = { .digest = {
.dia_digestsize = SHA512_DIGEST_SIZE,
@@ -295,6 +296,7 @@ static struct crypto_alg sha384 = {
.cra_flags = CRYPTO_ALG_TYPE_DIGEST,
.cra_blocksize = SHA384_HMAC_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct sha512_ctx),
+ .cra_alignmask = 3,
.cra_module = THIS_MODULE,
.cra_list = LIST_HEAD_INIT(sha384.cra_list),
.cra_u = { .digest = {
diff --git a/crypto/tgr192.c b/crypto/tgr192.c
index 2d8e44f..1eae1bb 100644
--- a/crypto/tgr192.c
+++ b/crypto/tgr192.c
@@ -627,6 +627,7 @@ static struct crypto_alg tgr192 = {
.cra_blocksize = TGR192_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct tgr192_ctx),
.cra_module = THIS_MODULE,
+ .cra_alignmask = 7,
.cra_list = LIST_HEAD_INIT(tgr192.cra_list),
.cra_u = {.digest = {
.dia_digestsize = TGR192_DIGEST_SIZE,
@@ -641,6 +642,7 @@ static struct crypto_alg tgr160 = {
.cra_blocksize = TGR192_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct tgr192_ctx),
.cra_module = THIS_MODULE,
+ .cra_alignmask = 7,
.cra_list = LIST_HEAD_INIT(tgr160.cra_list),
.cra_u = {.digest = {
.dia_digestsize = TGR160_DIGEST_SIZE,
@@ -655,6 +657,7 @@ static struct crypto_alg tgr128 = {
.cra_blocksize = TGR192_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct tgr192_ctx),
.cra_module = THIS_MODULE,
+ .cra_alignmask = 7,
.cra_list = LIST_HEAD_INIT(tgr128.cra_list),
.cra_u = {.digest = {
.dia_digestsize = TGR128_DIGEST_SIZE,
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH] crypto: add alignment handling to digest layer [ In reply to ]
Ping. This patch can be applied cleanly to 2.6.17-rc1.


Some hash modules load/store data words directly. The digest layer
should pass properly aligned buffer to update()/final() method. This
patch also add cra_alignmask to some hash modules.

Signed-off-by: Atsushi Nemoto <anemo@mba.ocn.ne.jp>

digest.c | 42 +++++++++++++++++++++++++++---------------
michael_mic.c | 1 +
sha1.c | 1 +
sha256.c | 1 +
sha512.c | 2 ++
tgr192.c | 3 +++
6 files changed, 35 insertions(+), 15 deletions(-)

diff --git a/crypto/digest.c b/crypto/digest.c
index d9b6ac9..062d0a5 100644
--- a/crypto/digest.c
+++ b/crypto/digest.c
@@ -27,6 +27,7 @@ static void update(struct crypto_tfm *tf
struct scatterlist *sg, unsigned int nsg)
{
unsigned int i;
+ unsigned int alignmask = crypto_tfm_alg_alignmask(tfm);

for (i = 0; i < nsg; i++) {

@@ -38,12 +39,24 @@ static void update(struct crypto_tfm *tf
unsigned int bytes_from_page = min(l, ((unsigned int)
(PAGE_SIZE)) -
offset);
- char *p = crypto_kmap(pg, 0) + offset;
+ char *src = crypto_kmap(pg, 0);
+ char *p = src + offset;

+ if (unlikely(offset & alignmask)) {
+ unsigned int bytes =
+ alignmask + 1 - (offset & alignmask);
+ bytes = min(bytes, bytes_from_page);
+ tfm->__crt_alg->cra_digest.dia_update
+ (crypto_tfm_ctx(tfm), p,
+ bytes);
+ p += bytes;
+ bytes_from_page -= bytes;
+ l -= bytes;
+ }
tfm->__crt_alg->cra_digest.dia_update
(crypto_tfm_ctx(tfm), p,
bytes_from_page);
- crypto_kunmap(p, 0);
+ crypto_kunmap(src, 0);
crypto_yield(tfm);
offset = 0;
pg++;
@@ -54,7 +67,15 @@ static void update(struct crypto_tfm *tf

static void final(struct crypto_tfm *tfm, u8 *out)
{
- tfm->__crt_alg->cra_digest.dia_final(crypto_tfm_ctx(tfm), out);
+ unsigned long alignmask = crypto_tfm_alg_alignmask(tfm);
+ if (unlikely((unsigned long)out & alignmask)) {
+ unsigned int size = crypto_tfm_alg_digestsize(tfm);
+ u8 buffer[size + alignmask];
+ u8 *dst = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1);
+ tfm->__crt_alg->cra_digest.dia_final(crypto_tfm_ctx(tfm), dst);
+ memcpy(out, dst, size);
+ } else
+ tfm->__crt_alg->cra_digest.dia_final(crypto_tfm_ctx(tfm), out);
}

static int setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen)
@@ -69,18 +90,9 @@ static int setkey(struct crypto_tfm *tfm
static void digest(struct crypto_tfm *tfm,
struct scatterlist *sg, unsigned int nsg, u8 *out)
{
- unsigned int i;
-
- tfm->crt_digest.dit_init(tfm);
-
- for (i = 0; i < nsg; i++) {
- char *p = crypto_kmap(sg[i].page, 0) + sg[i].offset;
- tfm->__crt_alg->cra_digest.dia_update(crypto_tfm_ctx(tfm),
- p, sg[i].length);
- crypto_kunmap(p, 0);
- crypto_yield(tfm);
- }
- crypto_digest_final(tfm, out);
+ init(tfm);
+ update(tfm, sg, nsg);
+ final(tfm, out);
}

int crypto_init_digest_flags(struct crypto_tfm *tfm, u32 flags)
diff --git a/crypto/michael_mic.c b/crypto/michael_mic.c
index 4f6ab23..701f859 100644
--- a/crypto/michael_mic.c
+++ b/crypto/michael_mic.c
@@ -145,6 +145,7 @@ static struct crypto_alg michael_mic_alg
.cra_blocksize = 8,
.cra_ctxsize = sizeof(struct michael_mic_ctx),
.cra_module = THIS_MODULE,
+ .cra_alignmask = 3,
.cra_list = LIST_HEAD_INIT(michael_mic_alg.cra_list),
.cra_u = { .digest = {
.dia_digestsize = 8,
diff --git a/crypto/sha1.c b/crypto/sha1.c
index 21571ed..b96f57d 100644
--- a/crypto/sha1.c
+++ b/crypto/sha1.c
@@ -112,6 +112,7 @@ static struct crypto_alg alg = {
.cra_blocksize = SHA1_HMAC_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct sha1_ctx),
.cra_module = THIS_MODULE,
+ .cra_alignmask = 3,
.cra_list = LIST_HEAD_INIT(alg.cra_list),
.cra_u = { .digest = {
.dia_digestsize = SHA1_DIGEST_SIZE,
diff --git a/crypto/sha256.c b/crypto/sha256.c
index 9d5ef67..d62264a 100644
--- a/crypto/sha256.c
+++ b/crypto/sha256.c
@@ -313,6 +313,7 @@ static struct crypto_alg alg = {
.cra_blocksize = SHA256_HMAC_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct sha256_ctx),
.cra_module = THIS_MODULE,
+ .cra_alignmask = 3,
.cra_list = LIST_HEAD_INIT(alg.cra_list),
.cra_u = { .digest = {
.dia_digestsize = SHA256_DIGEST_SIZE,
diff --git a/crypto/sha512.c b/crypto/sha512.c
index 3e6e939..7dbec4f 100644
--- a/crypto/sha512.c
+++ b/crypto/sha512.c
@@ -281,6 +281,7 @@ static struct crypto_alg sha512 = {
.cra_blocksize = SHA512_HMAC_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct sha512_ctx),
.cra_module = THIS_MODULE,
+ .cra_alignmask = 3,
.cra_list = LIST_HEAD_INIT(sha512.cra_list),
.cra_u = { .digest = {
.dia_digestsize = SHA512_DIGEST_SIZE,
@@ -295,6 +296,7 @@ static struct crypto_alg sha384 = {
.cra_flags = CRYPTO_ALG_TYPE_DIGEST,
.cra_blocksize = SHA384_HMAC_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct sha512_ctx),
+ .cra_alignmask = 3,
.cra_module = THIS_MODULE,
.cra_list = LIST_HEAD_INIT(sha384.cra_list),
.cra_u = { .digest = {
diff --git a/crypto/tgr192.c b/crypto/tgr192.c
index 2d8e44f..1eae1bb 100644
--- a/crypto/tgr192.c
+++ b/crypto/tgr192.c
@@ -627,6 +627,7 @@ static struct crypto_alg tgr192 = {
.cra_blocksize = TGR192_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct tgr192_ctx),
.cra_module = THIS_MODULE,
+ .cra_alignmask = 7,
.cra_list = LIST_HEAD_INIT(tgr192.cra_list),
.cra_u = {.digest = {
.dia_digestsize = TGR192_DIGEST_SIZE,
@@ -641,6 +642,7 @@ static struct crypto_alg tgr160 = {
.cra_blocksize = TGR192_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct tgr192_ctx),
.cra_module = THIS_MODULE,
+ .cra_alignmask = 7,
.cra_list = LIST_HEAD_INIT(tgr160.cra_list),
.cra_u = {.digest = {
.dia_digestsize = TGR160_DIGEST_SIZE,
@@ -655,6 +657,7 @@ static struct crypto_alg tgr128 = {
.cra_blocksize = TGR192_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct tgr192_ctx),
.cra_module = THIS_MODULE,
+ .cra_alignmask = 7,
.cra_list = LIST_HEAD_INIT(tgr128.cra_list),
.cra_u = {.digest = {
.dia_digestsize = TGR128_DIGEST_SIZE,
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH] crypto: add alignment handling to digest layer [ In reply to ]
On Tue, Apr 04, 2006 at 12:04:07AM +0900, Atsushi Nemoto wrote:
>
> Some hash modules load/store data words directly. The digest layer
> should pass properly aligned buffer to update()/final() method. This
> patch also add cra_alignmask to some hash modules.

This patch is in my queue. I'll be travelling for the next couple of
weeks but I'll get onto it after that.

Thanks,
--
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au>
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-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH] crypto: add alignment handling to digest layer [ In reply to ]
On Tue, Apr 04, 2006 at 12:04:07AM +0900, Atsushi Nemoto wrote:
>
> @@ -38,12 +39,24 @@ static void update(struct crypto_tfm *tf
> unsigned int bytes_from_page = min(l, ((unsigned int)
> (PAGE_SIZE)) -
> offset);
> - char *p = crypto_kmap(pg, 0) + offset;
> + char *src = crypto_kmap(pg, 0);
> + char *p = src + offset;
>
> + if (unlikely(offset & alignmask)) {
> + unsigned int bytes =
> + alignmask + 1 - (offset & alignmask);
> + bytes = min(bytes, bytes_from_page);
> + tfm->__crt_alg->cra_digest.dia_update
> + (crypto_tfm_ctx(tfm), p,
> + bytes);

Don't we need to copy this to an aligned buffer?

Thanks,
--
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au>
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-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH] crypto: add alignment handling to digest layer [ In reply to ]
On Thu, 6 Apr 2006 04:05:20 +1000, Herbert Xu <herbert@gondor.apana.org.au> wrote:
> Don't we need to copy this to an aligned buffer?

We don't. I think update functions do not need an aligned buffer for
data which is smaller then the alignment size.

---
Atsushi Nemoto
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH] crypto: add alignment handling to digest layer [ In reply to ]
On Thu, Apr 06, 2006 at 11:37:42AM +0900, Atsushi Nemoto wrote:
>
> We don't. I think update functions do not need an aligned buffer for
> data which is smaller then the alignment size.

You're right. If we do ever get any hardware that requires this we can
always change it later on.

Another thing, could you pleas change the stack allocation in final so
that it does it like cbc_process_decrypt? The reason is that gcc is too
stupid to not allocate that buffer unconditionally.

Thanks,
--
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au>
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-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH] crypto: add alignment handling to digest layer [ In reply to ]
On Fri, 7 Apr 2006 09:24:54 +1000, Herbert Xu <herbert@gondor.apana.org.au> wrote:
> Another thing, could you pleas change the stack allocation in final so
> that it does it like cbc_process_decrypt? The reason is that gcc is too
> stupid to not allocate that buffer unconditionally.

I can do it, but it will add another overhead. (we must call
crypto_tfm_alg_digestsize() unconditionally)

It seems modern gcc (at least gcc 3.4 on i386 and mips) can allocate
the buffer conditionally. It is better to optimize for newer gcc,
isn't it?

---
Atsushi Nemoto
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH] crypto: add alignment handling to digest layer [ In reply to ]
On Fri, Apr 07, 2006 at 02:27:55PM +0900, Atsushi Nemoto wrote:
>
> It seems modern gcc (at least gcc 3.4 on i386 and mips) can allocate
> the buffer conditionally. It is better to optimize for newer gcc,
> isn't it?

Of course it does. I must've been confused.

Cheers,
--
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au>
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-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH] crypto: add alignment handling to digest layer [ In reply to ]
On Tue, Apr 04, 2006 at 12:04:07AM +0900, Atsushi Nemoto wrote:
>
> Some hash modules load/store data words directly. The digest layer
> should pass properly aligned buffer to update()/final() method. This
> patch also add cra_alignmask to some hash modules.
>
> Signed-off-by: Atsushi Nemoto <anemo@mba.ocn.ne.jp>

Patch applied. Thanks a lot.
--
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au>
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-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/