diff options
-rwxr-xr-x | crypto/aes/asm/aesv8-armx.pl | 1426 | ||||
-rw-r--r-- | include/crypto/aes_platform.h | 4 | ||||
-rw-r--r-- | test/recipes/30-test_evp_data/evpciph_aes_common.txt | 38 |
3 files changed, 1468 insertions, 0 deletions
diff --git a/crypto/aes/asm/aesv8-armx.pl b/crypto/aes/asm/aesv8-armx.pl index d084885049..ee2e29823a 100755 --- a/crypto/aes/asm/aesv8-armx.pl +++ b/crypto/aes/asm/aesv8-armx.pl @@ -2131,6 +2131,1432 @@ $code.=<<___; .size ${prefix}_ctr32_encrypt_blocks,.-${prefix}_ctr32_encrypt_blocks ___ }}} +# Performance in cycles per byte. +# Processed with AES-XTS different key size. +# It shows the value before and after optimization as below: +# (before/after): +# +# AES-128-XTS AES-256-XTS +# Cortex-A57 3.36/1.09 4.02/1.37 +# Cortex-A72 3.03/1.02 3.28/1.33 + +# Optimization is implemented by loop unrolling and interleaving. +# Commonly, we choose the unrolling factor as 5, if the input +# data size smaller than 5 blocks, but not smaller than 3 blocks, +# choose 3 as the unrolling factor. +# If the input data size dsize >= 5*16 bytes, then take 5 blocks +# as one iteration, every loop the left size lsize -= 5*16. +# If lsize < 5*16 bytes, treat them as the tail. Note: left 4*16 bytes +# will be processed specially, which be integrated into the 5*16 bytes +# loop to improve the efficiency. +# There is one special case, if the original input data size dsize +# = 16 bytes, we will treat it seperately to improve the +# performance: one independent code block without LR, FP load and +# store. +# Encryption will process the (length -tailcnt) bytes as mentioned +# previously, then encrypt the composite block as last second +# cipher block. +# Decryption will process the (length -tailcnt -1) bytes as mentioned +# previously, then decrypt the last second cipher block to get the +# last plain block(tail), decrypt the composite block as last second +# plain text block. + +{{{ +my ($inp,$out,$len,$key1,$key2,$ivp)=map("x$_",(0..5)); +my ($rounds0,$rounds,$key_,$step,$ivl,$ivh)=("w5","w6","x7","x8","x9","x10"); +my ($tmpoutp,$loutp,$l2outp,$tmpinp)=("x13","w14","w15","x20"); +my ($tailcnt,$midnum,$midnumx,$constnum,$constnumx)=("x21","w22","x22","w19","x19"); +my ($xoffset,$tmpmx,$tmpmw)=("x6","x11","w11"); +my ($dat0,$dat1,$in0,$in1,$tmp0,$tmp1,$tmp2,$rndlast)=map("q$_",(0..7)); +my ($iv0,$iv1,$iv2,$iv3,$iv4)=("v6.16b","v8.16b","v9.16b","v10.16b","v11.16b"); +my ($ivd00,$ivd01,$ivd20,$ivd21)=("d6","v6.d[1]","d9","v9.d[1]"); +my ($ivd10,$ivd11,$ivd30,$ivd31,$ivd40,$ivd41)=("d8","v8.d[1]","d10","v10.d[1]","d11","v11.d[1]"); + +my ($tmpin)=("v26.16b"); +my ($dat,$tmp,$rndzero_n_last)=($dat0,$tmp0,$tmp1); + +# q7 last round key +# q10-q15, q7 Last 7 round keys +# q8-q9 preloaded round keys except last 7 keys for big size +# q20, q21, q8-q9 preloaded round keys except last 7 keys for only 16 byte + + +my ($dat2,$in2,$tmp2)=map("q$_",(10,11,9)); + +my ($dat3,$in3,$tmp3); # used only in 64-bit mode +my ($dat4,$in4,$tmp4); +if ($flavour =~ /64/) { + ($dat2,$dat3,$dat4,$in2,$in3,$in4,$tmp3,$tmp4)=map("q$_",(16..23)); +} + +$code.=<<___ if ($flavour =~ /64/); +.globl ${prefix}_xts_encrypt +.type ${prefix}_xts_encrypt,%function +.align 5 +${prefix}_xts_encrypt: +___ +$code.=<<___ if ($flavour =~ /64/); + cmp $len,#16 + // Original input data size bigger than 16, jump to big size processing. + b.ne .Lxts_enc_big_size + // Encrypt the iv with key2, as the first XEX iv. + ldr $rounds,[$key2,#240] + vld1.8 {$dat},[$key2],#16 + vld1.8 {$iv0},[$ivp] + sub $rounds,$rounds,#2 + vld1.8 {$dat1},[$key2],#16 + +.Loop_enc_iv_enc: + aese $iv0,$dat + aesmc $iv0,$iv0 + vld1.32 {$dat},[$key2],#16 + subs $rounds,$rounds,#2 + aese $iv0,$dat1 + aesmc $iv0,$iv0 + vld1.32 {$dat1},[$key2],#16 + b.gt .Loop_enc_iv_enc + + aese $iv0,$dat + aesmc $iv0,$iv0 + vld1.32 {$dat},[$key2] + aese $iv0,$dat1 + veor $iv0,$iv0,$dat + + vld1.8 {$dat0},[$inp] + veor $dat0,$iv0,$dat0 + + ldr $rounds,[$key1,#240] + vld1.32 {q20-q21},[$key1],#32 // load key schedule... + + aese $dat0,q20 + aesmc $dat0,$dat0 + vld1.32 {q8-q9},[$key1],#32 // load key schedule... + aese $dat0,q21 + aesmc $dat0,$dat0 + subs $rounds,$rounds,#10 // if rounds==10, jump to aes-128-xts processing + b.eq .Lxts_128_enc +.Lxts_enc_round_loop: + aese $dat0,q8 + aesmc $dat0,$dat0 + vld1.32 {q8},[$key1],#16 // load key schedule... + aese $dat0,q9 + aesmc $dat0,$dat0 + vld1.32 {q9},[$key1],#16 // load key schedule... + subs $rounds,$rounds,#2 // bias + b.gt .Lxts_enc_round_loop +.Lxts_128_enc: + vld1.32 {q10-q11},[$key1],#32 // load key schedule... + aese $dat0,q8 + aesmc $dat0,$dat0 + aese $dat0,q9 + aesmc $dat0,$dat0 + vld1.32 {q12-q13},[$key1],#32 // load key schedule... + aese $dat0,q10 + aesmc $dat0,$dat0 + aese $dat0,q11 + aesmc $dat0,$dat0 + vld1.32 {q14-q15},[$key1],#32 // load key schedule... + aese $dat0,q12 + aesmc $dat0,$dat0 + aese $dat0,q13 + aesmc $dat0,$dat0 + vld1.32 {$rndlast},[$key1] + aese $dat0,q14 + aesmc $dat0,$dat0 + aese $dat0,q15 + veor $dat0,$dat0,$rndlast + veor $dat0,$dat0,$iv0 + vst1.8 {$dat0},[$out] + b .Lxts_enc_final_abort + +.align 4 +.Lxts_enc_big_size: +___ +$code.=<<___ if ($flavour =~ /64/); + stp $constnumx,$tmpinp,[sp,#-64]! + stp $tailcnt,$midnumx,[sp,#48] + stp $ivd10,$ivd20,[sp,#32] + stp $ivd30,$ivd40,[sp,#16] + + // tailcnt store the tail value of length%16. + and $tailcnt,$len,#0xf + and $len,$len,#-16 + subs $len,$len,#16 + mov $step,#16 + b.lo .Lxts_abort + csel $step,xzr,$step,eq + + // Firstly, encrypt the iv with key2, as the first iv of XEX. + ldr $rounds,[$key2,#240] + vld1.32 {$dat},[$key2],#16 + vld1.8 {$iv0},[$ivp] + sub $rounds,$rounds,#2 + vld1.32 {$dat1},[$key2],#16 + +.Loop_iv_enc: + aese $iv0,$dat + aesmc $iv0,$iv0 + vld1.32 {$dat},[$key2],#16 + subs $rounds,$rounds,#2 + aese $iv0,$dat1 + aesmc $iv0,$iv0 + vld1.32 {$dat1},[$key2],#16 + b.gt .Loop_iv_enc + + aese $iv0,$dat + aesmc $iv0,$iv0 + vld1.32 {$dat},[$key2] + aese $iv0,$dat1 + veor $iv0,$iv0,$dat + + // The iv for second block + // $ivl- iv(low), $ivh - iv(high) + // the five ivs stored into, $iv0,$iv1,$iv2,$iv3,$iv4 + fmov $ivl,$ivd00 + fmov $ivh,$ivd01 + mov $constnum,#0x87 + extr $midnumx,$ivh,$ivh,#32 + extr $ivh,$ivh,$ivl,#63 + and $tmpmw,$constnum,$midnum,asr#31 + eor $ivl,$tmpmx,$ivl,lsl#1 + fmov $ivd10,$ivl + fmov $ivd11,$ivh + + ldr $rounds0,[$key1,#240] // next starting point + vld1.8 {$dat},[$inp],$step + + vld1.32 {q8-q9},[$key1] // load key schedule... + sub $rounds0,$rounds0,#6 + add $key_,$key1,$ivp,lsl#4 // pointer to last 7 round keys + sub $rounds0,$rounds0,#2 + vld1.32 {q10-q11},[$key_],#32 + vld1.32 {q12-q13},[$key_],#32 + vld1.32 {q14-q15},[$key_],#32 + vld1.32 {$rndlast},[$key_] + + add $key_,$key1,#32 + mov $rounds,$rounds0 + + // Encryption +.Lxts_enc: + vld1.8 {$dat2},[$inp],#16 + subs $len,$len,#32 // bias + add $rounds,$rounds0,#2 + vorr $in1,$dat,$dat + vorr $dat1,$dat,$dat + vorr $in3,$dat,$dat + vorr $in2,$dat2,$dat2 + vorr $in4,$dat2,$dat2 + b.lo .Lxts_inner_enc_tail + veor $dat,$dat,$iv0 // before encryption, xor with iv + veor $dat2,$dat2,$iv1 + + // The iv for third block + extr $midnumx,$ivh,$ivh,#32 + extr $ivh,$ivh,$ivl,#63 + and $tmpmw,$constnum,$midnum,asr#31 + eor $ivl,$tmpmx,$ivl,lsl#1 + fmov $ivd20,$ivl + fmov $ivd21,$ivh + + + vorr $dat1,$dat2,$dat2 + vld1.8 {$dat2},[$inp],#16 + vorr $in0,$dat,$dat + vorr $in1,$dat1,$dat1 + veor $in2,$dat2,$iv2 // the third block + veor $dat2,$dat2,$iv2 + cmp $len,#32 + b.lo .Lxts_outer_enc_tail + + // The iv for fourth block + extr $midnumx,$ivh,$ivh,#32 + extr $ivh,$ivh,$ivl,#63 + and $tmpmw,$constnum,$midnum,asr#31 + eor $ivl,$tmpmx,$ivl,lsl#1 + fmov $ivd30,$ivl + fmov $ivd31,$ivh + + vld1.8 {$dat3},[$inp],#16 + // The iv for fifth block + extr $midnumx,$ivh,$ivh,#32 + extr $ivh,$ivh,$ivl,#63 + and $tmpmw,$constnum,$midnum,asr#31 + eor $ivl,$tmpmx,$ivl,lsl#1 + fmov $ivd40,$ivl + fmov $ivd41,$ivh + + vld1.8 {$dat4},[$inp],#16 + veor $dat3,$dat3,$iv3 // the fourth block + veor $dat4,$dat4,$iv4 + sub $len,$len,#32 // bias + mov $rounds,$rounds0 + b .Loop5x_xts_enc + +.align 4 +.Loop5x_xts_enc: + aese $dat0,q8 + aesmc $dat0,$dat0 + aese $dat1,q8 + aesmc $dat1,$dat1 + aese $dat2,q8 + aesmc $dat2,$dat2 + aese $dat3,q8 + aesmc $dat3,$dat3 + aese $dat4,q8 + aesmc $dat4,$dat4 + vld1.32 {q8},[$key_],#16 + subs $rounds,$rounds,#2 + aese $dat0,q9 + aesmc $dat0,$dat0 + aese $dat1,q9 + aesmc $dat1,$dat1 + aese $dat2,q9 + aesmc $dat2,$dat2 + aese $dat3,q9 + aesmc $dat3,$dat3 + aese $dat4,q9 + aesmc $dat4,$dat4 + vld1.32 {q9},[$key_],#16 + b.gt .Loop5x_xts_enc + + aese $dat0,q8 + aesmc $dat0,$dat0 + aese $dat1,q8 + aesmc $dat1,$dat1 + aese $dat2,q8 + aesmc $dat2,$dat2 + aese $dat3,q8 + aesmc $dat3,$dat3 + aese $dat4,q8 + aesmc $dat4,$dat4 + subs $len,$len,#0x50 // because .Lxts_enc_tail4x + + aese $dat0,q9 + aesmc $dat0,$dat0 + aese $dat1,q9 + aesmc $dat1,$dat1 + aese $dat2,q9 + aesmc $dat2,$dat2 + aese $dat3,q9 + aesmc $dat3,$dat3 + aese $dat4,q9 + aesmc $dat4,$dat4 + csel $xoffset,xzr,$len,gt // borrow x6, w6, "gt" is not typo + mov $key_,$key1 + + aese $dat0,q10 + aesmc $dat0,$dat0 + aese $dat1,q10 + aesmc $dat1,$dat1 + aese $dat2,q10 + aesmc $dat2,$dat2 + aese $dat3,q10 + aesmc $dat3,$dat3 + aese $dat4,q10 + aesmc $dat4,$dat4 + add $inp,$inp,$xoffset // x0 is adjusted in such way that + // at exit from the loop v1.16b-v26.16b + // are loaded with last "words" + add $xoffset,$len,#0x60 // because .Lxts_enc_tail4x + + aese $dat0,q11 + aesmc $dat0,$dat0 + aese $dat1,q11 + aesmc $dat1,$dat1 + aese $dat2,q11 + aesmc $dat2,$dat2 + aese $dat3,q11 + aesmc $dat3,$dat3 + aese $dat4,q11 + aesmc $dat4,$dat4 + + aese $dat0,q12 + aesmc $dat0,$dat0 + aese $dat1,q12 + aesmc $dat1,$dat1 + aese $dat2,q12 + aesmc $dat2,$dat2 + aese $dat3,q12 + aesmc $dat3,$dat3 + aese $dat4,q12 + aesmc $dat4,$dat4 + + aese $dat0,q13 + aesmc $dat0,$dat0 + aese $dat1,q13 + aesmc $dat1,$dat1 + aese $dat2,q13 + aesmc $dat2,$dat2 + aese $dat3,q13 + aesmc $dat3,$dat3 + aese $dat4,q13 + aesmc $dat4,$dat4 + + aese $dat0,q14 + aesmc $dat0,$dat0 + aese $dat1,q14 + aesmc $dat1,$dat1 + aese $dat2,q14 + aesmc $dat2,$dat2 + aese $dat3,q14 + aesmc $dat3,$dat3 + aese $dat4,q14 + aesmc $dat4,$dat4 + + veor $tmp0,$rndlast,$iv0 + aese $dat0,q15 + // The iv for first block of one iteration + extr $midnumx,$ivh,$ivh,#32 + extr $ivh,$ivh,$ivl,#63 + and $tmpmw,$constnum,$midnum,asr#31 + eor $ivl,$tmpmx,$ivl,lsl#1 + fmov $ivd00,$ivl + fmov $ivd01,$ivh + veor $tmp1,$rndlast,$iv1 + vld1.8 {$in0},[$inp],#16 + aese $dat1,q15 + // The iv for second block + extr $midnumx,$ivh,$ivh,#32 + extr $ivh,$ivh,$ivl,#63 + and $tmpmw,$constnum,$midnum,asr#31 + eor $ivl,$tmpmx,$ivl,lsl#1 + fmov $ivd10,$ivl + fmov $ivd11,$ivh + veor $tmp2,$rndlast,$iv2 + vld1.8 {$in1},[$inp],#16 + aese $dat2,q15 + // The iv for third block + extr $midnumx,$ivh,$ivh,#32 + extr $ivh,$ivh,$ivl,#63 + and $tmpmw,$constnum,$midnum,asr#31 + eor $ivl,$tmpmx,$ivl,lsl#1 + fmov $ivd20,$ivl + fmov $ivd21,$ivh + veor $tmp3,$rndlast,$iv3 + vld1.8 {$in2},[$inp],#16 + aese $dat3,q15 + // The iv for fourth block + extr $midnumx,$ivh,$ivh,#32 + extr $ivh,$ivh,$ivl,#63 + and $tmpmw,$constnum,$midnum,asr#31 + eor $ivl,$tmpmx,$ivl,lsl#1 + fmov $ivd30,$ivl + fmov $ivd31,$ivh + veor $tmp4,$rndlast,$iv4 + vld1.8 {$in3},[$inp],#16 + aese $dat4,q15 + + // The iv for fifth block + extr $midnumx,$ivh,$ivh,#32 + extr $ivh,$ivh,$ivl,#63 + and $tmpmw,$constnum,$midnum,asr #31 + eor $ivl,$tmpmx,$ivl,lsl #1 + fmov $ivd40,$ivl + fmov $ivd41,$ivh + + vld1.8 {$in4},[$inp],#16 + cbz $xoffset,.Lxts_enc_tail4x + vld1.32 {q8},[$key_],#16 // re-pre-load rndkey[0] + veor $tmp0,$tmp0,$dat0 + veor $dat0,$in0,$iv0 + veor $tmp1,$tmp1,$dat1 + veor $dat1,$in1,$iv1 + veor $tmp2,$tmp2,$dat2 + veor $dat2,$in2,$iv2 + veor $tmp3,$tmp3,$dat3 + veor $dat3,$in3,$iv3 + veor $tmp4,$tmp4,$dat4 + vst1.8 {$tmp0},[$out],#16 + veor $dat4,$in4,$iv4 + vst1.8 {$tmp1},[$out],#16 + mov $rounds,$rounds0 + vst1.8 {$tmp2},[$out],#16 + vld1.32 {q9},[$key_],#16 // re-pre-load rndkey[1] + vst1.8 {$tmp3},[$out],#16 + vst1.8 {$tmp4},[$out],#16 + b.hs .Loop5x_xts_enc + + + // If left 4 blocks, borrow the five block's processing. + cmn $len,#0x10 + b.ne .Loop5x_enc_after + vorr $iv4,$iv3,$iv3 + vorr $iv3,$iv2,$iv2 + vorr $iv2,$iv1,$iv1 + vorr $iv1,$iv0,$iv0 + fmov $ivl,$ivd40 + fmov $ivh,$ivd41 + veor $dat0,$iv0,$in0 + veor $dat1,$iv1,$in1 + veor $dat2,$in2,$iv2 + veor $dat3,$in3,$iv3 + veor $dat4,$in4,$iv4 + b.eq .Loop5x_xts_enc + +.Loop5x_enc_after: + add $len,$len,#0x50 + cbz $len,.Lxts_enc_done + + add $rounds,$rounds0,#2 + subs $len,$len,#0x30 + b.lo .Lxts_inner_enc_tail + + veor $dat0,$iv0,$in2 + veor $dat1,$iv1,$in3 + veor $dat2,$in4,$iv2 + b .Lxts_outer_enc_tail + +.align 4 +.Lxts_enc_tail4x: + add $inp,$inp,#16 + veor $tmp1,$dat1,$tmp1 + vst1.8 {$tmp1},[$out],#16 + veor $tmp2,$dat2,$tmp2 + vst1.8 {$tmp2},[$out],#16 + veor $tmp3,$dat3,$tmp3 + veor $tmp4,$dat4,$tmp4 + vst1.8 {$tmp3-$tmp4},[$out],#32 + + b .Lxts_enc_done +.align 4 +.Lxts_outer_enc_tail: + aese $dat0,q8 + aesmc $dat0,$dat0 + aese $dat1,q8 + aesmc $dat1,$dat1 + aese $dat2,q8 + aesmc $dat2,$dat2 + vld1.32 {q8},[$key_],#16 + subs $rounds,$rounds,#2 + aese $dat0,q9 + aesmc $dat0,$dat0 + aese $dat1,q9 + aesmc $dat1,$dat1 + aese $dat2,q9 + aesmc $dat2,$dat2 + vld1.32 {q9},[$key_],#16 + b.gt .Lxts_outer_enc_tail + + aese $dat0,q8 + aesmc $dat0,$dat0 + aese $dat1,q8 + aesmc $dat1,$dat1 + aese $dat2,q8 + aesmc $dat2,$dat2 + veor $tmp0,$iv0,$rndlast + subs $len,$len,#0x30 + // The iv for first block + fmov $ivl,$ivd20 + fmov $ivh,$ivd21 + //mov $constnum,#0x87 + extr $midnumx,$ivh,$ivh,#32 + extr $ivh,$ivh,$ivl,#63 + and $tmpmw,$constnum,$midnum,asr#31 + eor $ivl,$tmpmx,$ivl,lsl#1 + fmov $ivd00,$ivl + fmov $ivd01,$ivh + veor $tmp1,$iv1,$rndlast + csel $xoffset,$len,$xoffset,lo // x6, w6, is zero at this point + aese $dat0,q9 + aesmc $dat0,$dat0 + aese $dat1,q9 + aesmc $dat1,$dat1 + aese $dat2,q9 + aesmc $dat2,$dat2 + veor $tmp2,$iv2,$rndlast + + add $xoffset,$xoffset,#0x20 + add $inp,$inp,$xoffset + mov $key_,$key1 + + aese $dat0,q12 + aesmc $dat0,$dat0 + aese $dat1,q12 + aesmc $dat1,$dat1 + aese $dat2,q12 + aesmc $dat2,$dat2 + aese $dat0,q13 + aesmc $dat0,$dat0 + aese $dat1,q13 + aesmc $dat1,$dat1 + aese $dat2,q13 + aesmc $dat2,$dat2 + aese $dat0,q14 + aesmc $dat0,$dat0 + aese $dat1,q14 + aesmc $dat1,$dat1 + aese $dat2,q14 + aesmc $dat2,$dat2 + aese $dat0,q15 + aese $dat1,q15 + aese $dat2,q15 + vld1.8 {$in2},[$inp],#16 + add $rounds,$rounds0,#2 + vld1.32 {q8},[$key_],#16 // re-pre-load rndkey[0] + veor $tmp0,$tmp0,$dat0 + veor $tmp1,$tmp1,$dat1 + veor $dat2,$dat2,$tmp2 + vld1.32 {q9},[$key_],#16 // re-pre-load rndkey[1] + vst1.8 {$tmp0},[$out],#16 + vst1.8 {$tmp1},[$out],#16 + vst1.8 {$dat2},[$out],#16 + cmn $len,#0x30 + b.eq .Lxts_enc_done +.Lxts_encxor_one: + vorr $in3,$in1,$in1 + vorr $in4,$in2,$in2 + nop + +.Lxts_inner_enc_tail: + cmn $len,#0x10 + veor $dat1,$in3,$iv0 + veor $dat2,$in4,$iv1 + b.eq .Lxts_enc_tail_loop + veor $dat2,$in4,$iv0 +.Lxts_enc_tail_loop: + aese $dat1,q8 + aesmc $dat1,$dat1 + aese $dat2,q8 + aesmc $dat2,$dat2 + vld1.32 {q8},[$key_],#16 + subs $rounds,$rounds,#2 + aese $dat1,q9 + aesmc $dat1,$dat1 + aese $dat2,q9 + aesmc $dat2,$dat2 + vld1.32 {q9},[$key_],#16 + b.gt .Lxts_enc_tail_loop + + aese $dat1,q8 + aesmc $dat1,$dat1 + aese $dat2,q8 + aesmc $dat2,$dat2 + aese $dat1,q9 + aesmc $dat1,$dat1 + aese $dat2,q9 + aesmc $dat2,$dat2 + aese $dat1,q12 + aesmc $dat1,$dat1 + aese $dat2,q12 + aesmc $dat2,$dat2 + cmn $len,#0x20 + aese $dat1,q13 + aesmc $dat1,$dat1 + aese $dat2,q13 + aesmc $dat2,$dat2 + veor $tmp1,$iv0,$rndlast + aese $dat1,q14 + aesmc $dat1,$dat1 + aese $dat2,q14 + aesmc $dat2,$dat2 + veor $tmp2,$iv1,$rndlast + aese $dat1,q15 + aese $dat2,q15 + b.eq .Lxts_enc_one + veor $tmp1,$tmp1,$dat1 + vst1.8 {$tmp1},[$out],#16 + veor $tmp2,$tmp2,$dat2 + vorr $iv0,$iv1,$iv1 + vst1.8 {$tmp2},[$out],#16 + fmov $ivl,$ivd10 + fmov $ivh,$ivd11 + mov $constnum,#0x87 + extr $midnumx,$ivh,$ivh,#32 + extr $ivh,$ivh,$ivl,#63 + and $tmpmw,$constnum,$midnum,asr #31 + eor $ivl,$tmpmx,$ivl,lsl #1 + fmov $ivd00,$ivl + fmov $ivd01,$ivh + b .Lxts_enc_done + +.Lxts_enc_one: + veor $tmp1,$tmp1,$dat2 + vorr $iv0,$iv0,$iv0 + vst1.8 {$tmp1},[$out],#16 + fmov $ivl,$ivd00 + fmov $ivh,$ivd01 + mov $constnum,#0x87 + extr $midnumx,$ivh,$ivh,#32 + extr $ivh,$ivh,$ivl,#63 + and $tmpmw,$constnum,$midnum,asr #31 + eor $ivl,$tmpmx,$ivl,lsl #1 + fmov $ivd00,$ivl + fmov $ivd01,$ivh + b .Lxts_enc_done +.align 5 +.Lxts_enc_done: + // Process the tail block with cipher stealing. + tst $tailcnt,#0xf + b.eq .Lxts_abort + + mov $tmpinp,$inp + mov $tmpoutp,$out + sub $out,$out,#16 +.composite_enc_loop: + subs $tailcnt,$tailcnt,#1 + ldrb $l2outp,[$out,$tailcnt] + ldrb $loutp,[$tmpinp,$tailcnt] + strb $l2outp,[$tmpoutp,$tailcnt] + strb $loutp,[$out,$tailcnt] + b.gt .composite_enc_loop +.Lxts_enc_load_done: + vld1.8 {$tmpin},[$out] + veor $tmpin,$tmpin,$iv0 + + // Encrypt the composite block to get the last second encrypted text block + ldr $rounds,[$key1,#240] // load key schedule... + vld1.8 {$dat},[$key1],#16 + sub $rounds,$rounds,#2 + vld1.8 {$dat1},[$key1],#16 // load key schedule... +.Loop_final_enc: + aese $tmpin,$dat0 + aesmc $tmpin,$tmpin + vld1.32 {$dat0},[$key1],#16 + subs $rounds,$rounds,#2 + aese $tmpin,$dat1 + aesmc $tmpin,$tmpin + vld1.32 {$dat1},[$key1],#16 + b.gt .Loop_final_enc + + aese $tmpin,$dat0 + aesmc $tmpin,$tmpin + vld1.32 {$dat0},[$key1] + aese $tmpin,$dat1 + veor $tmpin,$tmpin,$dat0 + veor $tmpin,$tmpin,$iv0 + vst1.8 {$tmpin},[$out] + +.Lxts_abort: + ldp $tailcnt,$midnumx,[sp,#48] + ldp $ivd10,$ivd20,[sp,#32] + ldp $ivd30,$ivd40,[sp,#16] + ldp $constnumx,$tmpinp,[sp],#64 +.Lxts_enc_final_abort: + ret +.size ${prefix}_xts_encrypt,.-${prefix}_xts_encrypt +___ + +}}} +{{{ +my ($inp,$out,$len,$key1,$key2,$ivp)=map("x$_",(0..5)); +my ($rounds0,$rounds,$key_,$step,$ivl,$ivh)=("w5","w6","x7","x8","x9","x10"); +my ($tmpoutp,$loutp,$l2outp,$tmpinp)=("x13","w14","w15","x20"); +my ($tailcnt,$midnum,$midnumx,$constnum,$constnumx)=("x21","w22","x22","w19","x19"); +my ($xoffset,$tmpmx,$tmpmw)=("x6","x11","w11"); +my ($dat0,$dat1,$in0,$in1,$tmp0,$tmp1,$tmp2,$rndlast)=map("q$_",(0..7)); +my ($iv0,$iv1,$iv2,$iv3,$iv4,$tmpin)=("v6.16b","v8.16b","v9.16b","v10.16b","v11.16b","v26.16b"); +my ($ivd00,$ivd01,$ivd20,$ivd21)=("d6","v6.d[1]","d9","v9.d[1]"); +my ($ivd10,$ivd11,$ivd30,$ivd31,$ivd40,$ivd41)=("d8","v8.d[1]","d10","v10.d[1]","d11","v11.d[1]"); + +my ($dat,$tmp,$rndzero_n_last)=($dat0,$tmp0,$tmp1); + +# q7 last round key +# q10-q15, q7 Last 7 round keys +# q8-q9 preloaded round keys except last 7 keys for big size +# q20, q21, q8-q9 preloaded round keys except last 7 keys for only 16 byte + +{ +my ($dat2,$in2,$tmp2)=map("q$_",(10,11,9)); + +my ($dat3,$in3,$tmp3); # used only in 64-bit mode +my ($dat4,$in4,$tmp4); +if ($flavour =~ /64/) { + ($dat2,$dat3,$dat4,$in2,$in3,$in4,$tmp3,$tmp4)=map("q$_",(16..23)); +} + +$code.=<<___ if ($flavour =~ /64/); +.globl ${prefix}_xts_decrypt +.type ${prefix}_xts_decrypt,%function +.align 5 +${prefix}_xts_decrypt: +___ +$code.=<<___ if ($flavour =~ /64/); + cmp $len,#16 + // Original input data size bigger than 16, jump to big size processing. + b.ne .Lxts_dec_big_size + // Encrypt the iv with key2, as the first XEX iv. + ldr $rounds,[$key2,#240] + vld1.8 {$dat},[$key2],#16 + vld1.8 {$iv0},[$ivp] + sub $rounds,$rounds,#2 + vld1.8 {$dat1},[$key2],#16 + +.Loop_dec_small_iv_enc: + aese $iv0,$dat + aesmc $iv0,$iv0 + vld1.32 {$dat},[$key2],#16 + subs $rounds,$rounds,#2 + aese $iv0,$dat1 + aesmc $iv0,$iv0 + vld1.32 {$dat1},[$key2],#16 + b.gt .Loop_dec_small_iv_enc + + aese $iv0,$dat + aesmc $iv0,$iv0 + vld1.32 {$dat},[$key2] + aese $iv0,$dat1 + veor $iv0,$iv0,$dat + + vld1.8 {$dat0},[$inp] + veor $dat0,$iv0,$dat0 + + ldr $rounds,[$key1,#240] + vld1.32 {q20-q21},[$key1],#32 // load key schedule... + + aesd $dat0,q20 + aesimc $dat0,$dat0 + vld1.32 {q8-q9},[$key1],#32 // load key schedule... + aesd $dat0,q21 + aesimc $dat0,$dat0 + subs $rounds,$rounds,#10 // bias + b.eq .Lxts_128_dec +.Lxts_dec_round_loop: + aesd $dat0,q8 + aesimc $dat0,$dat0 + vld1.32 {q8},[$key1],#16 // load key schedule... + aesd $dat0,q9 + aesimc $dat0,$dat0 + vld1.32 {q9},[$key1],#16 // load key schedule... + subs $rounds,$rounds,#2 // bias + b.gt .Lxts_dec_round_loop +.Lxts_128_dec: + vld1.32 {q10-q11},[$key1],#32 // load key schedule... + aesd $dat0,q8 + aesimc $dat0,$dat0 + aesd $dat0,q9 + aesimc $dat0,$dat0 + vld1.32 {q12-q13},[$key1],#32 // load key schedule... + aesd $dat0,q10 + aesimc $dat0,$dat0 + aesd $dat0,q11 + aesimc $dat0,$dat0 + vld1.32 {q14-q15},[$key1],#32 // load key schedule... + aesd $dat0,q12 + aesimc $dat0,$dat0 + aesd $dat0,q13 + aesimc $dat0,$dat0 + vld1.32 {$rndlast},[$key1] + aesd $dat0,q14 + aesimc $dat0,$dat0 + aesd $dat0,q15 + veor $dat0,$dat0,$rndlast + veor $dat0,$iv0,$dat0 + vst1.8 {$dat0},[$out] + b .Lxts_dec_final_abort +.Lxts_dec_big_size: +___ +$code.=<<___ if ($flavour =~ /64/); + stp $constnumx,$tmpinp,[sp,#-64]! + stp $tailcnt,$midnumx,[sp,#48] + stp $ivd10,$ivd20,[sp,#32] + stp $ivd30,$ivd40,[sp,#16] + + and $tailcnt,$len,#0xf + and $len,$len,#-16 + subs $len,$len,#16 + mov $step,#16 + b.lo .Lxts_dec_abort + + // Encrypt the iv with key2, as the first XEX iv + ldr $rounds,[$key2,#240] + vld1.8 {$dat},[$key2],#16 + vld1.8 {$iv0},[$ivp] + sub $rounds,$rounds,#2 + vld1.8 {$dat1},[$key2],#16 + +.Loop_dec_iv_enc: + aese $iv0,$dat + aesmc $iv0,$iv0 + vld1.32 {$dat},[$key2],#16 + subs $rounds,$rounds,#2 + aese $iv0,$dat1 + aesmc $iv0,$iv0 + vld1.32 {$dat1},[$key2],#16 + b.gt .Loop_dec_iv_enc + + aese $iv0,$dat + aesmc $iv0,$iv0 + vld1.32 {$dat},[$key2] + aese $iv0,$dat1 + veor $iv0,$iv0,$dat + + // The iv for second block + // $ivl- iv(low), $ivh - iv(high) + // the five ivs stored into, $iv0,$iv1,$iv2,$iv3,$iv4 + fmov $ivl,$ivd00 + fmov $ivh,$ivd01 + mov $constnum,#0x87 + extr $midnumx,$ivh,$ivh,#32 + extr $ivh,$ivh,$ivl,#63 + and $tmpmw,$constnum,$midnum,asr #31 + eor $ivl,$tmpmx,$ivl,lsl #1 + fmov $ivd10,$ivl + fmov $ivd11,$ivh + + ldr $rounds0,[$key1,#240] // load rounds number + + // The iv for third block + extr $midnumx,$ivh,$ivh,#32 + extr $ivh,$ivh,$ivl,#63 + and $tmpmw,$constnum,$midnum,asr #31 + eor $ivl,$tmpmx,$ivl,lsl #1 + fmov $ivd20,$ivl + fmov $ivd21,$ivh + + vld1.32 {q8-q9},[$key1] // load key schedule... + sub $rounds0,$rounds0,#6 + add $key_,$key1,$ivp,lsl#4 // pointer to last 7 round keys + sub $rounds0,$rounds0,#2 + vld1.32 {q10-q11},[$key_],#32 // load key schedule... + vld1.32 {q12-q13},[$key_],#32 + vld1.32 {q14-q15},[$key_],#32 + vld1.32 {$rndlast},[$key_] + + // The iv for fourth block + extr $midnumx,$ivh,$ivh,#32 + extr $ivh,$ivh,$ivl,#63 + and $tmpmw,$constnum,$midnum,asr #31 + eor $ivl,$tmpmx,$ivl,lsl #1 + fmov $ivd30,$ivl + fmov $ivd31,$ivh + + add $key_,$key1,#32 + mov $rounds,$rounds0 + b .Lxts_dec + + // Decryption +.align 5 +.Lxts_dec: + tst $tailcnt,#0xf + b.eq .Lxts_dec_begin + subs $len,$len,#16 + csel $step,xzr,$step,eq + vld1.8 {$dat},[$inp],#16 + b.lo .Lxts_done + sub $inp,$inp,#16 +.Lxts_dec_begin: + vld1.8 {$dat},[$inp],$step + subs $len,$len,#32 // bias + add $rounds,$rounds0,#2 + vorr $in1,$dat,$dat + vorr $dat1,$dat,$dat + vorr $in3,$dat,$dat + vld1.8 {$dat2},[$inp],#16 + vorr $in2,$dat2,$dat2 + vorr $in4,$dat2,$dat2 + b.lo .Lxts_inner_dec_tail + veor $dat,$dat,$iv0 // before decryt, xor with iv + veor $dat2,$dat2,$iv1 + + vorr $dat1,$dat2,$dat2 + vld1.8 {$dat2},[$inp],#16 + vorr $in0,$dat,$dat + vorr $in1,$dat1,$dat1 + veor $in2,$dat2,$iv2 // third block xox with third iv + veor $dat2,$dat2,$iv2 + cmp $len,#32 + b.lo .Lxts_outer_dec_tail + + vld1.8 {$dat3},[$inp],#16 + + // The iv for fifth block + extr $midnumx,$ivh,$ivh,#32 + extr $ivh,$ivh,$ivl,#63 + and $tmpmw,$constnum,$midnum,asr #31 + eor $ivl,$tmpmx,$ivl,lsl #1 + fmov $ivd40,$ivl + fmov $ivd41,$ivh + + vld1.8 {$dat4},[$inp],#16 + veor $dat3,$dat3,$iv3 // the fourth block + veor $dat4,$dat4,$iv4 + sub $len,$len,#32 // bias + mov $rounds,$rounds0 + b .Loop5x_xts_dec + +.align 4 +.Loop5x_xts_dec: + aesd $dat0,q8 + aesimc $dat0,$dat0 + aesd $dat1,q8 + aesimc $dat1,$dat1 + aesd $dat2,q8 + aesimc $dat2,$dat2 + aesd $dat3,q8 + aesimc $dat3,$dat3 + aesd $dat4,q8 + aesimc $dat4,$dat4 + vld1.32 {q8},[$key_],#16 // load key schedule... + subs $rounds,$rounds,#2 + aesd $dat0,q9 + aesimc $dat0,$dat0 + aesd $dat1,q9 + aesimc $dat1,$dat1 + aesd $dat2,q9 + aesimc $dat2,$dat2 + aesd $dat3,q9 + aesimc $dat3,$dat3 + aesd $dat4,q9 + aesimc $dat4,$dat4 + vld1.32 {q9},[$key_],#16 // load key schedule... + b.gt .Loop5x_xts_dec + + aesd $dat0,q8 + aesimc $dat0,$dat0 + aesd $dat1,q8 + aesimc $dat1,$dat1 + aesd $dat2,q8 + aesimc $dat2,$dat2 + aesd $dat3,q8 + aesimc $dat3,$dat3 + aesd $dat4,q8 + aesimc $dat4,$dat4 + subs $len,$len,#0x50 // because .Lxts_dec_tail4x + + aesd $dat0,q9 + aesimc $dat0,$dat + aesd $dat1,q9 + aesimc $dat1,$dat1 + aesd $dat2,q9 + aesimc $dat2,$dat2 + aesd $dat3,q9 + aesimc $dat3,$dat3 + aesd $dat4,q9 + aesimc $dat4,$dat4 + csel $xoffset,xzr,$len,gt // borrow x6, w6, "gt" is not typo + mov $key_,$key1 + + aesd $dat0,q10 + aesimc $dat0,$dat0 + aesd $dat1,q10 + aesimc $dat1,$dat1 + aesd $dat2,q10 + aesimc $dat2,$dat2 + aesd $dat3,q10 + aesimc $dat3,$dat3 + aesd $dat4,q10 + aesimc $dat4,$dat4 + add $inp,$inp,$xoffset // x0 is adjusted in such way that + // at exit from the loop v1.16b-v26.16b + // are loaded with last "words" + add $xoffset,$len,#0x60 // because .Lxts_dec_tail4x + + aesd $dat0,q11 + aesimc $dat0,$dat0 + aesd $dat1,q11 + aesimc $dat1,$dat1 + aesd $dat2,q11 + aesimc $dat2,$dat2 + aesd $dat3,q11 + aesimc $dat3,$dat3 + aesd $dat4,q11 + aesimc $dat4,$dat4 + + aesd $dat0,q12 + aesimc $dat0,$dat0 + aesd $dat1,q12 + aesimc $dat1,$dat1 + aesd $dat2,q12 + aesimc $dat2,$dat2 + aesd $dat3,q12 + aesimc $dat3,$dat3 + aesd $dat4,q12 + aesimc $dat4,$dat4 + + aesd $dat0,q13 + aesimc $dat0,$dat0 + aesd $dat1,q13 + aesimc $dat1,$dat1 + aesd $dat2,q13 + aesimc $dat2,$dat2 + aesd $dat3,q13 + aesimc $dat3,$dat3 + aesd $dat4,q13 + aesimc $dat4,$dat4 + + aesd $dat0,q14 + aesimc $dat0,$dat0 + aesd $dat1,q14 + aesimc $dat1,$dat1 + aesd $dat2,q14 + aesimc $dat2,$dat2 + aesd $dat3,q14 + aesimc $dat3,$dat3 + aesd $dat4,q14 + aesimc $dat4,$dat4 + + veor $tmp0,$rndlast,$iv0 + aesd $dat0,q15 + // The iv for first block of next iteration. + extr $midnumx,$ivh,$ivh,#32 + extr $ivh,$ivh,$ivl,#63 + and $tmpmw,$constnum,$midnum,asr #31 + eor $ivl,$tmpmx,$ivl,lsl #1 + fmov $ivd00,$ivl + fmov $ivd01,$ivh + veor $tmp1,$rndlast,$iv1 + vld1.8 {$in0},[$inp],#16 + aesd $dat1,q15 + // The iv for second block + extr $midnumx,$ivh,$ivh,#32 + extr $ivh,$ivh,$ivl,#63 + and $tmpmw,$constnum,$midnum,asr #31 + eor $ivl,$tmpmx,$ivl,lsl #1 + fmov $ivd10,$ivl + fmov $ivd11,$ivh + veor $tmp2,$rndlast,$iv2 + vld1.8 {$in1},[$inp],#16 + aesd $dat2,q15 + // The iv for third block + extr $midnumx,$ivh,$ivh,#32 + extr $ivh,$ivh,$ivl,#63 + and $tmpmw,$constnum,$midnum,asr #31 + eor $ivl,$tmpmx,$ivl,lsl #1 + fmov $ivd20,$ivl + fmov $ivd21,$ivh + veor $tmp3,$rndlast,$iv3 + vld1.8 {$in2},[$inp],#16 + aesd $dat3,q15 + // The iv for fourth block + extr $midnumx,$ivh,$ivh,#32 + extr $ivh,$ivh,$ivl,#63 + and $tmpmw,$constnum,$midnum,asr #31 + eor $ivl,$tmpmx,$ivl,lsl #1 + fmov $ivd30,$ivl + fmov $ivd31,$ivh + veor $tmp4,$rndlast,$iv4 + vld1.8 {$in3},[$inp],#16 + aesd $dat4,q15 + + // The iv for fifth block + extr $midnumx,$ivh,$ivh,#32 + extr $ivh,$ivh,$ivl,#63 + and $tmpmw,$constnum,$midnum,asr #31 + eor $ivl,$tmpmx,$ivl,lsl #1 + fmov $ivd40,$ivl + fmov $ivd41,$ivh + + vld1.8 {$in4},[$inp],#16 + cbz $xoffset,.Lxts_dec_tail4x + vld1.32 {q8},[$key_],#16 // re-pre-load rndkey[0] + veor $tmp0,$tmp0,$dat0 + veor $dat0,$in0,$iv0 + veor $tmp1,$tmp1,$dat1 + veor $dat1,$in1,$iv1 + veor $tmp2,$tmp2,$dat2 + veor $dat2,$in2,$iv2 + veor $tmp3,$tmp3,$dat3 + veor $dat3,$in3,$iv3 + veor $tmp4,$tmp4,$dat4 + vst1.8 {$tmp0},[$out],#16 + veor $dat4,$in4,$iv4 + vst1.8 {$tmp1},[$out],#16 + mov $rounds,$rounds0 + vst1.8 {$tmp2},[$out],#16 + vld1.32 {q9},[$key_],#16 // re-pre-load rndkey[1] + vst1.8 {$tmp3},[$out],#16 + vst1.8 {$tmp4},[$out],#16 + b.hs .Loop5x_xts_dec + + cmn $len,#0x10 + b.ne .Loop5x_dec_after + // If x2($len) equal to -0x10, the left blocks is 4. + // After specially processing, utilize the five blocks processing again. + // It will use the following IVs: $iv0,$iv0,$iv1,$iv2,$iv3. + vorr $iv4,$iv3,$iv3 + vorr $iv3,$iv2,$iv2 + vorr $iv2,$iv1,$iv1 + vorr $iv1,$iv0,$iv0 + fmov $ivl,$ivd40 + fmov $ivh,$ivd41 + veor $dat0,$iv0,$in0 + veor $dat1,$iv1,$in1 + veor $dat2,$in2,$iv2 + veor $dat3,$in3,$iv3 + veor $dat4,$in4,$iv4 + b.eq .Loop5x_xts_dec + +.Loop5x_dec_after: + add $len,$len,#0x50 + cbz $len,.Lxts_done + + add $rounds,$rounds0,#2 + subs $len,$len,#0x30 + b.lo .Lxts_inner_dec_tail + + veor $dat0,$iv0,$in2 + veor $dat1,$iv1,$in3 + veor $dat2,$in4,$iv2 + b .Lxts_outer_dec_tail + +.align 4 +.Lxts_dec_tail4x: + add $inp,$inp,#16 + vld1.32 {$dat0},[$inp],#16 + veor $tmp1,$dat1,$tmp0 + vst1.8 {$tmp1},[$out],#16 + veor $tmp2,$dat2,$tmp2 + vst1.8 {$tmp2},[$out],#16 + veor $tmp3,$dat3,$tmp3 + veor $tmp4,$dat4,$tmp4 + vst1.8 {$tmp3-$tmp4},[$out],#32 + + b .Lxts_done +.align 4 +.Lxts_outer_dec_tail: + aesd $dat0,q8 + aesimc $dat0,$dat0 + aesd $dat1,q8 + aesimc $dat1,$dat1 + aesd $dat2,q8 + aesimc $dat2,$dat2 + vld1.32 {q8},[$key_],#16 + subs $rounds,$rounds,#2 + aesd $dat0,q9 + aesimc $dat0,$dat0 + aesd $dat1,q9 + aesimc $dat1,$dat1 + aesd $dat2,q9 + aesimc $dat2,$dat2 + vld1.32 {q9},[$key_],#16 + b.gt .Lxts_outer_dec_tail + + aesd $dat0,q8 + aesimc $dat0,$dat0 + aesd $dat1,q8 + aesimc $dat1,$dat1 + aesd $dat2,q8 + aesimc $dat2,$dat2 + veor $tmp0,$iv0,$rndlast + subs $len,$len,#0x30 + // The iv for first block + fmov $ivl,$ivd20 + fmov $ivh,$ivd21 + mov $constnum,#0x87 + extr $midnumx,$ivh,$ivh,#32 + extr $ivh,$ivh,$ivl,#63 + and $tmpmw,$constnum,$midnum,asr #31 + eor $ivl,$tmpmx,$ivl,lsl #1 + fmov $ivd00,$ivl + fmov $ivd01,$ivh + veor $tmp1,$iv1,$rndlast + csel $xoffset,$len,$xoffset,lo // x6, w6, is zero at this point + aesd $dat0,q9 + aesimc $dat0,$dat0 + aesd $dat1,q9 + aesimc $dat1,$dat1 + aesd $dat2,q9 + aesimc $dat2,$dat2 + veor $tmp2,$iv2,$rndlast + // The iv for second block + extr $midnumx,$ivh,$ivh,#32 + extr $ivh,$ivh,$ivl,#63 + and $tmpmw,$constnum,$midnum,asr #31 + eor $ivl,$tmpmx,$ivl,lsl #1 + fmov $ivd10,$ivl + fmov $ivd11,$ivh + + add $xoffset,$xoffset,#0x20 + add $inp,$inp,$xoffset // $inp is adjusted to the last data + + mov $key_,$key1 + + // The iv for third block + extr $midnumx,$ivh,$ivh |