[PATCH 6/7] sm4: add Intel SM4 instructions accelerated AVX512 implementation
Jussi Kivilinna <[email protected]> Sun, 28 Jun 2026 15:37:40 +0300
| Newsgroups | gmane.comp.encryption.gpg.libgcrypt.devel |
|---|---|
| Message-ID | <[email protected]> |
* cipher/Makefile.am: Add 'sm4-avx512-amd64.h' and 'sm4-intel-avx512-amd64.S'. * cipher/sm4-avx512-amd64.h: New, 32-block cipher mode functions moved here from 'sm4-gfni-avx512-amd64.S'. * cipher/sm4-gfni-avx512-amd64.S (_gcry_sm4_gfni_avx512_crypt_blk32) (_gcry_sm4_gfni_avx512_ctr_enc_blk32) (_gcry_sm4_gfni_avx512_cbc_dec_blk32) (_gcry_sm4_gfni_avx512_cfb_dec_blk32) (_gcry_sm4_gfni_avx512_ocb_enc_blk32) (_gcry_sm4_gfni_avx512_ocb_dec_blk32): Move to 'sm4-avx512-amd64.h'. (FUNC_NAME, SM4_CRYPT_BLK32): New. * cipher/sm4-intel-avx512-amd64.S: New. * cipher/sm4.c (USE_INTEL_SM4_AVX512): New. (ASM_FUNC_ABI): Define also for Intel SM4 AVX512 implementation. (SM4_context): Add 'use_intel_sm4_avx512'. (_gcry_sm4_intel_avx512_ctr_enc_blk32) (_gcry_sm4_intel_avx512_cbc_dec_blk32) (_gcry_sm4_intel_avx512_cfb_dec_blk32) (_gcry_sm4_intel_avx512_ocb_enc_blk32) (_gcry_sm4_intel_avx512_ocb_dec_blk32) (_gcry_sm4_intel_avx512_crypt_blk32): New. (sm4_setkey): Enable Intel SM4 AVX512 implementation if supported by CPU. (sm4_crypt_blk1_32, _gcry_sm4_ctr_enc, _gcry_sm4_cbc_dec) (_gcry_sm4_cfb_dec, _gcry_sm4_ocb_crypt) [USE_INTEL_SM4_AVX512]: Add Intel SM4 AVX512 code path. * configure.ac (GCRYPT_ASM_CIPHERS) [x86_64]: Add 'sm4-intel-avx512-amd64.lo'. -- Add a 32-block SM4 implementation using the Intel SM4 instruction set extension (EVEX/512-bit encoded VSM4RNDS4). The 32-block cipher mode code is shared with the GFNI/AVX512 implementation through a new 'sm4-avx512-amd64.h' header; the key schedule and the 16-block and shorter paths are reused from the AVX2 implementation. It is used in preference to the GFNI/AVX512 implementation when available. Tested with Intel SDE; not yet tested on real hardware. Signed-off-by: Jussi Kivilinna <[email protected]> --- cipher/Makefile.am | 4 +- cipher/sm4-avx512-amd64.h | 620 ++++++++++++++++++++++++++++++++ cipher/sm4-gfni-avx512-amd64.S | 593 +----------------------------- cipher/sm4-intel-avx512-amd64.S | 174 +++++++++ cipher/sm4.c | 134 ++++++- configure.ac | 1 + 6 files changed, 934 insertions(+), 592 deletions(-) create mode 100644 cipher/sm4-avx512-amd64.h create mode 100644 cipher/sm4-intel-avx512-amd64.S diff --git a/cipher/Makefile.am b/cipher/Makefile.am index 04094a10..8f54ea47 100644 --- a/cipher/Makefile.am +++ b/cipher/Makefile.am @@ -137,8 +137,8 @@ EXTRA_libcipher_la_SOURCES = \ serpent-avx512-x86.c serpent-armv7-neon.S \ simd-common-aarch64.h simd-common-ppc.h simd-common-riscv.h \ sm4.c sm4-aesni-avx-amd64.S sm4-aesni-avx2-amd64.S \ - sm4-avx2-amd64.h \ - sm4-intel-avx2-amd64.S \ + sm4-avx2-amd64.h sm4-avx512-amd64.h \ + sm4-intel-avx2-amd64.S sm4-intel-avx512-amd64.S \ sm4-gfni-avx2-amd64.S sm4-gfni-avx512-amd64.S \ sm4-aarch64.S sm4-armv8-aarch64-ce.S sm4-armv9-aarch64-sve-ce.S \ sm4-ppc.c \ diff --git a/cipher/sm4-avx512-amd64.h b/cipher/sm4-avx512-amd64.h new file mode 100644 index 00000000..3ee5a4f6 --- /dev/null +++ b/cipher/sm4-avx512-amd64.h @@ -0,0 +1,620 @@ +/* sm4-avx512-amd64.h - Shared AVX512 32-block cipher mode code for SM4 + * + * Copyright (C) 2022-2023 Jussi Kivilinna <[email protected]> + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef GCRY_SM4_AVX512_AMD64_H +#define GCRY_SM4_AVX512_AMD64_H + +SECTION_RODATA +.align 64 + +ELF(.type FUNC_NAME(cipher_mode_consts),@object) +FUNC_NAME(cipher_mode_consts): + +/* CTR mode addition constants */ + +.Lcounter0123_lo: + .quad 0, 0 + .quad 1, 0 + .quad 2, 0 + .quad 3, 0 + +.Lbige_addb_0_1: + .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 +.Lbige_addb_2_3: + .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2 + .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3 +.Lbige_addb_4_5: + .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4 + .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5 +.Lbige_addb_6_7: + .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6 + .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7 +.Lbige_addb_8_9: + .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8 + .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9 +.Lbige_addb_10_11: + .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10 + .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11 +.Lbige_addb_12_13: + .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12 + .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13 +.Lbige_addb_14_15: + .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14 + .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15 +.Lbige_addb_16: + .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16 + +.Lcounter2222_lo: + .quad 2, 0 +.Lcounter4444_lo: + .quad 4, 0 +.Lcounter8888_lo: + .quad 8, 0 +.Lcounter16161616_lo: + .quad 16, 0 +.Lcounter1111_hi: + .quad 0, 1 + +.text + +.align 16 +.globl FUNC_NAME(crypt_blk32) +ELF(.type FUNC_NAME(crypt_blk32),@function;) +FUNC_NAME(crypt_blk32): + /* input: + * %rdi: ctx, CTX + * %rsi: dst (32 blocks) + * %rdx: src (32 blocks) + */ + CFI_STARTPROC(); + spec_stop_avx512; + + /* Load input */ + vmovdqu32 (0 * 64)(%rdx), RA0z; + vmovdqu32 (1 * 64)(%rdx), RA1z; + vmovdqu32 (2 * 64)(%rdx), RA2z; + vmovdqu32 (3 * 64)(%rdx), RA3z; + vmovdqu32 (4 * 64)(%rdx), RB0z; + vmovdqu32 (5 * 64)(%rdx), RB1z; + vmovdqu32 (6 * 64)(%rdx), RB2z; + vmovdqu32 (7 * 64)(%rdx), RB3z; + + call SM4_CRYPT_BLK32; + + vmovdqu32 RA0z, (0 * 64)(%rsi); + vmovdqu32 RA1z, (1 * 64)(%rsi); + vmovdqu32 RA2z, (2 * 64)(%rsi); + vmovdqu32 RA3z, (3 * 64)(%rsi); + vmovdqu32 RB0z, (4 * 64)(%rsi); + vmovdqu32 RB1z, (5 * 64)(%rsi); + vmovdqu32 RB2z, (6 * 64)(%rsi); + vmovdqu32 RB3z, (7 * 64)(%rsi); + + xorl %eax, %eax; + vzeroall; + + ret_spec_stop; + CFI_ENDPROC(); +ELF(.size FUNC_NAME(crypt_blk32),.-FUNC_NAME(crypt_blk32);) + +.align 16 +.globl FUNC_NAME(ctr_enc_blk32) +ELF(.type FUNC_NAME(ctr_enc_blk32),@function;) +FUNC_NAME(ctr_enc_blk32): + /* input: + * %rdi: ctx, CTX + * %rsi: dst (32 blocks) + * %rdx: src (32 blocks) + * %rcx: iv (big endian, 128bit) + */ + CFI_STARTPROC(); + spec_stop_avx512; + + cmpb $(0x100 - 32), 15(%rcx); + jbe .Lctr_byteadd32; + + vbroadcasti64x2 .Lbswap128_mask rRIP, RTMP0z; + vmovdqa32 .Lcounter0123_lo rRIP, RTMP1z; + vbroadcasti64x2 .Lcounter4444_lo rRIP, RTMP2z; + vbroadcasti64x2 .Lcounter8888_lo rRIP, RTMP3z; + vbroadcasti64x2 .Lcounter16161616_lo rRIP, RTMP4z; + + /* load IV and byteswap */ + movq 8(%rcx), %r11; + bswapq %r11; + vbroadcasti64x2 (%rcx), RB3z; + vpshufb RTMP0z, RB3z, RB3z; + + /* check need for handling 64-bit overflow and carry */ + cmpq $(0xffffffffffffffff - 32), %r11; + ja .Lhandle_ctr_carry_blk32; + + /* construct IVs */ + vpaddq RTMP1z, RB3z, RA0z; /* +0:+1:+2:+3 */ + vpaddq RTMP2z, RA0z, RA1z; /* +4:+5:+6:+7 */ + vpaddq RTMP3z, RA0z, RA2z; /* +8:+9:+10:+11 */ + vpaddq RTMP3z, RA1z, RA3z; /* +12:+13:+14:+15 */ + vpaddq RTMP4z, RA0z, RB0z; /* +16... */ + vpaddq RTMP4z, RA1z, RB1z; /* +20... */ + vpaddq RTMP4z, RA2z, RB2z; /* +24... */ + vpaddq RTMP4z, RA3z, RB3z; /* +28... */ + + /* Update counter */ + leaq 32(%r11), %r11; + bswapq %r11; + movq %r11, 8(%rcx); + + jmp .Lctr_carry_done_blk32; + +.Lhandle_ctr_carry_blk32: + vbroadcasti64x2 .Lcounter1111_hi rRIP, RNOTz; + + /* construct IVs */ + add_le128(RA0z, RB3z, RTMP1z, RNOTz); /* +0:+1:+2:+3 */ + add_le128(RA1z, RA0z, RTMP2z, RNOTz); /* +4:+5:+6:+7 */ + add_le128(RA2z, RA0z, RTMP3z, RNOTz); /* +8:+9:+10:+11 */ + add_le128(RA3z, RA1z, RTMP3z, RNOTz); /* +12:+13:+14:+15 */ + add_le128(RB0z, RA0z, RTMP4z, RNOTz); /* +16... */ + add_le128(RB1z, RA1z, RTMP4z, RNOTz); /* +20... */ + add_le128(RB2z, RA2z, RTMP4z, RNOTz); /* +24... */ + add_le128(RB3z, RA3z, RTMP4z, RNOTz); /* +28... */ + + /* Update counter */ + addq $32, %r11; + movq (%rcx), %r10; + bswapq %r10; + adcq $0, %r10; + bswapq %r11; + bswapq %r10; + movq %r11, 8(%rcx); + movq %r10, (%rcx); + +.align 16 +.Lctr_carry_done_blk32: + /* Byte-swap IVs. */ + vpshufb RTMP0z, RA0z, RA0z; + vpshufb RTMP0z, RA1z, RA1z; + vpshufb RTMP0z, RA2z, RA2z; + vpshufb RTMP0z, RA3z, RA3z; + vpshufb RTMP0z, RB0z, RB0z; + vpshufb RTMP0z, RB1z, RB1z; + vpshufb RTMP0z, RB2z, RB2z; + vpshufb RTMP0z, RB3z, RB3z; + +.align 16 +.Lload_ctr_done32: + call SM4_CRYPT_BLK32; + + vpxord (0 * 64)(%rdx), RA0z, RA0z; + vpxord (1 * 64)(%rdx), RA1z, RA1z; + vpxord (2 * 64)(%rdx), RA2z, RA2z; + vpxord (3 * 64)(%rdx), RA3z, RA3z; + vpxord (4 * 64)(%rdx), RB0z, RB0z; + vpxord (5 * 64)(%rdx), RB1z, RB1z; + vpxord (6 * 64)(%rdx), RB2z, RB2z; + vpxord (7 * 64)(%rdx), RB3z, RB3z; + + vmovdqu32 RA0z, (0 * 64)(%rsi); + vmovdqu32 RA1z, (1 * 64)(%rsi); + vmovdqu32 RA2z, (2 * 64)(%rsi); + vmovdqu32 RA3z, (3 * 64)(%rsi); + vmovdqu32 RB0z, (4 * 64)(%rsi); + vmovdqu32 RB1z, (5 * 64)(%rsi); + vmovdqu32 RB2z, (6 * 64)(%rsi); + vmovdqu32 RB3z, (7 * 64)(%rsi); + + vzeroall; + kxorq %k1, %k1, %k1; + + ret_spec_stop; + +.align 16 +.Lctr_byteadd_full_ctr_carry32: + movq 8(%rcx), %r11; + movq (%rcx), %r10; + bswapq %r11; + bswapq %r10; + addq $32, %r11; + adcq $0, %r10; + bswapq %r11; + bswapq %r10; + movq %r11, 8(%rcx); + movq %r10, (%rcx); + jmp .Lctr_byteadd_zmm32; +.align 16 +.Lctr_byteadd32: + vbroadcasti64x2 (%rcx), RA3z; + je .Lctr_byteadd_full_ctr_carry32; + addb $32, 15(%rcx); +.Lctr_byteadd_zmm32: + vbroadcasti64x2 .Lbige_addb_16 rRIP, RB3z; + vpaddb RB3z, RA3z, RB3z; + vpaddb .Lbige_addb_0_1 rRIP, RA3z, RA0z; + vpaddb .Lbige_addb_4_5 rRIP, RA3z, RA1z; + vpaddb .Lbige_addb_8_9 rRIP, RA3z, RA2z; + vpaddb .Lbige_addb_12_13 rRIP, RA3z, RA3z; + vpaddb .Lbige_addb_0_1 rRIP, RB3z, RB0z; + vpaddb .Lbige_addb_4_5 rRIP, RB3z, RB1z; + vpaddb .Lbige_addb_8_9 rRIP, RB3z, RB2z; + vpaddb .Lbige_addb_12_13 rRIP, RB3z, RB3z; + + jmp .Lload_ctr_done32; + CFI_ENDPROC(); +ELF(.size FUNC_NAME(ctr_enc_blk32),.-FUNC_NAME(ctr_enc_blk32);) + +.align 16 +.globl FUNC_NAME(cbc_dec_blk32) +ELF(.type FUNC_NAME(cbc_dec_blk32),@function;) +FUNC_NAME(cbc_dec_blk32): + /* input: + * %rdi: ctx, CTX + * %rsi: dst (32 blocks) + * %rdx: src (32 blocks) + * %rcx: iv + */ + CFI_STARTPROC(); + spec_stop_avx512; + + vmovdqu32 (0 * 64)(%rdx), RA0z; + vmovdqu32 (1 * 64)(%rdx), RA1z; + vmovdqu32 (2 * 64)(%rdx), RA2z; + vmovdqu32 (3 * 64)(%rdx), RA3z; + vmovdqu32 (4 * 64)(%rdx), RB0z; + vmovdqu32 (5 * 64)(%rdx), RB1z; + vmovdqu32 (6 * 64)(%rdx), RB2z; + vmovdqu32 (7 * 64)(%rdx), RB3z; + + call SM4_CRYPT_BLK32; + + vmovdqu (%rcx), RNOTx; + vinserti64x2 $1, (0 * 16)(%rdx), RNOT, RNOT; + vinserti64x4 $1, (1 * 16)(%rdx), RNOTz, RNOTz; + vpxord RNOTz, RA0z, RA0z; + vpxord (0 * 64 + 48)(%rdx), RA1z, RA1z; + vpxord (1 * 64 + 48)(%rdx), RA2z, RA2z; + vpxord (2 * 64 + 48)(%rdx), RA3z, RA3z; + vpxord (3 * 64 + 48)(%rdx), RB0z, RB0z; + vpxord (4 * 64 + 48)(%rdx), RB1z, RB1z; + vpxord (5 * 64 + 48)(%rdx), RB2z, RB2z; + vpxord (6 * 64 + 48)(%rdx), RB3z, RB3z; + vmovdqu (7 * 64 + 48)(%rdx), RNOTx; + vmovdqu RNOTx, (%rcx); /* store new IV */ + + vmovdqu32 RA0z, (0 * 64)(%rsi); + vmovdqu32 RA1z, (1 * 64)(%rsi); + vmovdqu32 RA2z, (2 * 64)(%rsi); + vmovdqu32 RA3z, (3 * 64)(%rsi); + vmovdqu32 RB0z, (4 * 64)(%rsi); + vmovdqu32 RB1z, (5 * 64)(%rsi); + vmovdqu32 RB2z, (6 * 64)(%rsi); + vmovdqu32 RB3z, (7 * 64)(%rsi); + + vzeroall; + + ret_spec_stop; + CFI_ENDPROC(); +ELF(.size FUNC_NAME(cbc_dec_blk32),.-FUNC_NAME(cbc_dec_blk32);) + +.align 16 +.globl FUNC_NAME(cfb_dec_blk32) +ELF(.type FUNC_NAME(cfb_dec_blk32),@function;) +FUNC_NAME(cfb_dec_blk32): + /* input: + * %rdi: ctx, CTX + * %rsi: dst (32 blocks) + * %rdx: src (32 blocks) + * %rcx: iv + */ + CFI_STARTPROC(); + spec_stop_avx512; + + /* Load input */ + vmovdqu (%rcx), RA0x; + vinserti64x2 $1, (%rdx), RA0, RA0; + vinserti64x4 $1, 16(%rdx), RA0z, RA0z; + vmovdqu32 (0 * 64 + 48)(%rdx), RA1z; + vmovdqu32 (1 * 64 + 48)(%rdx), RA2z; + vmovdqu32 (2 * 64 + 48)(%rdx), RA3z; + vmovdqu32 (3 * 64 + 48)(%rdx), RB0z; + vmovdqu32 (4 * 64 + 48)(%rdx), RB1z; + vmovdqu32 (5 * 64 + 48)(%rdx), RB2z; + vmovdqu32 (6 * 64 + 48)(%rdx), RB3z; + + /* Update IV */ + vmovdqu (7 * 64 + 48)(%rdx), RNOTx; + vmovdqu RNOTx, (%rcx); + + call SM4_CRYPT_BLK32; + + vpxord (0 * 64)(%rdx), RA0z, RA0z; + vpxord (1 * 64)(%rdx), RA1z, RA1z; + vpxord (2 * 64)(%rdx), RA2z, RA2z; + vpxord (3 * 64)(%rdx), RA3z, RA3z; + vpxord (4 * 64)(%rdx), RB0z, RB0z; + vpxord (5 * 64)(%rdx), RB1z, RB1z; + vpxord (6 * 64)(%rdx), RB2z, RB2z; + vpxord (7 * 64)(%rdx), RB3z, RB3z; + + vmovdqu32 RA0z, (0 * 64)(%rsi); + vmovdqu32 RA1z, (1 * 64)(%rsi); + vmovdqu32 RA2z, (2 * 64)(%rsi); + vmovdqu32 RA3z, (3 * 64)(%rsi); + vmovdqu32 RB0z, (4 * 64)(%rsi); + vmovdqu32 RB1z, (5 * 64)(%rsi); + vmovdqu32 RB2z, (6 * 64)(%rsi); + vmovdqu32 RB3z, (7 * 64)(%rsi); + + vzeroall; + + ret_spec_stop; + CFI_ENDPROC(); +ELF(.size FUNC_NAME(cfb_dec_blk32),.-FUNC_NAME(cfb_dec_blk32);) + +.align 16 +.globl FUNC_NAME(ocb_enc_blk32) +ELF(.type FUNC_NAME(ocb_enc_blk32),@function;) +FUNC_NAME(ocb_enc_blk32): + /* input: + * %rdi: ctx, CTX + * %rsi: dst (32 blocks) + * %rdx: src (32 blocks) + * %rcx: offset + * %r8 : checksum + * %r9 : L pointers (void *L[32]) + */ + CFI_STARTPROC(); + spec_stop_avx512; + + subq $(5 * 8), %rsp; + CFI_ADJUST_CFA_OFFSET(5 * 8); + + movq %r12, (0 * 8)(%rsp); + movq %r13, (1 * 8)(%rsp); + movq %r14, (2 * 8)(%rsp); + movq %r15, (3 * 8)(%rsp); + movq %rbx, (4 * 8)(%rsp); + CFI_REL_OFFSET(%r12, 0 * 8); + CFI_REL_OFFSET(%r13, 1 * 8); + CFI_REL_OFFSET(%r14, 2 * 8); + CFI_REL_OFFSET(%r15, 3 * 8); + CFI_REL_OFFSET(%rbx, 4 * 8); + + vmovdqu (%rcx), RTMP0x; + + /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */ + /* Checksum_i = Checksum_{i-1} xor P_i */ + /* C_i = Offset_i xor ENCIPHER(K, P_i xor Offset_i) */ + +#define OCB_INPUT(n, l0reg, l1reg, l2reg, l3reg, zreg, zplain) \ + vmovdqu32 (n * 64)(%rdx), zplain; \ + vpxor (l0reg), RTMP0x, RNOTx; \ + vpxor (l1reg), RNOTx, RTMP0x; \ + vinserti64x2 $1, RTMP0x, RNOT, RNOT; \ + vpxor (l2reg), RTMP0x, RTMP0x; \ + vinserti64x2 $2, RTMP0x, RNOTz, RNOTz; \ + vpxor (l3reg), RTMP0x, RTMP0x; \ + vinserti64x2 $3, RTMP0x, RNOTz, RNOTz; \ + vpxord zplain, RNOTz, zreg; \ + vmovdqu32 RNOTz, (n * 64)(%rsi); + +#define OCB_LOAD_PTRS(n) \ + movq ((n * 4 * 8) + (0 * 8))(%r9), %r10; \ + movq ((n * 4 * 8) + (1 * 8))(%r9), %r11; \ + movq ((n * 4 * 8) + (2 * 8))(%r9), %r12; \ + movq ((n * 4 * 8) + (3 * 8))(%r9), %r13; \ + movq ((n * 4 * 8) + (4 * 8))(%r9), %r14; \ + movq ((n * 4 * 8) + (5 * 8))(%r9), %r15; \ + movq ((n * 4 * 8) + (6 * 8))(%r9), %rax; \ + movq ((n * 4 * 8) + (7 * 8))(%r9), %rbx; + + OCB_LOAD_PTRS(0); + OCB_INPUT(0, %r10, %r11, %r12, %r13, RA0z, RTMP1z); + OCB_INPUT(1, %r14, %r15, %rax, %rbx, RA1z, RTMP2z); + OCB_LOAD_PTRS(2); + OCB_INPUT(2, %r10, %r11, %r12, %r13, RA2z, RTMP3z); + vpternlogd $0x96, RTMP1z, RTMP2z, RTMP3z; + OCB_INPUT(3, %r14, %r15, %rax, %rbx, RA3z, RTMP4z); + OCB_LOAD_PTRS(4); + OCB_INPUT(4, %r10, %r11, %r12, %r13, RB0z, RX0z); + OCB_INPUT(5, %r14, %r15, %rax, %rbx, RB1z, RX1z); + vpternlogd $0x96, RTMP4z, RX0z, RX1z; + OCB_LOAD_PTRS(6); + OCB_INPUT(6, %r10, %r11, %r12, %r13, RB2z, RTMP4z); + OCB_INPUT(7, %r14, %r15, %rax, %rbx, RB3z, RX0z); +#undef OCB_LOAD_PTRS +#undef OCB_INPUT + + vpternlogd $0x96, RTMP3z, RTMP4z, RX0z; + vpxord RX1z, RX0z, RNOTz; + vextracti64x4 $1, RNOTz, RTMP1; + vpxor RTMP1, RNOT, RNOT; + vextracti128 $1, RNOT, RTMP1x; + vpternlogd $0x96, (%r8), RTMP1x, RNOTx; + + movq (0 * 8)(%rsp), %r12; + movq (1 * 8)(%rsp), %r13; + movq (2 * 8)(%rsp), %r14; + movq (3 * 8)(%rsp), %r15; + movq (4 * 8)(%rsp), %rbx; + CFI_RESTORE(%r12); + CFI_RESTORE(%r13); + CFI_RESTORE(%r14); + CFI_RESTORE(%r15); + CFI_RESTORE(%rbx); + + vmovdqu RTMP0x, (%rcx); + vmovdqu RNOTx, (%r8); + + call SM4_CRYPT_BLK32; + + addq $(5 * 8), %rsp; + CFI_ADJUST_CFA_OFFSET(-5 * 8); + + vpxord (0 * 64)(%rsi), RA0z, RA0z; + vpxord (1 * 64)(%rsi), RA1z, RA1z; + vpxord (2 * 64)(%rsi), RA2z, RA2z; + vpxord (3 * 64)(%rsi), RA3z, RA3z; + vpxord (4 * 64)(%rsi), RB0z, RB0z; + vpxord (5 * 64)(%rsi), RB1z, RB1z; + vpxord (6 * 64)(%rsi), RB2z, RB2z; + vpxord (7 * 64)(%rsi), RB3z, RB3z; + + vmovdqu32 RA0z, (0 * 64)(%rsi); + vmovdqu32 RA1z, (1 * 64)(%rsi); + vmovdqu32 RA2z, (2 * 64)(%rsi); + vmovdqu32 RA3z, (3 * 64)(%rsi); + vmovdqu32 RB0z, (4 * 64)(%rsi); + vmovdqu32 RB1z, (5 * 64)(%rsi); + vmovdqu32 RB2z, (6 * 64)(%rsi); + vmovdqu32 RB3z, (7 * 64)(%rsi); + + vzeroall; + + ret_spec_stop; + CFI_ENDPROC(); +ELF(.size FUNC_NAME(ocb_enc_blk32),.-FUNC_NAME(ocb_enc_blk32);) + +.align 16 +.globl FUNC_NAME(ocb_dec_blk32) +ELF(.type FUNC_NAME(ocb_dec_blk32),@function;) +FUNC_NAME(ocb_dec_blk32): + /* input: + * %rdi: ctx, CTX + * %rsi: dst (32 blocks) + * %rdx: src (32 blocks) + * %rcx: offset + * %r8 : checksum + * %r9 : L pointers (void *L[32]) + */ + CFI_STARTPROC(); + spec_stop_avx512; + + subq $(5 * 8), %rsp; + CFI_ADJUST_CFA_OFFSET(5 * 8); + + movq %r12, (0 * 8)(%rsp); + movq %r13, (1 * 8)(%rsp); + movq %r14, (2 * 8)(%rsp); + movq %r15, (3 * 8)(%rsp); + movq %rbx, (4 * 8)(%rsp); + CFI_REL_OFFSET(%r12, 0 * 8); + CFI_REL_OFFSET(%r13, 1 * 8); + CFI_REL_OFFSET(%r14, 2 * 8); + CFI_REL_OFFSET(%r15, 3 * 8); + CFI_REL_OFFSET(%rbx, 4 * 8); + + vmovdqu (%rcx), RTMP0x; + + /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */ + /* C_i = Offset_i xor DECIPHER(K, P_i xor Offset_i) */ + +#define OCB_INPUT(n, l0reg, l1reg, l2reg, l3reg, zreg) \ + vmovdqu32 (n * 64)(%rdx), RTMP1z; \ + vpxor (l0reg), RTMP0x, RNOTx; \ + vpxor (l1reg), RNOTx, RTMP0x; \ + vinserti64x2 $1, RTMP0x, RNOT, RNOT; \ + vpxor (l2reg), RTMP0x, RTMP0x; \ + vinserti64x2 $2, RTMP0x, RNOTz, RNOTz; \ + vpxor (l3reg), RTMP0x, RTMP0x; \ + vinserti64x2 $3, RTMP0x, RNOTz, RNOTz; \ + vpxord RTMP1z, RNOTz, zreg; \ + vmovdqu32 RNOTz, (n * 64)(%rsi); + +#define OCB_LOAD_PTRS(n) \ + movq ((n * 4 * 8) + (0 * 8))(%r9), %r10; \ + movq ((n * 4 * 8) + (1 * 8))(%r9), %r11; \ + movq ((n * 4 * 8) + (2 * 8))(%r9), %r12; \ + movq ((n * 4 * 8) + (3 * 8))(%r9), %r13; \ + movq ((n * 4 * 8) + (4 * 8))(%r9), %r14; \ + movq ((n * 4 * 8) + (5 * 8))(%r9), %r15; \ + movq ((n * 4 * 8) + (6 * 8))(%r9), %rax; \ + movq ((n * 4 * 8) + (7 * 8))(%r9), %rbx; + + OCB_LOAD_PTRS(0); + OCB_INPUT(0, %r10, %r11, %r12, %r13, RA0z); + OCB_INPUT(1, %r14, %r15, %rax, %rbx, RA1z); + OCB_LOAD_PTRS(2); + OCB_INPUT(2, %r10, %r11, %r12, %r13, RA2z); + OCB_INPUT(3, %r14, %r15, %rax, %rbx, RA3z); + OCB_LOAD_PTRS(4); + OCB_INPUT(4, %r10, %r11, %r12, %r13, RB0z); + OCB_INPUT(5, %r14, %r15, %rax, %rbx, RB1z); + OCB_LOAD_PTRS(6); + OCB_INPUT(6, %r10, %r11, %r12, %r13, RB2z); + OCB_INPUT(7, %r14, %r15, %rax, %rbx, RB3z); +#undef OCB_LOAD_PTRS +#undef OCB_INPUT + + movq (0 * 8)(%rsp), %r12; + movq (1 * 8)(%rsp), %r13; + movq (2 * 8)(%rsp), %r14; + movq (3 * 8)(%rsp), %r15; + movq (4 * 8)(%rsp), %rbx; + CFI_RESTORE(%r12); + CFI_RESTORE(%r13); + CFI_RESTORE(%r14); + CFI_RESTORE(%r15); + CFI_RESTORE(%rbx); + + vmovdqu RTMP0x, (%rcx); + + call SM4_CRYPT_BLK32; + + addq $(5 * 8), %rsp; + CFI_ADJUST_CFA_OFFSET(-5 * 8); + + vpxord (0 * 64)(%rsi), RA0z, RA0z; + vpxord (1 * 64)(%rsi), RA1z, RA1z; + vpxord (2 * 64)(%rsi), RA2z, RA2z; + vpxord (3 * 64)(%rsi), RA3z, RA3z; + vpxord (4 * 64)(%rsi), RB0z, RB0z; + vpxord (5 * 64)(%rsi), RB1z, RB1z; + vpxord (6 * 64)(%rsi), RB2z, RB2z; + vpxord (7 * 64)(%rsi), RB3z, RB3z; + + vmovdqu32 RA0z, (0 * 64)(%rsi); + vmovdqu32 RA1z, (1 * 64)(%rsi); + vmovdqu32 RA2z, (2 * 64)(%rsi); + vmovdqu32 RA3z, (3 * 64)(%rsi); + vmovdqu32 RB0z, (4 * 64)(%rsi); + vmovdqu32 RB1z, (5 * 64)(%rsi); + vmovdqu32 RB2z, (6 * 64)(%rsi); + vmovdqu32 RB3z, (7 * 64)(%rsi); + + /* Checksum_i = Checksum_{i-1} xor C_i */ + vpternlogd $0x96, RA0z, RA1z, RA2z; + vpternlogd $0x96, RA3z, RB0z, RB1z; + vpternlogd $0x96, RB2z, RB3z, RA2z; + vpxord RA2z, RB1z, RTMP1z; + + vextracti64x4 $1, RTMP1z, RNOT; + vpxor RNOT, RTMP1, RTMP1; + vextracti128 $1, RTMP1, RNOTx; + vpternlogd $0x96, (%r8), RNOTx, RTMP1x; + vmovdqu RTMP1x, (%r8); + + vzeroall; + + ret_spec_stop; + CFI_ENDPROC(); +ELF(.size FUNC_NAME(ocb_dec_blk32),.-FUNC_NAME(ocb_dec_blk32);) + +#endif /* GCRY_SM4_AVX512_AMD64_H */ diff --git a/cipher/sm4-gfni-avx512-amd64.S b/cipher/sm4-gfni-avx512-amd64.S index 91f6e80b..8bc8bd81 100644 --- a/cipher/sm4-gfni-avx512-amd64.S +++ b/cipher/sm4-gfni-avx512-amd64.S @@ -120,7 +120,7 @@ SECTION_RODATA .byte 0x19, 0x8b, 0x6c, 0x1e, 0x51, 0x8e, 0x2d, 0xd7 .byte 0x19, 0x8b, 0x6c, 0x1e, 0x51, 0x8e, 0x2d, 0xd7 -/* For CTR-mode IV byteswap */ +/* For output IV byteswap */ .Lbswap128_mask: .byte 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 @@ -128,53 +128,6 @@ SECTION_RODATA .Lbswap32_mask: .byte 3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12 -.Lcounter2222_lo: - .quad 2, 0 -.Lcounter4444_lo: - .quad 4, 0 -.Lcounter8888_lo: - .quad 8, 0 -.Lcounter16161616_lo: - .quad 16, 0 -.Lcounter1111_hi: - .quad 0, 1 - -.align 64 -.Lcounter0123_lo: - .quad 0, 0 - .quad 1, 0 - .quad 2, 0 - .quad 3, 0 - -/* CTR byte addition constants */ -.align 64 -.Lbige_addb_0_1: - .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 -.Lbige_addb_2_3: - .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2 - .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3 -.Lbige_addb_4_5: - .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4 - .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5 -.Lbige_addb_6_7: - .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6 - .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7 -.Lbige_addb_8_9: - .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8 - .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9 -.Lbige_addb_10_11: - .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10 - .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11 -.Lbige_addb_12_13: - .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12 - .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13 -.Lbige_addb_14_15: - .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14 - .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15 -.Lbige_addb_16: - .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16 - .text .align 16 @@ -1315,547 +1268,9 @@ __sm4_gfni_crypt_blk32: CFI_ENDPROC(); ELF(.size __sm4_gfni_crypt_blk32,.-__sm4_gfni_crypt_blk32;) -.align 16 -.globl _gcry_sm4_gfni_avx512_crypt_blk32 -ELF(.type _gcry_sm4_gfni_avx512_crypt_blk32,@function;) -_gcry_sm4_gfni_avx512_crypt_blk32: - /* input: - * %rdi: ctx, CTX - * %rsi: dst (32 blocks) - * %rdx: src (32 blocks) - */ - CFI_STARTPROC(); - spec_stop_avx512; - - /* Load input */ - vmovdqu32 (0 * 64)(%rdx), RA0z; - vmovdqu32 (1 * 64)(%rdx), RA1z; - vmovdqu32 (2 * 64)(%rdx), RA2z; - vmovdqu32 (3 * 64)(%rdx), RA3z; - vmovdqu32 (4 * 64)(%rdx), RB0z; - vmovdqu32 (5 * 64)(%rdx), RB1z; - vmovdqu32 (6 * 64)(%rdx), RB2z; - vmovdqu32 (7 * 64)(%rdx), RB3z; - - call __sm4_gfni_crypt_blk32; - - vmovdqu32 RA0z, (0 * 64)(%rsi); - vmovdqu32 RA1z, (1 * 64)(%rsi); - vmovdqu32 RA2z, (2 * 64)(%rsi); - vmovdqu32 RA3z, (3 * 64)(%rsi); - vmovdqu32 RB0z, (4 * 64)(%rsi); - vmovdqu32 RB1z, (5 * 64)(%rsi); - vmovdqu32 RB2z, (6 * 64)(%rsi); - vmovdqu32 RB3z, (7 * 64)(%rsi); - - xorl %eax, %eax; - vzeroall; - - ret_spec_stop; - CFI_ENDPROC(); -ELF(.size _gcry_sm4_gfni_avx512_crypt_blk32,.-_gcry_sm4_gfni_avx512_crypt_blk32;) - -.align 16 -.globl _gcry_sm4_gfni_avx512_ctr_enc_blk32 -ELF(.type _gcry_sm4_gfni_avx512_ctr_enc_blk32,@function;) -_gcry_sm4_gfni_avx512_ctr_enc_blk32: - /* input: - * %rdi: ctx, CTX - * %rsi: dst (32 blocks) - * %rdx: src (32 blocks) - * %rcx: iv (big endian, 128bit) - */ - CFI_STARTPROC(); - spec_stop_avx512; - - cmpb $(0x100 - 32), 15(%rcx); - jbe .Lctr_byteadd32; - - vbroadcasti64x2 .Lbswap128_mask rRIP, RTMP0z; - vmovdqa32 .Lcounter0123_lo rRIP, RTMP1z; - vbroadcasti64x2 .Lcounter4444_lo rRIP, RTMP2z; - vbroadcasti64x2 .Lcounter8888_lo rRIP, RTMP3z; - vbroadcasti64x2 .Lcounter16161616_lo rRIP, RTMP4z; - - /* load IV and byteswap */ - movq 8(%rcx), %r11; - bswapq %r11; - vbroadcasti64x2 (%rcx), RB3z; - vpshufb RTMP0z, RB3z, RB3z; - - /* check need for handling 64-bit overflow and carry */ - cmpq $(0xffffffffffffffff - 32), %r11; - ja .Lhandle_ctr_carry_blk32; - - /* construct IVs */ - vpaddq RTMP1z, RB3z, RA0z; /* +0:+1:+2:+3 */ - vpaddq RTMP2z, RA0z, RA1z; /* +4:+5:+6:+7 */ - vpaddq RTMP3z, RA0z, RA2z; /* +8:+9:+10:+11 */ - vpaddq RTMP3z, RA1z, RA3z; /* +12:+13:+14:+15 */ - vpaddq RTMP4z, RA0z, RB0z; /* +16... */ - vpaddq RTMP4z, RA1z, RB1z; /* +20... */ - vpaddq RTMP4z, RA2z, RB2z; /* +24... */ - vpaddq RTMP4z, RA3z, RB3z; /* +28... */ - - /* Update counter */ - leaq 32(%r11), %r11; - bswapq %r11; - movq %r11, 8(%rcx); - - jmp .Lctr_carry_done_blk32; - -.Lhandle_ctr_carry_blk32: - vbroadcasti64x2 .Lcounter1111_hi rRIP, RNOTz; - - /* construct IVs */ - add_le128(RA0z, RB3z, RTMP1z, RNOTz); /* +0:+1:+2:+3 */ - add_le128(RA1z, RA0z, RTMP2z, RNOTz); /* +4:+5:+6:+7 */ - add_le128(RA2z, RA0z, RTMP3z, RNOTz); /* +8:+9:+10:+11 */ - add_le128(RA3z, RA1z, RTMP3z, RNOTz); /* +12:+13:+14:+15 */ - add_le128(RB0z, RA0z, RTMP4z, RNOTz); /* +16... */ - add_le128(RB1z, RA1z, RTMP4z, RNOTz); /* +20... */ - add_le128(RB2z, RA2z, RTMP4z, RNOTz); /* +24... */ - add_le128(RB3z, RA3z, RTMP4z, RNOTz); /* +28... */ - - /* Update counter */ - addq $32, %r11; - movq (%rcx), %r10; - bswapq %r10; - adcq $0, %r10; - bswapq %r11; - bswapq %r10; - movq %r11, 8(%rcx); - movq %r10, (%rcx); - -.align 16 -.Lctr_carry_done_blk32: - /* Byte-swap IVs. */ - vpshufb RTMP0z, RA0z, RA0z; - vpshufb RTMP0z, RA1z, RA1z; - vpshufb RTMP0z, RA2z, RA2z; - vpshufb RTMP0z, RA3z, RA3z; - vpshufb RTMP0z, RB0z, RB0z; - vpshufb RTMP0z, RB1z, RB1z; - vpshufb RTMP0z, RB2z, RB2z; - vpshufb RTMP0z, RB3z, RB3z; - -.align 16 -.Lload_ctr_done32: - call __sm4_gfni_crypt_blk32; - - vpxord (0 * 64)(%rdx), RA0z, RA0z; - vpxord (1 * 64)(%rdx), RA1z, RA1z; - vpxord (2 * 64)(%rdx), RA2z, RA2z; - vpxord (3 * 64)(%rdx), RA3z, RA3z; - vpxord (4 * 64)(%rdx), RB0z, RB0z; - vpxord (5 * 64)(%rdx), RB1z, RB1z; - vpxord (6 * 64)(%rdx), RB2z, RB2z; - vpxord (7 * 64)(%rdx), RB3z, RB3z; - - vmovdqu32 RA0z, (0 * 64)(%rsi); - vmovdqu32 RA1z, (1 * 64)(%rsi); - vmovdqu32 RA2z, (2 * 64)(%rsi); - vmovdqu32 RA3z, (3 * 64)(%rsi); - vmovdqu32 RB0z, (4 * 64)(%rsi); - vmovdqu32 RB1z, (5 * 64)(%rsi); - vmovdqu32 RB2z, (6 * 64)(%rsi); - vmovdqu32 RB3z, (7 * 64)(%rsi); - - vzeroall; - kxorq %k1, %k1, %k1; - - ret_spec_stop; - -.align 16 -.Lctr_byteadd_full_ctr_carry32: - movq 8(%rcx), %r11; - movq (%rcx), %r10; - bswapq %r11; - bswapq %r10; - addq $32, %r11; - adcq $0, %r10; - bswapq %r11; - bswapq %r10; - movq %r11, 8(%rcx); - movq %r10, (%rcx); - jmp .Lctr_byteadd_zmm32; -.align 16 -.Lctr_byteadd32: - vbroadcasti64x2 (%rcx), RA3z; - je .Lctr_byteadd_full_ctr_carry32; - addb $32, 15(%rcx); -.Lctr_byteadd_zmm32: - vbroadcasti64x2 .Lbige_addb_16 rRIP, RB3z; - vpaddb RB3z, RA3z, RB3z; - vpaddb .Lbige_addb_0_1 rRIP, RA3z, RA0z; - vpaddb .Lbige_addb_4_5 rRIP, RA3z, RA1z; - vpaddb .Lbige_addb_8_9 rRIP, RA3z, RA2z; - vpaddb .Lbige_addb_12_13 rRIP, RA3z, RA3z; - vpaddb .Lbige_addb_0_1 rRIP, RB3z, RB0z; - vpaddb .Lbige_addb_4_5 rRIP, RB3z, RB1z; - vpaddb .Lbige_addb_8_9 rRIP, RB3z, RB2z; - vpaddb .Lbige_addb_12_13 rRIP, RB3z, RB3z; - - jmp .Lload_ctr_done32; - CFI_ENDPROC(); -ELF(.size _gcry_sm4_gfni_avx512_ctr_enc_blk32,.-_gcry_sm4_gfni_avx512_ctr_enc_blk32;) - -.align 16 -.globl _gcry_sm4_gfni_avx512_cbc_dec_blk32 -ELF(.type _gcry_sm4_gfni_avx512_cbc_dec_blk32,@function;) -_gcry_sm4_gfni_avx512_cbc_dec_blk32: - /* input: - * %rdi: ctx, CTX - * %rsi: dst (32 blocks) - * %rdx: src (32 blocks) - * %rcx: iv - */ - CFI_STARTPROC(); - spec_stop_avx512; - - vmovdqu32 (0 * 64)(%rdx), RA0z; - vmovdqu32 (1 * 64)(%rdx), RA1z; - vmovdqu32 (2 * 64)(%rdx), RA2z; - vmovdqu32 (3 * 64)(%rdx), RA3z; - vmovdqu32 (4 * 64)(%rdx), RB0z; - vmovdqu32 (5 * 64)(%rdx), RB1z; - vmovdqu32 (6 * 64)(%rdx), RB2z; - vmovdqu32 (7 * 64)(%rdx), RB3z; - - call __sm4_gfni_crypt_blk32; - - vmovdqu (%rcx), RNOTx; - vinserti64x2 $1, (0 * 16)(%rdx), RNOT, RNOT; - vinserti64x4 $1, (1 * 16)(%rdx), RNOTz, RNOTz; - vpxord RNOTz, RA0z, RA0z; - vpxord (0 * 64 + 48)(%rdx), RA1z, RA1z; - vpxord (1 * 64 + 48)(%rdx), RA2z, RA2z; - vpxord (2 * 64 + 48)(%rdx), RA3z, RA3z; - vpxord (3 * 64 + 48)(%rdx), RB0z, RB0z; - vpxord (4 * 64 + 48)(%rdx), RB1z, RB1z; - vpxord (5 * 64 + 48)(%rdx), RB2z, RB2z; - vpxord (6 * 64 + 48)(%rdx), RB3z, RB3z; - vmovdqu (7 * 64 + 48)(%rdx), RNOTx; - vmovdqu RNOTx, (%rcx); /* store new IV */ - - vmovdqu32 RA0z, (0 * 64)(%rsi); - vmovdqu32 RA1z, (1 * 64)(%rsi); - vmovdqu32 RA2z, (2 * 64)(%rsi); - vmovdqu32 RA3z, (3 * 64)(%rsi); - vmovdqu32 RB0z, (4 * 64)(%rsi); - vmovdqu32 RB1z, (5 * 64)(%rsi); - vmovdqu32 RB2z, (6 * 64)(%rsi); - vmovdqu32 RB3z, (7 * 64)(%rsi); - - vzeroall; - - ret_spec_stop; - CFI_ENDPROC(); -ELF(.size _gcry_sm4_gfni_avx512_cbc_dec_blk32,.-_gcry_sm4_gfni_avx512_cbc_dec_blk32;) - -.align 16 -.globl _gcry_sm4_gfni_avx512_cfb_dec_blk32 -ELF(.type _gcry_sm4_gfni_avx512_cfb_dec_blk32,@function;) -_gcry_sm4_gfni_avx512_cfb_dec_blk32: - /* input: - * %rdi: ctx, CTX - * %rsi: dst (32 blocks) - * %rdx: src (32 blocks) - * %rcx: iv - */ - CFI_STARTPROC(); - spec_stop_avx512; - - /* Load input */ - vmovdqu (%rcx), RA0x; - vinserti64x2 $1, (%rdx), RA0, RA0; - vinserti64x4 $1, 16(%rdx), RA0z, RA0z; - vmovdqu32 (0 * 64 + 48)(%rdx), RA1z; - vmovdqu32 (1 * 64 + 48)(%rdx), RA2z; - vmovdqu32 (2 * 64 + 48)(%rdx), RA3z; - vmovdqu32 (3 * 64 + 48)(%rdx), RB0z; - vmovdqu32 (4 * 64 + 48)(%rdx), RB1z; - vmovdqu32 (5 * 64 + 48)(%rdx), RB2z; - vmovdqu32 (6 * 64 + 48)(%rdx), RB3z; - - /* Update IV */ - vmovdqu (7 * 64 + 48)(%rdx), RNOTx; - vmovdqu RNOTx, (%rcx); - - call __sm4_gfni_crypt_blk32; - - vpxord (0 * 64)(%rdx), RA0z, RA0z; - vpxord (1 * 64)(%rdx), RA1z, RA1z; - vpxord (2 * 64)(%rdx), RA2z, RA2z; - vpxord (3 * 64)(%rdx), RA3z, RA3z; - vpxord (4 * 64)(%rdx), RB0z, RB0z; - vpxord (5 * 64)(%rdx), RB1z, RB1z; - vpxord (6 * 64)(%rdx), RB2z, RB2z; - vpxord (7 * 64)(%rdx), RB3z, RB3z; - - vmovdqu32 RA0z, (0 * 64)(%rsi); - vmovdqu32 RA1z, (1 * 64)(%rsi); - vmovdqu32 RA2z, (2 * 64)(%rsi); - vmovdqu32 RA3z, (3 * 64)(%rsi); - vmovdqu32 RB0z, (4 * 64)(%rsi); - vmovdqu32 RB1z, (5 * 64)(%rsi); - vmovdqu32 RB2z, (6 * 64)(%rsi); - vmovdqu32 RB3z, (7 * 64)(%rsi); - - vzeroall; - - ret_spec_stop; - CFI_ENDPROC(); -ELF(.size _gcry_sm4_gfni_avx512_cfb_dec_blk32,.-_gcry_sm4_gfni_avx512_cfb_dec_blk32;) - -.align 16 -.globl _gcry_sm4_gfni_avx512_ocb_enc_blk32 -ELF(.type _gcry_sm4_gfni_avx512_ocb_enc_blk32,@function;) -_gcry_sm4_gfni_avx512_ocb_enc_blk32: - /* input: - * %rdi: ctx, CTX - * %rsi: dst (32 blocks) - * %rdx: src (32 blocks) - * %rcx: offset - * %r8 : checksum - * %r9 : L pointers (void *L[32]) - */ - CFI_STARTPROC(); - spec_stop_avx512; - - subq $(5 * 8), %rsp; - CFI_ADJUST_CFA_OFFSET(5 * 8); - - movq %r12, (0 * 8)(%rsp); - movq %r13, (1 * 8)(%rsp); - movq %r14, (2 * 8)(%rsp); - movq %r15, (3 * 8)(%rsp); - movq %rbx, (4 * 8)(%rsp); - CFI_REL_OFFSET(%r12, 0 * 8); - CFI_REL_OFFSET(%r13, 1 * 8); - CFI_REL_OFFSET(%r14, 2 * 8); - CFI_REL_OFFSET(%r15, 3 * 8); - CFI_REL_OFFSET(%rbx, 4 * 8); - - vmovdqu (%rcx), RTMP0x; - - /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */ - /* Checksum_i = Checksum_{i-1} xor P_i */ - /* C_i = Offset_i xor ENCIPHER(K, P_i xor Offset_i) */ - -#define OCB_INPUT(n, l0reg, l1reg, l2reg, l3reg, zreg, zplain) \ - vmovdqu32 (n * 64)(%rdx), zplain; \ - vpxor (l0reg), RTMP0x, RNOTx; \ - vpxor (l1reg), RNOTx, RTMP0x; \ - vinserti64x2 $1, RTMP0x, RNOT, RNOT; \ - vpxor (l2reg), RTMP0x, RTMP0x; \ - vinserti64x2 $2, RTMP0x, RNOTz, RNOTz; \ - vpxor (l3reg), RTMP0x, RTMP0x; \ - vinserti64x2 $3, RTMP0x, RNOTz, RNOTz; \ - vpxord zplain, RNOTz, zreg; \ - vmovdqu32 RNOTz, (n * 64)(%rsi); - -#define OCB_LOAD_PTRS(n) \ - movq ((n * 4 * 8) + (0 * 8))(%r9), %r10; \ - movq ((n * 4 * 8) + (1 * 8))(%r9), %r11; \ - movq ((n * 4 * 8) + (2 * 8))(%r9), %r12; \ - movq ((n * 4 * 8) + (3 * 8))(%r9), %r13; \ - movq ((n * 4 * 8) + (4 * 8))(%r9), %r14; \ - movq ((n * 4 * 8) + (5 * 8))(%r9), %r15; \ - movq ((n * 4 * 8) + (6 * 8))(%r9), %rax; \ - movq ((n * 4 * 8) + (7 * 8))(%r9), %rbx; - - OCB_LOAD_PTRS(0); - OCB_INPUT(0, %r10, %r11, %r12, %r13, RA0z, RTMP1z); - OCB_INPUT(1, %r14, %r15, %rax, %rbx, RA1z, RTMP2z); - OCB_LOAD_PTRS(2); - OCB_INPUT(2, %r10, %r11, %r12, %r13, RA2z, RTMP3z); - vpternlogd $0x96, RTMP1z, RTMP2z, RTMP3z; - OCB_INPUT(3, %r14, %r15, %rax, %rbx, RA3z, RTMP4z); - OCB_LOAD_PTRS(4); - OCB_INPUT(4, %r10, %r11, %r12, %r13, RB0z, RX0z); - OCB_INPUT(5, %r14, %r15, %rax, %rbx, RB1z, RX1z); - vpternlogd $0x96, RTMP4z, RX0z, RX1z; - OCB_LOAD_PTRS(6); - OCB_INPUT(6, %r10, %r11, %r12, %r13, RB2z, RTMP4z); - OCB_INPUT(7, %r14, %r15, %rax, %rbx, RB3z, RX0z); -#undef OCB_LOAD_PTRS -#undef OCB_INPUT - - vpternlogd $0x96, RTMP3z, RTMP4z, RX0z; - vpxord RX1z, RX0z, RNOTz; - vextracti64x4 $1, RNOTz, RTMP1; - vpxor RTMP1, RNOT, RNOT; - vextracti128 $1, RNOT, RTMP1x; - vpternlogd $0x96, (%r8), RTMP1x, RNOTx; - - movq (0 * 8)(%rsp), %r12; - movq (1 * 8)(%rsp), %r13; - movq (2 * 8)(%rsp), %r14; - movq (3 * 8)(%rsp), %r15; - movq (4 * 8)(%rsp), %rbx; - CFI_RESTORE(%r12); - CFI_RESTORE(%r13); - CFI_RESTORE(%r14); - CFI_RESTORE(%r15); - CFI_RESTORE(%rbx); - - vmovdqu RTMP0x, (%rcx); - vmovdqu RNOTx, (%r8); - - call __sm4_gfni_crypt_blk32; - - addq $(5 * 8), %rsp; - CFI_ADJUST_CFA_OFFSET(-5 * 8); - - vpxord (0 * 64)(%rsi), RA0z, RA0z; - vpxord (1 * 64)(%rsi), RA1z, RA1z; - vpxord (2 * 64)(%rsi), RA2z, RA2z; - vpxord (3 * 64)(%rsi), RA3z, RA3z; - vpxord (4 * 64)(%rsi), RB0z, RB0z; - vpxord (5 * 64)(%rsi), RB1z, RB1z; - vpxord (6 * 64)(%rsi), RB2z, RB2z; - vpxord (7 * 64)(%rsi), RB3z, RB3z; - - vmovdqu32 RA0z, (0 * 64)(%rsi); - vmovdqu32 RA1z, (1 * 64)(%rsi); - vmovdqu32 RA2z, (2 * 64)(%rsi); - vmovdqu32 RA3z, (3 * 64)(%rsi); - vmovdqu32 RB0z, (4 * 64)(%rsi); - vmovdqu32 RB1z, (5 * 64)(%rsi); - vmovdqu32 RB2z, (6 * 64)(%rsi); - vmovdqu32 RB3z, (7 * 64)(%rsi); - - vzeroall; - - ret_spec_stop; - CFI_ENDPROC(); -ELF(.size _gcry_sm4_gfni_avx512_ocb_enc_blk32,.-_gcry_sm4_gfni_avx512_ocb_enc_blk32;) - -.align 16 -.globl _gcry_sm4_gfni_avx512_ocb_dec_blk32 -ELF(.type _gcry_sm4_gfni_avx512_ocb_dec_blk32,@function;) -_gcry_sm4_gfni_avx512_ocb_dec_blk32: - /* input: - * %rdi: ctx, CTX - * %rsi: dst (32 blocks) - * %rdx: src (32 blocks) - * %rcx: offset - * %r8 : checksum - * %r9 : L pointers (void *L[32]) - */ - CFI_STARTPROC(); - spec_stop_avx512; - - subq $(5 * 8), %rsp; - CFI_ADJUST_CFA_OFFSET(5 * 8); - - movq %r12, (0 * 8)(%rsp); - movq %r13, (1 * 8)(%rsp); - movq %r14, (2 * 8)(%rsp); - movq %r15, (3 * 8)(%rsp); - movq %rbx, (4 * 8)(%rsp); - CFI_REL_OFFSET(%r12, 0 * 8); - CFI_REL_OFFSET(%r13, 1 * 8); - CFI_REL_OFFSET(%r14, 2 * 8); - CFI_REL_OFFSET(%r15, 3 * 8); - CFI_REL_OFFSET(%rbx, 4 * 8); - - vmovdqu (%rcx), RTMP0x; - - /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */ - /* C_i = Offset_i xor DECIPHER(K, P_i xor Offset_i) */ - -#define OCB_INPUT(n, l0reg, l1reg, l2reg, l3reg, zreg) \ - vmovdqu32 (n * 64)(%rdx), RTMP1z; \ - vpxor (l0reg), RTMP0x, RNOTx; \ - vpxor (l1reg), RNOTx, RTMP0x; \ - vinserti64x2 $1, RTMP0x, RNOT, RNOT; \ - vpxor (l2reg), RTMP0x, RTMP0x; \ - vinserti64x2 $2, RTMP0x, RNOTz, RNOTz; \ - vpxor (l3reg), RTMP0x, RTMP0x; \ - vinserti64x2 $3, RTMP0x, RNOTz, RNOTz; \ - vpxord RTMP1z, RNOTz, zreg; \ - vmovdqu32 RNOTz, (n * 64)(%rsi); - -#define OCB_LOAD_PTRS(n) \ - movq ((n * 4 * 8) + (0 * 8))(%r9), %r10; \ - movq ((n * 4 * 8) + (1 * 8))(%r9), %r11; \ - movq ((n * 4 * 8) + (2 * 8))(%r9), %r12; \ - movq ((n * 4 * 8) + (3 * 8))(%r9), %r13; \ - movq ((n * 4 * 8) + (4 * 8))(%r9), %r14; \ - movq ((n * 4 * 8) + (5 * 8))(%r9), %r15; \ - movq ((n * 4 * 8) + (6 * 8))(%r9), %rax; \ - movq ((n * 4 * 8) + (7 * 8))(%r9), %rbx; - - OCB_LOAD_PTRS(0); - OCB_INPUT(0, %r10, %r11, %r12, %r13, RA0z); - OCB_INPUT(1, %r14, %r15, %rax, %rbx, RA1z); - OCB_LOAD_PTRS(2); - OCB_INPUT(2, %r10, %r11, %r12, %r13, RA2z); - OCB_INPUT(3, %r14, %r15, %rax, %rbx, RA3z); - OCB_LOAD_PTRS(4); - OCB_INPUT(4, %r10, %r11, %r12, %r13, RB0z); - OCB_INPUT(5, %r14, %r15, %rax, %rbx, RB1z); - OCB_LOAD_PTRS(6); - OCB_INPUT(6, %r10, %r11, %r12, %r13, RB2z); - OCB_INPUT(7, %r14, %r15, %rax, %rbx, RB3z); -#undef OCB_LOAD_PTRS -#undef OCB_INPUT - - movq (0 * 8)(%rsp), %r12; - movq (1 * 8)(%rsp), %r13; - movq (2 * 8)(%rsp), %r14; - movq (3 * 8)(%rsp), %r15; - movq (4 * 8)(%rsp), %rbx; - CFI_RESTORE(%r12); - CFI_RESTORE(%r13); - CFI_RESTORE(%r14); - CFI_RESTORE(%r15); - CFI_RESTORE(%rbx); - - vmovdqu RTMP0x, (%rcx); - - call __sm4_gfni_crypt_blk32; - - addq $(5 * 8), %rsp; - CFI_ADJUST_CFA_OFFSET(-5 * 8); - - vpxord (0 * 64)(%rsi), RA0z, RA0z; - vpxord (1 * 64)(%rsi), RA1z, RA1z; - vpxord (2 * 64)(%rsi), RA2z, RA2z; - vpxord (3 * 64)(%rsi), RA3z, RA3z; - vpxord (4 * 64)(%rsi), RB0z, RB0z; - vpxord (5 * 64)(%rsi), RB1z, RB1z; - vpxord (6 * 64)(%rsi), RB2z, RB2z; - vpxord (7 * 64)(%rsi), RB3z, RB3z; - - vmovdqu32 RA0z, (0 * 64)(%rsi); - vmovdqu32 RA1z, (1 * 64)(%rsi); - vmovdqu32 RA2z, (2 * 64)(%rsi); - vmovdqu32 RA3z, (3 * 64)(%rsi); - vmovdqu32 RB0z, (4 * 64)(%rsi); - vmovdqu32 RB1z, (5 * 64)(%rsi); - vmovdqu32 RB2z, (6 * 64)(%rsi); - vmovdqu32 RB3z, (7 * 64)(%rsi); - - /* Checksum_i = Checksum_{i-1} xor C_i */ - vpternlogd $0x96, RA0z, RA1z, RA2z; - vpternlogd $0x96, RA3z, RB0z, RB1z; - vpternlogd $0x96, RB2z, RB3z, RA2z; - vpxord RA2z, RB1z, RTMP1z; - - vextracti64x4 $1, RTMP1z, RNOT; - vpxor RNOT, RTMP1, RTMP1; - vextracti128 $1, RTMP1, RNOTx; - vpternlogd $0x96, (%r8), RNOTx, RTMP1x; - vmovdqu RTMP1x, (%r8); - - vzeroall; - - ret_spec_stop; - CFI_ENDPROC(); -ELF(.size _gcry_sm4_gfni_avx512_ocb_dec_blk32,.-_gcry_sm4_gfni_avx512_ocb_dec_blk32;) +#define FUNC_NAME(func) _gcry_sm4_gfni_avx512_ ## func +#define SM4_CRYPT_BLK32 __sm4_gfni_crypt_blk32 +#include "sm4-avx512-amd64.h" #endif /*defined(ENABLE_GFNI_SUPPORT) && defined(ENABLE_AVX512_SUPPORT)*/ #endif /*__x86_64*/ diff --git a/cipher/sm4-intel-avx512-amd64.S b/cipher/sm4-intel-avx512-amd64.S new file mode 100644 index 00000000..a4963db0 --- /dev/null +++ b/cipher/sm4-intel-avx512-amd64.S @@ -0,0 +1,174 @@ +/* sm4-intel-avx512-amd64.S - Intel SM4 instructions AVX512 SM4 cipher + * + * Copyright (C) 2026 Jussi Kivilinna <[email protected]> + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#include <config.h> + +#ifdef __x86_64 +#if (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \ + defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS)) && \ + defined(ENABLE_AVX512_SUPPORT) && defined(HAVE_GCC_INLINE_ASM_SM4) + +#include "asm-common-amd64.h" + +/* vector registers */ +#define RA0 %ymm0 +#define RA1 %ymm1 +#define RA2 %ymm2 +#define RA3 %ymm3 +#define RA0x %xmm0 +#define RA1x %xmm1 +#define RA2x %xmm2 +#define RA3x %xmm3 +#define RA0z %zmm0 +#define RA1z %zmm1 +#define RA2z %zmm2 +#define RA3z %zmm3 + +#define RTMP0 %ymm4 +#define RTMP1 %ymm5 +#define RTMP2 %ymm6 +#define RTMP3 %ymm7 +#define RTMP4 %ymm8 +#define RTMP0x %xmm4 +#define RTMP1x %xmm5 +#define RTMP2x %xmm6 +#define RTMP3x %xmm7 +#define RTMP4x %xmm8 +#define RTMP0z %zmm4 +#define RTMP1z %zmm5 +#define RTMP2z %zmm6 +#define RTMP3z %zmm7 +#define RTMP4z %zmm8 + +#define RB0 %ymm9 +#define RB1 %ymm10 +#define RB2 %ymm11 +#define RB3 %ymm12 +#define RB0x %xmm9 +#define RB1x %xmm10 +#define RB2x %xmm11 +#define RB3x %xmm12 +#define RB0z %zmm9 +#define RB1z %zmm10 +#define RB2z %zmm11 +#define RB3z %zmm12 + +#define RX0 %ymm13 +#define RX1 %ymm14 +#define RX0x %xmm13 +#define RX1x %xmm14 +#define RX0z %zmm13 +#define RX1z %zmm14 + +#define RNOT %ymm15 +#define RNOTx %xmm15 +#define RNOTz %zmm15 + +SECTION_RODATA +.align 32 + +ELF(.type _sm4_intel_avx512_consts,@object) +_sm4_intel_avx512_consts: + +/* For output word byte-swap */ +.Lbswap128_mask: + .byte 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 + +/* For input word byte-swap */ +.Lbswap32_mask: + .byte 3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12 + +.text + +/********************************************************************** + 32-way SM4 with Intel SM4 instructions + **********************************************************************/ + +.align 16 +ELF(.type __sm4_intel_crypt_blk32,@function;) +__sm4_intel_crypt_blk32: + /* input: + * %rdi: round key array, CTX + * RA0z, RA1z, RA2z, RA3z, RB0z, RB1z, RB2z, RB3z: 32 parallel + * plaintext blocks + * output: + * RA0z, RA1z, RA2z, RA3z, RB0z, RB1z, RB2z, RB3z: 32 parallel + * ciphertext blocks + */ + CFI_STARTPROC(); + + vbroadcasti32x4 .Lbswap32_mask rRIP, RTMP0z; + vpshufb RTMP0z, RA0z, RA0z; + vpshufb RTMP0z, RA1z, RA1z; + vpshufb RTMP0z, RA2z, RA2z; + vpshufb RTMP0z, RA3z, RA3z; + vpshufb RTMP0z, RB0z, RB0z; + vpshufb RTMP0z, RB1z, RB1z; + vpshufb RTMP0z, RB2z, RB2z; + vpshufb RTMP0z, RB3z, RB3z; + +#define ROUND4(rkoff) \ + vbroadcasti32x4 (rkoff)(%rdi), RTMP1z; \ + vsm4rnds4 RTMP1z, RA0z, RA0z; \ + vsm4rnds4 RTMP1z, RA1z, RA1z; \ + vsm4rnds4 RTMP1z, RA2z, RA2z; \ + vsm4rnds4 RTMP1z, RA3z, RA3z; \ + vsm4rnds4 RTMP1z, RB0z, RB0z; \ + vsm4rnds4 RTMP1z, RB1z, RB1z; \ + vsm4rnds4 RTMP1z, RB2z, RB2z; \ + vsm4rnds4 RTMP1z, RB3z, RB3z; + + ROUND4(0 * 16); + ROUND4(1 * 16); + ROUND4(2 * 16); + ROUND4(3 * 16); + ROUND4(4 * 16); + ROUND4(5 * 16); + ROUND4(6 * 16); + ROUND4(7 * 16); + +#undef ROUND4 + + vbroadcasti32x4 .Lbswap128_mask rRIP, RTMP0z; + vpshufb RTMP0z, RA0z, RA0z; + vpshufb RTMP0z, RA1z, RA1z; + vpshufb RTMP0z, RA2z, RA2z; + vpshufb RTMP0z, RA3z, RA3z; + vpshufb RTMP0z, RB0z, RB0z; + vpshufb RTMP0z, RB1z, RB1z; + vpshufb RTMP0z, RB2z, RB2z; + vpshufb RTMP0z, RB3z, RB3z; + + ret_spec_stop; + CFI_ENDPROC(); +ELF(.size __sm4_intel_crypt_blk32,.-__sm4_intel_crypt_blk32;) + +#define add_le128(out, in, lo_counter, hi_counter1) \ + vpaddq lo_counter, in, out; \ + vpcmpuq $1, lo_counter, out, %k1; \ + kaddb %k1, %k1, %k1; \ + vpaddq hi_counter1, out, out{%k1}; + +#define FUNC_NAME(func) _gcry_sm4_intel_avx512_ ## func +#define SM4_CRYPT_BLK32 __sm4_intel_crypt_blk32 +#include "sm4-avx512-amd64.h" + +#endif /*defined(ENABLE_AVX512_SUPPORT) && defined(HAVE_GCC_INLINE_ASM_SM4)*/ +#endif /*__x86_64*/ diff --git a/cipher/sm4.c b/cipher/sm4.c index e397e452..37e1a6c3 100644 --- a/cipher/sm4.c +++ b/cipher/sm4.c @@ -84,12 +84,22 @@ # endif #endif +/* USE_INTEL_SM4_AVX512 indicates whether to compile with Intel SM4 + * instructions (VSM4RNDS4) based AVX512 code. */ +#undef USE_INTEL_SM4_AVX512 +#if defined(ENABLE_AVX512_SUPPORT) && defined(HAVE_GCC_INLINE_ASM_SM4) +# if defined(__x86_64__) && (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \ + defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS)) +# define USE_INTEL_SM4_AVX512 1 +# endif +#endif + /* Assembly implementations use SystemV ABI, ABI conversion and additional * stack to store XMM6-XMM15 needed on Win64. */ #undef ASM_FUNC_ABI #if defined(USE_AESNI_AVX) || defined(USE_AESNI_AVX2) || \ defined(USE_GFNI_AVX2) || defined(USE_GFNI_AVX512) || \ - defined(USE_INTEL_SM4_AVX2) + defined(USE_INTEL_SM4_AVX2) || defined(USE_INTEL_SM4_AVX512) # ifdef HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS # define ASM_FUNC_ABI __attribute__((sysv_abi)) # else @@ -182,6 +192,9 @@ typedef struct #ifdef USE_INTEL_SM4_AVX2 unsigned int use_intel_sm4_avx2:1; #endif +#ifdef USE_INTEL_SM4_AVX512 + unsigned int use_intel_sm4_avx512:1; +#endif #ifdef USE_AARCH64_SIMD unsigned int use_aarch64_simd:1; #endif @@ -419,6 +432,38 @@ sm4_intel_avx2_crypt_blk1_16(void *rk, byte *out, const byte *in, } #endif /* USE_INTEL_SM4_AVX2 */ +#ifdef USE_INTEL_SM4_AVX512 +extern void _gcry_sm4_intel_avx512_ctr_enc_blk32(const u32 *rk_enc, byte *out, + const byte *in, + byte *ctr) ASM_FUNC_ABI; + +extern void _gcry_sm4_intel_avx512_cbc_dec_blk32(const u32 *rk_dec, byte *out, + const byte *in, + byte *iv) ASM_FUNC_ABI; + +extern void _gcry_sm4_intel_avx512_cfb_dec_blk32(const u32 *rk_enc, byte *out, + const byte *in, + byte *iv) ASM_FUNC_ABI; + +extern void _gcry_sm4_intel_avx512_ocb_enc_blk32(const u32 *rk_enc, + unsigned char *out, + const unsigned char *in, + unsigned char *offset, + unsigned char *checksum, + const u64 Ls[32]) ASM_FUNC_ABI; + +extern void _gcry_sm4_intel_avx512_ocb_dec_blk32(const u32 *rk_dec, + unsigned char *out, + const unsigned char *in, + unsigned char *offset, + unsigned char *checksum, + const u64 Ls[32]) ASM_FUNC_ABI; + +extern unsigned int +_gcry_sm4_intel_avx512_crypt_blk32(u32 *rk, byte *out, + const byte *in) ASM_FUNC_ABI; +#endif /* USE_INTEL_SM4_AVX512 */ + #ifdef USE_GFNI_AVX2 extern void _gcry_sm4_gfni_avx2_expand_key(const byte *key, u32 *rk_enc, u32 *rk_dec, const u32 *fk, @@ -873,6 +918,9 @@ sm4_setkey (void *context, const byte *key, const unsigned keylen, #ifdef USE_INTEL_SM4_AVX2 ctx->use_intel_sm4_avx2 = (hwf & HWF_INTEL_SM4) && (hwf & HWF_INTEL_AVX2); #endif +#ifdef USE_INTEL_SM4_AVX512 + ctx->use_intel_sm4_avx512 = (hwf & HWF_INTEL_SM4) && (hwf & HWF_INTEL_AVX512); +#endif #ifdef USE_AARCH64_SIMD ctx->use_aarch64_simd = !!(hwf & HWF_ARM_NEON); #endif @@ -1188,6 +1236,21 @@ _gcry_sm4_ctr_enc(void *context, unsigned char *ctr, const byte *inbuf = inbuf_arg; int burn_stack_depth = 0; +#ifdef USE_INTEL_SM4_AVX512 + if (ctx->use_intel_sm4_avx512) + { + /* Process data in 32 block chunks. */ + while (nblocks >= 32) + { + _gcry_sm4_intel_avx512_ctr_enc_blk32(ctx->rkey_enc, outbuf, inbuf, ctr); + + nblocks -= 32; + outbuf += 32 * 16; + inbuf += 32 * 16; + } + } +#endif + #ifdef USE_INTEL_SM4_AVX2 if (ctx->use_intel_sm4_avx2) { @@ -1353,6 +1416,21 @@ _gcry_sm4_cbc_dec(void *context, unsigned char *iv, const unsigned char *inbuf = inbuf_arg; int burn_stack_depth = 0; +#ifdef USE_INTEL_SM4_AVX512 + if (ctx->use_intel_sm4_avx512) + { + /* Process data in 32 block chunks. */ + while (nblocks >= 32) + { + _gcry_sm4_intel_avx512_cbc_dec_blk32(ctx->rkey_dec, outbuf, inbuf, iv); + + nblocks -= 32; + outbuf += 32 * 16; + inbuf += 32 * 16; + } + } +#endif + #ifdef USE_INTEL_SM4_AVX2 if (ctx->use_intel_sm4_avx2) { @@ -1517,6 +1595,21 @@ _gcry_sm4_cfb_dec(void *context, unsigned char *iv, const unsigned char *inbuf = inbuf_arg; int burn_stack_depth = 0; +#ifdef USE_INTEL_SM4_AVX512 + if (ctx->use_intel_sm4_avx512) + { + /* Process data in 32 block chunks. */ + while (nblocks >= 32) + { + _gcry_sm4_intel_avx512_cfb_dec_blk32(ctx->rkey_enc, outbuf, inbuf, iv); + + nblocks -= 32; + outbuf += 32 * 16; + inbuf += 32 * 16; + } + } +#endif + #ifdef USE_INTEL_SM4_AVX2 if (ctx->use_intel_sm4_avx2) { @@ -1679,6 +1772,12 @@ sm4_crypt_blk1_32 (SM4_context *ctx, byte *outbuf, const byte *inbuf, gcry_assert (num_blks <= 32); +#ifdef USE_INTEL_SM4_AVX512 + if (num_blks == 32 && ctx->use_intel_sm4_avx512) + { + return _gcry_sm4_intel_avx512_crypt_blk32 (rk, outbuf, inbuf); + } +#endif #ifdef USE_GFNI_AVX512 if (num_blks == 32 && ctx->use_gfni_avx512) { @@ -1837,6 +1936,39 @@ _gcry_sm4_ocb_crypt (gcry_cipher_hd_t c, void *outbuf_arg, u64 blkn = c->u_mode.ocb.data_nblocks; int burn_stack_depth = 0; +#ifdef USE_INTEL_SM4_AVX512 + if (ctx->use_intel_sm4_avx512) + { + u64 Ls[32]; + u64 *l; + + if (nblocks >= 32) + { + l = bulk_ocb_prepare_L_pointers_array_blk32 (c, Ls, blkn); + + /* Process data in 32 block chunks. */ + while (nblocks >= 32) + { + blkn += 32; + *l = (uintptr_t)(void *)ocb_get_l (c, blkn - blkn % 32); + + if (encrypt) + _gcry_sm4_intel_avx512_ocb_enc_blk32 (ctx->rkey_enc, outbuf, + inbuf, c->u_iv.iv, + c->u_ctr.ctr, Ls); + else + _gcry_sm4_intel_avx512_ocb_dec_blk32 (ctx->rkey_dec, outbuf, + inbuf, c->u_iv.iv, + c->u_ctr.ctr, Ls); + + nblocks -= 32; + outbuf += 32 * 16; + inbuf += 32 * 16; + } + } + } +#endif + #ifdef USE_INTEL_SM4_AVX2 if (ctx->use_intel_sm4_avx2) { diff --git a/configure.ac b/configure.ac index f12b590e..604f063e 100644 --- a/configure.ac +++ b/configure.ac @@ -3874,6 +3874,7 @@ if test "$found" = "1" ; then GCRYPT_ASM_CIPHERS="$GCRYPT_ASM_CIPHERS sm4-gfni-avx2-amd64.lo" GCRYPT_ASM_CIPHERS="$GCRYPT_ASM_CIPHERS sm4-gfni-avx512-amd64.lo" GCRYPT_ASM_CIPHERS="$GCRYPT_ASM_CIPHERS sm4-intel-avx2-amd64.lo" + GCRYPT_ASM_CIPHERS="$GCRYPT_ASM_CIPHERS sm4-intel-avx512-amd64.lo" ;; aarch64-*-*) # Build with the assembly implementation -- 2.53.0