Counter Strike : Global Offensive Source Code
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.

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