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.

187 lines
5.3 KiB

  1. // square.cpp - written and placed in the public domain by Wei Dai
  2. // Based on Paulo S.L.M. Barreto's public domain implementation
  3. #include "pch.h"
  4. #include "config.h"
  5. #include "square.h"
  6. #include "misc.h"
  7. #include "gf256.h"
  8. #if CRYPTOPP_MSC_VERSION
  9. # pragma warning(disable: 4244)
  10. #endif
  11. #if CRYPTOPP_GCC_DIAGNOSTIC_AVAILABLE
  12. # pragma GCC diagnostic ignored "-Wmissing-braces"
  13. #endif
  14. NAMESPACE_BEGIN(CryptoPP)
  15. // apply theta to a roundkey
  16. static void SquareTransform (word32 in[4], word32 out[4])
  17. {
  18. static const byte G[4][4] =
  19. {
  20. 0x02U, 0x01U, 0x01U, 0x03U,
  21. 0x03U, 0x02U, 0x01U, 0x01U,
  22. 0x01U, 0x03U, 0x02U, 0x01U,
  23. 0x01U, 0x01U, 0x03U, 0x02U
  24. };
  25. GF256 gf256(0xf5);
  26. for (int i = 0; i < 4; i++)
  27. {
  28. word32 temp = 0;
  29. for (unsigned int j = 0; j < 4; j++)
  30. for (unsigned int k = 0; k < 4; k++)
  31. temp ^= (word32)gf256.Multiply(GETBYTE(in[i], 3-k), G[k][j]) << ((3-j)*8);
  32. out[i] = temp;
  33. }
  34. }
  35. #define roundkeys(i, j) m_roundkeys[(i)*4+(j)]
  36. #define roundkeys4(i) (m_roundkeys+(i)*4)
  37. void Square::Base::UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs &)
  38. {
  39. AssertValidKeyLength(length);
  40. static const word32 offset[ROUNDS] = {
  41. 0x01000000UL, 0x02000000UL, 0x04000000UL, 0x08000000UL,
  42. 0x10000000UL, 0x20000000UL, 0x40000000UL, 0x80000000UL,
  43. };
  44. GetUserKey(BIG_ENDIAN_ORDER, m_roundkeys.data(), KEYLENGTH/4, userKey, KEYLENGTH);
  45. /* apply the key evolution function */
  46. for (int i = 1; i < ROUNDS+1; i++)
  47. {
  48. roundkeys(i, 0) = roundkeys(i-1, 0) ^ rotlFixed(roundkeys(i-1, 3), 8U) ^ offset[i-1];
  49. roundkeys(i, 1) = roundkeys(i-1, 1) ^ roundkeys(i, 0);
  50. roundkeys(i, 2) = roundkeys(i-1, 2) ^ roundkeys(i, 1);
  51. roundkeys(i, 3) = roundkeys(i-1, 3) ^ roundkeys(i, 2);
  52. }
  53. /* produce the round keys */
  54. if (IsForwardTransformation())
  55. {
  56. for (int i = 0; i < ROUNDS; i++)
  57. SquareTransform (roundkeys4(i), roundkeys4(i));
  58. }
  59. else
  60. {
  61. for (int i = 0; i < ROUNDS/2; i++)
  62. for (int j = 0; j < 4; j++)
  63. std::swap(roundkeys(i, j), roundkeys(ROUNDS-i, j));
  64. SquareTransform (roundkeys4(ROUNDS), roundkeys4(ROUNDS));
  65. }
  66. }
  67. #define MSB(x) (((x) >> 24) & 0xffU) /* most significant byte */
  68. #define SSB(x) (((x) >> 16) & 0xffU) /* second in significance */
  69. #define TSB(x) (((x) >> 8) & 0xffU) /* third in significance */
  70. #define LSB(x) (((x) ) & 0xffU) /* least significant byte */
  71. #define squareRound(text, temp, T0, T1, T2, T3, roundkey) \
  72. { \
  73. temp[0] = T0[MSB (text[0])] \
  74. ^ T1[MSB (text[1])] \
  75. ^ T2[MSB (text[2])] \
  76. ^ T3[MSB (text[3])] \
  77. ^ roundkey[0]; \
  78. temp[1] = T0[SSB (text[0])] \
  79. ^ T1[SSB (text[1])] \
  80. ^ T2[SSB (text[2])] \
  81. ^ T3[SSB (text[3])] \
  82. ^ roundkey[1]; \
  83. temp[2] = T0[TSB (text[0])] \
  84. ^ T1[TSB (text[1])] \
  85. ^ T2[TSB (text[2])] \
  86. ^ T3[TSB (text[3])] \
  87. ^ roundkey[2]; \
  88. temp[3] = T0[LSB (text[0])] \
  89. ^ T1[LSB (text[1])] \
  90. ^ T2[LSB (text[2])] \
  91. ^ T3[LSB (text[3])] \
  92. ^ roundkey[3]; \
  93. } /* squareRound */
  94. #define squareFinal(text, temp, S, roundkey) \
  95. { \
  96. text[0] = ((word32) (S[MSB (temp[0])]) << 24) \
  97. ^ ((word32) (S[MSB (temp[1])]) << 16) \
  98. ^ ((word32) (S[MSB (temp[2])]) << 8) \
  99. ^ (word32) (S[MSB (temp[3])]) \
  100. ^ roundkey[0]; \
  101. text[1] = ((word32) (S[SSB (temp[0])]) << 24) \
  102. ^ ((word32) (S[SSB (temp[1])]) << 16) \
  103. ^ ((word32) (S[SSB (temp[2])]) << 8) \
  104. ^ (word32) (S[SSB (temp[3])]) \
  105. ^ roundkey[1]; \
  106. text[2] = ((word32) (S[TSB (temp[0])]) << 24) \
  107. ^ ((word32) (S[TSB (temp[1])]) << 16) \
  108. ^ ((word32) (S[TSB (temp[2])]) << 8) \
  109. ^ (word32) (S[TSB (temp[3])]) \
  110. ^ roundkey[2]; \
  111. text[3] = ((word32) (S[LSB (temp[0])]) << 24) \
  112. ^ ((word32) (S[LSB (temp[1])]) << 16) \
  113. ^ ((word32) (S[LSB (temp[2])]) << 8) \
  114. ^ (word32) (S[LSB (temp[3])]) \
  115. ^ roundkey[3]; \
  116. } /* squareFinal */
  117. typedef BlockGetAndPut<word32, BigEndian> Block;
  118. void Square::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
  119. {
  120. word32 text[4], temp[4];
  121. Block::Get(inBlock)(text[0])(text[1])(text[2])(text[3]);
  122. /* initial key addition */
  123. text[0] ^= roundkeys(0, 0);
  124. text[1] ^= roundkeys(0, 1);
  125. text[2] ^= roundkeys(0, 2);
  126. text[3] ^= roundkeys(0, 3);
  127. /* ROUNDS - 1 full rounds */
  128. for (int i=1; i+1<ROUNDS; i+=2)
  129. {
  130. squareRound (text, temp, Te[0], Te[1], Te[2], Te[3], roundkeys4(i));
  131. squareRound (temp, text, Te[0], Te[1], Te[2], Te[3], roundkeys4(i+1));
  132. }
  133. squareRound (text, temp, Te[0], Te[1], Te[2], Te[3], roundkeys4(ROUNDS-1));
  134. /* last round (diffusion becomes only transposition) */
  135. squareFinal (text, temp, Se, roundkeys4(ROUNDS));
  136. Block::Put(xorBlock, outBlock)(text[0])(text[1])(text[2])(text[3]);
  137. }
  138. void Square::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
  139. {
  140. word32 text[4], temp[4];
  141. Block::Get(inBlock)(text[0])(text[1])(text[2])(text[3]);
  142. /* initial key addition */
  143. text[0] ^= roundkeys(0, 0);
  144. text[1] ^= roundkeys(0, 1);
  145. text[2] ^= roundkeys(0, 2);
  146. text[3] ^= roundkeys(0, 3);
  147. /* ROUNDS - 1 full rounds */
  148. for (int i=1; i+1<ROUNDS; i+=2)
  149. {
  150. squareRound (text, temp, Td[0], Td[1], Td[2], Td[3], roundkeys4(i));
  151. squareRound (temp, text, Td[0], Td[1], Td[2], Td[3], roundkeys4(i+1));
  152. }
  153. squareRound (text, temp, Td[0], Td[1], Td[2], Td[3], roundkeys4(ROUNDS-1));
  154. /* last round (diffusion becomes only transposition) */
  155. squareFinal (text, temp, Sd, roundkeys4(ROUNDS));
  156. Block::Put(xorBlock, outBlock)(text[0])(text[1])(text[2])(text[3]);
  157. }
  158. NAMESPACE_END