PKSTRAW.CPP 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  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/PKSTRAW.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 : PKSTRAW.CPP *
  26. * *
  27. * Programmer : Joe L. Bostic *
  28. * *
  29. * Start Date : 07/08/96 *
  30. * *
  31. * Last Update : July 11, 1996 [JLB] *
  32. * *
  33. *---------------------------------------------------------------------------------------------*
  34. * Functions: *
  35. * PKStraw::Encrypted_Key_Length -- Fetch the encrypted key length. *
  36. * PKStraw::Get -- Fetch data and process it accordingly. *
  37. * PKStraw::Get_From -- Chains one straw to another. *
  38. * PKStraw::Key -- Assign a key to the cipher process straw. *
  39. * PKStraw::PKStraw -- Initialize the public key straw object. *
  40. * PKStraw::Plain_Key_Length -- Returns the number of bytes to encrypt key. *
  41. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  42. #include "pkstraw.h"
  43. #include "rndstraw.h"
  44. #include "blwstraw.h"
  45. /***********************************************************************************************
  46. * PKStraw::PKStraw -- Initialize the public key straw object. *
  47. * *
  48. * This constructs the public key straw object. The operation to perform (encrypt or *
  49. * decrypt) as well as a random number generator must be provided. *
  50. * *
  51. * INPUT: control -- What operation to perform on the data. Pass in either ENCRYPT or *
  52. * DECRYPT. *
  53. * *
  54. * rnd -- Reference to a random number straw that is used internally to *
  55. * generate the sub-key. The final strength of the cipher depends on *
  56. * quality of this random number generator. *
  57. * *
  58. * OUTPUT: none *
  59. * *
  60. * WARNINGS: none *
  61. * *
  62. * HISTORY: *
  63. * 07/11/1996 JLB : Created. *
  64. *=============================================================================================*/
  65. PKStraw::PKStraw(CryptControl control, RandomStraw & rnd) :
  66. IsGettingKey(true),
  67. Rand(rnd),
  68. BF((control == ENCRYPT) ? BlowStraw::ENCRYPT : BlowStraw::DECRYPT),
  69. Control(control),
  70. CipherKey(NULL),
  71. Counter(0),
  72. BytesLeft(0)
  73. {
  74. Straw::Get_From(BF);
  75. }
  76. /***********************************************************************************************
  77. * PKStraw::Get_From -- Chains one straw to another. *
  78. * *
  79. * This routine handles the special case of this straw object in that there is an *
  80. * embedded blowfish straw segment. It must be chained on correctly. *
  81. * *
  82. * INPUT: straw -- Pointer to the straw segment that this segment is to receive data from. *
  83. * *
  84. * OUTPUT: none *
  85. * *
  86. * WARNINGS: none *
  87. * *
  88. * HISTORY: *
  89. * 07/11/1996 JLB : Created. *
  90. *=============================================================================================*/
  91. void PKStraw::Get_From(Straw * straw)
  92. {
  93. if (BF.ChainTo != straw) {
  94. if (straw != NULL && straw->ChainFrom != NULL) {
  95. straw->ChainFrom->Get_From(NULL);
  96. straw->ChainFrom = NULL;
  97. }
  98. if (BF.ChainTo != NULL) {
  99. BF.ChainTo->ChainFrom = NULL;
  100. }
  101. BF.ChainTo = straw;
  102. BF.ChainFrom = this;
  103. ChainTo = &BF;
  104. if (BF.ChainTo != NULL) {
  105. BF.ChainTo->ChainFrom = this;
  106. }
  107. }
  108. }
  109. /***********************************************************************************************
  110. * PKStraw::Key -- Assign a key to the cipher process straw. *
  111. * *
  112. * This routine will assign the key (or NULL if the current key is to be removed) to the *
  113. * cipher stream process. When a key has been assigned, encryption or decryption will *
  114. * take place. In the absence (NULL key pointer) of a key, the data passes through *
  115. * unchanged. *
  116. * *
  117. * INPUT: key -- Pointer to the key to assign to the stream. If the key pointer is NULL, *
  118. * then this causes the cipher stream to stop processing the data and will *
  119. * pass the data through unchanged. *
  120. * *
  121. * OUTPUT: none *
  122. * *
  123. * WARNINGS: Be sure that the key passed to this routine is the opposite key to that used *
  124. * to process the stream originally (when decrypting). *
  125. * *
  126. * HISTORY: *
  127. * 07/08/1996 JLB : Created. *
  128. *=============================================================================================*/
  129. void PKStraw::Key(PKey const * key)
  130. {
  131. CipherKey = key;
  132. if (key != NULL) {
  133. IsGettingKey = true;
  134. }
  135. Counter = 0;
  136. BytesLeft = 0;
  137. }
  138. /***********************************************************************************************
  139. * PKStraw::Get -- Fetch data and process it accordingly. *
  140. * *
  141. * This routine will fetch the number of bytes requested. If a valid key has been assigned *
  142. * to this stream, then the data will be processed as it passes through. *
  143. * *
  144. * INPUT: source -- Pointer to the buffer that will hold the requested data. *
  145. * *
  146. * length -- The number of data bytes requested. *
  147. * *
  148. * OUTPUT: Returns with the actual number of data bytes stored to the destination buffer. If *
  149. * this number is less than that requested, then it indicates that the data source *
  150. * has been exhausted. *
  151. * *
  152. * WARNINGS: none *
  153. * *
  154. * HISTORY: *
  155. * 07/08/1996 JLB : Created. *
  156. *=============================================================================================*/
  157. int PKStraw::Get(void * source, int length)
  158. {
  159. /*
  160. ** If the parameters seem invalid, then pass the request on so that someone
  161. ** else can deal with it.
  162. */
  163. if (source == NULL || length < 1 || CipherKey == NULL) {
  164. return(Straw::Get(source, length));
  165. }
  166. int total = 0;
  167. /*
  168. ** The first part of the data flow must process the special key. After the special
  169. ** key has been processed, the data flows through this straw without direct
  170. ** modification (the blowfish straw will process the data).
  171. */
  172. if (IsGettingKey) {
  173. if (Control == DECRYPT) {
  174. /*
  175. ** Retrieve the pk encrypted blowfish key block.
  176. */
  177. char cbuffer[MAX_KEY_BLOCK_SIZE];
  178. int got = Straw::Get(cbuffer, Encrypted_Key_Length());
  179. /*
  180. ** If the entire key block could not be retrieved, then this indicates
  181. ** a major data flow error -- just return with no action performed.
  182. */
  183. if (got != Encrypted_Key_Length()) return(0);
  184. /*
  185. ** Decrypt the blowfish key and then activate the blowfish straw
  186. ** with that key.
  187. */
  188. CipherKey->Decrypt(cbuffer, got, Buffer);
  189. BF.Key(Buffer, BLOWFISH_KEY_SIZE);
  190. } else {
  191. /*
  192. ** Generate the blowfish key by using random numbers.
  193. */
  194. char buffer[MAX_KEY_BLOCK_SIZE];
  195. memset(buffer, '\0', sizeof(buffer));
  196. Rand.Get(buffer, BLOWFISH_KEY_SIZE);
  197. /*
  198. ** Encrypt the blowfish key (along with any necessary pad bytes).
  199. */
  200. Counter = BytesLeft = CipherKey->Encrypt(buffer, Plain_Key_Length(), Buffer);
  201. BF.Key(buffer, BLOWFISH_KEY_SIZE);
  202. }
  203. /*
  204. ** The first phase of getting the special key has been accomplished. Now, all
  205. ** subsequent data is passed (unmodified) though this straw segment. The blowfish
  206. ** straw takes over the compression/decompression from this point forward.
  207. */
  208. IsGettingKey = false;
  209. }
  210. /*
  211. ** If there are any pending bytes in the buffer, then pass
  212. ** these on first. The only time this should be is when the blowfish
  213. ** key has first been generated.
  214. */
  215. if (BytesLeft > 0) {
  216. int tocopy = (length < BytesLeft) ? length : BytesLeft;
  217. memmove(source, &Buffer[Counter-BytesLeft], tocopy);
  218. source = (char *)source + tocopy;
  219. BytesLeft -= tocopy;
  220. length -= tocopy;
  221. total += tocopy;
  222. }
  223. /*
  224. ** Any requested bytes that haven't been satisfied are copied over now by
  225. ** drawing the data through the blowfish engine. The blowfish engine happens
  226. ** to be linked to the chain so a normal Get() operation is sufficient.
  227. */
  228. total += Straw::Get(source, length);
  229. return(total);
  230. }
  231. /***********************************************************************************************
  232. * PKStraw::Encrypted_Key_Length -- Fetch the encrypted key length. *
  233. * *
  234. * This returns the total number of bytes (after encryption) that the blowfish key will *
  235. * consume. It should be possible to get a block of this size, then pass it to the *
  236. * public key decrypter and the result will be the full blowfish key. *
  237. * *
  238. * INPUT: none *
  239. * *
  240. * OUTPUT: Returns with the number of bytes that the encrypted blowfish key required. *
  241. * *
  242. * WARNINGS: none *
  243. * *
  244. * HISTORY: *
  245. * 07/11/1996 JLB : Created. *
  246. *=============================================================================================*/
  247. int PKStraw::Encrypted_Key_Length(void) const
  248. {
  249. if (CipherKey == NULL) return(0);
  250. return(CipherKey->Block_Count(BLOWFISH_KEY_SIZE) * CipherKey->Crypt_Block_Size());
  251. }
  252. /***********************************************************************************************
  253. * PKStraw::Plain_Key_Length -- Returns the number of bytes to encrypt key. *
  254. * *
  255. * This is the number of plain (unencrypted) bytes that the blowfish key will take up. This *
  256. * is actually the number of plain blocks minimum that can contain the full blowfish *
  257. * key. The public key cryptography system encrypts in whole blocks only. *
  258. * *
  259. * INPUT: none *
  260. * *
  261. * OUTPUT: Returns with the total number of bytes that will contain the full blowfish key *
  262. * and still be an even block size for the public key cryptography process. *
  263. * *
  264. * WARNINGS: This value is probably be larger than the actual blowfish key length. *
  265. * *
  266. * HISTORY: *
  267. * 07/11/1996 JLB : Created. *
  268. *=============================================================================================*/
  269. int PKStraw::Plain_Key_Length(void) const
  270. {
  271. if (CipherKey == NULL) return(0);
  272. return(CipherKey->Block_Count(BLOWFISH_KEY_SIZE) * CipherKey->Plain_Block_Size());
  273. }