Richard Boegli's CnC_Generals_Zero_Hour Fork WIP
This is documentation of Richard Boegil's Zero Hour Fork
 
Loading...
Searching...
No Matches
sha.cpp
Go to the documentation of this file.
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/***********************************************************************************************
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 * $Archive:: /Commando/Library/SHA.CPP $*
26 * *
27 * $Author:: Greg_h $*
28 * *
29 * $Modtime:: 7/22/97 11:37a $*
30 * *
31 * $Revision:: 1 $*
32 * *
33 *---------------------------------------------------------------------------------------------*
34 * Functions: *
35 * SHAEngine::Result -- Fetch the current digest. *
36 * SHAEngine::Hash -- Process an arbitrarily long data block. *
37 * SHAEngine::Process_Partial -- Helper routine to process any partially accumulated data blo*
38 * SHAEngine::Process_Block -- Process a full data block into the hash accumulator. *
39 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
40
41#include "sha.h"
42#include <iostream.h>
43#include <stdlib.h>
44
45
46#if !defined(__BORLANDC__) && !defined(min)
47#define min(a, b) ((a)<(b))?(a):(b)
48#endif
49
50
51/***********************************************************************************************
52 * SHAEngine::Process_Partial -- Helper routine to process any partially accumulated data bloc *
53 * *
54 * This routine will see if there is a partial block already accumulated in the holding *
55 * buffer. If so, then the data is fetched from the source such that a full buffer is *
56 * accumulated and then processed. If there is insufficient data to fill the buffer, then *
57 * it accumulates what data it can and then returns so that this routine can be called *
58 * again later. *
59 * *
60 * INPUT: data -- Reference to a pointer to the data. This pointer will be modified if *
61 * this routine consumes any of the data in the buffer. *
62 * *
63 * length-- Reference to the length of the data available. If this routine consumes *
64 * any of the data, then this length value will be modified. *
65 * *
66 * OUTPUT: none *
67 * *
68 * WARNINGS: none *
69 * *
70 * HISTORY: *
71 * 07/03/1996 JLB : Created. *
72 *=============================================================================================*/
73void SHAEngine::Process_Partial(void const * & data, long & length)
74{
75 if (length == 0 || data == NULL) return;
76
77 /*
78 ** If there is no partial buffer and the source is greater than
79 ** a source block size, then partial processing is unnecessary.
80 ** Bail out in this case.
81 */
82 if (PartialCount == 0 && length >= SRC_BLOCK_SIZE) return;
83
84 /*
85 ** Attach as many bytes as possible from the source data into
86 ** the staging buffer.
87 */
88 int add_count = min((int)length, SRC_BLOCK_SIZE - PartialCount);
89 memcpy(&Partial[PartialCount], data, add_count);
90 data = ((char const *&)data) + add_count;
91 PartialCount += add_count;
92 length -= add_count;
93
94 /*
95 ** If a full staging buffer has been accumulated, then process
96 ** the staging buffer and then bail.
97 */
98 if (PartialCount == SRC_BLOCK_SIZE) {
99 Process_Block(&Partial[0], Acc);
100 Length += (long)SRC_BLOCK_SIZE;
101 PartialCount = 0;
102 }
103}
104
105
106/***********************************************************************************************
107 * SHAEngine::Hash -- Process an arbitrarily long data block. *
108 * *
109 * This is the main access routine to the SHA engine. It will take the arbitrarily long *
110 * data block and process it. The hash value is accumulated with any previous calls to *
111 * this routine. *
112 * *
113 * INPUT: data -- Pointer to the data block to process. *
114 * *
115 * length -- The number of bytes to process. *
116 * *
117 * OUTPUT: none *
118 * *
119 * WARNINGS: none *
120 * *
121 * HISTORY: *
122 * 07/03/1996 JLB : Created. *
123 *=============================================================================================*/
124void SHAEngine::Hash(void const * data, long length)
125{
126 IsCached = false;
127
128 /*
129 ** Check for and handle any smaller-than-512bit blocks. This can
130 ** result in all of the source data submitted to this routine to be
131 ** consumed at this point.
132 */
133 Process_Partial(data, length);
134
135 /*
136 ** If there is no more source data to process, then bail. Speed reasons.
137 */
138 if (length == 0) return;
139
140 /*
141 ** First process all the whole blocks available in the source data.
142 */
143 long blocks = (length / SRC_BLOCK_SIZE);
144 long const * source = (long const *)data;
145 for (int bcount = 0; bcount < blocks; bcount++) {
146 Process_Block(source, Acc);
147 Length += (long)SRC_BLOCK_SIZE;
148 source += SRC_BLOCK_SIZE/sizeof(long);
149 length -= (long)SRC_BLOCK_SIZE;
150 }
151
152 /*
153 ** Process any remainder bytes. This data is stored in the source
154 ** accumulator buffer for future processing.
155 */
156 data = source;
157 Process_Partial(data, length);
158}
159
160
161#define Reverse_LONG(a) ((a>>24)&0x000000FFL) | ((a>>8)&0x0000FF00L) | ((a<<8)&0x00FF0000L) | ((a<<24)&0xFF000000L)
162
163
164/***********************************************************************************************
165 * SHAEngine::Result -- Fetch the current digest. *
166 * *
167 * This routine will return the digest as it currently stands. *
168 * *
169 * INPUT: pointer -- Pointer to the buffer that will hold the digest -- 20 bytes. *
170 * *
171 * OUTPUT: Returns with the number of bytes copied into the buffer. This will always be *
172 * 20. *
173 * *
174 * WARNINGS: none *
175 * *
176 * HISTORY: *
177 * 07/03/1996 JLB : Created. *
178 *=============================================================================================*/
179int SHAEngine::Result(void * result) const
180{
181 /*
182 ** If the final hash result has already been calculated for the
183 ** current data state, then immediately return with the precalculated
184 ** value.
185 */
186 if (IsCached) {
187 memcpy(result, &FinalResult, sizeof(FinalResult));
188 }
189
190 long length = Length + PartialCount;
191 int partialcount = PartialCount;
192 unsigned char partial[SRC_BLOCK_SIZE];
193 memcpy(partial, Partial, sizeof(Partial));
194
195 /*
196 ** Cap the end of the source data stream with a 1 bit.
197 */
198 partial[partialcount] = (unsigned char)0x80;
199
200 /*
201 ** Determine if there is insufficient room to append the
202 ** data length number to the hash source. If not, then
203 ** fill out the rest of the accumulator and flush it to
204 ** the hash so that there will be room for the final
205 ** count value.
206 */
207 SHADigest acc = Acc;
208 if ((SRC_BLOCK_SIZE - partialcount) < 9) {
209 if (partialcount+1 < SRC_BLOCK_SIZE) {
210 memset(&partial[partialcount+1], '\0', SRC_BLOCK_SIZE - (partialcount+1));
211 }
212 Process_Block(&partial[0], acc);
213 partialcount = 0;
214 } else {
215 partialcount++;
216 }
217
218 /*
219 ** Put the length of the source data as a 64 bit integer in the
220 ** last 8 bytes of the pseudo-source data.
221 */
222 memset(&partial[partialcount], '\0', SRC_BLOCK_SIZE - partialcount);
223 *(long *)(&partial[SRC_BLOCK_SIZE-4]) = Reverse_LONG((length*8));
224 Process_Block(&partial[0], acc);
225
226 memcpy((char *)&FinalResult, &acc, sizeof(acc));
227 for (int index = 0; index < sizeof(FinalResult)/sizeof(long); index++) {
228// for (int index = 0; index < SRC_BLOCK_SIZE/sizeof(long); index++) {
229 (long &)FinalResult.Long[index] = Reverse_LONG(FinalResult.Long[index]);
230 }
231 (bool&)IsCached = true;
232 memcpy(result, &FinalResult, sizeof(FinalResult));
233 return(sizeof(FinalResult));
234}
235
236/*
237** This pragma to turn off the warning "Conversion may lose significant digits" is to
238** work around a bug within the Borland compiler. It will give this warning when the
239** _rotl() function is called but will NOT give the warning when the _lrotl() function
240** is called even though they both have the same parameters and declaration attributes.
241*/
242#ifdef __BORLANDC__
243#pragma warn -sig
244#endif
245
246template<class T>
247T _rotl(T X, int n)
248{
249 return(T)( ( X << n ) | ( (unsigned)X >> ((sizeof(T)*8) - n) ) );
250}
251inline long _rotl(long X, int n)
252{
253 return(long)( ( X << n ) | ( (unsigned)X >> ((sizeof(long)*8) - n) ) );
254}
255
256inline unsigned long _rotl(unsigned long X, int n)
257{
258 return(unsigned long)( ( X << n ) | ( (unsigned)X >> ((sizeof(unsigned long)*8) - n) ) );
259}
260
261//unsigned long _RTLENTRY _rotl(unsigned long X, int n)
262//{
263// return(unsigned long)( (unsigned long)( (unsigned long)( (unsigned long)X ) << (int)n ) | (unsigned long)( ((unsigned long) X ) >> ( (int)((int)(sizeof(long)*(long)8) - (long)n) ) ) );
264//}
265void memrev(char * buffer, size_t length);
266
267
268/***********************************************************************************************
269 * SHAEngine::Process_Block -- Process a full data block into the hash accumulator. *
270 * *
271 * This helper routine is called when a full block of data is available for processing *
272 * into the hash. *
273 * *
274 * INPUT: source -- Pointer to the block of data to process. *
275 * *
276 * acc -- Reference to the hash accumulator that this hash step will be *
277 * accumulated into. *
278 * *
279 * OUTPUT: none *
280 * *
281 * WARNINGS: none *
282 * *
283 * HISTORY: *
284 * 07/03/1996 JLB : Created. *
285 *=============================================================================================*/
286void SHAEngine::Process_Block(void const * source, SHADigest & acc) const
287{
288 /*
289 ** The hash is generated by performing operations on a
290 ** block of generated/seeded data.
291 */
292 long block[PROC_BLOCK_SIZE/sizeof(long)];
293
294 /*
295 ** Expand the source data into a large 80 * 32bit buffer. This is the working
296 ** data that will be transformed by the secure hash algorithm.
297 */
298 long const * data = (long const *)source;
299 int index;
300 for (index = 0; index < SRC_BLOCK_SIZE/sizeof(long); index++) {
301 block[index] = Reverse_LONG(data[index]);
302 }
303
304 for (index = SRC_BLOCK_SIZE/sizeof(long); index < PROC_BLOCK_SIZE/sizeof(long); index++) {
305// block[index] = _rotl(block[(index-3)&15] ^ block[(index-8)&15] ^ block[(index-14)&15] ^ block[(index-16)&15], 1);
306 block[index] = _rotl(block[index-3] ^ block[index-8] ^ block[index-14] ^ block[index-16], 1);
307 }
308
309 /*
310 ** This is the core algorithm of the Secure Hash Algorithm. It is a block
311 ** transformation of 512 bit source data with a 2560 bit intermediate buffer.
312 */
313 SHADigest alt = acc;
314 for (index = 0; index < PROC_BLOCK_SIZE/sizeof(long); index++) {
315 long temp = _rotl(alt.Long[0], 5) + Do_Function(index, alt.Long[1], alt.Long[2], alt.Long[3]) + alt.Long[4] + block[index] + Get_Constant(index);
316 alt.Long[4] = alt.Long[3];
317 alt.Long[3] = alt.Long[2];
318 alt.Long[2] = _rotl(alt.Long[1], 30);
319 alt.Long[1] = alt.Long[0];
320 alt.Long[0] = temp;
321 }
322 acc.Long[0] += alt.Long[0];
323 acc.Long[1] += alt.Long[1];
324 acc.Long[2] += alt.Long[2];
325 acc.Long[3] += alt.Long[3];
326 acc.Long[4] += alt.Long[4];
327}
328
#define NULL
Definition BaseType.h:92
#define min(x, y)
Definition BaseType.h:101
UnicodeString alt
void Hash(void const *data, long length)
Definition sha.cpp:124
int Result(void *result) const
Definition sha.cpp:179
T _rotl(T X, int n)
Definition sha.cpp:247
void memrev(char *buffer, size_t length)
Definition mpmath.cpp:2227
#define Reverse_LONG(a)
Definition sha.cpp:161