authorgravatar for 124872+jedisct1@users.noreply.github.comFrank Denis <124872+jedisct1@users.noreply.github.com> 2023-03-13 08:06:27+01:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2023-03-13 07:06:27+00:00
log1d96a17af473d5ca79ecc7b64bbf2e899b5de3b4
treead2e8a32bebcd5a27eca3262028f2c4e62a8b339
parent10c74631b381b6b7d84def90a3a747192f2793a0
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

crypto.aescrypto.encrypt: do not add the round key in an asm block (#14899)

Apple M1/M2 have an EOR3 instruction that can XOR 2 operands with another one, and LLVM knows how to take advantage of it. However, two EOR can't be automatically combined into an EOR3 if one of them is in an assembly block. That simple change speeds up ciphers doing an AES round immediately followed by a XOR operation on Apple Silicon. Before: aegis-128l mac: 12534 MiB/s aegis-256 mac: 6722 MiB/s aegis-128l: 10634 MiB/s aegis-256: 6133 MiB/s aes128-gcm: 3890 MiB/s aes256-gcm: 3122 MiB/s aes128-ocb: 2832 MiB/s aes256-ocb: 2057 MiB/s After: aegis-128l mac: 15667 MiB/s aegis-256 mac: 8240 MiB/s aegis-128l: 12656 MiB/s aegis-256: 7214 MiB/s aes128-gcm: 3976 MiB/s aes256-gcm: 3202 MiB/s aes128-ocb: 2835 MiB/s aes256-ocb: 2118 MiB/s

1 files changed, 8 insertions(+), 16 deletions(-)

lib/std/crypto/aes/armcrypto.zig+8-16
......@@ -32,62 +32,54 @@ pub const Block = struct {
3232 /// Encrypt a block with a round key.
3333 pub inline fn encrypt(block: Block, round_key: Block) Block {
3434 return Block{
35 .repr = asm (
35 .repr = (asm (
3636 \\ mov %[out].16b, %[in].16b
3737 \\ aese %[out].16b, %[zero].16b
3838 \\ aesmc %[out].16b, %[out].16b
39 \\ eor %[out].16b, %[out].16b, %[rk].16b
4039 : [out] "=&x" (-> BlockVec),
4140 : [in] "x" (block.repr),
42 [rk] "x" (round_key.repr),
4341 [zero] "x" (zero),
44 ),
42 )) ^ round_key.repr,
4543 };
4644 }
4745
4846 /// Encrypt a block with the last round key.
4947 pub inline fn encryptLast(block: Block, round_key: Block) Block {
5048 return Block{
51 .repr = asm (
49 .repr = (asm (
5250 \\ mov %[out].16b, %[in].16b
5351 \\ aese %[out].16b, %[zero].16b
54 \\ eor %[out].16b, %[out].16b, %[rk].16b
5552 : [out] "=&x" (-> BlockVec),
5653 : [in] "x" (block.repr),
57 [rk] "x" (round_key.repr),
5854 [zero] "x" (zero),
59 ),
55 )) ^ round_key.repr,
6056 };
6157 }
6258
6359 /// Decrypt a block with a round key.
6460 pub inline fn decrypt(block: Block, inv_round_key: Block) Block {
6561 return Block{
66 .repr = asm (
62 .repr = (asm (
6763 \\ mov %[out].16b, %[in].16b
6864 \\ aesd %[out].16b, %[zero].16b
6965 \\ aesimc %[out].16b, %[out].16b
70 \\ eor %[out].16b, %[out].16b, %[rk].16b
7166 : [out] "=&x" (-> BlockVec),
7267 : [in] "x" (block.repr),
73 [rk] "x" (inv_round_key.repr),
7468 [zero] "x" (zero),
75 ),
69 )) ^ inv_round_key.repr,
7670 };
7771 }
7872
7973 /// Decrypt a block with the last round key.
8074 pub inline fn decryptLast(block: Block, inv_round_key: Block) Block {
8175 return Block{
82 .repr = asm (
76 .repr = (asm (
8377 \\ mov %[out].16b, %[in].16b
8478 \\ aesd %[out].16b, %[zero].16b
85 \\ eor %[out].16b, %[out].16b, %[rk].16b
8679 : [out] "=&x" (-> BlockVec),
8780 : [in] "x" (block.repr),
88 [rk] "x" (inv_round_key.repr),
8981 [zero] "x" (zero),
90 ),
82 )) ^ inv_round_key.repr,
9183 };
9284 }
9385