X-Git-Url: http://ftp.safe.ca/?a=blobdiff_plain;f=crypto%2Fxcbc.c;h=3b991bf2fd92065d9abc315d42b2533af527157e;hb=b5ebd44eb7559ea6135d536bafd02323d2ef0547;hp=d7b4be0a057d8c96f29cfdbb797bdaeaddfbbc50;hpb=2e306ee016fd4750289e65c3b1856db569f1f3f2;p=safe%2Fjmp%2Flinux-2.6 diff --git a/crypto/xcbc.c b/crypto/xcbc.c index d7b4be0..3b991bf 100644 --- a/crypto/xcbc.c +++ b/crypto/xcbc.c @@ -19,15 +19,9 @@ * Kazunori Miyazawa */ -#include +#include #include -#include #include -#include -#include -#include -#include -#include "internal.h" static u_int32_t ks[12] = {0x01010101, 0x01010101, 0x01010101, 0x01010101, 0x02020202, 0x02020202, 0x02020202, 0x02020202, @@ -48,7 +42,7 @@ static u_int32_t ks[12] = {0x01010101, 0x01010101, 0x01010101, 0x01010101, * +------------------------ */ struct crypto_xcbc_ctx { - struct crypto_tfm *child; + struct crypto_cipher *child; u8 *odds; u8 *prev; u8 *key; @@ -66,28 +60,27 @@ static void xor_128(u8 *a, const u8 *b, unsigned int bs) ((u32 *)a)[3] ^= ((u32 *)b)[3]; } -static int _crypto_xcbc_digest_setkey(struct crypto_hash *parent, +static int _crypto_xcbc_digest_setkey(struct crypto_shash *parent, struct crypto_xcbc_ctx *ctx) { - int bs = crypto_hash_blocksize(parent); + int bs = crypto_shash_blocksize(parent); int err = 0; u8 key1[bs]; if ((err = crypto_cipher_setkey(ctx->child, ctx->key, ctx->keylen))) return err; - ctx->child->__crt_alg->cra_cipher.cia_encrypt(ctx->child, key1, - ctx->consts); + crypto_cipher_encrypt_one(ctx->child, key1, ctx->consts); return crypto_cipher_setkey(ctx->child, key1, bs); } -static int crypto_xcbc_digest_setkey(struct crypto_hash *parent, +static int crypto_xcbc_digest_setkey(struct crypto_shash *parent, const u8 *inkey, unsigned int keylen) { - struct crypto_xcbc_ctx *ctx = crypto_hash_ctx_aligned(parent); + struct crypto_xcbc_ctx *ctx = crypto_shash_ctx(parent); - if (keylen != crypto_tfm_alg_blocksize(ctx->child)) + if (keylen != crypto_cipher_blocksize(ctx->child)) return -EINVAL; ctx->keylen = keylen; @@ -97,10 +90,10 @@ static int crypto_xcbc_digest_setkey(struct crypto_hash *parent, return _crypto_xcbc_digest_setkey(parent, ctx); } -static int crypto_xcbc_digest_init(struct hash_desc *pdesc) +static int crypto_xcbc_digest_init(struct shash_desc *pdesc) { - struct crypto_xcbc_ctx *ctx = crypto_hash_ctx_aligned(pdesc->tfm); - int bs = crypto_hash_blocksize(pdesc->tfm); + struct crypto_xcbc_ctx *ctx = crypto_shash_ctx(pdesc->tfm); + int bs = crypto_shash_blocksize(pdesc->tfm); ctx->len = 0; memset(ctx->odds, 0, bs); @@ -109,96 +102,55 @@ static int crypto_xcbc_digest_init(struct hash_desc *pdesc) return 0; } -static int crypto_xcbc_digest_update2(struct hash_desc *pdesc, - struct scatterlist *sg, - unsigned int nbytes) +static int crypto_xcbc_digest_update(struct shash_desc *pdesc, const u8 *p, + unsigned int len) { - struct crypto_hash *parent = pdesc->tfm; - struct crypto_xcbc_ctx *ctx = crypto_hash_ctx_aligned(parent); - struct crypto_tfm *tfm = ctx->child; - int bs = crypto_hash_blocksize(parent); - unsigned int i = 0; - - do { - - struct page *pg = sg[i].page; - unsigned int offset = sg[i].offset; - unsigned int slen = sg[i].length; - - while (slen > 0) { - unsigned int len = min(slen, ((unsigned int)(PAGE_SIZE)) - offset); - char *p = crypto_kmap(pg, 0) + offset; - - /* checking the data can fill the block */ - if ((ctx->len + len) <= bs) { - memcpy(ctx->odds + ctx->len, p, len); - ctx->len += len; - slen -= len; - - /* checking the rest of the page */ - if (len + offset >= PAGE_SIZE) { - offset = 0; - pg++; - } else - offset += len; - - crypto_kunmap(p, 0); - crypto_yield(tfm->crt_flags); - continue; - } - - /* filling odds with new data and encrypting it */ - memcpy(ctx->odds + ctx->len, p, bs - ctx->len); - len -= bs - ctx->len; - p += bs - ctx->len; - - ctx->xor(ctx->prev, ctx->odds, bs); - tfm->__crt_alg->cra_cipher.cia_encrypt(tfm, ctx->prev, ctx->prev); - - /* clearing the length */ - ctx->len = 0; - - /* encrypting the rest of data */ - while (len > bs) { - ctx->xor(ctx->prev, p, bs); - tfm->__crt_alg->cra_cipher.cia_encrypt(tfm, ctx->prev, ctx->prev); - p += bs; - len -= bs; - } - - /* keeping the surplus of blocksize */ - if (len) { - memcpy(ctx->odds, p, len); - ctx->len = len; - } - crypto_kunmap(p, 0); - crypto_yield(tfm->crt_flags); - slen -= min(slen, ((unsigned int)(PAGE_SIZE)) - offset); - offset = 0; - pg++; - } - nbytes-=sg[i].length; - i++; - } while (nbytes>0); + struct crypto_shash *parent = pdesc->tfm; + struct crypto_xcbc_ctx *ctx = crypto_shash_ctx(parent); + struct crypto_cipher *tfm = ctx->child; + int bs = crypto_shash_blocksize(parent); + + /* checking the data can fill the block */ + if ((ctx->len + len) <= bs) { + memcpy(ctx->odds + ctx->len, p, len); + ctx->len += len; + return 0; + } - return 0; -} + /* filling odds with new data and encrypting it */ + memcpy(ctx->odds + ctx->len, p, bs - ctx->len); + len -= bs - ctx->len; + p += bs - ctx->len; -static int crypto_xcbc_digest_update(struct hash_desc *pdesc, - struct scatterlist *sg, - unsigned int nbytes) -{ - if (WARN_ON_ONCE(in_irq())) - return -EDEADLK; - return crypto_xcbc_digest_update2(pdesc, sg, nbytes); + ctx->xor(ctx->prev, ctx->odds, bs); + crypto_cipher_encrypt_one(tfm, ctx->prev, ctx->prev); + + /* clearing the length */ + ctx->len = 0; + + /* encrypting the rest of data */ + while (len > bs) { + ctx->xor(ctx->prev, p, bs); + crypto_cipher_encrypt_one(tfm, ctx->prev, ctx->prev); + p += bs; + len -= bs; + } + + /* keeping the surplus of blocksize */ + if (len) { + memcpy(ctx->odds, p, len); + ctx->len = len; + } + + return 0; } -static int crypto_xcbc_digest_final(struct hash_desc *pdesc, u8 *out) +static int crypto_xcbc_digest_final(struct shash_desc *pdesc, u8 *out) { - struct crypto_hash *parent = pdesc->tfm; - struct crypto_xcbc_ctx *ctx = crypto_hash_ctx_aligned(parent); - struct crypto_tfm *tfm = ctx->child; - int bs = crypto_hash_blocksize(parent); + struct crypto_shash *parent = pdesc->tfm; + struct crypto_xcbc_ctx *ctx = crypto_shash_ctx(parent); + struct crypto_cipher *tfm = ctx->child; + int bs = crypto_shash_blocksize(parent); int err = 0; if (ctx->len == bs) { @@ -207,13 +159,14 @@ static int crypto_xcbc_digest_final(struct hash_desc *pdesc, u8 *out) if ((err = crypto_cipher_setkey(tfm, ctx->key, ctx->keylen)) != 0) return err; - tfm->__crt_alg->cra_cipher.cia_encrypt(tfm, key2, (const u8*)(ctx->consts+bs)); + crypto_cipher_encrypt_one(tfm, key2, + (u8 *)(ctx->consts + bs)); ctx->xor(ctx->prev, ctx->odds, bs); ctx->xor(ctx->prev, key2, bs); _crypto_xcbc_digest_setkey(parent, ctx); - tfm->__crt_alg->cra_cipher.cia_encrypt(tfm, out, ctx->prev); + crypto_cipher_encrypt_one(tfm, out, ctx->prev); } else { u8 key3[bs]; unsigned int rlen; @@ -228,37 +181,27 @@ static int crypto_xcbc_digest_final(struct hash_desc *pdesc, u8 *out) if ((err = crypto_cipher_setkey(tfm, ctx->key, ctx->keylen)) != 0) return err; - tfm->__crt_alg->cra_cipher.cia_encrypt(tfm, key3, (const u8*)(ctx->consts+bs*2)); + crypto_cipher_encrypt_one(tfm, key3, + (u8 *)(ctx->consts + bs * 2)); ctx->xor(ctx->prev, ctx->odds, bs); ctx->xor(ctx->prev, key3, bs); _crypto_xcbc_digest_setkey(parent, ctx); - tfm->__crt_alg->cra_cipher.cia_encrypt(tfm, out, ctx->prev); + crypto_cipher_encrypt_one(tfm, out, ctx->prev); } return 0; } -static int crypto_xcbc_digest(struct hash_desc *pdesc, - struct scatterlist *sg, unsigned int nbytes, u8 *out) -{ - if (WARN_ON_ONCE(in_irq())) - return -EDEADLK; - - crypto_xcbc_digest_init(pdesc); - crypto_xcbc_digest_update2(pdesc, sg, nbytes); - return crypto_xcbc_digest_final(pdesc, out); -} - static int xcbc_init_tfm(struct crypto_tfm *tfm) { struct crypto_cipher *cipher; struct crypto_instance *inst = (void *)tfm->__crt_alg; struct crypto_spawn *spawn = crypto_instance_ctx(inst); - struct crypto_xcbc_ctx *ctx = crypto_hash_ctx_aligned(__crypto_hash_cast(tfm)); - int bs = crypto_hash_blocksize(__crypto_hash_cast(tfm)); + struct crypto_xcbc_ctx *ctx = crypto_tfm_ctx(tfm); + int bs = crypto_tfm_alg_blocksize(tfm); cipher = crypto_spawn_cipher(spawn); if (IS_ERR(cipher)) @@ -282,66 +225,74 @@ static int xcbc_init_tfm(struct crypto_tfm *tfm) static void xcbc_exit_tfm(struct crypto_tfm *tfm) { - struct crypto_xcbc_ctx *ctx = crypto_hash_ctx_aligned(__crypto_hash_cast(tfm)); + struct crypto_xcbc_ctx *ctx = crypto_tfm_ctx(tfm); crypto_free_cipher(ctx->child); } -static struct crypto_instance *xcbc_alloc(void *param, unsigned int len) +static int xcbc_create(struct crypto_template *tmpl, struct rtattr **tb) { - struct crypto_instance *inst; + struct shash_instance *inst; struct crypto_alg *alg; - alg = crypto_get_attr_alg(param, len, CRYPTO_ALG_TYPE_CIPHER, - CRYPTO_ALG_TYPE_HASH_MASK | CRYPTO_ALG_ASYNC); + int err; + + err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_SHASH); + if (err) + return err; + + alg = crypto_get_attr_alg(tb, CRYPTO_ALG_TYPE_CIPHER, + CRYPTO_ALG_TYPE_MASK); if (IS_ERR(alg)) - return ERR_PTR(PTR_ERR(alg)); + return PTR_ERR(alg); switch(alg->cra_blocksize) { case 16: break; default: - return ERR_PTR(PTR_ERR(alg)); + goto out_put_alg; } - inst = crypto_alloc_instance("xcbc", alg); + inst = shash_alloc_instance("xcbc", alg); + err = PTR_ERR(inst); if (IS_ERR(inst)) goto out_put_alg; - inst->alg.cra_flags = CRYPTO_ALG_TYPE_HASH; - 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_hash.digestsize = - (alg->cra_flags & CRYPTO_ALG_TYPE_MASK) == - CRYPTO_ALG_TYPE_HASH ? alg->cra_hash.digestsize : - alg->cra_blocksize; - inst->alg.cra_ctxsize = sizeof(struct crypto_xcbc_ctx) + - ALIGN(inst->alg.cra_blocksize * 3, sizeof(void *)); - inst->alg.cra_init = xcbc_init_tfm; - inst->alg.cra_exit = xcbc_exit_tfm; - - inst->alg.cra_hash.init = crypto_xcbc_digest_init; - inst->alg.cra_hash.update = crypto_xcbc_digest_update; - inst->alg.cra_hash.final = crypto_xcbc_digest_final; - inst->alg.cra_hash.digest = crypto_xcbc_digest; - inst->alg.cra_hash.setkey = crypto_xcbc_digest_setkey; + err = crypto_init_spawn(shash_instance_ctx(inst), alg, + shash_crypto_instance(inst), + CRYPTO_ALG_TYPE_MASK); + if (err) + goto out_free_inst; + + inst->alg.base.cra_priority = alg->cra_priority; + inst->alg.base.cra_blocksize = alg->cra_blocksize; + inst->alg.base.cra_alignmask = alg->cra_alignmask; + + inst->alg.digestsize = alg->cra_blocksize; + inst->alg.base.cra_ctxsize = sizeof(struct crypto_xcbc_ctx) + + ALIGN(alg->cra_blocksize * 3, + sizeof(void *)); + inst->alg.base.cra_init = xcbc_init_tfm; + inst->alg.base.cra_exit = xcbc_exit_tfm; + + inst->alg.init = crypto_xcbc_digest_init; + inst->alg.update = crypto_xcbc_digest_update; + inst->alg.final = crypto_xcbc_digest_final; + inst->alg.setkey = crypto_xcbc_digest_setkey; + + err = shash_register_instance(tmpl, inst); + if (err) { +out_free_inst: + shash_free_instance(shash_crypto_instance(inst)); + } out_put_alg: crypto_mod_put(alg); - return inst; -} - -static void xcbc_free(struct crypto_instance *inst) -{ - crypto_drop_spawn(crypto_instance_ctx(inst)); - kfree(inst); + return err; } static struct crypto_template crypto_xcbc_tmpl = { .name = "xcbc", - .alloc = xcbc_alloc, - .free = xcbc_free, + .create = xcbc_create, + .free = shash_free_instance, .module = THIS_MODULE, };