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 | Copyright (C) 2011 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
11  OpenFOAM is free software: you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 Description
25  Functions to compute SHA1 message digest of files or memory blocks
26  according to the NIST specification FIPS-180-1.
27 
28  Adapted from the gnulib implementation written by Scott G. Miller with
29  credits to Robert Klep <robert@ilse.nl> -- Expansion function fix
30 
31  Copyright (C) 2000, 2001, 2003, 2004, 2005, 2006, 2008 Free Software
32  Foundation, Inc.
33 
34 \*---------------------------------------------------------------------------*/
35 
36 #include "SHA1.H"
37 #include "IOstreams.H"
38 
39 #include <cstring>
40 
41 #if defined (__GLIBC__)
42 # include <endian.h>
43 #endif
44 
45 
46 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
47 
49 // The bytes used to pad buffer to the next 64-byte boundary.
50 // (RFC 1321, 3.1: Step 1)
51 static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ... */ };
53 
54 
55 // * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * * //
56 
57 inline uint32_t Foam::SHA1::swapBytes(uint32_t n)
58 {
59 #ifdef __BYTE_ORDER
60 # if (__BYTE_ORDER == __BIG_ENDIAN)
61  return n;
62 # else
63  return
64  (
65  ((n) << 24)
66  | (((n) & 0xff00) << 8)
67  | (((n) >> 8) & 0xff00)
68  | ((n) >> 24)
69  );
70 # endif
71 
72 #else
73 
74  const short x = 0x0100;
75 
76  // yields 0x01 for big endian
77  if (*(reinterpret_cast<const char*>(&x)))
78  {
79  return n;
80  }
81  else
82  {
83  return
84  (
85  ((n) << 24)
86  | (((n) & 0xff00) << 8)
87  | (((n) >> 8) & 0xff00)
88  | ((n) >> 24)
89  );
90  }
91 #endif
92 }
93 
94 
95 inline void
96 Foam::SHA1::set_uint32(unsigned char *cp, uint32_t v)
97 {
98  memcpy(cp, &v, sizeof(uint32_t));
99 }
100 
101 
102 // * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * //
103 
104 
105 void Foam::SHA1::processBytes(const void *data, size_t len)
106 {
107  // already finalized, thus need to restart from nothing
108  if (finalized_)
109  {
110  clear();
111  }
112 
113  // complete filling of internal buffer
114  if (bufLen_)
115  {
116  size_t remaining = bufLen_;
117  size_t add =
118  (
119  sizeof(buffer_) - remaining > len
120  ? len
121  : sizeof(buffer_) - remaining
122  );
123 
124  unsigned char* bufp = reinterpret_cast<unsigned char*>(buffer_);
125 
126  memcpy(&bufp[remaining], data, add);
127  bufLen_ += add;
128 
129  if (bufLen_ > 64)
130  {
131  processBlock(buffer_, bufLen_ & ~63);
132 
133  bufLen_ &= 63;
134  // The regions in the following copy operation do not
135  // (cannot) overlap
136  memcpy(buffer_, &bufp[(remaining + add) & ~63], bufLen_);
137  }
138 
139  data = reinterpret_cast<const unsigned char*>(data) + add;
140  len -= add;
141  }
142 
143  // Process available complete blocks
144 // if (len >= 64)
145 // {
146 //#if !_STRING_ARCH_unaligned
147 //# define alignof(type) offsetof (struct { char c; type x; }, x)
148 //# define UNALIGNED_P(p) (((size_t) p) % alignof (uint32_t) != 0)
149 // if (UNALIGNED_P (data))
150 // {
151 // while (len > 64)
152  while (len >= 64)
153  {
154  processBlock(memcpy(buffer_, data, 64), 64);
155  data = reinterpret_cast<const unsigned char*>(data) + 64;
156  len -= 64;
157  }
158 // }
159 // else
160 //#endif
161 // {
162 // processBlock(data, len & ~63);
163 // data = reinterpret_cast<const unsigned char*>(data) + (len & ~63);
164 // len &= 63;
165 // }
166 // }
167 
168  // Move remaining bytes in internal buffer.
169  if (len > 0)
170  {
171  unsigned char* bufp = reinterpret_cast<unsigned char*>(buffer_);
172  size_t remaining = bufLen_;
173 
174  memcpy (&bufp[remaining], data, len);
175  remaining += len;
176  if (remaining >= 64)
177  {
178  processBlock(buffer_, 64);
179  remaining -= 64;
180  memcpy(buffer_, &buffer_[16], remaining);
181  }
182  bufLen_ = remaining;
183  }
184 }
185 
186 
187 // SHA1 round constants
188 #define K1 0x5a827999
189 #define K2 0x6ed9eba1
190 #define K3 0x8f1bbcdc
191 #define K4 0xca62c1d6
192 
193 // Round functions. Note that F2 is the same as F4.
194 #define F1(B,C,D) ( D ^ ( B & ( C ^ D ) ) )
195 #define F2(B,C,D) (B ^ C ^ D)
196 #define F3(B,C,D) ( ( B & C ) | ( D & ( B | C ) ) )
197 #define F4(B,C,D) (B ^ C ^ D)
198 
199 // Process LEN bytes of BUFFER, it is assumed that LEN % 64 == 0.
200 // Most of this code comes from GnuPG's cipher/sha1.c
201 
202 void
203 Foam::SHA1::processBlock(const void *data, size_t len)
204 {
205  const uint32_t *words = reinterpret_cast<const uint32_t*>(data);
206  size_t nwords = len / sizeof(uint32_t);
207  const uint32_t *endp = words + nwords;
208 
209  // calculate with sixteen words of 32-bits
210  uint32_t x[16];
211  uint32_t a = hashsumA_;
212  uint32_t b = hashsumB_;
213  uint32_t c = hashsumC_;
214  uint32_t d = hashsumD_;
215  uint32_t e = hashsumE_;
216 
217  // First increment the byte count.
218  // RFC 1321 specifies the possible length of the file up to 2^64 bits.
219  // Here we only compute the number of bytes. Do a double word increment.
220  bufTotal_[0] += len;
221  if (bufTotal_[0] < len)
222  {
223  ++bufTotal_[1];
224  }
225 
226  // rotate left uint32_t by n bits
227 #define rol_uint32(x, nbits) (((x) << (nbits)) | ((x) >> (32 - (nbits))))
228 
229 #define M(I) ( tm = x[I & 0x0F] ^ x[(I-14) & 0x0F] \
230  ^ x[(I-8) & 0x0F] ^ x[(I-3) & 0x0F] \
231  , (x[I & 0x0F] = rol_uint32(tm, 1)) )
232 
233 
234 #define R(A,B,C,D,E,F,K,M) \
235  do \
236  { \
237  E += rol_uint32(A, 5) + F(B, C, D) + K + M; \
238  B = rol_uint32(B, 30); \
239  } while (0)
240 
241  while (words < endp)
242  {
243  uint32_t tm;
244  for (int t = 0; t < 16; ++t)
245  {
246  x[t] = swapBytes(*words);
247  ++words;
248  }
249 
250  R( a, b, c, d, e, F1, K1, x[ 0] );
251  R( e, a, b, c, d, F1, K1, x[ 1] );
252  R( d, e, a, b, c, F1, K1, x[ 2] );
253  R( c, d, e, a, b, F1, K1, x[ 3] );
254  R( b, c, d, e, a, F1, K1, x[ 4] );
255  R( a, b, c, d, e, F1, K1, x[ 5] );
256  R( e, a, b, c, d, F1, K1, x[ 6] );
257  R( d, e, a, b, c, F1, K1, x[ 7] );
258  R( c, d, e, a, b, F1, K1, x[ 8] );
259  R( b, c, d, e, a, F1, K1, x[ 9] );
260  R( a, b, c, d, e, F1, K1, x[10] );
261  R( e, a, b, c, d, F1, K1, x[11] );
262  R( d, e, a, b, c, F1, K1, x[12] );
263  R( c, d, e, a, b, F1, K1, x[13] );
264  R( b, c, d, e, a, F1, K1, x[14] );
265  R( a, b, c, d, e, F1, K1, x[15] );
266  R( e, a, b, c, d, F1, K1, M(16) );
267  R( d, e, a, b, c, F1, K1, M(17) );
268  R( c, d, e, a, b, F1, K1, M(18) );
269  R( b, c, d, e, a, F1, K1, M(19) );
270  R( a, b, c, d, e, F2, K2, M(20) );
271  R( e, a, b, c, d, F2, K2, M(21) );
272  R( d, e, a, b, c, F2, K2, M(22) );
273  R( c, d, e, a, b, F2, K2, M(23) );
274  R( b, c, d, e, a, F2, K2, M(24) );
275  R( a, b, c, d, e, F2, K2, M(25) );
276  R( e, a, b, c, d, F2, K2, M(26) );
277  R( d, e, a, b, c, F2, K2, M(27) );
278  R( c, d, e, a, b, F2, K2, M(28) );
279  R( b, c, d, e, a, F2, K2, M(29) );
280  R( a, b, c, d, e, F2, K2, M(30) );
281  R( e, a, b, c, d, F2, K2, M(31) );
282  R( d, e, a, b, c, F2, K2, M(32) );
283  R( c, d, e, a, b, F2, K2, M(33) );
284  R( b, c, d, e, a, F2, K2, M(34) );
285  R( a, b, c, d, e, F2, K2, M(35) );
286  R( e, a, b, c, d, F2, K2, M(36) );
287  R( d, e, a, b, c, F2, K2, M(37) );
288  R( c, d, e, a, b, F2, K2, M(38) );
289  R( b, c, d, e, a, F2, K2, M(39) );
290  R( a, b, c, d, e, F3, K3, M(40) );
291  R( e, a, b, c, d, F3, K3, M(41) );
292  R( d, e, a, b, c, F3, K3, M(42) );
293  R( c, d, e, a, b, F3, K3, M(43) );
294  R( b, c, d, e, a, F3, K3, M(44) );
295  R( a, b, c, d, e, F3, K3, M(45) );
296  R( e, a, b, c, d, F3, K3, M(46) );
297  R( d, e, a, b, c, F3, K3, M(47) );
298  R( c, d, e, a, b, F3, K3, M(48) );
299  R( b, c, d, e, a, F3, K3, M(49) );
300  R( a, b, c, d, e, F3, K3, M(50) );
301  R( e, a, b, c, d, F3, K3, M(51) );
302  R( d, e, a, b, c, F3, K3, M(52) );
303  R( c, d, e, a, b, F3, K3, M(53) );
304  R( b, c, d, e, a, F3, K3, M(54) );
305  R( a, b, c, d, e, F3, K3, M(55) );
306  R( e, a, b, c, d, F3, K3, M(56) );
307  R( d, e, a, b, c, F3, K3, M(57) );
308  R( c, d, e, a, b, F3, K3, M(58) );
309  R( b, c, d, e, a, F3, K3, M(59) );
310  R( a, b, c, d, e, F4, K4, M(60) );
311  R( e, a, b, c, d, F4, K4, M(61) );
312  R( d, e, a, b, c, F4, K4, M(62) );
313  R( c, d, e, a, b, F4, K4, M(63) );
314  R( b, c, d, e, a, F4, K4, M(64) );
315  R( a, b, c, d, e, F4, K4, M(65) );
316  R( e, a, b, c, d, F4, K4, M(66) );
317  R( d, e, a, b, c, F4, K4, M(67) );
318  R( c, d, e, a, b, F4, K4, M(68) );
319  R( b, c, d, e, a, F4, K4, M(69) );
320  R( a, b, c, d, e, F4, K4, M(70) );
321  R( e, a, b, c, d, F4, K4, M(71) );
322  R( d, e, a, b, c, F4, K4, M(72) );
323  R( c, d, e, a, b, F4, K4, M(73) );
324  R( b, c, d, e, a, F4, K4, M(74) );
325  R( a, b, c, d, e, F4, K4, M(75) );
326  R( e, a, b, c, d, F4, K4, M(76) );
327  R( d, e, a, b, c, F4, K4, M(77) );
328  R( c, d, e, a, b, F4, K4, M(78) );
329  R( b, c, d, e, a, F4, K4, M(79) );
330 
331  a = hashsumA_ += a;
332  b = hashsumB_ += b;
333  c = hashsumC_ += c;
334  d = hashsumD_ += d;
335  e = hashsumE_ += e;
336  }
337 }
338 
339 
340 void Foam::SHA1::calcDigest(SHA1Digest& dig) const
341 {
342  if (bufTotal_[0] || bufTotal_[1])
343  {
344  unsigned char *r = dig.v_;
345 
346  set_uint32(r + 0 * sizeof(uint32_t), swapBytes(hashsumA_));
347  set_uint32(r + 1 * sizeof(uint32_t), swapBytes(hashsumB_));
348  set_uint32(r + 2 * sizeof(uint32_t), swapBytes(hashsumC_));
349  set_uint32(r + 3 * sizeof(uint32_t), swapBytes(hashsumD_));
350  set_uint32(r + 4 * sizeof(uint32_t), swapBytes(hashsumE_));
351  }
352  else
353  {
354  // no data!
355  dig.clear();
356  }
357 }
358 
359 
360 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
361 
362 // * * * * * * * * * * * * * * * * Selectors * * * * * * * * * * * * * * * * //
363 
364 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
365 
366 
367 // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
368 
369 
370 // * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
371 
372 
374 {
375  hashsumA_ = 0x67452301;
376  hashsumB_ = 0xefcdab89;
377  hashsumC_ = 0x98badcfe;
378  hashsumD_ = 0x10325476;
379  hashsumE_ = 0xc3d2e1f0;
380 
381  bufTotal_[0] = bufTotal_[1] = 0;
382  bufLen_ = 0;
383 
384  finalized_ = false;
385 }
386 
387 
389 {
390  if (!finalized_)
391  {
392  finalized_ = true;
393 
394  // account for unprocessed bytes
395  uint32_t bytes = bufLen_;
396  size_t size = (bytes < 56 ? 64 : 128) / sizeof(uint32_t);
397 
398  // count remaining bytes.
399  bufTotal_[0] += bytes;
400  if (bufTotal_[0] < bytes)
401  {
402  ++bufTotal_[1];
403  }
404 
405  // finalized, but no data!
406  if (!bufTotal_[0] && !bufTotal_[1])
407  {
408  return false;
409  }
410 
411  // place the 64-bit file length in *bits* at the end of the buffer.
412  buffer_[size-2] = swapBytes((bufTotal_[1] << 3) | (bufTotal_[0] >> 29));
413  buffer_[size-1] = swapBytes(bufTotal_[0] << 3);
414 
415  unsigned char* bufp = reinterpret_cast<unsigned char *>(buffer_);
416 
417  memcpy(&bufp[bytes], fillbuf, (size-2) * sizeof(uint32_t) - bytes);
418 
419  // Process remaining bytes
420  processBlock(buffer_, size * sizeof(uint32_t));
421  }
422 
423  return true;
424 }
425 
426 
428 {
429  SHA1Digest dig;
430 
431  if (finalized_)
432  {
433  calcDigest(dig);
434  }
435  else
436  {
437  // avoid disturbing our data - use a copy
438  SHA1 sha(*this);
439  if (sha.finalize())
440  {
441  sha.calcDigest(dig);
442  }
443  }
444 
445  return dig;
446 }
447 
448 
449 // * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * * //
450 
451 // void Foam::SHA1::operator=(const SHA1& rhs)
452 // {
453 // // Check for assignment to self
454 // if (this == &rhs)
455 // {
456 // FatalErrorIn("Foam::SHA1::operator=(const Foam::SHA1&)")
457 // << "Attempted assignment to self"
458 // << abort(FatalError);
459 // }
460 // }
461 
462 
463 // ************************************************************************* //
label n
#define F3(B, C, D)
Definition: SHA1.C:196
bool finalize()
Finalized the calculations (normally not needed directly).
Definition: SHA1.C:388
void add(FieldField< Field1, typename typeOfSum< Type1, Type2 >::type > &f, const FieldField< Field1, Type1 > &f1, const FieldField< Field2, Type2 > &f2)
const double e
Definition: doubleFloat.H:78
Useful combination of include files which define Sin, Sout and Serr and the use of IO streams general...
#define M(I)
void clear()
Reset the hashed data before appending more.
Definition: SHA1.C:373
The SHA1 message digest.
Definition: SHA1Digest.H:63
#define K4
Definition: SHA1.C:191
#define F4(B, C, D)
Definition: SHA1.C:197
#define F2(B, C, D)
Definition: SHA1.C:195
#define K1
Definition: SHA1.C:188
const dimensionedScalar b
Wien displacement law constant: default SI units: [m.K].
Definition: createFields.H:28
volScalarField::GeometricBoundaryField d(nearWallDist(mesh).y())
Functions to compute SHA1 message digest according to the NIST specification FIPS-180-1.
Definition: SHA1.H:69
UEqn clear()
const dimensionedScalar c
Speed of light in a vacuum.
SHA1Digest digest() const
Calculate current digest from appended data.
Definition: SHA1.C:427
#define K2
Definition: SHA1.C:189
#define K3
Definition: SHA1.C:190
#define R(A, B, C, D, E, F, K, M)
#define F1(B, C, D)
Definition: SHA1.C:194