2009-07-07 07:21:04

by Steffen Klassert

[permalink] [raw]
Subject: [RFC] [PATCH 0/3] convert hmac to ahash

This patchset converts hmac to the new ahash frontend. It has just some
basic tests and is not yet for inclusion.

Steffen


2009-07-07 07:22:11

by Steffen Klassert

[permalink] [raw]
Subject: [RFC] [PATCH 1/3] crypto: ahash - Add some helper functions


Signed-off-by: Steffen Klassert <[email protected]>
---
include/crypto/hash.h | 25 +++++++++++++++++++++++++
include/crypto/internal/hash.h | 5 +++++
2 files changed, 30 insertions(+), 0 deletions(-)

diff --git a/include/crypto/hash.h b/include/crypto/hash.h
index d56bb71..bd473a0 100644
--- a/include/crypto/hash.h
+++ b/include/crypto/hash.h
@@ -14,6 +14,7 @@
#define _CRYPTO_HASH_H

#include <linux/crypto.h>
+#include <crypto/algapi.h>

struct shash_desc {
struct crypto_shash *tfm;
@@ -54,6 +55,15 @@ static inline struct crypto_ahash *__crypto_ahash_cast(struct crypto_tfm *tfm)
return (struct crypto_ahash *)tfm;
}

+static inline struct crypto_ahash *crypto_spawn_ahash(
+ struct crypto_spawn *spawn)
+{
+ u32 type = CRYPTO_ALG_TYPE_AHASH;
+ u32 mask = CRYPTO_ALG_TYPE_AHASH_MASK;
+
+ return __crypto_ahash_cast(crypto_spawn_tfm(spawn, type, mask));
+}
+
static inline struct crypto_ahash *crypto_alloc_ahash(const char *alg_name,
u32 type, u32 mask)
{
@@ -86,6 +96,11 @@ static inline struct ahash_tfm *crypto_ahash_crt(struct crypto_ahash *tfm)
return &crypto_ahash_tfm(tfm)->crt_ahash;
}

+static inline unsigned int crypto_ahash_blocksize(struct crypto_ahash *tfm)
+{
+ return crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm));
+}
+
static inline unsigned int crypto_ahash_digestsize(struct crypto_ahash *tfm)
{
return crypto_ahash_crt(tfm)->digestsize;
@@ -162,6 +177,16 @@ static inline int crypto_ahash_final(struct ahash_request *req)
return crt->final(req);
}

+static inline void ahash_request_complete(struct ahash_request *req, int err)
+{
+ req->base.complete(&req->base, err);
+}
+
+static inline u32 ahash_request_flags(struct ahash_request *req)
+{
+ return req->base.flags;
+}
+
static inline void ahash_request_set_tfm(struct ahash_request *req,
struct crypto_ahash *tfm)
{
diff --git a/include/crypto/internal/hash.h b/include/crypto/internal/hash.h
index 82b7056..bbcc076 100644
--- a/include/crypto/internal/hash.h
+++ b/include/crypto/internal/hash.h
@@ -51,6 +51,11 @@ static inline void *crypto_ahash_ctx(struct crypto_ahash *tfm)
return crypto_tfm_ctx(&tfm->base);
}

