X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=crypto%2Fahash.c;h=27128f2c687a62494b8d20b60191c916376aca4a;hb=260eddf4391f162a69d1d163729249635fa7a78f;hp=8c1f918a6878bbb2883a5609bbe9cf1f61a49bca;hpb=ca786dc738f4f583b57b1bba7a335b5e8233f4b0;p=linux-2.6 diff --git a/crypto/ahash.c b/crypto/ahash.c index 8c1f918a68..27128f2c68 100644 --- a/crypto/ahash.c +++ b/crypto/ahash.c @@ -13,7 +13,8 @@ * */ -#include +#include +#include #include #include #include @@ -23,6 +24,94 @@ #include "internal.h" +static int hash_walk_next(struct crypto_hash_walk *walk) +{ + unsigned int alignmask = walk->alignmask; + unsigned int offset = walk->offset; + unsigned int nbytes = min(walk->entrylen, + ((unsigned int)(PAGE_SIZE)) - offset); + + walk->data = crypto_kmap(walk->pg, 0); + walk->data += offset; + + if (offset & alignmask) + nbytes = alignmask + 1 - (offset & alignmask); + + walk->entrylen -= nbytes; + return nbytes; +} + +static int hash_walk_new_entry(struct crypto_hash_walk *walk) +{ + struct scatterlist *sg; + + sg = walk->sg; + walk->pg = sg_page(sg); + walk->offset = sg->offset; + walk->entrylen = sg->length; + + if (walk->entrylen > walk->total) + walk->entrylen = walk->total; + walk->total -= walk->entrylen; + + return hash_walk_next(walk); +} + +int crypto_hash_walk_done(struct crypto_hash_walk *walk, int err) +{ + unsigned int alignmask = walk->alignmask; + unsigned int nbytes = walk->entrylen; + + walk->data -= walk->offset; + + if (nbytes && walk->offset & alignmask && !err) { + walk->offset += alignmask - 1; + walk->offset = ALIGN(walk->offset, alignmask + 1); + walk->data += walk->offset; + + nbytes = min(nbytes, + ((unsigned int)(PAGE_SIZE)) - walk->offset); + walk->entrylen -= nbytes; + + return nbytes; + } + + crypto_kunmap(walk->data, 0); + crypto_yield(walk->flags); + + if (err) + return err; + + walk->offset = 0; + + if (nbytes) + return hash_walk_next(walk); + + if (!walk->total) + return 0; + + walk->sg = scatterwalk_sg_next(walk->sg); + + return hash_walk_new_entry(walk); +} +EXPORT_SYMBOL_GPL(crypto_hash_walk_done); + +int crypto_hash_walk_first(struct ahash_request *req, + struct crypto_hash_walk *walk) +{ + walk->total = req->nbytes; + + if (!walk->total) + return 0; + + walk->alignmask = crypto_ahash_alignmask(crypto_ahash_reqtfm(req)); + walk->sg = req->src; + walk->flags = req->base.flags; + + return hash_walk_new_entry(walk); +} +EXPORT_SYMBOL_GPL(crypto_hash_walk_first); + static int ahash_setkey_unaligned(struct crypto_ahash *tfm, const u8 *key, unsigned int keylen) { @@ -76,7 +165,6 @@ static int crypto_init_ahash_ops(struct crypto_tfm *tfm, u32 type, u32 mask) crt->final = alg->final; crt->digest = alg->digest; crt->setkey = ahash_setkey; - crt->base = __crypto_ahash_cast(tfm); crt->digestsize = alg->digestsize; return 0;