diff options
author | David Benjamin <davidben@google.com> | 2024-05-17 21:30:32 -0400 |
---|---|---|
committer | Boringssl LUCI CQ <boringssl-scoped@luci-project-accounts.iam.gserviceaccount.com> | 2024-06-08 15:38:19 +0000 |
commit | 56fb43a204e57af68e00f4561c108a7004381aa3 (patch) | |
tree | c59a189622798c61b0fae8a8ef9ae04f9790dcab /crypto | |
parent | 29223ac349c144a4d0babc281644c0410dd1e313 (diff) | |
download | boringssl-56fb43a204e57af68e00f4561c108a7004381aa3.zip boringssl-56fb43a204e57af68e00f4561c108a7004381aa3.tar.gz boringssl-56fb43a204e57af68e00f4561c108a7004381aa3.tar.bz2 |
Extract the AES-NI encrypt -> decrypt assembly conversion
aes_hw_set_decrypt_key calls aes_hw_set_encrypt_key and then does a
conversion, all in assembly. On x86(_64), aes_hw_set_encrypt_key
internally checks OPENSSL_ia32cap_P to call one of two variants.
In preparation for splitting those variants into separate functions, get
the in-asm function call out o f the day by extracting an
aes_hw_encrypt_key_to_decrypt_key function.
Bug: 673
Change-Id: I23eefc00bdc8cb1f20e17fb6716974e91f1c32c4
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/68689
Reviewed-by: Bob Beck <bbe@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
Diffstat (limited to 'crypto')
-rw-r--r-- | crypto/fipsmodule/aes/aes.c | 13 | ||||
-rw-r--r-- | crypto/fipsmodule/aes/aes_test.cc | 5 | ||||
-rw-r--r-- | crypto/fipsmodule/aes/asm/aesni-x86.pl | 20 | ||||
-rw-r--r-- | crypto/fipsmodule/aes/asm/aesni-x86_64.pl | 62 | ||||
-rw-r--r-- | crypto/fipsmodule/aes/internal.h | 18 |
5 files changed, 58 insertions, 60 deletions
diff --git a/crypto/fipsmodule/aes/aes.c b/crypto/fipsmodule/aes/aes.c index 60f3545..56dfbe2 100644 --- a/crypto/fipsmodule/aes/aes.c +++ b/crypto/fipsmodule/aes/aes.c @@ -104,3 +104,16 @@ int AES_set_decrypt_key(const uint8_t *key, unsigned bits, AES_KEY *aeskey) { return aes_nohw_set_decrypt_key(key, bits, aeskey); } } + +#if defined(HWAES) && (defined(OPENSSL_X86) || defined(OPENSSL_X86_64)) +// On x86 and x86_64, |aes_hw_set_decrypt_key|, we implement +// |aes_hw_encrypt_key_to_decrypt_key| in assembly and rely on C code to combine +// the operations. +int aes_hw_set_decrypt_key(const uint8_t *user_key, int bits, AES_KEY *key) { + int ret = aes_hw_set_encrypt_key(user_key, bits, key); + if (ret == 0) { + aes_hw_encrypt_key_to_decrypt_key(key); + } + return ret; +} +#endif diff --git a/crypto/fipsmodule/aes/aes_test.cc b/crypto/fipsmodule/aes/aes_test.cc index d4a458b..dc90067 100644 --- a/crypto/fipsmodule/aes/aes_test.cc +++ b/crypto/fipsmodule/aes/aes_test.cc @@ -346,7 +346,12 @@ TEST(AESTest, ABI) { #endif } +#if defined(OPENSSL_X86) || defined(OPENSSL_X86_64) + ASSERT_EQ(CHECK_ABI_SEH(aes_hw_set_encrypt_key, kKey, bits, &key), 0); + CHECK_ABI_SEH(aes_hw_encrypt_key_to_decrypt_key, &key); +#else ASSERT_EQ(CHECK_ABI_SEH(aes_hw_set_decrypt_key, kKey, bits, &key), 0); +#endif CHECK_ABI(aes_hw_decrypt, block, block, &key); for (size_t blocks : block_counts) { SCOPED_TRACE(blocks); diff --git a/crypto/fipsmodule/aes/asm/aesni-x86.pl b/crypto/fipsmodule/aes/asm/aesni-x86.pl index bb5ee94..d8fdfb8 100644 --- a/crypto/fipsmodule/aes/asm/aesni-x86.pl +++ b/crypto/fipsmodule/aes/asm/aesni-x86.pl @@ -2490,17 +2490,11 @@ if ($PREFIX eq $AESNI_PREFIX) { &ret (); &function_end_B("${PREFIX}_set_encrypt_key"); -# int $PREFIX_set_decrypt_key (const unsigned char *userKey, int bits, -# AES_KEY *key) -&function_begin_B("${PREFIX}_set_decrypt_key"); - &mov ("eax",&wparam(0)); - &mov ($rounds,&wparam(1)); - &mov ($key,&wparam(2)); - &call ("_aesni_set_encrypt_key"); - &mov ($key,&wparam(2)); - &shl ($rounds,4); # rounds-1 after _aesni_set_encrypt_key - &test ("eax","eax"); - &jnz (&label("dec_key_ret")); +# void $PREFIX_encrypt_key_to_decrypt_key (AES_KEY *key) +&function_begin_B("${PREFIX}_encrypt_key_to_decrypt_key"); + &mov ($key,&wparam(0)); + &mov ($rounds,&DWP(240,$key)); + &shl ($rounds,4); &lea ("eax",&DWP(16,$key,$rounds)); # end of key schedule &$movekey ("xmm0",&QWP(0,$key)); # just swap @@ -2528,10 +2522,8 @@ if ($PREFIX eq $AESNI_PREFIX) { &pxor ("xmm0","xmm0"); &pxor ("xmm1","xmm1"); - &xor ("eax","eax"); # return success -&set_label("dec_key_ret"); &ret (); -&function_end_B("${PREFIX}_set_decrypt_key"); +&function_end_B("${PREFIX}_encrypt_key_to_decrypt_key"); &set_label("key_const",64); &data_word(0x0c0f0e0d,0x0c0f0e0d,0x0c0f0e0d,0x0c0f0e0d); diff --git a/crypto/fipsmodule/aes/asm/aesni-x86_64.pl b/crypto/fipsmodule/aes/asm/aesni-x86_64.pl index 17ec466..8b6036e 100644 --- a/crypto/fipsmodule/aes/asm/aesni-x86_64.pl +++ b/crypto/fipsmodule/aes/asm/aesni-x86_64.pl @@ -3172,69 +3172,55 @@ $code.=<<___; .size ${PREFIX}_cbc_encrypt,.-${PREFIX}_cbc_encrypt ___ } -# int ${PREFIX}_set_decrypt_key(const unsigned char *inp, -# int bits, AES_KEY *key) -# -# input: $inp user-supplied key -# $bits $inp length in bits -# $key pointer to key schedule -# output: %eax 0 denoting success, -1 or -2 - failure (see C) -# *$key key schedule -# -{ my ($inp,$bits,$key) = @_4args; - $bits =~ s/%r/%e/; +{ my ($key, $rounds, $tmp) = @_4args; + $rounds =~ s/%r/%e/; +# void ${PREFIX}_encrypt_key_to_decrypt_key(AES_KEY *key) $code.=<<___; -.globl ${PREFIX}_set_decrypt_key -.type ${PREFIX}_set_decrypt_key,\@abi-omnipotent +.globl ${PREFIX}_encrypt_key_to_decrypt_key +.type ${PREFIX}_encrypt_key_to_decrypt_key,\@abi-omnipotent .align 16 -${PREFIX}_set_decrypt_key: +${PREFIX}_encrypt_key_to_decrypt_key: .cfi_startproc -.seh_startproc _CET_ENDBR - sub \$8,%rsp -.cfi_adjust_cfa_offset 8 -.seh_stackalloc 8 -.seh_endprologue - call __aesni_set_encrypt_key - shl \$4,$bits # rounds-1 after _aesni_set_encrypt_key - test %eax,%eax - jnz .Ldec_key_ret - lea 16($key,$bits),$inp # points at the end of key schedule + + mov 240($key), $rounds + shl \$4,$rounds + + lea 16($key,$rounds),$tmp # points at the end of key schedule $movkey ($key),%xmm0 # just swap - $movkey ($inp),%xmm1 - $movkey %xmm0,($inp) + $movkey ($tmp),%xmm1 + $movkey %xmm0,($tmp) $movkey %xmm1,($key) lea 16($key),$key - lea -16($inp),$inp + lea -16($tmp),$tmp .Ldec_key_inverse: $movkey ($key),%xmm0 # swap and inverse - $movkey ($inp),%xmm1 + $movkey ($tmp),%xmm1 aesimc %xmm0,%xmm0 aesimc %xmm1,%xmm1 lea 16($key),$key - lea -16($inp),$inp - $movkey %xmm0,16($inp) + lea -16($tmp),$tmp + $movkey %xmm0,16($tmp) $movkey %xmm1,-16($key) - cmp $key,$inp + cmp $key,$tmp ja .Ldec_key_inverse $movkey ($key),%xmm0 # inverse middle aesimc %xmm0,%xmm0 pxor %xmm1,%xmm1 - $movkey %xmm0,($inp) + $movkey %xmm0,($tmp) pxor %xmm0,%xmm0 -.Ldec_key_ret: - add \$8,%rsp -.cfi_adjust_cfa_offset -8 ret .cfi_endproc -.seh_endproc -.size ${PREFIX}_set_decrypt_key,.-${PREFIX}_set_decrypt_key +.size ${PREFIX}_encrypt_key_to_decrypt_key,.-${PREFIX}_encrypt_key_to_decrypt_key ___ +} +{ my ($inp,$bits,$key) = @_4args; + $bits =~ s/%r/%e/; # This is based on submission from Intel by # Huang Ying # Vinodh Gopal @@ -3264,7 +3250,6 @@ $code.=<<___; .type ${PREFIX}_set_encrypt_key,\@abi-omnipotent .align 16 ${PREFIX}_set_encrypt_key: -__aesni_set_encrypt_key: .cfi_startproc .seh_startproc _CET_ENDBR @@ -3636,7 +3621,6 @@ __aesni_set_encrypt_key: xorps %xmm1,%xmm2 ret .size ${PREFIX}_set_encrypt_key,.-${PREFIX}_set_encrypt_key -.size __aesni_set_encrypt_key,.-__aesni_set_encrypt_key ___ } diff --git a/crypto/fipsmodule/aes/internal.h b/crypto/fipsmodule/aes/internal.h index 98b2a14d..e7f55d2 100644 --- a/crypto/fipsmodule/aes/internal.h +++ b/crypto/fipsmodule/aes/internal.h @@ -66,17 +66,21 @@ OPENSSL_INLINE int vpaes_capable(void) { return CRYPTO_is_NEON_capable(); } #if defined(HWAES) -int aes_hw_set_encrypt_key(const uint8_t *user_key, const int bits, - AES_KEY *key); -int aes_hw_set_decrypt_key(const uint8_t *user_key, const int bits, - AES_KEY *key); +int aes_hw_set_encrypt_key(const uint8_t *user_key, int bits, AES_KEY *key); +int aes_hw_set_decrypt_key(const uint8_t *user_key, int bits, AES_KEY *key); void aes_hw_encrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key); void aes_hw_decrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key); void aes_hw_cbc_encrypt(const uint8_t *in, uint8_t *out, size_t length, - const AES_KEY *key, uint8_t *ivec, const int enc); + const AES_KEY *key, uint8_t *ivec, int enc); void aes_hw_ctr32_encrypt_blocks(const uint8_t *in, uint8_t *out, size_t len, const AES_KEY *key, const uint8_t ivec[16]); +#if defined(OPENSSL_X86) || defined(OPENSSL_X86_64) +// On x86 and x86_64, |aes_hw_set_decrypt_key| is implemented in terms of +// |aes_hw_set_encrypt_key| and a conversion function. +void aes_hw_encrypt_key_to_decrypt_key(AES_KEY *key); +#endif + #else // If HWAES isn't defined then we provide dummy functions for each of the hwaes @@ -120,7 +124,7 @@ OPENSSL_INLINE void aes_hw_ctr32_encrypt_blocks(const uint8_t *in, uint8_t *out, #if defined(HWAES_ECB) void aes_hw_ecb_encrypt(const uint8_t *in, uint8_t *out, size_t length, - const AES_KEY *key, const int enc); + const AES_KEY *key, int enc); #endif // HWAES_ECB @@ -218,7 +222,7 @@ void aes_nohw_ctr32_encrypt_blocks(const uint8_t *in, uint8_t *out, size_t blocks, const AES_KEY *key, const uint8_t ivec[16]); void aes_nohw_cbc_encrypt(const uint8_t *in, uint8_t *out, size_t len, - const AES_KEY *key, uint8_t *ivec, const int enc); + const AES_KEY *key, uint8_t *ivec, int enc); #if defined(__cplusplus) |