1238384Sjkim#!/usr/bin/env perl
2238384Sjkim
3238384Sjkim######################################################################
4238384Sjkim## Constant-time SSSE3 AES core implementation.
5238384Sjkim## version 0.1
6238384Sjkim##
7238384Sjkim## By Mike Hamburg (Stanford University), 2009
8238384Sjkim## Public domain.
9238384Sjkim##
10238384Sjkim## For details see http://shiftleft.org/papers/vector_aes/ and
11238384Sjkim## http://crypto.stanford.edu/vpaes/.
12238384Sjkim
13238384Sjkim######################################################################
14238384Sjkim# September 2011.
15238384Sjkim#
16238384Sjkim# Interface to OpenSSL as "almost" drop-in replacement for
17238384Sjkim# aes-x86_64.pl. "Almost" refers to the fact that AES_cbc_encrypt
18238384Sjkim# doesn't handle partial vectors (doesn't have to if called from
19238384Sjkim# EVP only). "Drop-in" implies that this module doesn't share key
20238384Sjkim# schedule structure with the original nor does it make assumption
21238384Sjkim# about its alignment...
22238384Sjkim#
23238384Sjkim# Performance summary. aes-x86_64.pl column lists large-block CBC
24238384Sjkim# encrypt/decrypt/with-hyper-threading-off(*) results in cycles per
25238384Sjkim# byte processed with 128-bit key, and vpaes-x86_64.pl column -
26238384Sjkim# [also large-block CBC] encrypt/decrypt.
27238384Sjkim#
28238384Sjkim#		aes-x86_64.pl		vpaes-x86_64.pl
29238384Sjkim#
30238384Sjkim# Core 2(**)	30.5/43.7/14.3		21.8/25.7(***)
31238384Sjkim# Nehalem	30.5/42.2/14.6		 9.8/11.8
32238384Sjkim# Atom		63.9/79.0/32.1		64.0/84.8(***)
33238384Sjkim#
34238384Sjkim# (*)	"Hyper-threading" in the context refers rather to cache shared
35238384Sjkim#	among multiple cores, than to specifically Intel HTT. As vast
36238384Sjkim#	majority of contemporary cores share cache, slower code path
37238384Sjkim#	is common place. In other words "with-hyper-threading-off"
38238384Sjkim#	results are presented mostly for reference purposes.
39238384Sjkim#
40238384Sjkim# (**)	"Core 2" refers to initial 65nm design, a.k.a. Conroe.
41238384Sjkim#
42238384Sjkim# (***)	Less impressive improvement on Core 2 and Atom is due to slow
43238384Sjkim#	pshufb,	yet it's respectable +40%/78% improvement on Core 2
44238384Sjkim#	(as implied, over "hyper-threading-safe" code path).
45238384Sjkim#
46238384Sjkim#						<appro@openssl.org>
47238384Sjkim
48238384Sjkim$flavour = shift;
49238384Sjkim$output  = shift;
50238384Sjkimif ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
51238384Sjkim
52238384Sjkim$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
53238384Sjkim
54238384Sjkim$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
55238384Sjkim( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or
56238384Sjkim( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
57238384Sjkimdie "can't locate x86_64-xlate.pl";
58238384Sjkim
59246772Sjkimopen OUT,"| \"$^X\" $xlate $flavour $output";
60246772Sjkim*STDOUT=*OUT;
61238384Sjkim
62238384Sjkim$PREFIX="vpaes";
63238384Sjkim
64238384Sjkim$code.=<<___;
65238384Sjkim.text
66238384Sjkim
67238384Sjkim##
68238384Sjkim##  _aes_encrypt_core
69238384Sjkim##
70238384Sjkim##  AES-encrypt %xmm0.
71238384Sjkim##
72238384Sjkim##  Inputs:
73238384Sjkim##     %xmm0 = input
74238384Sjkim##     %xmm9-%xmm15 as in _vpaes_preheat
75238384Sjkim##    (%rdx) = scheduled keys
76238384Sjkim##
77238384Sjkim##  Output in %xmm0
78238384Sjkim##  Clobbers  %xmm1-%xmm5, %r9, %r10, %r11, %rax
79238384Sjkim##  Preserves %xmm6 - %xmm8 so you get some local vectors
80238384Sjkim##
81238384Sjkim##
82238384Sjkim.type	_vpaes_encrypt_core,\@abi-omnipotent
83238384Sjkim.align 16
84238384Sjkim_vpaes_encrypt_core:
85238384Sjkim	mov	%rdx,	%r9
86238384Sjkim	mov	\$16,	%r11
87238384Sjkim	mov	240(%rdx),%eax
88238384Sjkim	movdqa	%xmm9,	%xmm1
89238384Sjkim	movdqa	.Lk_ipt(%rip), %xmm2	# iptlo
90238384Sjkim	pandn	%xmm0,	%xmm1
91238384Sjkim	movdqu	(%r9),	%xmm5		# round0 key
92238384Sjkim	psrld	\$4,	%xmm1
93238384Sjkim	pand	%xmm9,	%xmm0
94238384Sjkim	pshufb	%xmm0,	%xmm2
95238384Sjkim	movdqa	.Lk_ipt+16(%rip), %xmm0	# ipthi
96238384Sjkim	pshufb	%xmm1,	%xmm0
97238384Sjkim	pxor	%xmm5,	%xmm2
98238384Sjkim	pxor	%xmm2,	%xmm0
99238384Sjkim	add	\$16,	%r9
100238384Sjkim	lea	.Lk_mc_backward(%rip),%r10
101238384Sjkim	jmp	.Lenc_entry
102238384Sjkim
103238384Sjkim.align 16
104238384Sjkim.Lenc_loop:
105238384Sjkim	# middle of middle round
106238384Sjkim	movdqa  %xmm13,	%xmm4	# 4 : sb1u
107238384Sjkim	pshufb  %xmm2,	%xmm4	# 4 = sb1u
108238384Sjkim	pxor	%xmm5,	%xmm4	# 4 = sb1u + k
109238384Sjkim	movdqa  %xmm12,	%xmm0	# 0 : sb1t
110238384Sjkim	pshufb  %xmm3,	%xmm0	# 0 = sb1t
111238384Sjkim	pxor	%xmm4,	%xmm0	# 0 = A
112238384Sjkim	movdqa  %xmm15,	%xmm5	# 4 : sb2u
113238384Sjkim	pshufb	%xmm2,	%xmm5	# 4 = sb2u
114238384Sjkim	movdqa	-0x40(%r11,%r10), %xmm1		# .Lk_mc_forward[]
115238384Sjkim	movdqa	%xmm14, %xmm2	# 2 : sb2t
116238384Sjkim	pshufb	%xmm3,  %xmm2	# 2 = sb2t
117238384Sjkim	pxor	%xmm5,	%xmm2	# 2 = 2A
118238384Sjkim	movdqa	(%r11,%r10), %xmm4		# .Lk_mc_backward[]
119238384Sjkim	movdqa	%xmm0,  %xmm3	# 3 = A
120238384Sjkim	pshufb  %xmm1,  %xmm0	# 0 = B
121238384Sjkim	add	\$16,	%r9	# next key
122238384Sjkim	pxor	%xmm2,  %xmm0	# 0 = 2A+B
123238384Sjkim	pshufb	%xmm4,	%xmm3	# 3 = D
124238384Sjkim	add	\$16,	%r11	# next mc
125238384Sjkim	pxor	%xmm0,	%xmm3	# 3 = 2A+B+D
126238384Sjkim	pshufb  %xmm1,	%xmm0	# 0 = 2B+C
127238384Sjkim	and	\$0x30,	%r11	# ... mod 4
128238384Sjkim	pxor	%xmm3,	%xmm0	# 0 = 2A+3B+C+D
129238384Sjkim	sub	\$1,%rax	# nr--
130238384Sjkim
131238384Sjkim.Lenc_entry:
132238384Sjkim	# top of round
133238384Sjkim	movdqa  %xmm9, 	%xmm1	# 1 : i
134238384Sjkim	pandn	%xmm0, 	%xmm1	# 1 = i<<4
135238384Sjkim	psrld	\$4,   	%xmm1   # 1 = i
136238384Sjkim	pand	%xmm9, 	%xmm0   # 0 = k
137238384Sjkim	movdqa	%xmm11, %xmm5	# 2 : a/k
138238384Sjkim	pshufb  %xmm0,  %xmm5	# 2 = a/k
139238384Sjkim	pxor	%xmm1,	%xmm0	# 0 = j
140238384Sjkim	movdqa	%xmm10,	%xmm3  	# 3 : 1/i
141238384Sjkim	pshufb  %xmm1, 	%xmm3  	# 3 = 1/i
142238384Sjkim	pxor	%xmm5, 	%xmm3  	# 3 = iak = 1/i + a/k
143238384Sjkim	movdqa	%xmm10,	%xmm4  	# 4 : 1/j
144238384Sjkim	pshufb	%xmm0, 	%xmm4  	# 4 = 1/j
145238384Sjkim	pxor	%xmm5, 	%xmm4  	# 4 = jak = 1/j + a/k
146238384Sjkim	movdqa	%xmm10,	%xmm2  	# 2 : 1/iak
147238384Sjkim	pshufb  %xmm3,	%xmm2  	# 2 = 1/iak
148238384Sjkim	pxor	%xmm0, 	%xmm2  	# 2 = io
149238384Sjkim	movdqa	%xmm10, %xmm3   # 3 : 1/jak
150238384Sjkim	movdqu	(%r9),	%xmm5
151238384Sjkim	pshufb  %xmm4,  %xmm3   # 3 = 1/jak
152238384Sjkim	pxor	%xmm1,  %xmm3   # 3 = jo
153238384Sjkim	jnz	.Lenc_loop
154238384Sjkim
155238384Sjkim	# middle of last round
156238384Sjkim	movdqa	-0x60(%r10), %xmm4	# 3 : sbou	.Lk_sbo
157238384Sjkim	movdqa	-0x50(%r10), %xmm0	# 0 : sbot	.Lk_sbo+16
158238384Sjkim	pshufb  %xmm2,  %xmm4	# 4 = sbou
159238384Sjkim	pxor	%xmm5,  %xmm4	# 4 = sb1u + k
160238384Sjkim	pshufb  %xmm3,	%xmm0	# 0 = sb1t
161238384Sjkim	movdqa	0x40(%r11,%r10), %xmm1		# .Lk_sr[]
162238384Sjkim	pxor	%xmm4,	%xmm0	# 0 = A
163238384Sjkim	pshufb	%xmm1,	%xmm0
164238384Sjkim	ret
165238384Sjkim.size	_vpaes_encrypt_core,.-_vpaes_encrypt_core
166238384Sjkim
167238384Sjkim##
168238384Sjkim##  Decryption core
169238384Sjkim##
170238384Sjkim##  Same API as encryption core.
171238384Sjkim##
172238384Sjkim.type	_vpaes_decrypt_core,\@abi-omnipotent
173238384Sjkim.align	16
174238384Sjkim_vpaes_decrypt_core:
175238384Sjkim	mov	%rdx,	%r9		# load key
176238384Sjkim	mov	240(%rdx),%eax
177238384Sjkim	movdqa	%xmm9,	%xmm1
178238384Sjkim	movdqa	.Lk_dipt(%rip), %xmm2	# iptlo
179238384Sjkim	pandn	%xmm0,	%xmm1
180238384Sjkim	mov	%rax,	%r11
181238384Sjkim	psrld	\$4,	%xmm1
182238384Sjkim	movdqu	(%r9),	%xmm5		# round0 key
183238384Sjkim	shl	\$4,	%r11
184238384Sjkim	pand	%xmm9,	%xmm0
185238384Sjkim	pshufb	%xmm0,	%xmm2
186238384Sjkim	movdqa	.Lk_dipt+16(%rip), %xmm0 # ipthi
187238384Sjkim	xor	\$0x30,	%r11
188238384Sjkim	lea	.Lk_dsbd(%rip),%r10
189238384Sjkim	pshufb	%xmm1,	%xmm0
190238384Sjkim	and	\$0x30,	%r11
191238384Sjkim	pxor	%xmm5,	%xmm2
192238384Sjkim	movdqa	.Lk_mc_forward+48(%rip), %xmm5
193238384Sjkim	pxor	%xmm2,	%xmm0
194238384Sjkim	add	\$16,	%r9
195238384Sjkim	add	%r10,	%r11
196238384Sjkim	jmp	.Ldec_entry
197238384Sjkim
198238384Sjkim.align 16
199238384Sjkim.Ldec_loop:
200238384Sjkim##
201238384Sjkim##  Inverse mix columns
202238384Sjkim##
203238384Sjkim	movdqa  -0x20(%r10),%xmm4	# 4 : sb9u
204238384Sjkim	pshufb	%xmm2,	%xmm4		# 4 = sb9u
205238384Sjkim	pxor	%xmm0,	%xmm4
206238384Sjkim	movdqa  -0x10(%r10),%xmm0	# 0 : sb9t
207238384Sjkim	pshufb	%xmm3,	%xmm0		# 0 = sb9t
208238384Sjkim	pxor	%xmm4,	%xmm0		# 0 = ch
209238384Sjkim	add	\$16, %r9		# next round key
210238384Sjkim
211238384Sjkim	pshufb	%xmm5,	%xmm0		# MC ch
212238384Sjkim	movdqa  0x00(%r10),%xmm4	# 4 : sbdu
213238384Sjkim	pshufb	%xmm2,	%xmm4		# 4 = sbdu
214238384Sjkim	pxor	%xmm0,	%xmm4		# 4 = ch
215238384Sjkim	movdqa  0x10(%r10),%xmm0	# 0 : sbdt
216238384Sjkim	pshufb	%xmm3,	%xmm0		# 0 = sbdt
217238384Sjkim	pxor	%xmm4,	%xmm0		# 0 = ch
218238384Sjkim	sub	\$1,%rax		# nr--
219238384Sjkim
220238384Sjkim	pshufb	%xmm5,	%xmm0		# MC ch
221238384Sjkim	movdqa  0x20(%r10),%xmm4	# 4 : sbbu
222238384Sjkim	pshufb	%xmm2,	%xmm4		# 4 = sbbu
223238384Sjkim	pxor	%xmm0,	%xmm4		# 4 = ch
224238384Sjkim	movdqa  0x30(%r10),%xmm0	# 0 : sbbt
225238384Sjkim	pshufb	%xmm3,	%xmm0		# 0 = sbbt
226238384Sjkim	pxor	%xmm4,	%xmm0		# 0 = ch
227238384Sjkim
228238384Sjkim	pshufb	%xmm5,	%xmm0		# MC ch
229238384Sjkim	movdqa  0x40(%r10),%xmm4	# 4 : sbeu
230238384Sjkim	pshufb	%xmm2,	%xmm4		# 4 = sbeu
231238384Sjkim	pxor	%xmm0,	%xmm4		# 4 = ch
232238384Sjkim	movdqa  0x50(%r10),%xmm0	# 0 : sbet
233238384Sjkim	pshufb	%xmm3,	%xmm0		# 0 = sbet
234238384Sjkim	pxor	%xmm4,	%xmm0		# 0 = ch
235238384Sjkim
236238384Sjkim	palignr	\$12,	%xmm5,	%xmm5
237238384Sjkim
238238384Sjkim.Ldec_entry:
239238384Sjkim	# top of round
240238384Sjkim	movdqa  %xmm9, 	%xmm1	# 1 : i
241238384Sjkim	pandn	%xmm0, 	%xmm1	# 1 = i<<4
242238384Sjkim	psrld	\$4,    %xmm1	# 1 = i
243238384Sjkim	pand	%xmm9, 	%xmm0	# 0 = k
244238384Sjkim	movdqa	%xmm11, %xmm2	# 2 : a/k
245238384Sjkim	pshufb  %xmm0,  %xmm2	# 2 = a/k
246238384Sjkim	pxor	%xmm1,	%xmm0	# 0 = j
247238384Sjkim	movdqa	%xmm10,	%xmm3	# 3 : 1/i
248238384Sjkim	pshufb  %xmm1, 	%xmm3	# 3 = 1/i
249238384Sjkim	pxor	%xmm2, 	%xmm3	# 3 = iak = 1/i + a/k
250238384Sjkim	movdqa	%xmm10,	%xmm4	# 4 : 1/j
251238384Sjkim	pshufb	%xmm0, 	%xmm4	# 4 = 1/j
252238384Sjkim	pxor	%xmm2, 	%xmm4	# 4 = jak = 1/j + a/k
253238384Sjkim	movdqa	%xmm10,	%xmm2	# 2 : 1/iak
254238384Sjkim	pshufb  %xmm3,	%xmm2	# 2 = 1/iak
255238384Sjkim	pxor	%xmm0, 	%xmm2	# 2 = io
256238384Sjkim	movdqa	%xmm10, %xmm3	# 3 : 1/jak
257238384Sjkim	pshufb  %xmm4,  %xmm3	# 3 = 1/jak
258238384Sjkim	pxor	%xmm1,  %xmm3	# 3 = jo
259238384Sjkim	movdqu	(%r9),	%xmm0
260238384Sjkim	jnz	.Ldec_loop
261238384Sjkim
262238384Sjkim	# middle of last round
263238384Sjkim	movdqa	0x60(%r10), %xmm4	# 3 : sbou
264238384Sjkim	pshufb  %xmm2,  %xmm4	# 4 = sbou
265238384Sjkim	pxor	%xmm0,  %xmm4	# 4 = sb1u + k
266238384Sjkim	movdqa	0x70(%r10), %xmm0	# 0 : sbot
267238384Sjkim	movdqa	-0x160(%r11), %xmm2	# .Lk_sr-.Lk_dsbd=-0x160
268238384Sjkim	pshufb  %xmm3,	%xmm0	# 0 = sb1t
269238384Sjkim	pxor	%xmm4,	%xmm0	# 0 = A
270238384Sjkim	pshufb	%xmm2,	%xmm0
271238384Sjkim	ret
272238384Sjkim.size	_vpaes_decrypt_core,.-_vpaes_decrypt_core
273238384Sjkim
274238384Sjkim########################################################
275238384Sjkim##                                                    ##
276238384Sjkim##                  AES key schedule                  ##
277238384Sjkim##                                                    ##
278238384Sjkim########################################################
279238384Sjkim.type	_vpaes_schedule_core,\@abi-omnipotent
280238384Sjkim.align	16
281238384Sjkim_vpaes_schedule_core:
282238384Sjkim	# rdi = key
283238384Sjkim	# rsi = size in bits
284238384Sjkim	# rdx = buffer
285238384Sjkim	# rcx = direction.  0=encrypt, 1=decrypt
286238384Sjkim
287238384Sjkim	call	_vpaes_preheat		# load the tables
288238384Sjkim	movdqa	.Lk_rcon(%rip), %xmm8	# load rcon
289238384Sjkim	movdqu	(%rdi),	%xmm0		# load key (unaligned)
290238384Sjkim
291238384Sjkim	# input transform
292238384Sjkim	movdqa	%xmm0,	%xmm3
293238384Sjkim	lea	.Lk_ipt(%rip), %r11
294238384Sjkim	call	_vpaes_schedule_transform
295238384Sjkim	movdqa	%xmm0,	%xmm7
296238384Sjkim
297238384Sjkim	lea	.Lk_sr(%rip),%r10
298238384Sjkim	test	%rcx,	%rcx
299238384Sjkim	jnz	.Lschedule_am_decrypting
300238384Sjkim
301238384Sjkim	# encrypting, output zeroth round key after transform
302238384Sjkim	movdqu	%xmm0,	(%rdx)
303238384Sjkim	jmp	.Lschedule_go
304238384Sjkim
305238384Sjkim.Lschedule_am_decrypting:
306238384Sjkim	# decrypting, output zeroth round key after shiftrows
307238384Sjkim	movdqa	(%r8,%r10),%xmm1
308238384Sjkim	pshufb  %xmm1,	%xmm3
309238384Sjkim	movdqu	%xmm3,	(%rdx)
310238384Sjkim	xor	\$0x30, %r8
311238384Sjkim
312238384Sjkim.Lschedule_go:
313238384Sjkim	cmp	\$192,	%esi
314238384Sjkim	ja	.Lschedule_256
315238384Sjkim	je	.Lschedule_192
316238384Sjkim	# 128: fall though
317238384Sjkim
318238384Sjkim##
319238384Sjkim##  .schedule_128
320238384Sjkim##
321238384Sjkim##  128-bit specific part of key schedule.
322238384Sjkim##
323238384Sjkim##  This schedule is really simple, because all its parts
324238384Sjkim##  are accomplished by the subroutines.
325238384Sjkim##
326238384Sjkim.Lschedule_128:
327238384Sjkim	mov	\$10, %esi
328238384Sjkim
329238384Sjkim.Loop_schedule_128:
330238384Sjkim	call 	_vpaes_schedule_round
331238384Sjkim	dec	%rsi
332238384Sjkim	jz 	.Lschedule_mangle_last
333238384Sjkim	call	_vpaes_schedule_mangle	# write output
334238384Sjkim	jmp 	.Loop_schedule_128
335238384Sjkim
336238384Sjkim##
337238384Sjkim##  .aes_schedule_192
338238384Sjkim##
339238384Sjkim##  192-bit specific part of key schedule.
340238384Sjkim##
341238384Sjkim##  The main body of this schedule is the same as the 128-bit
342238384Sjkim##  schedule, but with more smearing.  The long, high side is
343238384Sjkim##  stored in %xmm7 as before, and the short, low side is in
344238384Sjkim##  the high bits of %xmm6.
345238384Sjkim##
346238384Sjkim##  This schedule is somewhat nastier, however, because each
347238384Sjkim##  round produces 192 bits of key material, or 1.5 round keys.
348238384Sjkim##  Therefore, on each cycle we do 2 rounds and produce 3 round
349238384Sjkim##  keys.
350238384Sjkim##
351238384Sjkim.align	16
352238384Sjkim.Lschedule_192:
353238384Sjkim	movdqu	8(%rdi),%xmm0		# load key part 2 (very unaligned)
354238384Sjkim	call	_vpaes_schedule_transform	# input transform
355238384Sjkim	movdqa	%xmm0,	%xmm6		# save short part
356238384Sjkim	pxor	%xmm4,	%xmm4		# clear 4
357238384Sjkim	movhlps	%xmm4,	%xmm6		# clobber low side with zeros
358238384Sjkim	mov	\$4,	%esi
359238384Sjkim
360238384Sjkim.Loop_schedule_192:
361238384Sjkim	call	_vpaes_schedule_round
362238384Sjkim	palignr	\$8,%xmm6,%xmm0
363238384Sjkim	call	_vpaes_schedule_mangle	# save key n
364238384Sjkim	call	_vpaes_schedule_192_smear
365238384Sjkim	call	_vpaes_schedule_mangle	# save key n+1
366238384Sjkim	call	_vpaes_schedule_round
367238384Sjkim	dec	%rsi
368238384Sjkim	jz 	.Lschedule_mangle_last
369238384Sjkim	call	_vpaes_schedule_mangle	# save key n+2
370238384Sjkim	call	_vpaes_schedule_192_smear
371238384Sjkim	jmp	.Loop_schedule_192
372238384Sjkim
373238384Sjkim##
374238384Sjkim##  .aes_schedule_256
375238384Sjkim##
376238384Sjkim##  256-bit specific part of key schedule.
377238384Sjkim##
378238384Sjkim##  The structure here is very similar to the 128-bit
379238384Sjkim##  schedule, but with an additional "low side" in
380238384Sjkim##  %xmm6.  The low side's rounds are the same as the
381238384Sjkim##  high side's, except no rcon and no rotation.
382238384Sjkim##
383238384Sjkim.align	16
384238384Sjkim.Lschedule_256:
385238384Sjkim	movdqu	16(%rdi),%xmm0		# load key part 2 (unaligned)
386238384Sjkim	call	_vpaes_schedule_transform	# input transform
387238384Sjkim	mov	\$7, %esi
388238384Sjkim
389238384Sjkim.Loop_schedule_256:
390238384Sjkim	call	_vpaes_schedule_mangle	# output low result
391238384Sjkim	movdqa	%xmm0,	%xmm6		# save cur_lo in xmm6
392238384Sjkim
393238384Sjkim	# high round
394238384Sjkim	call	_vpaes_schedule_round
395238384Sjkim	dec	%rsi
396238384Sjkim	jz 	.Lschedule_mangle_last
397238384Sjkim	call	_vpaes_schedule_mangle
398238384Sjkim
399238384Sjkim	# low round. swap xmm7 and xmm6
400238384Sjkim	pshufd	\$0xFF,	%xmm0,	%xmm0
401238384Sjkim	movdqa	%xmm7,	%xmm5
402238384Sjkim	movdqa	%xmm6,	%xmm7
403238384Sjkim	call	_vpaes_schedule_low_round
404238384Sjkim	movdqa	%xmm5,	%xmm7
405238384Sjkim
406238384Sjkim	jmp	.Loop_schedule_256
407238384Sjkim
408238384Sjkim
409238384Sjkim##
410238384Sjkim##  .aes_schedule_mangle_last
411238384Sjkim##
412238384Sjkim##  Mangler for last round of key schedule
413238384Sjkim##  Mangles %xmm0
414238384Sjkim##    when encrypting, outputs out(%xmm0) ^ 63
415238384Sjkim##    when decrypting, outputs unskew(%xmm0)
416238384Sjkim##
417238384Sjkim##  Always called right before return... jumps to cleanup and exits
418238384Sjkim##
419238384Sjkim.align	16
420238384Sjkim.Lschedule_mangle_last:
421238384Sjkim	# schedule last round key from xmm0
422238384Sjkim	lea	.Lk_deskew(%rip),%r11	# prepare to deskew
423238384Sjkim	test	%rcx, 	%rcx
424238384Sjkim	jnz	.Lschedule_mangle_last_dec
425238384Sjkim
426238384Sjkim	# encrypting
427238384Sjkim	movdqa	(%r8,%r10),%xmm1
428238384Sjkim	pshufb	%xmm1,	%xmm0		# output permute
429238384Sjkim	lea	.Lk_opt(%rip),	%r11	# prepare to output transform
430238384Sjkim	add	\$32,	%rdx
431238384Sjkim
432238384Sjkim.Lschedule_mangle_last_dec:
433238384Sjkim	add	\$-16,	%rdx
434238384Sjkim	pxor	.Lk_s63(%rip),	%xmm0
435238384Sjkim	call	_vpaes_schedule_transform # output transform
436238384Sjkim	movdqu	%xmm0,	(%rdx)		# save last key
437238384Sjkim
438238384Sjkim	# cleanup
439238384Sjkim	pxor	%xmm0,  %xmm0
440238384Sjkim	pxor	%xmm1,  %xmm1
441238384Sjkim	pxor	%xmm2,  %xmm2
442238384Sjkim	pxor	%xmm3,  %xmm3
443238384Sjkim	pxor	%xmm4,  %xmm4
444238384Sjkim	pxor	%xmm5,  %xmm5
445238384Sjkim	pxor	%xmm6,  %xmm6
446238384Sjkim	pxor	%xmm7,  %xmm7
447238384Sjkim	ret
448238384Sjkim.size	_vpaes_schedule_core,.-_vpaes_schedule_core
449238384Sjkim
450238384Sjkim##
451238384Sjkim##  .aes_schedule_192_smear
452238384Sjkim##
453238384Sjkim##  Smear the short, low side in the 192-bit key schedule.
454238384Sjkim##
455238384Sjkim##  Inputs:
456238384Sjkim##    %xmm7: high side, b  a  x  y
457238384Sjkim##    %xmm6:  low side, d  c  0  0
458238384Sjkim##    %xmm13: 0
459238384Sjkim##
460238384Sjkim##  Outputs:
461238384Sjkim##    %xmm6: b+c+d  b+c  0  0
462238384Sjkim##    %xmm0: b+c+d  b+c  b  a
463238384Sjkim##
464238384Sjkim.type	_vpaes_schedule_192_smear,\@abi-omnipotent
465238384Sjkim.align	16
466238384Sjkim_vpaes_schedule_192_smear:
467238384Sjkim	pshufd	\$0x80,	%xmm6,	%xmm0	# d c 0 0 -> c 0 0 0
468238384Sjkim	pxor	%xmm0,	%xmm6		# -> c+d c 0 0
469238384Sjkim	pshufd	\$0xFE,	%xmm7,	%xmm0	# b a _ _ -> b b b a
470238384Sjkim	pxor	%xmm0,	%xmm6		# -> b+c+d b+c b a
471238384Sjkim	movdqa	%xmm6,	%xmm0
472238384Sjkim	pxor	%xmm1,	%xmm1
473238384Sjkim	movhlps	%xmm1,	%xmm6		# clobber low side with zeros
474238384Sjkim	ret
475238384Sjkim.size	_vpaes_schedule_192_smear,.-_vpaes_schedule_192_smear
476238384Sjkim
477238384Sjkim##
478238384Sjkim##  .aes_schedule_round
479238384Sjkim##
480238384Sjkim##  Runs one main round of the key schedule on %xmm0, %xmm7
481238384Sjkim##
482238384Sjkim##  Specifically, runs subbytes on the high dword of %xmm0
483238384Sjkim##  then rotates it by one byte and xors into the low dword of
484238384Sjkim##  %xmm7.
485238384Sjkim##
486238384Sjkim##  Adds rcon from low byte of %xmm8, then rotates %xmm8 for
487238384Sjkim##  next rcon.
488238384Sjkim##
489238384Sjkim##  Smears the dwords of %xmm7 by xoring the low into the
490238384Sjkim##  second low, result into third, result into highest.
491238384Sjkim##
492238384Sjkim##  Returns results in %xmm7 = %xmm0.
493238384Sjkim##  Clobbers %xmm1-%xmm4, %r11.
494238384Sjkim##
495238384Sjkim.type	_vpaes_schedule_round,\@abi-omnipotent
496238384Sjkim.align	16
497238384Sjkim_vpaes_schedule_round:
498238384Sjkim	# extract rcon from xmm8
499238384Sjkim	pxor	%xmm1,	%xmm1
500238384Sjkim	palignr	\$15,	%xmm8,	%xmm1
501238384Sjkim	palignr	\$15,	%xmm8,	%xmm8
502238384Sjkim	pxor	%xmm1,	%xmm7
503238384Sjkim
504238384Sjkim	# rotate
505238384Sjkim	pshufd	\$0xFF,	%xmm0,	%xmm0
506238384Sjkim	palignr	\$1,	%xmm0,	%xmm0
507238384Sjkim
508238384Sjkim	# fall through...
509238384Sjkim
510238384Sjkim	# low round: same as high round, but no rotation and no rcon.
511238384Sjkim_vpaes_schedule_low_round:
512238384Sjkim	# smear xmm7
513238384Sjkim	movdqa	%xmm7,	%xmm1
514238384Sjkim	pslldq	\$4,	%xmm7
515238384Sjkim	pxor	%xmm1,	%xmm7
516238384Sjkim	movdqa	%xmm7,	%xmm1
517238384Sjkim	pslldq	\$8,	%xmm7
518238384Sjkim	pxor	%xmm1,	%xmm7
519238384Sjkim	pxor	.Lk_s63(%rip), %xmm7
520238384Sjkim
521238384Sjkim	# subbytes
522238384Sjkim	movdqa  %xmm9, 	%xmm1
523238384Sjkim	pandn	%xmm0, 	%xmm1
524238384Sjkim	psrld	\$4,    %xmm1		# 1 = i
525238384Sjkim	pand	%xmm9, 	%xmm0		# 0 = k
526238384Sjkim	movdqa	%xmm11, %xmm2		# 2 : a/k
527238384Sjkim	pshufb  %xmm0,  %xmm2		# 2 = a/k
528238384Sjkim	pxor	%xmm1,	%xmm0		# 0 = j
529238384Sjkim	movdqa	%xmm10,	%xmm3		# 3 : 1/i
530238384Sjkim	pshufb  %xmm1, 	%xmm3		# 3 = 1/i
531238384Sjkim	pxor	%xmm2, 	%xmm3		# 3 = iak = 1/i + a/k
532238384Sjkim	movdqa	%xmm10,	%xmm4		# 4 : 1/j
533238384Sjkim	pshufb	%xmm0, 	%xmm4		# 4 = 1/j
534238384Sjkim	pxor	%xmm2, 	%xmm4		# 4 = jak = 1/j + a/k
535238384Sjkim	movdqa	%xmm10,	%xmm2		# 2 : 1/iak
536238384Sjkim	pshufb  %xmm3,	%xmm2		# 2 = 1/iak
537238384Sjkim	pxor	%xmm0, 	%xmm2		# 2 = io
538238384Sjkim	movdqa	%xmm10, %xmm3		# 3 : 1/jak
539238384Sjkim	pshufb  %xmm4,  %xmm3		# 3 = 1/jak
540238384Sjkim	pxor	%xmm1,  %xmm3		# 3 = jo
541238384Sjkim	movdqa	%xmm13, %xmm4		# 4 : sbou
542238384Sjkim	pshufb  %xmm2,  %xmm4		# 4 = sbou
543238384Sjkim	movdqa	%xmm12, %xmm0		# 0 : sbot
544238384Sjkim	pshufb  %xmm3,	%xmm0		# 0 = sb1t
545238384Sjkim	pxor	%xmm4, 	%xmm0		# 0 = sbox output
546238384Sjkim
547238384Sjkim	# add in smeared stuff
548238384Sjkim	pxor	%xmm7,	%xmm0
549238384Sjkim	movdqa	%xmm0,	%xmm7
550238384Sjkim	ret
551238384Sjkim.size	_vpaes_schedule_round,.-_vpaes_schedule_round
552238384Sjkim
553238384Sjkim##
554238384Sjkim##  .aes_schedule_transform
555238384Sjkim##
556238384Sjkim##  Linear-transform %xmm0 according to tables at (%r11)
557238384Sjkim##
558238384Sjkim##  Requires that %xmm9 = 0x0F0F... as in preheat
559238384Sjkim##  Output in %xmm0
560238384Sjkim##  Clobbers %xmm1, %xmm2
561238384Sjkim##
562238384Sjkim.type	_vpaes_schedule_transform,\@abi-omnipotent
563238384Sjkim.align	16
564238384Sjkim_vpaes_schedule_transform:
565238384Sjkim	movdqa	%xmm9,	%xmm1
566238384Sjkim	pandn	%xmm0,	%xmm1
567238384Sjkim	psrld	\$4,	%xmm1
568238384Sjkim	pand	%xmm9,	%xmm0
569238384Sjkim	movdqa	(%r11), %xmm2 	# lo
570238384Sjkim	pshufb	%xmm0,	%xmm2
571238384Sjkim	movdqa	16(%r11), %xmm0 # hi
572238384Sjkim	pshufb	%xmm1,	%xmm0
573238384Sjkim	pxor	%xmm2,	%xmm0
574238384Sjkim	ret
575238384Sjkim.size	_vpaes_schedule_transform,.-_vpaes_schedule_transform
576238384Sjkim
577238384Sjkim##
578238384Sjkim##  .aes_schedule_mangle
579238384Sjkim##
580238384Sjkim##  Mangle xmm0 from (basis-transformed) standard version
581238384Sjkim##  to our version.
582238384Sjkim##
583238384Sjkim##  On encrypt,
584238384Sjkim##    xor with 0x63
585238384Sjkim##    multiply by circulant 0,1,1,1
586238384Sjkim##    apply shiftrows transform
587238384Sjkim##
588238384Sjkim##  On decrypt,
589238384Sjkim##    xor with 0x63
590238384Sjkim##    multiply by "inverse mixcolumns" circulant E,B,D,9
591238384Sjkim##    deskew
592238384Sjkim##    apply shiftrows transform
593238384Sjkim##
594238384Sjkim##
595238384Sjkim##  Writes out to (%rdx), and increments or decrements it
596238384Sjkim##  Keeps track of round number mod 4 in %r8
597238384Sjkim##  Preserves xmm0
598238384Sjkim##  Clobbers xmm1-xmm5
599238384Sjkim##
600238384Sjkim.type	_vpaes_schedule_mangle,\@abi-omnipotent
601238384Sjkim.align	16
602238384Sjkim_vpaes_schedule_mangle:
603238384Sjkim	movdqa	%xmm0,	%xmm4	# save xmm0 for later
604238384Sjkim	movdqa	.Lk_mc_forward(%rip),%xmm5
605238384Sjkim	test	%rcx, 	%rcx
606238384Sjkim	jnz	.Lschedule_mangle_dec
607238384Sjkim
608238384Sjkim	# encrypting
609238384Sjkim	add	\$16,	%rdx
610238384Sjkim	pxor	.Lk_s63(%rip),%xmm4
611238384Sjkim	pshufb	%xmm5,	%xmm4
612238384Sjkim	movdqa	%xmm4,	%xmm3
613238384Sjkim	pshufb	%xmm5,	%xmm4
614238384Sjkim	pxor	%xmm4,	%xmm3
615238384Sjkim	pshufb	%xmm5,	%xmm4
616238384Sjkim	pxor	%xmm4,	%xmm3
617238384Sjkim
618238384Sjkim	jmp	.Lschedule_mangle_both
619238384Sjkim.align	16
620238384Sjkim.Lschedule_mangle_dec:
621238384Sjkim	# inverse mix columns
622238384Sjkim	lea	.Lk_dksd(%rip),%r11
623238384Sjkim	movdqa	%xmm9,	%xmm1
624238384Sjkim	pandn	%xmm4,	%xmm1
625238384Sjkim	psrld	\$4,	%xmm1	# 1 = hi
626238384Sjkim	pand	%xmm9,	%xmm4	# 4 = lo
627238384Sjkim
628238384Sjkim	movdqa	0x00(%r11), %xmm2
629238384Sjkim	pshufb	%xmm4,	%xmm2
630238384Sjkim	movdqa	0x10(%r11), %xmm3
631238384Sjkim	pshufb	%xmm1,	%xmm3
632238384Sjkim	pxor	%xmm2,	%xmm3
633238384Sjkim	pshufb	%xmm5,	%xmm3
634238384Sjkim
635238384Sjkim	movdqa	0x20(%r11), %xmm2
636238384Sjkim	pshufb	%xmm4,	%xmm2
637238384Sjkim	pxor	%xmm3,	%xmm2
638238384Sjkim	movdqa	0x30(%r11), %xmm3
639238384Sjkim	pshufb	%xmm1,	%xmm3
640238384Sjkim	pxor	%xmm2,	%xmm3
641238384Sjkim	pshufb	%xmm5,	%xmm3
642238384Sjkim
643238384Sjkim	movdqa	0x40(%r11), %xmm2
644238384Sjkim	pshufb	%xmm4,	%xmm2
645238384Sjkim	pxor	%xmm3,	%xmm2
646238384Sjkim	movdqa	0x50(%r11), %xmm3
647238384Sjkim	pshufb	%xmm1,	%xmm3
648238384Sjkim	pxor	%xmm2,	%xmm3
649238384Sjkim	pshufb	%xmm5,	%xmm3
650238384Sjkim
651238384Sjkim	movdqa	0x60(%r11), %xmm2
652238384Sjkim	pshufb	%xmm4,	%xmm2
653238384Sjkim	pxor	%xmm3,	%xmm2
654238384Sjkim	movdqa	0x70(%r11), %xmm3
655238384Sjkim	pshufb	%xmm1,	%xmm3
656238384Sjkim	pxor	%xmm2,	%xmm3
657238384Sjkim
658238384Sjkim	add	\$-16,	%rdx
659238384Sjkim
660238384Sjkim.Lschedule_mangle_both:
661238384Sjkim	movdqa	(%r8,%r10),%xmm1
662238384Sjkim	pshufb	%xmm1,%xmm3
663238384Sjkim	add	\$-16,	%r8
664238384Sjkim	and	\$0x30,	%r8
665238384Sjkim	movdqu	%xmm3,	(%rdx)
666238384Sjkim	ret
667238384Sjkim.size	_vpaes_schedule_mangle,.-_vpaes_schedule_mangle
668238384Sjkim
669238384Sjkim#
670238384Sjkim# Interface to OpenSSL
671238384Sjkim#
672238384Sjkim.globl	${PREFIX}_set_encrypt_key
673238384Sjkim.type	${PREFIX}_set_encrypt_key,\@function,3
674238384Sjkim.align	16
675238384Sjkim${PREFIX}_set_encrypt_key:
676238384Sjkim___
677238384Sjkim$code.=<<___ if ($win64);
678238384Sjkim	lea	-0xb8(%rsp),%rsp
679238384Sjkim	movaps	%xmm6,0x10(%rsp)
680238384Sjkim	movaps	%xmm7,0x20(%rsp)
681238384Sjkim	movaps	%xmm8,0x30(%rsp)
682238384Sjkim	movaps	%xmm9,0x40(%rsp)
683238384Sjkim	movaps	%xmm10,0x50(%rsp)
684238384Sjkim	movaps	%xmm11,0x60(%rsp)
685238384Sjkim	movaps	%xmm12,0x70(%rsp)
686238384Sjkim	movaps	%xmm13,0x80(%rsp)
687238384Sjkim	movaps	%xmm14,0x90(%rsp)
688238384Sjkim	movaps	%xmm15,0xa0(%rsp)
689238384Sjkim.Lenc_key_body:
690238384Sjkim___
691238384Sjkim$code.=<<___;
692238384Sjkim	mov	%esi,%eax
693238384Sjkim	shr	\$5,%eax
694238384Sjkim	add	\$5,%eax
695238384Sjkim	mov	%eax,240(%rdx)	# AES_KEY->rounds = nbits/32+5;
696238384Sjkim
697238384Sjkim	mov	\$0,%ecx
698238384Sjkim	mov	\$0x30,%r8d
699238384Sjkim	call	_vpaes_schedule_core
700238384Sjkim___
701238384Sjkim$code.=<<___ if ($win64);
702238384Sjkim	movaps	0x10(%rsp),%xmm6
703238384Sjkim	movaps	0x20(%rsp),%xmm7
704238384Sjkim	movaps	0x30(%rsp),%xmm8
705238384Sjkim	movaps	0x40(%rsp),%xmm9
706238384Sjkim	movaps	0x50(%rsp),%xmm10
707238384Sjkim	movaps	0x60(%rsp),%xmm11
708238384Sjkim	movaps	0x70(%rsp),%xmm12
709238384Sjkim	movaps	0x80(%rsp),%xmm13
710238384Sjkim	movaps	0x90(%rsp),%xmm14
711238384Sjkim	movaps	0xa0(%rsp),%xmm15
712238384Sjkim	lea	0xb8(%rsp),%rsp
713238384Sjkim.Lenc_key_epilogue:
714238384Sjkim___
715238384Sjkim$code.=<<___;
716238384Sjkim	xor	%eax,%eax
717238384Sjkim	ret
718238384Sjkim.size	${PREFIX}_set_encrypt_key,.-${PREFIX}_set_encrypt_key
719238384Sjkim
720238384Sjkim.globl	${PREFIX}_set_decrypt_key
721238384Sjkim.type	${PREFIX}_set_decrypt_key,\@function,3
722238384Sjkim.align	16
723238384Sjkim${PREFIX}_set_decrypt_key:
724238384Sjkim___
725238384Sjkim$code.=<<___ if ($win64);
726238384Sjkim	lea	-0xb8(%rsp),%rsp
727238384Sjkim	movaps	%xmm6,0x10(%rsp)
728238384Sjkim	movaps	%xmm7,0x20(%rsp)
729238384Sjkim	movaps	%xmm8,0x30(%rsp)
730238384Sjkim	movaps	%xmm9,0x40(%rsp)
731238384Sjkim	movaps	%xmm10,0x50(%rsp)
732238384Sjkim	movaps	%xmm11,0x60(%rsp)
733238384Sjkim	movaps	%xmm12,0x70(%rsp)
734238384Sjkim	movaps	%xmm13,0x80(%rsp)
735238384Sjkim	movaps	%xmm14,0x90(%rsp)
736238384Sjkim	movaps	%xmm15,0xa0(%rsp)
737238384Sjkim.Ldec_key_body:
738238384Sjkim___
739238384Sjkim$code.=<<___;
740238384Sjkim	mov	%esi,%eax
741238384Sjkim	shr	\$5,%eax
742238384Sjkim	add	\$5,%eax
743238384Sjkim	mov	%eax,240(%rdx)	# AES_KEY->rounds = nbits/32+5;
744238384Sjkim	shl	\$4,%eax
745238384Sjkim	lea	16(%rdx,%rax),%rdx
746238384Sjkim
747238384Sjkim	mov	\$1,%ecx
748238384Sjkim	mov	%esi,%r8d
749238384Sjkim	shr	\$1,%r8d
750238384Sjkim	and	\$32,%r8d
751238384Sjkim	xor	\$32,%r8d	# nbits==192?0:32
752238384Sjkim	call	_vpaes_schedule_core
753238384Sjkim___
754238384Sjkim$code.=<<___ if ($win64);
755238384Sjkim	movaps	0x10(%rsp),%xmm6
756238384Sjkim	movaps	0x20(%rsp),%xmm7
757238384Sjkim	movaps	0x30(%rsp),%xmm8
758238384Sjkim	movaps	0x40(%rsp),%xmm9
759238384Sjkim	movaps	0x50(%rsp),%xmm10
760238384Sjkim	movaps	0x60(%rsp),%xmm11
761238384Sjkim	movaps	0x70(%rsp),%xmm12
762238384Sjkim	movaps	0x80(%rsp),%xmm13
763238384Sjkim	movaps	0x90(%rsp),%xmm14
764238384Sjkim	movaps	0xa0(%rsp),%xmm15
765238384Sjkim	lea	0xb8(%rsp),%rsp
766238384Sjkim.Ldec_key_epilogue:
767238384Sjkim___
768238384Sjkim$code.=<<___;
769238384Sjkim	xor	%eax,%eax
770238384Sjkim	ret
771238384Sjkim.size	${PREFIX}_set_decrypt_key,.-${PREFIX}_set_decrypt_key
772238384Sjkim
773238384Sjkim.globl	${PREFIX}_encrypt
774238384Sjkim.type	${PREFIX}_encrypt,\@function,3
775238384Sjkim.align	16
776238384Sjkim${PREFIX}_encrypt:
777238384Sjkim___
778238384Sjkim$code.=<<___ if ($win64);
779238384Sjkim	lea	-0xb8(%rsp),%rsp
780238384Sjkim	movaps	%xmm6,0x10(%rsp)
781238384Sjkim	movaps	%xmm7,0x20(%rsp)
782238384Sjkim	movaps	%xmm8,0x30(%rsp)
783238384Sjkim	movaps	%xmm9,0x40(%rsp)
784238384Sjkim	movaps	%xmm10,0x50(%rsp)
785238384Sjkim	movaps	%xmm11,0x60(%rsp)
786238384Sjkim	movaps	%xmm12,0x70(%rsp)
787238384Sjkim	movaps	%xmm13,0x80(%rsp)
788238384Sjkim	movaps	%xmm14,0x90(%rsp)
789238384Sjkim	movaps	%xmm15,0xa0(%rsp)
790238384Sjkim.Lenc_body:
791238384Sjkim___
792238384Sjkim$code.=<<___;
793238384Sjkim	movdqu	(%rdi),%xmm0
794238384Sjkim	call	_vpaes_preheat
795238384Sjkim	call	_vpaes_encrypt_core
796238384Sjkim	movdqu	%xmm0,(%rsi)
797238384Sjkim___
798238384Sjkim$code.=<<___ if ($win64);
799238384Sjkim	movaps	0x10(%rsp),%xmm6
800238384Sjkim	movaps	0x20(%rsp),%xmm7
801238384Sjkim	movaps	0x30(%rsp),%xmm8
802238384Sjkim	movaps	0x40(%rsp),%xmm9
803238384Sjkim	movaps	0x50(%rsp),%xmm10
804238384Sjkim	movaps	0x60(%rsp),%xmm11
805238384Sjkim	movaps	0x70(%rsp),%xmm12
806238384Sjkim	movaps	0x80(%rsp),%xmm13
807238384Sjkim	movaps	0x90(%rsp),%xmm14
808238384Sjkim	movaps	0xa0(%rsp),%xmm15
809238384Sjkim	lea	0xb8(%rsp),%rsp
810238384Sjkim.Lenc_epilogue:
811238384Sjkim___
812238384Sjkim$code.=<<___;
813238384Sjkim	ret
814238384Sjkim.size	${PREFIX}_encrypt,.-${PREFIX}_encrypt
815238384Sjkim
816238384Sjkim.globl	${PREFIX}_decrypt
817238384Sjkim.type	${PREFIX}_decrypt,\@function,3
818238384Sjkim.align	16
819238384Sjkim${PREFIX}_decrypt:
820238384Sjkim___
821238384Sjkim$code.=<<___ if ($win64);
822238384Sjkim	lea	-0xb8(%rsp),%rsp
823238384Sjkim	movaps	%xmm6,0x10(%rsp)
824238384Sjkim	movaps	%xmm7,0x20(%rsp)
825238384Sjkim	movaps	%xmm8,0x30(%rsp)
826238384Sjkim	movaps	%xmm9,0x40(%rsp)
827238384Sjkim	movaps	%xmm10,0x50(%rsp)
828238384Sjkim	movaps	%xmm11,0x60(%rsp)
829238384Sjkim	movaps	%xmm12,0x70(%rsp)
830238384Sjkim	movaps	%xmm13,0x80(%rsp)
831238384Sjkim	movaps	%xmm14,0x90(%rsp)
832238384Sjkim	movaps	%xmm15,0xa0(%rsp)
833238384Sjkim.Ldec_body:
834238384Sjkim___
835238384Sjkim$code.=<<___;
836238384Sjkim	movdqu	(%rdi),%xmm0
837238384Sjkim	call	_vpaes_preheat
838238384Sjkim	call	_vpaes_decrypt_core
839238384Sjkim	movdqu	%xmm0,(%rsi)
840238384Sjkim___
841238384Sjkim$code.=<<___ if ($win64);
842238384Sjkim	movaps	0x10(%rsp),%xmm6
843238384Sjkim	movaps	0x20(%rsp),%xmm7
844238384Sjkim	movaps	0x30(%rsp),%xmm8
845238384Sjkim	movaps	0x40(%rsp),%xmm9
846238384Sjkim	movaps	0x50(%rsp),%xmm10
847238384Sjkim	movaps	0x60(%rsp),%xmm11
848238384Sjkim	movaps	0x70(%rsp),%xmm12
849238384Sjkim	movaps	0x80(%rsp),%xmm13
850238384Sjkim	movaps	0x90(%rsp),%xmm14
851238384Sjkim	movaps	0xa0(%rsp),%xmm15
852238384Sjkim	lea	0xb8(%rsp),%rsp
853238384Sjkim.Ldec_epilogue:
854238384Sjkim___
855238384Sjkim$code.=<<___;
856238384Sjkim	ret
857238384Sjkim.size	${PREFIX}_decrypt,.-${PREFIX}_decrypt
858238384Sjkim___
859238384Sjkim{
860238384Sjkimmy ($inp,$out,$len,$key,$ivp,$enc)=("%rdi","%rsi","%rdx","%rcx","%r8","%r9");
861238384Sjkim# void AES_cbc_encrypt (const void char *inp, unsigned char *out,
862238384Sjkim#                       size_t length, const AES_KEY *key,
863238384Sjkim#                       unsigned char *ivp,const int enc);
864238384Sjkim$code.=<<___;
865238384Sjkim.globl	${PREFIX}_cbc_encrypt
866238384Sjkim.type	${PREFIX}_cbc_encrypt,\@function,6
867238384Sjkim.align	16
868238384Sjkim${PREFIX}_cbc_encrypt:
869238384Sjkim	xchg	$key,$len
870238384Sjkim___
871238384Sjkim($len,$key)=($key,$len);
872238384Sjkim$code.=<<___;
873238384Sjkim	sub	\$16,$len
874238384Sjkim	jc	.Lcbc_abort
875238384Sjkim___
876238384Sjkim$code.=<<___ if ($win64);
877238384Sjkim	lea	-0xb8(%rsp),%rsp
878238384Sjkim	movaps	%xmm6,0x10(%rsp)
879238384Sjkim	movaps	%xmm7,0x20(%rsp)
880238384Sjkim	movaps	%xmm8,0x30(%rsp)
881238384Sjkim	movaps	%xmm9,0x40(%rsp)
882238384Sjkim	movaps	%xmm10,0x50(%rsp)
883238384Sjkim	movaps	%xmm11,0x60(%rsp)
884238384Sjkim	movaps	%xmm12,0x70(%rsp)
885238384Sjkim	movaps	%xmm13,0x80(%rsp)
886238384Sjkim	movaps	%xmm14,0x90(%rsp)
887238384Sjkim	movaps	%xmm15,0xa0(%rsp)
888238384Sjkim.Lcbc_body:
889238384Sjkim___
890238384Sjkim$code.=<<___;
891238384Sjkim	movdqu	($ivp),%xmm6		# load IV
892238384Sjkim	sub	$inp,$out
893238384Sjkim	call	_vpaes_preheat
894238384Sjkim	cmp	\$0,${enc}d
895238384Sjkim	je	.Lcbc_dec_loop
896238384Sjkim	jmp	.Lcbc_enc_loop
897238384Sjkim.align	16
898238384Sjkim.Lcbc_enc_loop:
899238384Sjkim	movdqu	($inp),%xmm0
900238384Sjkim	pxor	%xmm6,%xmm0
901238384Sjkim	call	_vpaes_encrypt_core
902238384Sjkim	movdqa	%xmm0,%xmm6
903238384Sjkim	movdqu	%xmm0,($out,$inp)
904238384Sjkim	lea	16($inp),$inp
905238384Sjkim	sub	\$16,$len
906238384Sjkim	jnc	.Lcbc_enc_loop
907238384Sjkim	jmp	.Lcbc_done
908238384Sjkim.align	16
909238384Sjkim.Lcbc_dec_loop:
910238384Sjkim	movdqu	($inp),%xmm0
911238384Sjkim	movdqa	%xmm0,%xmm7
912238384Sjkim	call	_vpaes_decrypt_core
913238384Sjkim	pxor	%xmm6,%xmm0
914238384Sjkim	movdqa	%xmm7,%xmm6
915238384Sjkim	movdqu	%xmm0,($out,$inp)
916238384Sjkim	lea	16($inp),$inp
917238384Sjkim	sub	\$16,$len
918238384Sjkim	jnc	.Lcbc_dec_loop
919238384Sjkim.Lcbc_done:
920238384Sjkim	movdqu	%xmm6,($ivp)		# save IV
921238384Sjkim___
922238384Sjkim$code.=<<___ if ($win64);
923238384Sjkim	movaps	0x10(%rsp),%xmm6
924238384Sjkim	movaps	0x20(%rsp),%xmm7
925238384Sjkim	movaps	0x30(%rsp),%xmm8
926238384Sjkim	movaps	0x40(%rsp),%xmm9
927238384Sjkim	movaps	0x50(%rsp),%xmm10
928238384Sjkim	movaps	0x60(%rsp),%xmm11
929238384Sjkim	movaps	0x70(%rsp),%xmm12
930238384Sjkim	movaps	0x80(%rsp),%xmm13
931238384Sjkim	movaps	0x90(%rsp),%xmm14
932238384Sjkim	movaps	0xa0(%rsp),%xmm15
933238384Sjkim	lea	0xb8(%rsp),%rsp
934238384Sjkim.Lcbc_epilogue:
935238384Sjkim___
936238384Sjkim$code.=<<___;
937238384Sjkim.Lcbc_abort:
938238384Sjkim	ret
939238384Sjkim.size	${PREFIX}_cbc_encrypt,.-${PREFIX}_cbc_encrypt
940238384Sjkim___
941238384Sjkim}
942238384Sjkim$code.=<<___;
943238384Sjkim##
944238384Sjkim##  _aes_preheat
945238384Sjkim##
946238384Sjkim##  Fills register %r10 -> .aes_consts (so you can -fPIC)
947238384Sjkim##  and %xmm9-%xmm15 as specified below.
948238384Sjkim##
949238384Sjkim.type	_vpaes_preheat,\@abi-omnipotent
950238384Sjkim.align	16
951238384Sjkim_vpaes_preheat:
952238384Sjkim	lea	.Lk_s0F(%rip), %r10
953238384Sjkim	movdqa	-0x20(%r10), %xmm10	# .Lk_inv
954238384Sjkim	movdqa	-0x10(%r10), %xmm11	# .Lk_inv+16
955238384Sjkim	movdqa	0x00(%r10), %xmm9	# .Lk_s0F
956238384Sjkim	movdqa	0x30(%r10), %xmm13	# .Lk_sb1
957238384Sjkim	movdqa	0x40(%r10), %xmm12	# .Lk_sb1+16
958238384Sjkim	movdqa	0x50(%r10), %xmm15	# .Lk_sb2
959238384Sjkim	movdqa	0x60(%r10), %xmm14	# .Lk_sb2+16
960238384Sjkim	ret
961238384Sjkim.size	_vpaes_preheat,.-_vpaes_preheat
962238384Sjkim########################################################
963238384Sjkim##                                                    ##
964238384Sjkim##                     Constants                      ##
965238384Sjkim##                                                    ##
966238384Sjkim########################################################
967238384Sjkim.type	_vpaes_consts,\@object
968238384Sjkim.align	64
969238384Sjkim_vpaes_consts:
970238384Sjkim.Lk_inv:	# inv, inva
971238384Sjkim	.quad	0x0E05060F0D080180, 0x040703090A0B0C02
972238384Sjkim	.quad	0x01040A060F0B0780, 0x030D0E0C02050809
973238384Sjkim
974238384Sjkim.Lk_s0F:	# s0F
975238384Sjkim	.quad	0x0F0F0F0F0F0F0F0F, 0x0F0F0F0F0F0F0F0F
976238384Sjkim
977238384Sjkim.Lk_ipt:	# input transform (lo, hi)
978238384Sjkim	.quad	0xC2B2E8985A2A7000, 0xCABAE09052227808
979238384Sjkim	.quad	0x4C01307D317C4D00, 0xCD80B1FCB0FDCC81
980238384Sjkim
981238384Sjkim.Lk_sb1:	# sb1u, sb1t
982238384Sjkim	.quad	0xB19BE18FCB503E00, 0xA5DF7A6E142AF544
983238384Sjkim	.quad	0x3618D415FAE22300, 0x3BF7CCC10D2ED9EF
984238384Sjkim.Lk_sb2:	# sb2u, sb2t
985238384Sjkim	.quad	0xE27A93C60B712400, 0x5EB7E955BC982FCD
986238384Sjkim	.quad	0x69EB88400AE12900, 0xC2A163C8AB82234A
987238384Sjkim.Lk_sbo:	# sbou, sbot
988238384Sjkim	.quad	0xD0D26D176FBDC700, 0x15AABF7AC502A878
989238384Sjkim	.quad	0xCFE474A55FBB6A00, 0x8E1E90D1412B35FA
990238384Sjkim
991238384Sjkim.Lk_mc_forward:	# mc_forward
992238384Sjkim	.quad	0x0407060500030201, 0x0C0F0E0D080B0A09
993238384Sjkim	.quad	0x080B0A0904070605, 0x000302010C0F0E0D
994238384Sjkim	.quad	0x0C0F0E0D080B0A09, 0x0407060500030201
995238384Sjkim	.quad	0x000302010C0F0E0D, 0x080B0A0904070605
996238384Sjkim
997238384Sjkim.Lk_mc_backward:# mc_backward
998238384Sjkim	.quad	0x0605040702010003, 0x0E0D0C0F0A09080B
999238384Sjkim	.quad	0x020100030E0D0C0F, 0x0A09080B06050407
1000238384Sjkim	.quad	0x0E0D0C0F0A09080B, 0x0605040702010003
1001238384Sjkim	.quad	0x0A09080B06050407, 0x020100030E0D0C0F
1002238384Sjkim
1003238384Sjkim.Lk_sr:		# sr
1004238384Sjkim	.quad	0x0706050403020100, 0x0F0E0D0C0B0A0908
1005238384Sjkim	.quad	0x030E09040F0A0500, 0x0B06010C07020D08
1006238384Sjkim	.quad	0x0F060D040B020900, 0x070E050C030A0108
1007238384Sjkim	.quad	0x0B0E0104070A0D00, 0x0306090C0F020508
1008238384Sjkim
1009238384Sjkim.Lk_rcon:	# rcon
1010238384Sjkim	.quad	0x1F8391B9AF9DEEB6, 0x702A98084D7C7D81
1011238384Sjkim
1012238384Sjkim.Lk_s63:	# s63: all equal to 0x63 transformed
1013238384Sjkim	.quad	0x5B5B5B5B5B5B5B5B, 0x5B5B5B5B5B5B5B5B
1014238384Sjkim
1015238384Sjkim.Lk_opt:	# output transform
1016238384Sjkim	.quad	0xFF9F4929D6B66000, 0xF7974121DEBE6808
1017238384Sjkim	.quad	0x01EDBD5150BCEC00, 0xE10D5DB1B05C0CE0
1018238384Sjkim
1019238384Sjkim.Lk_deskew:	# deskew tables: inverts the sbox's "skew"
1020238384Sjkim	.quad	0x07E4A34047A4E300, 0x1DFEB95A5DBEF91A
1021238384Sjkim	.quad	0x5F36B5DC83EA6900, 0x2841C2ABF49D1E77
1022238384Sjkim
1023238384Sjkim##
1024238384Sjkim##  Decryption stuff
1025238384Sjkim##  Key schedule constants
1026238384Sjkim##
1027238384Sjkim.Lk_dksd:	# decryption key schedule: invskew x*D
1028238384Sjkim	.quad	0xFEB91A5DA3E44700, 0x0740E3A45A1DBEF9
1029238384Sjkim	.quad	0x41C277F4B5368300, 0x5FDC69EAAB289D1E
1030238384Sjkim.Lk_dksb:	# decryption key schedule: invskew x*B
1031238384Sjkim	.quad	0x9A4FCA1F8550D500, 0x03D653861CC94C99
1032238384Sjkim	.quad	0x115BEDA7B6FC4A00, 0xD993256F7E3482C8
1033238384Sjkim.Lk_dkse:	# decryption key schedule: invskew x*E + 0x63
1034238384Sjkim	.quad	0xD5031CCA1FC9D600, 0x53859A4C994F5086
1035238384Sjkim	.quad	0xA23196054FDC7BE8, 0xCD5EF96A20B31487
1036238384Sjkim.Lk_dks9:	# decryption key schedule: invskew x*9
1037238384Sjkim	.quad	0xB6116FC87ED9A700, 0x4AED933482255BFC
1038238384Sjkim	.quad	0x4576516227143300, 0x8BB89FACE9DAFDCE
1039238384Sjkim
1040238384Sjkim##
1041238384Sjkim##  Decryption stuff
1042238384Sjkim##  Round function constants
1043238384Sjkim##
1044238384Sjkim.Lk_dipt:	# decryption input transform
1045238384Sjkim	.quad	0x0F505B040B545F00, 0x154A411E114E451A
1046238384Sjkim	.quad	0x86E383E660056500, 0x12771772F491F194
1047238384Sjkim
1048238384Sjkim.Lk_dsb9:	# decryption sbox output *9*u, *9*t
1049238384Sjkim	.quad	0x851C03539A86D600, 0xCAD51F504F994CC9
1050238384Sjkim	.quad	0xC03B1789ECD74900, 0x725E2C9EB2FBA565
1051238384Sjkim.Lk_dsbd:	# decryption sbox output *D*u, *D*t
1052238384Sjkim	.quad	0x7D57CCDFE6B1A200, 0xF56E9B13882A4439
1053238384Sjkim	.quad	0x3CE2FAF724C6CB00, 0x2931180D15DEEFD3
1054238384Sjkim.Lk_dsbb:	# decryption sbox output *B*u, *B*t
1055238384Sjkim	.quad	0xD022649296B44200, 0x602646F6B0F2D404
1056238384Sjkim	.quad	0xC19498A6CD596700, 0xF3FF0C3E3255AA6B
1057238384Sjkim.Lk_dsbe:	# decryption sbox output *E*u, *E*t
1058238384Sjkim	.quad	0x46F2929626D4D000, 0x2242600464B4F6B0
1059238384Sjkim	.quad	0x0C55A6CDFFAAC100, 0x9467F36B98593E32
1060238384Sjkim.Lk_dsbo:	# decryption sbox final output
1061238384Sjkim	.quad	0x1387EA537EF94000, 0xC7AA6DB9D4943E2D
1062238384Sjkim	.quad	0x12D7560F93441D00, 0xCA4B8159D8C58E9C
1063264331Sjkim.asciz	"Vector Permutation AES for x86_64/SSSE3, Mike Hamburg (Stanford University)"
1064238384Sjkim.align	64
1065238384Sjkim.size	_vpaes_consts,.-_vpaes_consts
1066238384Sjkim___
1067238384Sjkim
1068238384Sjkimif ($win64) {
1069238384Sjkim# EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame,
1070238384Sjkim#		CONTEXT *context,DISPATCHER_CONTEXT *disp)
1071238384Sjkim$rec="%rcx";
1072238384Sjkim$frame="%rdx";
1073238384Sjkim$context="%r8";
1074238384Sjkim$disp="%r9";
1075238384Sjkim
1076238384Sjkim$code.=<<___;
1077238384Sjkim.extern	__imp_RtlVirtualUnwind
1078238384Sjkim.type	se_handler,\@abi-omnipotent
1079238384Sjkim.align	16
1080238384Sjkimse_handler:
1081238384Sjkim	push	%rsi
1082238384Sjkim	push	%rdi
1083238384Sjkim	push	%rbx
1084238384Sjkim	push	%rbp
1085238384Sjkim	push	%r12
1086238384Sjkim	push	%r13
1087238384Sjkim	push	%r14
1088238384Sjkim	push	%r15
1089238384Sjkim	pushfq
1090238384Sjkim	sub	\$64,%rsp
1091238384Sjkim
1092238384Sjkim	mov	120($context),%rax	# pull context->Rax
1093238384Sjkim	mov	248($context),%rbx	# pull context->Rip
1094238384Sjkim
1095238384Sjkim	mov	8($disp),%rsi		# disp->ImageBase
1096238384Sjkim	mov	56($disp),%r11		# disp->HandlerData
1097238384Sjkim
1098238384Sjkim	mov	0(%r11),%r10d		# HandlerData[0]
1099238384Sjkim	lea	(%rsi,%r10),%r10	# prologue label
1100238384Sjkim	cmp	%r10,%rbx		# context->Rip<prologue label
1101238384Sjkim	jb	.Lin_prologue
1102238384Sjkim
1103238384Sjkim	mov	152($context),%rax	# pull context->Rsp
1104238384Sjkim
1105238384Sjkim	mov	4(%r11),%r10d		# HandlerData[1]
1106238384Sjkim	lea	(%rsi,%r10),%r10	# epilogue label
1107238384Sjkim	cmp	%r10,%rbx		# context->Rip>=epilogue label
1108238384Sjkim	jae	.Lin_prologue
1109238384Sjkim
1110238384Sjkim	lea	16(%rax),%rsi		# %xmm save area
1111238384Sjkim	lea	512($context),%rdi	# &context.Xmm6
1112238384Sjkim	mov	\$20,%ecx		# 10*sizeof(%xmm0)/sizeof(%rax)
1113238384Sjkim	.long	0xa548f3fc		# cld; rep movsq
1114238384Sjkim	lea	0xb8(%rax),%rax		# adjust stack pointer
1115238384Sjkim
1116238384Sjkim.Lin_prologue:
1117238384Sjkim	mov	8(%rax),%rdi
1118238384Sjkim	mov	16(%rax),%rsi
1119238384Sjkim	mov	%rax,152($context)	# restore context->Rsp
1120238384Sjkim	mov	%rsi,168($context)	# restore context->Rsi
1121238384Sjkim	mov	%rdi,176($context)	# restore context->Rdi
1122238384Sjkim
1123238384Sjkim	mov	40($disp),%rdi		# disp->ContextRecord
1124238384Sjkim	mov	$context,%rsi		# context
1125238384Sjkim	mov	\$`1232/8`,%ecx		# sizeof(CONTEXT)
1126238384Sjkim	.long	0xa548f3fc		# cld; rep movsq
1127238384Sjkim
1128238384Sjkim	mov	$disp,%rsi
1129238384Sjkim	xor	%rcx,%rcx		# arg1, UNW_FLAG_NHANDLER
1130238384Sjkim	mov	8(%rsi),%rdx		# arg2, disp->ImageBase
1131238384Sjkim	mov	0(%rsi),%r8		# arg3, disp->ControlPc
1132238384Sjkim	mov	16(%rsi),%r9		# arg4, disp->FunctionEntry
1133238384Sjkim	mov	40(%rsi),%r10		# disp->ContextRecord
1134238384Sjkim	lea	56(%rsi),%r11		# &disp->HandlerData
1135238384Sjkim	lea	24(%rsi),%r12		# &disp->EstablisherFrame
1136238384Sjkim	mov	%r10,32(%rsp)		# arg5
1137238384Sjkim	mov	%r11,40(%rsp)		# arg6
1138238384Sjkim	mov	%r12,48(%rsp)		# arg7
1139238384Sjkim	mov	%rcx,56(%rsp)		# arg8, (NULL)
1140238384Sjkim	call	*__imp_RtlVirtualUnwind(%rip)
1141238384Sjkim
1142238384Sjkim	mov	\$1,%eax		# ExceptionContinueSearch
1143238384Sjkim	add	\$64,%rsp
1144238384Sjkim	popfq
1145238384Sjkim	pop	%r15
1146238384Sjkim	pop	%r14
1147238384Sjkim	pop	%r13
1148238384Sjkim	pop	%r12
1149238384Sjkim	pop	%rbp
1150238384Sjkim	pop	%rbx
1151238384Sjkim	pop	%rdi
1152238384Sjkim	pop	%rsi
1153238384Sjkim	ret
1154238384Sjkim.size	se_handler,.-se_handler
1155238384Sjkim
1156238384Sjkim.section	.pdata
1157238384Sjkim.align	4
1158238384Sjkim	.rva	.LSEH_begin_${PREFIX}_set_encrypt_key
1159238384Sjkim	.rva	.LSEH_end_${PREFIX}_set_encrypt_key
1160238384Sjkim	.rva	.LSEH_info_${PREFIX}_set_encrypt_key
1161238384Sjkim
1162238384Sjkim	.rva	.LSEH_begin_${PREFIX}_set_decrypt_key
1163238384Sjkim	.rva	.LSEH_end_${PREFIX}_set_decrypt_key
1164238384Sjkim	.rva	.LSEH_info_${PREFIX}_set_decrypt_key
1165238384Sjkim
1166238384Sjkim	.rva	.LSEH_begin_${PREFIX}_encrypt
1167238384Sjkim	.rva	.LSEH_end_${PREFIX}_encrypt
1168238384Sjkim	.rva	.LSEH_info_${PREFIX}_encrypt
1169238384Sjkim
1170238384Sjkim	.rva	.LSEH_begin_${PREFIX}_decrypt
1171238384Sjkim	.rva	.LSEH_end_${PREFIX}_decrypt
1172238384Sjkim	.rva	.LSEH_info_${PREFIX}_decrypt
1173238384Sjkim
1174238384Sjkim	.rva	.LSEH_begin_${PREFIX}_cbc_encrypt
1175238384Sjkim	.rva	.LSEH_end_${PREFIX}_cbc_encrypt
1176238384Sjkim	.rva	.LSEH_info_${PREFIX}_cbc_encrypt
1177238384Sjkim
1178238384Sjkim.section	.xdata
1179238384Sjkim.align	8
1180238384Sjkim.LSEH_info_${PREFIX}_set_encrypt_key:
1181238384Sjkim	.byte	9,0,0,0
1182238384Sjkim	.rva	se_handler
1183238384Sjkim	.rva	.Lenc_key_body,.Lenc_key_epilogue	# HandlerData[]
1184238384Sjkim.LSEH_info_${PREFIX}_set_decrypt_key:
1185238384Sjkim	.byte	9,0,0,0
1186238384Sjkim	.rva	se_handler
1187238384Sjkim	.rva	.Ldec_key_body,.Ldec_key_epilogue	# HandlerData[]
1188238384Sjkim.LSEH_info_${PREFIX}_encrypt:
1189238384Sjkim	.byte	9,0,0,0
1190238384Sjkim	.rva	se_handler
1191238384Sjkim	.rva	.Lenc_body,.Lenc_epilogue		# HandlerData[]
1192238384Sjkim.LSEH_info_${PREFIX}_decrypt:
1193238384Sjkim	.byte	9,0,0,0
1194238384Sjkim	.rva	se_handler
1195238384Sjkim	.rva	.Ldec_body,.Ldec_epilogue		# HandlerData[]
1196238384Sjkim.LSEH_info_${PREFIX}_cbc_encrypt:
1197238384Sjkim	.byte	9,0,0,0
1198238384Sjkim	.rva	se_handler
1199238384Sjkim	.rva	.Lcbc_body,.Lcbc_epilogue		# HandlerData[]
1200238384Sjkim___
1201238384Sjkim}
1202238384Sjkim
1203238384Sjkim$code =~ s/\`([^\`]*)\`/eval($1)/gem;
1204238384Sjkim
1205238384Sjkimprint $code;
1206238384Sjkim
1207238384Sjkimclose STDOUT;
1208