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 -------------------------------------------------------------------------------
11 License
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 
27 Description
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)
49 static 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
57 static 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
69 static 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 
78 void 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 
158 void 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 
294 void 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 
315 void Foam::SHA1::clear() noexcept
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 // ************************************************************************* //
Foam::SHA1::clear
void clear() noexcept
Reset the hashed data before appending more.
Definition: SHA1.C:315
F1
#define F1(B, C, D)
Definition: SHA1.C:150
IOstreams.H
Useful combination of include files which define Sin, Sout and Serr and the use of IO streams general...
K1
#define K1
Definition: SHA1.C:144
K4
#define K4
Definition: SHA1.C:147
K3
#define K3
Definition: SHA1.C:146
n
label n
Definition: TABSMDCalcMethod2.H:31
R
#define R(A, B, C, D, E, F, K, M)
Foam::constant::physicoChemical::b
const dimensionedScalar b
Wien displacement law constant: default SI units: [m.K].
Definition: createFields.H:27
F3
#define F3(B, C, D)
Definition: SHA1.C:152
K2
#define K2
Definition: SHA1.C:145
Foam::add
void add(FieldField< Field1, typename typeOfSum< Type1, Type2 >::type > &f, const FieldField< Field1, Type1 > &f1, const FieldField< Field2, Type2 > &f2)
Definition: FieldFieldFunctions.C:939
Foam::endian::swap32
static uint32_t swap32(uint32_t)
Byte endian swapping for 32-bits.
Definition: endianI.H:61
M
#define M(I)
Foam::constant::electromagnetic::e
const dimensionedScalar e
Elementary charge.
Definition: createFields.H:11
x
x
Definition: LISASMDCalcMethod2.H:52
Foam::constant::universal::c
const dimensionedScalar c
Speed of light in a vacuum.
Foam::SHA1::finalize
bool finalize()
Finalized the calculations (normally not needed directly).
Definition: SHA1.C:330
endian.H
Help with architecture-specific aspects.
SHA1.H
F2
#define F2(B, C, D)
Definition: SHA1.C:151
F4
#define F4(B, C, D)
Definition: SHA1.C:153