crypto: michael_mic - Switch to shash

This patch changes michael_mic to the new shash interface.

Signed-off-by: Adrian-Ken Rueegsegger <ken@codelabs.ch>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
This commit is contained in:
Adrian-Ken Rueegsegger 2008-12-07 19:35:38 +08:00 committed by Herbert Xu
parent 4946510baa
commit 19e2bf1467
2 changed files with 42 additions and 32 deletions

View file

@ -288,7 +288,7 @@ config CRYPTO_MD5
config CRYPTO_MICHAEL_MIC config CRYPTO_MICHAEL_MIC
tristate "Michael MIC keyed digest algorithm" tristate "Michael MIC keyed digest algorithm"
select CRYPTO_ALGAPI select CRYPTO_HASH
help help
Michael MIC is used for message integrity protection in TKIP Michael MIC is used for message integrity protection in TKIP
(IEEE 802.11i). This algorithm is required for TKIP, but it (IEEE 802.11i). This algorithm is required for TKIP, but it

View file

@ -9,23 +9,25 @@
* it under the terms of the GNU General Public License version 2 as * it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation. * published by the Free Software Foundation.
*/ */
#include <crypto/internal/hash.h>
#include <asm/byteorder.h> #include <asm/byteorder.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/crypto.h>
#include <linux/types.h> #include <linux/types.h>
struct michael_mic_ctx { struct michael_mic_ctx {
u32 l, r;
};
struct michael_mic_desc_ctx {
u8 pending[4]; u8 pending[4];
size_t pending_len; size_t pending_len;
u32 l, r; u32 l, r;
}; };
static inline u32 xswap(u32 val) static inline u32 xswap(u32 val)
{ {
return ((val & 0x00ff00ff) << 8) | ((val & 0xff00ff00) >> 8); return ((val & 0x00ff00ff) << 8) | ((val & 0xff00ff00) >> 8);
@ -45,17 +47,22 @@ do { \
} while (0) } while (0)
static void michael_init(struct crypto_tfm *tfm) static int michael_init(struct shash_desc *desc)
{ {
struct michael_mic_ctx *mctx = crypto_tfm_ctx(tfm); struct michael_mic_desc_ctx *mctx = shash_desc_ctx(desc);
struct michael_mic_ctx *ctx = crypto_shash_ctx(desc->tfm);
mctx->pending_len = 0; mctx->pending_len = 0;
mctx->l = ctx->l;
mctx->r = ctx->r;
return 0;
} }
static void michael_update(struct crypto_tfm *tfm, const u8 *data, static int michael_update(struct shash_desc *desc, const u8 *data,
unsigned int len) unsigned int len)
{ {
struct michael_mic_ctx *mctx = crypto_tfm_ctx(tfm); struct michael_mic_desc_ctx *mctx = shash_desc_ctx(desc);
const __le32 *src; const __le32 *src;
if (mctx->pending_len) { if (mctx->pending_len) {
@ -68,7 +75,7 @@ static void michael_update(struct crypto_tfm *tfm, const u8 *data,
len -= flen; len -= flen;
if (mctx->pending_len < 4) if (mctx->pending_len < 4)
return; return 0;
src = (const __le32 *)mctx->pending; src = (const __le32 *)mctx->pending;
mctx->l ^= le32_to_cpup(src); mctx->l ^= le32_to_cpup(src);
@ -88,12 +95,14 @@ static void michael_update(struct crypto_tfm *tfm, const u8 *data,
mctx->pending_len = len; mctx->pending_len = len;
memcpy(mctx->pending, src, len); memcpy(mctx->pending, src, len);
} }
return 0;
} }
static void michael_final(struct crypto_tfm *tfm, u8 *out) static int michael_final(struct shash_desc *desc, u8 *out)
{ {
struct michael_mic_ctx *mctx = crypto_tfm_ctx(tfm); struct michael_mic_desc_ctx *mctx = shash_desc_ctx(desc);
u8 *data = mctx->pending; u8 *data = mctx->pending;
__le32 *dst = (__le32 *)out; __le32 *dst = (__le32 *)out;
@ -119,17 +128,20 @@ static void michael_final(struct crypto_tfm *tfm, u8 *out)
dst[0] = cpu_to_le32(mctx->l); dst[0] = cpu_to_le32(mctx->l);
dst[1] = cpu_to_le32(mctx->r); dst[1] = cpu_to_le32(mctx->r);
return 0;
} }
static int michael_setkey(struct crypto_tfm *tfm, const u8 *key, static int michael_setkey(struct crypto_shash *tfm, const u8 *key,
unsigned int keylen) unsigned int keylen)
{ {
struct michael_mic_ctx *mctx = crypto_tfm_ctx(tfm); struct michael_mic_ctx *mctx = crypto_shash_ctx(tfm);
const __le32 *data = (const __le32 *)key; const __le32 *data = (const __le32 *)key;
if (keylen != 8) { if (keylen != 8) {
tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; crypto_shash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
return -EINVAL; return -EINVAL;
} }
@ -138,33 +150,31 @@ static int michael_setkey(struct crypto_tfm *tfm, const u8 *key,
return 0; return 0;
} }
static struct shash_alg alg = {
static struct crypto_alg michael_mic_alg = { .digestsize = 8,
.cra_name = "michael_mic", .setkey = michael_setkey,
.cra_flags = CRYPTO_ALG_TYPE_DIGEST, .init = michael_init,
.cra_blocksize = 8, .update = michael_update,
.cra_ctxsize = sizeof(struct michael_mic_ctx), .final = michael_final,
.cra_module = THIS_MODULE, .descsize = sizeof(struct michael_mic_desc_ctx),
.cra_alignmask = 3, .base = {
.cra_list = LIST_HEAD_INIT(michael_mic_alg.cra_list), .cra_name = "michael_mic",
.cra_u = { .digest = { .cra_blocksize = 8,
.dia_digestsize = 8, .cra_alignmask = 3,
.dia_init = michael_init, .cra_ctxsize = sizeof(struct michael_mic_ctx),
.dia_update = michael_update, .cra_module = THIS_MODULE,
.dia_final = michael_final, }
.dia_setkey = michael_setkey } }
}; };
static int __init michael_mic_init(void) static int __init michael_mic_init(void)
{ {
return crypto_register_alg(&michael_mic_alg); return crypto_register_shash(&alg);
} }
static void __exit michael_mic_exit(void) static void __exit michael_mic_exit(void)
{ {
crypto_unregister_alg(&michael_mic_alg); crypto_unregister_shash(&alg);
} }