Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

518 lines
13 KiB

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