X-Git-Url: http://ftp.safe.ca/?a=blobdiff_plain;f=crypto%2Fahash.c;h=27128f2c687a62494b8d20b60191c916376aca4a;hb=c381060869317b3c84430d4f54965d409cbfe65f;hp=a83e035d9a3f55dbfb30a9931cf29caccd995079;hpb=004a403c2e954734090a69aedc7f4f822bdcc142;p=safe%2Fjmp%2Flinux-2.6 diff --git a/crypto/ahash.c b/crypto/ahash.c index a83e035..27128f2 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) { @@ -68,7 +157,7 @@ static int crypto_init_ahash_ops(struct crypto_tfm *tfm, u32 type, u32 mask) struct ahash_alg *alg = &tfm->__crt_alg->cra_ahash; struct ahash_tfm *crt = &tfm->crt_ahash; - if (alg->digestsize > crypto_tfm_alg_blocksize(tfm)) + if (alg->digestsize > PAGE_SIZE / 8) return -EINVAL; crt->init = alg->init; @@ -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;