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