1 //
2 // SHA1Engine.cpp
3 //
4 // Library: Foundation
5 // Package: Crypt
6 // Module:  SHA1Engine
7 //
8 // Based on the public domain implementation by Peter C. Gutmann
9 // on 2 Sep 1992, modified by Carl Ellison to be SHA-1.
10 //
11 // Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
12 // and Contributors.
13 //
14 // SPDX-License-Identifier:	BSL-1.0
15 //
16 
17 
18 #include "Poco/SHA1Engine.h"
19 #include <cstring>
20 
21 
22 #ifdef POCO_ARCH_LITTLE_ENDIAN
23 	#define SHA1_BYTE_REVERSE(x, y) byteReverse(x, y)
24 #else
25 	#define SHA1_BYTE_REVERSE(x, y)
26 #endif
27 
28 
29 namespace Poco {
30 
31 
SHA1Engine()32 SHA1Engine::SHA1Engine()
33 {
34 	_digest.reserve(16);
35 	reset();
36 }
37 
38 
~SHA1Engine()39 SHA1Engine::~SHA1Engine()
40 {
41 	reset();
42 }
43 
44 
byteReverse(UInt32 * buffer,int byteCount)45 inline void SHA1Engine::byteReverse(UInt32* buffer, int byteCount)
46 {
47 #ifdef POCO_ARCH_LITTLE_ENDIAN
48 	byteCount /= sizeof(UInt32);
49 	for(int count = 0; count < byteCount; count++)
50 	{
51 		UInt32 value = (buffer[ count ] << 16) | (buffer[ count ] >> 16);
52 		buffer[count] = ((value & 0xFF00FF00L) >> 8) | ((value & 0x00FF00FFL) << 8);
53 	}
54 #endif // POCO_ARCH_LITTLE_ENDIAN
55 }
56 
57 
updateImpl(const void * buffer_,std::size_t count)58 void SHA1Engine::updateImpl(const void* buffer_, std::size_t count)
59 {
60 	const BYTE* buffer = (const BYTE*) buffer_;
61 	BYTE* db = (BYTE*) &_context.data[0];
62 
63 	/* Update bitcount */
64 	if ((_context.countLo + ((UInt32) count << 3)) < _context.countLo)
65 		_context.countHi++; /* Carry from low to high bitCount */
66 	_context.countLo += ((UInt32) count << 3);
67 	_context.countHi += ((UInt32 ) count >> 29);
68 
69 	/* Process data in BLOCK_SIZE chunks */
70 	while (count-- > 0)
71 	{
72 		db[_context.slop++] = *(buffer++);
73 		if (_context.slop == BLOCK_SIZE)
74 		{
75 			/* transform this one block */
76 			SHA1_BYTE_REVERSE(_context.data, BLOCK_SIZE);
77 			transform();
78 			_context.slop = 0 ;	/* no slop left */
79 		}
80 	}
81 }
82 
83 
digestLength() const84 std::size_t SHA1Engine::digestLength() const
85 {
86 	return DIGEST_SIZE;
87 }
88 
89 
reset()90 void SHA1Engine::reset()
91 {
92 	_context.digest[0] = 0x67452301L;
93 	_context.digest[1] = 0xEFCDAB89L;
94 	_context.digest[2] = 0x98BADCFEL;
95 	_context.digest[3] = 0x10325476L;
96 	_context.digest[4] = 0xC3D2E1F0L;
97 	_context.countLo   = 0;
98 	_context.countHi   = 0;
99 	_context.slop      = 0;
100 	std::memset(_context.data, 0, sizeof(_context.data));
101 }
102 
103 
digest()104 const DigestEngine::Digest& SHA1Engine::digest()
105 {
106 	int count;
107 	UInt32 lowBitcount  = _context.countLo;
108 	UInt32 highBitcount = _context.countHi;
109 
110 	/* Compute number of bytes mod 64 */
111 	count = (int) ((_context.countLo >> 3) & 0x3F);
112 
113 	/* Set the first char of padding to 0x80.  This is safe since there is
114 		always at least one byte free */
115 	((BYTE*) _context.data)[count++] = 0x80;
116 
117 	/* Pad out to 56 mod 64 */
118 	if (count > 56)
119 	{
120 		/* Two lots of padding:  Pad the first block to 64 bytes */
121 		std::memset((BYTE*) &_context.data + count, 0, 64 - count);
122 		SHA1_BYTE_REVERSE(_context.data, BLOCK_SIZE);
123 		transform();
124 
125 		/* Now fill the next block with 56 bytes */
126 		std::memset(&_context.data, 0, 56);
127 	}
128 	else
129 	{
130 		/* Pad block to 56 bytes */
131 		std::memset((BYTE*) &_context.data + count, 0, 56 - count);
132 	}
133 	SHA1_BYTE_REVERSE(_context.data, BLOCK_SIZE);
134 
135 	/* Append length in bits and transform */
136 	_context.data[14] = highBitcount;
137 	_context.data[15] = lowBitcount;
138 
139 	transform();
140 	SHA1_BYTE_REVERSE(_context.data, DIGEST_SIZE);
141 
142 	unsigned char hash[DIGEST_SIZE];
143 	for (count = 0; count < DIGEST_SIZE; count++)
144 		hash[count] = (BYTE) ((_context.digest[count>>2]) >> (8*(3-(count & 0x3)))) & 0xff;
145 	_digest.clear();
146 	_digest.insert(_digest.begin(), hash, hash + DIGEST_SIZE);
147 	reset();
148 	return _digest;
149 }
150 
151 
152 /* The SHA f()-functions */
153 #define f1(x,y,z)   ( ( x & y ) | ( ~x & z ) )              /* Rounds  0-19 */
154 #define f2(x,y,z)   ( x ^ y ^ z )                           /* Rounds 20-39 */
155 #define f3(x,y,z)   ( ( x & y ) | ( x & z ) | ( y & z ) )   /* Rounds 40-59 */
156 #define f4(x,y,z)   ( x ^ y ^ z )                           /* Rounds 60-79 */
157 
158 
159 /* The SHA Mysterious Constants */
160 #define K1  0x5A827999L     /* Rounds  0-19 */
161 #define K2  0x6ED9EBA1L     /* Rounds 20-39 */
162 #define K3  0x8F1BBCDCL     /* Rounds 40-59 */
163 #define K4  0xCA62C1D6L     /* Rounds 60-79 */
164 
165 
166 /* 32-bit rotate - kludged with shifts */
167 typedef UInt32 UL;	/* to save space */
168 
169 
170 #define S(n,X)  ( ( ((UL)X) << n ) | ( ((UL)X) >> ( 32 - n ) ) )
171 
172 
173 /* The initial expanding function */
174 #define expand(count)   W[ count ] = S(1,(W[ count - 3 ] ^ W[ count - 8 ] ^ W[ count - 14 ] ^ W[ count - 16 ]))	/* to make this SHA-1 */
175 
176 
177 /* The four SHA sub-rounds */
178 #define subRound1(count)    \
179 { \
180     temp = S( 5, A ) + f1( B, C, D ) + E + W[ count ] + K1; \
181     E = D; \
182     D = C; \
183     C = S( 30, B ); \
184     B = A; \
185     A = temp; \
186 }
187 
188 #define subRound2(count)    \
189 { \
190     temp = S( 5, A ) + f2( B, C, D ) + E + W[ count ] + K2; \
191     E = D; \
192     D = C; \
193     C = S( 30, B ); \
194     B = A; \
195     A = temp; \
196 }
197 
198 #define subRound3(count)    \
199 { \
200     temp = S( 5, A ) + f3( B, C, D ) + E + W[ count ] + K3; \
201     E = D; \
202     D = C; \
203     C = S( 30, B ); \
204     B = A; \
205     A = temp; \
206 }
207 
208 #define subRound4(count)    \
209 { \
210     temp = S( 5, A ) + f4( B, C, D ) + E + W[ count ] + K4; \
211     E = D; \
212     D = C; \
213     C = S( 30, B ); \
214     B = A; \
215     A = temp; \
216 }
217 
218 
transform()219 void SHA1Engine::transform()
220 {
221 	UInt32 W[80];
222 	UInt32 temp;
223 	UInt32 A, B, C, D, E;
224 	int i;
225 
226 	/* Step A.  Copy the data buffer into the local work buffer */
227 	for( i = 0; i < 16; i++ )
228 	W[ i ] = _context.data[ i ];
229 
230 	/* Step B.  Expand the 16 words into 64 temporary data words */
231 	expand( 16 ); expand( 17 ); expand( 18 ); expand( 19 ); expand( 20 );
232 	expand( 21 ); expand( 22 ); expand( 23 ); expand( 24 ); expand( 25 );
233 	expand( 26 ); expand( 27 ); expand( 28 ); expand( 29 ); expand( 30 );
234 	expand( 31 ); expand( 32 ); expand( 33 ); expand( 34 ); expand( 35 );
235 	expand( 36 ); expand( 37 ); expand( 38 ); expand( 39 ); expand( 40 );
236 	expand( 41 ); expand( 42 ); expand( 43 ); expand( 44 ); expand( 45 );
237 	expand( 46 ); expand( 47 ); expand( 48 ); expand( 49 ); expand( 50 );
238 	expand( 51 ); expand( 52 ); expand( 53 ); expand( 54 ); expand( 55 );
239 	expand( 56 ); expand( 57 ); expand( 58 ); expand( 59 ); expand( 60 );
240 	expand( 61 ); expand( 62 ); expand( 63 ); expand( 64 ); expand( 65 );
241 	expand( 66 ); expand( 67 ); expand( 68 ); expand( 69 ); expand( 70 );
242 	expand( 71 ); expand( 72 ); expand( 73 ); expand( 74 ); expand( 75 );
243 	expand( 76 ); expand( 77 ); expand( 78 ); expand( 79 );
244 
245 	/* Step C.  Set up first buffer */
246 	A = _context.digest[ 0 ];
247 	B = _context.digest[ 1 ];
248 	C = _context.digest[ 2 ];
249 	D = _context.digest[ 3 ];
250 	E = _context.digest[ 4 ];
251 
252 	/* Step D.  Serious mangling, divided into four sub-rounds */
253 	subRound1( 0 ); subRound1( 1 ); subRound1( 2 ); subRound1( 3 );
254 	subRound1( 4 ); subRound1( 5 ); subRound1( 6 ); subRound1( 7 );
255 	subRound1( 8 ); subRound1( 9 ); subRound1( 10 ); subRound1( 11 );
256 	subRound1( 12 ); subRound1( 13 ); subRound1( 14 ); subRound1( 15 );
257 	subRound1( 16 ); subRound1( 17 ); subRound1( 18 ); subRound1( 19 );
258 	subRound2( 20 ); subRound2( 21 ); subRound2( 22 ); subRound2( 23 );
259 	subRound2( 24 ); subRound2( 25 ); subRound2( 26 ); subRound2( 27 );
260 	subRound2( 28 ); subRound2( 29 ); subRound2( 30 ); subRound2( 31 );
261 	subRound2( 32 ); subRound2( 33 ); subRound2( 34 ); subRound2( 35 );
262 	subRound2( 36 ); subRound2( 37 ); subRound2( 38 ); subRound2( 39 );
263 	subRound3( 40 ); subRound3( 41 ); subRound3( 42 ); subRound3( 43 );
264 	subRound3( 44 ); subRound3( 45 ); subRound3( 46 ); subRound3( 47 );
265 	subRound3( 48 ); subRound3( 49 ); subRound3( 50 ); subRound3( 51 );
266 	subRound3( 52 ); subRound3( 53 ); subRound3( 54 ); subRound3( 55 );
267 	subRound3( 56 ); subRound3( 57 ); subRound3( 58 ); subRound3( 59 );
268 	subRound4( 60 ); subRound4( 61 ); subRound4( 62 ); subRound4( 63 );
269 	subRound4( 64 ); subRound4( 65 ); subRound4( 66 ); subRound4( 67 );
270 	subRound4( 68 ); subRound4( 69 ); subRound4( 70 ); subRound4( 71 );
271 	subRound4( 72 ); subRound4( 73 ); subRound4( 74 ); subRound4( 75 );
272 	subRound4( 76 ); subRound4( 77 ); subRound4( 78 ); subRound4( 79 );
273 
274 	/* Step E.  Build message digest */
275 	_context.digest[ 0 ] += A;
276 	_context.digest[ 1 ] += B;
277 	_context.digest[ 2 ] += C;
278 	_context.digest[ 3 ] += D;
279 	_context.digest[ 4 ] += E;
280 }
281 
282 
283 } // namespace Poco
284