-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
arm64/crypto: use crypto instructions to generate AES key schedule
(cherry pick from commit 12ac3efe74f888a13cb4df88b38bb01e8034dea8) This patch implements the AES key schedule generation using ARMv8 Crypto Instructions. It replaces the table based C implementation in aes_generic.ko, which means we can drop the dependency on that module. Tested-by: Steve Capper <[email protected]> Acked-by: Steve Capper <[email protected]> Signed-off-by: Ard Biesheuvel <[email protected]> Signed-off-by: Will Deacon <[email protected]> Signed-off-by: Mark Salyzyn <[email protected]> Bug: 23181629
- Loading branch information
Showing
5 changed files
with
133 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,6 +14,8 @@ | |
#include <linux/crypto.h> | ||
#include <linux/module.h> | ||
|
||
#include "aes-ce-setkey.h" | ||
|
||
MODULE_DESCRIPTION("Synchronous AES cipher using ARMv8 Crypto Extensions"); | ||
MODULE_AUTHOR("Ard Biesheuvel <[email protected]>"); | ||
MODULE_LICENSE("GPL v2"); | ||
|
@@ -124,6 +126,114 @@ static void aes_cipher_decrypt(struct crypto_tfm *tfm, u8 dst[], u8 const src[]) | |
kernel_neon_end(); | ||
} | ||
|
||
/* | ||
* aes_sub() - use the aese instruction to perform the AES sbox substitution | ||
* on each byte in 'input' | ||
*/ | ||
static u32 aes_sub(u32 input) | ||
{ | ||
u32 ret; | ||
|
||
__asm__("dup v1.4s, %w[in] ;" | ||
"movi v0.16b, #0 ;" | ||
"aese v0.16b, v1.16b ;" | ||
"umov %w[out], v0.4s[0] ;" | ||
|
||
: [out] "=r"(ret) | ||
: [in] "r"(input) | ||
: "v0","v1"); | ||
|
||
return ret; | ||
} | ||
|
||
int ce_aes_expandkey(struct crypto_aes_ctx *ctx, const u8 *in_key, | ||
unsigned int key_len) | ||
{ | ||
/* | ||
* The AES key schedule round constants | ||
*/ | ||
static u8 const rcon[] = { | ||
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, | ||
}; | ||
|
||
u32 kwords = key_len / sizeof(u32); | ||
struct aes_block *key_enc, *key_dec; | ||
int i, j; | ||
|
||
if (key_len != AES_KEYSIZE_128 && | ||
key_len != AES_KEYSIZE_192 && | ||
key_len != AES_KEYSIZE_256) | ||
return -EINVAL; | ||
|
||
memcpy(ctx->key_enc, in_key, key_len); | ||
ctx->key_length = key_len; | ||
|
||
kernel_neon_begin_partial(2); | ||
for (i = 0; i < sizeof(rcon); i++) { | ||
u32 *rki = ctx->key_enc + (i * kwords); | ||
u32 *rko = rki + kwords; | ||
|
||
rko[0] = ror32(aes_sub(rki[kwords - 1]), 8) ^ rcon[i] ^ rki[0]; | ||
rko[1] = rko[0] ^ rki[1]; | ||
rko[2] = rko[1] ^ rki[2]; | ||
rko[3] = rko[2] ^ rki[3]; | ||
|
||
if (key_len == AES_KEYSIZE_192) { | ||
if (i >= 7) | ||
break; | ||
rko[4] = rko[3] ^ rki[4]; | ||
rko[5] = rko[4] ^ rki[5]; | ||
} else if (key_len == AES_KEYSIZE_256) { | ||
if (i >= 6) | ||
break; | ||
rko[4] = aes_sub(rko[3]) ^ rki[4]; | ||
rko[5] = rko[4] ^ rki[5]; | ||
rko[6] = rko[5] ^ rki[6]; | ||
rko[7] = rko[6] ^ rki[7]; | ||
} | ||
} | ||
|
||
/* | ||
* Generate the decryption keys for the Equivalent Inverse Cipher. | ||
* This involves reversing the order of the round keys, and applying | ||
* the Inverse Mix Columns transformation on all but the first and | ||
* the last one. | ||
*/ | ||
key_enc = (struct aes_block *)ctx->key_enc; | ||
key_dec = (struct aes_block *)ctx->key_dec; | ||
j = num_rounds(ctx); | ||
|
||
key_dec[0] = key_enc[j]; | ||
for (i = 1, j--; j > 0; i++, j--) | ||
__asm__("ld1 {v0.16b}, %[in] ;" | ||
"aesimc v1.16b, v0.16b ;" | ||
"st1 {v1.16b}, %[out] ;" | ||
|
||
: [out] "=Q"(key_dec[i]) | ||
: [in] "Q"(key_enc[j]) | ||
: "v0","v1"); | ||
key_dec[i] = key_enc[0]; | ||
|
||
kernel_neon_end(); | ||
return 0; | ||
} | ||
EXPORT_SYMBOL(ce_aes_expandkey); | ||
|
||
int ce_aes_setkey(struct crypto_tfm *tfm, const u8 *in_key, | ||
unsigned int key_len) | ||
{ | ||
struct crypto_aes_ctx *ctx = crypto_tfm_ctx(tfm); | ||
int ret; | ||
|
||
ret = ce_aes_expandkey(ctx, in_key, key_len); | ||
if (!ret) | ||
return 0; | ||
|
||
tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; | ||
return -EINVAL; | ||
} | ||
EXPORT_SYMBOL(ce_aes_setkey); | ||
|
||
static struct crypto_alg aes_alg = { | ||
.cra_name = "aes", | ||
.cra_driver_name = "aes-ce", | ||
|
@@ -135,7 +245,7 @@ static struct crypto_alg aes_alg = { | |
.cra_cipher = { | ||
.cia_min_keysize = AES_MIN_KEY_SIZE, | ||
.cia_max_keysize = AES_MAX_KEY_SIZE, | ||
.cia_setkey = crypto_aes_set_key, | ||
.cia_setkey = ce_aes_setkey, | ||
.cia_encrypt = aes_cipher_encrypt, | ||
.cia_decrypt = aes_cipher_decrypt | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
|
||
int ce_aes_setkey(struct crypto_tfm *tfm, const u8 *in_key, | ||
unsigned int key_len); | ||
int ce_aes_expandkey(struct crypto_aes_ctx *ctx, const u8 *in_key, | ||
unsigned int key_len); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters