PK.CPP 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  1. //
  2. // Copyright 2020 Electronic Arts Inc.
  3. //
  4. // TiberianDawn.DLL and RedAlert.dll and corresponding source code is free
  5. // software: you can redistribute it and/or modify it under the terms of
  6. // the GNU General Public License as published by the Free Software Foundation,
  7. // either version 3 of the License, or (at your option) any later version.
  8. // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed
  9. // in the hope that it will be useful, but with permitted additional restrictions
  10. // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT
  11. // distributed with this program. You should have received a copy of the
  12. // GNU General Public License along with permitted additional restrictions
  13. // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
  14. /* $Header: /CounterStrike/PK.CPP 1 3/03/97 10:25a Joe_bostic $ */
  15. /***********************************************************************************************
  16. *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
  17. ***********************************************************************************************
  18. * *
  19. * Project Name : Command & Conquer *
  20. * *
  21. * File Name : PK.CPP *
  22. * *
  23. * Programmer : Joe L. Bostic *
  24. * *
  25. * Start Date : 07/04/96 *
  26. * *
  27. * Last Update : July 10, 1996 [JLB] *
  28. * *
  29. *---------------------------------------------------------------------------------------------*
  30. * Functions: *
  31. * PKey::Decode_Exponent -- Decodes the exponent back into the key. *
  32. * PKey::Decode_Modulus -- Decodes the modulus value back into the key. *
  33. * PKey::Decrypt -- Decrypt supplied cyphertext into its original plaintext. *
  34. * PKey::Encode_Exponent -- Encode the exponent portion of the key into a buffer. *
  35. * PKey::Encode_Modulus -- Encode the modulus portion of the key. *
  36. * PKey::Encrypt -- Encrypt blocks of plaintext. *
  37. * PKey::Generate -- Generate a public and private key. *
  38. * PKey::PKey -- Construct a key using encoded strings. *
  39. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  40. #include "pk.h"
  41. #include "rndstraw.h"
  42. /***********************************************************************************************
  43. * PKey::PKey -- Construct a key using encoded strings. *
  44. * *
  45. * This constructor will construct a key based on the encoded strings supplied. *
  46. * *
  47. * INPUT: exponent -- The encoded string for the exponent portion of the key. *
  48. * *
  49. * modulus -- The encoded string for the modulus portion of the key. *
  50. * *
  51. * OUTPUT: none *
  52. * *
  53. * WARNINGS: none *
  54. * *
  55. * HISTORY: *
  56. * 07/08/1996 JLB : Created. *
  57. *=============================================================================================*/
  58. PKey::PKey(void const * exponent, void const * modulus)
  59. {
  60. Modulus.DERDecode((unsigned char *)modulus);
  61. Exponent.DERDecode((unsigned char *)exponent);
  62. BitPrecision = Modulus.BitCount()-1;
  63. }
  64. /***********************************************************************************************
  65. * PKey::Encode_Modulus -- Encode the modulus portion of the key. *
  66. * *
  67. * This will store the modulus portion of the key into a buffer. The number of bytes *
  68. * stored into the buffer depends on the value of the key. *
  69. * *
  70. * INPUT: buffer -- Pointer to the buffer that will hold the encoded modulus value. *
  71. * *
  72. * OUTPUT: Returns with the number of bytes stored to the buffer. *
  73. * *
  74. * WARNINGS: Be sure that the buffer can hold the encoded bytes. This is normally around the *
  75. * same size as the Crypt_Block_Size() (plus a byte or two). *
  76. * *
  77. * HISTORY: *
  78. * 07/08/1996 JLB : Created. *
  79. *=============================================================================================*/
  80. int PKey::Encode_Modulus(void * buffer) const
  81. {
  82. if (buffer == NULL) {
  83. return(0);
  84. }
  85. return(Modulus.DEREncode((unsigned char *)buffer));
  86. }
  87. /***********************************************************************************************
  88. * PKey::Encode_Exponent -- Encode the exponent portion of the key into a buffer. *
  89. * *
  90. * This routine will encode the exponent portion of the key. This is only necessary for the *
  91. * slow key since the fast key always has an exponent of 65537. *
  92. * *
  93. * INPUT: buffer -- Pointer to the buffer that will be filled with the encoded exponent. *
  94. * *
  95. * OUTPUT: Returns with the nuber of bytes stored into the buffer. *
  96. * *
  97. * WARNINGS: Be sure the buffer is big enough to hold the encoded exponent. Usually this is *
  98. * about the same size as the Crypt_Block_Size (plus a byte or two). *
  99. * *
  100. * HISTORY: *
  101. * 07/08/1996 JLB : Created. *
  102. *=============================================================================================*/
  103. int PKey::Encode_Exponent(void * buffer) const
  104. {
  105. if (buffer == NULL) {
  106. return(0);
  107. }
  108. return(Exponent.DEREncode((unsigned char *)buffer));
  109. }
  110. /***********************************************************************************************
  111. * PKey::Decode_Modulus -- Decodes the modulus value back into the key. *
  112. * *
  113. * This is the counterpart to the Encode_Modulus() function. It will initialize the *
  114. * modulus portion of the key with the encoded data supplied. *
  115. * *
  116. * INPUT: buffer -- Pointer to the buffer that holds the previously encoded modulus value. *
  117. * *
  118. * OUTPUT: void *
  119. * *
  120. * WARNINGS: void *
  121. * *
  122. * HISTORY: *
  123. * 07/08/1996 JLB : Created. *
  124. *=============================================================================================*/
  125. void PKey::Decode_Modulus(void * buffer)
  126. {
  127. Modulus.DERDecode((unsigned char *)buffer);
  128. BitPrecision = Modulus.BitCount()-1;
  129. }
  130. /***********************************************************************************************
  131. * PKey::Decode_Exponent -- Decodes the exponent back into the key. *
  132. * *
  133. * This is the counterpart to the Encode_Exponent function. It will decode a previously *
  134. * encoded exponent portion back into the key. *
  135. * *
  136. * INPUT: buffer -- Pointer to the buffer that holds the encoded exponent value. *
  137. * *
  138. * OUTPUT: none *
  139. * *
  140. * WARNINGS: none *
  141. * *
  142. * HISTORY: *
  143. * 07/08/1996 JLB : Created. *
  144. *=============================================================================================*/
  145. void PKey::Decode_Exponent(void * buffer)
  146. {
  147. Exponent.DERDecode((unsigned char *)buffer);
  148. }
  149. /***********************************************************************************************
  150. * PKey::Generate -- Generate a public and private key. *
  151. * *
  152. * Public key cryptography relies on having two paired keys. The key used to encrypt *
  153. * data must be decrypted by using the other key. Which key designated as the public or *
  154. * private key is arbitrary. However, one is faster than the other. Use the faster key for *
  155. * the more common operation. *
  156. * *
  157. * INPUT: random -- Reference to a source of random data. *
  158. * *
  159. * bits -- The number of bits to use for key generation. Use a number greater *
  160. * than 16 but less than 2048. The ideal bit size is one that is evenly *
  161. * divisible by 8 and then add one. Practical numbers range from 65 to *
  162. * 1025 bits. *
  163. * *
  164. * fastkey -- Reference to the key that has fast encryption/decryption properties. *
  165. * *
  166. * slowkey -- Reference to the mate key of the other. *
  167. * *
  168. * OUTPUT: none *
  169. * *
  170. * WARNINGS: This routine can take a very long time. It can take MINUTES to generate a *
  171. * 1024 bit key (even on a Pentium Pro 200Mghz machine). *
  172. * *
  173. * HISTORY: *
  174. * 07/05/1996 JLB : Created. *
  175. * 07/10/1996 JLB : Must supply source of random data. *
  176. *=============================================================================================*/
  177. void PKey::Generate(Straw & random, int bits, PKey & fastkey, PKey & slowkey)
  178. {
  179. //PG_TO_FIX
  180. fastkey;
  181. slowkey;
  182. #if (0)
  183. /*
  184. ** Key generation consists of create a key pair and then testing the key
  185. ** pair. If the test fails, then repeat the process. The test and repeat
  186. ** method is required since the prime number generating process can't
  187. ** guarantee the generation of a prime number -- it can only generate a
  188. ** highly likely prime number.
  189. */
  190. for (;;) {
  191. /*
  192. ** Generate the two random prime numbers. This is the longest
  193. ** step.
  194. */
  195. BigInt p = Generate_Prime(random, bits, &p);
  196. BigInt q = Generate_Prime(random, bits, &q);
  197. /*
  198. ** The exponent factors are easy to calculate from the prime numbers.
  199. */
  200. BigInt e = Fast_Exponent();
  201. BigInt n = p * q;
  202. BigInt pqmin = (p-(unsigned short)1)*(q-(unsigned short)1);
  203. BigInt d = e.Inverse(pqmin);
  204. /*
  205. ** Store the data into the key objects. Notice that the modulus is the
  206. ** same for both the fast and slow keys. Also notice that the exponent for
  207. ** the fast key is ALWAYS 65537. Given this, it is possible to economize the
  208. ** fast key into being just the modulus and the slow key to being just the
  209. ** exponent (presuming the slow key also has access to the fast key so that
  210. ** it can get the modulus).
  211. */
  212. fastkey.Exponent = e;
  213. fastkey.Modulus = n;
  214. fastkey.BitPrecision = n.BitCount()-1;
  215. slowkey.Exponent = d;
  216. slowkey.Modulus = n;
  217. slowkey.BitPrecision = fastkey.BitPrecision;
  218. /*
  219. ** Test the keys by encrypting a block of random bytes. If it decrypts
  220. ** correctly, then a valid key pair has been generated -- bail.
  221. */
  222. char before[256];
  223. char after[256];
  224. for (int index = 0; index < fastkey.Plain_Block_Size(); index++) {
  225. before[index] = (char)rand();
  226. }
  227. fastkey.Encrypt(before, fastkey.Plain_Block_Size(), after);
  228. slowkey.Decrypt(after, slowkey.Crypt_Block_Size(), after);
  229. /*
  230. ** Compare the pre and post processing buffer. A match indicates
  231. ** a valid key pair.
  232. */
  233. if (memcmp(before, after, fastkey.Plain_Block_Size()) == 0) break;
  234. }
  235. #endif
  236. }
  237. /***********************************************************************************************
  238. * PKey::Encrypt -- Encrypt blocks of plaintext. *
  239. * *
  240. * This routine will encrypt the supplied plaintext into cyphertext by processing the input *
  241. * in block. The source is processed in whole blocks. Partial blocks are not supported by *
  242. * public key cryptography. *
  243. * *
  244. * INPUT: source -- Pointer to the source plaintext that will be encrypted. *
  245. * *
  246. * length -- The length of the plaintext to encrypt. *
  247. * *
  248. * dest -- Pointer to the buffer that will hold the encrypted data. *
  249. * *
  250. * OUTPUT: Returns with the number of cypher text bytes placed into the destination buffer. *
  251. * *
  252. * WARNINGS: Be sure that the destination buffer is big enough to hold the output. *
  253. * *
  254. * HISTORY: *
  255. * 07/05/1996 JLB : Created. *
  256. *=============================================================================================*/
  257. int PKey::Encrypt(void const * source, int slen, void * dest) const
  258. {
  259. int total = 0;
  260. /*
  261. ** Encrypt the source data in full blocks. Partial blocks are not processed and are not
  262. ** copied to the destination buffer.
  263. */
  264. while (slen >= Plain_Block_Size()) {
  265. /*
  266. ** Perform the encryption of the block.
  267. */
  268. BigInt temp = 0;
  269. memmove(&temp, source, Plain_Block_Size());
  270. temp = temp.exp_b_mod_c(Exponent, Modulus);
  271. /*
  272. ** Move the cypher block to the destination.
  273. */
  274. memmove(dest, &temp, Crypt_Block_Size());
  275. slen -= Plain_Block_Size();
  276. source = (char *)source + Plain_Block_Size();
  277. dest = (char *)dest + Crypt_Block_Size();
  278. total += Crypt_Block_Size();
  279. }
  280. return(total);
  281. }
  282. /***********************************************************************************************
  283. * PKey::Decrypt -- Decrypt supplied cyphertext into its original plaintext. *
  284. * *
  285. * This routine will process the supplied cyphertext by breaking it up into blocks and *
  286. * then decrypting each block in turn. The block size is dependant upon the key. By NOT *
  287. * embedding this information into the cypher data, it makes the encryption more secure. *
  288. * *
  289. * INPUT: source -- Pointer to the cypher text to be decrypted. *
  290. * *
  291. * length -- The number of cypher text bytes supplied to this routine. *
  292. * *
  293. * dest -- Pointer to the buffer to hold the plaintext. *
  294. * *
  295. * OUTPUT: Returns with the number of plaintext bytes output to the destination buffer. *
  296. * *
  297. * WARNINGS: Only whole blocks are processed. If the source has any partial block sized *
  298. * data, then it will be left unprocessed. *
  299. * *
  300. * HISTORY: *
  301. * 07/05/1996 JLB : Created. *
  302. *=============================================================================================*/
  303. int PKey::Decrypt(void const * source, int slen, void * dest) const
  304. {
  305. int total = 0;
  306. BigInt temp;
  307. /*
  308. ** Decrypt the source data in full blocks. Partial blocks are not processed in any way.
  309. */
  310. while (slen >= Crypt_Block_Size()) {
  311. /*
  312. ** Perform the encryption.
  313. */
  314. temp = 0;
  315. memmove(&temp, source, Crypt_Block_Size());
  316. temp = temp.exp_b_mod_c(Exponent, Modulus);
  317. /*
  318. ** Move the cypher block to the destination.
  319. */
  320. memmove(dest, &temp, Plain_Block_Size());
  321. slen -= Crypt_Block_Size();
  322. source = (char *)source + Crypt_Block_Size();
  323. dest = (char *)dest + Plain_Block_Size();
  324. total += Plain_Block_Size();
  325. }
  326. return(total);
  327. }