+static inline void *crypto_ahash_ctx_aligned(struct crypto_ahash *tfm)
+{
+ return crypto_tfm_ctx_aligned(&tfm->base);
+}
+
static inline struct ahash_alg *crypto_ahash_alg(
struct crypto_ahash *tfm)
{
--
1.5.4.2


2009-07-07 07:23:17

by Steffen Klassert

[permalink] [raw]
Subject: [RFC] [PATCH 2/3] crypto: ahash - add crypto_ahash_finup

This patch adds the finup method for ahash. This can be used to
do the last hash update and the hash final together.

Signed-off-by: Steffen Klassert <[email protected]>
---
crypto/ahash.c | 1 +
crypto/shash.c | 15 +++++++++++++++
include/crypto/hash.h | 6 ++++++
include/linux/crypto.h | 2 ++
4 files changed, 24 insertions(+), 0 deletions(-)

diff --git a/crypto/ahash.c b/crypto/ahash.c
index f347637..c2fbc6d 100644
--- a/crypto/ahash.c
+++ b/crypto/ahash.c
@@ -200,6 +200,7 @@ static int crypto_init_ahash_ops(struct crypto_tfm *tfm, u32 type, u32 mask)
crt->init = alg->init;
crt->update = alg->update;
crt->final = alg->final;
+ crt->finup = alg->finup;
crt->digest = alg->digest;
crt->setkey = alg->setkey ? ahash_setkey : ahash_nosetkey;
crt->digestsize = alg->digestsize;
diff --git a/crypto/shash.c b/crypto/shash.c
index 2ccc8b0..3f494fe 100644
--- a/crypto/shash.c
+++ b/crypto/shash.c
@@ -224,6 +224,20 @@ static int shash_async_final(struct ahash_request *req)
return crypto_shash_final(ahash_request_ctx(req), req->result);
}

+static int shash_async_finup(struct ahash_request *req)
+{
+ int err;
+
+ err = shash_async_update(req);
+ if (err)
+ goto out;
+
+ err = shash_async_final(req);
+
+out:
+ return err;
+}
+
static int shash_async_digest(struct ahash_request *req)
{
struct scatterlist *sg = req->src;
@@ -292,6 +306,7 @@ static int crypto_init_shash_ops_async(struct crypto_tfm *tfm)
crt->init = shash_async_init;
crt->update = shash_async_update;
crt->final = shash_async_final;
+ crt->finup = shash_async_finup;
crt->digest = shash_async_digest;
crt->setkey = shash_async_setkey;

diff --git a/include/crypto/hash.h b/include/crypto/hash.h
index bd473a0..7c36733 100644
--- a/include/crypto/hash.h
+++ b/include/crypto/hash.h
@@ -177,6 +177,12 @@ static inline int crypto_ahash_final(struct ahash_request *req)
return crt->final(req);
}

