diff options
Diffstat (limited to 'drivers/crypto')
-rw-r--r-- | drivers/crypto/padlock-aes.c | 53 |
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. */ |
422 | static 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 | |||
430 | static 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 | |||
439 | static 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 | |||
422 | static inline void padlock_xcrypt_ecb(const u8 *input, u8 *output, void *key, | 454 | static 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 | ||
431 | static inline u8 *padlock_xcrypt_cbc(const u8 *input, u8 *output, void *key, | 476 | static 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, | |||
443 | static void aes_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) | 488 | static 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 | ||
449 | static void aes_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) | 494 | static 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 | ||
455 | static struct crypto_alg aes_alg = { | 500 | static struct crypto_alg aes_alg = { |