1 //
2 // SHA2Engine.cpp
3 //
4 // Library: Foundation
5 // Package: Crypt
6 // Module:  SHA2Engine
7 //
8 // Code of class SHA2Engine.
9 //
10 // Secure Hash Standard SHA-2 algorithm
11 // (FIPS 180-4, see http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf)
12 //
13 // Based on the implementation of mbed TLS (Apache 2.0)
14 // http://www.apache.org/licenses/LICENSE-2.0
15 //
16 // Copyright (c) 2017, Applied Informatics Software Engineering GmbH
17 // and Contributors.
18 //
19 // SPDX-License-Identifier:	BSL-1.0
20 //
21 
22 
23 #include "Poco/SHA2Engine.h"
24 #include <string.h>
25 
26 
27 namespace Poco {
28 
29 
30 typedef struct
31 {
32 	union
33 	{
34 		Poco::UInt32 total32[4];
35 		Poco::UInt64 total64[2];
36 	} total;
37 
38 	union
39 	{
40 		Poco::UInt32 state32[16];
41 		Poco::UInt64 state64[8];
42 	} state;
43 
44 	SHA2Engine::ALGORITHM size;
45 	unsigned char buffer[128];
46 } HASHCONTEXT;
47 
48 
49 static const Poco::UInt32 K32[] =
50 {
51 	0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5,
52 	0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5,
53 	0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3,
54 	0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174,
55 	0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC,
56 	0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA,
57 	0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7,
58 	0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967,
59 	0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13,
60 	0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85,
61 	0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3,
62 	0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070,
63 	0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5,
64 	0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3,
65 	0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208,
66 	0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2,
67 };
68 
69 
70 #if defined(_MSC_VER) || defined(__WATCOMC__)
71 #define UL64(x) x##ui64
72 #else
73 #define UL64(x) x##ULL
74 #endif
75 
76 
77 static const Poco::UInt64 K64[80] =
78 {
79 	UL64(0x428A2F98D728AE22), UL64(0x7137449123EF65CD),
80 	UL64(0xB5C0FBCFEC4D3B2F), UL64(0xE9B5DBA58189DBBC),
81 	UL64(0x3956C25BF348B538), UL64(0x59F111F1B605D019),
82 	UL64(0x923F82A4AF194F9B), UL64(0xAB1C5ED5DA6D8118),
83 	UL64(0xD807AA98A3030242), UL64(0x12835B0145706FBE),
84 	UL64(0x243185BE4EE4B28C), UL64(0x550C7DC3D5FFB4E2),
85 	UL64(0x72BE5D74F27B896F), UL64(0x80DEB1FE3B1696B1),
86 	UL64(0x9BDC06A725C71235), UL64(0xC19BF174CF692694),
87 	UL64(0xE49B69C19EF14AD2), UL64(0xEFBE4786384F25E3),
88 	UL64(0x0FC19DC68B8CD5B5), UL64(0x240CA1CC77AC9C65),
89 	UL64(0x2DE92C6F592B0275), UL64(0x4A7484AA6EA6E483),
90 	UL64(0x5CB0A9DCBD41FBD4), UL64(0x76F988DA831153B5),
91 	UL64(0x983E5152EE66DFAB), UL64(0xA831C66D2DB43210),
92 	UL64(0xB00327C898FB213F), UL64(0xBF597FC7BEEF0EE4),
93 	UL64(0xC6E00BF33DA88FC2), UL64(0xD5A79147930AA725),
94 	UL64(0x06CA6351E003826F), UL64(0x142929670A0E6E70),
95 	UL64(0x27B70A8546D22FFC), UL64(0x2E1B21385C26C926),
96 	UL64(0x4D2C6DFC5AC42AED), UL64(0x53380D139D95B3DF),
97 	UL64(0x650A73548BAF63DE), UL64(0x766A0ABB3C77B2A8),
98 	UL64(0x81C2C92E47EDAEE6), UL64(0x92722C851482353B),
99 	UL64(0xA2BFE8A14CF10364), UL64(0xA81A664BBC423001),
100 	UL64(0xC24B8B70D0F89791), UL64(0xC76C51A30654BE30),
101 	UL64(0xD192E819D6EF5218), UL64(0xD69906245565A910),
102 	UL64(0xF40E35855771202A), UL64(0x106AA07032BBD1B8),
103 	UL64(0x19A4C116B8D2D0C8), UL64(0x1E376C085141AB53),
104 	UL64(0x2748774CDF8EEB99), UL64(0x34B0BCB5E19B48A8),
105 	UL64(0x391C0CB3C5C95A63), UL64(0x4ED8AA4AE3418ACB),
106 	UL64(0x5B9CCA4F7763E373), UL64(0x682E6FF3D6B2B8A3),
107 	UL64(0x748F82EE5DEFB2FC), UL64(0x78A5636F43172F60),
108 	UL64(0x84C87814A1F0AB72), UL64(0x8CC702081A6439EC),
109 	UL64(0x90BEFFFA23631E28), UL64(0xA4506CEBDE82BDE9),
110 	UL64(0xBEF9A3F7B2C67915), UL64(0xC67178F2E372532B),
111 	UL64(0xCA273ECEEA26619C), UL64(0xD186B8C721C0C207),
112 	UL64(0xEADA7DD6CDE0EB1E), UL64(0xF57D4F7FEE6ED178),
113 	UL64(0x06F067AA72176FBA), UL64(0x0A637DC5A2C898A6),
114 	UL64(0x113F9804BEF90DAE), UL64(0x1B710B35131C471B),
115 	UL64(0x28DB77F523047D84), UL64(0x32CAAB7B40C72493),
116 	UL64(0x3C9EBE0A15C9BEBC), UL64(0x431D67C49C100D4C),
117 	UL64(0x4CC5D4BECB3E42B6), UL64(0x597F299CFC657E2A),
118 	UL64(0x5FCB6FAB3AD6FAEC), UL64(0x6C44198C4A475817)
119 };
120 
121 
122 static const unsigned char padding[128] = { 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
123 
124 
125 #define SHR32(x,n) ((x & 0xFFFFFFFF) >> n)
126 #define SHR64(x,n) (x >> n)
127 #define ROTR32(x,n) (SHR32(x,n) | (x << (32 - n)))
128 #define ROTR64(x,n) (SHR64(x,n) | (x << (64 - n)))
129 #define S320(x) (ROTR32(x, 7) ^ ROTR32(x,18) ^ SHR32(x, 3))
130 #define S321(x) (ROTR32(x,17) ^ ROTR32(x,19) ^ SHR32(x,10))
131 #define S322(x) (ROTR32(x, 2) ^ ROTR32(x,13) ^ ROTR32(x,22))
132 #define S323(x) (ROTR32(x, 6) ^ ROTR32(x,11) ^ ROTR32(x,25))
133 #define S640(x) (ROTR64(x, 1) ^ ROTR64(x, 8) ^ SHR64(x, 7))
134 #define S641(x) (ROTR64(x,19) ^ ROTR64(x,61) ^ SHR64(x, 6))
135 #define S642(x) (ROTR64(x,28) ^ ROTR64(x,34) ^ ROTR64(x,39))
136 #define S643(x) (ROTR64(x,14) ^ ROTR64(x,18) ^ ROTR64(x,41))
137 #define F320(x,y,z) ((x & y) | (z & (x | y)))
138 #define F321(x,y,z) (z ^ (x & (y ^ z)))
139 #define F640(x,y,z) ((x & y) | (z & (x | y)))
140 #define F641(x,y,z) (z ^ (x & (y ^ z)))
141 #define R32(t) (W[t] = S321(W[t -  2]) + W[t -  7] + S320(W[t - 15]) + W[t - 16])
142 #define P32(a,b,c,d,e,f,g,h,x,K)               \
143 {                                              \
144 	temp1 = h + S323(e) + F321(e,f,g) + K + x; \
145 	temp2 = S322(a) + F320(a,b,c);             \
146 	d += temp1; h = temp1 + temp2;             \
147 }
148 #define P64(a,b,c,d,e,f,g,h,x,K)               \
149 {                                              \
150 	temp1 = h + S643(e) + F641(e,f,g) + K + x; \
151 	temp2 = S642(a) + F640(a,b,c);             \
152 	d += temp1; h = temp1 + temp2;             \
153 }
154 #ifndef GET_UINT32
155 #define GET_UINT32(n,b,i)                        \
156 do {                                             \
157 	(n) = ( (Poco::UInt32) (b)[(i)    ] << 24 )  \
158 		| ( (Poco::UInt32) (b)[(i) + 1] << 16 )  \
159 		| ( (Poco::UInt32) (b)[(i) + 2] <<  8 )  \
160 		| ( (Poco::UInt32) (b)[(i) + 3]       ); \
161 } while( 0 )
162 #endif
163 #ifndef PUT_UINT32
164 #define PUT_UINT32(n,b,i)                         \
165 do {                                              \
166 	(b)[(i)    ] = (unsigned char) ( (n) >> 24 ); \
167 	(b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
168 	(b)[(i) + 2] = (unsigned char) ( (n) >>  8 ); \
169 	(b)[(i) + 3] = (unsigned char) ( (n)       ); \
170 } while( 0 )
171 #endif
172 #ifndef GET_UINT64
173 #define GET_UINT64(n,b,i)                        \
174 {                                                \
175 	(n) = ( (Poco::UInt64) (b)[(i)    ] << 56 )  \
176 		| ( (Poco::UInt64) (b)[(i) + 1] << 48 )  \
177 		| ( (Poco::UInt64) (b)[(i) + 2] << 40 )  \
178 		| ( (Poco::UInt64) (b)[(i) + 3] << 32 )  \
179 		| ( (Poco::UInt64) (b)[(i) + 4] << 24 )  \
180 		| ( (Poco::UInt64) (b)[(i) + 5] << 16 )  \
181 		| ( (Poco::UInt64) (b)[(i) + 6] <<  8 )  \
182 		| ( (Poco::UInt64) (b)[(i) + 7]       ); \
183 }
184 #endif
185 #ifndef PUT_UINT64
186 #define PUT_UINT64(n,b,i)                         \
187 {                                                 \
188 	(b)[(i)    ] = (unsigned char) ( (n) >> 56 ); \
189 	(b)[(i) + 1] = (unsigned char) ( (n) >> 48 ); \
190 	(b)[(i) + 2] = (unsigned char) ( (n) >> 40 ); \
191 	(b)[(i) + 3] = (unsigned char) ( (n) >> 32 ); \
192 	(b)[(i) + 4] = (unsigned char) ( (n) >> 24 ); \
193 	(b)[(i) + 5] = (unsigned char) ( (n) >> 16 ); \
194 	(b)[(i) + 6] = (unsigned char) ( (n) >>  8 ); \
195 	(b)[(i) + 7] = (unsigned char) ( (n)       ); \
196 }
197 #endif
198 
199 
SHA2Engine(ALGORITHM algorithm)200 SHA2Engine::SHA2Engine(ALGORITHM algorithm):
201 	_context(NULL),
202 	_algorithm(algorithm)
203 {
204 	_digest.reserve(digestLength());
205 	reset();
206 }
207 
208 
~SHA2Engine()209 SHA2Engine::~SHA2Engine()
210 {
211 	reset();
212 	free(_context);
213 }
214 
215 
_sha256_process(HASHCONTEXT * pContext,const unsigned char data[64])216 void _sha256_process(HASHCONTEXT* pContext, const unsigned char data[64])
217 {
218 	unsigned int i;
219 	Poco::UInt32 temp1, temp2, temp3[8], W[64];
220 	for (i = 0; i < 8; i++) temp3[i] = pContext->state.state32[i];
221 	for (i = 0; i < 16; i++) { GET_UINT32(W[i], data, 4 * i); }
222 	for (i = 0; i < 16; i += 8)
223 	{
224 		P32(temp3[0], temp3[1], temp3[2], temp3[3], temp3[4], temp3[5], temp3[6], temp3[7], W[i + 0], K32[i + 0]);
225 		P32(temp3[7], temp3[0], temp3[1], temp3[2], temp3[3], temp3[4], temp3[5], temp3[6], W[i + 1], K32[i + 1]);
226 		P32(temp3[6], temp3[7], temp3[0], temp3[1], temp3[2], temp3[3], temp3[4], temp3[5], W[i + 2], K32[i + 2]);
227 		P32(temp3[5], temp3[6], temp3[7], temp3[0], temp3[1], temp3[2], temp3[3], temp3[4], W[i + 3], K32[i + 3]);
228 		P32(temp3[4], temp3[5], temp3[6], temp3[7], temp3[0], temp3[1], temp3[2], temp3[3], W[i + 4], K32[i + 4]);
229 		P32(temp3[3], temp3[4], temp3[5], temp3[6], temp3[7], temp3[0], temp3[1], temp3[2], W[i + 5], K32[i + 5]);
230 		P32(temp3[2], temp3[3], temp3[4], temp3[5], temp3[6], temp3[7], temp3[0], temp3[1], W[i + 6], K32[i + 6]);
231 		P32(temp3[1], temp3[2], temp3[3], temp3[4], temp3[5], temp3[6], temp3[7], temp3[0], W[i + 7], K32[i + 7]);
232 	}
233 	for (i = 16; i < 64; i += 8)
234 	{
235 		P32(temp3[0], temp3[1], temp3[2], temp3[3], temp3[4], temp3[5], temp3[6], temp3[7], R32(i + 0), K32[i + 0]);
236 		P32(temp3[7], temp3[0], temp3[1], temp3[2], temp3[3], temp3[4], temp3[5], temp3[6], R32(i + 1), K32[i + 1]);
237 		P32(temp3[6], temp3[7], temp3[0], temp3[1], temp3[2], temp3[3], temp3[4], temp3[5], R32(i + 2), K32[i + 2]);
238 		P32(temp3[5], temp3[6], temp3[7], temp3[0], temp3[1], temp3[2], temp3[3], temp3[4], R32(i + 3), K32[i + 3]);
239 		P32(temp3[4], temp3[5], temp3[6], temp3[7], temp3[0], temp3[1], temp3[2], temp3[3], R32(i + 4), K32[i + 4]);
240 		P32(temp3[3], temp3[4], temp3[5], temp3[6], temp3[7], temp3[0], temp3[1], temp3[2], R32(i + 5), K32[i + 5]);
241 		P32(temp3[2], temp3[3], temp3[4], temp3[5], temp3[6], temp3[7], temp3[0], temp3[1], R32(i + 6), K32[i + 6]);
242 		P32(temp3[1], temp3[2], temp3[3], temp3[4], temp3[5], temp3[6], temp3[7], temp3[0], R32(i + 7), K32[i + 7]);
243 	}
244 	for (i = 0; i < 8; i++) pContext->state.state32[i] += temp3[i];
245 }
246 
247 
_sha512_process(HASHCONTEXT * pContext,const unsigned char data[128])248 void _sha512_process(HASHCONTEXT* pContext, const unsigned char data[128])
249 {
250 	int i;
251 	Poco::UInt64 temp1, temp2, temp3[8], W[80];
252 	for (i = 0; i < 16; i++) { GET_UINT64(W[i], data, i << 3); }
253 	for (; i < 80; i++) { W[i] = S641(W[i - 2]) + W[i - 7] + S640(W[i - 15]) + W[i - 16]; }
254 	for (i = 0; i < 8; i++) temp3[i] = pContext->state.state64[i];
255 	i = 0;
256 	do
257 	{
258 		P64(temp3[0], temp3[1], temp3[2], temp3[3], temp3[4], temp3[5], temp3[6], temp3[7], W[i], K64[i]); i++;
259 		P64(temp3[7], temp3[0], temp3[1], temp3[2], temp3[3], temp3[4], temp3[5], temp3[6], W[i], K64[i]); i++;
260 		P64(temp3[6], temp3[7], temp3[0], temp3[1], temp3[2], temp3[3], temp3[4], temp3[5], W[i], K64[i]); i++;
261 		P64(temp3[5], temp3[6], temp3[7], temp3[0], temp3[1], temp3[2], temp3[3], temp3[4], W[i], K64[i]); i++;
262 		P64(temp3[4], temp3[5], temp3[6], temp3[7], temp3[0], temp3[1], temp3[2], temp3[3], W[i], K64[i]); i++;
263 		P64(temp3[3], temp3[4], temp3[5], temp3[6], temp3[7], temp3[0], temp3[1], temp3[2], W[i], K64[i]); i++;
264 		P64(temp3[2], temp3[3], temp3[4], temp3[5], temp3[6], temp3[7], temp3[0], temp3[1], W[i], K64[i]); i++;
265 		P64(temp3[1], temp3[2], temp3[3], temp3[4], temp3[5], temp3[6], temp3[7], temp3[0], W[i], K64[i]); i++;
266 	} while (i < 80);
267 	for (i = 0; i < 8; i++) pContext->state.state64[i] += temp3[i];
268 }
269 
270 
updateImpl(const void * buffer_,std::size_t count)271 void SHA2Engine::updateImpl(const void* buffer_, std::size_t count)
272 {
273 	if (_context == NULL || buffer_ == NULL || count == 0) return;
274 	Poco::UInt32 left = 0;
275 	HASHCONTEXT* pContext = (HASHCONTEXT*)_context;
276 	unsigned char* data = (unsigned char*)buffer_;
277 	if (pContext->size > SHA_256)
278 	{
279 		left = (Poco::UInt32)(pContext->total.total64[0] & 0x7F);
280 		size_t fill = 128 - left;
281 		pContext->total.total64[0] += (Poco::UInt64)count;
282 		if (pContext->total.total64[0] < (Poco::UInt64)count)	pContext->total.total64[1]++;
283 		if (left && count >= fill)
284 		{
285 			memcpy((void *)(pContext->buffer + left), data, fill);
286 			_sha512_process(pContext, pContext->buffer);
287 			data += fill;
288 			count -= fill;
289 			left = 0;
290 		}
291 		while (count >= 128)
292 		{
293 			_sha512_process(pContext, data);
294 			data += 128;
295 			count -= 128;
296 		}
297 	}
298 	else
299 	{
300 		left = (Poco::UInt32)(pContext->total.total32[0] & 0x3F);
301 		size_t fill = 64 - left;
302 		pContext->total.total32[0] += (Poco::UInt32)count;
303 		pContext->total.total32[0] &= 0xFFFFFFFF;
304 		if (pContext->total.total32[0] < (Poco::UInt32)count) pContext->total.total32[1]++;
305 		if (left && count >= fill)
306 		{
307 			memcpy((void *)(pContext->buffer + left), data, fill);
308 			_sha256_process(pContext, pContext->buffer);
309 			data += fill;
310 			count -= fill;
311 			left = 0;
312 		}
313 		while (count >= 64)
314 		{
315 			_sha256_process(pContext, data);
316 			data += 64;
317 			count -= 64;
318 		}
319 	}
320 	if (count > 0) memcpy((void *)(pContext->buffer + left), data, count);
321 }
322 
323 
digestLength() const324 std::size_t SHA2Engine::digestLength() const
325 {
326 	return (size_t)((int)_algorithm / 8);
327 }
328 
329 
reset()330 void SHA2Engine::reset()
331 {
332 	if (_context != NULL) free(_context);
333 	_context = calloc(1, sizeof(HASHCONTEXT));
334 	HASHCONTEXT* pContext = (HASHCONTEXT*)_context;
335 	pContext->size = _algorithm;
336 	if (_algorithm == SHA_224)
337 	{
338 		pContext->state.state32[0] = 0xC1059ED8;
339 		pContext->state.state32[1] = 0x367CD507;
340 		pContext->state.state32[2] = 0x3070DD17;
341 		pContext->state.state32[3] = 0xF70E5939;
342 		pContext->state.state32[4] = 0xFFC00B31;
343 		pContext->state.state32[5] = 0x68581511;
344 		pContext->state.state32[6] = 0x64F98FA7;
345 		pContext->state.state32[7] = 0xBEFA4FA4;
346 	}
347 	else if (_algorithm == SHA_256)
348 	{
349 		pContext->state.state32[0] = 0x6A09E667;
350 		pContext->state.state32[1] = 0xBB67AE85;
351 		pContext->state.state32[2] = 0x3C6EF372;
352 		pContext->state.state32[3] = 0xA54FF53A;
353 		pContext->state.state32[4] = 0x510E527F;
354 		pContext->state.state32[5] = 0x9B05688C;
355 		pContext->state.state32[6] = 0x1F83D9AB;
356 		pContext->state.state32[7] = 0x5BE0CD19;
357 	}
358 	else if (_algorithm == SHA_384)
359 	{
360 		pContext->state.state64[0] = UL64(0xCBBB9D5DC1059ED8);
361 		pContext->state.state64[1] = UL64(0x629A292A367CD507);
362 		pContext->state.state64[2] = UL64(0x9159015A3070DD17);
363 		pContext->state.state64[3] = UL64(0x152FECD8F70E5939);
364 		pContext->state.state64[4] = UL64(0x67332667FFC00B31);
365 		pContext->state.state64[5] = UL64(0x8EB44A8768581511);
366 		pContext->state.state64[6] = UL64(0xDB0C2E0D64F98FA7);
367 		pContext->state.state64[7] = UL64(0x47B5481DBEFA4FA4);
368 	}
369 	else
370 	{
371 		pContext->state.state64[0] = UL64(0x6A09E667F3BCC908);
372 		pContext->state.state64[1] = UL64(0xBB67AE8584CAA73B);
373 		pContext->state.state64[2] = UL64(0x3C6EF372FE94F82B);
374 		pContext->state.state64[3] = UL64(0xA54FF53A5F1D36F1);
375 		pContext->state.state64[4] = UL64(0x510E527FADE682D1);
376 		pContext->state.state64[5] = UL64(0x9B05688C2B3E6C1F);
377 		pContext->state.state64[6] = UL64(0x1F83D9ABFB41BD6B);
378 		pContext->state.state64[7] = UL64(0x5BE0CD19137E2179);
379 	}
380 }
381 
382 
digest()383 const DigestEngine::Digest& SHA2Engine::digest()
384 {
385 	_digest.clear();
386 	if (_context == NULL) return _digest;
387 	HASHCONTEXT* pContext = (HASHCONTEXT*)_context;
388 	size_t last, padn;
389 	unsigned char hash[64];
390 	memset(hash, 0, 64);
391 	if (pContext->size > SHA_256)
392 	{
393 		unsigned char msglen[16];
394 		Poco::UInt64 high = (pContext->total.total64[0] >> 61) | (pContext->total.total64[1] << 3);
395 		Poco::UInt64 low = (pContext->total.total64[0] << 3);
396 		PUT_UINT64(high, msglen, 0);
397 		PUT_UINT64(low, msglen, 8);
398 		last = (size_t)(pContext->total.total64[0] & 0x7F);
399 		padn = (last < 112) ? (112 - last) : (240 - last);
400 		updateImpl(padding, padn);
401 		updateImpl(msglen, 16);
402 		PUT_UINT64(pContext->state.state64[0], hash, 0);
403 		PUT_UINT64(pContext->state.state64[1], hash, 8);
404 		PUT_UINT64(pContext->state.state64[2], hash, 16);
405 		PUT_UINT64(pContext->state.state64[3], hash, 24);
406 		PUT_UINT64(pContext->state.state64[4], hash, 32);
407 		PUT_UINT64(pContext->state.state64[5], hash, 40);
408 		if (pContext->size > SHA_384)
409 		{
410 			PUT_UINT64(pContext->state.state64[6], hash, 48);
411 			PUT_UINT64(pContext->state.state64[7], hash, 56);
412 		}
413 	}
414 	else
415 	{
416 		unsigned char msglen[8];
417 		Poco::UInt32 high = (pContext->total.total32[0] >> 29) | (pContext->total.total32[1] << 3);
418 		Poco::UInt32 low = (pContext->total.total32[0] << 3);
419 		PUT_UINT32(high, msglen, 0);
420 		PUT_UINT32(low, msglen, 4);
421 		last = pContext->total.total32[0] & 0x3F;
422 		padn = (last < 56) ? (56 - last) : (120 - last);
423 		updateImpl(padding, padn);
424 		updateImpl(msglen, 8);
425 		PUT_UINT32(pContext->state.state32[0], hash, 0);
426 		PUT_UINT32(pContext->state.state32[1], hash, 4);
427 		PUT_UINT32(pContext->state.state32[2], hash, 8);
428 		PUT_UINT32(pContext->state.state32[3], hash, 12);
429 		PUT_UINT32(pContext->state.state32[4], hash, 16);
430 		PUT_UINT32(pContext->state.state32[5], hash, 20);
431 		PUT_UINT32(pContext->state.state32[6], hash, 24);
432 		if (pContext->size > SHA_224) PUT_UINT32(pContext->state.state32[7], hash, 28);
433 	}
434 	_digest.insert(_digest.begin(), hash, hash + digestLength());
435 	reset();
436 	return _digest;
437 }
438 
439 
440 } // namespace Poco
441