SHA1.C
Go to the documentation of this file.
1/*---------------------------------------------------------------------------*\
2 ========= |
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4 \\ / O peration |
5 \\ / A nd | www.openfoam.com
6 \\/ M anipulation |
7-------------------------------------------------------------------------------
8 Copyright (C) 2011-2016 OpenFOAM Foundation
9 Copyright (C) 2019 OpenCFD Ltd.
10-------------------------------------------------------------------------------
11License
12 This file is part of OpenFOAM.
13
14 OpenFOAM is free software: you can redistribute it and/or modify it
15 under the terms of the GNU General Public License as published by
16 the Free Software Foundation, either version 3 of the License, or
17 (at your option) any later version.
18
19 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26
27Description
28 Functions to compute SHA1 message digest of files or memory blocks
29 according to the NIST specification FIPS-180-1.
30
31 Adapted from the gnulib implementation written by Scott G. Miller with
32 credits to Robert Klep <robert@ilse.nl> -- Expansion function fix
33
34 Copyright (C) 2000, 2001, 2003, 2004, 2005, 2006, 2008 Free Software
35 Foundation, Inc.
36
37\*---------------------------------------------------------------------------*/
38
39#include "SHA1.H"
40#include "endian.H"
41#include "IOstreams.H"
42#include <cstring>
43
44// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
45
47// The bytes used to pad buffer to the next 64-byte boundary.
48// (RFC 1321, 3.1: Step 1)
49static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ... */ };
51
52
53// * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * * //
54
56//- Swap bytes from internal to network (big-endian) order
57static inline uint32_t swapBytes(uint32_t n)
58{
59#ifdef WM_LITTLE_ENDIAN
60 return Foam::endian::swap32(n);
61#else
62 return n;
63#endif
64}
65
66//- Copy the 4-byte value into the memory location pointed to by *dst.
67// If the architecture allows unaligned access this is equivalent to
68// *(uint32_t *) cp = val
69static inline void set_uint32(unsigned char *dst, uint32_t v)
70{
71 std::memcpy(dst, &v, sizeof(uint32_t));
72}
74
75
76// * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * //
77
78void Foam::SHA1::processBytes(const void *data, size_t len)
79{
80 // Already finalized, thus need to restart from nothing
81 if (finalized_)
82 {
83 clear();
84 }
85
86 // Complete filling of internal buffer
87 if (bufLen_)
88 {
89 const size_t remaining = bufLen_;
90 const size_t add =
91 (
92 sizeof(buffer_) - remaining > len
93 ? len
94 : sizeof(buffer_) - remaining
95 );
96
97 unsigned char* bufp = reinterpret_cast<unsigned char*>(buffer_);
98
99 std::memcpy(&bufp[remaining], data, add);
100 bufLen_ += add;
101
102 if (bufLen_ > 64)
103 {
104 processBlock(buffer_, bufLen_ & ~63);
105
106 bufLen_ &= 63;
107 // The regions in the following copy operation do not
108 // (cannot) overlap
109 std::memcpy(buffer_, &bufp[(remaining + add) & ~63], bufLen_);
110 }
111
112 data = reinterpret_cast<const unsigned char*>(data) + add;
113 len -= add;
114 }
115
116 // Process available complete blocks
117 while (len >= 64)
118 {
119 processBlock(std::memcpy(buffer_, data, 64), 64);
120 data = reinterpret_cast<const unsigned char*>(data) + 64;
121 len -= 64;
122 }
123
124 // Move remaining bytes in internal buffer.
125 if (len > 0)
126 {
127 unsigned char* bufp = reinterpret_cast<unsigned char*>(buffer_);
128 size_t remaining = bufLen_;
129
130 std::memcpy(&bufp[remaining], data, len);
131 remaining += len;
132 if (remaining >= 64)
133 {
134 processBlock(buffer_, 64);
135 remaining -= 64;
136 std::memcpy(buffer_, &buffer_[16], remaining);
137 }
138 bufLen_ = remaining;
139 }
140}
141
142
143// SHA1 round constants
144#define K1 0x5a827999
145#define K2 0x6ed9eba1
146#define K3 0x8f1bbcdc
147#define K4 0xca62c1d6
148
149// Round functions. Note that F2 is the same as F4.
150#define F1(B,C,D) ( D ^ ( B & ( C ^ D ) ) )
151#define F2(B,C,D) (B ^ C ^ D)
152#define F3(B,C,D) ( ( B & C ) | ( D & ( B | C ) ) )
153#define F4(B,C,D) (B ^ C ^ D)
154
155// Process LEN bytes of BUFFER, it is assumed that LEN % 64 == 0.
156// Most of this code comes from GnuPG's cipher/sha1.c
157
158void Foam::SHA1::processBlock(const void *data, size_t len)
159{
160 const uint32_t *words = reinterpret_cast<const uint32_t*>(data);
161 const size_t nwords = len / sizeof(uint32_t);
162 const uint32_t *endp = words + nwords;
163
164 // Calculate with sixteen words of 32-bits
165 uint32_t x[16];
166 uint32_t a = hashsumA_;
167 uint32_t b = hashsumB_;
168 uint32_t c = hashsumC_;
169 uint32_t d = hashsumD_;
170 uint32_t e = hashsumE_;
171
172 // First increment the byte count.
173 // RFC 1321 specifies the possible length of the file up to 2^64 bits.
174 // Here we only compute the number of bytes. Do a double word increment.
175 bufTotal_[0] += len;
176 if (bufTotal_[0] < len)
177 {
178 ++bufTotal_[1];
179 }
180
181 // rotate left uint32_t by n bits
182 #define rol_uint32(x, nbits) (((x) << (nbits)) | ((x) >> (32 - (nbits))))
183
184 #define M(I) ( tm = x[I & 0x0F] ^ x[(I-14) & 0x0F] \
185 ^ x[(I-8) & 0x0F] ^ x[(I-3) & 0x0F] \
186 , (x[I & 0x0F] = rol_uint32(tm, 1)) )
187
188 #define R(A,B,C,D,E,F,K,M) \
189 do \
190 { \
191 E += rol_uint32(A, 5) + F(B, C, D) + K + M; \
192 B = rol_uint32(B, 30); \
193 } while (0)
194
195 while (words < endp)
196 {
197 uint32_t tm;
198 for (int t = 0; t < 16; ++t)
199 {
200 x[t] = swapBytes(*words);
201 ++words;
202 }
203
204 R( a, b, c, d, e, F1, K1, x[ 0] );
205 R( e, a, b, c, d, F1, K1, x[ 1] );
206 R( d, e, a, b, c, F1, K1, x[ 2] );
207 R( c, d, e, a, b, F1, K1, x[ 3] );
208 R( b, c, d, e, a, F1, K1, x[ 4] );
209 R( a, b, c, d, e, F1, K1, x[ 5] );
210 R( e, a, b, c, d, F1, K1, x[ 6] );
211 R( d, e, a, b, c, F1, K1, x[ 7] );
212 R( c, d, e, a, b, F1, K1, x[ 8] );
213 R( b, c, d, e, a, F1, K1, x[ 9] );
214 R( a, b, c, d, e, F1, K1, x[10] );
215 R( e, a, b, c, d, F1, K1, x[11] );
216 R( d, e, a, b, c, F1, K1, x[12] );
217 R( c, d, e, a, b, F1, K1, x[13] );
218 R( b, c, d, e, a, F1, K1, x[14] );
219 R( a, b, c, d, e, F1, K1, x[15] );
220 R( e, a, b, c, d, F1, K1, M(16) );
221 R( d, e, a, b, c, F1, K1, M(17) );
222 R( c, d, e, a, b, F1, K1, M(18) );
223 R( b, c, d, e, a, F1, K1, M(19) );
224 R( a, b, c, d, e, F2, K2, M(20) );
225 R( e, a, b, c, d, F2, K2, M(21) );
226 R( d, e, a, b, c, F2, K2, M(22) );
227 R( c, d, e, a, b, F2, K2, M(23) );
228 R( b, c, d, e, a, F2, K2, M(24) );
229 R( a, b, c, d, e, F2, K2, M(25) );
230 R( e, a, b, c, d, F2, K2, M(26) );
231 R( d, e, a, b, c, F2, K2, M(27) );
232 R( c, d, e, a, b, F2, K2, M(28) );
233 R( b, c, d, e, a, F2, K2, M(29) );
234 R( a, b, c, d, e, F2, K2, M(30) );
235 R( e, a, b, c, d, F2, K2, M(31) );
236 R( d, e, a, b, c, F2, K2, M(32) );
237 R( c, d, e, a, b, F2, K2, M(33) );
238 R( b, c, d, e, a, F2, K2, M(34) );
239 R( a, b, c, d, e, F2, K2, M(35) );
240 R( e, a, b, c, d, F2, K2, M(36) );
241 R( d, e, a, b, c, F2, K2, M(37) );
242 R( c, d, e, a, b, F2, K2, M(38) );
243 R( b, c, d, e, a, F2, K2, M(39) );
244 R( a, b, c, d, e, F3, K3, M(40) );
245 R( e, a, b, c, d, F3, K3, M(41) );
246 R( d, e, a, b, c, F3, K3, M(42) );
247 R( c, d, e, a, b, F3, K3, M(43) );
248 R( b, c, d, e, a, F3, K3, M(44) );
249 R( a, b, c, d, e, F3, K3, M(45) );
250 R( e, a, b, c, d, F3, K3, M(46) );
251 R( d, e, a, b, c, F3, K3, M(47) );
252 R( c, d, e, a, b, F3, K3, M(48) );
253 R( b, c, d, e, a, F3, K3, M(49) );
254 R( a, b, c, d, e, F3, K3, M(50) );
255 R( e, a, b, c, d, F3, K3, M(51) );
256 R( d, e, a, b, c, F3, K3, M(52) );
257 R( c, d, e, a, b, F3, K3, M(53) );
258 R( b, c, d, e, a, F3, K3, M(54) );
259 R( a, b, c, d, e, F3, K3, M(55) );
260 R( e, a, b, c, d, F3, K3, M(56) );
261 R( d, e, a, b, c, F3, K3, M(57) );
262 R( c, d, e, a, b, F3, K3, M(58) );
263 R( b, c, d, e, a, F3, K3, M(59) );
264 R( a, b, c, d, e, F4, K4, M(60) );
265 R( e, a, b, c, d, F4, K4, M(61) );
266 R( d, e, a, b, c, F4, K4, M(62) );
267 R( c, d, e, a, b, F4, K4, M(63) );
268 R( b, c, d, e, a, F4, K4, M(64) );
269 R( a, b, c, d, e, F4, K4, M(65) );
270 R( e, a, b, c, d, F4, K4, M(66) );
271 R( d, e, a, b, c, F4, K4, M(67) );
272 R( c, d, e, a, b, F4, K4, M(68) );
273 R( b, c, d, e, a, F4, K4, M(69) );
274 R( a, b, c, d, e, F4, K4, M(70) );
275 R( e, a, b, c, d, F4, K4, M(71) );
276 R( d, e, a, b, c, F4, K4, M(72) );
277 R( c, d, e, a, b, F4, K4, M(73) );
278 R( b, c, d, e, a, F4, K4, M(74) );
279 R( a, b, c, d, e, F4, K4, M(75) );
280 R( e, a, b, c, d, F4, K4, M(76) );
281 R( d, e, a, b, c, F4, K4, M(77) );
282 R( c, d, e, a, b, F4, K4, M(78) );
283 R( b, c, d, e, a, F4, K4, M(79) );
284
285 a = hashsumA_ += a;
286 b = hashsumB_ += b;
287 c = hashsumC_ += c;
288 d = hashsumD_ += d;
289 e = hashsumE_ += e;
290 }
291}
292
293
294void Foam::SHA1::calcDigest(SHA1Digest& dig) const
295{
296 if (bufTotal_[0] || bufTotal_[1])
297 {
298 unsigned char *r = dig.data();
299
300 set_uint32(r + 0 * sizeof(uint32_t), swapBytes(hashsumA_));
301 set_uint32(r + 1 * sizeof(uint32_t), swapBytes(hashsumB_));
302 set_uint32(r + 2 * sizeof(uint32_t), swapBytes(hashsumC_));
303 set_uint32(r + 3 * sizeof(uint32_t), swapBytes(hashsumD_));
304 set_uint32(r + 4 * sizeof(uint32_t), swapBytes(hashsumE_));
305 }
306 else
307 {
308 dig.clear(); // No data!
309 }
310}
311
312
313// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
314
316{
317 hashsumA_ = 0x67452301;
318 hashsumB_ = 0xefcdab89;
319 hashsumC_ = 0x98badcfe;
320 hashsumD_ = 0x10325476;
321 hashsumE_ = 0xc3d2e1f0;
322
323 bufTotal_[0] = bufTotal_[1] = 0;
324 bufLen_ = 0;
325
326 finalized_ = false;
327}
328
329
331{
332 if (!finalized_)
333 {
334 finalized_ = true;
335
336 // Account for unprocessed bytes
337 const uint32_t bytes = bufLen_;
338 const size_t size = (bytes < 56 ? 64 : 128) / sizeof(uint32_t);
339
340 // Count remaining bytes.
341 bufTotal_[0] += bytes;
342 if (bufTotal_[0] < bytes)
343 {
344 ++bufTotal_[1];
345 }
346
347 // Finalized, but no data!
348 if (!bufTotal_[0] && !bufTotal_[1])
349 {
350 return false;
351 }
352
353 // Place the 64-bit length in *bits* at the end of the buffer.
354 buffer_[size-2] = swapBytes((bufTotal_[1] << 3) | (bufTotal_[0] >> 29));
355 buffer_[size-1] = swapBytes(bufTotal_[0] << 3);
356
357 unsigned char* bufp = reinterpret_cast<unsigned char *>(buffer_);
358
359 std::memcpy(&bufp[bytes], fillbuf, (size-2) * sizeof(uint32_t) - bytes);
360
361 // Process remaining bytes
362 processBlock(buffer_, size * sizeof(uint32_t));
363 }
364
365 return true;
366}
367
368
369// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
370
371#undef K1
372#undef K2
373#undef K3
374#undef K4
375
376#undef F1
377#undef F2
378#undef F3
379#undef F4
380
381#undef rol_uint32
382#undef M
383#undef R
384
385// ************************************************************************* //
Useful combination of include files which define Sin, Sout and Serr and the use of IO streams general...
#define F2(B, C, D)
Definition: SHA1.C:151
#define R(A, B, C, D, E, F, K, M)
#define F1(B, C, D)
Definition: SHA1.C:150
#define K3
Definition: SHA1.C:146
#define K1
Definition: SHA1.C:144
#define K4
Definition: SHA1.C:147
#define K2
Definition: SHA1.C:145
#define F4(B, C, D)
Definition: SHA1.C:153
#define F3(B, C, D)
Definition: SHA1.C:152
#define M(I)
label n
void clear() noexcept
Reset the hashed data before appending more.
Definition: SHA1.C:315
bool finalize()
Finalized the calculations (normally not needed directly).
Definition: SHA1.C:330
static uint32_t swap32(uint32_t)
Byte endian swapping for 32-bits.
Definition: endianI.H:61
Help with architecture-specific aspects.
void add(FieldField< Field1, typename typeOfSum< Type1, Type2 >::type > &f, const FieldField< Field1, Type1 > &f1, const FieldField< Field2, Type2 > &f2)
const direction noexcept
Definition: Scalar.H:223
volScalarField & b
Definition: createFields.H:27
volScalarField & e
Definition: createFields.H:11