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.

193 lines
3.8 KiB

  1. // idea.cpp - written and placed in the public domain by Wei Dai
  2. #include "pch.h"
  3. #include "idea.h"
  4. #include "misc.h"
  5. #include "secblock.h"
  6. NAMESPACE_BEGIN(CryptoPP)
  7. static const int IDEA_KEYLEN=(6*IDEA::ROUNDS+4); // key schedule length in # of word16s
  8. #define low16(x) ((x)&0xffff) // compiler should be able to optimize this away if word is 16 bits
  9. #define high16(x) ((x)>>16)
  10. CRYPTOPP_COMPILE_ASSERT(sizeof(IDEA::Word) >= 2);
  11. // should use an inline function but macros are still faster in MSVC 4.0
  12. #define DirectMUL(a,b) \
  13. { \
  14. assert(b <= 0xffff); \
  15. \
  16. word32 p=(word32)low16(a)*b; \
  17. \
  18. if (p) \
  19. { \
  20. p = low16(p) - high16(p); \
  21. a = (IDEA::Word)p - (IDEA::Word)high16(p); \
  22. } \
  23. else \
  24. a = 1-a-b; \
  25. }
  26. #ifdef IDEA_LARGECACHE
  27. volatile bool IDEA::Base::tablesBuilt = false;
  28. word16 IDEA::Base::log[0x10000];
  29. word16 IDEA::Base::antilog[0x10000];
  30. void IDEA::Base::BuildLogTables()
  31. {
  32. if (tablesBuilt)
  33. return;
  34. else
  35. {
  36. tablesBuilt = true;
  37. IDEA::Word x=1;
  38. word32 i;
  39. for (i=0; i<0x10000; i++)
  40. {
  41. antilog[i] = (word16)x;
  42. DirectMUL(x, 3);
  43. }
  44. for (i=0; i<0x10000; i++)
  45. log[antilog[i]] = (word16)i;
  46. }
  47. }
  48. void IDEA::Base::LookupKeyLogs()
  49. {
  50. IDEA::Word* Z=key;
  51. int r=ROUNDS;
  52. do
  53. {
  54. Z[0] = log[Z[0]];
  55. Z[3] = log[Z[3]];
  56. Z[4] = log[Z[4]];
  57. Z[5] = log[Z[5]];
  58. Z+=6;
  59. } while (--r);
  60. Z[0] = log[Z[0]];
  61. Z[3] = log[Z[3]];
  62. }
  63. inline void IDEA::Base::LookupMUL(IDEA::Word &a, IDEA::Word b)
  64. {
  65. a = antilog[low16(log[low16(a)]+b)];
  66. }
  67. #endif // IDEA_LARGECACHE
  68. void IDEA::Base::UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs &)
  69. {
  70. AssertValidKeyLength(length);
  71. #ifdef IDEA_LARGECACHE
  72. BuildLogTables();
  73. #endif
  74. EnKey(userKey);
  75. if (!IsForwardTransformation())
  76. DeKey();
  77. #ifdef IDEA_LARGECACHE
  78. LookupKeyLogs();
  79. #endif
  80. }
  81. void IDEA::Base::EnKey (const byte *userKey)
  82. {
  83. unsigned int i;
  84. for (i=0; i<8; i++)
  85. m_key[i] = ((IDEA::Word)userKey[2*i]<<8) | userKey[2*i+1];
  86. for (; i<IDEA_KEYLEN; i++)
  87. {
  88. unsigned int j = RoundDownToMultipleOf(i,8U)-8;
  89. m_key[i] = low16((m_key[j+(i+1)%8] << 9) | (m_key[j+(i+2)%8] >> 7));
  90. }
  91. }
  92. static IDEA::Word MulInv(IDEA::Word x)
  93. {
  94. IDEA::Word y=x;
  95. for (unsigned i=0; i<15; i++)
  96. {
  97. DirectMUL(y,low16(y));
  98. DirectMUL(y,x);
  99. }
  100. return low16(y);
  101. }
  102. static inline IDEA::Word AddInv(IDEA::Word x)
  103. {
  104. return low16(0-x);
  105. }
  106. void IDEA::Base::DeKey()
  107. {
  108. FixedSizeSecBlock<IDEA::Word, 6*ROUNDS+4> tempkey;
  109. size_t i;
  110. for (i=0; i<ROUNDS; i++)
  111. {
  112. tempkey[i*6+0] = MulInv(m_key[(ROUNDS-i)*6+0]);
  113. tempkey[i*6+1] = AddInv(m_key[(ROUNDS-i)*6+1+(i>0)]);
  114. tempkey[i*6+2] = AddInv(m_key[(ROUNDS-i)*6+2-(i>0)]);
  115. tempkey[i*6+3] = MulInv(m_key[(ROUNDS-i)*6+3]);
  116. tempkey[i*6+4] = m_key[(ROUNDS-1-i)*6+4];
  117. tempkey[i*6+5] = m_key[(ROUNDS-1-i)*6+5];
  118. }
  119. tempkey[i*6+0] = MulInv(m_key[(ROUNDS-i)*6+0]);
  120. tempkey[i*6+1] = AddInv(m_key[(ROUNDS-i)*6+1]);
  121. tempkey[i*6+2] = AddInv(m_key[(ROUNDS-i)*6+2]);
  122. tempkey[i*6+3] = MulInv(m_key[(ROUNDS-i)*6+3]);
  123. m_key = tempkey;
  124. }
  125. #ifdef IDEA_LARGECACHE
  126. #define MUL(a,b) LookupMUL(a,b)
  127. #else
  128. #define MUL(a,b) DirectMUL(a,b)
  129. #endif
  130. void IDEA::Base::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
  131. {
  132. typedef BlockGetAndPut<word16, BigEndian> Block;
  133. const IDEA::Word *key = m_key;
  134. IDEA::Word x0,x1,x2,x3,t0,t1;
  135. Block::Get(inBlock)(x0)(x1)(x2)(x3);
  136. for (unsigned int i=0; i<ROUNDS; i++)
  137. {
  138. MUL(x0, key[i*6+0]);
  139. x1 += key[i*6+1];
  140. x2 += key[i*6+2];
  141. MUL(x3, key[i*6+3]);
  142. t0 = x0^x2;
  143. MUL(t0, key[i*6+4]);
  144. t1 = t0 + (x1^x3);
  145. MUL(t1, key[i*6+5]);
  146. t0 += t1;
  147. x0 ^= t1;
  148. x3 ^= t0;
  149. t0 ^= x1;
  150. x1 = x2^t1;
  151. x2 = t0;
  152. }
  153. MUL(x0, key[ROUNDS*6+0]);
  154. x2 += key[ROUNDS*6+1];
  155. x1 += key[ROUNDS*6+2];
  156. MUL(x3, key[ROUNDS*6+3]);
  157. Block::Put(xorBlock, outBlock)(x0)(x2)(x1)(x3);
  158. }
  159. NAMESPACE_END