#! /usr/bin/env perl # SPDX-License-Identifier: GPL-2.0 # This code is taken from CRYPTOGAMs[1] and is included here using the option # in the license to distribute the code under the GPL. Therefore this program # is free software; you can redistribute it and/or modify it under the terms of # the GNU General Public License version 2 as published by the Free Software # Foundation. # # [1] https://www.openssl.org/~appro/cryptogams/ # Copyright (c) 2006-2017, CRYPTOGAMS by <appro@openssl.org> # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain copyright notices, # this list of conditions and the following disclaimer. # # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following # disclaimer in the documentation and/or other materials # provided with the distribution. # # * Neither the name of the CRYPTOGAMS nor the names of its # copyright holder and contributors may be used to endorse or # promote products derived from this software without specific # prior written permission. # # ALTERNATIVELY, provided that this notice is retained in full, this # product may be distributed under the terms of the GNU General Public # License (GPL), in which case the provisions of the GPL apply INSTEAD OF # those given above. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ==================================================================== # Written by Andy Polyakov <appro@openssl.org> for the OpenSSL # project. The module is, however, dual licensed under OpenSSL and # CRYPTOGAMS licenses depending on where you obtain it. For further # details see https://www.openssl.org/~appro/cryptogams/. # ==================================================================== # # This module implements support for AES instructions as per PowerISA # specification version 2.07, first implemented by POWER8 processor. # The module is endian-agnostic in sense that it supports both big- # and little-endian cases. Data alignment in parallelizable modes is # handled with VSX loads and stores, which implies MSR.VSX flag being # set. It should also be noted that ISA specification doesn't prohibit # alignment exceptions for these instructions on page boundaries. # Initially alignment was handled in pure AltiVec/VMX way [when data # is aligned programmatically, which in turn guarantees exception- # free execution], but it turned to hamper performance when vcipher # instructions are interleaved. It's reckoned that eventual # misalignment penalties at page boundaries are in average lower # than additional overhead in pure AltiVec approach. # # May 2016 # # Add XTS subroutine, 9x on little- and 12x improvement on big-endian # systems were measured. # ###################################################################### # Current large-block performance in cycles per byte processed with # 128-bit key (less is better). # # CBC en-/decrypt CTR XTS # POWER8[le] 3.96/0.72 0.74 1.1 # POWER8[be] 3.75/0.65 0.66 1.0 $flavour = shift; if ($flavour =~ /64/) { $SIZE_T =8; $LRSAVE =2*$SIZE_T; $STU ="stdu"; $POP ="ld"; $PUSH ="std"; $UCMP ="cmpld"; $SHL ="sldi"; } elsif ($flavour =~ /32/) { $SIZE_T =4; $LRSAVE =$SIZE_T; $STU ="stwu"; $POP ="lwz"; $PUSH ="stw"; $UCMP ="cmplw"; $SHL ="slwi"; } else { die "nonsense $flavour"; } $LITTLE_ENDIAN = ($flavour=~/le$/) ? $SIZE_T : 0; $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; ( $xlate="${dir}ppc-xlate.pl" and -f $xlate ) or ( $xlate="${dir}../../perlasm/ppc-xlate.pl" and -f $xlate) or die "can't locate ppc-xlate.pl"; open STDOUT,"| $^X $xlate $flavour ".shift || die "can't call $xlate: $!"; $FRAME=8*$SIZE_T; $prefix="aes_p8"; $sp="r1"; $vrsave="r12"; ######################################################################### {{{ # Key setup procedures # my ($inp,$bits,$out,$ptr,$cnt,$rounds)=map("r$_",(3..8)); my ($zero,$in0,$in1,$key,$rcon,$mask,$tmp)=map("v$_",(0..6)); my ($stage,$outperm,$outmask,$outhead,$outtail)=map("v$_",(7..11)); $code.=<<___; .machine "any" .text .align 7 rcon: .long 0x01000000, 0x01000000, 0x01000000, 0x01000000 ?rev .long 0x1b000000, 0x1b000000, 0x1b000000, 0x1b000000 ?rev .long 0x0d0e0f0c, 0x0d0e0f0c, 0x0d0e0f0c, 0x0d0e0f0c ?rev .long 0,0,0,0 ?asis Lconsts: mflr r0 bcl 20,31,\$+4 mflr $ptr #vvvvv "distance between . and rcon addi $ptr,$ptr,-0x48 mtlr r0 blr .long 0 .byte 0,12,0x14,0,0,0,0,0 .asciz "AES for PowerISA 2.07, CRYPTOGAMS by <appro\@openssl.org>" .globl .${prefix}_set_encrypt_key Lset_encrypt_key: mflr r11 $PUSH r11,$LRSAVE($sp) li $ptr,-1 ${UCMP}i $inp,0 beq- Lenc_key_abort # if ($inp==0) return -1; ${UCMP}i $out,0 beq- Lenc_key_abort # if ($out==0) return -1; li $ptr,-2 cmpwi $bits,128 blt- Lenc_key_abort cmpwi $bits,256 bgt- Lenc_key_abort andi. r0,$bits,0x3f bne- Lenc_key_abort lis r0,0xfff0 mfspr $vrsave,256 mtspr 256,r0 bl Lconsts mtlr r11 neg r9,$inp lvx $in0,0,$inp addi $inp,$inp,15 # 15 is not typo lvsr $key,0,r9 # borrow $key li r8,0x20 cmpwi $bits,192 lvx $in1,0,$inp le?vspltisb $mask,0x0f # borrow $mask lvx $rcon,0,$ptr le?vxor $key,$key,$mask # adjust for byte swap lvx $mask,r8,$ptr addi $ptr,$ptr,0x10 vperm $in0,$in0,$in1,$key # align [and byte swap in LE] li $cnt,8 vxor $zero,$zero,$zero mtctr $cnt ?lvsr $outperm,0,$out vspltisb $outmask,-1 lvx $outhead,0,$out ?vperm $outmask,$zero,$outmask,$outperm blt Loop128 addi $inp,$inp,8 beq L192 addi $inp,$inp,8 b L256 .align 4 Loop128: vperm $key,$in0,$in0,$mask # rotate-n-splat vsldoi $tmp,$zero,$in0,12 # >>32 vperm $outtail,$in0,$in0,$outperm # rotate vsel $stage,$outhead,$outtail,$outmask vmr $outhead,$outtail vcipherlast $key,$key,$rcon stvx $stage,0,$out addi $out,$out,16 vxor $in0,$in0,$tmp vsldoi $tmp,$zero,$tmp,12 # >>32 vxor $in0,$in0,$tmp vsldoi $tmp,$zero,$tmp,12 # >>32 vxor $in0,$in0,$tmp vadduwm $rcon,$rcon,$rcon vxor $in0,$in0,$key bdnz Loop128 lvx $rcon,0,$ptr # last two round keys vperm $key,$in0,$in0,$mask # rotate-n-splat vsldoi $tmp,$zero,$in0,12 # >>32 vperm $outtail,$in0,$in0,$outperm # rotate vsel $stage,$outhead,$outtail,$outmask vmr $outhead,$outtail vcipherlast $key,$key,$rcon stvx $stage,0,$out addi $out,$out,16 vxor $in0,$in0,$tmp vsldoi $tmp,$zero,$tmp,12 # >>32 vxor $in0,$in0,$tmp vsldoi $tmp,$zero,$tmp,12 # >>32 vxor $in0,$in0,$tmp vadduwm $rcon,$rcon,$rcon vxor $in0,$in0,$key vperm $key,$in0,$in0,$mask # rotate-n-splat vsldoi $tmp,$zero,$in0,12 # >>32 vperm $outtail,$in0,$in0,$outperm # rotate vsel $stage,$outhead,$outtail,$outmask vmr $outhead,$outtail vcipherlast $key,$key,$rcon stvx $stage,0,$out addi $out,$out,16 vxor $in0,$in0,$tmp vsldoi $tmp,$zero,$tmp,12 # >>32 vxor $in0,$in0,$tmp vsldoi $tmp,$zero,$tmp,12 # >>32 vxor $in0,$in0,$tmp vxor $in0,$in0,$key vperm $outtail,$in0,$in0,$outperm # rotate vsel $stage,$outhead,$outtail,$outmask vmr $outhead,$outtail stvx $stage,0,$out addi $inp,$out,15 # 15 is not typo addi $out,$out,0x50 li $rounds,10 b Ldone .align 4 L192: lvx $tmp,0,$inp li $cnt,4 vperm $outtail,$in0,$in0,$outperm # rotate vsel $stage,$outhead,$outtail,$outmask vmr $outhead,$outtail stvx $stage,0,$out addi $out,$out,16 vperm $in1,$in1,$tmp,$key # align [and byte swap in LE] vspltisb $key,8 # borrow $key mtctr $cnt vsububm $mask,$mask,$key # adjust the mask Loop192: vperm $key,$in1,$in1,$mask # roate-n-splat vsldoi $tmp,$zero,$in0,12 # >>32 vcipherlast $key,$key,$rcon vxor $in0,$in0,$tmp vsldoi $tmp,$zero,$tmp,12 # >>32 vxor $in0,$in0,$tmp vsldoi $tmp,$zero,$tmp,12 # >>32 vxor $in0,$in0,$tmp vsldoi $stage,$zero,$in1,8 vspltw $tmp,$in0,3 vxor $tmp,$tmp,$in1 vsldoi $in1,$zero,$in1,12 # >>32 vadduwm $rcon,$rcon,$rcon vxor $in1,$in1,$tmp vxor $in0,$in0,$key vxor $in1,$in1,$key vsldoi $stage,$stage,$in0,8 vperm $key,$in1,$in1,$mask # rotate-n-splat vsldoi $tmp,$zero,$in0,12 # >>32 vperm $outtail,$stage,$stage,$outperm # rotate vsel $stage,$outhead,$outtail,$outmask vmr $outhead,$outtail vcipherlast $key,$key,$rcon stvx $stage,0,$out addi $out,$out,16 vsldoi $stage,$in0,$in1,8 vxor $in0,$in0,$tmp vsldoi $tmp,$zero,$tmp,12 # >>32 vperm $outtail,$stage,$stage,$outperm # rotate vsel $stage,$outhead,$outtail,$outmask vmr $outhead,$outtail vxor $in0,$in0,$tmp vsldoi $tmp,$zero,$tmp,12 # >>32 vxor $in0,$in0,$tmp stvx $stage,0,$out addi $out,$out,16 vspltw $tmp,$in0,3 vxor $tmp,$tmp,$in1 vsldoi $in1,$zero,$in1,12 # >>32 vadduwm $rcon,$rcon,$rcon vxor $in1,$in1,$tmp vxor $in0,$in0,$key vxor $in1,$in1,$key vperm $outtail,$in0,$in0,$outperm # rotate vsel $stage,$outhead,$outtail,$outmask vmr $outhead,$outtail stvx $stage,0,$out addi $inp,$out,15 # 15 is not typo addi $out,$out,16 bdnz Loop192 li $rounds,12 addi $out,$out,0x20 b Ldone .align 4 L256: lvx $tmp,0,$inp li $cnt,7 li $rounds,14 vperm $outtail,$in0,$in0,$outperm # rotate vsel $stage,$outhead,$outtail,$outmask vmr $outhead,$outtail stvx $stage,0,$out addi $out,$out,16 vperm $in1,$in1,$tmp,$key # align [and byte swap in LE] mtctr $cnt Loop256: vperm $key,$in1,$in1,$mask # rotate-n-splat vsldoi $tmp,$zero,$in0,12 # >>32 vperm $outtail,$in1,$in1,$outperm # rotate vsel $stage,$outhead,$outtail,$outmask vmr $outhead,$outtail vcipherlast $key,$key,$rcon stvx $stage,0,$out addi $out,$out,16 vxor $in0,$in0,$tmp vsldoi $tmp,$zero,$tmp,12 # >>32 vxor $in0,$in0,$tmp vsldoi $tmp,$zero,$tmp,12 # >>32 vxor $in0,$in0,$tmp vadduwm $rcon,$rcon,$rcon vxor $in0,$in0,$key vperm $outtail,$in0,$in0,$outperm # rotate vsel $stage,$outhead,$outtail,$outmask vmr $outhead,$outtail stvx $stage,0,$out addi $inp,$out,15 # 15 is not typo addi $out,$out,16 bdz Ldone vspltw $key,$in0,3 # just splat vsldoi $tmp,$zero,$in1,12 # >>32 vsbox $key,$key vxor $in1,$in1,$tmp vsldoi $tmp,$zero,$tmp,12 # >>32 vxor $in1,$in1,$tmp vsldoi $tmp,$zero,$tmp,12 # >>32 vxor $in1,$in1,$tmp vxor $in1,$in1,$key b Loop256 .align 4 Ldone: lvx $in1,0,$inp # redundant in aligned case vsel $in1,$outhead,$in1,$outmask stvx $in1,0,$inp li $ptr,0 mtspr 256,$vrsave stw $rounds,0($out) Lenc_key_abort: mr r3,$ptr blr .long 0 .byte 0,12,0x14,1,0,0,3,0 .long 0 .size .${prefix}_set_encrypt_key,.-.${prefix}_set_encrypt_key .globl .${prefix}_set_decrypt_key $STU $sp,-$FRAME($sp) mflr r10 $PUSH r10,$FRAME+$LRSAVE($sp) bl Lset_encrypt_key mtlr r10 cmpwi r3,0 bne- Ldec_key_abort slwi $cnt,$rounds,4 subi $inp,$out,240 # first round key srwi $rounds,$rounds,1 add $out,$inp,$cnt # last round key mtctr $rounds Ldeckey: lwz r0, 0($inp) lwz r6, 4($inp) lwz r7, 8($inp) lwz r8, 12($inp) addi $inp,$inp,16 lwz r9, 0($out) lwz r10,4($out) lwz r11,8($out) lwz r12,12($out) stw r0, 0($out) stw r6, 4($out) stw r7, 8($out) stw r8, 12($out) subi $out,$out,16 stw r9, -16($inp) stw r10,-12($inp) stw r11,-8($inp) stw r12,-4($inp) bdnz Ldeckey xor r3,r3,r3 # return value Ldec_key_abort: addi $sp,$sp,$FRAME blr .long 0 .byte 0,12,4,1,0x80,0,3,0 .long 0 .size .${prefix}_set_decrypt_key,.-.${prefix}_set_decrypt_key ___ }}} ######################################################################### {{{ # Single block en- and decrypt procedures # sub gen_block () { my $dir = shift; my $n = $dir eq "de" ? "n" : ""; my ($inp,$out,$key,$rounds,$idx)=map("r$_",(3..7)); $code.=<<___; .globl .${prefix}_${dir}crypt lwz $rounds,240($key) lis r0,0xfc00 mfspr $vrsave,256 li $idx,15 # 15 is not typo mtspr 256,r0 lvx v0,0,$inp neg r11,$out lvx v1,$idx,$inp lvsl v2,0,$inp # inpperm le?vspltisb v4,0x0f ?lvsl v3,0,r11 # outperm le?vxor v2,v2,v4 li $idx,16 vperm v0,v0,v1,v2 # align [and byte swap in LE] lvx v1,0,$key ?lvsl v5,0,$key # keyperm srwi $rounds,$rounds,1 lvx v2,$idx,$key addi $idx,$idx,16 subi $rounds,$rounds,1 ?vperm v1,v1,v2,v5 # align round key vxor v0,v0,v1 lvx v1,$idx,$key addi $idx,$idx,16 mtctr $rounds Loop_${dir}c: ?vperm v2,v2,v1,v5 v${n}cipher v0,v0,v2 lvx v2,$idx,$key addi $idx,$idx,16 ?vperm v1,v1,v2,v5 v${n}cipher v0,v0,v1 lvx v1,$idx,$key addi $idx,$idx,16 bdnz Loop_${dir}c ?vperm v2,v2,v1,v5 v${n}cipher v0,v0,v2 lvx v2,$idx,$key ?vperm v1,v1,v2,v5 v${n}cipherlast v0,v0,v1 vspltisb v2,-1 vxor v1,v1,v1 li $idx,15 # 15 is not typo ?vperm v2,v1,v2,v3 # outmask le?vxor v3,v3,v4 lvx v1,0,$out # outhead vperm v0,v0,v0,v3 # rotate [and byte swap in LE] vsel v1,v1,v0,v2 lvx v4,$idx,$out stvx v1,0,$out vsel v0,v0,v4,v2 stvx v0,$idx,$out mtspr 256,$vrsave blr .long 0 .byte 0,12,0x14,0,0,0,3,0 .long 0 .size .${prefix}_${dir}crypt,.-.${prefix}_${dir}crypt ___ } &gen_block("en"); &gen_block("de"); }}} ######################################################################### {{{ # CBC en- and decrypt procedures # my ($inp,$out,$len,$key,$ivp,$enc,$rounds,$idx)=map("r$_",(3..10)); my ($rndkey0,$rndkey1,$inout,$tmp)= map("v$_",(0..3)); my ($ivec,$inptail,$inpperm,$outhead,$outperm,$outmask,$keyperm)= map("v$_",(4..10)); $code.=<<___; .globl .${prefix}_cbc_encrypt ${UCMP}i $len,16 bltlr- cmpwi $enc,0 # test direction lis r0,0xffe0 mfspr $vrsave,256 mtspr 256,r0 li $idx,15 vxor $rndkey0,$rndkey0,$rndkey0 le?vspltisb $tmp,0x0f lvx $ivec,0,$ivp # load [unaligned] iv lvsl $inpperm,0,$ivp lvx $inptail,$idx,$ivp le?vxor $inpperm,$inpperm,$tmp vperm $ivec,$ivec,$inptail,$inpperm neg r11,$inp ?lvsl $keyperm,0,$key # prepare for unaligned key lwz $rounds,240($key) lvsr $inpperm,0,r11 # prepare for unaligned load lvx $inptail,0,$inp addi $inp,$inp,15 # 15 is not typo le?vxor $inpperm,$inpperm,$tmp ?lvsr $outperm,0,$out # prepare for unaligned store vspltisb $outmask,-1 lvx $outhead,0,$out ?vperm $outmask,$rndkey0,$outmask,$outperm le?vxor $outperm,$outperm,$tmp srwi $rounds,$rounds,1 li $idx,16 subi $rounds,$rounds,1 beq Lcbc_dec Lcbc_enc: vmr $inout,$inptail lvx $inptail,0,$inp addi $inp,$inp,16 mtctr $rounds subi $len,$len,16 # len-=16 lvx $rndkey0,0,$key vperm $inout,$inout,$inptail,$inpperm lvx $rndkey1,$idx,$key addi $idx,$idx,16 ?vperm $rndkey0,$rndkey0,$rndkey1,$keyperm vxor $inout,$inout,$rndkey0 lvx $rndkey0,$idx,$key addi $idx,$idx,16 vxor $inout,$inout,$ivec Loop_cbc_enc: ?vperm $rndkey1,$rndkey1,$rndkey0,$keyperm vcipher $inout,$inout,$rndkey1 lvx $rndkey1,$idx,$key addi $idx,$idx,16 ?vperm $rndkey0,$rndkey0,$rndkey1,$keyperm vcipher $inout,$inout,$rndkey0 lvx $rndkey0,$idx,$key addi $idx,$idx,16 bdnz Loop_cbc_enc ?vperm $rndkey1,$rndkey1,$rndkey0,$keyperm vcipher $inout,$inout,$rndkey1 lvx $rndkey1,$idx,$key li $idx,16 ?vperm $rndkey0,$rndkey0,$rndkey1,$keyperm vcipherlast $ivec,$inout,$rndkey0 ${UCMP}i $len,16 vperm $tmp,$ivec,$ivec,$outperm vsel $inout,$outhead,$tmp,$outmask vmr $outhead,$tmp stvx $inout,0,$out addi $out,$out,16 bge Lcbc_enc b Lcbc_done .align 4 Lcbc_dec: ${UCMP}i $len,128 bge _aesp8_cbc_decrypt8x vmr $tmp,$inptail lvx $inptail,0,$inp addi $inp,$inp,16 mtctr $rounds subi $len,$len,16 # len-=16 lvx $rndkey0,0,$key vperm $tmp,$tmp,$inptail,$inpperm lvx $rndkey1,$idx,$key addi $idx,$idx,16 ?vperm $rndkey0,$rndkey0,$rndkey1,$keyperm vxor $inout,$tmp,$rndkey0 lvx $rndkey0,$idx,$key addi $idx,$idx,16 Loop_cbc_dec: ?vperm $rndkey1,$rndkey1,$rndkey0,$keyperm vncipher $inout,$inout,$rndkey1 lvx $rndkey1,$idx,$key addi $idx,$idx,16 ?vperm $rndkey0,$rndkey0,$rndkey1,$keyperm vncipher $inout,$inout,$rndkey0 lvx $rndkey0,$idx,$key addi $idx,$idx,16 bdnz Loop_cbc_dec ?vperm $rndkey1,$rndkey1,$rndkey0,$keyperm vncipher $inout,$inout,$rndkey1 lvx $rndkey1,$idx,$key li $idx,16 ?vperm $rndkey0,$rndkey0,$rndkey1,$keyperm vncipherlast $inout,$inout,$rndkey0 ${UCMP}i $len,16 vxor $inout,$inout,$ivec vmr $ivec,$tmp vperm $tmp,$inout,$inout,$outperm vsel $inout,$outhead,$tmp,$outmask vmr $outhead,$tmp stvx $inout,0,$out addi $out,$out,16 bge Lcbc_dec Lcbc_done: addi $out,$out,-1 lvx $inout,0,$out # redundant in aligned case vsel $inout,$outhead,$inout,$outmask stvx $inout,0,$out neg $enc,$ivp # write [unaligned] iv li $idx,15 # 15 is not typo vxor $rndkey0,$rndkey0,$rndkey0 vspltisb $outmask,-1 le?vspltisb $tmp,0x0f ?lvsl $outperm,0,$enc ?vperm $outmask,$rndkey0,$outmask,$outperm le?vxor $outperm,$outperm,$tmp lvx $outhead,0,$ivp vperm $ivec,$ivec,$ivec,$outperm vsel $inout,$outhead,$ivec,$outmask lvx $inptail,$idx,$ivp stvx $inout,0,$ivp vsel $inout,$ivec,$inptail,$outmask stvx $inout,$idx,$ivp mtspr 256,$vrsave blr .long 0 .byte 0,12,0x14,0,0,0,6,0 .long 0 ___ ######################################################################### {{ # Optimized CBC decrypt procedure # my $key_="r11"; my ($x00,$x10,$x20,$x30,$x40,$x50,$x60,$x70)=map("r$_",(0,8,26..31)); my ($in0, $in1, $in2, $in3, $in4, $in5, $in6, $in7 )=map("v$_",(0..3,10..13)); my ($out0,$out1,$out2,$out3,$out4,$out5,$out6,$out7)=map("v$_",(14..21)); my $rndkey0="v23"; # v24-v25 rotating buffer for first found keys # v26-v31 last 6 round keys my ($tmp,$keyperm)=($in3,$in4); # aliases with "caller", redundant assignment $code.=<<___; .align 5 _aesp8_cbc_decrypt8x: $STU $sp,-`($FRAME+21*16+6*$SIZE_T)`($sp) li r10,`$FRAME+8*16+15` li r11,`$FRAME+8*16+31` stvx v20,r10,$sp # ABI says so addi r10,r10,32 stvx v21,r11,$sp addi r11,r11,32 stvx v22,r10,$sp addi r10,r10,32 stvx v23,r11,$sp addi r11,r11,32 stvx v24,r10,$sp addi r10,r10,32 stvx v25,r11,$sp addi r11,r11,32 stvx v26,r10,$sp addi r10,r10,32 stvx v27,r11,$sp addi r11,r11,32 stvx v28,r10,$sp addi r10,r10,32 stvx v29,r11,$sp addi r11,r11,32 stvx v30,r10,$sp stvx v31,r11,$sp li r0,-1 stw $vrsave,`$FRAME+21*16-4`($sp) # save vrsave li $x10,0x10 $PUSH r26,`$FRAME+21*16+0*$SIZE_T`($sp) li $x20,0x20 $PUSH r27,`$FRAME+21*16+1*$SIZE_T`($sp) li $x30,0x30 $PUSH r28,`$FRAME+21*16+2*$SIZE_T`($sp) li $x40,0x40 $PUSH r29,`$FRAME+21*16+3*$SIZE_T`($sp) li $x50,0x50 $PUSH r30,`$FRAME+21*16+4*$SIZE_T`($sp) li $x60,0x60 $PUSH r31,`$FRAME+21*16+5*$SIZE_T`($sp) li $x70,0x70 mtspr 256,r0 subi $rounds,$rounds,3 # -4 in total subi $len,$len,128 # bias lvx $rndkey0,$x00,$key # load key schedule lvx v30,$x10,$key addi $key,$key,0x20 lvx v31,$x00,$key ?vperm $rndkey0,$rndkey0,v30,$keyperm addi $key_,$sp,$FRAME+15 mtctr $rounds Load_cbc_dec_key: ?vperm v24,v30,v31,$keyperm lvx v30,$x10,$key addi $key,$key,0x20 stvx v24,$x00,$key_ # off-load round[1] ?vperm v25,v31,v30,$keyperm lvx v31,$x00,$key stvx v25,$x10,$key_ # off-load round[2] addi $key_,$key_,0x20 bdnz Load_cbc_dec_key lvx v26,$x10,$key ?vperm v24,v30,v31,$keyperm lvx v27,$x20,$key stvx v24,$x00,$key_ # off-load round[3] ?vperm v25,v31,v26,$keyperm lvx v28,$x30,$key stvx v25,$x10,$key_ # off-load round[4] addi $key_,$sp,$FRAME+15 # rewind $key_ ?vperm v26,v26,v27,$keyperm lvx v29,$x40,$key ?vperm v27,v27,v28,$keyperm lvx v30,$x50,$key ?vperm v28,v28,v29,$keyperm lvx v31,$x60,$key ?vperm v29,v29,v30,$keyperm lvx $out0,$x70,$key # borrow $out0 ?vperm v30,v30,v31,$keyperm lvx v24,$x00,$key_ # pre-load round[1] ?vperm v31,v31,$out0,$keyperm lvx v25,$x10,$key_ # pre-load round[2] #lvx $inptail,0,$inp # "caller" already did this #addi $inp,$inp,15 # 15 is not typo subi $inp,$inp,15 # undo "caller" le?li $idx,8 lvx_u $in0,$x00,$inp # load first 8 "words" le?lvsl $inpperm,0,$idx le?vspltisb $tmp,0x0f lvx_u $in1,$x10,$inp le?vxor $inpperm,$inpperm,$tmp # transform for lvx_u/stvx_u lvx_u $in2,$x20,$inp le?vperm $in0,$in0,$in0,$inpperm lvx_u $in3,$x30,$inp le?vperm $in1,$in1,$in1,$inpperm lvx_u $in4,$x40,$inp le?vperm $in2,$in2,$in2,$inpperm vxor $out0,$in0,$rndkey0 lvx_u $in5,$x50,$inp le?vperm $in3,$in3,$in3,$inpperm vxor $out1,$in1,$rndkey0 lvx_u $in6,$x60,$inp le?vperm $in4,$in4,$in4,$inpperm vxor $out2,$in2,$rndkey0 lvx_u $in7,$x70,$inp addi $inp,$inp,0x80 le?vperm $in5,$in5,$in5,$inpperm vxor $out3,$in3,$rndkey0 le?vperm $in6,$in6,$in6,$inpperm vxor $out4,$in4,$rndkey0 le?vperm $in7,$in7,$in7,$inpperm vxor $out5,$in5,$rndkey0 vxor $out6,$in6,$rndkey0 vxor $out7,$in7,$rndkey0 mtctr $rounds b Loop_cbc_dec8x .align 5 Loop_cbc_dec8x: vncipher $out0,$out0,v24 vncipher $out1,$out1,v24 vncipher $out2,$out2,v24 vncipher $out3,$out3,v24 vncipher $out4,$out4,v24 vncipher $out5,$out5,v24 vncipher $out6,$out6,v24 vncipher $out7,$out7,v24 lvx v24,$x20,$key_ # round[3] addi $key_,$key_,0x20 vncipher $out0,$out0,v25 vncipher $out1,$out1,v25 vncipher $out2,$out2,v25 vncipher $out3,$out3,v25 vncipher $out4,$out4,v25 vncipher $out5,$out5,v25 vncipher $out6,$out6,v25 vncipher $out7,$out7,v25 lvx v25,$x10,$key_ # round[4] bdnz Loop_cbc_dec8x subic $len,$len,128 # $len-=128 vncipher $out0,$out0,v24 vncipher $out1,$out1,v24 vncipher $out2,$out2,v24 vncipher $out3,$out3,v24 vncipher $out4,$out4,v24 vncipher $out5,$out5,v24 vncipher $out6,$out6,v24 vncipher $out7,$out7,v24 subfe. r0,r0,r0 # borrow?-1:0 vncipher $out0,$out0,v25 vncipher $out1,$out1,v25 vncipher $out2,$out2,v25 vncipher $out3,$out3,v25 vncipher $out4,$out4,v25 vncipher $out5,$out5,v25 vncipher $out6,$out6,v25 vncipher $out7,$out7,v25 and r0,r0,$len vncipher $out0,$out0,v26 vncipher $out1,$out1,v26 vncipher $out2,$out2,v26 vncipher $out3,$out3,v26 vncipher $out4,$out4,v26 vncipher $out5,$out5,v26 vncipher $out6,$out6,v26 vncipher $out7,$out7,v26 add $inp,$inp,r0 # $inp is adjusted in such # way that at exit from the # loop inX-in7 are loaded # with last "words" vncipher $out0,$out0,v27 vncipher $out1,$out1,v27 vncipher $out2,$out2,v27 vncipher $out3,$out3,v27 vncipher $out4,$out4,v27 vncipher $out5,$out5,v27 vncipher $out6,$out6,v27 vncipher $out7,$out7,v27 addi $key_,$sp,$FRAME+15 # rewind $key_ vncipher $out0,$out0,v28 vncipher $out1,$out1,v28 vncipher $out2,$out2,v28 vncipher $out3,$out3,v28 vncipher $out4,$out4,v28 vncipher $out5,$out5,v28 vncipher $out6,$out6,v28 vncipher $out7,$out7,v28 lvx v24,$x00,$key_ # re-pre-load round[1] vncipher $out0,$out0,v29 vncipher $out1,$out1,v29 vncipher $out2,$out2,v29 vncipher $out3,$out3,v29 vncipher $out4,$out4,v29 vncipher $out5,$out5,v29 vncipher $out6,$out6,v29 vncipher $out7,$out7,v29 lvx v25,$x10,$key_ # re-pre-load round[2] vncipher $out0,$out0,v30 vxor $ivec,$ivec,v31 # xor with last round key vncipher $out1,$out1,v30 vxor $in0,$in0,v31 vncipher $out2,$out2,v30 vxor $in1,$in1,v31 vncipher $out3,$out3,v30 vxor $in2,$in2,v31 vncipher $out4,$out4,v30 vxor $in3,$in3,v31 vncipher $out5,$out5,v30 vxor $in4,$in4,v31 vncipher $out6,$out6,v30 vxor $in5,$in5,v31 vncipher $out7,$out7,v30 vxor $in6,$in6,v31 vncipherlast $out0,$out0,$ivec vncipherlast $out1,$out1,$in0 lvx_u $in0,$x00,$inp # load next input block vncipherlast $out2,$out2,$in1 lvx_u $in1,$x10,$inp vncipherlast $out3,$out3,$in2 le?vperm $in0,$in0,$in0,$inpperm lvx_u $in2,$x20,$inp vncipherlast $out4,$out4,$in3 le?vperm $in1,$in1,$in1,$inpperm lvx_u $in3,$x30,$inp vncipherlast $out5,$out5,$in4 le?vperm $in2,$in2,$in2,$inpperm lvx_u $in4,$x40,$inp vncipherlast $out6,$out6,$in5 le?vperm $in3,$in3,$in3,$inpperm lvx_u $in5,$x50,$inp vncipherlast $out7,$out7,$in6 le?vperm $in4,$in4,$in4,$inpperm lvx_u $in6,$x60,$inp vmr $ivec,$in7 le?vperm $in5,$in5,$in5,$inpperm lvx_u $in7,$x70,$inp addi $inp,$inp,0x80 le?vperm $out0,$out0,$out0,$inpperm le?vperm $out1,$out1,$out1,$inpperm stvx_u $out0,$x00,$out le?vperm $in6,$in6,$in6,$inpperm vxor $out0,$in0,$rndkey0 le?vperm $out2,$out2,$out2,$inpperm stvx_u $out1,$x10,$out le?vperm $in7,$in7,$in7,$inpperm vxor $out1,$in1,$rndkey0 le?vperm $out3,$out3,$out3,$inpperm stvx_u $out2,$x20,$out vxor $out2,$in2,$rndkey0 le?vperm $out4,$out4,$out4,$inpperm stvx_u $out3,$x30,$out vxor $out3,$in3,$rndkey0 le?vperm $out5,$out5,$out5,$inpperm stvx_u $out4,$x40,$out vxor $out4,$in4,$rndkey0 le?vperm $out6,$out6,$out6,$inpperm stvx_u $out5,$x50,$out vxor $out5,$in5,$rndkey0 le?vperm $out7,$out7,$out7,$inpperm stvx_u $out6,$x60,$out vxor $out6,$in6,$rndkey0 stvx_u $out7,$x70,$out addi $out,$out,0x80 vxor $out7,$in7,$rndkey0 mtctr $rounds beq Loop_cbc_dec8x # did $len-=128 borrow? addic. $len,$len,128 beq Lcbc_dec8x_done nop nop Loop_cbc_dec8x_tail: # up to 7 "words" tail... vncipher $out1,$out1,v24 vncipher $out2,$out2,v24 vncipher $out3,$out3,v24 vncipher $out4,$out4,v24 vncipher $out5,$out5,v24 vncipher $out6,$out6,v24 vncipher $out7,$out7,v24 lvx v24,$x20,$key_ # round[3] addi $key_,$key_,0x20 vncipher $out1,$out1,v25 vncipher $out2,$out2,v25 vncipher $out3,$out3,v25 vncipher $out4,$out4,v25 vncipher $out5,$out5,v25 vncipher $out6,$out6,v25 vncipher $out7,$out7,v25 lvx v25,$x10,$key_ # round[4] bdnz Loop_cbc_dec8x_tail vncipher $out1,$out1,v24 vncipher $out2,$out2,v24 vncipher $out3,$out3,v24 vncipher $out4,$out4,v24 vncipher $out5,$out5,v24 vncipher $out6,$out6,v24 vncipher $out7,$out7,v24 vncipher $out1,$out1,v25 vncipher $out2,$out2,v25 vncipher $out3,$out3,v25 vncipher $out4,$out4,v25 vncipher $out5,$out5,v25 vncipher $out6,$out6,v25 vncipher $out7,$out7,v25 vncipher $out1,$out1,v26 vncipher $out2,$out2,v26 vncipher $out3,$out3,v26 vncipher $out4,$out4,v26 vncipher $out5,$out5,v26 vncipher $out6,$out6,v26 vncipher $out7,$out7,v26 vncipher $out1,$out1,v27 vncipher $out2,$out2,v27 vncipher $out3,$out3,v27 vncipher $out4,$out4,v27 vncipher $out5,$out5,v27 vncipher $out6,$out6,v27 vncipher $out7,$out7,v27 vncipher $out1,$out1,v28 vncipher $out2,$out2,v28 vncipher $out3,$out3,v28 vncipher $out4,$out4,v28 vncipher $out5,$out5,v28 vncipher $out6,$out6,v28 vncipher $out7,$out7,v28 vncipher $out1,$out1,v29 vncipher $out2,$out2,v29 vncipher $out3,$out3,v29 vncipher $out4,$out4,v29 vncipher $out5,$out5,v29 vncipher $out6,$out6,v29 vncipher $out7,$out7,v29 vncipher $out1,$out1,v30 vxor $ivec,$ivec,v31 # last round key vncipher $out2,$out2,v30 vxor $in1,$in1,v31 vncipher $out3,$out3,v30 vxor $in2,$in2,v31 vncipher $out4,$out4,v30 vxor $in3,$in3,v31 vncipher $out5,$out5,v30 vxor $in4,$in4,v31 vncipher $out6,$out6,v30 vxor $in5,$in5,v31 vncipher $out7,$out7,v30 vxor $in6,$in6,v31 cmplwi $len,32 # switch($len) blt Lcbc_dec8x_one nop beq Lcbc_dec8x_two cmplwi $len,64 blt Lcbc_dec8x_three nop beq Lcbc_dec8x_four cmplwi $len,96 blt Lcbc_dec8x_five nop beq Lcbc_dec8x_six Lcbc_dec8x_seven: vncipherlast $out1,$out1,$ivec vncipherlast $out2,$out2,$in1 vncipherlast $out3,$out3,$in2 vncipherlast $out4,$out4,$in3 vncipherlast $out5,$out5,$in4 vncipherlast $out6,$out6,$in5 vncipherlast $out7,$out7,$in6 vmr $ivec,$in7 le?vperm $out1,$out1,$out1,$inpperm le?vperm $out2,$out2,$out2,$inpperm stvx_u $out1,$x00,$out le?vperm $out3,$out3,$out3,$inpperm stvx_u $out2,$x10,$out le?vperm $out4,$out4,$out4,$inpperm stvx_u $out3,$x20,$out le?vperm $out5,$out5,$out5,$inpperm stvx_u $out4,$x30,$out le?vperm $out6,$out6,$out6,$inpperm stvx_u $out5,$x40,$out le?vperm $out7,$out7,$out7,$inpperm stvx_u $out6,$x50,$out stvx_u $out7,$x60,$out addi $out,$out,0x70 b Lcbc_dec8x_done .align 5 Lcbc_dec8x_six: vncipherlast $out2,$out2,$ivec vncipherlast $out3,$out3,$in2 vncipherlast $out4,$out4,$in3 vncipherlast $out5,$out5,$in4 vncipherlast $out6,$out6,$in5 vncipherlast $out7,$out7,$in6 vmr $ivec,$in7 le?vperm $out2,$out2,$out2,$inpperm le?vperm $out3,$out3,$out3,$inpperm stvx_u $out2,$x00,$out le?vperm $out4,$out4,$out4,$inpperm stvx_u $out3,$x10,$out le?vperm $out5,$out5,$out5,$inpperm stvx_u $out4,$x20,$out le?vperm $out6,$out6,$out6,$inpperm stvx_u $out5,$x30,$out le?vperm $out7,$out7,$out7,$inpperm stvx_u $out6,$x40,$out stvx_u $out7,$x50,$out addi $out,$out,0x60 b Lcbc_dec8x_done .align 5 Lcbc_dec8x_five: vncipherlast $out3,$out3,$ivec vncipherlast $out4,$out4,$in3 vncipherlast $out5,$out5,$in4 vncipherlast $out6,$out6,$in5 vncipherlast $out7,$out7,$in6 vmr $ivec,$in7 le?vperm $out3,$out3,$out3,$inpperm le?vperm $out4,$out4,$out4,$inpperm stvx_u $out3,$x00,$out le?vperm $out5,$out5,$out5,$inpperm stvx_u $out4,$x10,$out le?vperm $out6,$out6,$out6,$inpperm stvx_u $out5,$x20,$out le?vperm $out7,$out7,$out7,$inpperm stvx_u $out6,$x30,$out stvx_u $out7,$x40,$out addi $out,$out,0x50 b Lcbc_dec8x_done .align 5 Lcbc_dec8x_four: vncipherlast $out4,$out4,$ivec vncipherlast $out5,$out5,$in4 vncipherlast $out6,$out6,$in5 vncipherlast $out7,$out7,$in6 vmr $ivec,$in7 le?vperm $out4,$out4,$out4,$inpperm le?vperm $out5,$out5,$out5,$inpperm stvx_u $out4,$x00,$out le?vperm $out6,$out6,$out6,$inpperm stvx_u $out5,$x10,$out le?vperm $out7,$out7,$out7,$inpperm stvx_u $out6,$x20,$out stvx_u $out7,$x30,$out addi $out,$out,0x40 b Lcbc_dec8x_done .align 5 Lcbc_dec8x_three: vncipherlast $out5,$out5,$ivec vncipherlast $out6,$out6,$in5 vncipherlast $out7,$out7,$in6 vmr $ivec,$in7 le?vperm $out5,$out5,$out5,$inpperm le?vperm $out6,$out6,$out6,$inpperm stvx_u $out5,$x00,$out le?vperm $out7,$out7,$out7,$inpperm stvx_u $out6,$x10,$out stvx_u $out7,$x20,$out addi $out,$out,0x30 b Lcbc_dec8x_done .align 5 Lcbc_dec8x_two: vncipherlast $out6,$out6,$ivec vncipherlast $out7,$out7,$in6 vmr $ivec,$in7 le?vperm $out6,$out6,$out6,$inpperm le?vperm $out7,$out7,$out7,$inpperm stvx_u $out6,$x00,$out stvx_u $out7,$x10,$out addi $out,$out,0x20 b Lcbc_dec8x_done .align 5 Lcbc_dec8x_one: vncipherlast $out7,$out7,$ivec vmr $ivec,$in7 le?vperm $out7,$out7,$out7,$inpperm stvx_u $out7,0,$out addi $out,$out,0x10 Lcbc_dec8x_done: le?vperm $ivec,$ivec,$ivec,$inpperm stvx_u $ivec,0,$ivp # write [unaligned] iv li r10,`$FRAME+15` li r11,`$FRAME+31` stvx $inpperm,r10,$sp # wipe copies of round keys addi r10,r10,32 stvx $inpperm,r11,$sp addi r11,r11,32 stvx $inpperm,r10,$sp addi r10,r10,32 stvx $inpperm,r11,$sp addi r11,r11,32 stvx $inpperm,r10,$sp addi r10,r10,32 stvx $inpperm,r11,$sp addi r11,r11,32 stvx $inpperm,r10,$sp addi r10,r10,32 stvx $inpperm,r11,$sp addi r11,r11,32 mtspr 256,$vrsave lvx v20,r10,$sp # ABI says so addi r10,r10,32 lvx v21,r11,$sp addi r11,r11,32 lvx v22,r10,$sp addi r10,r10,32 lvx v23,r11,$sp addi r11,r11,32 lvx v24,r10,$sp addi r10,r10,32 lvx v25,r11,$sp addi r11,r11,32 lvx v26,r10,$sp addi r10,r10,32 lvx v27,r11,$sp addi r11,r11,32 lvx v28,r10,$sp addi r10,r10,32 lvx v29,r11,$sp addi r11,r11,32 lvx v30,r10,$sp lvx v31,r11,$sp $POP r26,`$FRAME+21*16+0*$SIZE_T`($sp) $POP r27,`$FRAME+21*16+1*$SIZE_T`($sp) $POP r28,`$FRAME+21*16+2*$SIZE_T`($sp) $POP r29,`$FRAME+21*16+3*$SIZE_T`($sp) $POP r30,`$FRAME+21*16+4*$SIZE_T`($sp) $POP r31,`$FRAME+21*16+5*$SIZE_T`($sp) addi $sp,$sp,`$FRAME+21*16+6*$SIZE_T` blr .long 0 .byte 0,12,0x14,0,0x80,6,6,0 .long 0 .size .${prefix}_cbc_encrypt,.-.${prefix}_cbc_encrypt ___ }} }}} ######################################################################### {{{ # CTR procedure[s] # ####################### WARNING: Here be dragons! ####################### # # This code is written as 'ctr32', based on a 32-bit counter used # upstream. The kernel does *not* use a 32-bit counter. The kernel uses # a 128-bit counter. # # This leads to subtle changes from the upstream code: the counter # is incremented with vaddu_q_m rather than vaddu_w_m. This occurs in # both the bulk (8 blocks at a time) path, and in the individual block # path. Be aware of this when doing updates. # # See: # 1d4aa0b4c181 ("crypto: vmx - Fixing AES-CTR counter bug") # 009b30ac7444 ("crypto: vmx - CTR: always increment IV as quadword") # https://github.com/openssl/openssl/pull/8942 # ######################################################################### my ($inp,$out,$len,$key,$ivp,$x10,$rounds,$idx)=map("r$_",(3..10)); my ($rndkey0,$rndkey1,$inout,$tmp)= map("v$_",(0..3)); my ($ivec,$inptail,$inpperm,$outhead,$outperm,$outmask,$keyperm,$one)= map("v$_",(4..11)); my $dat=$tmp; $code.=<<___; .globl .${prefix}_ctr32_encrypt_blocks ${UCMP}i $len,1 bltlr- lis r0,0xfff0 mfspr $vrsave,256 mtspr 256,r0 li $idx,15 vxor $rndkey0,$rndkey0,$rndkey0 le?vspltisb $tmp,0x0f lvx $ivec,0,$ivp # load [unaligned] iv lvsl $inpperm,0,$ivp lvx $inptail,$idx,$ivp vspltisb $one,1 le?vxor $inpperm,$inpperm,$tmp vperm $ivec,$ivec,$inptail,$inpperm vsldoi $one,$rndkey0,$one,1 neg r11,$inp ?lvsl $keyperm,0,$key # prepare for unaligned key lwz $rounds,240($key) lvsr $inpperm,0,r11 # prepare for unaligned load lvx $inptail,0,$inp addi $inp,$inp,15 # 15 is not typo le?vxor $inpperm,$inpperm,$tmp srwi $rounds,$rounds,1 li $idx,16 subi $rounds,$rounds,1 ${UCMP}i $len,8 bge _aesp8_ctr32_encrypt8x ?lvsr $outperm,0,$out # prepare for unaligned store vspltisb $outmask,-1 lvx $outhead,0,$out ?vperm $outmask,$rndkey0,$outmask,$outperm le?vxor $outperm,$outperm,$tmp lvx $rndkey0,0,$key mtctr $rounds lvx $rndkey1,$idx,$key addi $idx,$idx,16 ?vperm $rndkey0,$rndkey0,$rndkey1,$keyperm vxor $inout,$ivec,$rndkey0 lvx $rndkey0,$idx,$key addi $idx,$idx,16 b Loop_ctr32_enc .align 5 Loop_ctr32_enc: ?vperm $rndkey1,$rndkey1,$rndkey0,$keyperm vcipher $inout,$inout,$rndkey1 lvx $rndkey1,$idx,$key addi $idx,$idx,16 ?vperm $rndkey0,$rndkey0,$rndkey1,$keyperm vcipher $inout,$inout,$rndkey0 lvx $rndkey0,$idx,$key addi $idx,$idx,16 bdnz Loop_ctr32_enc vadduqm $ivec,$ivec,$one # Kernel change for 128-bit vmr $dat,$inptail lvx $inptail,0,$inp addi $inp,$inp,16 subic. $len,$len,1 # blocks-- ?vperm $rndkey1,$rndkey1,$rndkey0,$keyperm vcipher $inout,$inout,$rndkey1 lvx $rndkey1,$idx,$key vperm $dat,$dat,$inptail,$inpperm li $idx,16 ?vperm $rndkey1,$rndkey0,$rndkey1,$keyperm lvx $rndkey0,0,$key vxor $dat,$dat,$rndkey1 # last round key vcipherlast $inout,$inout,$dat lvx $rndkey1,$idx,$key addi $idx,$idx,16 vperm $inout,$inout,$inout,$outperm vsel $dat,$outhead,$inout,$outmask mtctr $rounds ?vperm $rndkey0,$rndkey0,$rndkey1,$keyperm vmr $outhead,$inout vxor $inout,$ivec,$rndkey0 lvx $rndkey0,$idx,$key addi $idx,$idx,16 stvx $dat,0,$out addi $out,$out,16 bne Loop_ctr32_enc addi $out,$out,-1 lvx $inout,0,$out # redundant in aligned case vsel $inout,$outhead,$inout,$outmask stvx $inout,0,$out mtspr 256,$vrsave blr .long 0 .byte 0,12,0x14,0,0,0,6,0 .long 0 ___ ######################################################################### {{ # Optimized CTR procedure # my $key_="r11"; my ($x00,$x10,$x20,$x30,$x40,$x50,$x60,$x70)=map("r$_",(0,8,26..31)); my ($in0, $in1, $in2, $in3, $in4, $in5, $in6, $in7 )=map("v$_",(0..3,10,12..14)); my ($out0,$out1,$out2,$out3,$out4,$out5,$out6,$out7)=map("v$_",(15..22)); my $rndkey0="v23"; # v24-v25 rotating buffer for first found keys # v26-v31 last 6 round keys my ($tmp,$keyperm)=($in3,$in4); # aliases with "caller", redundant assignment my ($two,$three,$four)=($outhead,$outperm,$outmask); $code.=<<___; .align 5 _aesp8_ctr32_encrypt8x: $STU $sp,-`($FRAME+21*16+6*$SIZE_T)`($sp) li r10,`$FRAME+8*16+15` li r11,`$FRAME+8*16+31` stvx v20,r10,$sp # ABI says so addi r10,r10,32 stvx v21,r11,$sp addi r11,r11,32 stvx v22,r10,$sp addi r10,r10,32 stvx v23,r11,$sp addi r11,r11,32 stvx v24,r10,$sp addi r10,r10,32 stvx v25,r11,$sp addi r11,r11,32 stvx v26,r10,$sp addi r10,r10,32 stvx v27,r11,$sp addi r11,r11,32 stvx v28,r10,$sp addi r10,r10,32 stvx v29,r11,$sp addi r11,r11,32 stvx v30,r10,$sp stvx v31,r11,$sp li r0,-1 stw $vrsave,`$FRAME+21*16-4`($sp) # save vrsave li $x10,0x10 $PUSH r26,`$FRAME+21*16+0*$SIZE_T`($sp) li $x20,0x20 $PUSH r27,`$FRAME+21*16+1*$SIZE_T`($sp) li $x30,0x30 $PUSH r28,`$FRAME+21*16+2*$SIZE_T`($sp) li $x40,0x40 $PUSH r29,`$FRAME+21*16+3*$SIZE_T`($sp) li $x50,0x50 $PUSH r30,`$FRAME+21*16+4*$SIZE_T`($sp) li $x60,0x60 $PUSH r31,`$FRAME+21*16+5*$SIZE_T`($sp) li $x70,0x70 mtspr 256,r0 subi $rounds,$rounds,3 # -4 in total lvx $rndkey0,$x00,$key # load key schedule lvx v30,$x10,$key addi $key,$key,0x20 lvx v31,$x00,$key ?vperm $rndkey0,$rndkey0,v30,$keyperm addi $key_,$sp,$FRAME+15 mtctr $rounds Load_ctr32_enc_key: ?vperm v24,v30,v31,$keyperm lvx v30,$x10,$key addi $key,$key,0x20 stvx v24,$x00,$key_ # off-load round[1] ?vperm v25,v31,v30,$keyperm lvx v31,$x00,$key stvx v25,$x10,$key_ # off-load round[2] addi $key_,$key_,0x20 bdnz Load_ctr32_enc_key lvx v26,$x10,$key ?vperm v24,v30,v31,$keyperm lvx v27,$x20,$key stvx v24,$x00,$key_ # off-load round[3] ?vperm v25,v31,v26,$keyperm lvx v28,$x30,$key stvx v25,$x10,$key_ # off-load round[4] addi $key_,$sp,$FRAME+15 # rewind $key_ ?vperm v26,v26,v27,$keyperm lvx v29,$x40,$key ?vperm v27,v27,v28,$keyperm lvx v30,$x50,$key ?vperm v28,v28,v29,$keyperm lvx v31,$x60,$key ?vperm v29,v29,v30,$keyperm lvx $out0,$x70,$key # borrow $out0 ?vperm v30,v30,v31,$keyperm lvx v24,$x00,$key_ # pre-load round[1] ?vperm v31,v31,$out0,$keyperm lvx v25,$x10,$key_ # pre-load round[2] vadduqm $two,$one,$one subi $inp,$inp,15 # undo "caller" $SHL $len,$len,4 vadduqm $out1,$ivec,$one # counter values ... vadduqm $out2,$ivec,$two # (do all ctr adds as 128-bit) vxor $out0,$ivec,$rndkey0 # ... xored with rndkey[0] le?li $idx,8 vadduqm $out3,$out1,$two vxor $out1,$out1,$rndkey0 le?lvsl $inpperm,0,$idx vadduqm $out4,$out2,$two vxor $out2,$out2,$rndkey0 le?vspltisb $tmp,0x0f vadduqm $out5,$out3,$two vxor $out3,$out3,$rndkey0 le?vxor $inpperm,$inpperm,$tmp # transform for lvx_u/stvx_u vadduqm $out6,$out4,$two vxor $out4,$out4,$rndkey0 vadduqm $out7,$out5,$two vxor $out5,$out5,$rndkey0 vadduqm $ivec,$out6,$two # next counter value vxor $out6,$out6,$rndkey0 vxor $out7,$out7,$rndkey0 mtctr $rounds b Loop_ctr32_enc8x .align 5 Loop_ctr32_enc8x: vcipher $out0,$out0,v24 vcipher $out1,$out1,v24 vcipher $out2,$out2,v24 vcipher $out3,$out3,v24 vcipher $out4,$out4,v24 vcipher $out5,$out5,v24 vcipher $out6,$out6,v24 vcipher $out7,$out7,v24 Loop_ctr32_enc8x_middle: lvx v24,$x20,$key_ # round[3] addi $key_,$key_,0x20 vcipher $out0,$out0,v25 vcipher $out1,$out1,v25 vcipher $out2,$out2,v25 vcipher $out3,$out3,v25 vcipher $out4,$out4,v25 vcipher $out5,$out5,v25 vcipher $out6,$out6,v25 vcipher $out7,$out7,v25 lvx v25,$x10,$key_ # round[4] bdnz Loop_ctr32_enc8x subic r11,$len,256 # $len-256, borrow $key_ vcipher $out0,$out0,v24 vcipher $out1,$out1,v24 vcipher $out2,$out2,v24 vcipher $out3,$out3,v24 vcipher $out4,$out4,v24 vcipher $out5,$out5,v24 vcipher $out6,$out6,v24 vcipher $out7,$out7,v24 subfe r0,r0,r0 # borrow?-1:0 vcipher $out0,$out0,v25 vcipher $out1,$out1,v25 vcipher $out2,$out2,v25 vcipher $out3,$out3,v25 vcipher $out4,$out4,v25 vcipher $out5,$out5,v25 vcipher $out6,$out6,v25 vcipher $out7,$out7,v25 and r0,r0,r11 addi $key_,$sp,$FRAME+15 # rewind $key_ vcipher $out0,$out0,v26 vcipher $out1,$out1,v26 vcipher $out2,$out2,v26 vcipher $out3,$out3,v26 vcipher $out4,$out4,v26 vcipher $out5,$out5,v26 vcipher $out6,$out6,v26 vcipher $out7,$out7,v26 lvx v24,$x00,$key_ # re-pre-load round[1] subic $len,$len,129 # $len-=129 vcipher $out0,$out0,v27 addi $len,$len,1 # $len-=128 really vcipher $out1,$out1,v27 vcipher $out2,$out2,v27 vcipher $out3,$out3,v27 vcipher $out4,$out4,v27 vcipher $out5,$out5,v27 vcipher $out6,$out6,v27 vcipher $out7,$out7,v27 lvx v25,$x10,$key_ # re-pre-load round[2] vcipher $out0,$out0,v28 lvx_u $in0,$x00,$inp # load input vcipher $out1,$out1,v28 lvx_u $in1,$x10,$inp vcipher $out2,$out2,v28 lvx_u $in2,$x20,$inp vcipher $out3,$out3,v28 lvx_u $in3,$x30,$inp vcipher $out4,$out4,v28 lvx_u $in4,$x40,$inp vcipher $out5,$out5,v28 lvx_u $in5,$x50,$inp vcipher $out6,$out6,v28 lvx_u $in6,$x60,$inp vcipher $out7,$out7,v28 lvx_u $in7,$x70,$inp addi $inp,$inp,0x80 vcipher $out0,$out0,v29 le?vperm $in0,$in0,$in0,$inpperm vcipher $out1,$out1,v29 le?vperm $in1,$in1,$in1,$inpperm vcipher $out2,$out2,v29 le?vperm $in2,$in2,$in2,$inpperm vcipher $out3,$out3,v29 le?vperm $in3,$in3,$in3,$inpperm vcipher $out4,$out4,v29 le?vperm $in4,$in4,$in4,$inpperm vcipher $out5,$out5,v29 le?vperm $in5,$in5,$in5,$inpperm vcipher $out6,$out6,v29 le?vperm $in6,$in6,$in6,$inpperm vcipher $out7,$out7,v29 le?vperm $in7,$in7,$in7,$inpperm add $inp,$inp,r0 # $inp is adjusted in such # way that at exit from the # loop inX-in7 are loaded # with last "words" subfe. r0,r0,r0 # borrow?-1:0 vcipher $out0,$out0,v30 vxor $in0,$in0,v31 # xor with last round key vcipher $out1,$out1,v30 vxor $in1,$in1,v31 vcipher $out2,$out2,v30 vxor $in2,$in2,v31 vcipher $out3,$out3,v30 vxor $in3,$in3,v31 vcipher $out4,$out4,v30 vxor $in4,$in4,v31 vcipher $out5,$out5,v30 vxor $in5,$in5,v31 vcipher $out6,$out6,v30 vxor $in6,$in6,v31 vcipher $out7,$out7,v30 vxor $in7,$in7,v31 bne Lctr32_enc8x_break # did $len-129 borrow? vcipherlast $in0,$out0,$in0 vcipherlast $in1,$out1,$in1 vadduqm $out1,$ivec,$one # counter values ... vcipherlast $in2,$out2,$in2 vadduqm $out2,$ivec,$two vxor $out0,$ivec,$rndkey0 # ... xored with rndkey[0] vcipherlast $in3,$out3,$in3 vadduqm $out3,$out1,$two vxor $out1,$out1,$rndkey0 vcipherlast $in4,$out4,$in4 vadduqm $out4,$out2,$two vxor $out2,$out2,$rndkey0 vcipherlast $in5,$out5,$in5 vadduqm $out5,$out3,$two vxor $out3,$out3,$rndkey0 vcipherlast $in6,$out6,$in6 vadduqm $out6,$out4,$two vxor $out4,$out4,$rndkey0 vcipherlast $in7,$out7,$in7 vadduqm $out7,$out5,$two vxor $out5,$out5,$rndkey0 le?vperm $in0,$in0,$in0,$inpperm vadduqm $ivec,$out6,$two # next counter value vxor $out6,$out6,$rndkey0 le?vperm $in1,$in1,$in1,$inpperm vxor $out7,$out7,$rndkey0 mtctr $rounds vcipher $out0,$out0,v24 stvx_u $in0,$x00,$out le?vperm $in2,$in2,$in2,$inpperm vcipher $out1,$out1,v24 stvx_u $in1,$x10,$out le?vperm $in3,$in3,$in3,$inpperm vcipher $out2,$out2,v24 stvx_u $in2,$x20,$out le?vperm $in4,$in4,$in4,$inpperm vcipher $out3,$out3,v24 stvx_u $in3,$x30,$out le?vperm $in5,$in5,$in5,$inpperm vcipher $out4,$out4,v24 stvx_u $in4,$x40,$out le?vperm $in6,$in6,$in6,$inpperm vcipher $out5,$out5,v24 stvx_u $in5,$x50,$out le?vperm $in7,$in7,$in7,$inpperm vcipher $out6,$out6,v24 stvx_u $in6,$x60,$out vcipher $out7,$out7,v24 stvx_u $in7,$x70,$out addi $out,$out,0x80 b Loop_ctr32_enc8x_middle .align 5 Lctr32_enc8x_break: cmpwi $len,-0x60 blt Lctr32_enc8x_one nop beq Lctr32_enc8x_two cmpwi $len,-0x40 blt Lctr32_enc8x_three nop beq Lctr32_enc8x_four cmpwi $len,-0x20 blt Lctr32_enc8x_five nop beq Lctr32_enc8x_six cmpwi $len,0x00 blt Lctr32_enc8x_seven Lctr32_enc8x_eight: vcipherlast $out0,$out0,$in0 vcipherlast $out1,$out1,$in1 vcipherlast $out2,$out2,$in2 vcipherlast $out3,$out3,$in3 vcipherlast $out4,$out4,$in4 vcipherlast $out5,$out5,$in5 vcipherlast $out6,$out6,$in6 vcipherlast $out7,$out7,$in7 le?vperm $out0,$out0,$out0,$inpperm le?vperm $out1,$out1,$out1,$inpperm stvx_u $out0,$x00,$out le?vperm $out2,$out2,$out2,$inpperm stvx_u $out1,$x10,$out le?vperm $out3,$out3,$out3,$inpperm stvx_u $out2,$x20,$out le?vperm $out4,$out4,$out4,$inpperm stvx_u $out3,$x30,$out le?vperm $out5,$out5,$out5,$inpperm stvx_u $out4,$x40,$out le?vperm $out6,$out6,$out6,$inpperm stvx_u $out5,$x50,$out le?vperm $out7,$out7,$out7,$inpperm stvx_u $out6,$x60,$out stvx_u $out7,$x70,$out addi $out,$out,0x80 b Lctr32_enc8x_done .align 5 Lctr32_enc8x_seven: vcipherlast $out0,$out0,$in1 vcipherlast $out1,$out1,$in2 vcipherlast $out2,$out2,$in3 vcipherlast $out3,$out3,$in4 vcipherlast $out4,$out4,$in5 vcipherlast $out5,$out5,$in6 vcipherlast $out6,$out6,$in7 le?vperm $out0,$out0,$out0,$inpperm le?vperm $out1,$out1,$out1,$inpperm stvx_u $out0,$x00,$out le?vperm $out2,$out2,$out2,$inpperm stvx_u $out1,$x10,$out le?vperm $out3,$out3,$out3,$inpperm stvx_u $out2,$x20,$out le?vperm $out4,$out4,$out4,$inpperm stvx_u $out3,$x30,$out le?vperm $out5,$out5,$out5,$inpperm stvx_u $out4,$x40,$out le?vperm $out6,$out6,$out6,$inpperm stvx_u $out5,$x50,$out stvx_u $out6,$x60,$out addi $out,$out,0x70 b Lctr32_enc8x_done .align 5 Lctr32_enc8x_six: vcipherlast $out0,$out0,$in2 vcipherlast $out1,$out1,$in3 vcipherlast $out2,$out2,$in4 vcipherlast $out3,$out3,$in5 vcipherlast $out4,$out4,$in6 vcipherlast $out5,$out5,$in7 le?vperm $out0,$out0,$out0,$inpperm le?vperm $out1,$out1,$out1,$inpperm stvx_u $out0,$x00,$out le?vperm $out2,$out2,$out2,$inpperm stvx_u $out1,$x10,$out le?vperm $out3,$out3,$out3,$inpperm stvx_u $out2,$x20,$out le?vperm $out4,$out4,$out4,$inpperm stvx_u $out3,$x30,$out le?vperm $out5,$out5,$out5,$inpperm stvx_u $out4,$x40,$out stvx_u $out5,$x50,$out addi $out,$out,0x60 b Lctr32_enc8x_done .align 5 Lctr32_enc8x_five: vcipherlast $out0,$out0,$in3 vcipherlast $out1,$out1,$in4 vcipherlast $out2,$out2,$in5 vcipherlast $out3,$out3,$in6 vcipherlast $out4,$out4,$in7 le?vperm $out0,$out0,$out0,$inpperm le?vperm $out1,$out1,$out1,$inpperm stvx_u $out0,$x00,$out le?vperm $out2,$out2,$out2,$inpperm stvx_u $out1,$x10,$out le?vperm $out3,$out3,$out3,$inpperm stvx_u $out2,$x20,$out le?vperm $out4,$out4,$out4,$inpperm stvx_u $out3,$x30,$out stvx_u $out4,$x40,$out addi $out,$out,0x50 b Lctr32_enc8x_done .align 5 Lctr32_enc8x_four: vcipherlast $out0,$out0,$in4 vcipherlast $out1,$out1,$in5 vcipherlast $out2,$out2,$in6 vcipherlast $out3,$out3,$in7 le?vperm $out0,$out0,$out0,$inpperm le?vperm $out1,$out1,$out1,$inpperm stvx_u $out0,$x00,$out le?vperm $out2,$out2,$out2,$inpperm stvx_u $out1,$x10,$out le?vperm $out3,$out3,$out3,$inpperm stvx_u $out2,$x20,$out stvx_u $out3,$x30,$out addi $out,$out,0x40 b Lctr32_enc8x_done .align 5 Lctr32_enc8x_three: vcipherlast $out0,$out0,$in5 vcipherlast $out1,$out1,$in6 vcipherlast $out2,$out2,$in7 le?vperm $out0,$out0,$out0,$inpperm le?vperm $out1,$out1,$out1,$inpperm stvx_u $out0,$x00,$out le?vperm $out2,$out2,$out2,$inpperm stvx_u $out1,$x10,$out stvx_u $out2,$x20,$out addi $out,$out,0x30 b Lctr32_enc8x_done .align 5 Lctr32_enc8x_two: vcipherlast $out0,$out0,$in6 vcipherlast $out1,$out1,$in7 le?vperm $out0,$out0,$out0,$inpperm le?vperm $out1,$out1,$out1,$inpperm stvx_u $out0,$x00,$out stvx_u $out1,$x10,$out addi $out,$out,0x20 b Lctr32_enc8x_done .align 5 Lctr32_enc8x_one: vcipherlast $out0,$out0,$in7 le?vperm $out0,$out0,$out0,$inpperm stvx_u $out0,0,$out addi $out,$out,0x10 Lctr32_enc8x_done: li r10,`$FRAME+15` li r11,`$FRAME+31` stvx $inpperm,r10,$sp # wipe copies of round keys addi r10,r10,32 stvx $inpperm,r11,$sp addi r11,r11,32 stvx $inpperm,r10,$sp addi r10,r10,32 stvx $inpperm,r11,$sp addi r11,r11,32 stvx $inpperm,r10,$sp addi r10,r10,32 stvx $inpperm,r11,$sp addi r11,r11,32 stvx $inpperm,r10,$sp addi r10,r10,32 stvx $inpperm,r11,$sp addi r11,r11,32 mtspr 256,$vrsave lvx v20,r10,$sp # ABI says so addi r10,r10,32 lvx v21,r11,$sp addi r11,r11,32 lvx v22,r10,$sp addi r10,r10,32 lvx v23,r11,$sp addi r11,r11,32 lvx v24,r10,$sp addi r10,r10,32 lvx v25,r11,$sp addi r11,r11,32 lvx v26,r10,$sp addi r10,r10,32 lvx v27,r11,$sp addi r11,r11,32 lvx v28,r10,$sp addi r10,r10,32 lvx v29,r11,$sp addi r11,r11,32 lvx v30,r10,$sp lvx v31,r11,$sp $POP r26,`$FRAME+21*16+0*$SIZE_T`($sp) $POP r27,`$FRAME+21*16+1*$SIZE_T`($sp) $POP r28,`$FRAME+21*16+2*$SIZE_T`($sp) $POP r29,`$FRAME+21*16+3*$SIZE_T`($sp) $POP r30,`$FRAME+21*16+4*$SIZE_T`($sp) $POP r31,`$FRAME+21*16+5*$SIZE_T`($sp) addi $sp,$sp,`$FRAME+21*16+6*$SIZE_T` blr .long 0 .byte 0,12,0x14,0,0x80,6,6,0 .long 0 .size .${prefix}_ctr32_encrypt_blocks,.-.${prefix}_ctr32_encrypt_blocks ___ }} }}} ######################################################################### {{{ # XTS procedures # # int aes_p8_xts_[en|de]crypt(const char *inp, char *out, size_t len, # # const AES_KEY *key1, const AES_KEY *key2, # # [const] unsigned char iv[16]); # # If $key2 is NULL, then a "tweak chaining" mode is engaged, in which # # input tweak value is assumed to be encrypted already, and last tweak # # value, one suitable for consecutive call on same chunk of data, is # # written back to original buffer. In addition, in "tweak chaining" # # mode only complete input blocks are processed. # my ($inp,$out,$len,$key1,$key2,$ivp,$rounds,$idx) = map("r$_",(3..10)); my ($rndkey0,$rndkey1,$inout) = map("v$_",(0..2)); my ($output,$inptail,$inpperm,$leperm,$keyperm) = map("v$_",(3..7)); my ($tweak,$seven,$eighty7,$tmp,$tweak1) = map("v$_",(8..12)); my $taillen = $key2; ($inp,$idx) = ($idx,$inp); # reassign $code.=<<___; .globl .${prefix}_xts_encrypt mr $inp,r3 # reassign li r3,-1 ${UCMP}i $len,16 bltlr- lis r0,0xfff0 mfspr r12,256 # save vrsave li r11,0 mtspr 256,r0 vspltisb $seven,0x07 # 0x070707..07 le?lvsl $leperm,r11,r11 le?vspltisb $tmp,0x0f le?vxor $leperm,$leperm,$seven li $idx,15 lvx $tweak,0,$ivp # load [unaligned] iv lvsl $inpperm,0,$ivp lvx $inptail,$idx,$ivp le?vxor $inpperm,$inpperm,$tmp vperm $tweak,$tweak,$inptail,$inpperm neg r11,$inp lvsr $inpperm,0,r11 # prepare for unaligned load lvx $inout,0,$inp addi $inp,$inp,15 # 15 is not typo le?vxor $inpperm,$inpperm,$tmp ${UCMP}i $key2,0 # key2==NULL? beq Lxts_enc_no_key2 ?lvsl $keyperm,0,$key2 # prepare for unaligned key lwz $rounds,240($key2) srwi $rounds,$rounds,1 subi $rounds,$rounds,1 li $idx,16 lvx $rndkey0,0,$key2 lvx $rndkey1,$idx,$key2 addi $idx,$idx,16 ?vperm $rndkey0,$rndkey0,$rndkey1,$keyperm vxor $tweak,$tweak,$rndkey0 lvx $rndkey0,$idx,$key2 addi $idx,$idx,16 mtctr $rounds Ltweak_xts_enc: ?vperm $rndkey1,$rndkey1,$rndkey0,$keyperm vcipher $tweak,$tweak,$rndkey1 lvx $rndkey1,$idx,$key2 addi $idx,$idx,16 ?vperm $rndkey0,$rndkey0,$rndkey1,$keyperm vcipher $tweak,$tweak,$rndkey0 lvx $rndkey0,$idx,$key2 addi $idx,$idx,16 bdnz Ltweak_xts_enc ?vperm $rndkey1,$rndkey1,$rndkey0,$keyperm vcipher $tweak,$tweak,$rndkey1 lvx $rndkey1,$idx,$key2 ?vperm $rndkey0,$rndkey0,$rndkey1,$keyperm vcipherlast $tweak,$tweak,$rndkey0 li $ivp,0 # don't chain the tweak b Lxts_enc Lxts_enc_no_key2: li $idx,-16 and $len,$len,$idx # in "tweak chaining" # mode only complete # blocks are processed Lxts_enc: lvx $inptail,0,$inp addi $inp,$inp,16 ?lvsl $keyperm,0,$key1 # prepare for unaligned key lwz $rounds,240($key1) srwi $rounds,$rounds,1 subi $rounds,$rounds,1 li $idx,16 vslb $eighty7,$seven,$seven # 0x808080..80 vor $eighty7,$eighty7,$seven # 0x878787..87 vspltisb $tmp,1 # 0x010101..01 vsldoi $eighty7,$eighty7,$tmp,15 # 0x870101..01 ${UCMP}i $len,96 bge _aesp8_xts_encrypt6x andi. $taillen,$len,15 subic r0,$len,32 subi $taillen,$taillen,16 subfe r0,r0,r0 and r0,r0,$taillen add $inp,$inp,r0 lvx $rndkey0,0,$key1 lvx $rndkey1,$idx,$key1 addi $idx,$idx,16 vperm $inout,$inout,$inptail,$inpperm ?vperm $rndkey0,$rndkey0,$rndkey1,$keyperm vxor $inout,$inout,$tweak vxor $inout,$inout,$rndkey0 lvx $rndkey0,$idx,$key1 addi $idx,$idx,16 mtctr $rounds b Loop_xts_enc .align 5 Loop_xts_enc: ?vperm $rndkey1,$rndkey1,$rndkey0,$keyperm vcipher $inout,$inout,$rndkey1 lvx $rndkey1,$idx,$key1 addi $idx,$idx,16 ?vperm $rndkey0,$rndkey0,$rndkey1,$keyperm vcipher $inout,$inout,$rndkey0 lvx $rndkey0,$idx,$key1 addi $idx,$idx,16 bdnz Loop_xts_enc ?vperm $rndkey1,$rndkey1,$rndkey0,$keyperm vcipher $inout,$inout,$rndkey1 lvx $rndkey1,$idx,$key1 li $idx,16 ?vperm $rndkey0,$rndkey0,$rndkey1,$keyperm vxor $rndkey0,$rndkey0,$tweak vcipherlast $output,$inout,$rndkey0 le?vperm $tmp,$output,$output,$leperm be?nop le?stvx_u $tmp,0,$out be?stvx_u $output,0,$out addi $out,$out,16 subic. $len,$len,16 beq Lxts_enc_done vmr $inout,$inptail lvx $inptail,0,$inp addi $inp,$inp,16 lvx $rndkey0,0,$key1 lvx $rndkey1,$idx,$key1 addi $idx,$idx,16 subic r0,$len,32 subfe r0,r0,r0 and r0,r0,$taillen add $inp,$inp,r0 vsrab $tmp,$tweak,$seven # next tweak value vaddubm $tweak,$tweak,$tweak vsldoi $tmp,$tmp,$tmp,15 vand $tmp,$tmp,$eighty7 vxor $tweak,$tweak,$tmp vperm $inout,$inout,$inptail,$inpperm ?vperm $rndkey0,$rndkey0,$rndkey1,$keyperm vxor $inout,$inout,$tweak vxor $output,$output,$rndkey0 # just in case $len<16 vxor $inout,$inout,$rndkey0 lvx $rndkey0,$idx,$key1 addi $idx,$idx,16 mtctr $rounds ${UCMP}i $len,16 bge Loop_xts_enc vxor $output,$output,$tweak lvsr $inpperm,0,$len # $inpperm is no longer needed vxor $inptail,$inptail,$inptail # $inptail is no longer needed vspltisb $tmp,-1 vperm $inptail,$inptail,$tmp,$inpperm vsel $inout,$inout,$output,$inptail subi r11,$out,17 subi $out,$out,16 mtctr $len li $len,16 Loop_xts_enc_steal: lbzu r0,1(r11) stb r0,16(r11) bdnz Loop_xts_enc_steal mtctr $rounds b Loop_xts_enc # one more time... Lxts_enc_done: ${UCMP}i $ivp,0 beq Lxts_enc_ret vsrab $tmp,$tweak,$seven # next tweak value vaddubm $tweak,$tweak,$tweak vsldoi $tmp,$tmp,$tmp,15 vand $tmp,$tmp,$eighty7 vxor $tweak,$tweak,$tmp le?vperm $tweak,$tweak,$tweak,$leperm stvx_u $tweak,0,$ivp Lxts_enc_ret: mtspr 256,r12 # restore vrsave li r3,0 blr .long 0 .byte 0,12,0x04,0,0x80,6,6,0 .long 0 .size .${prefix}_xts_encrypt,.-.${prefix}_xts_encrypt .globl .${prefix}_xts_decrypt mr $inp,r3 # reassign li r3,-1 ${UCMP}i $len,16 bltlr- lis r0,0xfff8 mfspr r12,256 # save vrsave li r11,0 mtspr 256,r0 andi. r0,$len,15 neg r0,r0 andi. r0,r0,16 sub $len,$len,r0 vspltisb $seven,0x07 # 0x070707..07 le?lvsl $leperm,r11,r11 le?vspltisb $tmp,0x0f le?vxor $leperm,$leperm,$seven li $idx,15 lvx $tweak,0,$ivp # load [unaligned] iv lvsl $inpperm,0,$ivp lvx $inptail,$idx,$ivp le?vxor $inpperm,$inpperm,$tmp vperm $tweak,$tweak,$inptail,$inpperm neg r11,$inp lvsr $inpperm,0,r11 # prepare for unaligned load lvx $inout,0,$inp addi $inp,$inp,15 # 15 is not typo le?vxor $inpperm,$inpperm,$tmp ${UCMP}i $key2,0 # key2==NULL? beq Lxts_dec_no_key2 ?lvsl $keyperm,0,$key2 # prepare for unaligned key lwz $rounds,240($key2) srwi $rounds,$rounds,1 subi $rounds,$rounds,1 li $idx,16 lvx $rndkey0,0,$key2 lvx $rndkey1,$idx,$key2 addi $idx,$idx,16 ?vperm $rndkey0,$rndkey0,$rndkey1,$keyperm vxor $tweak,$tweak,$rndkey0 lvx $rndkey0,$idx,$key2 addi $idx,$idx,16 mtctr $rounds Ltweak_xts_dec: ?vperm $rndkey1,$rndkey1,$rndkey0,$keyperm vcipher $tweak,$tweak,$rndkey1 lvx $rndkey1,$idx,$key2 addi $idx,$idx,16 ?vperm $rndkey0,$rndkey0,$rndkey1,$keyperm vcipher $tweak,$tweak,$rndkey0 lvx $rndkey0,$idx,$key2 addi $idx,$idx,16 bdnz Ltweak_xts_dec ?vperm $rndkey1,$rndkey1,$rndkey0,$keyperm vcipher $tweak,$tweak,$rndkey1 lvx $rndkey1,$idx,$key2 ?vperm $rndkey0,$rndkey0,$rndkey1,$keyperm vcipherlast $tweak,$tweak,$rndkey0 li $ivp,0 # don't chain the tweak b Lxts_dec Lxts_dec_no_key2: neg $idx,$len andi. $idx,$idx,15 add $len,$len,$idx # in "tweak chaining" # mode only complete # blocks are processed Lxts_dec: lvx $inptail,0,$inp addi $inp,$inp,16 ?lvsl $keyperm,0,$key1 # prepare for unaligned key lwz $rounds,240($key1) srwi $rounds,$rounds,1 subi $rounds,$rounds,1 li $idx,16 vslb $eighty7,$seven,$seven # 0x808080..80 vor $eighty7,$eighty7,$seven # 0x878787..87 vspltisb $tmp,1 # 0x010101..01 vsldoi $eighty7,$eighty7,$tmp,15 # 0x870101..01 ${UCMP}i $len,96 bge _aesp8_xts_decrypt6x lvx $rndkey0,0,$key1 lvx $rndkey1,$idx,$key1 addi $idx,$idx,16 vperm $inout,$inout,$inptail,$inpperm ?vperm $rndkey0,$rndkey0,$rndkey1,$keyperm vxor $inout,$inout,$tweak vxor $inout,$inout,$rndkey0 lvx $rndkey0,$idx,$key1 addi $idx,$idx,16 mtctr $rounds ${UCMP}i $len,16 blt Ltail_xts_dec be?b Loop_xts_dec .align 5 Loop_xts_dec: ?vperm $rndkey1,$rndkey1,$rndkey0,$keyperm vncipher $inout,$inout,$rndkey1 lvx $rndkey1,$idx,$key1 addi $idx,$idx,16 ?vperm $rndkey0,$rndkey0,$rndkey1,$keyperm vncipher $inout,$inout,$rndkey0 lvx $rndkey0,$idx,$key1 addi $idx,$idx,16 bdnz Loop_xts_dec ?vperm $rndkey1,$rndkey1,$rndkey0,$keyperm vncipher $inout,$inout,$rndkey1 lvx $rndkey1,$idx,$key1 li $idx,16 ?vperm $rndkey0,$rndkey0,$rndkey1,$keyperm vxor $rndkey0,$rndkey0,$tweak vncipherlast $output,$inout,$rndkey0 le?vperm $tmp,$output,$output,$leperm be?nop le?stvx_u $tmp,0,$out be?stvx_u $output,0,$out addi $out,$out,16 subic. $len,$len,16 beq Lxts_dec_done vmr $inout,$inptail lvx $inptail,0,$inp addi $inp,$inp,16 lvx $rndkey0,0,$key1 lvx $rndkey1,$idx,$key1 addi $idx,$idx,16 vsrab $tmp,$tweak,$seven # next tweak value vaddubm $tweak,$tweak,$tweak vsldoi $tmp,$tmp,$tmp,15 vand $tmp,$tmp,$eighty7 vxor $tweak,$tweak,$tmp vperm $inout,$inout,$inptail,$inpperm ?vperm $rndkey0,$rndkey0,$rndkey1,$keyperm vxor $inout,$inout,$tweak vxor $inout,$inout,$rndkey0 lvx $rndkey0,$idx,$key1 addi $idx,$idx,16 mtctr $rounds ${UCMP}i $len,16 bge Loop_xts_dec Ltail_xts_dec: vsrab $tmp,$tweak,$seven # next tweak value vaddubm $tweak1,$tweak,$tweak vsldoi $tmp,$tmp,$tmp,15 vand $tmp,$tmp,$eighty7 vxor $tweak1,$tweak1,$tmp subi $inp,$inp,16 add $inp,$inp,$len vxor $inout,$inout,$tweak # :-( vxor $inout,$inout,$tweak1 # :-) Loop_xts_dec_short: ?vperm $rndkey1,$rndkey1,$rndkey0,$keyperm vncipher $inout,$inout,$rndkey1 lvx $rndkey1,$idx,$key1 addi $idx,$idx,16 ?vperm $rndkey0,$rndkey0,$rndkey1,$keyperm vncipher $inout,$inout,$rndkey0 lvx $rndkey0,$idx,$key1 addi $idx,$idx,16 bdnz Loop_xts_dec_short ?vperm $rndkey1,$rndkey1,$rndkey0,$keyperm vncipher $inout,$inout,$rndkey1 lvx $rndkey1,$idx,$key1 li $idx,16 ?vperm $rndkey0,$rndkey0,$rndkey1,$keyperm vxor $rndkey0,$rndkey0,$tweak1 vncipherlast $output,$inout,$rndkey0 le?vperm $tmp,$output,$output,$leperm be?nop le?stvx_u $tmp,0,$out be?stvx_u $output,0,$out vmr $inout,$inptail lvx $inptail,0,$inp #addi $inp,$inp,16 lvx $rndkey0,0,$key1 lvx $rndkey1,$idx,$key1 addi $idx,$idx,16 vperm $inout,$inout,$inptail,$inpperm ?vperm $rndkey0,$rndkey0,$rndkey1,$keyperm lvsr $inpperm,0,$len # $inpperm is no longer needed vxor $inptail,$inptail,$inptail # $inptail is no longer needed vspltisb $tmp,-1 vperm $inptail,$inptail,$tmp,$inpperm vsel $inout,$inout,$output,$inptail vxor $rndkey0,$rndkey0,$tweak vxor $inout,$inout,$rndkey0 lvx $rndkey0,$idx,$key1 addi $idx,$idx,16 subi r11,$out,1 mtctr $len li $len,16 Loop_xts_dec_steal: lbzu r0,1(r11) stb r0,16(r11) bdnz Loop_xts_dec_steal mtctr $rounds b Loop_xts_dec # one more time... Lxts_dec_done: ${UCMP}i $ivp,0 beq Lxts_dec_ret vsrab $tmp,$tweak,$seven # next tweak value vaddubm $tweak,$tweak,$tweak vsldoi $tmp,$tmp,$tmp,15 vand $tmp,$tmp,$eighty7 vxor $tweak,$tweak,$tmp le?vperm $tweak,$tweak,$tweak,$leperm stvx_u $tweak,0,$ivp Lxts_dec_ret: mtspr 256,r12 # restore vrsave li r3,0 blr .long 0 .byte 0,12,0x04,0,0x80,6,6,0 .long 0 .size .${prefix}_xts_decrypt,.-.${prefix}_xts_decrypt ___ ######################################################################### {{ # Optimized XTS procedures # my $key_=$key2; my ($x00,$x10,$x20,$x30,$x40,$x50,$x60,$x70)=map("r$_",(0,3,26..31)); $x00=0 if ($flavour =~ /osx/); my ($in0, $in1, $in2, $in3, $in4, $in5 )=map("v$_",(0..5)); my ($out0, $out1, $out2, $out3, $out4, $out5)=map("v$_",(7,12..16)); my ($twk0, $twk1, $twk2, $twk3, $twk4, $twk5)=map("v$_",(17..22)); my $rndkey0="v23"; # v24-v25 rotating buffer for first found keys # v26-v31 last 6 round keys my ($keyperm)=($out0); # aliases with "caller", redundant assignment my $taillen=$x70; $code.=<<___; .align 5 _aesp8_xts_encrypt6x: $STU $sp,-`($FRAME+21*16+6*$SIZE_T)`($sp) mflr r11 li r7,`$FRAME+8*16+15` li r3,`$FRAME+8*16+31` $PUSH r11,`$FRAME+21*16+6*$SIZE_T+$LRSAVE`($sp) stvx v20,r7,$sp # ABI says so addi r7,r7,32 stvx v21,r3,$sp addi r3,r3,32 stvx v22,r7,$sp addi r7,r7,32 stvx v23,r3,$sp addi r3,r3,32 stvx v24,r7,$sp addi r7,r7,32 stvx v25,r3,$sp addi r3,r3,32 stvx v26,r7,$sp addi r7,r7,32 stvx v27,r3,$sp addi r3,r3,32 stvx v28,r7,$sp addi r7,r7,32 stvx v29,r3,$sp addi r3,r3,32 stvx v30,r7,$sp stvx v31,r3,$sp li r0,-1 stw $vrsave,`$FRAME+21*16-4`($sp) # save vrsave li $x10,0x10 $PUSH r26,`$FRAME+21*16+0*$SIZE_T`($sp) li $x20,0x20 $PUSH r27,`$FRAME+21*16+1*$SIZE_T`($sp) li $x30,0x30 $PUSH r28,`$FRAME+21*16+2*$SIZE_T`($sp) li $x40,0x40 $PUSH r29,`$FRAME+21*16+3*$SIZE_T`($sp) li $x50,0x50 $PUSH r30,`$FRAME+21*16+4*$SIZE_T`($sp) li $x60,0x60 $PUSH r31,`$FRAME+21*16+5*$SIZE_T`($sp) li $x70,0x70 mtspr 256,r0 subi $rounds,$rounds,3 # -4 in total lvx $rndkey0,$x00,$key1 # load key schedule lvx v30,$x10,$key1 addi $key1,$key1,0x20 lvx v31,$x00,$key1 ?vperm $rndkey0,$rndkey0,v30,$keyperm addi $key_,$sp,$FRAME+15 mtctr $rounds Load_xts_enc_key: ?vperm v24,v30,v31,$keyperm lvx v30,$x10,$key1 addi $key1,$key1,0x20 stvx v24,$x00,$key_ # off-load round[1] ?vperm v25,v31,v30,$keyperm lvx v31,$x00,$key1 stvx v25,$x10,$key_ # off-load round[2] addi $key_,$key_,0x20 bdnz Load_xts_enc_key lvx v26,$x10,$key1 ?vperm v24,v30,v31,$keyperm lvx v27,$x20,$key1 stvx v24,$x00,$key_ # off-load round[3] ?vperm v25,v31,v26,$keyperm lvx v28,$x30,$key1 stvx v25,$x10,$key_ # off-load round[4] addi $key_,$sp,$FRAME+15 # rewind $key_ ?vperm v26,v26,v27,$keyperm lvx v29,$x40,$key1 ?vperm v27,v27,v28,$keyperm lvx v30,$x50,$key1 ?vperm v28,v28,v29,$keyperm lvx v31,$x60,$key1 ?vperm v29,v29,v30,$keyperm lvx $twk5,$x70,$key1 # borrow $twk5 ?vperm v30,v30,v31,$keyperm lvx v24,$x00,$key_ # pre-load round[1] ?vperm v31,v31,$twk5,$keyperm lvx v25,$x10,$key_ # pre-load round[2] vperm $in0,$inout,$inptail,$inpperm subi $inp,$inp,31 # undo "caller" vxor $twk0,$tweak,$rndkey0 vsrab $tmp,$tweak,$seven # next tweak value vaddubm $tweak,$tweak,$tweak vsldoi $tmp,$tmp,$tmp,15 vand $tmp,$tmp,$eighty7 vxor $out0,$in0,$twk0 vxor $tweak,$tweak,$tmp lvx_u $in1,$x10,$inp vxor $twk1,$tweak,$rndkey0 vsrab $tmp,$tweak,$seven # next tweak value vaddubm $tweak,$tweak,$tweak vsldoi $tmp,$tmp,$tmp,15 le?vperm $in1,$in1,$in1,$leperm vand $tmp,$tmp,$eighty7 vxor $out1,$in1,$twk1 vxor $tweak,$tweak,$tmp lvx_u $in2,$x20,$inp andi. $taillen,$len,15 vxor $twk2,$tweak,$rndkey0 vsrab $tmp,$tweak,$seven # next tweak value vaddubm $tweak,$tweak,$tweak vsldoi $tmp,$tmp,$tmp,15 le?vperm $in2,$in2,$in2,$leperm vand $tmp,$tmp,$eighty7 vxor $out2,$in2,$twk2 vxor $tweak,$tweak,$tmp lvx_u $in3,$x30,$inp sub $len,$len,$taillen vxor $twk3,$tweak,$rndkey0 vsrab $tmp,$tweak,$seven # next tweak value vaddubm $tweak,$tweak,$tweak vsldoi $tmp,$tmp,$tmp,15 le?vperm $in3,$in3,$in3,$leperm vand $tmp,$tmp,$eighty7 vxor $out3,$in3,$twk3 vxor $tweak,$tweak,$tmp lvx_u $in4,$x40,$inp subi $len,$len,0x60 vxor $twk4,$tweak,$rndkey0 vsrab $tmp,$tweak,$seven # next tweak value vaddubm $tweak,$tweak,$tweak vsldoi $tmp,$tmp,$tmp,15 le?vperm $in4,$in4,$in4,$leperm vand $tmp,$tmp,$eighty7 vxor $out4,$in4,$twk4 vxor $tweak,$tweak,$tmp lvx_u $in5,$x50,$inp addi $inp,$inp,0x60 vxor $twk5,$tweak,$rndkey0 vsrab $tmp,$tweak,$seven # next tweak value vaddubm $tweak,$tweak,$tweak vsldoi $tmp,$tmp,$tmp,15 le?vperm $in5,$in5,$in5,$leperm vand $tmp,$tmp,$eighty7 vxor $out5,$in5,$twk5 vxor $tweak,$tweak,$tmp vxor v31,v31,$rndkey0 mtctr $rounds b Loop_xts_enc6x .align 5 Loop_xts_enc6x: vcipher $out0,$out0,v24 vcipher $out1,$out1,v24 vcipher $out2,$out2,v24 vcipher $out3,$out3,v24 vcipher $out4,$out4,v24 vcipher $out5,$out5,v24 lvx v24,$x20,$key_ # round[3] addi $key_,$key_,0x20 vcipher $out0,$out0,v25 vcipher $out1,$out1,v25 vcipher $out2,$out2,v25 vcipher $out3,$out3,v25 vcipher $out4,$out4,v25 vcipher $out5,$out5,v25 lvx v25,$x10,$key_ # round[4] bdnz Loop_xts_enc6x subic $len,$len,96 # $len-=96 vxor $in0,$twk0,v31 # xor with last round key vcipher $out0,$out0,v24 vcipher $out1,$out1,v24 vsrab $tmp,$tweak,$seven # next tweak value vxor $twk0,$tweak,$rndkey0 vaddubm $tweak,$tweak,$tweak vcipher $out2,$out2,v24 vcipher $out3,$out3,v24 vsldoi $tmp,$tmp,$tmp,15 vcipher $out4,$out4,v24 vcipher $out5,$out5,v24 subfe. r0,r0,r0 # borrow?-1:0 vand $tmp,$tmp,$eighty7 vcipher $out0,$out0,v25 vcipher $out1,$out1,v25 vxor $tweak,$tweak,$tmp vcipher $out2,$out2,v25 vcipher $out3,$out3,v25 vxor $in1,$twk1,v31 vsrab $tmp,$tweak,$seven # next tweak value vxor $twk1,$tweak,$rndkey0 vcipher $out4,$out4,v25 vcipher $out5,$out5,v25 and r0,r0,$len vaddubm $tweak,$tweak,$tweak vsldoi $tmp,$tmp,$tmp,15 vcipher $out0,$out0,v26 vcipher $out1,$out1,v26 vand $tmp,$tmp,$eighty7 vcipher $out2,$out2,v26 vcipher $out3,$out3,v26 vxor $tweak,$tweak,$tmp vcipher $out4,$out4,v26 vcipher $out5,$out5,v26 add $inp,$inp,r0 # $inp is adjusted in such # way that at exit from the # loop inX-in5 are loaded # with last "words" vxor $in2,$twk2,v31 vsrab $tmp,$tweak,$seven # next tweak value vxor $twk2,$tweak,$rndkey0 vaddubm $tweak,$tweak,$tweak vcipher $out0,$out0,v27 vcipher $out1,$out1,v27 vsldoi $tmp,$tmp,$tmp,15 vcipher $out2,$out2,v27 vcipher $out3,$out3,v27 vand $tmp,$tmp,$eighty7 vcipher $out4,$out4,v27 vcipher $out5,$out5,v27 addi $key_,$sp,$FRAME+15 # rewind $key_ vxor $tweak,$tweak,$tmp vcipher $out0,$out0,v28 vcipher $out1,$out1,v28 vxor $in3,$twk3,v31 vsrab $tmp,$tweak,$seven # next tweak value vxor $twk3,$tweak,$rndkey0 vcipher $out2,$out2,v28 vcipher $out3,$out3,v28 vaddubm $tweak,$tweak,$tweak vsldoi $tmp,$tmp,$tmp,15 vcipher $out4,$out4,v28 vcipher $out5,$out5,v28 lvx v24,$x00,$key_ # re-pre-load round[1] vand $tmp,$tmp,$eighty7 vcipher $out0,$out0,v29 vcipher $out1,$out1,v29 vxor $tweak,$tweak,$tmp vcipher $out2,$out2,v29 vcipher $out3,$out3,v29 vxor $in4,$twk4,v31 vsrab $tmp,$tweak,$seven # next tweak value vxor $twk4,$tweak,$rndkey0 vcipher $out4,$out4,v29 vcipher $out5,$out5,v29 lvx v25,$x10,$key_ # re-pre-load round[2] vaddubm $tweak,$tweak,$tweak vsldoi $tmp,$tmp,$tmp,15 vcipher $out0,$out0,v30 vcipher $out1,$out1,v30 vand $tmp,$tmp,$eighty7 vcipher $out2,$out2,v30 vcipher $out3,$out3,v30 vxor $tweak,$tweak,$tmp vcipher $out4,$out4,v30 vcipher $out5,$out5,v30 vxor $in5,$twk5,v31 vsrab $tmp,$tweak,$seven # next tweak value vxor $twk5,$tweak,$rndkey0 vcipherlast $out0,$out0,$in0 lvx_u $in0,$x00,$inp # load next input block vaddubm $tweak,$tweak,$tweak vsldoi $tmp,$tmp,$tmp,15 vcipherlast $out1,$out1,$in1 lvx_u $in1,$x10,$inp vcipherlast $out2,$out2,$in2 le?vperm $in0,$in0,$in0,$leperm lvx_u $in2,$x20,$inp vand $tmp,$tmp,$eighty7 vcipherlast $out3,$out3,$in3 le?vperm $in1,$in1,$in1,$leperm lvx_u $in3,$x30,$inp vcipherlast $out4,$out4,$in4 le?vperm $in2,$in2,$in2,$leperm lvx_u $in4,$x40,$inp vxor $tweak,$tweak,$tmp vcipherlast $tmp,$out5,$in5 # last block might be needed # in stealing mode le?vperm $in3,$in3,$in3,$leperm lvx_u $in5,$x50,$inp addi $inp,$inp,0x60 le?vperm $in4,$in4,$in4,$leperm le?vperm $in5,$in5,$in5,$leperm le?vperm $out0,$out0,$out0,$leperm le?vperm $out1,$out1,$out1,$leperm stvx_u $out0,$x00,$out # store output vxor $out0,$in0,$twk0 le?vperm $out2,$out2,$out2,$leperm stvx_u $out1,$x10,$out vxor $out1,$in1,$twk1 le?vperm $out3,$out3,$out3,$leperm stvx_u $out2,$x20,$out vxor $out2,$in2,$twk2 le?vperm $out4,$out4,$out4,$leperm stvx_u $out3,$x30,$out vxor $out3,$in3,$twk3 le?vperm $out5,$tmp,$tmp,$leperm stvx_u $out4,$x40,$out vxor $out4,$in4,$twk4 le?stvx_u $out5,$x50,$out be?stvx_u $tmp, $x50,$out vxor $out5,$in5,$twk5 addi $out,$out,0x60 mtctr $rounds beq Loop_xts_enc6x # did $len-=96 borrow? addic. $len,$len,0x60 beq Lxts_enc6x_zero cmpwi $len,0x20 blt Lxts_enc6x_one nop beq Lxts_enc6x_two cmpwi $len,0x40 blt Lxts_enc6x_three nop beq Lxts_enc6x_four Lxts_enc6x_five: vxor $out0,$in1,$twk0 vxor $out1,$in2,$twk1 vxor $out2,$in3,$twk2 vxor $out3,$in4,$twk3 vxor $out4,$in5,$twk4 bl _aesp8_xts_enc5x le?vperm $out0,$out0,$out0,$leperm vmr $twk0,$twk5 # unused tweak le?vperm $out1,$out1,$out1,$leperm stvx_u $out0,$x00,$out # store output le?vperm $out2,$out2,$out2,$leperm stvx_u $out1,$x10,$out le?vperm $out3,$out3,$out3,$leperm stvx_u $out2,$x20,$out vxor $tmp,$out4,$twk5 # last block prep for stealing le?vperm $out4,$out4,$out4,$leperm stvx_u $out3,$x30,$out stvx_u $out4,$x40,$out addi $out,$out,0x50 bne Lxts_enc6x_steal b Lxts_enc6x_done .align 4 Lxts_enc6x_four: vxor $out0,$in2,$twk0 vxor $out1,$in3,$twk1 vxor $out2,$in4,$twk2 vxor $out3,$in5,$twk3 vxor $out4,$out4,$out4 bl _aesp8_xts_enc5x le?vperm $out0,$out0,$out0,$leperm vmr $twk0,$twk4 # unused tweak le?vperm $out1,$out1,$out1,$leperm stvx_u $out0,$x00,$out # store output le?vperm $out2,$out2,$out2,$leperm stvx_u $out1,$x10,$out vxor $tmp,$out3,$twk4 # last block prep for stealing le?vperm $out3,$out3,$out3,$leperm stvx_u $out2,$x20,$out stvx_u $out3,$x30,$out addi $out,$out,0x40 bne Lxts_enc6x_steal b Lxts_enc6x_done .align 4 Lxts_enc6x_three: vxor $out0,$in3,$twk0 vxor $out1,$in4,$twk1 vxor $out2,$in5,$twk2 vxor $out3,$out3,$out3 vxor $out4,$out4,$out4 bl _aesp8_xts_enc5x le?vperm $out0,$out0,$out0,$leperm vmr $twk0,$twk3 # unused tweak le?vperm $out1,$out1,$out1,$leperm stvx_u $out0,$x00,$out # store output vxor $tmp,$out2,$twk3 # last block prep for stealing le?vperm $out2,$out2,$out2,$leperm stvx_u $out1,$x10,$out stvx_u $out2,$x20,$out addi $out,$out,0x30 bne Lxts_enc6x_steal b Lxts_enc6x_done .align 4 Lxts_enc6x_two: vxor $out0,$in4,$twk0 vxor $out1,$in5,$twk1 vxor $out2,$out2,$out2 vxor $out3,$out3,$out3 vxor $out4,$out4,$out4 bl _aesp8_xts_enc5x le?vperm $out0,$out0,$out0,$leperm vmr $twk0,$twk2 # unused tweak vxor $tmp,$out1,$twk2 # last block prep for stealing le?vperm $out1,$out1,$out1,$leperm stvx_u $out0,$x00,$out # store output stvx_u $out1,$x10,$out addi $out,$out,0x20 bne Lxts_enc6x_steal b Lxts_enc6x_done .align 4 Lxts_enc6x_one: vxor $out0,$in5,$twk0 nop Loop_xts_enc1x: vcipher $out0,$out0,v24 lvx v24,$x20,$key_ # round[3] addi $key_,$key_,0x20 vcipher $out0,$out0,v25 lvx v25,$x10,$key_ # round[4] bdnz Loop_xts_enc1x add $inp,$inp,$taillen cmpwi $taillen,0 vcipher $out0,$out0,v24 subi $inp,$inp,16 vcipher $out0,$out0,v25 lvsr $inpperm,0,$taillen vcipher $out0,$out0,v26 lvx_u $in0,0,$inp vcipher $out0,$out0,v27 addi $key_,$sp,$FRAME+15 # rewind $key_ vcipher $out0,$out0,v28 lvx v24,$x00,$key_ # re-pre-load round[1] vcipher $out0,$out0,v29 lvx v25,$x10,$key_ # re-pre-load round[2] vxor $twk0,$twk0,v31 le?vperm $in0,$in0,$in0,$leperm vcipher $out0,$out0,v30 vperm $in0,$in0,$in0,$inpperm vcipherlast $out0,$out0,$twk0 vmr $twk0,$twk1 # unused tweak vxor $tmp,$out0,$twk1 # last block prep for stealing le?vperm $out0,$out0,$out0,$leperm stvx_u $out0,$x00,$out # store output addi $out,$out,0x10 bne Lxts_enc6x_steal b Lxts_enc6x_done .align 4 Lxts_enc6x_zero: cmpwi $taillen,0 beq Lxts_enc6x_done add $inp,$inp,$taillen subi $inp,$inp,16 lvx_u $in0,0,$inp lvsr $inpperm,0,$taillen # $in5 is no more le?vperm $in0,$in0,$in0,$leperm vperm $in0,$in0,$in0,$inpperm vxor $tmp,$tmp,$twk0 Lxts_enc6x_steal: vxor $in0,$in0,$twk0 vxor $out0,$out0,$out0 vspltisb $out1,-1 vperm $out0,$out0,$out1,$inpperm vsel $out0,$in0,$tmp,$out0 # $tmp is last block, remember? subi r30,$out,17 subi $out,$out,16 mtctr $taillen Loop_xts_enc6x_steal: lbzu r0,1(r30) stb r0,16(r30) bdnz Loop_xts_enc6x_steal li $taillen,0 mtctr $rounds b Loop_xts_enc1x # one more time... .align 4 Lxts_enc6x_done: ${UCMP}i $ivp,0 beq Lxts_enc6x_ret vxor $tweak,$twk0,$rndkey0 le?vperm $tweak,$tweak,$tweak,$leperm stvx_u $tweak,0,$ivp Lxts_enc6x_ret: mtlr r11 li r10,`$FRAME+15` li r11,`$FRAME+31` stvx $seven,r10,$sp # wipe copies of round keys addi r10,r10,32 stvx $seven,r11,$sp addi r11,r11,32 stvx $seven,r10,$sp addi r10,r10,32 stvx $seven,r11,$sp addi r11,r11,32 stvx $seven,r10,$sp addi r10,r10,32 stvx $seven,r11,$sp addi r11,r11,32 stvx $seven,r10,$sp addi r10,r10,32 stvx $seven,r11,$sp addi r11,r11,32 mtspr 256,$vrsave lvx v20,r10,$sp # ABI says so addi r10,r10,32 lvx v21,r11,$sp addi r11,r11,32 lvx v22,r10,$sp addi r10,r10,32 lvx v23,r11,$sp addi r11,r11,32 lvx v24,r10,$sp addi r10,r10,32 lvx v25,r11,$sp addi r11,r11,32 lvx v26,r10,$sp addi r10,r10,32 lvx v27,r11,$sp addi r11,r11,32 lvx v28,r10,$sp addi r10,r10,32 lvx v29,r11,$sp addi r11,r11,32 lvx v30,r10,$sp lvx v31,r11,$sp $POP r26,`$FRAME+21*16+0*$SIZE_T`($sp) $POP r27,`$FRAME+21*16+1*$SIZE_T`($sp) $POP r28,`$FRAME+21*16+2*$SIZE_T`($sp) $POP r29,`$FRAME+21*16+3*$SIZE_T`($sp) $POP r30,`$FRAME+21*16+4*$SIZE_T`($sp) $POP r31,`$FRAME+21*16+5*$SIZE_T`($sp) addi $sp,$sp,`$FRAME+21*16+6*$SIZE_T` blr .long 0 .byte 0,12,0x04,1,0x80,6,6,0 .long 0 .align 5 _aesp8_xts_enc5x: vcipher $out0,$out0,v24 vcipher $out1,$out1,v24 vcipher $out2,$out2,v24 vcipher $out3,$out3,v24 vcipher $out4,$out4,v24 lvx v24,$x20,$key_ # round[3] addi $key_,$key_,0x20 vcipher $out0,$out0,v25 vcipher $out1,$out1,v25 vcipher $out2,$out2,v25 vcipher $out3,$out3,v25 vcipher $out4,$out4,v25 lvx v25,$x10,$key_ # round[4] bdnz _aesp8_xts_enc5x add $inp,$inp,$taillen cmpwi $taillen,0 vcipher $out0,$out0,v24 vcipher $out1,$out1,v24 vcipher $out2,$out2,v24 vcipher $out3,$out3,v24 vcipher $out4,$out4,v24 subi $inp,$inp,16 vcipher $out0,$out0,v25 vcipher $out1,$out1,v25 vcipher $out2,$out2,v25 vcipher $out3,$out3,v25 vcipher $out4,$out4,v25 vxor $twk0,$twk0,v31 vcipher $out0,$out0,v26 lvsr $inpperm,r0,$taillen # $in5 is no more vcipher $out1,$out1,v26 vcipher $out2,$out2,v26 vcipher $out3,$out3,v26 vcipher $out4,$out4,v26 vxor $in1,$twk1,v31 vcipher $out0,$out0,v27 lvx_u $in0,0,$inp vcipher $out1,$out1,v27 vcipher $out2,$out2,v27 vcipher $out3,$out3,v27 vcipher $out4,$out4,v27 vxor $in2,$twk2,v31 addi $key_,$sp,$FRAME+15 # rewind $key_ vcipher $out0,$out0,v28 vcipher $out1,$out1,v28 vcipher $out2,$out2,v28 vcipher $out3,$out3,v28 vcipher $out4,$out4,v28 lvx v24,$x00,$key_ # re-pre-load round[1] vxor $in3,$twk3,v31 vcipher $out0,$out0,v29 le?vperm $in0,$in0,$in0,$leperm vcipher $out1,$out1,v29 vcipher $out2,$out2,v29 vcipher $out3,$out3,v29 vcipher $out4,$out4,v29 lvx v25,$x10,$key_ # re-pre-load round[2] vxor $in4,$twk4,v31 vcipher $out0,$out0,v30 vperm $in0,$in0,$in0,$inpperm vcipher $out1,$out1,v30 vcipher $out2,$out2,v30 vcipher $out3,$out3,v30 vcipher $out4,$out4,v30 vcipherlast $out0,$out0,$twk0 vcipherlast $out1,$out1,$in1 vcipherlast $out2,$out2,$in2 vcipherlast $out3,$out3,$in3 vcipherlast $out4,$out4,$in4 blr .long 0 .byte 0,12,0x14,0,0,0,0,0 .align 5 _aesp8_xts_decrypt6x: $STU $sp,-`($FRAME+21*16+6*$SIZE_T)`($sp) mflr r11 li r7,`$FRAME+8*16+15` li r3,`$FRAME+8*16+31` $PUSH r11,`$FRAME+21*16+6*$SIZE_T+$LRSAVE`($sp) stvx v20,r7,$sp # ABI says so addi r7,r7,32 stvx v21,r3,$sp addi r3,r3,32 stvx v22,r7,$sp addi r7,r7,32 stvx v23,r3,$sp addi r3,r3,32 stvx v24,r7,$sp addi r7,r7,32 stvx v25,r3,$sp addi r3,r3,32 stvx v26,r7,$sp addi r7,r7,32 stvx v27,r3,$sp addi r3,r3,32 stvx v28,r7,$sp addi r7,r7,32 stvx v29,r3,$sp addi r3,r3,32 stvx v30,r7,$sp stvx v31,r3,$sp li r0,-1 stw $vrsave,`$FRAME+21*16-4`($sp) # save vrsave li $x10,0x10 $PUSH r26,`$FRAME+21*16+0*$SIZE_T`($sp) li $x20,0x20 $PUSH r27,`$FRAME+21*16+1*$SIZE_T`($sp) li $x30,0x30 $PUSH r28,`$FRAME+21*16+2*$SIZE_T`($sp) li $x40,0x40 $PUSH r29,`$FRAME+21*16+3*$SIZE_T`($sp) li $x50,0x50 $PUSH r30,`$FRAME+21*16+4*$SIZE_T`($sp) li $x60,0x60 $PUSH r31,`$FRAME+21*16+5*$SIZE_T`($sp) li $x70,0x70 mtspr 256,r0 subi $rounds,$rounds,3 # -4 in total lvx $rndkey0,$x00,$key1 # load key schedule lvx v30,$x10,$key1 addi $key1,$key1,0x20 lvx v31,$x00,$key1 ?vperm $rndkey0,$rndkey0,v30,$keyperm addi $key_,$sp,$FRAME+15 mtctr $rounds Load_xts_dec_key: ?vperm v24,v30,v31,$keyperm lvx v30,$x10,$key1 addi $key1,$key1,0x20 stvx v24,$x00,$key_ # off-load round[1] ?vperm v25,v31,v30,$keyperm lvx v31,$x00,$key1 stvx v25,$x10,$key_ # off-load round[2] addi $key_,$key_,0x20 bdnz Load_xts_dec_key lvx v26,$x10,$key1 ?vperm v24,v30,v31,$keyperm lvx v27,$x20,$key1 stvx v24,$x00,$key_ # off-load round[3] ?vperm v25,v31,v26,$keyperm lvx v28,$x30,$key1 stvx v25,$x10,$key_ # off-load round[4] addi $key_,$sp,$FRAME+15 # rewind $key_ ?vperm v26,v26,v27,$keyperm lvx v29,$x40,$key1 ?vperm v27,v27,v28,$keyperm lvx v30,$x50,$key1 ?vperm v28,v28,v29,$keyperm lvx v31,$x60,$key1 ?vperm v29,v29,v30,$keyperm lvx $twk5,$x70,$key1 # borrow $twk5 ?vperm v30,v30,v31,$keyperm lvx v24,$x00,$key_ # pre-load round[1] ?vperm v31,v31,$twk5,$keyperm lvx v25,$x10,$key_ # pre-load round[2] vperm $in0,$inout,$inptail,$inpperm subi $inp,$inp,31 # undo "caller" vxor $twk0,$tweak,$rndkey0 vsrab $tmp,$tweak,$seven # next tweak value vaddubm $tweak,$tweak,$tweak vsldoi $tmp,$tmp,$tmp,15 vand $tmp,$tmp,$eighty7 vxor $out0,$in0,$twk0 vxor $tweak,$tweak,$tmp lvx_u $in1,$x10,$inp vxor $twk1,$tweak,$rndkey0 vsrab $tmp,$tweak,$seven # next tweak value vaddubm $tweak,$tweak,$tweak vsldoi $tmp,$tmp,$tmp,15 le?vperm $in1,$in1,$in1,$leperm vand $tmp,$tmp,$eighty7 vxor $out1,$in1,$twk1 vxor $tweak,$tweak,$tmp lvx_u $in2,$x20,$inp andi. $taillen,$len,15 vxor $twk2,$tweak,$rndkey0 vsrab $tmp,$tweak,$seven # next tweak value vaddubm $tweak,$tweak,$tweak vsldoi $tmp,$tmp,$tmp,15 le?vperm $in2,$in2,$in2,$leperm vand $tmp,$tmp,$eighty7 vxor $out2,$in2,$twk2 vxor $tweak,$tweak,$tmp lvx_u $in3,$x30,$inp sub $len,$len,$taillen vxor $twk3,$tweak,$rndkey0 vsrab $tmp,$tweak,$seven # next tweak value vaddubm $tweak,$tweak,$tweak vsldoi $tmp,$tmp,$tmp,15 le?vperm $in3,$in3,$in3,$leperm vand $tmp,$tmp,$eighty7 vxor $out3,$in3,$twk3 vxor $tweak,$tweak,$tmp lvx_u $in4,$x40,$inp subi $len,$len,0x60 vxor $twk4,$tweak,$rndkey0 vsrab $tmp,$tweak,$seven # next tweak value vaddubm $tweak,$tweak,$tweak vsldoi $tmp,$tmp,$tmp,15 le?vperm $in4,$in4,$in4,$leperm vand $tmp,$tmp,$eighty7 vxor $out4,$in4,$twk4 vxor $tweak,$tweak,$tmp lvx_u $in5,$x50,$inp addi $inp,$inp,0x60 vxor $twk5,$tweak,$rndkey0 vsrab $tmp,$tweak,$seven # next tweak value vaddubm $tweak,$tweak,$tweak vsldoi $tmp,$tmp,$tmp,15 le?vperm $in5,$in5,$in5,$leperm vand $tmp,$tmp,$eighty7 vxor $out5,$in5,$twk5 vxor $tweak,$tweak,$tmp vxor v31,v31,$rndkey0 mtctr $rounds b Loop_xts_dec6x .align 5 Loop_xts_dec6x: vncipher $out0,$out0,v24 vncipher $out1,$out1,v24 vncipher $out2,$out2,v24 vncipher $out3,$out3,v24 vncipher $out4,$out4,v24 vncipher $out5,$out5,v24 lvx v24,$x20,$key_ # round[3] addi $key_,$key_,0x20 vncipher $out0,$out0,v25 vncipher $out1,$out1,v25 vncipher $out2,$out2,v25 vncipher $out3,$out3,v25 vncipher $out4,$out4,v25 vncipher $out5,$out5,v25 lvx v25,$x10,$key_ # round[4] bdnz Loop_xts_dec6x subic $len,$len,96 # $len-=96 vxor $in0,$twk0,v31 # xor with last round key vncipher $out0,$out0,v24 vncipher $out1,$out1,v24 vsrab $tmp,$tweak,$seven # next tweak value vxor $twk0,$tweak,$rndkey0 vaddubm $tweak,$tweak,$tweak vncipher $out2,$out2,v24 vncipher $out3,$out3,v24 vsldoi $tmp,$tmp,$tmp,15 vncipher $out4,$out4,v24 vncipher $out5,$out5,v24 subfe. r0,r0,r0 # borrow?-1:0 vand $tmp,$tmp,$eighty7 vncipher $out0,$out0,v25 vncipher $out1,$out1,v25 vxor $tweak,$tweak,$tmp vncipher $out2,$out2,v25 vncipher $out3,$out3,v25 vxor $in1,$twk1,v31 vsrab $tmp,$tweak,$seven # next tweak value vxor $twk1,$tweak,$rndkey0 vncipher $out4,$out4,v25 vncipher $out5,$out5,v25 and r0,r0,$len vaddubm $tweak,$tweak,$tweak vsldoi $tmp,$tmp,$tmp,15 vncipher $out0,$out0,v26 vncipher $out1,$out1,v26 vand $tmp,$tmp,$eighty7 vncipher $out2,$out2,v26 vncipher $out3,$out3,v26 vxor $tweak,$tweak,$tmp vncipher $out4,$out4,v26 vncipher $out5,$out5,v26 add $inp,$inp,r0 # $inp is adjusted in such # way that at exit from the # loop inX-in5 are loaded # with last "words" vxor $in2,$twk2,v31 vsrab $tmp,$tweak,$seven # next tweak value vxor $twk2,$tweak,$rndkey0 vaddubm $tweak,$tweak,$tweak vncipher $out0,$out0,v27 vncipher $out1,$out1,v27 vsldoi $tmp,$tmp,$tmp,15 vncipher $out2,$out2,v27 vncipher $out3,$out3,v27 vand $tmp,$tmp,$eighty7 vncipher $out4,$out4,v27 vncipher $out5,$out5,v27 addi $key_,$sp,$FRAME+15 # rewind $key_ vxor $tweak,$tweak,$tmp vncipher $out0,$out0,v28 vncipher $out1,$out1,v28 vxor $in3,$twk3,v31 vsrab $tmp,$tweak,$seven # next tweak value vxor $twk3,$tweak,$rndkey0 vncipher $out2,$out2,v28 vncipher $out3,$out3,v28 vaddubm $tweak,$tweak,$tweak vsldoi $tmp,$tmp,$tmp,15 vncipher $out4,$out4,v28 vncipher $out5,$out5,v28 lvx v24,$x00,$key_ # re-pre-load round[1] vand $tmp,$tmp,$eighty7 vncipher $out0,$out0,v29 vncipher $out1,$out1,v29 vxor $tweak,$tweak,$tmp vncipher $out2,$out2,v29 vncipher $out3,$out3,v29 vxor $in4,$twk4,v31 vsrab $tmp,$tweak,$seven # next tweak value vxor $twk4,$tweak,$rndkey0 vncipher $out4,$out4,v29 vncipher $out5,$out5,v29 lvx v25,$x10,$key_ # re-pre-load round[2] vaddubm $tweak,$tweak,$tweak vsldoi $tmp,$tmp,$tmp,15 vncipher $out0,$out0,v30 vncipher $out1,$out1,v30 vand $tmp,$tmp,$eighty7 vncipher $out2,$out2,v30 vncipher $out3,$out3,v30 vxor $tweak,$tweak,$tmp vncipher $out4,$out4,v30 vncipher $out5,$out5,v30 vxor $in5,$twk5,v31 vsrab $tmp,$tweak,$seven # next tweak value vxor $twk5,$tweak,$rndkey0 vncipherlast $out0,$out0,$in0 lvx_u $in0,$x00,$inp # load next input block vaddubm $tweak,$tweak,$tweak vsldoi $tmp,$tmp,$tmp,15 vncipherlast $out1,$out1,$in1 lvx_u $in1,$x10,$inp vncipherlast $out2,$out2,$in2 le?vperm $in0,$in0,$in0,$leperm lvx_u $in2,$x20,$inp vand $tmp,$tmp,$eighty7 vncipherlast $out3,$out3,$in3 le?vperm $in1,$in1,$in1,$leperm lvx_u $in3,$x30,$inp vncipherlast $out4,$out4,$in4 le?vperm $in2,$in2,$in2,$leperm lvx_u $in4,$x40,$inp vxor $tweak,$tweak,$tmp vncipherlast $out5,$out5,$in5 le?vperm $in3,$in3,$in3,$leperm lvx_u $in5,$x50,$inp addi $inp,$inp,0x60 le?vperm $in4,$in4,$in4,$leperm le?vperm $in5,$in5,$in5,$leperm le?vperm $out0,$out0,$out0,$leperm le?vperm $out1,$out1,$out1,$leperm stvx_u $out0,$x00,$out # store output vxor $out0,$in0,$twk0 le?vperm $out2,$out2,$out2,$leperm stvx_u $out1,$x10,$out vxor $out1,$in1,$twk1 le?vperm $out3,$out3,$out3,$leperm stvx_u $out2,$x20,$out vxor $out2,$in2,$twk2 le?vperm $out4,$out4,$out4,$leperm stvx_u $out3,$x30,$out vxor $out3,$in3,$twk3 le?vperm $out5,$out5,$out5,$leperm stvx_u $out4,$x40,$out vxor $out4,$in4,$twk4 stvx_u $out5,$x50,$out vxor $out5,$in5,$twk5 addi $out,$out,0x60 mtctr $rounds beq Loop_xts_dec6x # did $len-=96 borrow? addic. $len,$len,0x60 beq Lxts_dec6x_zero cmpwi $len,0x20 blt Lxts_dec6x_one nop beq Lxts_dec6x_two cmpwi $len,0x40 blt Lxts_dec6x_three nop beq Lxts_dec6x_four Lxts_dec6x_five: vxor $out0,$in1,$twk0 vxor $out1,$in2,$twk1 vxor $out2,$in3,$twk2 vxor $out3,$in4,$twk3 vxor $out4,$in5,$twk4 bl _aesp8_xts_dec5x le?vperm $out0,$out0,$out0,$leperm vmr $twk0,$twk5 # unused tweak vxor $twk1,$tweak,$rndkey0 le?vperm $out1,$out1,$out1,$leperm stvx_u $out0,$x00,$out # store output vxor $out0,$in0,$twk1 le?vperm $out2,$out2,$out2,$leperm stvx_u $out1,$x10,$out le?vperm $out3,$out3,$out3,$leperm stvx_u $out2,$x20,$out le?vperm $out4,$out4,$out4,$leperm stvx_u $out3,$x30,$out stvx_u $out4,$x40,$out addi $out,$out,0x50 bne Lxts_dec6x_steal b Lxts_dec6x_done .align 4 Lxts_dec6x_four: vxor $out0,$in2,$twk0 vxor $out1,$in3,$twk1 vxor $out2,$in4,$twk2 vxor $out3,$in5,$twk3 vxor $out4,$out4,$out4 bl _aesp8_xts_dec5x le?vperm $out0,$out0,$out0,$leperm vmr $twk0,$twk4 # unused tweak vmr $twk1,$twk5 le?vperm $out1,$out1,$out1,$leperm stvx_u $out0,$x00,$out # store output vxor $out0,$in0,$twk5 le?vperm $out2,$out2,$out2,$leperm stvx_u $out1,$x10,$out le?vperm $out3,$out3,$out3,$leperm stvx_u $out2,$x20,$out stvx_u $out3,$x30,$out addi $out,$out,0x40 bne Lxts_dec6x_steal b Lxts_dec6x_done .align 4 Lxts_dec6x_three: vxor $out0,$in3,$twk0 vxor $out1,$in4,$twk1 vxor $out2,$in5,$twk2 vxor $out3,$out3,$out3 vxor $out4,$out4,$out4 bl _aesp8_xts_dec5x le?vperm $out0,$out0,$out0,$leperm vmr $twk0,$twk3 # unused tweak vmr $twk1,$twk4 le?vperm $out1,$out1,$out1,$leperm stvx_u $out0,$x00,$out # store output vxor $out0,$in0,$twk4 le?vperm $out2,$out2,$out2,$leperm stvx_u $out1,$x10,$out stvx_u $out2,$x20,$out addi $out,$out,0x30 bne Lxts_dec6x_steal b Lxts_dec6x_done .align 4 Lxts_dec6x_two: vxor $out0,$in4,$twk0 vxor $out1,$in5,$twk1 vxor $out2,$out2,$out2 vxor $out3,$out3,$out3 vxor $out4,$out4,$out4 bl _aesp8_xts_dec5x le?vperm $out0,$out0,$out0,$leperm vmr $twk0,$twk2 # unused tweak vmr $twk1,$twk3 le?vperm $out1,$out1,$out1,$leperm stvx_u $out0,$x00,$out # store output vxor $out0,$in0,$twk3 stvx_u $out1,$x10,$out addi $out,$out,0x20 bne Lxts_dec6x_steal b Lxts_dec6x_done .align 4 Lxts_dec6x_one: vxor $out0,$in5,$twk0 nop Loop_xts_dec1x: vncipher $out0,$out0,v24 lvx v24,$x20,$key_ # round[3] addi $key_,$key_,0x20 vncipher $out0,$out0,v25 lvx v25,$x10,$key_ # round[4] bdnz Loop_xts_dec1x subi r0,$taillen,1 vncipher $out0,$out0,v24 andi. r0,r0,16 cmpwi $taillen,0 vncipher $out0,$out0,v25 sub $inp,$inp,r0 vncipher $out0,$out0,v26 lvx_u $in0,0,$inp vncipher $out0,$out0,v27 addi $key_,$sp,$FRAME+15 # rewind $key_ vncipher $out0,$out0,v28 lvx v24,$x00,$key_ # re-pre-load round[1] vncipher $out0,$out0,v29 lvx v25,$x10,$key_ # re-pre-load round[2] vxor $twk0,$twk0,v31 le?vperm $in0,$in0,$in0,$leperm vncipher $out0,$out0,v30 mtctr $rounds vncipherlast $out0,$out0,$twk0 vmr $twk0,$twk1 # unused tweak vmr $twk1,$twk2 le?vperm $out0,$out0,$out0,$leperm stvx_u $out0,$x00,$out # store output addi $out,$out,0x10 vxor $out0,$in0,$twk2 bne Lxts_dec6x_steal b Lxts_dec6x_done .align 4 Lxts_dec6x_zero: cmpwi $taillen,0 beq Lxts_dec6x_done lvx_u $in0,0,$inp le?vperm $in0,$in0,$in0,$leperm vxor $out0,$in0,$twk1 Lxts_dec6x_steal: vncipher $out0,$out0,v24 lvx v24,$x20,$key_ # round[3] addi $key_,$key_,0x20 vncipher $out0,$out0,v25 lvx v25,$x10,$key_ # round[4] bdnz Lxts_dec6x_steal add $inp,$inp,$taillen vncipher $out0,$out0,v24 cmpwi $taillen,0 vncipher $out0,$out0,v25 lvx_u $in0,0,$inp vncipher $out0,$out0,v26 lvsr $inpperm,0,$taillen # $in5 is no more vncipher $out0,$out0,v27 addi $key_,$sp,$FRAME+15 # rewind $key_ vncipher $out0,$out0,v28 lvx v24,$x00,$key_ # re-pre-load round[1] vncipher $out0,$out0,v29 lvx v25,$x10,$key_ # re-pre-load round[2] vxor $twk1,$twk1,v31 le?vperm $in0,$in0,$in0,$leperm vncipher $out0,$out0,v30 vperm $in0,$in0,$in0,$inpperm vncipherlast $tmp,$out0,$twk1 le?vperm $out0,$tmp,$tmp,$leperm le?stvx_u $out0,0,$out be?stvx_u $tmp,0,$out vxor $out0,$out0,$out0 vspltisb $out1,-1 vperm $out0,$out0,$out1,$inpperm vsel $out0,$in0,$tmp,$out0 vxor $out0,$out0,$twk0 subi r30,$out,1 mtctr $taillen Loop_xts_dec6x_steal: lbzu r0,1(r30) stb r0,16(r30) bdnz Loop_xts_dec6x_steal li $taillen,0 mtctr $rounds b Loop_xts_dec1x # one more time... .align 4 Lxts_dec6x_done: ${UCMP}i $ivp,0 beq Lxts_dec6x_ret vxor $tweak,$twk0,$rndkey0 le?vperm $tweak,$tweak,$tweak,$leperm stvx_u $tweak,0,$ivp Lxts_dec6x_ret: mtlr r11 li r10,`$FRAME+15` li r11,`$FRAME+31` stvx $seven,r10,$sp # wipe copies of round keys addi r10,r10,32 stvx $seven,r11,$sp addi r11,r11,32 stvx $seven,r10,$sp addi r10,r10,32 stvx $seven,r11,$sp addi r11,r11,32 stvx $seven,r10,$sp addi r10,r10,32 stvx $seven,r11,$sp addi r11,r11,32 stvx $seven,r10,$sp addi r10,r10,32 stvx $seven,r11,$sp addi r11,r11,32 mtspr 256,$vrsave lvx v20,r10,$sp # ABI says so addi r10,r10,32 lvx v21,r11,$sp addi r11,r11,32 lvx v22,r10,$sp addi r10,r10,32 lvx v23,r11,$sp addi r11,r11,32 lvx v24,r10,$sp addi r10,r10,32 lvx v25,r11,$sp addi r11,r11,32 lvx v26,r10,$sp addi r10,r10,32 lvx v27,r11,$sp addi r11,r11,32 lvx v28,r10,$sp addi r10,r10,32 lvx v29,r11,$sp addi r11,r11,32 lvx v30,r10,$sp lvx v31,r11,$sp $POP r26,`$FRAME+21*16+0*$SIZE_T`($sp) $POP r27,`$FRAME+21*16+1*$SIZE_T`($sp) $POP r28,`$FRAME+21*16+2*$SIZE_T`($sp) $POP r29,`$FRAME+21*16+3*$SIZE_T`($sp) $POP r30,`$FRAME+21*16+4*$SIZE_T`($sp) $POP r31,`$FRAME+21*16+5*$SIZE_T`($sp) addi $sp,$sp,`$FRAME+21*16+6*$SIZE_T` blr .long 0 .byte 0,12,0x04,1,0x80,6,6,0 .long 0 .align 5 _aesp8_xts_dec5x: vncipher $out0,$out0,v24 vncipher $out1,$out1,v24 vncipher $out2,$out2,v24 vncipher $out3,$out3,v24 vncipher $out4,$out4,v24 lvx v24,$x20,$key_ # round[3] addi $key_,$key_,0x20 vncipher $out0,$out0,v25 vncipher $out1,$out1,v25 vncipher $out2,$out2,v25 vncipher $out3,$out3,v25 vncipher $out4,$out4,v25 lvx v25,$x10,$key_ # round[4] bdnz _aesp8_xts_dec5x subi r0,$taillen,1 vncipher $out0,$out0,v24 vncipher $out1,$out1,v24 vncipher $out2,$out2,v24 vncipher $out3,$out3,v24 vncipher $out4,$out4,v24 andi. r0,r0,16 cmpwi $taillen,0 vncipher $out0,$out0,v25 vncipher $out1,$out1,v25 vncipher $out2,$out2,v25 vncipher $out3,$out3,v25 vncipher $out4,$out4,v25 vxor $twk0,$twk0,v31 sub $inp,$inp,r0 vncipher $out0,$out0,v26 vncipher $out1,$out1,v26 vncipher $out2,$out2,v26 vncipher $out3,$out3,v26 vncipher $out4,$out4,v26 vxor $in1,$twk1,v31 vncipher $out0,$out0,v27 lvx_u $in0,0,$inp vncipher $out1,$out1,v27 vncipher $out2,$out2,v27 vncipher $out3,$out3,v27 vncipher $out4,$out4,v27 vxor $in2,$twk2,v31 addi $key_,$sp,$FRAME+15 # rewind $key_ vncipher $out0,$out0,v28 vncipher $out1,$out1,v28 vncipher $out2,$out2,v28 vncipher $out3,$out3,v28 vncipher $out4,$out4,v28 lvx v24,$x00,$key_ # re-pre-load round[1] vxor $in3,$twk3,v31 vncipher $out0,$out0,v29 le?vperm $in0,$in0,$in0,$leperm vncipher $out1,$out1,v29 vncipher $out2,$out2,v29 vncipher $out3,$out3,v29 vncipher $out4,$out4,v29 lvx v25,$x10,$key_ # re-pre-load round[2] vxor $in4,$twk4,v31 vncipher $out0,$out0,v30 vncipher $out1,$out1,v30 vncipher $out2,$out2,v30 vncipher $out3,$out3,v30 vncipher $out4,$out4,v30 vncipherlast $out0,$out0,$twk0 vncipherlast $out1,$out1,$in1 vncipherlast $out2,$out2,$in2 vncipherlast $out3,$out3,$in3 vncipherlast $out4,$out4,$in4 mtctr $rounds blr .long 0 .byte 0,12,0x14,0,0,0,0,0 ___ }} }}} my $consts=1; foreach(split("\n",$code)) { s/\`([^\`]*)\`/eval($1)/geo; # constants table endian-specific conversion if ($consts && m/\.(long|byte)\s+(.+)\s+(\?[a-z]*)$/o) { my $conv=$3; my @bytes=(); # convert to endian-agnostic format if ($1 eq "long") { foreach (split(/,\s*/,$2)) { my $l = /^0/?oct:int; push @bytes,($l>>24)&0xff,($l>>16)&0xff,($l>>8)&0xff,$l&0xff; } } else { @bytes = map(/^0/?oct:int,split(/,\s*/,$2)); } # little-endian conversion if ($flavour =~ /le$/o) { SWITCH: for($conv) { /\?inv/ && do { @bytes=map($_^0xf,@bytes); last; }; /\?rev/ && do { @bytes=reverse(@bytes); last; }; } } #emit print ".byte\t",join(',',map (sprintf("0x%02x",$_),@bytes)),"\n"; next; } $consts=0 if (m/Lconsts:/o); # end of table # instructions prefixed with '?' are endian-specific and need # to be adjusted accordingly... if ($flavour =~ /le$/o) { # little-endian s/le\?//o or s/be\?/#be#/o or s/\?lvsr/lvsl/o or s/\?lvsl/lvsr/o or s/\?(vperm\s+v[0-9]+,\s*)(v[0-9]+,\s*)(v[0-9]+,\s*)(v[0-9]+)/$1$3$2$4/o or s/\?(vsldoi\s+v[0-9]+,\s*)(v[0-9]+,)\s*(v[0-9]+,\s*)([0-9]+)/$1$3$2 16-$4/o or s/\?(vspltw\s+v[0-9]+,\s*)(v[0-9]+,)\s*([0-9])/$1$2 3-$3/o; } else { # big-endian s/le\?/#le#/o or s/be\?//o or s/\?([a-z]+)/$1/o; } print $_,"\n"; } close STDOUT;