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.

393 lines
7.1 KiB

  1. // Purpose: C++ implementation of the ICE encryption algorithm.
  2. // Taken from public domain code, as written by Matthew Kwan - July 1996
  3. // http://www.darkside.com.au/ice/
  4. #if !defined(_STATIC_LINKED) || defined(_SHARED_LIB)
  5. #include "mathlib/IceKey.H"
  6. #include "tier0/memdbgon.h"
  7. #pragma warning(disable: 4244)
  8. /* Structure of a single round subkey */
  9. class IceSubkey {
  10. public:
  11. unsigned long val[3];
  12. };
  13. /* The S-boxes */
  14. static unsigned long ice_sbox[4][1024];
  15. static int ice_sboxes_initialised = 0;
  16. /* Modulo values for the S-boxes */
  17. static const int ice_smod[4][4] = {
  18. {333, 313, 505, 369},
  19. {379, 375, 319, 391},
  20. {361, 445, 451, 397},
  21. {397, 425, 395, 505}};
  22. /* XOR values for the S-boxes */
  23. static const int ice_sxor[4][4] = {
  24. {0x83, 0x85, 0x9b, 0xcd},
  25. {0xcc, 0xa7, 0xad, 0x41},
  26. {0x4b, 0x2e, 0xd4, 0x33},
  27. {0xea, 0xcb, 0x2e, 0x04}};
  28. /* Permutation values for the P-box */
  29. static const unsigned long ice_pbox[32] = {
  30. 0x00000001, 0x00000080, 0x00000400, 0x00002000,
  31. 0x00080000, 0x00200000, 0x01000000, 0x40000000,
  32. 0x00000008, 0x00000020, 0x00000100, 0x00004000,
  33. 0x00010000, 0x00800000, 0x04000000, 0x20000000,
  34. 0x00000004, 0x00000010, 0x00000200, 0x00008000,
  35. 0x00020000, 0x00400000, 0x08000000, 0x10000000,
  36. 0x00000002, 0x00000040, 0x00000800, 0x00001000,
  37. 0x00040000, 0x00100000, 0x02000000, 0x80000000};
  38. /* The key rotation schedule */
  39. static const int ice_keyrot[16] = {
  40. 0, 1, 2, 3, 2, 1, 3, 0,
  41. 1, 3, 2, 0, 3, 1, 0, 2};
  42. /*
  43. * 8-bit Galois Field multiplication of a by b, modulo m.
  44. * Just like arithmetic multiplication, except that additions and
  45. * subtractions are replaced by XOR.
  46. */
  47. static unsigned int
  48. gf_mult (
  49. unsigned int a,
  50. unsigned int b,
  51. unsigned int m
  52. ) {
  53. unsigned int res = 0;
  54. while (b) {
  55. if (b & 1)
  56. res ^= a;
  57. a <<= 1;
  58. b >>= 1;
  59. if (a >= 256)
  60. a ^= m;
  61. }
  62. return (res);
  63. }
  64. /*
  65. * Galois Field exponentiation.
  66. * Raise the base to the power of 7, modulo m.
  67. */
  68. static unsigned long
  69. gf_exp7 (
  70. unsigned int b,
  71. unsigned int m
  72. ) {
  73. unsigned int x;
  74. if (b == 0)
  75. return (0);
  76. x = gf_mult (b, b, m);
  77. x = gf_mult (b, x, m);
  78. x = gf_mult (x, x, m);
  79. return (gf_mult (b, x, m));
  80. }
  81. /*
  82. * Carry out the ICE 32-bit P-box permutation.
  83. */
  84. static unsigned long
  85. ice_perm32 (
  86. unsigned long x
  87. ) {
  88. unsigned long res = 0;
  89. const unsigned long *pbox = ice_pbox;
  90. while (x) {
  91. if (x & 1)
  92. res |= *pbox;
  93. pbox++;
  94. x >>= 1;
  95. }
  96. return (res);
  97. }
  98. /*
  99. * Initialise the ICE S-boxes.
  100. * This only has to be done once.
  101. */
  102. static void
  103. ice_sboxes_init (void)
  104. {
  105. int i;
  106. for (i=0; i<1024; i++) {
  107. int col = (i >> 1) & 0xff;
  108. int row = (i & 0x1) | ((i & 0x200) >> 8);
  109. unsigned long x;
  110. x = gf_exp7 (col ^ ice_sxor[0][row], ice_smod[0][row]) << 24;
  111. ice_sbox[0][i] = ice_perm32 (x);
  112. x = gf_exp7 (col ^ ice_sxor[1][row], ice_smod[1][row]) << 16;
  113. ice_sbox[1][i] = ice_perm32 (x);
  114. x = gf_exp7 (col ^ ice_sxor[2][row], ice_smod[2][row]) << 8;
  115. ice_sbox[2][i] = ice_perm32 (x);
  116. x = gf_exp7 (col ^ ice_sxor[3][row], ice_smod[3][row]);
  117. ice_sbox[3][i] = ice_perm32 (x);
  118. }
  119. }
  120. /*
  121. * Create a new ICE key.
  122. */
  123. IceKey::IceKey (int n)
  124. {
  125. if (!ice_sboxes_initialised) {
  126. ice_sboxes_init ();
  127. ice_sboxes_initialised = 1;
  128. }
  129. if (n < 1) {
  130. _size = 1;
  131. _rounds = 8;
  132. } else {
  133. _size = n;
  134. _rounds = n * 16;
  135. }
  136. _keysched = new IceSubkey[_rounds];
  137. }
  138. /*
  139. * Destroy an ICE key.
  140. */
  141. IceKey::~IceKey ()
  142. {
  143. int i, j;
  144. for (i=0; i<_rounds; i++)
  145. for (j=0; j<3; j++)
  146. _keysched[i].val[j] = 0;
  147. _rounds = _size = 0;
  148. delete[] _keysched;
  149. }
  150. /*
  151. * The single round ICE f function.
  152. */
  153. static unsigned long
  154. ice_f (
  155. unsigned long p,
  156. const IceSubkey *sk
  157. ) {
  158. unsigned long tl, tr; /* Expanded 40-bit values */
  159. unsigned long al, ar; /* Salted expanded 40-bit values */
  160. /* Left half expansion */
  161. tl = ((p >> 16) & 0x3ff) | (((p >> 14) | (p << 18)) & 0xffc00);
  162. /* Right half expansion */
  163. tr = (p & 0x3ff) | ((p << 2) & 0xffc00);
  164. /* Perform the salt permutation */
  165. // al = (tr & sk->val[2]) | (tl & ~sk->val[2]);
  166. // ar = (tl & sk->val[2]) | (tr & ~sk->val[2]);
  167. al = sk->val[2] & (tl ^ tr);
  168. ar = al ^ tr;
  169. al ^= tl;
  170. al ^= sk->val[0]; /* XOR with the subkey */
  171. ar ^= sk->val[1];
  172. /* S-box lookup and permutation */
  173. return (ice_sbox[0][al >> 10] | ice_sbox[1][al & 0x3ff]
  174. | ice_sbox[2][ar >> 10] | ice_sbox[3][ar & 0x3ff]);
  175. }
  176. /*
  177. * Encrypt a block of 8 bytes of data with the given ICE key.
  178. */
  179. void
  180. IceKey::encrypt (
  181. const unsigned char *ptext,
  182. unsigned char *ctext
  183. ) const
  184. {
  185. int i;
  186. unsigned long l, r;
  187. l = (((unsigned long) ptext[0]) << 24)
  188. | (((unsigned long) ptext[1]) << 16)
  189. | (((unsigned long) ptext[2]) << 8) | ptext[3];
  190. r = (((unsigned long) ptext[4]) << 24)
  191. | (((unsigned long) ptext[5]) << 16)
  192. | (((unsigned long) ptext[6]) << 8) | ptext[7];
  193. for (i = 0; i < _rounds; i += 2) {
  194. l ^= ice_f (r, &_keysched[i]);
  195. r ^= ice_f (l, &_keysched[i + 1]);
  196. }
  197. for (i = 0; i < 4; i++) {
  198. ctext[3 - i] = r & 0xff;
  199. ctext[7 - i] = l & 0xff;
  200. r >>= 8;
  201. l >>= 8;
  202. }
  203. }
  204. /*
  205. * Decrypt a block of 8 bytes of data with the given ICE key.
  206. */
  207. void
  208. IceKey::decrypt (
  209. const unsigned char *ctext,
  210. unsigned char *ptext
  211. ) const
  212. {
  213. int i;
  214. unsigned long l, r;
  215. l = (((unsigned long) ctext[0]) << 24)
  216. | (((unsigned long) ctext[1]) << 16)
  217. | (((unsigned long) ctext[2]) << 8) | ctext[3];
  218. r = (((unsigned long) ctext[4]) << 24)
  219. | (((unsigned long) ctext[5]) << 16)
  220. | (((unsigned long) ctext[6]) << 8) | ctext[7];
  221. for (i = _rounds - 1; i > 0; i -= 2) {
  222. l ^= ice_f (r, &_keysched[i]);
  223. r ^= ice_f (l, &_keysched[i - 1]);
  224. }
  225. for (i = 0; i < 4; i++) {
  226. ptext[3 - i] = r & 0xff;
  227. ptext[7 - i] = l & 0xff;
  228. r >>= 8;
  229. l >>= 8;
  230. }
  231. }
  232. /*
  233. * Set 8 rounds [n, n+7] of the key schedule of an ICE key.
  234. */
  235. void
  236. IceKey::scheduleBuild (
  237. unsigned short *kb,
  238. int n,
  239. const int *keyrot
  240. ) {
  241. int i;
  242. for (i=0; i<8; i++) {
  243. int j;
  244. int kr = keyrot[i];
  245. IceSubkey *isk = &_keysched[n + i];
  246. for (j=0; j<3; j++)
  247. isk->val[j] = 0;
  248. for (j=0; j<15; j++) {
  249. int k;
  250. unsigned long *curr_sk = &isk->val[j % 3];
  251. for (k=0; k<4; k++) {
  252. unsigned short *curr_kb = &kb[(kr + k) & 3];
  253. int bit = *curr_kb & 1;
  254. *curr_sk = (*curr_sk << 1) | bit;
  255. *curr_kb = (*curr_kb >> 1) | ((bit ^ 1) << 15);
  256. }
  257. }
  258. }
  259. }
  260. /*
  261. * Set the key schedule of an ICE key.
  262. */
  263. void
  264. IceKey::set (
  265. const unsigned char *key
  266. ) {
  267. int i;
  268. if (_rounds == 8) {
  269. unsigned short kb[4];
  270. for (i=0; i<4; i++)
  271. kb[3 - i] = (key[i*2] << 8) | key[i*2 + 1];
  272. scheduleBuild (kb, 0, ice_keyrot);
  273. return;
  274. }
  275. for (i=0; i<_size; i++) {
  276. int j;
  277. unsigned short kb[4];
  278. for (j=0; j<4; j++)
  279. kb[3 - j] = (key[i*8 + j*2] << 8) | key[i*8 + j*2 + 1];
  280. scheduleBuild (kb, i*8, ice_keyrot);
  281. scheduleBuild (kb, _rounds - 8 - i*8, &ice_keyrot[8]);
  282. }
  283. }
  284. /*
  285. * Return the key size, in bytes.
  286. */
  287. int
  288. IceKey::keySize () const
  289. {
  290. return (_size * 8);
  291. }
  292. /*
  293. * Return the block size, in bytes.
  294. */
  295. int
  296. IceKey::blockSize () const
  297. {
  298. return (8);
  299. }
  300. #endif // !_STATIC_LINKED || _SHARED_LIB