CnC_Remastered_Collection

Command and Conquer: Red Alert
Log | Files | Refs | README | LICENSE

SHA.CPP (16166B)


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