PK.CPP 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  1. /*
  2. ** Command & Conquer Red Alert(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /* $Header: /CounterStrike/PK.CPP 1 3/03/97 10:25a Joe_bostic $ */
  19. /***********************************************************************************************
  20. *** 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 ***
  21. ***********************************************************************************************
  22. * *
  23. * Project Name : Command & Conquer *
  24. * *
  25. * File Name : PK.CPP *
  26. * *
  27. * Programmer : Joe L. Bostic *
  28. * *
  29. * Start Date : 07/04/96 *
  30. * *
  31. * Last Update : July 10, 1996 [JLB] *
  32. * *
  33. *---------------------------------------------------------------------------------------------*
  34. * Functions: *
  35. * PKey::Decode_Exponent -- Decodes the exponent back into the key. *
  36. * PKey::Decode_Modulus -- Decodes the modulus value back into the key. *
  37. * PKey::Decrypt -- Decrypt supplied cyphertext into its original plaintext. *
  38. * PKey::Encode_Exponent -- Encode the exponent portion of the key into a buffer. *
  39. * PKey::Encode_Modulus -- Encode the modulus portion of the key. *
  40. * PKey::Encrypt -- Encrypt blocks of plaintext. *
  41. * PKey::Generate -- Generate a public and private key. *
  42. * PKey::PKey -- Construct a key using encoded strings. *
  43. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  44. #include "pk.h"
  45. #include "rndstraw.h"
  46. /***********************************************************************************************
  47. * PKey::PKey -- Construct a key using encoded strings. *
  48. * *
  49. * This constructor will construct a key based on the encoded strings supplied. *
  50. * *
  51. * INPUT: exponent -- The encoded string for the exponent portion of the key. *
  52. * *
  53. * modulus -- The encoded string for the modulus portion of the key. *
  54. * *
  55. * OUTPUT: none *
  56. * *
  57. * WARNINGS: none *
  58. * *
  59. * HISTORY: *
  60. * 07/08/1996 JLB : Created. *
  61. *=============================================================================================*/
  62. PKey::PKey(void const * exponent, void const * modulus)
  63. {
  64. Modulus.DERDecode((unsigned char *)modulus);
  65. Exponent.DERDecode((unsigned char *)exponent);
  66. BitPrecision = Modulus.BitCount()-1;
  67. }
  68. /***********************************************************************************************
  69. * PKey::Encode_Modulus -- Encode the modulus portion of the key. *
  70. * *
  71. * This will store the modulus portion of the key into a buffer. The number of bytes *
  72. * stored into the buffer depends on the value of the key. *
  73. * *
  74. * INPUT: buffer -- Pointer to the buffer that will hold the encoded modulus value. *
  75. * *
  76. * OUTPUT: Returns with the number of bytes stored to the buffer. *
  77. * *
  78. * WARNINGS: Be sure that the buffer can hold the encoded bytes. This is normally around the *
  79. * same size as the Crypt_Block_Size() (plus a byte or two). *
  80. * *
  81. * HISTORY: *
  82. * 07/08/1996 JLB : Created. *
  83. *=============================================================================================*/
  84. int PKey::Encode_Modulus(void * buffer) const
  85. {
  86. if (buffer == NULL) {
  87. return(0);
  88. }
  89. return(Modulus.DEREncode((unsigned char *)buffer));
  90. }
  91. /***********************************************************************************************
  92. * PKey::Encode_Exponent -- Encode the exponent portion of the key into a buffer. *
  93. * *
  94. * This routine will encode the exponent portion of the key. This is only necessary for the *
  95. * slow key since the fast key always has an exponent of 65537. *
  96. * *
  97. * INPUT: buffer -- Pointer to the buffer that will be filled with the encoded exponent. *
  98. * *
  99. * OUTPUT: Returns with the nuber of bytes stored into the buffer. *
  100. * *
  101. * WARNINGS: Be sure the buffer is big enough to hold the encoded exponent. Usually this is *
  102. * about the same size as the Crypt_Block_Size (plus a byte or two). *
  103. * *
  104. * HISTORY: *
  105. * 07/08/1996 JLB : Created. *
  106. *=============================================================================================*/
  107. int PKey::Encode_Exponent(void * buffer) const
  108. {
  109. if (buffer == NULL) {
  110. return(0);
  111. }
  112. return(Exponent.DEREncode((unsigned char *)buffer));
  113. }
  114. /***********************************************************************************************
  115. * PKey::Decode_Modulus -- Decodes the modulus value back into the key. *
  116. * *
  117. * This is the counterpart to the Encode_Modulus() function. It will initialize the *
  118. * modulus portion of the key with the encoded data supplied. *
  119. * *
  120. * INPUT: buffer -- Pointer to the buffer that holds the previously encoded modulus value. *
  121. * *
  122. * OUTPUT: void *
  123. * *
  124. * WARNINGS: void *
  125. * *
  126. * HISTORY: *
  127. * 07/08/1996 JLB : Created. *
  128. *=============================================================================================*/
  129. void PKey::Decode_Modulus(void * buffer)
  130. {
  131. Modulus.DERDecode((unsigned char *)buffer);
  132. BitPrecision = Modulus.BitCount()-1;
  133. }
  134. /***********************************************************************************************
  135. * PKey::Decode_Exponent -- Decodes the exponent back into the key. *
  136. * *
  137. * This is the counterpart to the Encode_Exponent function. It will decode a previously *
  138. * encoded exponent portion back into the key. *
  139. * *
  140. * INPUT: buffer -- Pointer to the buffer that holds the encoded exponent value. *
  141. * *
  142. * OUTPUT: none *
  143. * *
  144. * WARNINGS: none *
  145. * *
  146. * HISTORY: *
  147. * 07/08/1996 JLB : Created. *
  148. *=============================================================================================*/
  149. void PKey::Decode_Exponent(void * buffer)
  150. {
  151. Exponent.DERDecode((unsigned char *)buffer);
  152. }
  153. /***********************************************************************************************
  154. * PKey::Generate -- Generate a public and private key. *
  155. * *
  156. * Public key cryptography relies on having two paired keys. The key used to encrypt *
  157. * data must be decrypted by using the other key. Which key designated as the public or *
  158. * private key is arbitrary. However, one is faster than the other. Use the faster key for *
  159. * the more common operation. *
  160. * *
  161. * INPUT: random -- Reference to a source of random data. *
  162. * *
  163. * bits -- The number of bits to use for key generation. Use a number greater *
  164. * than 16 but less than 2048. The ideal bit size is one that is evenly *
  165. * divisible by 8 and then add one. Practical numbers range from 65 to *
  166. * 1025 bits. *
  167. * *
  168. * fastkey -- Reference to the key that has fast encryption/decryption properties. *
  169. * *
  170. * slowkey -- Reference to the mate key of the other. *
  171. * *
  172. * OUTPUT: none *
  173. * *
  174. * WARNINGS: This routine can take a very long time. It can take MINUTES to generate a *
  175. * 1024 bit key (even on a Pentium Pro 200Mghz machine). *
  176. * *
  177. * HISTORY: *
  178. * 07/05/1996 JLB : Created. *
  179. * 07/10/1996 JLB : Must supply source of random data. *
  180. *=============================================================================================*/
  181. void PKey::Generate(Straw & random, int bits, PKey & fastkey, PKey & slowkey)
  182. {
  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. }
  236. /***********************************************************************************************
  237. * PKey::Encrypt -- Encrypt blocks of plaintext. *
  238. * *
  239. * This routine will encrypt the supplied plaintext into cyphertext by processing the input *
  240. * in block. The source is processed in whole blocks. Partial blocks are not supported by *
  241. * public key cryptography. *
  242. * *
  243. * INPUT: source -- Pointer to the source plaintext that will be encrypted. *
  244. * *
  245. * length -- The length of the plaintext to encrypt. *
  246. * *
  247. * dest -- Pointer to the buffer that will hold the encrypted data. *
  248. * *
  249. * OUTPUT: Returns with the number of cypher text bytes placed into the destination buffer. *
  250. * *
  251. * WARNINGS: Be sure that the destination buffer is big enough to hold the output. *
  252. * *
  253. * HISTORY: *
  254. * 07/05/1996 JLB : Created. *
  255. *=============================================================================================*/
  256. int PKey::Encrypt(void const * source, int slen, void * dest) const
  257. {
  258. int total = 0;
  259. /*
  260. ** Encrypt the source data in full blocks. Partial blocks are not processed and are not
  261. ** copied to the destination buffer.
  262. */
  263. while (slen >= Plain_Block_Size()) {
  264. /*
  265. ** Perform the encryption of the block.
  266. */
  267. BigInt temp = 0;
  268. memmove(&temp, source, Plain_Block_Size());
  269. temp = temp.exp_b_mod_c(Exponent, Modulus);
  270. /*
  271. ** Move the cypher block to the destination.
  272. */
  273. memmove(dest, &temp, Crypt_Block_Size());
  274. slen -= Plain_Block_Size();
  275. source = (char *)source + Plain_Block_Size();
  276. dest = (char *)dest + Crypt_Block_Size();
  277. total += Crypt_Block_Size();
  278. }
  279. return(total);
  280. }
  281. /***********************************************************************************************
  282. * PKey::Decrypt -- Decrypt supplied cyphertext into its original plaintext. *
  283. * *
  284. * This routine will process the supplied cyphertext by breaking it up into blocks and *
  285. * then decrypting each block in turn. The block size is dependant upon the key. By NOT *
  286. * embedding this information into the cypher data, it makes the encryption more secure. *
  287. * *
  288. * INPUT: source -- Pointer to the cypher text to be decrypted. *
  289. * *
  290. * length -- The number of cypher text bytes supplied to this routine. *
  291. * *
  292. * dest -- Pointer to the buffer to hold the plaintext. *
  293. * *
  294. * OUTPUT: Returns with the number of plaintext bytes output to the destination buffer. *
  295. * *
  296. * WARNINGS: Only whole blocks are processed. If the source has any partial block sized *
  297. * data, then it will be left unprocessed. *
  298. * *
  299. * HISTORY: *
  300. * 07/05/1996 JLB : Created. *
  301. *=============================================================================================*/
  302. int PKey::Decrypt(void const * source, int slen, void * dest) const
  303. {
  304. int total = 0;
  305. BigInt temp;
  306. /*
  307. ** Decrypt the source data in full blocks. Partial blocks are not processed in any way.
  308. */
  309. while (slen >= Crypt_Block_Size()) {
  310. /*
  311. ** Perform the encryption.
  312. */
  313. temp = 0;
  314. memmove(&temp, source, Crypt_Block_Size());
  315. temp = temp.exp_b_mod_c(Exponent, Modulus);
  316. /*
  317. ** Move the cypher block to the destination.
  318. */
  319. memmove(dest, &temp, Plain_Block_Size());
  320. slen -= Crypt_Block_Size();
  321. source = (char *)source + Crypt_Block_Size();
  322. dest = (char *)dest + Plain_Block_Size();
  323. total += Plain_Block_Size();
  324. }
  325. return(total);
  326. }