2007-12-26 13:48:28

by Herbert Xu

[permalink] [raw]
Subject: Re: OOPS: 2.6.23.11 in PadLock-AES when used in LRW-Mode

On Sun, Dec 23, 2007 at 06:22:14PM +0000, Alexander Eichhorn wrote:
>
> BUG: unable to handle kernel paging request at virtual address f8000000
> printing eip:
> c03bbc8c
> *pde = 00000000
> Oops: 0000 [#1]
> PREEMPT
> Modules linked in:
> CPU: 0
> EIP: 0060:[<c03bbc8c>] Not tainted VLI
> EFLAGS: 00010282 (2.6.23.11-vanilla #1)
> EIP is at aes_encrypt+0x17/0x1f
> eax: f4679400 ebx: f4679450 ecx: 00000001 edx: f4679420
> esi: f7fffff0 edi: f7fffff0 ebp: f7557e40 esp: f7557de4

Thanks for the report. This is due to the fact that xcryptecb always
processes an even number of blocks.

Please let me know if the following patch fixes the problem for you.

Thanks,
--
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <[email protected]>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
--
diff --git a/drivers/crypto/padlock-aes.c b/drivers/crypto/padlock-aes.c
index 6154cf1..a3e14ce 100644
--- a/drivers/crypto/padlock-aes.c
+++ b/drivers/crypto/padlock-aes.c
@@ -417,20 +417,65 @@ static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
/* ====== Encryption/decryption routines ====== */

/* These are the real call to PadLock. */
+static inline void padlock_reset_key(void)
+{
+ asm volatile ("pushfl; popfl");
+}
+
+static inline void padlock_xcrypt(const u8 *input, u8 *output, void *key,
+ void *control_word)
+{
+ asm volatile (".byte 0xf3,0x0f,0xa7,0xc8" /* rep xcryptecb */
+ : "+S"(input), "+D"(output)
+ : "d"(control_word), "b"(key), "c"(1));
+}
+
+static void aes_crypt_copy(const u8 *in, u8 *out, u32 *key, struct cword *cword)
+{
+ u8 tmp[AES_BLOCK_SIZE * 2]
+ __attribute__ ((__aligned__(PADLOCK_ALIGNMENT)));
+
+ memcpy(tmp, in, AES_BLOCK_SIZE);
+ padlock_xcrypt(tmp, out, key, cword);
+}
+
+static inline void aes_crypt(const u8 *in, u8 *out, u32 *key,
+ struct cword *cword)
+{
+ /* padlock_xcrypt requires at least two blocks of data. */
+ if (unlikely(!(((unsigned long)in ^ (PAGE_SIZE - AES_BLOCK_SIZE)) &
+ (PAGE_SIZE - 1)))) {
+ aes_crypt_copy(in, out, key, cword);
+ return;
+ }
+
+ padlock_xcrypt(in, out, key, cword);
+}
+
static inline void padlock_xcrypt_ecb(const u8 *input, u8 *output, void *key,
void *control_word, u32 count)
{
- asm volatile ("pushfl; popfl"); /* enforce key reload. */
- asm volatile (".byte 0xf3,0x0f,0xa7,0xc8" /* rep xcryptecb */
+ if (count == 1) {
+ aes_crypt(input, output, key, control_word);
+ return;
+ }
+
+ asm volatile ("test $1, %%cl;"
+ "je 1f;"
+ "lea -1(%%ecx), %%eax;"
+ "mov $1, %%ecx;"
+ ".byte 0xf3,0x0f,0xa7,0xc8;" /* rep xcryptecb */
+ "mov %%eax, %%ecx;"
+ "1:"
+ ".byte 0xf3,0x0f,0xa7,0xc8" /* rep xcryptecb */
: "+S"(input), "+D"(output)
- : "d"(control_word), "b"(key), "c"(count));
+ : "d"(control_word), "b"(key), "c"(count)
+ : "ax");
}

static inline u8 *padlock_xcrypt_cbc(const u8 *input, u8 *output, void *key,
u8 *iv, void *control_word, u32 count)
{
- /* Enforce key reload. */
- asm volatile ("pushfl; popfl");
/* rep xcryptcbc */
asm volatile (".byte 0xf3,0x0f,0xa7,0xd0"
: "+S" (input), "+D" (output), "+a" (iv)
@@ -441,13 +486,15 @@ static inline u8 *padlock_xcrypt_cbc(const u8 *input, u8 *output, void *key,
static void aes_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
{
struct aes_ctx *ctx = aes_ctx(tfm);
- padlock_xcrypt_ecb(in, out, ctx->E, &ctx->cword.encrypt, 1);
+ padlock_reset_key();
+ aes_crypt(in, out, ctx->E, &ctx->cword.encrypt);
}

static void aes_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
{
struct aes_ctx *ctx = aes_ctx(tfm);
- padlock_xcrypt_ecb(in, out, ctx->D, &ctx->cword.decrypt, 1);
+ padlock_reset_key();
+ aes_crypt(in, out, ctx->D, &ctx->cword.decrypt);
}

static struct crypto_alg aes_alg = {
@@ -479,6 +526,8 @@ static int ecb_aes_encrypt(struct blkcipher_desc *desc,
struct blkcipher_walk walk;
int err;

+ padlock_reset_key();
+
blkcipher_walk_init(&walk, dst, src, nbytes);
err = blkcipher_walk_virt(desc, &walk);

@@ -501,6 +550,8 @@ static int ecb_aes_decrypt(struct blkcipher_desc *desc,
struct blkcipher_walk walk;
int err;

+ padlock_reset_key();
+
blkcipher_walk_init(&walk, dst, src, nbytes);
err = blkcipher_walk_virt(desc, &walk);

@@ -545,6 +596,8 @@ static int cbc_aes_encrypt(struct blkcipher_desc *desc,
struct blkcipher_walk walk;
int err;

+ padlock_reset_key();
+
blkcipher_walk_init(&walk, dst, src, nbytes);
err = blkcipher_walk_virt(desc, &walk);

@@ -569,6 +622,8 @@ static int cbc_aes_decrypt(struct blkcipher_desc *desc,
struct blkcipher_walk walk;
int err;

+ padlock_reset_key();
+
blkcipher_walk_init(&walk, dst, src, nbytes);
err = blkcipher_walk_virt(desc, &walk);



2007-12-27 18:29:34

by Alexander Eichhorn

[permalink] [raw]
Subject: Re: OOPS: 2.6.23.11 in PadLock-AES when used in LRW-Mode

Patch Works. Tested with 2.6.23.11 on Via C7 with aes-lrw-benbi and
key-size 384 bit. Filesystem was an ext3 (default options) on top of
plain partition, Raid-1, and Raid-5.

Thanks a lot,
Alexander

On 26. Dec 2007, at 14:48 Uhr, Herbert Xu wrote:
> Please let me know if the following patch fixes the problem for you.


Alexander Eichhorn Distr. Systems and
Operating Systems Group
Faculty of Computer Science and Automation Ilmenau Technical University
Campus Center, room 433 phone: +49(0)3677-694557
http://www-ia.tu-ilmenau.de/~echa fax: +49(0)3677-694541

PGP Public Key: http://www-ia.tu-ilmenau.de/~echa/AlexanderEichhorn.asc
Fingerprint: 9724 37D9 77AD AF99 65B6 E220 F540 E333 C9EC DC4F




Attachments:
PGP.sig (194.00 B)
This is a digitally signed message part