FreeFOAM The Cross-Platform CFD Toolkit
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) 1991-2010 OpenCFD Ltd.
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 <OpenFOAM/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 (((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24));
64 # endif
65 
66 #else
67 
68  const short x = 0x0100;
69 
70  // yields 0x01 for big endian
71  if (*(reinterpret_cast<const char *>(&x)))
72  {
73  return n;
74  }
75  else
76  {
77  return (((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24));
78  }
79 #endif
80 }
81 
82 
83 inline void
84 Foam::SHA1::set_uint32(unsigned char *cp, uint32_t v)
85 {
86  memcpy(cp, &v, sizeof(uint32_t));
87 }
88 
89 
90 // * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * //
91 
92 
93 void Foam::SHA1::processBytes(const void *data, size_t len)
94 {
95  // already finalized, thus need to restart from nothing
96  if (finalized_)
97  {
98  clear();
99  }
100 
101  // complete filling of internal buffer
102  if (bufLen_)
103  {
104  size_t remaining = bufLen_;
105  size_t add =
106  (
107  sizeof(buffer_) - remaining > len
108  ? len
109  : sizeof(buffer_) - remaining
110  );
111 
112  unsigned char* bufp = reinterpret_cast<unsigned char*>(buffer_);
113 
114  memcpy(&bufp[remaining], data, add);
115  bufLen_ += add;
116 
117  if (bufLen_ > 64)
118  {
119  processBlock(buffer_, bufLen_ & ~63);
120 
121  bufLen_ &= 63;
122  // The regions in the following copy operation do not (cannot) overlap
123  memcpy(buffer_, &bufp[(remaining + add) & ~63], bufLen_);
124  }
125 
126  data = reinterpret_cast<const unsigned char*>(data) + add;
127  len -= add;
128  }
129 
130  // Process available complete blocks
131 // if (len >= 64)
132 // {
133 //#if !_STRING_ARCH_unaligned
134 //# define alignof(type) offsetof (struct { char c; type x; }, x)
135 //# define UNALIGNED_P(p) (((size_t) p) % alignof (uint32_t) != 0)
136 // if (UNALIGNED_P (data))
137 // {
138  while (len >= 64)
139  {
140  processBlock(memcpy (buffer_, data, 64), 64);
141  data = reinterpret_cast<const unsigned char*>(data) + 64;
142  len -= 64;
143  }
144 // }
145 // else
146 //#endif
147 // {
148 // processBlock(data, len & ~63);
149 // data = reinterpret_cast<const unsigned char*>(data) + (len & ~63);
150 // len &= 63;
151 // }
152 // }
153 
154  // Move remaining bytes in internal buffer.
155  if (len > 0)
156  {
157  unsigned char* bufp = reinterpret_cast<unsigned char*>(buffer_);
158  size_t remaining = bufLen_;
159 
160  memcpy (&bufp[remaining], data, len);
161  remaining += len;
162  if (remaining >= 64)
163  {
164  processBlock(buffer_, 64);
165  remaining -= 64;
166  memcpy (buffer_, &buffer_[16], remaining);
167  }
168  bufLen_ = remaining;
169  }
170 }
171 
172 
173 // SHA1 round constants
174 #define K1 0x5a827999
175 #define K2 0x6ed9eba1
176 #define K3 0x8f1bbcdc
177 #define K4 0xca62c1d6
178 
179 // Round functions. Note that F2 is the same as F4.
180 #define F1(B,C,D) ( D ^ ( B & ( C ^ D ) ) )
181 #define F2(B,C,D) (B ^ C ^ D)
182 #define F3(B,C,D) ( ( B & C ) | ( D & ( B | C ) ) )
183 #define F4(B,C,D) (B ^ C ^ D)
184 
185 // Process LEN bytes of BUFFER, it is assumed that LEN % 64 == 0.
186 // Most of this code comes from GnuPG's cipher/sha1.c
187 
188 void
189 Foam::SHA1::processBlock(const void *data, size_t len)
190 {
191  const uint32_t *words = reinterpret_cast<const uint32_t*>(data);
192  size_t nwords = len / sizeof(uint32_t);
193  const uint32_t *endp = words + nwords;
194 
195  // calculate with sixteen words of 32-bits
196  uint32_t x[16];
197  uint32_t a = hashsumA_;
198  uint32_t b = hashsumB_;
199  uint32_t c = hashsumC_;
200  uint32_t d = hashsumD_;
201  uint32_t e = hashsumE_;
202 
203  // First increment the byte count.
204  // RFC 1321 specifies the possible length of the file up to 2^64 bits.
205  // Here we only compute the number of bytes. Do a double word increment.
206  bufTotal_[0] += len;
207  if (bufTotal_[0] < len)
208  {
209  ++bufTotal_[1];
210  }
211 
212  // rotate left uint32_t by n bits
213 #define rol_uint32(x, nbits) (((x) << (nbits)) | ((x) >> (32 - (nbits))))
214 
215 #define M(I) ( tm = x[I & 0x0F] ^ x[(I-14) & 0x0F] \
216  ^ x[(I-8) & 0x0F] ^ x[(I-3) & 0x0F] \
217  , (x[I & 0x0F] = rol_uint32(tm, 1)) )
218 
219 
220 #define R(A,B,C,D,E,F,K,M) \
221  do \
222  { \
223  E += rol_uint32(A, 5) + F(B, C, D) + K + M; \
224  B = rol_uint32(B, 30); \
225  } while(0)
226 
227  while (words < endp)
228  {
229  uint32_t tm;
230  for (int t = 0; t < 16; t++)
231  {
232  x[t] = swapBytes (*words);
233  words++;
234  }
235 
236  R( a, b, c, d, e, F1, K1, x[ 0] );
237  R( e, a, b, c, d, F1, K1, x[ 1] );
238  R( d, e, a, b, c, F1, K1, x[ 2] );
239  R( c, d, e, a, b, F1, K1, x[ 3] );
240  R( b, c, d, e, a, F1, K1, x[ 4] );
241  R( a, b, c, d, e, F1, K1, x[ 5] );
242  R( e, a, b, c, d, F1, K1, x[ 6] );
243  R( d, e, a, b, c, F1, K1, x[ 7] );
244  R( c, d, e, a, b, F1, K1, x[ 8] );
245  R( b, c, d, e, a, F1, K1, x[ 9] );
246  R( a, b, c, d, e, F1, K1, x[10] );
247  R( e, a, b, c, d, F1, K1, x[11] );
248  R( d, e, a, b, c, F1, K1, x[12] );
249  R( c, d, e, a, b, F1, K1, x[13] );
250  R( b, c, d, e, a, F1, K1, x[14] );
251  R( a, b, c, d, e, F1, K1, x[15] );
252  R( e, a, b, c, d, F1, K1, M(16) );
253  R( d, e, a, b, c, F1, K1, M(17) );
254  R( c, d, e, a, b, F1, K1, M(18) );
255  R( b, c, d, e, a, F1, K1, M(19) );
256  R( a, b, c, d, e, F2, K2, M(20) );
257  R( e, a, b, c, d, F2, K2, M(21) );
258  R( d, e, a, b, c, F2, K2, M(22) );
259  R( c, d, e, a, b, F2, K2, M(23) );
260  R( b, c, d, e, a, F2, K2, M(24) );
261  R( a, b, c, d, e, F2, K2, M(25) );
262  R( e, a, b, c, d, F2, K2, M(26) );
263  R( d, e, a, b, c, F2, K2, M(27) );
264  R( c, d, e, a, b, F2, K2, M(28) );
265  R( b, c, d, e, a, F2, K2, M(29) );
266  R( a, b, c, d, e, F2, K2, M(30) );
267  R( e, a, b, c, d, F2, K2, M(31) );
268  R( d, e, a, b, c, F2, K2, M(32) );
269  R( c, d, e, a, b, F2, K2, M(33) );
270  R( b, c, d, e, a, F2, K2, M(34) );
271  R( a, b, c, d, e, F2, K2, M(35) );
272  R( e, a, b, c, d, F2, K2, M(36) );
273  R( d, e, a, b, c, F2, K2, M(37) );
274  R( c, d, e, a, b, F2, K2, M(38) );
275  R( b, c, d, e, a, F2, K2, M(39) );
276  R( a, b, c, d, e, F3, K3, M(40) );
277  R( e, a, b, c, d, F3, K3, M(41) );
278  R( d, e, a, b, c, F3, K3, M(42) );
279  R( c, d, e, a, b, F3, K3, M(43) );
280  R( b, c, d, e, a, F3, K3, M(44) );
281  R( a, b, c, d, e, F3, K3, M(45) );
282  R( e, a, b, c, d, F3, K3, M(46) );
283  R( d, e, a, b, c, F3, K3, M(47) );
284  R( c, d, e, a, b, F3, K3, M(48) );
285  R( b, c, d, e, a, F3, K3, M(49) );
286  R( a, b, c, d, e, F3, K3, M(50) );
287  R( e, a, b, c, d, F3, K3, M(51) );
288  R( d, e, a, b, c, F3, K3, M(52) );
289  R( c, d, e, a, b, F3, K3, M(53) );
290  R( b, c, d, e, a, F3, K3, M(54) );
291  R( a, b, c, d, e, F3, K3, M(55) );
292  R( e, a, b, c, d, F3, K3, M(56) );
293  R( d, e, a, b, c, F3, K3, M(57) );
294  R( c, d, e, a, b, F3, K3, M(58) );
295  R( b, c, d, e, a, F3, K3, M(59) );
296  R( a, b, c, d, e, F4, K4, M(60) );
297  R( e, a, b, c, d, F4, K4, M(61) );
298  R( d, e, a, b, c, F4, K4, M(62) );
299  R( c, d, e, a, b, F4, K4, M(63) );
300  R( b, c, d, e, a, F4, K4, M(64) );
301  R( a, b, c, d, e, F4, K4, M(65) );
302  R( e, a, b, c, d, F4, K4, M(66) );
303  R( d, e, a, b, c, F4, K4, M(67) );
304  R( c, d, e, a, b, F4, K4, M(68) );
305  R( b, c, d, e, a, F4, K4, M(69) );
306  R( a, b, c, d, e, F4, K4, M(70) );
307  R( e, a, b, c, d, F4, K4, M(71) );
308  R( d, e, a, b, c, F4, K4, M(72) );
309  R( c, d, e, a, b, F4, K4, M(73) );
310  R( b, c, d, e, a, F4, K4, M(74) );
311  R( a, b, c, d, e, F4, K4, M(75) );
312  R( e, a, b, c, d, F4, K4, M(76) );
313  R( d, e, a, b, c, F4, K4, M(77) );
314  R( c, d, e, a, b, F4, K4, M(78) );
315  R( b, c, d, e, a, F4, K4, M(79) );
316 
317  a = hashsumA_ += a;
318  b = hashsumB_ += b;
319  c = hashsumC_ += c;
320  d = hashsumD_ += d;
321  e = hashsumE_ += e;
322  }
323 }
324 
325 
326 void Foam::SHA1::calcDigest(SHA1Digest& dig) const
327 {
328  if (bufTotal_[0] || bufTotal_[1])
329  {
330  unsigned char *r = dig.v_;
331 
332  set_uint32 (r + 0 * sizeof(uint32_t), swapBytes(hashsumA_));
333  set_uint32 (r + 1 * sizeof(uint32_t), swapBytes(hashsumB_));
334  set_uint32 (r + 2 * sizeof(uint32_t), swapBytes(hashsumC_));
335  set_uint32 (r + 3 * sizeof(uint32_t), swapBytes(hashsumD_));
336  set_uint32 (r + 4 * sizeof(uint32_t), swapBytes(hashsumE_));
337  }
338  else
339  {
340  // no data!
341  dig.clear();
342  }
343 }
344 
345 
346 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
347 
348 // * * * * * * * * * * * * * * * * Selectors * * * * * * * * * * * * * * * * //
349 
350 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
351 
352 
353 // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
354 
355 
356 // * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
357 
358 
360 {
361  hashsumA_ = 0x67452301;
362  hashsumB_ = 0xefcdab89;
363  hashsumC_ = 0x98badcfe;
364  hashsumD_ = 0x10325476;
365  hashsumE_ = 0xc3d2e1f0;
366 
367  bufTotal_[0] = bufTotal_[1] = 0;
368  bufLen_ = 0;
369 
370  finalized_ = false;
371 }
372 
373 
375 {
376  if (!finalized_)
377  {
378  finalized_ = true;
379 
380  // account for unprocessed bytes
381  uint32_t bytes = bufLen_;
382  size_t size = (bytes < 56 ? 64 : 128) / sizeof(uint32_t);
383 
384  // count remaining bytes.
385  bufTotal_[0] += bytes;
386  if (bufTotal_[0] < bytes)
387  {
388  ++bufTotal_[1];
389  }
390 
391  // finalized, but no data!
392  if (!bufTotal_[0] && !bufTotal_[1])
393  {
394  return false;
395  }
396 
397  // place the 64-bit file length in *bits* at the end of the buffer.
398  buffer_[size-2] = swapBytes((bufTotal_[1] << 3) | (bufTotal_[0] >> 29));
399  buffer_[size-1] = swapBytes(bufTotal_[0] << 3);
400 
401  unsigned char* bufp = reinterpret_cast<unsigned char *>(buffer_);
402 
403  memcpy(&bufp[bytes], fillbuf, (size-2) * sizeof(uint32_t) - bytes);
404 
405  // Process remaining bytes
406  processBlock(buffer_, size * sizeof(uint32_t));
407  }
408 
409  return true;
410 }
411 
412 
414 {
415  SHA1Digest dig;
416 
417  if (finalized_)
418  {
419  calcDigest(dig);
420  }
421  else
422  {
423  // avoid disturbing our data - use a copy
424  SHA1 sha(*this);
425  if (sha.finalize())
426  {
427  sha.calcDigest(dig);
428  }
429  }
430 
431  return dig;
432 }
433 
434 
435 // * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * * //
436 
437 // void Foam::SHA1::operator=(const SHA1& rhs)
438 // {
439 // // Check for assignment to self
440 // if (this == &rhs)
441 // {
442 // FatalErrorIn("Foam::SHA1::operator=(const Foam::SHA1&)")
443 // << "Attempted assignment to self"
444 // << abort(FatalError);
445 // }
446 // }
447 
448 // * * * * * * * * * * * * * * Friend Functions * * * * * * * * * * * * * * //
449 
450 
451 // * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * * //
452 
453 
454 // ************************ vim: set sw=4 sts=4 et: ************************ //