pk.cpp 21 KB

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