diff options
author | Tan Swee Heng <thesweeheng@gmail.com> | 2007-12-07 09:38:45 +0100 |
---|---|---|
committer | Herbert Xu <herbert@gondor.apana.org.au> | 2008-01-10 22:16:34 +0100 |
commit | eb6f13eb9f812f5812ed5d14f241309da369dee6 (patch) | |
tree | eb49b8f64333e9389852dcd99a38279a076150d6 /crypto/salsa20_generic.c | |
parent | [CRYPTO] gcm: Put abreq in private context instead of on stack (diff) | |
download | linux-eb6f13eb9f812f5812ed5d14f241309da369dee6.tar.xz linux-eb6f13eb9f812f5812ed5d14f241309da369dee6.zip |
[CRYPTO] salsa20_generic: Fix multi-page processing
This patch fixes the multi-page processing bug that affects large test
vectors (the same bug that previously affected ctr.c).
There is an optimization for the case walk.nbytes == nbytes. Also we
now use crypto_xor() instead of adhoc XOR routines.
Signed-off-by: Tan Swee Heng <thesweeheng@gmail.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'crypto/salsa20_generic.c')
-rw-r--r-- | crypto/salsa20_generic.c | 34 |
1 files changed, 23 insertions, 11 deletions
diff --git a/crypto/salsa20_generic.c b/crypto/salsa20_generic.c index b49328afcf0a..1fa4e4ddcab5 100644 --- a/crypto/salsa20_generic.c +++ b/crypto/salsa20_generic.c @@ -143,7 +143,6 @@ static void salsa20_encrypt_bytes(struct salsa20_ctx *ctx, u8 *dst, const u8 *src, unsigned int bytes) { u8 buf[64]; - int i; if (dst != src) memcpy(dst, src, bytes); @@ -156,15 +155,11 @@ static void salsa20_encrypt_bytes(struct salsa20_ctx *ctx, u8 *dst, ctx->input[9] = PLUSONE(ctx->input[9]); if (bytes <= 64) { - for (i = 0; i < bytes/4; ++i) - ((u32*)dst)[i] ^= ((u32*)buf)[i]; - for (i = bytes - bytes % 4; i < bytes; ++i) - dst[i] ^= buf[i]; + crypto_xor(dst, buf, bytes); return; } - for (i = 0; i < 64/4; ++i) - ((u32*)dst)[i] ^= ((u32*)buf)[i]; + crypto_xor(dst, buf, 64); bytes -= 64; dst += 64; } @@ -192,13 +187,30 @@ static int encrypt(struct blkcipher_desc *desc, int err; blkcipher_walk_init(&walk, dst, src, nbytes); - err = blkcipher_walk_virt(desc, &walk); + err = blkcipher_walk_virt_block(desc, &walk, 64); salsa20_ivsetup(ctx, walk.iv); - salsa20_encrypt_bytes(ctx, walk.dst.virt.addr, - walk.src.virt.addr, nbytes); - err = blkcipher_walk_done(desc, &walk, 0); + if (likely(walk.nbytes == nbytes)) + { + salsa20_encrypt_bytes(ctx, walk.dst.virt.addr, + walk.src.virt.addr, nbytes); + return blkcipher_walk_done(desc, &walk, 0); + } + + while (walk.nbytes >= 64) { + salsa20_encrypt_bytes(ctx, walk.dst.virt.addr, + walk.src.virt.addr, + walk.nbytes - (walk.nbytes % 64)); + err = blkcipher_walk_done(desc, &walk, walk.nbytes % 64); + } + + if (walk.nbytes) { + salsa20_encrypt_bytes(ctx, walk.dst.virt.addr, + walk.src.virt.addr, walk.nbytes); + err = blkcipher_walk_done(desc, &walk, 0); + } + return err; } |