+static inline int crypto_ahash_finup(struct ahash_request *req)
+{
+ struct ahash_tfm *crt = crypto_ahash_crt(crypto_ahash_reqtfm(req));
+ return crt->finup(req);
+}
+
static inline void ahash_request_complete(struct ahash_request *req, int err)
{
req->base.complete(&req->base, err);
diff --git a/include/linux/crypto.h b/include/linux/crypto.h
index ec29fa2..ab3e4b8 100644
--- a/include/linux/crypto.h
+++ b/include/linux/crypto.h
@@ -225,6 +225,7 @@ struct ahash_alg {
int (*reinit)(struct ahash_request *req);
int (*update)(struct ahash_request *req);
int (*final)(struct ahash_request *req);
+ int (*finup)(struct ahash_request *req);
int (*digest)(struct ahash_request *req);
int (*setkey)(struct crypto_ahash *tfm, const u8 *key,
unsigned int keylen);
@@ -437,6 +438,7 @@ struct ahash_tfm {
int (*init)(struct ahash_request *req);
int (*update)(struct ahash_request *req);
int (*final)(struct ahash_request *req);
+ int (*finup)(struct ahash_request *req);
int (*digest)(struct ahash_request *req);
int (*setkey)(struct crypto_ahash *tfm, const u8 *key,
unsigned int keylen);
--
1.5.4.2


2009-07-07 07:24:19

by Steffen Klassert

[permalink] [raw]
Subject: [RFC] [PATCH 3/3] crypto: hmac - convert to ahash

This converts hmac to the new ahash frontend.
Also the hashing of the ipaded and opaded key is done now with the
setkey function, this saves some bytes of hashing on each request.

Signed-off-by: Steffen Klassert <[email protected]>
---
crypto/hmac.c | 471 +++++++++++++++++++++++++++++++++++++++++----------------
1 files changed, 340 insertions(+), 131 deletions(-)

diff --git a/crypto/hmac.c b/crypto/hmac.c
index 0ad39c3..c3b2c76 100644
--- a/crypto/hmac.c
+++ b/crypto/hmac.c
@@ -18,6 +18,7 @@

#include <crypto/internal/hash.h>
#include <crypto/scatterwalk.h>
+#include <linux/completion.h>
#include <linux/err.h>
#include <linux/init.h>
#include <linux/kernel.h>
@@ -27,192 +28,400 @@
#include <linux/string.h>

struct hmac_ctx {
- struct crypto_hash *child;
+ struct crypto_ahash *child;
+ struct ahash_request *ipad_req;
+ struct ahash_request *opad_req;
+ unsigned int reqoff;
};

-static inline void *align_ptr(void *p, unsigned int align)
+struct hmac_request_ctx {
+ struct scatterlist sg;
+ char tail[];
+};
+
+struct hmac_setkey_result {
+ int err;
+ struct completion completion;
+};
+
+static inline struct hmac_ctx *hmac_ctx(struct crypto_ahash *tfm)
{
- return (void *)ALIGN((unsigned long)p, align);
+ return PTR_ALIGN((void *)crypto_ahash_ctx_aligned(tfm) +
+ crypto_ahash_blocksize(tfm) * 2 +
+ crypto_ahash_digestsize(tfm),
+ crypto_ahash_alignmask(tfm) + 1);
}

-static inline struct hmac_ctx *hmac_ctx(struct crypto_hash *tfm)
+static int hmac_hash_pad(struct ahash_request *req,
+ struct hmac_setkey_result *result, u8 *out)
{
- return align_ptr(crypto_hash_ctx_aligned(tfm) +
- crypto_hash_blocksize(tfm) * 2 +
- crypto_hash_digestsize(tfm), sizeof(void *));
+ int err;
+
+ err = crypto_ahash_init(req);
+ if (err == -EINPROGRESS || err == -EBUSY) {
+ err = wait_for_completion_interruptible(&result->completion);
+ if (!err)
+ err = result->err;
+ }
+
+ if (err)
+ goto out;
+
+ err = crypto_ahash_update(req);
+ if (err == -EINPROGRESS || err == -EBUSY) {
+ err = wait_for_completion_interruptible(&result->completion);
+ if (!err)
+ err = result->err;
+ }
+
+ if (err)
+ goto out;
+
+ crypto_ahash_export(req, out);
+
+out:
+ return err;
}

-static int hmac_setkey(struct crypto_hash *parent,
+static void hmac_setkey_done(struct crypto_async_request *req, int err)
+{
+ struct hmac_setkey_result *result = req->data;
+
+ if (err == -EINPROGRESS)
+ return;
+
+ result->err = err;
+ complete(&result->completion);
+}
+
+static int hmac_setkey(struct crypto_ahash *parent,
const u8 *inkey, unsigned int keylen)
{
- int bs = crypto_hash_blocksize(parent);
- int ds = crypto_hash_digestsize(parent);
- char *ipad = crypto_hash_ctx_aligned(parent);
- char *opad = ipad + bs;
- char *digest = opad + bs;
- struct hmac_ctx *ctx = align_ptr(digest + ds, sizeof(void *));
- struct crypto_hash *tfm = ctx->child;
- unsigned int i;
+ int err, i;
+ int bs = crypto_ahash_blocksize(parent);
+ int ds = crypto_ahash_digestsize(parent);
+ struct hmac_ctx *ctx = crypto_ahash_ctx(parent);
+ struct {
+ u8 ipad[bs];
+ u8 opad[bs];
+ u8 digest[ds];
+ struct hmac_setkey_result result;
+ struct scatterlist sg;
+ struct ahash_request req;

- if (keylen > bs) {
- struct hash_desc desc;
- struct scatterlist tmp;
- int tmplen;
- int err;
+ } *data;

- desc.tfm = tfm;
- desc.flags = crypto_hash_get_flags(parent);
- desc.flags &= CRYPTO_TFM_REQ_MAY_SLEEP;
+ err = -ENOMEM;
+ data = kzalloc(sizeof(*data) + crypto_ahash_reqsize(parent) +
+ bs * 2 + ds, GFP_KERNEL);

- err = crypto_hash_init(&desc);
- if (err)
- return err;
+ if (!data)
+ goto out;

- tmplen = bs * 2 + ds;
- sg_init_one(&tmp, ipad, tmplen);
+ init_completion(&data->result.completion);

- for (; keylen > tmplen; inkey += tmplen, keylen -= tmplen) {
- memcpy(ipad, inkey, tmplen);
- err = crypto_hash_update(&desc, &tmp, tmplen);
- if (err)
- return err;
- }
+ ahash_request_set_tfm(&data->req, ctx->child);
+ ahash_request_set_callback(&data->req, CRYPTO_TFM_REQ_MAY_BACKLOG,
+ hmac_setkey_done, &data->result);

- if (keylen) {
- memcpy(ipad, inkey, keylen);
- err = crypto_hash_update(&desc, &tmp, keylen);
- if (err)
- return err;
+ if (keylen > bs) {
+ sg_init_one(&data->sg, inkey, keylen);
+
+ ahash_request_set_crypt(&data->req, &data->sg,
+ data->digest, keylen);
+
+ err = crypto_ahash_digest(&data->req);
+ if (err == -EINPROGRESS || err == -EBUSY) {
+ err = wait_for_completion_interruptible(
+ &data->result.completion);
+ if (!err)
+ err = data->result.err;
}

- err = crypto_hash_final(&desc, digest);
if (err)
- return err;
+ goto out_free;

- inkey = digest;
+ inkey = data->digest;
keylen = ds;
}

- memcpy(ipad, inkey, keylen);
- memset(ipad + keylen, 0, bs - keylen);
- memcpy(opad, ipad, bs);
+ memcpy(data->ipad, inkey, keylen);
+ memset(data->ipad + keylen, 0, bs - keylen);
+ memcpy(data->opad, data->ipad, bs);

for (i = 0; i < bs; i++) {
- ipad[i] ^= 0x36;
- opad[i] ^= 0x5c;
+ data->ipad[i] ^= 0x36;
+ data->opad[i] ^= 0x5c;
}

- return 0;
+ err = -ENOMEM;
+ ctx->ipad_req = kmalloc(crypto_ahash_reqsize(ctx->child), GFP_KERNEL);
+ if (!ctx->ipad_req)
+ goto out_free;
+ ctx->opad_req = kmalloc(crypto_ahash_reqsize(ctx->child), GFP_KERNEL);
+ if (!ctx->opad_req)
+ goto out_free;
+
+ sg_init_one(&data->sg, data->ipad, bs);
+
+ ahash_request_set_crypt(&data->req, &data->sg, data->digest, bs);
+
+ err = hmac_hash_pad(&data->req, &data->result, (u8 *)ctx->ipad_req);
+ if (err)
+ goto out_free;
+
+ sg_init_one(&data->sg, data->opad, bs);
+
+ ahash_request_set_crypt(&data->req, &data->sg, data->digest, bs);
+
+ err = hmac_hash_pad(&data->req, &data->result, (u8 *)ctx->opad_req);
+
+out_free:
+ kfree(data);
+out:
+ return err;
}

-static int hmac_init(struct hash_desc *pdesc)
+static int hmac_init(struct ahash_request *req)
{
- struct crypto_hash *parent = pdesc->tfm;
- int bs = crypto_hash_blocksize(parent);
- int ds = crypto_hash_digestsize(parent);
- char *ipad = crypto_hash_ctx_aligned(parent);
- struct hmac_ctx *ctx = align_ptr(ipad + bs * 2 + ds, sizeof(void *));
- struct hash_desc desc;
- struct scatterlist tmp;
- int err;
+ struct crypto_ahash *parent = crypto_ahash_reqtfm(req);
+ struct hmac_ctx *ctx = crypto_ahash_ctx(parent);
+ struct hmac_request_ctx *reqctx = ahash_request_ctx(req);
+ struct ahash_request *creq = (void *)(reqctx->tail + ctx->reqoff);

- desc.tfm = ctx->child;
- desc.flags = pdesc->flags & CRYPTO_TFM_REQ_MAY_SLEEP;
- sg_init_one(&tmp, ipad, bs);
+ u8 *digest = PTR_ALIGN((u8 *)reqctx->tail,
+ crypto_ahash_alignmask(parent) + 1);

- err = crypto_hash_init(&desc);
+ if (!ctx->ipad_req)
+ return -EINVAL;
+
+ ahash_request_set_tfm(creq, ctx->child);
+ ahash_request_set_crypt(creq, req->src, digest, req->nbytes);
+ ahash_request_set_callback(creq, ahash_request_flags(req) &
+ CRYPTO_TFM_REQ_MAY_SLEEP,
+ req->base.complete, req->base.data);
+
+ return crypto_ahash_import(creq, (u8 *)ctx->ipad_req);
+}
+
+static int hmac_update(struct ahash_request *req)
+{
+ struct crypto_ahash *parent = crypto_ahash_reqtfm(req);
+ struct hmac_ctx *ctx = crypto_ahash_ctx(parent);
+ struct hmac_request_ctx *reqctx = ahash_request_ctx(req);
+ struct ahash_request *creq = (void *)(reqctx->tail + ctx->reqoff);
+
+ u8 *digest = PTR_ALIGN((u8 *)reqctx->tail,
+ crypto_ahash_alignmask(parent) + 1);
+
+ ahash_request_set_tfm(creq, ctx->child);
+ ahash_request_set_crypt(creq, req->src, digest, req->nbytes);
+ ahash_request_set_callback(creq, ahash_request_flags(req) &
+ CRYPTO_TFM_REQ_MAY_SLEEP,
+ req->base.complete, req->base.data);
+
+ return crypto_ahash_update(creq);
+}
+
+static void hmac_final_done(struct crypto_async_request *base, int err)
+{
+ struct ahash_request *req = base->data;
+ struct crypto_ahash *parent = crypto_ahash_reqtfm(req);
+ struct hmac_ctx *ctx = crypto_ahash_ctx(parent);
+ struct hmac_request_ctx *reqctx = ahash_request_ctx(req);
+ struct ahash_request *creq = (void *)(reqctx->tail + ctx->reqoff);
+ int ds = crypto_ahash_digestsize(parent);
+
+ u8 *digest = PTR_ALIGN((u8 *)reqctx->tail,
+ crypto_ahash_alignmask(parent) + 1);
+
+ if (err)
+ goto out;
+
+ err = -EINVAL;
+ if (!ctx->opad_req)
+ goto out;
+
+ sg_init_one(&reqctx->sg, digest, ds);
+
+ ahash_request_set_tfm(creq, ctx->child);
+ ahash_request_set_crypt(creq, &reqctx->sg, req->result, ds);
+ ahash_request_set_callback(creq, ahash_request_flags(req) &
+ CRYPTO_TFM_REQ_MAY_SLEEP,
+ req->base.complete, req->base.data);
+
+ err = crypto_ahash_import(creq, (u8 *)ctx->opad_req);
if (unlikely(err))
- return err;
+ goto out;

- return crypto_hash_update(&desc, &tmp, bs);
+ err = crypto_ahash_finup(creq);
+ if (err == -EINPROGRESS)
+ return;
+
+out:
+ ahash_request_complete(req, err);
}

-static int hmac_update(struct hash_desc *pdesc,
- struct scatterlist *sg, unsigned int nbytes)
+static int hmac_final(struct ahash_request *req)
{
- struct hmac_ctx *ctx = hmac_ctx(pdesc->tfm);
- struct hash_desc desc;
+ struct crypto_ahash *parent = crypto_ahash_reqtfm(req);
+ struct hmac_ctx *ctx = crypto_ahash_ctx(parent);
+ struct hmac_request_ctx *reqctx = ahash_request_ctx(req);
+ struct ahash_request *creq = (void *)(reqctx->tail + ctx->reqoff);
+ int ds = crypto_ahash_digestsize(parent);
+ int err = -EINVAL;
+
+ u8 *digest = PTR_ALIGN((u8 *)reqctx->tail,
+ crypto_ahash_alignmask(parent) + 1);
+
+ if (!ctx->opad_req)
+ goto out;
+
+ ahash_request_set_tfm(creq, ctx->child);
+ ahash_request_set_crypt(creq, req->src, digest, req->nbytes);
+ ahash_request_set_callback(creq, ahash_request_flags(req) &
+ CRYPTO_TFM_REQ_MAY_SLEEP,
+ hmac_final_done, req);
+
+ err = crypto_ahash_final(creq);
+ if (err)
+ goto out;
+
+ sg_init_one(&reqctx->sg, digest, ds);

- desc.tfm = ctx->child;
- desc.flags = pdesc->flags & CRYPTO_TFM_REQ_MAY_SLEEP;
+ ahash_request_set_crypt(creq, &reqctx->sg, req->result, ds);
+ ahash_request_set_callback(creq, ahash_request_flags(req) &
+ CRYPTO_TFM_REQ_MAY_SLEEP,
+ req->base.complete, req->base.data);
+
+ err = crypto_ahash_import(creq, (u8 *)ctx->opad_req);
+ if (unlikely(err))
+ goto out;

- return crypto_hash_update(&desc, sg, nbytes);
+ err = crypto_ahash_finup(creq);
+
+out:
+ return err;
}

-static int hmac_final(struct hash_desc *pdesc, u8 *out)
+static int hmac_finup(struct ahash_request *req)
{
- struct crypto_hash *parent = pdesc->tfm;
- int bs = crypto_hash_blocksize(parent);
- int ds = crypto_hash_digestsize(parent);
- char *opad = crypto_hash_ctx_aligned(parent) + bs;
- char *digest = opad + bs;
- struct hmac_ctx *ctx = align_ptr(digest + ds, sizeof(void *));
- struct hash_desc desc;
- struct scatterlist tmp;
- int err;
+ struct crypto_ahash *parent = crypto_ahash_reqtfm(req);
+ struct hmac_ctx *ctx = crypto_ahash_ctx(parent);
+ struct hmac_request_ctx *reqctx = ahash_request_ctx(req);
+ struct ahash_request *creq = (void *)(reqctx->tail + ctx->reqoff);
+ int ds = crypto_ahash_digestsize(parent);
+ int err = -EINVAL;
+
+ u8 *digest = PTR_ALIGN((u8 *)reqctx->tail,
+ crypto_ahash_alignmask(parent) + 1);
+
+ if (!ctx->opad_req)
+ goto out;
+
+ ahash_request_set_tfm(creq, ctx->child);
+ ahash_request_set_crypt(creq, req->src, digest, req->nbytes);
+ ahash_request_set_callback(creq, ahash_request_flags(req) &
+ CRYPTO_TFM_REQ_MAY_SLEEP,
+ hmac_final_done, req);
+
+ err = crypto_ahash_finup(creq);
+ if (err)
+ goto out;
+
+ sg_init_one(&reqctx->sg, digest, ds);

- desc.tfm = ctx->child;
- desc.flags = pdesc->flags & CRYPTO_TFM_REQ_MAY_SLEEP;
- sg_init_one(&tmp, opad, bs + ds);
+ ahash_request_set_crypt(creq, &reqctx->sg, req->result, ds);
+ ahash_request_set_callback(creq, ahash_request_flags(req) &
+ CRYPTO_TFM_REQ_MAY_SLEEP,
+ req->base.complete, req->base.data);

- err = crypto_hash_final(&desc, digest);
+ err = crypto_ahash_import(creq, (u8 *)ctx->opad_req);
if (unlikely(err))
- return err;
+ goto out;

- return crypto_hash_digest(&desc, &tmp, bs + ds, out);
+ err = crypto_ahash_finup(creq);
+
+out:
+ return err;
}

-static int hmac_digest(struct hash_desc *pdesc, struct scatterlist *sg,
- unsigned int nbytes, u8 *out)
+static int hmac_digest(struct ahash_request *req)
{
- struct crypto_hash *parent = pdesc->tfm;
- int bs = crypto_hash_blocksize(parent);
- int ds = crypto_hash_digestsize(parent);
- char *ipad = crypto_hash_ctx_aligned(parent);
- char *opad = ipad + bs;
- char *digest = opad + bs;
- struct hmac_ctx *ctx = align_ptr(digest + ds, sizeof(void *));
- struct hash_desc desc;
- struct scatterlist sg1[2];
- struct scatterlist sg2[1];
- int err;
+ struct crypto_ahash *parent = crypto_ahash_reqtfm(req);
+ struct hmac_ctx *ctx = crypto_ahash_ctx(parent);
+ struct hmac_request_ctx *reqctx = ahash_request_ctx(req);
+ struct ahash_request *creq = (void *)(reqctx->tail + ctx->reqoff);
+ int ds = crypto_ahash_digestsize(parent);
+ int err = -EINVAL;
+
+ u8 *digest = PTR_ALIGN((u8 *)reqctx->tail,
+ crypto_ahash_alignmask(parent) + 1);
+
+ if (!ctx->ipad_req || !ctx->opad_req)
+ goto out;
+
+ ahash_request_set_tfm(creq, ctx->child);
+ ahash_request_set_crypt(creq, req->src, digest, req->nbytes);
+ ahash_request_set_callback(creq, ahash_request_flags(req) &
+ CRYPTO_TFM_REQ_MAY_SLEEP,
+ hmac_final_done, req);
+
+ err = crypto_ahash_import(creq, (u8 *)ctx->ipad_req);
+ if (unlikely(err))
+ goto out;

- desc.tfm = ctx->child;
- desc.flags = pdesc->flags & CRYPTO_TFM_REQ_MAY_SLEEP;
+ err = crypto_ahash_finup(creq);
+ if (err)
+ goto out;

- sg_init_table(sg1, 2);
- sg_set_buf(sg1, ipad, bs);
- scatterwalk_sg_chain(sg1, 2, sg);
+ sg_init_one(&reqctx->sg, digest, ds);

- sg_init_table(sg2, 1);
- sg_set_buf(sg2, opad, bs + ds);
+ ahash_request_set_crypt(creq, &reqctx->sg, req->result, ds);
+ ahash_request_set_callback(creq, ahash_request_flags(req) &
+ CRYPTO_TFM_REQ_MAY_SLEEP,
+ hmac_final_done, req);

- err = crypto_hash_digest(&desc, sg1, nbytes + bs, digest);
+ err = crypto_ahash_import(creq, (u8 *)ctx->opad_req);
if (unlikely(err))
- return err;
+ goto out;
+
+ err = crypto_ahash_finup(creq);

- return crypto_hash_digest(&desc, sg2, bs + ds, out);
+out:
+ return err;
}

static int hmac_init_tfm(struct crypto_tfm *tfm)
{
- struct crypto_hash *hash;
- struct crypto_instance *inst = (void *)tfm->__crt_alg;
+ struct crypto_ahash *ahash;
+ struct crypto_instance *inst = crypto_tfm_alg_instance(tfm);
struct crypto_spawn *spawn = crypto_instance_ctx(inst);
- struct hmac_ctx *ctx = hmac_ctx(__crypto_hash_cast(tfm));
+ struct hmac_ctx *ctx = crypto_tfm_ctx(tfm);

- hash = crypto_spawn_hash(spawn);
- if (IS_ERR(hash))
- return PTR_ERR(hash);
+ ahash = crypto_spawn_ahash(spawn);
+ if (IS_ERR(ahash))
+ return PTR_ERR(ahash);
+
+ ctx->child = ahash;
+
+ ctx->reqoff = ALIGN(crypto_ahash_digestsize(ahash),
+ crypto_ahash_alignmask(ahash) + 1);
+
+ tfm->crt_ahash.reqsize = sizeof(struct ahash_request) +
+ sizeof(struct hmac_request_ctx) +
+ ctx->reqoff + crypto_ahash_reqsize(ahash);

- ctx->child = hash;
return 0;
}

static void hmac_exit_tfm(struct crypto_tfm *tfm)
{
- struct hmac_ctx *ctx = hmac_ctx(__crypto_hash_cast(tfm));
- crypto_free_hash(ctx->child);
+ struct hmac_ctx *ctx = crypto_tfm_ctx(tfm);
+
+ kfree(ctx->ipad_req);
+ kfree(ctx->opad_req);
+ crypto_free_ahash(ctx->child);
}

static void hmac_free(struct crypto_instance *inst)
@@ -233,7 +442,7 @@ static struct crypto_instance *hmac_alloc(struct rtattr **tb)
return ERR_PTR(err);

alg = crypto_get_attr_alg(tb, CRYPTO_ALG_TYPE_HASH,
- CRYPTO_ALG_TYPE_HASH_MASK);
+ CRYPTO_ALG_TYPE_AHASH_MASK);
if (IS_ERR(alg))
return ERR_CAST(alg);

@@ -250,26 +459,26 @@ static struct crypto_instance *hmac_alloc(struct rtattr **tb)
if (IS_ERR(inst))
goto out_put_alg;

- inst->alg.cra_flags = CRYPTO_ALG_TYPE_HASH;
+ inst->alg.cra_flags = CRYPTO_ALG_TYPE_AHASH;
+ inst->alg.cra_flags |= alg->cra_flags & CRYPTO_ALG_ASYNC;;
inst->alg.cra_priority = alg->cra_priority;
inst->alg.cra_blocksize = alg->cra_blocksize;
inst->alg.cra_alignmask = alg->cra_alignmask;
- inst->alg.cra_type = &crypto_hash_type;
+ inst->alg.cra_type = &crypto_ahash_type;

- inst->alg.cra_hash.digestsize = ds;
+ inst->alg.cra_ahash.digestsize = ds;

- inst->alg.cra_ctxsize = sizeof(struct hmac_ctx) +
- ALIGN(inst->alg.cra_blocksize * 2 + ds,
- sizeof(void *));
+ inst->alg.cra_ctxsize = sizeof(struct hmac_ctx);

inst->alg.cra_init = hmac_init_tfm;
inst->alg.cra_exit = hmac_exit_tfm;

- inst->alg.cra_hash.init = hmac_init;
- inst->alg.cra_hash.update = hmac_update;
- inst->alg.cra_hash.final = hmac_final;
- inst->alg.cra_hash.digest = hmac_digest;
- inst->alg.cra_hash.setkey = hmac_setkey;
+ inst->alg.cra_ahash.init = hmac_init;
+ inst->alg.cra_ahash.update = hmac_update;
+ inst->alg.cra_ahash.final = hmac_final;
+ inst->alg.cra_ahash.finup = hmac_finup;
+ inst->alg.cra_ahash.digest = hmac_digest;
+ inst->alg.cra_ahash.setkey = hmac_setkey;

out_put_alg:
crypto_mod_put(alg);
--
1.5.4.2


2009-07-09 04:48:18

by Herbert Xu

[permalink] [raw]
Subject: Re: [RFC] [PATCH 3/3] crypto: hmac - convert to ahash

On Tue, Jul 07, 2009 at 09:26:58AM +0200, Steffen Klassert wrote:
> This converts hmac to the new ahash frontend.
> Also the hashing of the ipaded and opaded key is done now with the
> setkey function, this saves some bytes of hashing on each request.
>
> Signed-off-by: Steffen Klassert <[email protected]>

This looks pretty good!

I'll come back to it once we start the ahash conversion.

For now I've cherry-picked the import/export bit (although not
in its exact form).

Thanks,
--
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <[email protected]>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt