aboutsummaryrefslogtreecommitdiff
path: root/crypto
diff options
context:
space:
mode:
authorDavid Benjamin <davidben@google.com>2024-05-17 21:30:32 -0400
committerBoringssl LUCI CQ <boringssl-scoped@luci-project-accounts.iam.gserviceaccount.com>2024-06-08 15:38:19 +0000
commit56fb43a204e57af68e00f4561c108a7004381aa3 (patch)
treec59a189622798c61b0fae8a8ef9ae04f9790dcab /crypto
parent29223ac349c144a4d0babc281644c0410dd1e313 (diff)
downloadboringssl-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.c13
-rw-r--r--crypto/fipsmodule/aes/aes_test.cc5
-rw-r--r--crypto/fipsmodule/aes/asm/aesni-x86.pl20
-rw-r--r--crypto/fipsmodule/aes/asm/aesni-x86_64.pl62
-rw-r--r--crypto/fipsmodule/aes/internal.h18
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)