pkstraw.cpp 17 KB

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