aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2007-12-27 19:05:46 -0500
committerHerbert Xu <herbert@gondor.apana.org.au>2007-12-27 19:05:46 -0500
commitd4a7dd8e637b322faaa934ffcd6dd07711af831f (patch)
treedf36c0ce7c538f34dd8f1a0fb183ee2dcc8c73c6
parent38cb2419f544ad413c7f7aa8c17fd7377610cdd8 (diff)
[CRYPTO] padlock: Fix spurious ECB page fault
The xcryptecb instruction always processes an even number of blocks so we need to ensure th existence of an extra block if we have to process an odd number of blocks. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
-rw-r--r--drivers/crypto/padlock-aes.c53
1 files changed, 49 insertions, 4 deletions
diff --git a/drivers/crypto/padlock-aes.c b/drivers/crypto/padlock-aes.c
index abbcff0762b1..a337b693b6c9 100644
--- a/drivers/crypto/padlock-aes.c
+++ b/drivers/crypto/padlock-aes.c
@@ -419,13 +419,58 @@ static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
419/* ====== Encryption/decryption routines ====== */ 419/* ====== Encryption/decryption routines ====== */
420 420
421/* These are the real call to PadLock. */ 421/* These are the real call to PadLock. */
422static inline void padlock_xcrypt(const u8 *input, u8 *output, void *key,
423 void *control_word)
424{
425 asm volatile (".byte 0xf3,0x0f,0xa7,0xc8" /* rep xcryptecb */
426 : "+S"(input), "+D"(output)
427 : "d"(control_word), "b"(key), "c"(1));
428}
429
430static void aes_crypt_copy(const u8 *in, u8 *out, u32 *key, struct cword *cword)
431{
432 u8 tmp[AES_BLOCK_SIZE * 2]
433 __attribute__ ((__aligned__(PADLOCK_ALIGNMENT)));
434
435 memcpy(tmp, in, AES_BLOCK_SIZE);
436 padlock_xcrypt(tmp, out, key, cword);
437}
438
439static inline void aes_crypt(const u8 *in, u8 *out, u32 *key,
440 struct cword *cword)
441{
442 asm volatile ("pushfl; popfl");
443
444 /* padlock_xcrypt requires at least two blocks of data. */
445 if (unlikely(!(((unsigned long)in ^ (PAGE_SIZE - AES_BLOCK_SIZE)) &
446 (PAGE_SIZE - 1)))) {
447 aes_crypt_copy(in, out, key, cword);
448 return;
449 }
450
451 padlock_xcrypt(in, out, key, cword);
452}
453
422static inline void padlock_xcrypt_ecb(const u8 *input, u8 *output, void *key, 454static inline void padlock_xcrypt_ecb(const u8 *input, u8 *output, void *key,
423 void *control_word, u32 count) 455 void *control_word, u32 count)
424{ 456{
457 if (count == 1) {
458 aes_crypt(input, output, key, control_word);
459 return;
460 }
461
425 asm volatile ("pushfl; popfl"); /* enforce key reload. */ 462 asm volatile ("pushfl; popfl"); /* enforce key reload. */
426 asm volatile (".byte 0xf3,0x0f,0xa7,0xc8" /* rep xcryptecb */ 463 asm volatile ("test $1, %%cl;"
464 "je 1f;"
465 "lea -1(%%ecx), %%eax;"
466 "mov $1, %%ecx;"
467 ".byte 0xf3,0x0f,0xa7,0xc8;" /* rep xcryptecb */
468 "mov %%eax, %%ecx;"
469 "1:"
470 ".byte 0xf3,0x0f,0xa7,0xc8" /* rep xcryptecb */
427 : "+S"(input), "+D"(output) 471 : "+S"(input), "+D"(output)
428 : "d"(control_word), "b"(key), "c"(count)); 472 : "d"(control_word), "b"(key), "c"(count)
473 : "ax");
429} 474}
430 475
431static inline u8 *padlock_xcrypt_cbc(const u8 *input, u8 *output, void *key, 476static inline u8 *padlock_xcrypt_cbc(const u8 *input, u8 *output, void *key,
@@ -443,13 +488,13 @@ static inline u8 *padlock_xcrypt_cbc(const u8 *input, u8 *output, void *key,
443static void aes_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) 488static void aes_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
444{ 489{
445 struct aes_ctx *ctx = aes_ctx(tfm); 490 struct aes_ctx *ctx = aes_ctx(tfm);
446 padlock_xcrypt_ecb(in, out, ctx->E, &ctx->cword.encrypt, 1); 491 aes_crypt(in, out, ctx->E, &ctx->cword.encrypt);
447} 492}
448 493
449static void aes_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) 494static void aes_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
450{ 495{
451 struct aes_ctx *ctx = aes_ctx(tfm); 496 struct aes_ctx *ctx = aes_ctx(tfm);
452 padlock_xcrypt_ecb(in, out, ctx->D, &ctx->cword.decrypt, 1); 497 aes_crypt(in, out, ctx->D, &ctx->cword.decrypt);
453} 498}
454 499
455static struct crypto_alg aes_alg = { 500static struct crypto_alg aes_alg = {