1 // panama.cpp - originally written and placed in the public domain by Wei Dai
2 
3 // use "cl /EP /P /DCRYPTOPP_GENERATE_X64_MASM panama.cpp" to generate MASM code
4 
5 #include "pch.h"
6 
7 #ifndef CRYPTOPP_GENERATE_X64_MASM
8 
9 #include "panama.h"
10 #include "secblock.h"
11 #include "misc.h"
12 #include "cpu.h"
13 
NAMESPACE_BEGIN(CryptoPP)14 NAMESPACE_BEGIN(CryptoPP)
15 
16 #if CRYPTOPP_MSC_VERSION
17 # pragma warning(disable: 4731)
18 #endif
19 
20 template <class B>
21 std::string Panama<B>::AlgorithmProvider() const
22 {
23 #ifndef CRYPTOPP_DISABLE_PANAMA_ASM
24 # if CRYPTOPP_SSSE3_ASM_AVAILABLE
25 	if(HasSSSE3())
26 		return "SSSE3";
27 # elif CRYPTOPP_SSE2_ASM_AVAILABLE
28 	if(HasSSE2())
29 		return "SSE2";
30 # endif
31 #endif
32 	return "C++";
33 }
34 
35 template <class B>
Reset()36 void Panama<B>::Reset()
37 {
38 	memset(m_state, 0, m_state.SizeInBytes());
39 #if CRYPTOPP_SSSE3_ASM_AVAILABLE && !defined(CRYPTOPP_DISABLE_PANAMA_ASM)
40 	m_state[17] = HasSSSE3();
41 #endif
42 }
43 
44 #endif	// #ifndef CRYPTOPP_GENERATE_X64_MASM
45 
46 #ifdef CRYPTOPP_X64_MASM_AVAILABLE
47 extern "C" {
48 void Panama_SSE2_Pull(size_t count, word32 *state, word32 *z, const word32 *y);
49 }
50 #elif CRYPTOPP_SSE2_ASM_AVAILABLE && !defined(CRYPTOPP_DISABLE_PANAMA_ASM)
51 
52 #ifdef CRYPTOPP_GENERATE_X64_MASM
53 	Panama_SSE2_Pull	PROC FRAME
54 	rex_push_reg rdi
55 	alloc_stack(2*16)
56 	save_xmm128 xmm6, 0h
57 	save_xmm128 xmm7, 10h
58 	.endprolog
59 #else
60 void CRYPTOPP_NOINLINE Panama_SSE2_Pull(size_t count, word32 *state, word32 *z, const word32 *y)
61 {
62 #if defined(CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY)
63 	asm __volatile__
64 	(
65 	INTEL_NOPREFIX
66 	AS_PUSH_IF86(	bx)
67 #else
68 	AS2(	mov		AS_REG_1, count)
69 	AS2(	mov		AS_REG_2, state)
70 	AS2(	mov		AS_REG_3, z)
71 	AS2(	mov		AS_REG_4, y)
72 #endif
73 #endif	// #ifdef CRYPTOPP_GENERATE_X64_MASM
74 
75 #if CRYPTOPP_BOOL_X86
76 	#define REG_loopEnd			[esp]
77 #elif defined(CRYPTOPP_GENERATE_X64_MASM)
78 	#define REG_loopEnd			rdi
79 #else
80 	#define REG_loopEnd			r8
81 #endif
82 
83 	AS2(	shl		AS_REG_1, 5)
84 	ASJ(	jz,		5, f)
85 	AS2(	mov		AS_REG_6d, [AS_REG_2+4*17])
86 	AS2(	add		AS_REG_1, AS_REG_6)
87 
88 	#if CRYPTOPP_BOOL_X64
89 		AS2(	mov		REG_loopEnd, AS_REG_1)
90 	#else
91 		AS_PUSH_IF86(	bp)
92 		AS1(	push	AS_REG_1)
93 	#endif
94 
95 	AS2(	movdqa	xmm0, XMMWORD_PTR [AS_REG_2+0*16])
96 	AS2(	movdqa	xmm1, XMMWORD_PTR [AS_REG_2+1*16])
97 	AS2(	movdqa	xmm2, XMMWORD_PTR [AS_REG_2+2*16])
98 	AS2(	movdqa	xmm3, XMMWORD_PTR [AS_REG_2+3*16])
99 	AS2(	mov		eax, dword ptr [AS_REG_2+4*16])
100 
101 	ASL(4)
102 	// gamma and pi
103 #if CRYPTOPP_SSSE3_ASM_AVAILABLE
104 	AS2(	test	AS_REG_6, 1)
105 	ASJ(	jnz,	6, f)
106 #endif
107 	AS2(	movdqa	xmm6, xmm2)
108 	AS2(	movss	xmm6, xmm3)
109 	ASS(	pshufd	xmm5, xmm6, 0, 3, 2, 1)
110 	AS2(	movd	xmm6, eax)
111 	AS2(	movdqa	xmm7, xmm3)
112 	AS2(	movss	xmm7, xmm6)
113 	ASS(	pshufd	xmm6, xmm7, 0, 3, 2, 1)
114 #if CRYPTOPP_SSSE3_ASM_AVAILABLE
115 	ASJ(	jmp,	7, f)
116 	ASL(6)
117 	AS2(	movdqa	xmm5, xmm3)
118 	AS3(	palignr	xmm5, xmm2, 4)
119 	AS2(	movd	xmm6, eax)
120 	AS3(	palignr	xmm6, xmm3, 4)
121 	ASL(7)
122 #endif
123 
124 	AS2(	movd	AS_REG_1d, xmm2)
125 	AS1(	not		AS_REG_1d)
126 	AS2(	movd	AS_REG_7d, xmm3)
127 	AS2(	or		AS_REG_1d, AS_REG_7d)
128 	AS2(	xor		eax, AS_REG_1d)
129 
130 #define SSE2_Index(i) ASM_MOD(((i)*13+16), 17)
131 
132 #define pi(i)	\
133 	AS2(	movd	AS_REG_1d, xmm7)\
134 	AS2(	rol		AS_REG_1d, ASM_MOD((ASM_MOD(5*i,17)*(ASM_MOD(5*i,17)+1)/2), 32))\
135 	AS2(	mov		[AS_REG_2+SSE2_Index(ASM_MOD(5*(i), 17))*4], AS_REG_1d)
136 
137 #define pi4(x, y, z, a, b, c, d)	\
138 	AS2(	pcmpeqb	xmm7, xmm7)\
139 	AS2(	pxor	xmm7, x)\
140 	AS2(	por		xmm7, y)\
141 	AS2(	pxor	xmm7, z)\
142 	pi(a)\
143 	ASS(	pshuflw	xmm7, xmm7, 1, 0, 3, 2)\
144 	pi(b)\
145 	AS2(	punpckhqdq	xmm7, xmm7)\
146 	pi(c)\
147 	ASS(	pshuflw	xmm7, xmm7, 1, 0, 3, 2)\
148 	pi(d)
149 
150 	pi4(xmm1, xmm2, xmm3, 1, 5, 9, 13)
151 	pi4(xmm0, xmm1, xmm2, 2, 6, 10, 14)
152 	pi4(xmm6, xmm0, xmm1, 3, 7, 11, 15)
153 	pi4(xmm5, xmm6, xmm0, 4, 8, 12, 16)
154 
155 	// output keystream and update buffer here to hide partial memory stalls between pi and theta
156 	AS2(	movdqa	xmm4, xmm3)
157 	AS2(	punpcklqdq	xmm3, xmm2)		// 1 5 2 6
158 	AS2(	punpckhdq	xmm4, xmm2)		// 9 10 13 14
159 	AS2(	movdqa	xmm2, xmm1)
160 	AS2(	punpcklqdq	xmm1, xmm0)		// 3 7 4 8
161 	AS2(	punpckhdq	xmm2, xmm0)		// 11 12 15 16
162 
163 	// keystream
164 	AS2(	test	AS_REG_3, AS_REG_3)
165 	ASJ(	jz,		0, f)
166 	AS2(	movdqa	xmm6, xmm4)
167 	AS2(	punpcklqdq	xmm4, xmm2)
168 	AS2(	punpckhqdq	xmm6, xmm2)
169 	AS2(	test	AS_REG_4, 15)
170 	ASJ(	jnz,	2, f)
171 	AS2(	test	AS_REG_4, AS_REG_4)
172 	ASJ(	jz,		1, f)
173 	AS2(	pxor	xmm4, [AS_REG_4])
174 	AS2(	pxor	xmm6, [AS_REG_4+16])
175 	AS2(	add		AS_REG_4, 32)
176 	ASJ(	jmp,	1, f)
177 	ASL(2)
178 	AS2(	movdqu	xmm0, [AS_REG_4])
179 	AS2(	movdqu	xmm2, [AS_REG_4+16])
180 	AS2(	pxor	xmm4, xmm0)
181 	AS2(	pxor	xmm6, xmm2)
182 	AS2(	add		AS_REG_4, 32)
183 	ASL(1)
184 	AS2(	test	AS_REG_3, 15)
185 	ASJ(	jnz,	3, f)
186 	AS2(	movdqa	XMMWORD_PTR [AS_REG_3], xmm4)
187 	AS2(	movdqa	XMMWORD_PTR [AS_REG_3+16], xmm6)
188 	AS2(	add		AS_REG_3, 32)
189 	ASJ(	jmp,	0, f)
190 	ASL(3)
191 	AS2(	movdqu	XMMWORD_PTR [AS_REG_3], xmm4)
192 	AS2(	movdqu	XMMWORD_PTR [AS_REG_3+16], xmm6)
193 	AS2(	add		AS_REG_3, 32)
194 	ASL(0)
195 
196 	// buffer update
197 	AS2(	lea		AS_REG_1, [AS_REG_6 + 32])
198 	AS2(	and		AS_REG_1, 31*32)
199 	AS2(	lea		AS_REG_7, [AS_REG_6 + (32-24)*32])
200 	AS2(	and		AS_REG_7, 31*32)
201 
202 	AS2(	movdqa	xmm0, XMMWORD_PTR [AS_REG_2+20*4+AS_REG_1+0*8])
203 	AS2(	pxor	xmm3, xmm0)
204 	ASS(	pshufd	xmm0, xmm0, 2, 3, 0, 1)
205 	AS2(	movdqa	XMMWORD_PTR [AS_REG_2+20*4+AS_REG_1+0*8], xmm3)
206 	AS2(	pxor	xmm0, XMMWORD_PTR [AS_REG_2+20*4+AS_REG_7+2*8])
207 	AS2(	movdqa	XMMWORD_PTR [AS_REG_2+20*4+AS_REG_7+2*8], xmm0)
208 
209 	AS2(	movdqa	xmm4, XMMWORD_PTR [AS_REG_2+20*4+AS_REG_1+2*8])
210 	AS2(	pxor	xmm1, xmm4)
211 	AS2(	movdqa	XMMWORD_PTR [AS_REG_2+20*4+AS_REG_1+2*8], xmm1)
212 	AS2(	pxor	xmm4, XMMWORD_PTR [AS_REG_2+20*4+AS_REG_7+0*8])
213 	AS2(	movdqa	XMMWORD_PTR [AS_REG_2+20*4+AS_REG_7+0*8], xmm4)
214 
215 	// theta
216 	AS2(	movdqa	xmm3, XMMWORD_PTR [AS_REG_2+3*16])
217 	AS2(	movdqa	xmm2, XMMWORD_PTR [AS_REG_2+2*16])
218 	AS2(	movdqa	xmm1, XMMWORD_PTR [AS_REG_2+1*16])
219 	AS2(	movdqa	xmm0, XMMWORD_PTR [AS_REG_2+0*16])
220 
221 #if CRYPTOPP_SSSE3_ASM_AVAILABLE
222 	AS2(	test	AS_REG_6, 1)
223 	ASJ(	jnz,	8, f)
224 #endif
225 	AS2(	movd	xmm6, eax)
226 	AS2(	movdqa	xmm7, xmm3)
227 	AS2(	movss	xmm7, xmm6)
228 	AS2(	movdqa	xmm6, xmm2)
229 	AS2(	movss	xmm6, xmm3)
230 	AS2(	movdqa	xmm5, xmm1)
231 	AS2(	movss	xmm5, xmm2)
232 	AS2(	movdqa	xmm4, xmm0)
233 	AS2(	movss	xmm4, xmm1)
234 	ASS(	pshufd	xmm7, xmm7, 0, 3, 2, 1)
235 	ASS(	pshufd	xmm6, xmm6, 0, 3, 2, 1)
236 	ASS(	pshufd	xmm5, xmm5, 0, 3, 2, 1)
237 	ASS(	pshufd	xmm4, xmm4, 0, 3, 2, 1)
238 #if CRYPTOPP_SSSE3_ASM_AVAILABLE
239 	ASJ(	jmp,	9, f)
240 	ASL(8)
241 	AS2(	movd	xmm7, eax)
242 	AS3(	palignr	xmm7, xmm3, 4)
243 	AS2(	movq	xmm6, xmm3)
244 	AS3(	palignr	xmm6, xmm2, 4)
245 	AS2(	movq	xmm5, xmm2)
246 	AS3(	palignr	xmm5, xmm1, 4)
247 	AS2(	movq	xmm4, xmm1)
248 	AS3(	palignr	xmm4, xmm0, 4)
249 	ASL(9)
250 #endif
251 
252 	AS2(	xor		eax, 1)
253 	AS2(	movd	AS_REG_1d, xmm0)
254 	AS2(	xor		eax, AS_REG_1d)
255 	AS2(	movd	AS_REG_1d, xmm3)
256 	AS2(	xor		eax, AS_REG_1d)
257 
258 	AS2(	pxor	xmm3, xmm2)
259 	AS2(	pxor	xmm2, xmm1)
260 	AS2(	pxor	xmm1, xmm0)
261 	AS2(	pxor	xmm0, xmm7)
262 	AS2(	pxor	xmm3, xmm7)
263 	AS2(	pxor	xmm2, xmm6)
264 	AS2(	pxor	xmm1, xmm5)
265 	AS2(	pxor	xmm0, xmm4)
266 
267 	// sigma
268 	AS2(	lea		AS_REG_1, [AS_REG_6 + (32-4)*32])
269 	AS2(	and		AS_REG_1, 31*32)
270 	AS2(	lea		AS_REG_7, [AS_REG_6 + 16*32])
271 	AS2(	and		AS_REG_7, 31*32)
272 
273 	AS2(	movdqa	xmm4, XMMWORD_PTR [AS_REG_2+20*4+AS_REG_1+0*16])
274 	AS2(	movdqa	xmm5, XMMWORD_PTR [AS_REG_2+20*4+AS_REG_7+0*16])
275 	AS2(	movdqa	xmm6, xmm4)
276 	AS2(	punpcklqdq	xmm4, xmm5)
277 	AS2(	punpckhqdq	xmm6, xmm5)
278 	AS2(	pxor	xmm3, xmm4)
279 	AS2(	pxor	xmm2, xmm6)
280 
281 	AS2(	movdqa	xmm4, XMMWORD_PTR [AS_REG_2+20*4+AS_REG_1+1*16])
282 	AS2(	movdqa	xmm5, XMMWORD_PTR [AS_REG_2+20*4+AS_REG_7+1*16])
283 	AS2(	movdqa	xmm6, xmm4)
284 	AS2(	punpcklqdq	xmm4, xmm5)
285 	AS2(	punpckhqdq	xmm6, xmm5)
286 	AS2(	pxor	xmm1, xmm4)
287 	AS2(	pxor	xmm0, xmm6)
288 
289 	// loop
290 	AS2(	add		AS_REG_6, 32)
291 	AS2(	cmp		AS_REG_6, REG_loopEnd)
292 	ASJ(	jne,	4, b)
293 
294 	// save state
295 	AS2(	mov		[AS_REG_2+4*16], eax)
296 	AS2(	movdqa	XMMWORD_PTR [AS_REG_2+3*16], xmm3)
297 	AS2(	movdqa	XMMWORD_PTR [AS_REG_2+2*16], xmm2)
298 	AS2(	movdqa	XMMWORD_PTR [AS_REG_2+1*16], xmm1)
299 	AS2(	movdqa	XMMWORD_PTR [AS_REG_2+0*16], xmm0)
300 
301 	#if CRYPTOPP_BOOL_X86
302 		AS2(	add		esp, 4)
303 		AS_POP_IF86(	bp)
304 	#endif
305 	ASL(5)
306 
307 #if defined(CRYPTOPP_GNU_STYLE_INLINE_ASSEMBLY)
308 		AS_POP_IF86(	bx)
309 		ATT_PREFIX
310 			:
311 	#if CRYPTOPP_BOOL_X64
312 			: "D" (count), "S" (state), "d" (z), "c" (y)
313 			: "%r8", "%r9", "r10", "%eax", "memory", "cc", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7"
314 	#else
315 			: "c" (count), "d" (state), "S" (z), "D" (y)
316 			: "%eax", "memory", "cc"
317 	#endif
318 	);
319 #endif
320 
321 #ifdef CRYPTOPP_GENERATE_X64_MASM
322 	movdqa	xmm6, [rsp + 0h]
323 	movdqa	xmm7, [rsp + 10h]
324 	add rsp, 2*16
325 	pop	rdi
326 	ret
327 	Panama_SSE2_Pull ENDP
328 #else
329 }
330 #endif
331 #endif	// CRYPTOPP_SSE2_ASM_AVAILABLE
332 
333 #ifndef CRYPTOPP_GENERATE_X64_MASM
334 
335 template <class B>
336 void Panama<B>::Iterate(size_t count, const word32 *p, byte *output, const byte *input, KeystreamOperation operation)
337 {
338 	word32 bstart = m_state[17];
339 	word32 *const aPtr = m_state;
340 	word32 cPtr[17];
341 
342 #define bPtr ((byte *)(aPtr+20))
343 
344 // reorder the state for SSE2
345 // a and c: 4 8 12 16 | 3 7 11 15 | 2 6 10 14 | 1 5 9 13 |  0  |
346 //            xmm0        xmm1        xmm2        xmm3     eax
347 #define a(i) aPtr[((i)*13+16) % 17]		// 13 is inverse of 4 mod 17
348 #define c(i) cPtr[((i)*13+16) % 17]
349 // b: 0 4 | 1 5 | 2 6 | 3 7
350 #define b(i, j) b##i[(j)*2%8 + (j)/4]
351 
352 // buffer update
353 #define US(i) {word32 t=b(0,i); b(0,i)=ConditionalByteReverse(B::ToEnum(), p[i])^t; b(25,(i+6)%8)^=t;}
354 #define UL(i) {word32 t=b(0,i); b(0,i)=a(i+1)^t; b(25,(i+6)%8)^=t;}
355 // gamma and pi
356 #define GP(i) c(5*i%17) = rotlFixed(a(i) ^ (a((i+1)%17) | ~a((i+2)%17)), ((5*i%17)*((5*i%17)+1)/2)%32)
357 // theta and sigma
358 #define T(i,x) a(i) = c(i) ^ c((i+1)%17) ^ c((i+4)%17) ^ x
359 #define TS1S(i) T(i+1, ConditionalByteReverse(B::ToEnum(), p[i]))
360 #define TS1L(i) T(i+1, b(4,i))
361 #define TS2(i) T(i+9, b(16,i))
362 
363 	while (count--)
364 	{
365 		if (output)
366 		{
367 #define PANAMA_OUTPUT(x)	\
368 	CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, B::ToEnum(), 0, a(0+9));\
369 	CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, B::ToEnum(), 1, a(1+9));\
370 	CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, B::ToEnum(), 2, a(2+9));\
371 	CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, B::ToEnum(), 3, a(3+9));\
372 	CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, B::ToEnum(), 4, a(4+9));\
373 	CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, B::ToEnum(), 5, a(5+9));\
374 	CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, B::ToEnum(), 6, a(6+9));\
375 	CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, B::ToEnum(), 7, a(7+9));
376 
377 			typedef word32 WordType;
378 			CRYPTOPP_KEYSTREAM_OUTPUT_SWITCH(PANAMA_OUTPUT, 4*8);
379 		}
380 
381 		word32 *const b16 = (word32 *)(void *)(bPtr+((bstart+16*32) & 31*32));
382 		word32 *const b4 = (word32 *)(void *)(bPtr+((bstart+(32-4)*32) & 31*32));
383        	bstart += 32;
384 		word32 *const b0 = (word32 *)(void *)(bPtr+((bstart) & 31*32));
385 		word32 *const b25 = (word32 *)(void *)(bPtr+((bstart+(32-25)*32) & 31*32));
386 
387 		if (p)
388 		{
389 			US(0); US(1); US(2); US(3); US(4); US(5); US(6); US(7);
390 		}
391 		else
392 		{
393 			UL(0); UL(1); UL(2); UL(3); UL(4); UL(5); UL(6); UL(7);
394 		}
395 
396 		GP(0);
397 		GP(1);
398 		GP(2);
399 		GP(3);
400 		GP(4);
401 		GP(5);
402 		GP(6);
403 		GP(7);
404 		GP(8);
405 		GP(9);
406 		GP(10);
407 		GP(11);
408 		GP(12);
409 		GP(13);
410 		GP(14);
411 		GP(15);
412 		GP(16);
413 
414 		T(0,1);
415 
416 		if (p)
417 		{
418 			TS1S(0); TS1S(1); TS1S(2); TS1S(3); TS1S(4); TS1S(5); TS1S(6); TS1S(7);
419 			p += 8;
420 		}
421 		else
422 		{
423 			TS1L(0); TS1L(1); TS1L(2); TS1L(3); TS1L(4); TS1L(5); TS1L(6); TS1L(7);
424 		}
425 
426 		TS2(0); TS2(1); TS2(2); TS2(3); TS2(4); TS2(5); TS2(6); TS2(7);
427 	}
428 	m_state[17] = bstart;
429 }
430 
NAMESPACE_BEGIN(Weak)431 NAMESPACE_BEGIN(Weak)
432 template <class B>
433 size_t PanamaHash<B>::HashMultipleBlocks(const word32 *input, size_t length)
434 {
435 	this->Iterate(length / this->BLOCKSIZE, input);
436 	return length % this->BLOCKSIZE;
437 }
438 
439 template <class B>
TruncatedFinal(byte * hash,size_t size)440 void PanamaHash<B>::TruncatedFinal(byte *hash, size_t size)
441 {
442 	this->ThrowIfInvalidTruncatedSize(size);
443 
444 	this->PadLastBlock(this->BLOCKSIZE, 0x01);
445 
446 	this->HashEndianCorrectedBlock(this->m_data);
447 
448 	this->Iterate(32);	// pull
449 
450 	this->Iterate(1, NULLPTR, m_buf.BytePtr(), NULLPTR);
451 
452 	memcpy(hash, m_buf, size);
453 
454 	this->Restart();		// reinit for next use
455 }
456 NAMESPACE_END
457 
458 template <class B>
CipherSetKey(const NameValuePairs & params,const byte * key,size_t length)459 void PanamaCipherPolicy<B>::CipherSetKey(const NameValuePairs &params, const byte *key, size_t length)
460 {
461 	CRYPTOPP_UNUSED(params); CRYPTOPP_UNUSED(length);
462 	CRYPTOPP_ASSERT(length==32);
463 	memcpy(m_key, key, 32);
464 }
465 
466 template <class B>
CipherResynchronize(byte * keystreamBuffer,const byte * iv,size_t length)467 void PanamaCipherPolicy<B>::CipherResynchronize(byte *keystreamBuffer, const byte *iv, size_t length)
468 {
469 	CRYPTOPP_UNUSED(keystreamBuffer); CRYPTOPP_UNUSED(iv);
470 	CRYPTOPP_UNUSED(length); CRYPTOPP_ASSERT(length==32);
471 
472 	this->Reset();
473 	this->Iterate(1, m_key);
474 	if (iv && IsAligned<word32>(iv))
475 		this->Iterate(1, reinterpret_cast<const word32*>(iv));
476 	else
477 	{
478 		if (iv)
479 			memcpy(m_buf, iv, 32);
480 		else
481 			memset(m_buf, 0, 32);
482 		this->Iterate(1, m_buf);
483 	}
484 
485 #if (CRYPTOPP_SSE2_ASM_AVAILABLE || defined(CRYPTOPP_X64_MASM_AVAILABLE)) && !defined(CRYPTOPP_DISABLE_PANAMA_ASM)
486 	if (B::ToEnum() == LITTLE_ENDIAN_ORDER && HasSSE2() && !IsP4())		// SSE2 code is slower on P4 Prescott
487 		Panama_SSE2_Pull(32, this->m_state, NULLPTR, NULLPTR);
488 	else
489 #endif
490 		this->Iterate(32);
491 }
492 
493 template <class B>
AlgorithmProvider() const494 std::string PanamaCipherPolicy<B>::AlgorithmProvider() const
495 {
496 	return Panama<B>::AlgorithmProvider();
497 }
498 
499 template <class B>
GetAlignment() const500 unsigned int PanamaCipherPolicy<B>::GetAlignment() const
501 {
502 #if (CRYPTOPP_SSE2_ASM_AVAILABLE || defined(CRYPTOPP_X64_MASM_AVAILABLE)) && !defined(CRYPTOPP_DISABLE_PANAMA_ASM)
503 	if (B::ToEnum() == LITTLE_ENDIAN_ORDER && HasSSE2())
504 		return 16;
505 	else
506 #endif
507 		return 1;
508 }
509 
510 template <class B>
OperateKeystream(KeystreamOperation operation,byte * output,const byte * input,size_t iterationCount)511 void PanamaCipherPolicy<B>::OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount)
512 {
513 #if (CRYPTOPP_SSE2_ASM_AVAILABLE || defined(CRYPTOPP_X64_MASM_AVAILABLE)) && !defined(CRYPTOPP_DISABLE_PANAMA_ASM)
514 	if (B::ToEnum() == LITTLE_ENDIAN_ORDER && HasSSE2())
515 		Panama_SSE2_Pull(iterationCount, this->m_state,
516 			reinterpret_cast<word32*>(output), reinterpret_cast<const word32*>(input));
517 	else
518 #endif
519 		this->Iterate(iterationCount, NULLPTR, output, input, operation);
520 }
521 
522 template class Panama<BigEndian>;
523 template class Panama<LittleEndian>;
524 
525 template class Weak::PanamaHash<BigEndian>;
526 template class Weak::PanamaHash<LittleEndian>;
527 
528 template class PanamaCipherPolicy<BigEndian>;
529 template class PanamaCipherPolicy<LittleEndian>;
530 
531 NAMESPACE_END
532 
533 #endif	// #ifndef CRYPTOPP_GENERATE_X64_MASM
534