diff options
author | Tan Swee Heng <thesweeheng@gmail.com> | 2007-12-07 03:38:45 -0500 |
---|---|---|
committer | Herbert Xu <herbert@gondor.apana.org.au> | 2008-01-10 16:16:34 -0500 |
commit | eb6f13eb9f812f5812ed5d14f241309da369dee6 (patch) | |
tree | eb49b8f64333e9389852dcd99a38279a076150d6 /crypto | |
parent | 7f6813786a6521380e1756ca5b4336bc63c5bf7d (diff) |
[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')
-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, | |||
143 | const u8 *src, unsigned int bytes) | 143 | const u8 *src, unsigned int bytes) |
144 | { | 144 | { |
145 | u8 buf[64]; | 145 | u8 buf[64]; |
146 | int i; | ||
147 | 146 | ||
148 | if (dst != src) | 147 | if (dst != src) |
149 | memcpy(dst, src, bytes); | 148 | memcpy(dst, src, bytes); |
@@ -156,15 +155,11 @@ static void salsa20_encrypt_bytes(struct salsa20_ctx *ctx, u8 *dst, | |||
156 | ctx->input[9] = PLUSONE(ctx->input[9]); | 155 | ctx->input[9] = PLUSONE(ctx->input[9]); |
157 | 156 | ||
158 | if (bytes <= 64) { | 157 | if (bytes <= 64) { |
159 | for (i = 0; i < bytes/4; ++i) | 158 | crypto_xor(dst, buf, bytes); |
160 | ((u32*)dst)[i] ^= ((u32*)buf)[i]; | ||
161 | for (i = bytes - bytes % 4; i < bytes; ++i) | ||
162 | dst[i] ^= buf[i]; | ||
163 | return; | 159 | return; |
164 | } | 160 | } |
165 | 161 | ||
166 | for (i = 0; i < 64/4; ++i) | 162 | crypto_xor(dst, buf, 64); |
167 | ((u32*)dst)[i] ^= ((u32*)buf)[i]; | ||
168 | bytes -= 64; | 163 | bytes -= 64; |
169 | dst += 64; | 164 | dst += 64; |
170 | } | 165 | } |
@@ -192,13 +187,30 @@ static int encrypt(struct blkcipher_desc *desc, | |||
192 | int err; | 187 | int err; |
193 | 188 | ||
194 | blkcipher_walk_init(&walk, dst, src, nbytes); | 189 | blkcipher_walk_init(&walk, dst, src, nbytes); |
195 | err = blkcipher_walk_virt(desc, &walk); | 190 | err = blkcipher_walk_virt_block(desc, &walk, 64); |
196 | 191 | ||
197 | salsa20_ivsetup(ctx, walk.iv); | 192 | salsa20_ivsetup(ctx, walk.iv); |
198 | salsa20_encrypt_bytes(ctx, walk.dst.virt.addr, | ||
199 | walk.src.virt.addr, nbytes); | ||
200 | 193 | ||
201 | err = blkcipher_walk_done(desc, &walk, 0); | 194 | if (likely(walk.nbytes == nbytes)) |
195 | { | ||
196 | salsa20_encrypt_bytes(ctx, walk.dst.virt.addr, | ||
197 | walk.src.virt.addr, nbytes); | ||
198 | return blkcipher_walk_done(desc, &walk, 0); | ||
199 | } | ||
200 | |||
201 | while (walk.nbytes >= 64) { | ||
202 | salsa20_encrypt_bytes(ctx, walk.dst.virt.addr, | ||
203 | walk.src.virt.addr, | ||
204 | walk.nbytes - (walk.nbytes % 64)); | ||
205 | err = blkcipher_walk_done(desc, &walk, walk.nbytes % 64); | ||
206 | } | ||
207 | |||
208 | if (walk.nbytes) { | ||
209 | salsa20_encrypt_bytes(ctx, walk.dst.virt.addr, | ||
210 | walk.src.virt.addr, walk.nbytes); | ||
211 | err = blkcipher_walk_done(desc, &walk, 0); | ||
212 | } | ||
213 | |||
202 | return err; | 214 | return err; |
203 | } | 215 | } |
204 | 216 | ||