| #!/usr/bin/env perl |
| |
| # Copyright (c) 2017, Shay Gueron. |
| # Copyright (c) 2017, Google Inc. |
| # |
| # Permission to use, copy, modify, and/or distribute this software for any |
| # purpose with or without fee is hereby granted, provided that the above |
| # copyright notice and this permission notice appear in all copies. |
| # |
| # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
| # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
| # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY |
| # SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
| # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION |
| # OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN |
| # CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ |
| |
| use warnings FATAL => 'all'; |
| |
| $flavour = shift; |
| $output = shift; |
| if ($flavour =~ /\./) { $output = $flavour; undef $flavour; } |
| |
| $win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/); |
| |
| $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; |
| ( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or |
| ( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or |
| die "can't locate x86_64-xlate.pl"; |
| |
| open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\""; |
| *STDOUT=*OUT; |
| |
| $code.=<<___; |
| .section .rodata |
| |
| .align 16 |
| one: |
| .quad 1,0 |
| two: |
| .quad 2,0 |
| three: |
| .quad 3,0 |
| four: |
| .quad 4,0 |
| five: |
| .quad 5,0 |
| six: |
| .quad 6,0 |
| seven: |
| .quad 7,0 |
| eight: |
| .quad 8,0 |
| |
| OR_MASK: |
| .long 0x00000000,0x00000000,0x00000000,0x80000000 |
| poly: |
| .quad 0x1, 0xc200000000000000 |
| mask: |
| .long 0x0c0f0e0d,0x0c0f0e0d,0x0c0f0e0d,0x0c0f0e0d |
| con1: |
| .long 1,1,1,1 |
| con2: |
| .long 0x1b,0x1b,0x1b,0x1b |
| con3: |
| .byte -1,-1,-1,-1,-1,-1,-1,-1,4,5,6,7,4,5,6,7 |
| and_mask: |
| .long 0,0xffffffff, 0xffffffff, 0xffffffff |
| ___ |
| |
| $code.=<<___; |
| .text |
| ___ |
| |
| sub gfmul { |
| ######################### |
| # a = T |
| # b = TMP0 - remains unchanged |
| # res = T |
| # uses also TMP1,TMP2,TMP3,TMP4 |
| # __m128i GFMUL(__m128i A, __m128i B); |
| |
| my $T = "%xmm0"; |
| my $TMP0 = "%xmm1"; |
| my $TMP1 = "%xmm2"; |
| my $TMP2 = "%xmm3"; |
| my $TMP3 = "%xmm4"; |
| my $TMP4 = "%xmm5"; |
| |
| $code.=<<___; |
| .type GFMUL,\@abi-omnipotent |
| .align 16 |
| GFMUL: |
| .cfi_startproc |
| vpclmulqdq \$0x00, $TMP0, $T, $TMP1 |
| vpclmulqdq \$0x11, $TMP0, $T, $TMP4 |
| vpclmulqdq \$0x10, $TMP0, $T, $TMP2 |
| vpclmulqdq \$0x01, $TMP0, $T, $TMP3 |
| vpxor $TMP3, $TMP2, $TMP2 |
| vpslldq \$8, $TMP2, $TMP3 |
| vpsrldq \$8, $TMP2, $TMP2 |
| vpxor $TMP3, $TMP1, $TMP1 |
| vpxor $TMP2, $TMP4, $TMP4 |
| |
| vpclmulqdq \$0x10, poly(%rip), $TMP1, $TMP2 |
| vpshufd \$78, $TMP1, $TMP3 |
| vpxor $TMP3, $TMP2, $TMP1 |
| |
| vpclmulqdq \$0x10, poly(%rip), $TMP1, $TMP2 |
| vpshufd \$78, $TMP1, $TMP3 |
| vpxor $TMP3, $TMP2, $TMP1 |
| |
| vpxor $TMP4, $TMP1, $T |
| ret |
| .cfi_endproc |
| .size GFMUL, .-GFMUL |
| ___ |
| } |
| gfmul(); |
| |
| sub aesgcmsiv_htable_init { |
| # aesgcmsiv_htable_init writes an eight-entry table of powers of |H| to |
| # |out_htable|. |
| # void aesgcmsiv_htable_init(uint8_t out_htable[16*8], uint8_t *H); |
| |
| my $Htbl = "%rdi"; |
| my $H = "%rsi"; |
| my $T = "%xmm0"; |
| my $TMP0 = "%xmm1"; |
| |
| $code.=<<___; |
| .globl aesgcmsiv_htable_init |
| .type aesgcmsiv_htable_init,\@function,2 |
| .align 16 |
| aesgcmsiv_htable_init: |
| .cfi_startproc |
| vmovdqa ($H), $T |
| vmovdqa $T, $TMP0 |
| vmovdqa $T, ($Htbl) # H |
| call GFMUL |
| vmovdqa $T, 16($Htbl) # H^2 |
| call GFMUL |
| vmovdqa $T, 32($Htbl) # H^3 |
| call GFMUL |
| vmovdqa $T, 48($Htbl) # H^4 |
| call GFMUL |
| vmovdqa $T, 64($Htbl) # H^5 |
| call GFMUL |
| vmovdqa $T, 80($Htbl) # H^6 |
| call GFMUL |
| vmovdqa $T, 96($Htbl) # H^7 |
| call GFMUL |
| vmovdqa $T, 112($Htbl) # H^8 |
| ret |
| .cfi_endproc |
| .size aesgcmsiv_htable_init, .-aesgcmsiv_htable_init |
| ___ |
| } |
| aesgcmsiv_htable_init(); |
| |
| sub aesgcmsiv_htable6_init { |
| # aesgcmsiv_htable6_init writes a six-entry table of powers of |H| to |
| # |out_htable|. |
| # void aesgcmsiv_htable6_init(uint8_t out_htable[16*6], uint8_t *H); |
| # |
| my $Htbl = "%rdi"; |
| my $H = "%rsi"; |
| my $T = "%xmm0"; |
| my $TMP0 = "%xmm1"; |
| |
| $code.=<<___; |
| .globl aesgcmsiv_htable6_init |
| .type aesgcmsiv_htable6_init,\@function,2 |
| .align 16 |
| aesgcmsiv_htable6_init: |
| .cfi_startproc |
| vmovdqa ($H), $T |
| vmovdqa $T, $TMP0 |
| vmovdqa $T, ($Htbl) # H |
| call GFMUL |
| vmovdqa $T, 16($Htbl) # H^2 |
| call GFMUL |
| vmovdqa $T, 32($Htbl) # H^3 |
| call GFMUL |
| vmovdqa $T, 48($Htbl) # H^4 |
| call GFMUL |
| vmovdqa $T, 64($Htbl) # H^5 |
| call GFMUL |
| vmovdqa $T, 80($Htbl) # H^6 |
| ret |
| .cfi_endproc |
| .size aesgcmsiv_htable6_init, .-aesgcmsiv_htable6_init |
| ___ |
| } |
| aesgcmsiv_htable6_init(); |
| |
| sub aesgcmsiv_htable_polyval { |
| # void aesgcmsiv_htable_polyval(uint8_t Htbl[16*8], uint8_t *MSG, uint64_t LEN, uint8_t *T); |
| # parameter 1: %rdi Htable - pointer to Htable |
| # parameter 2: %rsi INp - pointer to input |
| # parameter 3: %rdx LEN - length of BUFFER in bytes |
| # parameter 4: %rcx T - pointer to POLYVAL output |
| |
| my $DATA = "%xmm0"; |
| my $hlp0 = "%r11"; |
| my $Htbl = "%rdi"; |
| my $inp = "%rsi"; |
| my $len = "%rdx"; |
| my $TMP0 = "%xmm3"; |
| my $TMP1 = "%xmm4"; |
| my $TMP2 = "%xmm5"; |
| my $TMP3 = "%xmm6"; |
| my $TMP4 = "%xmm7"; |
| my $Tp = "%rcx"; |
| my $T = "%xmm1"; |
| my $Xhi = "%xmm9"; |
| |
| my $SCHOOLBOOK_AAD = sub { |
| my ($i)=@_; |
| return <<___; |
| vpclmulqdq \$0x01, ${\eval(16*$i)}($Htbl), $DATA, $TMP3 |
| vpxor $TMP3, $TMP2, $TMP2 |
| vpclmulqdq \$0x00, ${\eval(16*$i)}($Htbl), $DATA, $TMP3 |
| vpxor $TMP3, $TMP0, $TMP0 |
| vpclmulqdq \$0x11, ${\eval(16*$i)}($Htbl), $DATA, $TMP3 |
| vpxor $TMP3, $TMP1, $TMP1 |
| vpclmulqdq \$0x10, ${\eval(16*$i)}($Htbl), $DATA, $TMP3 |
| vpxor $TMP3, $TMP2, $TMP2 |
| ___ |
| }; |
| |
| $code.=<<___; |
| .globl aesgcmsiv_htable_polyval |
| .type aesgcmsiv_htable_polyval,\@function,4 |
| .align 16 |
| aesgcmsiv_htable_polyval: |
| .cfi_startproc |
| test $len, $len |
| jnz .Lhtable_polyval_start |
| ret |
| |
| .Lhtable_polyval_start: |
| vzeroall |
| |
| # We hash 8 blocks each iteration. If the total number of blocks is not a |
| # multiple of 8, we first hash the leading n%8 blocks. |
| movq $len, $hlp0 |
| andq \$127, $hlp0 |
| |
| jz .Lhtable_polyval_no_prefix |
| |
| vpxor $Xhi, $Xhi, $Xhi |
| vmovdqa ($Tp), $T |
| sub $hlp0, $len |
| |
| sub \$16, $hlp0 |
| |
| # hash first prefix block |
| vmovdqu ($inp), $DATA |
| vpxor $T, $DATA, $DATA |
| |
| vpclmulqdq \$0x01, ($Htbl,$hlp0), $DATA, $TMP2 |
| vpclmulqdq \$0x00, ($Htbl,$hlp0), $DATA, $TMP0 |
| vpclmulqdq \$0x11, ($Htbl,$hlp0), $DATA, $TMP1 |
| vpclmulqdq \$0x10, ($Htbl,$hlp0), $DATA, $TMP3 |
| vpxor $TMP3, $TMP2, $TMP2 |
| |
| lea 16($inp), $inp |
| test $hlp0, $hlp0 |
| jnz .Lhtable_polyval_prefix_loop |
| jmp .Lhtable_polyval_prefix_complete |
| |
| # hash remaining prefix bocks (up to 7 total prefix blocks) |
| .align 64 |
| .Lhtable_polyval_prefix_loop: |
| sub \$16, $hlp0 |
| |
| vmovdqu ($inp), $DATA # next data block |
| |
| vpclmulqdq \$0x00, ($Htbl,$hlp0), $DATA, $TMP3 |
| vpxor $TMP3, $TMP0, $TMP0 |
| vpclmulqdq \$0x11, ($Htbl,$hlp0), $DATA, $TMP3 |
| vpxor $TMP3, $TMP1, $TMP1 |
| vpclmulqdq \$0x01, ($Htbl,$hlp0), $DATA, $TMP3 |
| vpxor $TMP3, $TMP2, $TMP2 |
| vpclmulqdq \$0x10, ($Htbl,$hlp0), $DATA, $TMP3 |
| vpxor $TMP3, $TMP2, $TMP2 |
| |
| test $hlp0, $hlp0 |
| |
| lea 16($inp), $inp |
| |
| jnz .Lhtable_polyval_prefix_loop |
| |
| .Lhtable_polyval_prefix_complete: |
| vpsrldq \$8, $TMP2, $TMP3 |
| vpslldq \$8, $TMP2, $TMP2 |
| |
| vpxor $TMP3, $TMP1, $Xhi |
| vpxor $TMP2, $TMP0, $T |
| |
| jmp .Lhtable_polyval_main_loop |
| |
| .Lhtable_polyval_no_prefix: |
| # At this point we know the number of blocks is a multiple of 8. However, |
| # the reduction in the main loop includes a multiplication by x^(-128). In |
| # order to counter this, the existing tag needs to be multipled by x^128. |
| # In practice, this just means that it is loaded into $Xhi, not $T. |
| vpxor $T, $T, $T |
| vmovdqa ($Tp), $Xhi |
| |
| .align 64 |
| .Lhtable_polyval_main_loop: |
| sub \$0x80, $len |
| jb .Lhtable_polyval_out |
| |
| vmovdqu 16*7($inp), $DATA # Ii |
| |
| vpclmulqdq \$0x01, ($Htbl), $DATA, $TMP2 |
| vpclmulqdq \$0x00, ($Htbl), $DATA, $TMP0 |
| vpclmulqdq \$0x11, ($Htbl), $DATA, $TMP1 |
| vpclmulqdq \$0x10, ($Htbl), $DATA, $TMP3 |
| vpxor $TMP3, $TMP2, $TMP2 |
| |
| ######################################################### |
| vmovdqu 16*6($inp), $DATA |
| ${\$SCHOOLBOOK_AAD->(1)} |
| |
| ######################################################### |
| vmovdqu 16*5($inp), $DATA |
| |
| vpclmulqdq \$0x10, poly(%rip), $T, $TMP4 # reduction stage 1a |
| vpalignr \$8, $T, $T, $T |
| |
| ${\$SCHOOLBOOK_AAD->(2)} |
| |
| vpxor $TMP4, $T, $T # reduction stage 1b |
| ######################################################### |
| vmovdqu 16*4($inp), $DATA |
| |
| ${\$SCHOOLBOOK_AAD->(3)} |
| ######################################################### |
| vmovdqu 16*3($inp), $DATA |
| |
| vpclmulqdq \$0x10, poly(%rip), $T, $TMP4 # reduction stage 2a |
| vpalignr \$8, $T, $T, $T |
| |
| ${\$SCHOOLBOOK_AAD->(4)} |
| |
| vpxor $TMP4, $T, $T # reduction stage 2b |
| ######################################################### |
| vmovdqu 16*2($inp), $DATA |
| |
| ${\$SCHOOLBOOK_AAD->(5)} |
| |
| vpxor $Xhi, $T, $T # reduction finalize |
| ######################################################### |
| vmovdqu 16*1($inp), $DATA |
| |
| ${\$SCHOOLBOOK_AAD->(6)} |
| ######################################################### |
| vmovdqu 16*0($inp), $DATA |
| vpxor $T, $DATA, $DATA |
| |
| ${\$SCHOOLBOOK_AAD->(7)} |
| ######################################################### |
| vpsrldq \$8, $TMP2, $TMP3 |
| vpslldq \$8, $TMP2, $TMP2 |
| |
| vpxor $TMP3, $TMP1, $Xhi |
| vpxor $TMP2, $TMP0, $T |
| |
| lea 16*8($inp), $inp |
| jmp .Lhtable_polyval_main_loop |
| |
| ######################################################### |
| |
| .Lhtable_polyval_out: |
| vpclmulqdq \$0x10, poly(%rip), $T, $TMP3 |
| vpalignr \$8, $T, $T, $T |
| vpxor $TMP3, $T, $T |
| |
| vpclmulqdq \$0x10, poly(%rip), $T, $TMP3 |
| vpalignr \$8, $T, $T, $T |
| vpxor $TMP3, $T, $T |
| vpxor $Xhi, $T, $T |
| |
| vmovdqu $T, ($Tp) |
| vzeroupper |
| ret |
| .cfi_endproc |
| .size aesgcmsiv_htable_polyval,.-aesgcmsiv_htable_polyval |
| ___ |
| } |
| aesgcmsiv_htable_polyval(); |
| |
| sub aesgcmsiv_polyval_horner { |
| #void aesgcmsiv_polyval_horner(unsigned char T[16], // output |
| # const unsigned char* H, // H |
| # unsigned char* BUF, // Buffer |
| # unsigned int blocks); // Len2 |
| # |
| # parameter 1: %rdi T - pointers to POLYVAL output |
| # parameter 2: %rsi Hp - pointer to H (user key) |
| # parameter 3: %rdx INp - pointer to input |
| # parameter 4: %rcx L - total number of blocks in input BUFFER |
| # |
| my $T = "%rdi"; |
| my $Hp = "%rsi"; |
| my $INp = "%rdx"; |
| my $L = "%rcx"; |
| my $LOC = "%r10"; |
| my $LEN = "%eax"; |
| my $H = "%xmm1"; |
| my $RES = "%xmm0"; |
| |
| $code.=<<___; |
| .globl aesgcmsiv_polyval_horner |
| .type aesgcmsiv_polyval_horner,\@function,4 |
| .align 16 |
| aesgcmsiv_polyval_horner: |
| .cfi_startproc |
| test $L, $L |
| jnz .Lpolyval_horner_start |
| ret |
| |
| .Lpolyval_horner_start: |
| # We will start with L GFMULS for POLYVAL(BIG_BUFFER) |
| # RES = GFMUL(RES, H) |
| |
| xorq $LOC, $LOC |
| shlq \$4, $L # L contains number of bytes to process |
| |
| vmovdqa ($Hp), $H |
| vmovdqa ($T), $RES |
| |
| .Lpolyval_horner_loop: |
| vpxor ($INp,$LOC), $RES, $RES # RES = RES + Xi |
| call GFMUL # RES = RES * H |
| |
| add \$16, $LOC |
| cmp $LOC, $L |
| jne .Lpolyval_horner_loop |
| |
| # calculation of T is complete. RES=T |
| vmovdqa $RES, ($T) |
| ret |
| .cfi_endproc |
| .size aesgcmsiv_polyval_horner,.-aesgcmsiv_polyval_horner |
| ___ |
| } |
| aesgcmsiv_polyval_horner(); |
| |
| # void aes128gcmsiv_aes_ks(const uint8_t *key, uint8_t *out_expanded_key); |
| # parameter 1: %rdi |
| # parameter 2: %rsi |
| $code.=<<___; |
| .globl aes128gcmsiv_aes_ks |
| .type aes128gcmsiv_aes_ks,\@function,2 |
| .align 16 |
| aes128gcmsiv_aes_ks: |
| .cfi_startproc |
| vmovdqu (%rdi), %xmm1 # xmm1 = user key |
| vmovdqa %xmm1, (%rsi) # rsi points to output |
| |
| vmovdqa con1(%rip), %xmm0 |
| vmovdqa mask(%rip), %xmm15 |
| |
| movq \$8, %rax |
| |
| .Lks128_loop: |
| addq \$16, %rsi # rsi points for next key |
| subq \$1, %rax |
| vpshufb %xmm15, %xmm1, %xmm2 # xmm2 = shuffled user key |
| vaesenclast %xmm0, %xmm2, %xmm2 |
| vpslld \$1, %xmm0, %xmm0 |
| vpslldq \$4, %xmm1, %xmm3 |
| vpxor %xmm3, %xmm1, %xmm1 |
| vpslldq \$4, %xmm3, %xmm3 |
| vpxor %xmm3, %xmm1, %xmm1 |
| vpslldq \$4, %xmm3, %xmm3 |
| vpxor %xmm3, %xmm1, %xmm1 |
| vpxor %xmm2, %xmm1, %xmm1 |
| vmovdqa %xmm1, (%rsi) |
| jne .Lks128_loop |
| |
| vmovdqa con2(%rip), %xmm0 |
| vpshufb %xmm15, %xmm1, %xmm2 |
| vaesenclast %xmm0, %xmm2, %xmm2 |
| vpslld \$1, %xmm0, %xmm0 |
| vpslldq \$4, %xmm1, %xmm3 |
| vpxor %xmm3, %xmm1, %xmm1 |
| vpslldq \$4, %xmm3, %xmm3 |
| vpxor %xmm3, %xmm1, %xmm1 |
| vpslldq \$4, %xmm3, %xmm3 |
| vpxor %xmm3, %xmm1, %xmm1 |
| vpxor %xmm2, %xmm1, %xmm1 |
| vmovdqa %xmm1, 16(%rsi) |
| |
| vpshufb %xmm15, %xmm1, %xmm2 |
| vaesenclast %xmm0, %xmm2, %xmm2 |
| vpslldq \$4, %xmm1, %xmm3 |
| vpxor %xmm3, %xmm1, %xmm1 |
| vpslldq \$4, %xmm3, %xmm3 |
| vpxor %xmm3, %xmm1, %xmm1 |
| vpslldq \$4, %xmm3, %xmm3 |
| vpxor %xmm3, %xmm1, %xmm1 |
| vpxor %xmm2, %xmm1, %xmm1 |
| vmovdqa %xmm1, 32(%rsi) |
| ret |
| .cfi_endproc |
| .size aes128gcmsiv_aes_ks,.-aes128gcmsiv_aes_ks |
| ___ |
| |
| # void aes256gcmsiv_aes_ks(const uint8_t *key, uint8_t *out_expanded_key); |
| # parameter 1: %rdi |
| # parameter 2: %rsi |
| $code.=<<___; |
| .globl aes256gcmsiv_aes_ks |
| .type aes256gcmsiv_aes_ks,\@function,2 |
| .align 16 |
| aes256gcmsiv_aes_ks: |
| .cfi_startproc |
| vmovdqu (%rdi), %xmm1 |
| vmovdqu 16(%rdi), %xmm3 |
| vmovdqa %xmm1, (%rsi) |
| vmovdqa %xmm3, 16(%rsi) |
| vmovdqa con1(%rip), %xmm0 |
| vmovdqa mask(%rip), %xmm15 |
| vpxor %xmm14, %xmm14, %xmm14 |
| mov \$6, %rax |
| |
| .Lks256_loop: |
| add \$32, %rsi |
| subq \$1, %rax |
| vpshufb %xmm15, %xmm3, %xmm2 |
| vaesenclast %xmm0, %xmm2, %xmm2 |
| vpslld \$1, %xmm0, %xmm0 |
| vpsllq \$32, %xmm1, %xmm4 |
| vpxor %xmm4, %xmm1, %xmm1 |
| vpshufb con3(%rip), %xmm1, %xmm4 |
| vpxor %xmm4, %xmm1, %xmm1 |
| vpxor %xmm2, %xmm1, %xmm1 |
| vmovdqa %xmm1, (%rsi) |
| vpshufd \$0xff, %xmm1, %xmm2 |
| vaesenclast %xmm14, %xmm2, %xmm2 |
| vpsllq \$32, %xmm3, %xmm4 |
| vpxor %xmm4, %xmm3, %xmm3 |
| vpshufb con3(%rip), %xmm3, %xmm4 |
| vpxor %xmm4, %xmm3, %xmm3 |
| vpxor %xmm2, %xmm3, %xmm3 |
| vmovdqa %xmm3, 16(%rsi) |
| jne .Lks256_loop |
| |
| vpshufb %xmm15, %xmm3, %xmm2 |
| vaesenclast %xmm0, %xmm2, %xmm2 |
| vpsllq \$32, %xmm1, %xmm4 |
| vpxor %xmm4, %xmm1, %xmm1 |
| vpshufb con3(%rip), %xmm1, %xmm4 |
| vpxor %xmm4, %xmm1, %xmm1 |
| vpxor %xmm2, %xmm1, %xmm1 |
| vmovdqa %xmm1, 32(%rsi) |
| ret |
| .cfi_endproc |
| ___ |
| |
| sub aes128gcmsiv_aes_ks_enc_x1 { |
| my $KS1_REGA = "%xmm1"; |
| my $KS1_REGB = "%xmm2"; |
| my $BLOCK1 = "%xmm4"; |
| my $AUXREG = "%xmm3"; |
| |
| my $KS_BLOCK = sub { |
| my ($reg, $reg2, $auxReg) = @_; |
| return <<___; |
| vpsllq \$32, $reg, $auxReg #!!saving mov instruction to xmm3 |
| vpxor $auxReg, $reg, $reg |
| vpshufb con3(%rip), $reg, $auxReg |
| vpxor $auxReg, $reg, $reg |
| vpxor $reg2, $reg, $reg |
| ___ |
| }; |
| |
| my $round = sub { |
| my ($i, $j) = @_; |
| return <<___; |
| vpshufb %xmm15, %xmm1, %xmm2 #!!saving mov instruction to xmm2 |
| vaesenclast %xmm0, %xmm2, %xmm2 |
| vpslld \$1, %xmm0, %xmm0 |
| ${\$KS_BLOCK->($KS1_REGA, $KS1_REGB, $AUXREG)} |
| vaesenc %xmm1, $BLOCK1, $BLOCK1 |
| vmovdqa %xmm1, ${\eval(16*$i)}($j) |
| ___ |
| }; |
| |
| my $roundlast = sub { |
| my ($i, $j) = @_; |
| return <<___; |
| vpshufb %xmm15, %xmm1, %xmm2 #!!saving mov instruction to xmm2 |
| vaesenclast %xmm0, %xmm2, %xmm2 |
| ${\$KS_BLOCK->($KS1_REGA, $KS1_REGB, $AUXREG)} |
| vaesenclast %xmm1, $BLOCK1, $BLOCK1 |
| vmovdqa %xmm1, ${\eval(16*$i)}($j) |
| ___ |
| }; |
| |
| # parameter 1: %rdi Pointer to PT |
| # parameter 2: %rsi Pointer to CT |
| # parameter 4: %rdx Pointer to keys |
| # parameter 5: %rcx Pointer to initial key |
| $code.=<<___; |
| .globl aes128gcmsiv_aes_ks_enc_x1 |
| .type aes128gcmsiv_aes_ks_enc_x1,\@function,4 |
| .align 16 |
| aes128gcmsiv_aes_ks_enc_x1: |
| .cfi_startproc |
| vmovdqa (%rcx), %xmm1 # xmm1 = first 16 bytes of random key |
| vmovdqa 0*16(%rdi), $BLOCK1 |
| |
| vmovdqa %xmm1, (%rdx) # KEY[0] = first 16 bytes of random key |
| vpxor %xmm1, $BLOCK1, $BLOCK1 |
| |
| vmovdqa con1(%rip), %xmm0 # xmm0 = 1,1,1,1 |
| vmovdqa mask(%rip), %xmm15 # xmm15 = mask |
| |
| ${\$round->(1, "%rdx")} |
| ${\$round->(2, "%rdx")} |
| ${\$round->(3, "%rdx")} |
| ${\$round->(4, "%rdx")} |
| ${\$round->(5, "%rdx")} |
| ${\$round->(6, "%rdx")} |
| ${\$round->(7, "%rdx")} |
| ${\$round->(8, "%rdx")} |
| |
| vmovdqa con2(%rip), %xmm0 |
| |
| ${\$round->(9, "%rdx")} |
| ${\$roundlast->(10, "%rdx")} |
| |
| vmovdqa $BLOCK1, 0*16(%rsi) |
| ret |
| .cfi_endproc |
| .size aes128gcmsiv_aes_ks_enc_x1,.-aes128gcmsiv_aes_ks_enc_x1 |
| ___ |
| } |
| aes128gcmsiv_aes_ks_enc_x1(); |
| |
| sub aes128gcmsiv_kdf { |
| my $BLOCK1 = "%xmm9"; |
| my $BLOCK2 = "%xmm10"; |
| my $BLOCK3 = "%xmm11"; |
| my $BLOCK4 = "%xmm12"; |
| my $BLOCK5 = "%xmm13"; |
| my $BLOCK6 = "%xmm14"; |
| my $ONE = "%xmm13"; |
| my $KSp = "%rdx"; |
| my $STATE_1 = "%xmm1"; |
| |
| my $enc_roundx4 = sub { |
| my ($i, $j) = @_; |
| return <<___; |
| vmovdqa ${\eval($i*16)}(%rdx), $j |
| vaesenc $j, $BLOCK1, $BLOCK1 |
| vaesenc $j, $BLOCK2, $BLOCK2 |
| vaesenc $j, $BLOCK3, $BLOCK3 |
| vaesenc $j, $BLOCK4, $BLOCK4 |
| ___ |
| }; |
| |
| my $enc_roundlastx4 = sub { |
| my ($i, $j) = @_; |
| return <<___; |
| vmovdqa ${\eval($i*16)}(%rdx), $j |
| vaesenclast $j, $BLOCK1, $BLOCK1 |
| vaesenclast $j, $BLOCK2, $BLOCK2 |
| vaesenclast $j, $BLOCK3, $BLOCK3 |
| vaesenclast $j, $BLOCK4, $BLOCK4 |
| ___ |
| }; |
| |
| # void aes128gcmsiv_kdf(const uint8_t nonce[16], |
| # uint8_t *out_key_material, |
| # const uint8_t *key_schedule); |
| $code.=<<___; |
| .globl aes128gcmsiv_kdf |
| .type aes128gcmsiv_kdf,\@function,3 |
| .align 16 |
| aes128gcmsiv_kdf: |
| .cfi_startproc |
| # parameter 1: %rdi Pointer to NONCE |
| # parameter 2: %rsi Pointer to CT |
| # parameter 4: %rdx Pointer to keys |
| |
| vmovdqa (%rdx), %xmm1 # xmm1 = first 16 bytes of random key |
| vmovdqa 0*16(%rdi), $BLOCK1 |
| vmovdqa and_mask(%rip), $BLOCK4 |
| vmovdqa one(%rip), $ONE |
| vpshufd \$0x90, $BLOCK1, $BLOCK1 |
| vpand $BLOCK4, $BLOCK1, $BLOCK1 |
| vpaddd $ONE, $BLOCK1, $BLOCK2 |
| vpaddd $ONE, $BLOCK2, $BLOCK3 |
| vpaddd $ONE, $BLOCK3, $BLOCK4 |
| |
| vpxor %xmm1, $BLOCK1, $BLOCK1 |
| vpxor %xmm1, $BLOCK2, $BLOCK2 |
| vpxor %xmm1, $BLOCK3, $BLOCK3 |
| vpxor %xmm1, $BLOCK4, $BLOCK4 |
| |
| ${\$enc_roundx4->(1, "%xmm1")} |
| ${\$enc_roundx4->(2, "%xmm2")} |
| ${\$enc_roundx4->(3, "%xmm1")} |
| ${\$enc_roundx4->(4, "%xmm2")} |
| ${\$enc_roundx4->(5, "%xmm1")} |
| ${\$enc_roundx4->(6, "%xmm2")} |
| ${\$enc_roundx4->(7, "%xmm1")} |
| ${\$enc_roundx4->(8, "%xmm2")} |
| ${\$enc_roundx4->(9, "%xmm1")} |
| ${\$enc_roundlastx4->(10, "%xmm2")} |
| |
| vmovdqa $BLOCK1, 0*16(%rsi) |
| vmovdqa $BLOCK2, 1*16(%rsi) |
| vmovdqa $BLOCK3, 2*16(%rsi) |
| vmovdqa $BLOCK4, 3*16(%rsi) |
| ret |
| .cfi_endproc |
| .size aes128gcmsiv_kdf,.-aes128gcmsiv_kdf |
| ___ |
| } |
| aes128gcmsiv_kdf(); |
| |
| sub aes128gcmsiv_enc_msg_x4 { |
| my $CTR1 = "%xmm0"; |
| my $CTR2 = "%xmm1"; |
| my $CTR3 = "%xmm2"; |
| my $CTR4 = "%xmm3"; |
| my $ADDER = "%xmm4"; |
| |
| my $STATE1 = "%xmm5"; |
| my $STATE2 = "%xmm6"; |
| my $STATE3 = "%xmm7"; |
| my $STATE4 = "%xmm8"; |
| |
| my $TMP = "%xmm12"; |
| my $TMP2 = "%xmm13"; |
| my $TMP3 = "%xmm14"; |
| my $IV = "%xmm15"; |
| |
| my $PT = "%rdi"; |
| my $CT = "%rsi"; |
| my $TAG = "%rdx"; |
| my $KS = "%rcx"; |
| my $LEN = "%r8"; |
| |
| my $aes_round = sub { |
| my ($i) = @_; |
| return <<___; |
| vmovdqu ${\eval($i*16)}($KS), $TMP |
| vaesenc $TMP, $STATE1, $STATE1 |
| vaesenc $TMP, $STATE2, $STATE2 |
| vaesenc $TMP, $STATE3, $STATE3 |
| vaesenc $TMP, $STATE4, $STATE4 |
| ___ |
| }; |
| |
| my $aes_lastround = sub { |
| my ($i) = @_; |
| return <<___; |
| vmovdqu ${\eval($i*16)}($KS), $TMP |
| vaesenclast $TMP, $STATE1, $STATE1 |
| vaesenclast $TMP, $STATE2, $STATE2 |
| vaesenclast $TMP, $STATE3, $STATE3 |
| vaesenclast $TMP, $STATE4, $STATE4 |
| ___ |
| }; |
| |
| # void aes128gcmsiv_enc_msg_x4(unsigned char* PT, unsigned char* CT, |
| # unsigned char* TAG, unsigned char* KS, |
| # size_t byte_len); |
| # parameter 1: %rdi #PT |
| # parameter 2: %rsi #CT |
| # parameter 3: %rdx #TAG [127 126 ... 0] IV=[127...32] |
| # parameter 4: %rcx #KS |
| # parameter 5: %r8 #LEN MSG_length in bytes |
| $code.=<<___; |
| .globl aes128gcmsiv_enc_msg_x4 |
| .type aes128gcmsiv_enc_msg_x4,\@function,5 |
| .align 16 |
| aes128gcmsiv_enc_msg_x4: |
| .cfi_startproc |
| test $LEN, $LEN |
| jnz .L128_enc_msg_x4_start |
| ret |
| |
| .L128_enc_msg_x4_start: |
| pushq %r12 |
| .cfi_push %r12 |
| pushq %r13 |
| .cfi_push %r13 |
| |
| shrq \$4, $LEN # LEN = num of blocks |
| movq $LEN, %r10 |
| shlq \$62, %r10 |
| shrq \$62, %r10 |
| |
| # make IV from TAG |
| vmovdqa ($TAG), $IV |
| vpor OR_MASK(%rip), $IV, $IV #IV = [1]TAG[126...32][00..00] |
| |
| vmovdqu four(%rip), $ADDER # Register to increment counters |
| vmovdqa $IV, $CTR1 # CTR1 = TAG[1][127...32][00..00] |
| vpaddd one(%rip), $IV, $CTR2 # CTR2 = TAG[1][127...32][00..01] |
| vpaddd two(%rip), $IV, $CTR3 # CTR3 = TAG[1][127...32][00..02] |
| vpaddd three(%rip), $IV, $CTR4 # CTR4 = TAG[1][127...32][00..03] |
| |
| shrq \$2, $LEN |
| je .L128_enc_msg_x4_check_remainder |
| |
| subq \$64, $CT |
| subq \$64, $PT |
| |
| .L128_enc_msg_x4_loop1: |
| addq \$64, $CT |
| addq \$64, $PT |
| |
| vmovdqa $CTR1, $STATE1 |
| vmovdqa $CTR2, $STATE2 |
| vmovdqa $CTR3, $STATE3 |
| vmovdqa $CTR4, $STATE4 |
| |
| vpxor ($KS), $STATE1, $STATE1 |
| vpxor ($KS), $STATE2, $STATE2 |
| vpxor ($KS), $STATE3, $STATE3 |
| vpxor ($KS), $STATE4, $STATE4 |
| |
| ${\$aes_round->(1)} |
| vpaddd $ADDER, $CTR1, $CTR1 |
| ${\$aes_round->(2)} |
| vpaddd $ADDER, $CTR2, $CTR2 |
| ${\$aes_round->(3)} |
| vpaddd $ADDER, $CTR3, $CTR3 |
| ${\$aes_round->(4)} |
| vpaddd $ADDER, $CTR4, $CTR4 |
| |
| ${\$aes_round->(5)} |
| ${\$aes_round->(6)} |
| ${\$aes_round->(7)} |
| ${\$aes_round->(8)} |
| ${\$aes_round->(9)} |
| ${\$aes_lastround->(10)} |
| |
| # XOR with Plaintext |
| vpxor 0*16($PT), $STATE1, $STATE1 |
| vpxor 1*16($PT), $STATE2, $STATE2 |
| vpxor 2*16($PT), $STATE3, $STATE3 |
| vpxor 3*16($PT), $STATE4, $STATE4 |
| |
| subq \$1, $LEN |
| |
| vmovdqu $STATE1, 0*16($CT) |
| vmovdqu $STATE2, 1*16($CT) |
| vmovdqu $STATE3, 2*16($CT) |
| vmovdqu $STATE4, 3*16($CT) |
| |
| jne .L128_enc_msg_x4_loop1 |
| |
| addq \$64,$CT |
| addq \$64,$PT |
| |
| .L128_enc_msg_x4_check_remainder: |
| cmpq \$0, %r10 |
| je .L128_enc_msg_x4_out |
| |
| .L128_enc_msg_x4_loop2: |
| # enc each block separately |
| # CTR1 is the highest counter (even if no LOOP done) |
| vmovdqa $CTR1, $STATE1 |
| vpaddd one(%rip), $CTR1, $CTR1 # inc counter |
| |
| vpxor ($KS), $STATE1, $STATE1 |
| vaesenc 16($KS), $STATE1, $STATE1 |
| vaesenc 32($KS), $STATE1, $STATE1 |
| vaesenc 48($KS), $STATE1, $STATE1 |
| vaesenc 64($KS), $STATE1, $STATE1 |
| vaesenc 80($KS), $STATE1, $STATE1 |
| vaesenc 96($KS), $STATE1, $STATE1 |
| vaesenc 112($KS), $STATE1, $STATE1 |
| vaesenc 128($KS), $STATE1, $STATE1 |
| vaesenc 144($KS), $STATE1, $STATE1 |
| vaesenclast 160($KS), $STATE1, $STATE1 |
| |
| # XOR with plaintext |
| vpxor ($PT), $STATE1, $STATE1 |
| vmovdqu $STATE1, ($CT) |
| |
| addq \$16, $PT |
| addq \$16, $CT |
| |
| subq \$1, %r10 |
| jne .L128_enc_msg_x4_loop2 |
| |
| .L128_enc_msg_x4_out: |
| popq %r13 |
| .cfi_pop %r13 |
| popq %r12 |
| .cfi_pop %r12 |
| ret |
| .cfi_endproc |
| .size aes128gcmsiv_enc_msg_x4,.-aes128gcmsiv_enc_msg_x4 |
| ___ |
| } |
| aes128gcmsiv_enc_msg_x4(); |
| |
| sub aes128gcmsiv_enc_msg_x8 { |
| my $STATE1 = "%xmm1"; |
| my $STATE2 = "%xmm2"; |
| my $STATE3 = "%xmm3"; |
| my $STATE4 = "%xmm4"; |
| my $STATE5 = "%xmm5"; |
| my $STATE6 = "%xmm6"; |
| my $STATE7 = "%xmm7"; |
| my $STATE8 = "%xmm8"; |
| |
| my $CTR1 = "%xmm0"; |
| my $CTR2 = "%xmm9"; |
| my $CTR3 = "%xmm10"; |
| my $CTR4 = "%xmm11"; |
| my $CTR5 = "%xmm12"; |
| my $CTR6 = "%xmm13"; |
| my $CTR7 = "%xmm14"; |
| my $SCHED = "%xmm15"; |
| |
| my $TMP1 = "%xmm1"; |
| my $TMP2 = "%xmm2"; |
| |
| my $PT = "%rdi"; |
| my $CT = "%rsi"; |
| my $TAG = "%rdx"; |
| my $KS = "%rcx"; |
| my $LEN = "%r8"; |
| |
| my $aes_round8 = sub { |
| my ($i) = @_; |
| return <<___; |
| vmovdqu ${\eval($i*16)}($KS), $SCHED |
| vaesenc $SCHED, $STATE1, $STATE1 |
| vaesenc $SCHED, $STATE2, $STATE2 |
| vaesenc $SCHED, $STATE3, $STATE3 |
| vaesenc $SCHED, $STATE4, $STATE4 |
| vaesenc $SCHED, $STATE5, $STATE5 |
| vaesenc $SCHED, $STATE6, $STATE6 |
| vaesenc $SCHED, $STATE7, $STATE7 |
| vaesenc $SCHED, $STATE8, $STATE8 |
| ___ |
| }; |
| |
| my $aes_lastround8 = sub { |
| my ($i) = @_; |
| return <<___; |
| vmovdqu ${\eval($i*16)}($KS), $SCHED |
| vaesenclast $SCHED, $STATE1, $STATE1 |
| vaesenclast $SCHED, $STATE2, $STATE2 |
| vaesenclast $SCHED, $STATE3, $STATE3 |
| vaesenclast $SCHED, $STATE4, $STATE4 |
| vaesenclast $SCHED, $STATE5, $STATE5 |
| vaesenclast $SCHED, $STATE6, $STATE6 |
| vaesenclast $SCHED, $STATE7, $STATE7 |
| vaesenclast $SCHED, $STATE8, $STATE8 |
| ___ |
| }; |
| |
| # void ENC_MSG_x8(unsigned char* PT, |
| # unsigned char* CT, |
| # unsigned char* TAG, |
| # unsigned char* KS, |
| # size_t byte_len); |
| # parameter 1: %rdi #PT |
| # parameter 2: %rsi #CT |
| # parameter 3: %rdx #TAG [127 126 ... 0] IV=[127...32] |
| # parameter 4: %rcx #KS |
| # parameter 5: %r8 #LEN MSG_length in bytes |
| $code.=<<___; |
| .globl aes128gcmsiv_enc_msg_x8 |
| .type aes128gcmsiv_enc_msg_x8,\@function,5 |
| .align 16 |
| aes128gcmsiv_enc_msg_x8: |
| .cfi_startproc |
| test $LEN, $LEN |
| jnz .L128_enc_msg_x8_start |
| ret |
| |
| .L128_enc_msg_x8_start: |
| pushq %r12 |
| .cfi_push %r12 |
| pushq %r13 |
| .cfi_push %r13 |
| pushq %rbp |
| .cfi_push %rbp |
| movq %rsp, %rbp |
| .cfi_def_cfa_register rbp |
| |
| # Place in stack |
| subq \$128, %rsp |
| andq \$-64, %rsp |
| |
| shrq \$4, $LEN # LEN = num of blocks |
| movq $LEN, %r10 |
| shlq \$61, %r10 |
| shrq \$61, %r10 |
| |
| # make IV from TAG |
| vmovdqu ($TAG), $TMP1 |
| vpor OR_MASK(%rip), $TMP1, $TMP1 # TMP1= IV = [1]TAG[126...32][00..00] |
| |
| # store counter8 in the stack |
| vpaddd seven(%rip), $TMP1, $CTR1 |
| vmovdqu $CTR1, (%rsp) # CTR8 = TAG[127...32][00..07] |
| vpaddd one(%rip), $TMP1, $CTR2 # CTR2 = TAG[127...32][00..01] |
| vpaddd two(%rip), $TMP1, $CTR3 # CTR3 = TAG[127...32][00..02] |
| vpaddd three(%rip), $TMP1, $CTR4 # CTR4 = TAG[127...32][00..03] |
| vpaddd four(%rip), $TMP1, $CTR5 # CTR5 = TAG[127...32][00..04] |
| vpaddd five(%rip), $TMP1, $CTR6 # CTR6 = TAG[127...32][00..05] |
| vpaddd six(%rip), $TMP1, $CTR7 # CTR7 = TAG[127...32][00..06] |
| vmovdqa $TMP1, $CTR1 # CTR1 = TAG[127...32][00..00] |
| |
| shrq \$3, $LEN |
| je .L128_enc_msg_x8_check_remainder |
| |
| subq \$128, $CT |
| subq \$128, $PT |
| |
| .L128_enc_msg_x8_loop1: |
| addq \$128, $CT |
| addq \$128, $PT |
| |
| vmovdqa $CTR1, $STATE1 |
| vmovdqa $CTR2, $STATE2 |
| vmovdqa $CTR3, $STATE3 |
| vmovdqa $CTR4, $STATE4 |
| vmovdqa $CTR5, $STATE5 |
| vmovdqa $CTR6, $STATE6 |
| vmovdqa $CTR7, $STATE7 |
| # move from stack |
| vmovdqu (%rsp), $STATE8 |
| |
| vpxor ($KS), $STATE1, $STATE1 |
| vpxor ($KS), $STATE2, $STATE2 |
| vpxor ($KS), $STATE3, $STATE3 |
| vpxor ($KS), $STATE4, $STATE4 |
| vpxor ($KS), $STATE5, $STATE5 |
| vpxor ($KS), $STATE6, $STATE6 |
| vpxor ($KS), $STATE7, $STATE7 |
| vpxor ($KS), $STATE8, $STATE8 |
| |
| ${\$aes_round8->(1)} |
| vmovdqu (%rsp), $CTR7 # deal with CTR8 |
| vpaddd eight(%rip), $CTR7, $CTR7 |
| vmovdqu $CTR7, (%rsp) |
| ${\$aes_round8->(2)} |
| vpsubd one(%rip), $CTR7, $CTR7 |
| ${\$aes_round8->(3)} |
| vpaddd eight(%rip), $CTR1, $CTR1 |
| ${\$aes_round8->(4)} |
| vpaddd eight(%rip), $CTR2, $CTR2 |
| ${\$aes_round8->(5)} |
| vpaddd eight(%rip), $CTR3, $CTR3 |
| ${\$aes_round8->(6)} |
| vpaddd eight(%rip), $CTR4, $CTR4 |
| ${\$aes_round8->(7)} |
| vpaddd eight(%rip), $CTR5, $CTR5 |
| ${\$aes_round8->(8)} |
| vpaddd eight(%rip), $CTR6, $CTR6 |
| ${\$aes_round8->(9)} |
| ${\$aes_lastround8->(10)} |
| |
| # XOR with Plaintext |
| vpxor 0*16($PT), $STATE1, $STATE1 |
| vpxor 1*16($PT), $STATE2, $STATE2 |
| vpxor 2*16($PT), $STATE3, $STATE3 |
| vpxor 3*16($PT), $STATE4, $STATE4 |
| vpxor 4*16($PT), $STATE5, $STATE5 |
| vpxor 5*16($PT), $STATE6, $STATE6 |
| vpxor 6*16($PT), $STATE7, $STATE7 |
| vpxor 7*16($PT), $STATE8, $STATE8 |
| |
| dec $LEN |
| |
| vmovdqu $STATE1, 0*16($CT) |
| vmovdqu $STATE2, 1*16($CT) |
| vmovdqu $STATE3, 2*16($CT) |
| vmovdqu $STATE4, 3*16($CT) |
| vmovdqu $STATE5, 4*16($CT) |
| vmovdqu $STATE6, 5*16($CT) |
| vmovdqu $STATE7, 6*16($CT) |
| vmovdqu $STATE8, 7*16($CT) |
| |
| jne .L128_enc_msg_x8_loop1 |
| |
| addq \$128, $CT |
| addq \$128, $PT |
| |
| .L128_enc_msg_x8_check_remainder: |
| cmpq \$0, %r10 |
| je .L128_enc_msg_x8_out |
| |
| .L128_enc_msg_x8_loop2: |
| # enc each block separately |
| # CTR1 is the highest counter (even if no LOOP done) |
| vmovdqa $CTR1, $STATE1 |
| vpaddd one(%rip), $CTR1, $CTR1 # inc counter |
| |
| vpxor ($KS), $STATE1, $STATE1 |
| vaesenc 16($KS), $STATE1, $STATE1 |
| vaesenc 32($KS), $STATE1, $STATE1 |
| vaesenc 48($KS), $STATE1, $STATE1 |
| vaesenc 64($KS), $STATE1, $STATE1 |
| vaesenc 80($KS), $STATE1, $STATE1 |
| vaesenc 96($KS), $STATE1, $STATE1 |
| vaesenc 112($KS), $STATE1, $STATE1 |
| vaesenc 128($KS), $STATE1, $STATE1 |
| vaesenc 144($KS), $STATE1, $STATE1 |
| vaesenclast 160($KS), $STATE1, $STATE1 |
| |
| # XOR with Plaintext |
| vpxor ($PT), $STATE1, $STATE1 |
| |
| vmovdqu $STATE1, ($CT) |
| |
| addq \$16, $PT |
| addq \$16, $CT |
| |
| decq %r10 |
| jne .L128_enc_msg_x8_loop2 |
| |
| .L128_enc_msg_x8_out: |
| movq %rbp, %rsp |
| .cfi_def_cfa_register %rsp |
| popq %rbp |
| .cfi_pop %rbp |
| popq %r13 |
| .cfi_pop %r13 |
| popq %r12 |
| .cfi_pop %r12 |
| ret |
| .cfi_endproc |
| .size aes128gcmsiv_enc_msg_x8,.-aes128gcmsiv_enc_msg_x8 |
| ___ |
| } |
| aes128gcmsiv_enc_msg_x8(); |
| |
| sub aesgcmsiv_dec { |
| my ($aes256) = @_; |
| |
| my $T = "%xmm0"; |
| my $TMP0 = "%xmm1"; |
| my $TMP1 = "%xmm2"; |
| my $TMP2 = "%xmm3"; |
| my $TMP3 = "%xmm4"; |
| my $TMP4 = "%xmm5"; |
| my $TMP5 = "%xmm6"; |
| my $CTR1 = "%xmm7"; |
| my $CTR2 = "%xmm8"; |
| my $CTR3 = "%xmm9"; |
| my $CTR4 = "%xmm10"; |
| my $CTR5 = "%xmm11"; |
| my $CTR6 = "%xmm12"; |
| my $CTR = "%xmm15"; |
| my $CT = "%rdi"; |
| my $PT = "%rsi"; |
| my $POL = "%rdx"; |
| my $Htbl = "%rcx"; |
| my $KS = "%r8"; |
| my $LEN = "%r9"; |
| my $secureBuffer = "%rax"; |
| my $HTABLE_ROUNDS = "%xmm13"; |
| |
| my $labelPrefix = "128"; |
| if ($aes256) { |
| $labelPrefix = "256"; |
| } |
| |
| my $aes_round_dec = sub { |
| my ($i) = @_; |
| return <<___; |
| vmovdqu ${\eval($i*16)}($KS), $TMP3 |
| vaesenc $TMP3, $CTR1, $CTR1 |
| vaesenc $TMP3, $CTR2, $CTR2 |
| vaesenc $TMP3, $CTR3, $CTR3 |
| vaesenc $TMP3, $CTR4, $CTR4 |
| vaesenc $TMP3, $CTR5, $CTR5 |
| vaesenc $TMP3, $CTR6, $CTR6 |
| ___ |
| }; |
| |
| my $aes_lastround_dec = sub { |
| my ($i) = @_; |
| return <<___; |
| vmovdqu ${\eval($i*16)}($KS), $TMP3 |
| vaesenclast $TMP3, $CTR1, $CTR1 |
| vaesenclast $TMP3, $CTR2, $CTR2 |
| vaesenclast $TMP3, $CTR3, $CTR3 |
| vaesenclast $TMP3, $CTR4, $CTR4 |
| vaesenclast $TMP3, $CTR5, $CTR5 |
| vaesenclast $TMP3, $CTR6, $CTR6 |
| ___ |
| }; |
| |
| my $schoolbook = sub { |
| my ($i) = @_; |
| return <<___; |
| vmovdqu ${\eval($i*16-32)}($secureBuffer), $TMP5 |
| vmovdqu ${\eval($i*16-32)}($Htbl), $HTABLE_ROUNDS |
| |
| vpclmulqdq \$0x10, $HTABLE_ROUNDS, $TMP5, $TMP3 |
| vpxor $TMP3, $TMP0, $TMP0 |
| vpclmulqdq \$0x11, $HTABLE_ROUNDS, $TMP5, $TMP3 |
| vpxor $TMP3, $TMP1, $TMP1 |
| vpclmulqdq \$0x00, $HTABLE_ROUNDS, $TMP5, $TMP3 |
| vpxor $TMP3, $TMP2, $TMP2 |
| vpclmulqdq \$0x01, $HTABLE_ROUNDS, $TMP5, $TMP3 |
| vpxor $TMP3, $TMP0, $TMP0 |
| ___ |
| }; |
| |
| if ($aes256) { |
| $code.=<<___; |
| .globl aes256gcmsiv_dec |
| .type aes256gcmsiv_dec,\@function,6 |
| .align 16 |
| aes256gcmsiv_dec: |
| ___ |
| } else { |
| $code.=<<___; |
| .globl aes128gcmsiv_dec |
| .type aes128gcmsiv_dec,\@function,6 |
| .align 16 |
| aes128gcmsiv_dec: |
| ___ |
| } |
| |
| $code.=<<___; |
| .cfi_startproc |
| test \$~15, $LEN |
| jnz .L${labelPrefix}_dec_start |
| ret |
| |
| .L${labelPrefix}_dec_start: |
| vzeroupper |
| vmovdqa ($POL), $T |
| movq $POL, $secureBuffer |
| |
| leaq 32($secureBuffer), $secureBuffer |
| leaq 32($Htbl), $Htbl |
| |
| # make CTRBLKs from given tag. |
| vmovdqu ($CT,$LEN), $CTR |
| vpor OR_MASK(%rip), $CTR, $CTR # CTR = [1]TAG[126...32][00..00] |
| andq \$~15, $LEN |
| |
| # If less then 6 blocks, make singles |
| cmp \$96, $LEN |
| jb .L${labelPrefix}_dec_loop2 |
| |
| # Decrypt the first six blocks |
| sub \$96, $LEN |
| vmovdqa $CTR, $CTR1 |
| vpaddd one(%rip), $CTR1, $CTR2 |
| vpaddd two(%rip), $CTR1, $CTR3 |
| vpaddd one(%rip), $CTR3, $CTR4 |
| vpaddd two(%rip), $CTR3, $CTR5 |
| vpaddd one(%rip), $CTR5, $CTR6 |
| vpaddd two(%rip), $CTR5, $CTR |
| |
| vpxor ($KS), $CTR1, $CTR1 |
| vpxor ($KS), $CTR2, $CTR2 |
| vpxor ($KS), $CTR3, $CTR3 |
| vpxor ($KS), $CTR4, $CTR4 |
| vpxor ($KS), $CTR5, $CTR5 |
| vpxor ($KS), $CTR6, $CTR6 |
| |
| ${\$aes_round_dec->(1)} |
| ${\$aes_round_dec->(2)} |
| ${\$aes_round_dec->(3)} |
| ${\$aes_round_dec->(4)} |
| ${\$aes_round_dec->(5)} |
| ${\$aes_round_dec->(6)} |
| ${\$aes_round_dec->(7)} |
| ${\$aes_round_dec->(8)} |
| ${\$aes_round_dec->(9)} |
| ___ |
| |
| if ($aes256) { |
| $code.=<<___; |
| ${\$aes_round_dec->(10)} |
| ${\$aes_round_dec->(11)} |
| ${\$aes_round_dec->(12)} |
| ${\$aes_round_dec->(13)} |
| ${\$aes_lastround_dec->(14)} |
| ___ |
| } else { |
| $code.=<<___; |
| ${\$aes_lastround_dec->(10)} |
| ___ |
| } |
| |
| $code.=<<___; |
| # XOR with CT |
| vpxor 0*16($CT), $CTR1, $CTR1 |
| vpxor 1*16($CT), $CTR2, $CTR2 |
| vpxor 2*16($CT), $CTR3, $CTR3 |
| vpxor 3*16($CT), $CTR4, $CTR4 |
| vpxor 4*16($CT), $CTR5, $CTR5 |
| vpxor 5*16($CT), $CTR6, $CTR6 |
| |
| vmovdqu $CTR1, 0*16($PT) |
| vmovdqu $CTR2, 1*16($PT) |
| vmovdqu $CTR3, 2*16($PT) |
| vmovdqu $CTR4, 3*16($PT) |
| vmovdqu $CTR5, 4*16($PT) |
| vmovdqu $CTR6, 5*16($PT) |
| |
| addq \$96, $CT |
| addq \$96, $PT |
| jmp .L${labelPrefix}_dec_loop1 |
| |
| # Decrypt 6 blocks each time while hashing previous 6 blocks |
| .align 64 |
| .L${labelPrefix}_dec_loop1: |
| cmp \$96, $LEN |
| jb .L${labelPrefix}_dec_finish_96 |
| sub \$96, $LEN |
| |
| vmovdqa $CTR6, $TMP5 |
| vmovdqa $CTR5, 1*16-32($secureBuffer) |
| vmovdqa $CTR4, 2*16-32($secureBuffer) |
| vmovdqa $CTR3, 3*16-32($secureBuffer) |
| vmovdqa $CTR2, 4*16-32($secureBuffer) |
| vmovdqa $CTR1, 5*16-32($secureBuffer) |
| |
| vmovdqa $CTR, $CTR1 |
| vpaddd one(%rip), $CTR1, $CTR2 |
| vpaddd two(%rip), $CTR1, $CTR3 |
| vpaddd one(%rip), $CTR3, $CTR4 |
| vpaddd two(%rip), $CTR3, $CTR5 |
| vpaddd one(%rip), $CTR5, $CTR6 |
| vpaddd two(%rip), $CTR5, $CTR |
| |
| vmovdqa ($KS), $TMP3 |
| vpxor $TMP3, $CTR1, $CTR1 |
| vpxor $TMP3, $CTR2, $CTR2 |
| vpxor $TMP3, $CTR3, $CTR3 |
| vpxor $TMP3, $CTR4, $CTR4 |
| vpxor $TMP3, $CTR5, $CTR5 |
| vpxor $TMP3, $CTR6, $CTR6 |
| |
| vmovdqu 0*16-32($Htbl), $TMP3 |
| vpclmulqdq \$0x11, $TMP3, $TMP5, $TMP1 |
| vpclmulqdq \$0x00, $TMP3, $TMP5, $TMP2 |
| vpclmulqdq \$0x01, $TMP3, $TMP5, $TMP0 |
| vpclmulqdq \$0x10, $TMP3, $TMP5, $TMP3 |
| vpxor $TMP3, $TMP0, $TMP0 |
| |
| ${\$aes_round_dec->(1)} |
| ${\$schoolbook->(1)} |
| |
| ${\$aes_round_dec->(2)} |
| ${\$schoolbook->(2)} |
| |
| ${\$aes_round_dec->(3)} |
| ${\$schoolbook->(3)} |
| |
| ${\$aes_round_dec->(4)} |
| ${\$schoolbook->(4)} |
| |
| ${\$aes_round_dec->(5)} |
| ${\$aes_round_dec->(6)} |
| ${\$aes_round_dec->(7)} |
| |
| vmovdqa 5*16-32($secureBuffer), $TMP5 |
| vpxor $T, $TMP5, $TMP5 |
| vmovdqu 5*16-32($Htbl), $TMP4 |
| |
| vpclmulqdq \$0x01, $TMP4, $TMP5, $TMP3 |
| vpxor $TMP3, $TMP0, $TMP0 |
| vpclmulqdq \$0x11, $TMP4, $TMP5, $TMP3 |
| vpxor $TMP3, $TMP1, $TMP1 |
| vpclmulqdq \$0x00, $TMP4, $TMP5, $TMP3 |
| vpxor $TMP3, $TMP2, $TMP2 |
| vpclmulqdq \$0x10, $TMP4, $TMP5, $TMP3 |
| vpxor $TMP3, $TMP0, $TMP0 |
| |
| ${\$aes_round_dec->(8)} |
| |
| vpsrldq \$8, $TMP0, $TMP3 |
| vpxor $TMP3, $TMP1, $TMP4 |
| vpslldq \$8, $TMP0, $TMP3 |
| vpxor $TMP3, $TMP2, $T |
| |
| vmovdqa poly(%rip), $TMP2 |
| |
| ${\$aes_round_dec->(9)} |
| ___ |
| |
| if ($aes256) { |
| $code.=<<___; |
| ${\$aes_round_dec->(10)} |
| ${\$aes_round_dec->(11)} |
| ${\$aes_round_dec->(12)} |
| ${\$aes_round_dec->(13)} |
| vmovdqu 14*16($KS), $TMP5 |
| ___ |
| } else { |
| $code.=<<___; |
| vmovdqu 10*16($KS), $TMP5 |
| ___ |
| } |
| |
| $code.=<<___; |
| vpalignr \$8, $T, $T, $TMP1 |
| vpclmulqdq \$0x10, $TMP2, $T, $T |
| vpxor $T, $TMP1, $T |
| |
| vpxor 0*16($CT), $TMP5, $TMP3 |
| vaesenclast $TMP3, $CTR1, $CTR1 |
| vpxor 1*16($CT), $TMP5, $TMP3 |
| vaesenclast $TMP3, $CTR2, $CTR2 |
| vpxor 2*16($CT), $TMP5, $TMP3 |
| vaesenclast $TMP3, $CTR3, $CTR3 |
| vpxor 3*16($CT), $TMP5, $TMP3 |
| vaesenclast $TMP3, $CTR4, $CTR4 |
| vpxor 4*16($CT), $TMP5, $TMP3 |
| vaesenclast $TMP3, $CTR5, $CTR5 |
| vpxor 5*16($CT), $TMP5, $TMP3 |
| vaesenclast $TMP3, $CTR6, $CTR6 |
| |
| vpalignr \$8, $T, $T, $TMP1 |
| vpclmulqdq \$0x10, $TMP2, $T, $T |
| vpxor $T, $TMP1, $T |
| |
| vmovdqu $CTR1, 0*16($PT) |
| vmovdqu $CTR2, 1*16($PT) |
| vmovdqu $CTR3, 2*16($PT) |
| vmovdqu $CTR4, 3*16($PT) |
| vmovdqu $CTR5, 4*16($PT) |
| vmovdqu $CTR6, 5*16($PT) |
| |
| vpxor $TMP4, $T, $T |
| |
| lea 96($CT), $CT |
| lea 96($PT), $PT |
| jmp .L${labelPrefix}_dec_loop1 |
| |
| .L${labelPrefix}_dec_finish_96: |
| vmovdqa $CTR6, $TMP5 |
| vmovdqa $CTR5, 1*16-32($secureBuffer) |
| vmovdqa $CTR4, 2*16-32($secureBuffer) |
| vmovdqa $CTR3, 3*16-32($secureBuffer) |
| vmovdqa $CTR2, 4*16-32($secureBuffer) |
| vmovdqa $CTR1, 5*16-32($secureBuffer) |
| |
| vmovdqu 0*16-32($Htbl), $TMP3 |
| vpclmulqdq \$0x10, $TMP3, $TMP5, $TMP0 |
| vpclmulqdq \$0x11, $TMP3, $TMP5, $TMP1 |
| vpclmulqdq \$0x00, $TMP3, $TMP5, $TMP2 |
| vpclmulqdq \$0x01, $TMP3, $TMP5, $TMP3 |
| vpxor $TMP3, $TMP0, $TMP0 |
| |
| ${\$schoolbook->(1)} |
| ${\$schoolbook->(2)} |
| ${\$schoolbook->(3)} |
| ${\$schoolbook->(4)} |
| |
| vmovdqu 5*16-32($secureBuffer), $TMP5 |
| vpxor $T, $TMP5, $TMP5 |
| vmovdqu 5*16-32($Htbl), $TMP4 |
| vpclmulqdq \$0x11, $TMP4, $TMP5, $TMP3 |
| vpxor $TMP3, $TMP1, $TMP1 |
| vpclmulqdq \$0x00, $TMP4, $TMP5, $TMP3 |
| vpxor $TMP3, $TMP2, $TMP2 |
| vpclmulqdq \$0x10, $TMP4, $TMP5, $TMP3 |
| vpxor $TMP3, $TMP0, $TMP0 |
| vpclmulqdq \$0x01, $TMP4, $TMP5, $TMP3 |
| vpxor $TMP3, $TMP0, $TMP0 |
| |
| vpsrldq \$8, $TMP0, $TMP3 |
| vpxor $TMP3, $TMP1, $TMP4 |
| vpslldq \$8, $TMP0, $TMP3 |
| vpxor $TMP3, $TMP2, $T |
| |
| vmovdqa poly(%rip), $TMP2 |
| |
| vpalignr \$8, $T, $T, $TMP1 |
| vpclmulqdq \$0x10, $TMP2, $T, $T |
| vpxor $T, $TMP1, $T |
| |
| vpalignr \$8, $T, $T, $TMP1 |
| vpclmulqdq \$0x10, $TMP2, $T, $T |
| vpxor $T, $TMP1, $T |
| |
| vpxor $TMP4, $T, $T |
| |
| .L${labelPrefix}_dec_loop2: |
| # Here we encrypt any remaining whole block |
| |
| # if there are no whole blocks |
| cmp \$16, $LEN |
| jb .L${labelPrefix}_dec_out |
| sub \$16, $LEN |
| |
| vmovdqa $CTR, $TMP1 |
| vpaddd one(%rip), $CTR, $CTR |
| |
| vpxor 0*16($KS), $TMP1, $TMP1 |
| vaesenc 1*16($KS), $TMP1, $TMP1 |
| vaesenc 2*16($KS), $TMP1, $TMP1 |
| vaesenc 3*16($KS), $TMP1, $TMP1 |
| vaesenc 4*16($KS), $TMP1, $TMP1 |
| vaesenc 5*16($KS), $TMP1, $TMP1 |
| vaesenc 6*16($KS), $TMP1, $TMP1 |
| vaesenc 7*16($KS), $TMP1, $TMP1 |
| vaesenc 8*16($KS), $TMP1, $TMP1 |
| vaesenc 9*16($KS), $TMP1, $TMP1 |
| ___ |
| if ($aes256) { |
| $code.=<<___; |
| vaesenc 10*16($KS), $TMP1, $TMP1 |
| vaesenc 11*16($KS), $TMP1, $TMP1 |
| vaesenc 12*16($KS), $TMP1, $TMP1 |
| vaesenc 13*16($KS), $TMP1, $TMP1 |
| vaesenclast 14*16($KS), $TMP1, $TMP1 |
| ___ |
| } else { |
| $code.=<<___; |
| vaesenclast 10*16($KS), $TMP1, $TMP1 |
| ___ |
| } |
| |
| $code.=<<___; |
| vpxor ($CT), $TMP1, $TMP1 |
| vmovdqu $TMP1, ($PT) |
| addq \$16, $CT |
| addq \$16, $PT |
| |
| vpxor $TMP1, $T, $T |
| vmovdqa -32($Htbl), $TMP0 |
| call GFMUL |
| |
| jmp .L${labelPrefix}_dec_loop2 |
| |
| .L${labelPrefix}_dec_out: |
| vmovdqu $T, ($POL) |
| ret |
| .cfi_endproc |
| ___ |
| |
| if ($aes256) { |
| $code.=<<___; |
| .size aes256gcmsiv_dec, .-aes256gcmsiv_dec |
| ___ |
| } else { |
| $code.=<<___; |
| .size aes128gcmsiv_dec, .-aes128gcmsiv_dec |
| ___ |
| } |
| } |
| |
| aesgcmsiv_dec(0); # emit 128-bit version |
| |
| sub aes128gcmsiv_ecb_enc_block { |
| my $STATE_1 = "%xmm1"; |
| my $KSp = "%rdx"; |
| |
| # parameter 1: PT %rdi (pointer to 128 bit) |
| # parameter 2: CT %rsi (pointer to 128 bit) |
| # parameter 3: ks %rdx (pointer to ks) |
| $code.=<<___; |
| .globl aes128gcmsiv_ecb_enc_block |
| .type aes128gcmsiv_ecb_enc_block,\@function,3 |
| .align 16 |
| aes128gcmsiv_ecb_enc_block: |
| .cfi_startproc |
| vmovdqa (%rdi), $STATE_1 |
| |
| vpxor ($KSp), $STATE_1, $STATE_1 |
| vaesenc 1*16($KSp), $STATE_1, $STATE_1 |
| vaesenc 2*16($KSp), $STATE_1, $STATE_1 |
| vaesenc 3*16($KSp), $STATE_1, $STATE_1 |
| vaesenc 4*16($KSp), $STATE_1, $STATE_1 |
| vaesenc 5*16($KSp), $STATE_1, $STATE_1 |
| vaesenc 6*16($KSp), $STATE_1, $STATE_1 |
| vaesenc 7*16($KSp), $STATE_1, $STATE_1 |
| vaesenc 8*16($KSp), $STATE_1, $STATE_1 |
| vaesenc 9*16($KSp), $STATE_1, $STATE_1 |
| vaesenclast 10*16($KSp), $STATE_1, $STATE_1 # STATE_1 == IV |
| |
| vmovdqa $STATE_1, (%rsi) |
| |
| ret |
| .cfi_endproc |
| .size aes128gcmsiv_ecb_enc_block,.-aes128gcmsiv_ecb_enc_block |
| ___ |
| } |
| aes128gcmsiv_ecb_enc_block(); |
| |
| sub aes256gcmsiv_aes_ks_enc_x1 { |
| my $KS = "%rdx"; |
| my $KEYp = "%rcx"; |
| my $CON_MASK = "%xmm0"; |
| my $MASK_256 = "%xmm15"; |
| my $KEY_1 = "%xmm1"; |
| my $KEY_2 = "%xmm3"; |
| my $BLOCK1 = "%xmm8"; |
| my $AUX_REG = "%xmm14"; |
| my $PT = "%rdi"; |
| my $CT = "%rsi"; |
| |
| my $round_double = sub { |
| my ($i, $j) = @_; |
| return <<___; |
| vpshufb %xmm15, %xmm3, %xmm2 |
| vaesenclast %xmm0, %xmm2, %xmm2 |
| vpslld \$1, %xmm0, %xmm0 |
| vpslldq \$4, %xmm1, %xmm4 |
| vpxor %xmm4, %xmm1, %xmm1 |
| vpslldq \$4, %xmm4, %xmm4 |
| vpxor %xmm4, %xmm1, %xmm1 |
| vpslldq \$4, %xmm4, %xmm4 |
| vpxor %xmm4, %xmm1, %xmm1 |
| vpxor %xmm2, %xmm1, %xmm1 |
| vaesenc %xmm1, $BLOCK1, $BLOCK1 |
| vmovdqu %xmm1, ${\eval(16*$i)}($KS) |
| |
| vpshufd \$0xff, %xmm1, %xmm2 |
| vaesenclast %xmm14, %xmm2, %xmm2 |
| vpslldq \$4, %xmm3, %xmm4 |
| vpxor %xmm4, %xmm3, %xmm3 |
| vpslldq \$4, %xmm4, %xmm4 |
| vpxor %xmm4, %xmm3, %xmm3 |
| vpslldq \$4, %xmm4, %xmm4 |
| vpxor %xmm4, %xmm3, %xmm3 |
| vpxor %xmm2, %xmm3, %xmm3 |
| vaesenc %xmm3, $BLOCK1, $BLOCK1 |
| vmovdqu %xmm3, ${\eval(16*$j)}($KS) |
| ___ |
| }; |
| |
| my $round_last = sub { |
| my ($i) = @_; |
| return <<___; |
| vpshufb %xmm15, %xmm3, %xmm2 |
| vaesenclast %xmm0, %xmm2, %xmm2 |
| vpslldq \$4, %xmm1, %xmm4 |
| vpxor %xmm4, %xmm1, %xmm1 |
| vpslldq \$4, %xmm4, %xmm4 |
| vpxor %xmm4, %xmm1, %xmm1 |
| vpslldq \$4, %xmm4, %xmm4 |
| vpxor %xmm4, %xmm1, %xmm1 |
| vpxor %xmm2, %xmm1, %xmm1 |
| vaesenclast %xmm1, $BLOCK1, $BLOCK1 |
| vmovdqu %xmm1, ${\eval(16*$i)}($KS) |
| ___ |
| }; |
| |
| # parameter 1: %rdi Pointer to PT1 |
| # parameter 2: %rsi Pointer to CT1 |
| # parameter 3: %rdx Pointer to KS |
| # parameter 4: %rcx Pointer to initial key |
| $code.=<<___; |
| .globl aes256gcmsiv_aes_ks_enc_x1 |
| .type aes256gcmsiv_aes_ks_enc_x1,\@function,4 |
| .align 16 |
| aes256gcmsiv_aes_ks_enc_x1: |
| .cfi_startproc |
| vmovdqa con1(%rip), $CON_MASK # CON_MASK = 1,1,1,1 |
| vmovdqa mask(%rip), $MASK_256 # MASK_256 |
| vmovdqa ($PT), $BLOCK1 |
| vmovdqa ($KEYp), $KEY_1 # KEY_1 || KEY_2 [0..7] = user key |
| vmovdqa 16($KEYp), $KEY_2 |
| vpxor $KEY_1, $BLOCK1, $BLOCK1 |
| vaesenc $KEY_2, $BLOCK1, $BLOCK1 |
| vmovdqu $KEY_1, ($KS) # First round key |
| vmovdqu $KEY_2, 16($KS) |
| vpxor $AUX_REG, $AUX_REG, $AUX_REG |
| |
| ${\$round_double->(2, 3)} |
| ${\$round_double->(4, 5)} |
| ${\$round_double->(6, 7)} |
| ${\$round_double->(8, 9)} |
| ${\$round_double->(10, 11)} |
| ${\$round_double->(12, 13)} |
| ${\$round_last->(14)} |
| vmovdqa $BLOCK1, ($CT) |
| ret |
| .cfi_endproc |
| .size aes256gcmsiv_aes_ks_enc_x1,.-aes256gcmsiv_aes_ks_enc_x1 |
| ___ |
| } |
| aes256gcmsiv_aes_ks_enc_x1(); |
| |
| sub aes256gcmsiv_ecb_enc_block { |
| my $STATE_1 = "%xmm1"; |
| my $PT = "%rdi"; |
| my $CT = "%rsi"; |
| my $KSp = "%rdx"; |
| |
| # parameter 1: PT %rdi (pointer to 128 bit) |
| # parameter 2: CT %rsi (pointer to 128 bit) |
| # parameter 3: ks %rdx (pointer to ks) |
| $code.=<<___; |
| .globl aes256gcmsiv_ecb_enc_block |
| .type aes256gcmsiv_ecb_enc_block,\@function,3 |
| .align 16 |
| aes256gcmsiv_ecb_enc_block: |
| .cfi_startproc |
| vmovdqa (%rdi), $STATE_1 |
| vpxor ($KSp), $STATE_1, $STATE_1 |
| vaesenc 1*16($KSp), $STATE_1, $STATE_1 |
| vaesenc 2*16($KSp), $STATE_1, $STATE_1 |
| vaesenc 3*16($KSp), $STATE_1, $STATE_1 |
| vaesenc 4*16($KSp), $STATE_1, $STATE_1 |
| vaesenc 5*16($KSp), $STATE_1, $STATE_1 |
| vaesenc 6*16($KSp), $STATE_1, $STATE_1 |
| vaesenc 7*16($KSp), $STATE_1, $STATE_1 |
| vaesenc 8*16($KSp), $STATE_1, $STATE_1 |
| vaesenc 9*16($KSp), $STATE_1, $STATE_1 |
| vaesenc 10*16($KSp), $STATE_1, $STATE_1 |
| vaesenc 11*16($KSp), $STATE_1, $STATE_1 |
| vaesenc 12*16($KSp), $STATE_1, $STATE_1 |
| vaesenc 13*16($KSp), $STATE_1, $STATE_1 |
| vaesenclast 14*16($KSp), $STATE_1, $STATE_1 # $STATE_1 == IV |
| vmovdqa $STATE_1, (%rsi) |
| ret |
| .cfi_endproc |
| .size aes256gcmsiv_ecb_enc_block,.-aes256gcmsiv_ecb_enc_block |
| ___ |
| } |
| aes256gcmsiv_ecb_enc_block(); |
| |
| sub aes256gcmsiv_enc_msg_x4 { |
| my $CTR1 = "%xmm0"; |
| my $CTR2 = "%xmm1"; |
| my $CTR3 = "%xmm2"; |
| my $CTR4 = "%xmm3"; |
| my $ADDER = "%xmm4"; |
| |
| my $STATE1 = "%xmm5"; |
| my $STATE2 = "%xmm6"; |
| my $STATE3 = "%xmm7"; |
| my $STATE4 = "%xmm8"; |
| |
| my $TMP = "%xmm12"; |
| my $TMP2 = "%xmm13"; |
| my $TMP3 = "%xmm14"; |
| my $IV = "%xmm15"; |
| |
| my $PT = "%rdi"; |
| my $CT = "%rsi"; |
| my $TAG = "%rdx"; |
| my $KS = "%rcx"; |
| my $LEN = "%r8"; |
| |
| my $aes_round = sub { |
| my ($i) = @_; |
| return <<___; |
| vmovdqu ${\eval($i*16)}($KS), $TMP |
| vaesenc $TMP, $STATE1, $STATE1 |
| vaesenc $TMP, $STATE2, $STATE2 |
| vaesenc $TMP, $STATE3, $STATE3 |
| vaesenc $TMP, $STATE4, $STATE4 |
| ___ |
| }; |
| |
| my $aes_lastround = sub { |
| my ($i) = @_; |
| return <<___; |
| vmovdqu ${\eval($i*16)}($KS), $TMP |
| vaesenclast $TMP, $STATE1, $STATE1 |
| vaesenclast $TMP, $STATE2, $STATE2 |
| vaesenclast $TMP, $STATE3, $STATE3 |
| vaesenclast $TMP, $STATE4, $STATE4 |
| ___ |
| }; |
| |
| # void aes256gcmsiv_enc_msg_x4(unsigned char* PT, unsigned char* CT, |
| # unsigned char* TAG, unsigned char* KS, |
| # size_t byte_len); |
| # parameter 1: %rdi #PT |
| # parameter 2: %rsi #CT |
| # parameter 3: %rdx #TAG [127 126 ... 0] IV=[127...32] |
| # parameter 4: %rcx #KS |
| # parameter 5: %r8 #LEN MSG_length in bytes |
| $code.=<<___; |
| .globl aes256gcmsiv_enc_msg_x4 |
| .type aes256gcmsiv_enc_msg_x4,\@function,5 |
| .align 16 |
| aes256gcmsiv_enc_msg_x4: |
| .cfi_startproc |
| test $LEN, $LEN |
| jnz .L256_enc_msg_x4_start |
| ret |
| |
| .L256_enc_msg_x4_start: |
| movq $LEN, %r10 |
| shrq \$4, $LEN # LEN = num of blocks |
| shlq \$60, %r10 |
| jz .L256_enc_msg_x4_start2 |
| addq \$1, $LEN |
| |
| .L256_enc_msg_x4_start2: |
| movq $LEN, %r10 |
| shlq \$62, %r10 |
| shrq \$62, %r10 |
| |
| # make IV from TAG |
| vmovdqa ($TAG), $IV |
| vpor OR_MASK(%rip), $IV, $IV # IV = [1]TAG[126...32][00..00] |
| |
| vmovdqa four(%rip), $ADDER # Register to increment counters |
| vmovdqa $IV, $CTR1 # CTR1 = TAG[1][127...32][00..00] |
| vpaddd one(%rip), $IV, $CTR2 # CTR2 = TAG[1][127...32][00..01] |
| vpaddd two(%rip), $IV, $CTR3 # CTR3 = TAG[1][127...32][00..02] |
| vpaddd three(%rip), $IV, $CTR4 # CTR4 = TAG[1][127...32][00..03] |
| |
| shrq \$2, $LEN |
| je .L256_enc_msg_x4_check_remainder |
| |
| subq \$64, $CT |
| subq \$64, $PT |
| |
| .L256_enc_msg_x4_loop1: |
| addq \$64, $CT |
| addq \$64, $PT |
| |
| vmovdqa $CTR1, $STATE1 |
| vmovdqa $CTR2, $STATE2 |
| vmovdqa $CTR3, $STATE3 |
| vmovdqa $CTR4, $STATE4 |
| |
| vpxor ($KS), $STATE1, $STATE1 |
| vpxor ($KS), $STATE2, $STATE2 |
| vpxor ($KS), $STATE3, $STATE3 |
| vpxor ($KS), $STATE4, $STATE4 |
| |
| ${\$aes_round->(1)} |
| vpaddd $ADDER, $CTR1, $CTR1 |
| ${\$aes_round->(2)} |
| vpaddd $ADDER, $CTR2, $CTR2 |
| ${\$aes_round->(3)} |
| vpaddd $ADDER, $CTR3, $CTR3 |
| ${\$aes_round->(4)} |
| vpaddd $ADDER, $CTR4, $CTR4 |
| |
| ${\$aes_round->(5)} |
| ${\$aes_round->(6)} |
| ${\$aes_round->(7)} |
| ${\$aes_round->(8)} |
| ${\$aes_round->(9)} |
| ${\$aes_round->(10)} |
| ${\$aes_round->(11)} |
| ${\$aes_round->(12)} |
| ${\$aes_round->(13)} |
| ${\$aes_lastround->(14)} |
| |
| # XOR with Plaintext |
| vpxor 0*16($PT), $STATE1, $STATE1 |
| vpxor 1*16($PT), $STATE2, $STATE2 |
| vpxor 2*16($PT), $STATE3, $STATE3 |
| vpxor 3*16($PT), $STATE4, $STATE4 |
| |
| subq \$1, $LEN |
| |
| vmovdqu $STATE1, 0*16($CT) |
| vmovdqu $STATE2, 1*16($CT) |
| vmovdqu $STATE3, 2*16($CT) |
| vmovdqu $STATE4, 3*16($CT) |
| |
| jne .L256_enc_msg_x4_loop1 |
| |
| addq \$64, $CT |
| addq \$64, $PT |
| |
| .L256_enc_msg_x4_check_remainder: |
| cmpq \$0, %r10 |
| je .L256_enc_msg_x4_out |
| |
| .L256_enc_msg_x4_loop2: |
| # encrypt each block separately |
| # CTR1 is the highest counter (even if no LOOP done) |
| |
| vmovdqa $CTR1, $STATE1 |
| vpaddd one(%rip), $CTR1, $CTR1 # inc counter |
| vpxor ($KS), $STATE1, $STATE1 |
| vaesenc 16($KS), $STATE1, $STATE1 |
| vaesenc 32($KS), $STATE1, $STATE1 |
| vaesenc 48($KS), $STATE1, $STATE1 |
| vaesenc 64($KS), $STATE1, $STATE1 |
| vaesenc 80($KS), $STATE1, $STATE1 |
| vaesenc 96($KS), $STATE1, $STATE1 |
| vaesenc 112($KS), $STATE1, $STATE1 |
| vaesenc 128($KS), $STATE1, $STATE1 |
| vaesenc 144($KS), $STATE1, $STATE1 |
| vaesenc 160($KS), $STATE1, $STATE1 |
| vaesenc 176($KS), $STATE1, $STATE1 |
| vaesenc 192($KS), $STATE1, $STATE1 |
| vaesenc 208($KS), $STATE1, $STATE1 |
| vaesenclast 224($KS), $STATE1, $STATE1 |
| |
| # XOR with Plaintext |
| vpxor ($PT), $STATE1, $STATE1 |
| |
| vmovdqu $STATE1, ($CT) |
| |
| addq \$16, $PT |
| addq \$16, $CT |
| |
| subq \$1, %r10 |
| jne .L256_enc_msg_x4_loop2 |
| |
| .L256_enc_msg_x4_out: |
| ret |
| .cfi_endproc |
| .size aes256gcmsiv_enc_msg_x4,.-aes256gcmsiv_enc_msg_x4 |
| ___ |
| } |
| aes256gcmsiv_enc_msg_x4(); |
| |
| sub aes256gcmsiv_enc_msg_x8() { |
| my $STATE1 = "%xmm1"; |
| my $STATE2 = "%xmm2"; |
| my $STATE3 = "%xmm3"; |
| my $STATE4 = "%xmm4"; |
| my $STATE5 = "%xmm5"; |
| my $STATE6 = "%xmm6"; |
| my $STATE7 = "%xmm7"; |
| my $STATE8 = "%xmm8"; |
| my $CTR1 = "%xmm0"; |
| my $CTR2 = "%xmm9"; |
| my $CTR3 = "%xmm10"; |
| my $CTR4 = "%xmm11"; |
| my $CTR5 = "%xmm12"; |
| my $CTR6 = "%xmm13"; |
| my $CTR7 = "%xmm14"; |
| my $TMP1 = "%xmm1"; |
| my $TMP2 = "%xmm2"; |
| my $KS = "%rcx"; |
| my $LEN = "%r8"; |
| my $PT = "%rdi"; |
| my $CT = "%rsi"; |
| my $TAG = "%rdx"; |
| my $SCHED = "%xmm15"; |
| |
| my $aes_round8 = sub { |
| my ($i) = @_; |
| return <<___; |
| vmovdqu ${\eval($i*16)}($KS), $SCHED |
| vaesenc $SCHED, $STATE1, $STATE1 |
| vaesenc $SCHED, $STATE2, $STATE2 |
| vaesenc $SCHED, $STATE3, $STATE3 |
| vaesenc $SCHED, $STATE4, $STATE4 |
| vaesenc $SCHED, $STATE5, $STATE5 |
| vaesenc $SCHED, $STATE6, $STATE6 |
| vaesenc $SCHED, $STATE7, $STATE7 |
| vaesenc $SCHED, $STATE8, $STATE8 |
| ___ |
| }; |
| |
| my $aes_lastround8 = sub { |
| my ($i) = @_; |
| return <<___; |
| vmovdqu ${\eval($i*16)}($KS), $SCHED |
| vaesenclast $SCHED, $STATE1, $STATE1 |
| vaesenclast $SCHED, $STATE2, $STATE2 |
| vaesenclast $SCHED, $STATE3, $STATE3 |
| vaesenclast $SCHED, $STATE4, $STATE4 |
| vaesenclast $SCHED, $STATE5, $STATE5 |
| vaesenclast $SCHED, $STATE6, $STATE6 |
| vaesenclast $SCHED, $STATE7, $STATE7 |
| vaesenclast $SCHED, $STATE8, $STATE8 |
| ___ |
| }; |
| |
| # void ENC_MSG_x8(unsigned char* PT, |
| # unsigned char* CT, |
| # unsigned char* TAG, |
| # unsigned char* KS, |
| # size_t byte_len); |
| # parameter 1: %rdi #PT |
| # parameter 2: %rsi #CT |
| # parameter 3: %rdx #TAG [127 126 ... 0] IV=[127...32] |
| # parameter 4: %rcx #KS |
| # parameter 5: %r8 #LEN MSG_length in bytes |
| $code.=<<___; |
| .globl aes256gcmsiv_enc_msg_x8 |
| .type aes256gcmsiv_enc_msg_x8,\@function,5 |
| .align 16 |
| aes256gcmsiv_enc_msg_x8: |
| .cfi_startproc |
| test $LEN, $LEN |
| jnz .L256_enc_msg_x8_start |
| ret |
| |
| .L256_enc_msg_x8_start: |
| # Place in stack |
| movq %rsp, %r11 |
| subq \$16, %r11 |
| andq \$-64, %r11 |
| |
| movq $LEN, %r10 |
| shrq \$4, $LEN # LEN = num of blocks |
| shlq \$60, %r10 |
| jz .L256_enc_msg_x8_start2 |
| addq \$1, $LEN |
| |
| .L256_enc_msg_x8_start2: |
| movq $LEN, %r10 |
| shlq \$61, %r10 |
| shrq \$61, %r10 |
| |
| # Make IV from TAG |
| vmovdqa ($TAG), $TMP1 |
| vpor OR_MASK(%rip), $TMP1, $TMP1 # TMP1= IV = [1]TAG[126...32][00..00] |
| |
| # store counter8 on the stack |
| vpaddd seven(%rip), $TMP1, $CTR1 |
| vmovdqa $CTR1, (%r11) # CTR8 = TAG[127...32][00..07] |
| vpaddd one(%rip), $TMP1, $CTR2 # CTR2 = TAG[127...32][00..01] |
| vpaddd two(%rip), $TMP1, $CTR3 # CTR3 = TAG[127...32][00..02] |
| vpaddd three(%rip), $TMP1, $CTR4 # CTR4 = TAG[127...32][00..03] |
| vpaddd four(%rip), $TMP1, $CTR5 # CTR5 = TAG[127...32][00..04] |
| vpaddd five(%rip), $TMP1, $CTR6 # CTR6 = TAG[127...32][00..05] |
| vpaddd six(%rip), $TMP1, $CTR7 # CTR7 = TAG[127...32][00..06] |
| vmovdqa $TMP1, $CTR1 # CTR1 = TAG[127...32][00..00] |
| |
| shrq \$3, $LEN |
| jz .L256_enc_msg_x8_check_remainder |
| |
| subq \$128, $CT |
| subq \$128, $PT |
| |
| .L256_enc_msg_x8_loop1: |
| addq \$128, $CT |
| addq \$128, $PT |
| |
| vmovdqa $CTR1, $STATE1 |
| vmovdqa $CTR2, $STATE2 |
| vmovdqa $CTR3, $STATE3 |
| vmovdqa $CTR4, $STATE4 |
| vmovdqa $CTR5, $STATE5 |
| vmovdqa $CTR6, $STATE6 |
| vmovdqa $CTR7, $STATE7 |
| # move from stack |
| vmovdqa (%r11), $STATE8 |
| |
| vpxor ($KS), $STATE1, $STATE1 |
| vpxor ($KS), $STATE2, $STATE2 |
| vpxor ($KS), $STATE3, $STATE3 |
| vpxor ($KS), $STATE4, $STATE4 |
| vpxor ($KS), $STATE5, $STATE5 |
| vpxor ($KS), $STATE6, $STATE6 |
| vpxor ($KS), $STATE7, $STATE7 |
| vpxor ($KS), $STATE8, $STATE8 |
| |
| ${\$aes_round8->(1)} |
| vmovdqa (%r11), $CTR7 # deal with CTR8 |
| vpaddd eight(%rip), $CTR7, $CTR7 |
| vmovdqa $CTR7, (%r11) |
| ${\$aes_round8->(2)} |
| vpsubd one(%rip), $CTR7, $CTR7 |
| ${\$aes_round8->(3)} |
| vpaddd eight(%rip), $CTR1, $CTR1 |
| ${\$aes_round8->(4)} |
| vpaddd eight(%rip), $CTR2, $CTR2 |
| ${\$aes_round8->(5)} |
| vpaddd eight(%rip), $CTR3, $CTR3 |
| ${\$aes_round8->(6)} |
| vpaddd eight(%rip), $CTR4, $CTR4 |
| ${\$aes_round8->(7)} |
| vpaddd eight(%rip), $CTR5, $CTR5 |
| ${\$aes_round8->(8)} |
| vpaddd eight(%rip), $CTR6, $CTR6 |
| ${\$aes_round8->(9)} |
| ${\$aes_round8->(10)} |
| ${\$aes_round8->(11)} |
| ${\$aes_round8->(12)} |
| ${\$aes_round8->(13)} |
| ${\$aes_lastround8->(14)} |
| |
| # XOR with Plaintext |
| vpxor 0*16($PT), $STATE1, $STATE1 |
| vpxor 1*16($PT), $STATE2, $STATE2 |
| vpxor 2*16($PT), $STATE3, $STATE3 |
| vpxor 3*16($PT), $STATE4, $STATE4 |
| vpxor 4*16($PT), $STATE5, $STATE5 |
| vpxor 5*16($PT), $STATE6, $STATE6 |
| vpxor 6*16($PT), $STATE7, $STATE7 |
| vpxor 7*16($PT), $STATE8, $STATE8 |
| |
| subq \$1, $LEN |
| |
| vmovdqu $STATE1, 0*16($CT) |
| vmovdqu $STATE2, 1*16($CT) |
| vmovdqu $STATE3, 2*16($CT) |
| vmovdqu $STATE4, 3*16($CT) |
| vmovdqu $STATE5, 4*16($CT) |
| vmovdqu $STATE6, 5*16($CT) |
| vmovdqu $STATE7, 6*16($CT) |
| vmovdqu $STATE8, 7*16($CT) |
| |
| jne .L256_enc_msg_x8_loop1 |
| |
| addq \$128, $CT |
| addq \$128, $PT |
| |
| .L256_enc_msg_x8_check_remainder: |
| cmpq \$0, %r10 |
| je .L256_enc_msg_x8_out |
| |
| .L256_enc_msg_x8_loop2: |
| # encrypt each block separately |
| # CTR1 is the highest counter (even if no LOOP done) |
| vmovdqa $CTR1, $STATE1 |
| vpaddd one(%rip), $CTR1, $CTR1 |
| |
| vpxor ($KS), $STATE1, $STATE1 |
| vaesenc 16($KS), $STATE1, $STATE1 |
| vaesenc 32($KS), $STATE1, $STATE1 |
| vaesenc 48($KS), $STATE1, $STATE1 |
| vaesenc 64($KS), $STATE1, $STATE1 |
| vaesenc 80($KS), $STATE1, $STATE1 |
| vaesenc 96($KS), $STATE1, $STATE1 |
| vaesenc 112($KS), $STATE1, $STATE1 |
| vaesenc 128($KS), $STATE1, $STATE1 |
| vaesenc 144($KS), $STATE1, $STATE1 |
| vaesenc 160($KS), $STATE1, $STATE1 |
| vaesenc 176($KS), $STATE1, $STATE1 |
| vaesenc 192($KS), $STATE1, $STATE1 |
| vaesenc 208($KS), $STATE1, $STATE1 |
| vaesenclast 224($KS), $STATE1, $STATE1 |
| |
| # XOR with Plaintext |
| vpxor ($PT), $STATE1, $STATE1 |
| |
| vmovdqu $STATE1, ($CT) |
| |
| addq \$16, $PT |
| addq \$16, $CT |
| subq \$1, %r10 |
| jnz .L256_enc_msg_x8_loop2 |
| |
| .L256_enc_msg_x8_out: |
| ret |
| |
| .cfi_endproc |
| .size aes256gcmsiv_enc_msg_x8,.-aes256gcmsiv_enc_msg_x8 |
| ___ |
| } |
| aes256gcmsiv_enc_msg_x8(); |
| aesgcmsiv_dec(1); |
| |
| sub aes256gcmsiv_kdf { |
| my $ONE = "%xmm8"; |
| my $BLOCK1 = "%xmm4"; |
| my $BLOCK2 = "%xmm6"; |
| my $BLOCK3 = "%xmm7"; |
| my $BLOCK4 = "%xmm11"; |
| my $BLOCK5 = "%xmm12"; |
| my $BLOCK6 = "%xmm13"; |
| |
| my $enc_roundx6 = sub { |
| my ($i, $j) = @_; |
| return <<___; |
| vmovdqa ${\eval($i*16)}(%rdx), $j |
| vaesenc $j, $BLOCK1, $BLOCK1 |
| vaesenc $j, $BLOCK2, $BLOCK2 |
| vaesenc $j, $BLOCK3, $BLOCK3 |
| vaesenc $j, $BLOCK4, $BLOCK4 |
| vaesenc $j, $BLOCK5, $BLOCK5 |
| vaesenc $j, $BLOCK6, $BLOCK6 |
| ___ |
| }; |
| |
| my $enc_roundlastx6 = sub { |
| my ($i, $j) = @_; |
| return <<___; |
| vmovdqa ${\eval($i*16)}(%rdx), $j |
| vaesenclast $j, $BLOCK1, $BLOCK1 |
| vaesenclast $j, $BLOCK2, $BLOCK2 |
| vaesenclast $j, $BLOCK3, $BLOCK3 |
| vaesenclast $j, $BLOCK4, $BLOCK4 |
| vaesenclast $j, $BLOCK5, $BLOCK5 |
| vaesenclast $j, $BLOCK6, $BLOCK6 |
| ___ |
| }; |
| |
| # void aes256gcmsiv_kdf(const uint8_t nonce[16], |
| # uint8_t *out_key_material, |
| # const uint8_t *key_schedule); |
| $code.=<<___; |
| .globl aes256gcmsiv_kdf |
| .type aes256gcmsiv_kdf,\@function,3 |
| .align 16 |
| aes256gcmsiv_kdf: |
| .cfi_startproc |
| # parameter 1: %rdi Pointer to NONCE |
| # parameter 2: %rsi Pointer to CT |
| # parameter 4: %rdx Pointer to keys |
| |
| vmovdqa (%rdx), %xmm1 # xmm1 = first 16 bytes of random key |
| vmovdqa 0*16(%rdi), $BLOCK1 |
| vmovdqa and_mask(%rip), $BLOCK4 |
| vmovdqa one(%rip), $ONE |
| vpshufd \$0x90, $BLOCK1, $BLOCK1 |
| vpand $BLOCK4, $BLOCK1, $BLOCK1 |
| vpaddd $ONE, $BLOCK1, $BLOCK2 |
| vpaddd $ONE, $BLOCK2, $BLOCK3 |
| vpaddd $ONE, $BLOCK3, $BLOCK4 |
| vpaddd $ONE, $BLOCK4, $BLOCK5 |
| vpaddd $ONE, $BLOCK5, $BLOCK6 |
| |
| vpxor %xmm1, $BLOCK1, $BLOCK1 |
| vpxor %xmm1, $BLOCK2, $BLOCK2 |
| vpxor %xmm1, $BLOCK3, $BLOCK3 |
| vpxor %xmm1, $BLOCK4, $BLOCK4 |
| vpxor %xmm1, $BLOCK5, $BLOCK5 |
| vpxor %xmm1, $BLOCK6, $BLOCK6 |
| |
| ${\$enc_roundx6->(1, "%xmm1")} |
| ${\$enc_roundx6->(2, "%xmm2")} |
| ${\$enc_roundx6->(3, "%xmm1")} |
| ${\$enc_roundx6->(4, "%xmm2")} |
| ${\$enc_roundx6->(5, "%xmm1")} |
| ${\$enc_roundx6->(6, "%xmm2")} |
| ${\$enc_roundx6->(7, "%xmm1")} |
| ${\$enc_roundx6->(8, "%xmm2")} |
| ${\$enc_roundx6->(9, "%xmm1")} |
| ${\$enc_roundx6->(10, "%xmm2")} |
| ${\$enc_roundx6->(11, "%xmm1")} |
| ${\$enc_roundx6->(12, "%xmm2")} |
| ${\$enc_roundx6->(13, "%xmm1")} |
| ${\$enc_roundlastx6->(14, "%xmm2")} |
| |
| vmovdqa $BLOCK1, 0*16(%rsi) |
| vmovdqa $BLOCK2, 1*16(%rsi) |
| vmovdqa $BLOCK3, 2*16(%rsi) |
| vmovdqa $BLOCK4, 3*16(%rsi) |
| vmovdqa $BLOCK5, 4*16(%rsi) |
| vmovdqa $BLOCK6, 5*16(%rsi) |
| ret |
| .cfi_endproc |
| .size aes256gcmsiv_kdf, .-aes256gcmsiv_kdf |
| ___ |
| } |
| aes256gcmsiv_kdf(); |
| |
| print $code; |
| |
| close STDOUT or die "error closing STDOUT: $!"; |