PKSTRAW.CPP 17 KB

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