summaryrefslogtreecommitdiffstats
path: root/include/crypto/algapi.h
diff options
context:
space:
mode:
authorArd Biesheuvel <ard.biesheuvel@linaro.org>2017-02-05 05:06:12 -0500
committerHerbert Xu <herbert@gondor.apana.org.au>2017-02-11 04:52:28 -0500
commitdb91af0fbe20474cec33263e28d15f5e6b45ebc9 (patch)
tree22ff7970897903b0418cef78a2aeb59907f5b554 /include/crypto/algapi.h
parent7d6e9105026788c497f0ab32fa16c82f4ab5ff61 (diff)
crypto: algapi - make crypto_xor() and crypto_inc() alignment agnostic
Instead of unconditionally forcing 4 byte alignment for all generic chaining modes that rely on crypto_xor() or crypto_inc() (which may result in unnecessary copying of data when the underlying hardware can perform unaligned accesses efficiently), make those functions deal with unaligned input explicitly, but only if the Kconfig symbol HAVE_EFFICIENT_UNALIGNED_ACCESS is set. This will allow us to drop the alignmasks from the CBC, CMAC, CTR, CTS, PCBC and SEQIV drivers. For crypto_inc(), this simply involves making the 4-byte stride conditional on HAVE_EFFICIENT_UNALIGNED_ACCESS being set, given that it typically operates on 16 byte buffers. For crypto_xor(), an algorithm is implemented that simply runs through the input using the largest strides possible if unaligned accesses are allowed. If they are not, an optimal sequence of memory accesses is emitted that takes the relative alignment of the input buffers into account, e.g., if the relative misalignment of dst and src is 4 bytes, the entire xor operation will be completed using 4 byte loads and stores (modulo unaligned bits at the start and end). Note that all expressions involving misalign are simply eliminated by the compiler when HAVE_EFFICIENT_UNALIGNED_ACCESS is defined. Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'include/crypto/algapi.h')
-rw-r--r--include/crypto/algapi.h20
1 files changed, 18 insertions, 2 deletions
diff --git a/include/crypto/algapi.h b/include/crypto/algapi.h
index 404e9558e879..ebe4ded0c55d 100644
--- a/include/crypto/algapi.h
+++ b/include/crypto/algapi.h
@@ -191,9 +191,25 @@ static inline unsigned int crypto_queue_len(struct crypto_queue *queue)
191 return queue->qlen; 191 return queue->qlen;
192} 192}
193 193
194/* These functions require the input/output to be aligned as u32. */
195void crypto_inc(u8 *a, unsigned int size); 194void crypto_inc(u8 *a, unsigned int size);
196void crypto_xor(u8 *dst, const u8 *src, unsigned int size); 195void __crypto_xor(u8 *dst, const u8 *src, unsigned int size);
196
197static inline void crypto_xor(u8 *dst, const u8 *src, unsigned int size)
198{
199 if (IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) &&
200 __builtin_constant_p(size) &&
201 (size % sizeof(unsigned long)) == 0) {
202 unsigned long *d = (unsigned long *)dst;
203 unsigned long *s = (unsigned long *)src;
204
205 while (size > 0) {
206 *d++ ^= *s++;
207 size -= sizeof(unsigned long);
208 }
209 } else {
210 __crypto_xor(dst, src, size);
211 }
212}
197 213
198int blkcipher_walk_done(struct blkcipher_desc *desc, 214int blkcipher_walk_done(struct blkcipher_desc *desc,
199 struct blkcipher_walk *walk, int err); 215 struct blkcipher_walk *walk, int err);