_________ __                 __
        /   _____//  |_____________ _/  |______     ____  __ __  ______
        \_____  \\   __\_  __ \__  \\   __\__  \   / ___\|  |  \/  ___/
        /        \|  |  |  | \// __ \|  |  / __ \_/ /_/  >  |  /\___ \
       /_______  /|__|  |__|  (____  /__| (____  /\___  /|____//____  >
               \/                  \/          \//_____/            \/
    ______________________                           ______________________
                          T H E   W A R   B E G I N S
                   Stratagus - A free fantasy real time strategy game engine

xsha1.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2020 The Stratagus Project
3  * Copyright (C) 1999 Descolada (dyn1-tnt9-237.chicago.il.ameritech.net)
4  * Copyright (C) 1999,2000,2001 Ross Combs ([email protected])
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19  */
20 #include <cstdint>
21 #include <cstdio>
22 #include <cstring>
23 
24 /* valid for 0<=n and w>0 , depends on 2's complement */
25 #define ROTL(x,n,w) (((x)<<((n)&(w-1))) | ((x)>>(((-(n))&(w-1)))))
26 
27 /* valid for 0<=n and w>0 , uses three mods and an ugly conditional */
28 /* FIXME: and also a bug because it doesn't work on PPC */
29 /*#define ROTL(x,n,w) (((n)%(w)) ? (((x)<<((n)%(w))) | ((x)>>((w)-((n)%(w))))) : (x))*/
30 
31 #define ROTL32(x,n) ROTL(x,n,32)
32 #define ROTL16(x,n) ROTL(x,n,16)
33 
34 
35 namespace pvpgn
36 {
37  using bn_basic = std::uint8_t;
38  using bn_byte = bn_basic[1];
39  using bn_short = bn_basic[2];
40  using bn_int = bn_basic[4];
41  using bn_long = bn_basic[8];
42  using t_hash = std::uint32_t[5];
43 
44  int bn_int_set(bn_int * dst, std::uint32_t src)
45  {
46  if (!dst)
47  {
48  return -1;
49  }
50 
51  (*dst)[0] = (std::uint8_t)((src)& 0xff);
52  (*dst)[1] = (std::uint8_t)((src >> 8) & 0xff);
53  (*dst)[2] = (std::uint8_t)((src >> 16) & 0xff);
54  (*dst)[3] = (std::uint8_t)((src >> 24));
55  return 0;
56  }
57 
58  int bn_int_nset(bn_int * dst, std::uint32_t src)
59  {
60  if (!dst)
61  {
62  return -1;
63  }
64 
65  (*dst)[0] = (std::uint8_t)((src >> 24));
66  (*dst)[1] = (std::uint8_t)((src >> 16) & 0xff);
67  (*dst)[2] = (std::uint8_t)((src >> 8) & 0xff);
68  (*dst)[3] = (std::uint8_t)((src)& 0xff);
69  return 0;
70  }
71 
72  std::uint32_t bn_int_get(bn_int const src)
73  {
74  std::uint32_t temp;
75 
76  if (!src)
77  {
78  return 0;
79  }
80 
81  temp = ((std::uint32_t)src[0]);
82  temp |= ((std::uint32_t)src[1]) << 8;
83  temp |= ((std::uint32_t)src[2]) << 16;
84  temp |= ((std::uint32_t)src[3]) << 24;
85  return temp;
86  }
87 
88  typedef enum {
92 
93  static void hash_init(t_hash * hash);
94  static void do_hash(t_hash * hash, std::uint32_t * tmp);
95  static void hash_set_16(std::uint32_t * dst, unsigned char const * src, unsigned int count, t_hash_variant hash_variant);
96 
97 
98  static void hash_init(t_hash * hash)
99  {
100  (*hash)[0] = 0x67452301;
101  (*hash)[1] = 0xefcdab89;
102  (*hash)[2] = 0x98badcfe;
103  (*hash)[3] = 0x10325476;
104  (*hash)[4] = 0xc3d2e1f0;
105  }
106 
107 
108  static void do_hash(t_hash * hash, std::uint32_t * tmp, t_hash_variant hash_variant)
109  {
110  unsigned int i;
111  std::uint32_t a, b, c, d, e, g;
112 
113  for (i = 0; i < 64; i++)
114  if (hash_variant == do_blizzard_hash)
115  tmp[i + 16] = ROTL32(1, tmp[i] ^ tmp[i + 8] ^ tmp[i + 2] ^ tmp[i + 13]);
116  else
117  tmp[i + 16] = ROTL32(tmp[i] ^ tmp[i + 8] ^ tmp[i + 2] ^ tmp[i + 13], 1);
118 
119  a = (*hash)[0];
120  b = (*hash)[1];
121  c = (*hash)[2];
122  d = (*hash)[3];
123  e = (*hash)[4];
124 
125  for (i = 0; i < 20 * 1; i++)
126  {
127  g = tmp[i] + ROTL32(a, 5) + e + ((b & c) | (~b & d)) + 0x5a827999;
128  e = d;
129  d = c;
130  c = ROTL32(b, 30);
131  b = a;
132  a = g;
133  }
134 
135  for (; i < 20 * 2; i++)
136  {
137  g = (d ^ c ^ b) + e + ROTL32(g, 5) + tmp[i] + 0x6ed9eba1;
138  e = d;
139  d = c;
140  c = ROTL32(b, 30);
141  b = a;
142  a = g;
143  }
144 
145  for (; i < 20 * 3; i++)
146  {
147  g = tmp[i] + ROTL32(g, 5) + e + ((c & b) | (d & c) | (d & b)) - 0x70e44324;
148  e = d;
149  d = c;
150  c = ROTL32(b, 30);
151  b = a;
152  a = g;
153  }
154 
155  for (; i < 20 * 4; i++)
156  {
157  g = (d ^ c ^ b) + e + ROTL32(g, 5) + tmp[i] - 0x359d3e2a;
158  e = d;
159  d = c;
160  c = ROTL32(b, 30);
161  b = a;
162  a = g;
163  }
164 
165  (*hash)[0] += g;
166  (*hash)[1] += b;
167  (*hash)[2] += c;
168  (*hash)[3] += d;
169  (*hash)[4] += e;
170  }
171 
172 
173  /*
174  * Fill 16 elements of the array of 32 bit values with the bytes from
175  * dst up to count in little endian order. Fill left over space with
176  * zeros. In case of SHA1 hash variant a binary 1 is appended after
177  * the actual data.
178  */
179  static void hash_set_16(std::uint32_t * dst, unsigned char const * src, unsigned int count,
180  t_hash_variant hash_variant)
181  {
182  unsigned int i;
183  unsigned int pos;
184 
185  for (pos = 0, i = 0; i < 16; i++)
186  {
187  dst[i] = 0;
188 
189  if (hash_variant == do_blizzard_hash) {
190  if (pos < count)
191  dst[i] |= ((std::uint32_t)src[pos]);
192  }
193  else {
194  if (pos < count)
195  dst[i] |= ((std::uint32_t)src[pos]) << 24;
196  else if (pos == count)
197  dst[i] |= ((std::uint32_t)0x80000000);
198  }
199  pos++;
200 
201  if (hash_variant == do_blizzard_hash) {
202  if (pos < count)
203  dst[i] |= ((std::uint32_t)src[pos]) << 8;
204  }
205  else {
206  if (pos < count)
207  dst[i] |= ((std::uint32_t)src[pos]) << 16;
208  else if (pos == count)
209  dst[i] |= ((std::uint32_t)0x800000);
210  }
211  pos++;
212 
213  if (hash_variant == do_blizzard_hash) {
214  if (pos < count)
215  dst[i] |= ((std::uint32_t)src[pos]) << 16;
216  }
217  else {
218  if (pos < count)
219  dst[i] |= ((std::uint32_t)src[pos]) << 8;
220  else if (pos == count)
221  dst[i] |= ((std::uint32_t)0x8000);
222  }
223  pos++;
224 
225  if (hash_variant == do_blizzard_hash) {
226  if (pos < count)
227  dst[i] |= ((std::uint32_t)src[pos]) << 24;
228  }
229  else {
230  if (pos < count)
231  dst[i] |= ((std::uint32_t)src[pos]);
232  else if (pos == count)
233  dst[i] |= ((std::uint32_t)0x80);
234  }
235  pos++;
236  }
237  }
238 
239 
240  extern int bnet_hash(t_hash * hashout, unsigned int size, void const * datain)
241  {
242  std::uint32_t tmp[64 + 16];
243  const unsigned char* data;
244  unsigned int inc;
245 
246  if (!hashout)
247  {
248  return -1;
249  }
250  if (size > 0 && !datain)
251  {
252  return -1;
253  }
254 
255  hash_init(hashout);
256 
257  data = (const unsigned char*)datain;
258  while (size > 0)
259  {
260  if (size > 64)
261  inc = 64;
262  else
263  inc = size;
264 
265  hash_set_16(tmp, data, inc, do_blizzard_hash);
266  do_hash(hashout, tmp, do_blizzard_hash);
267 
268  data += inc;
269  size -= inc;
270  }
271 
272  return 0;
273  }
274 
275  static void hash_set_length(std::uint32_t * dst, unsigned int size){
276  std::uint32_t size_high = 0;
277  std::uint32_t size_low = 0;
278  unsigned int counter;
279  for (counter = 0; counter < size; counter++){
280  size_low += 8;
281  if (size_low == 0)
282  size_high++;
283  }
284 
285  dst[14] |= ((size_high >> 24) & 0xff) << 24;
286  dst[14] |= ((size_high >> 16) & 0xff) << 16;
287  dst[14] |= ((size_high >> 8) & 0xff) << 8;
288  dst[14] |= ((size_high)& 0xff);
289 
290  dst[15] |= ((size_low >> 24) & 0xff) << 24;
291  dst[15] |= ((size_low >> 16) & 0xff) << 16;
292  dst[15] |= ((size_low >> 8) & 0xff) << 8;
293  dst[15] |= ((size_low)& 0xff);
294  }
295 
296  extern int sha1_hash(t_hash * hashout, unsigned int size, void const * datain)
297  {
298  std::uint32_t tmp[64 + 16];
299  unsigned char const * data;
300  unsigned int inc;
301  unsigned int orgSize;
302 
303  if (!hashout)
304  {
305  return -1;
306  }
307  if (size > 0 && !datain)
308  {
309  return -1;
310  }
311 
312  hash_init(hashout);
313  orgSize = size;
314 
315  data = (const unsigned char*)datain;
316  while (size > 0)
317  {
318  if (size >= 64)
319  inc = 64;
320  else
321  inc = size;
322 
323  if (size >= 64)
324  {
325  hash_set_16(tmp, data, inc, do_sha1_hash);
326  do_hash(hashout, tmp, do_sha1_hash);
327  }
328  else if (size > 55){
329 
330  hash_set_16(tmp, data, inc, do_sha1_hash);
331  do_hash(hashout, tmp, do_sha1_hash);
332 
333  // now use blizz variant as we only wanna fill in zeros
334  hash_set_16(tmp, data, 0, do_blizzard_hash);
335  hash_set_length(tmp, orgSize);
336  do_hash(hashout, tmp, do_sha1_hash);
337  }
338  else{
339  hash_set_16(tmp, data, inc, do_sha1_hash);
340  hash_set_length(tmp, orgSize);
341  do_hash(hashout, tmp, do_sha1_hash);
342  }
343 
344  data += inc;
345  size -= inc;
346  }
347 
348  return 0;
349  }
350 
351  extern int little_endian_sha1_hash(t_hash * hashout, unsigned int size, void const * datain)
352  {
353  bn_int value;
354  unsigned int i;
355  sha1_hash(hashout, size, datain);
356  for (i = 0; i < 5; i++)
357  {
358  bn_int_nset(&value, (*hashout)[i]);
359  (*hashout)[i] = bn_int_get(value);
360  }
361  return 0;
362  }
363 
364  extern int hash_eq(t_hash const h1, t_hash const h2)
365  {
366  unsigned int i;
367 
368  if (!h1 || !h2)
369  {
370  return -1;
371  }
372 
373  for (i = 0; i < 5; i++) {
374  if (h1[i] != h2[i]) {
375  return 0;
376  }
377  }
378 
379  return 1;
380  }
381 
382 
383  extern char const * hash_get_str(t_hash const hash)
384  {
385  static char temp[8 * 5 + 1]; /* each of 5 ints to 8 chars + null */
386  unsigned int i;
387 
388  if (!hash)
389  {
390  return NULL;
391  }
392 
393  for (i = 0; i < 5; i++)
394  std::sprintf(&temp[i * 8], "%08x", hash[i]);
395 
396  return temp;
397  }
398 
399  extern char const * little_endian_hash_get_str(t_hash const hash)
400  {
401  bn_int value;
402  t_hash be_hash;
403  unsigned int i;
404  for (i = 0; i < 5; i++)
405  {
406  bn_int_nset(&value, hash[i]);
407  be_hash[i] = bn_int_get(value);
408  }
409  return hash_get_str(be_hash);
410  }
411 
412 
413  extern int hash_set_str(t_hash * hash, char const * str)
414  {
415  unsigned int i;
416 
417  if (!hash)
418  {
419  return -1;
420  }
421  if (!*hash)
422  {
423  return -1;
424  }
425  if (!str)
426  {
427  return -1;
428  }
429  if (std::strlen(str) != 5 * 8)
430  {
431  return -1;
432  }
433 
434  for (i = 0; i < 5; i++)
435  if (std::sscanf(&str[i * 8], "%8x", &(*hash)[i]) != 1)
436  {
437  return -1;
438  }
439 
440  return 0;
441  }
442 
443  void bnhash_to_hash(bn_int const * bnhash, t_hash * hash)
444  {
445  unsigned int i;
446 
447  if (!bnhash)
448  {
449  return;
450  }
451  if (!hash)
452  {
453  return;
454  }
455 
456  for (i = 0; i < 5; i++)
457  (*hash)[i] = bn_int_get(bnhash[i]);
458  }
459 
460 
461  void hash_to_bnhash(t_hash const * hash, bn_int * bnhash)
462  {
463  unsigned int i;
464 
465  if (!bnhash)
466  {
467  return;
468  }
469  if (!hash)
470  {
471  return;
472  }
473 
474  for (i = 0; i < 5; i++)
475  bn_int_set(&bnhash[i], (*hash)[i]);
476  }
477 
478 }
pvpgn
Definition: xsha1.h:35
pvpgn::bn_int_get
std::uint32_t bn_int_get(bn_int const src)
Definition: xsha1.h:72
pvpgn::t_hash_variant
t_hash_variant
Definition: xsha1.h:88
pvpgn::little_endian_sha1_hash
int little_endian_sha1_hash(t_hash *hashout, unsigned int size, void const *datain)
Definition: xsha1.h:351
pvpgn::hash_set_str
int hash_set_str(t_hash *hash, char const *str)
Definition: xsha1.h:413
pvpgn::bn_int_nset
int bn_int_nset(bn_int *dst, std::uint32_t src)
Definition: xsha1.h:58
pvpgn::do_hash
static void do_hash(t_hash *hash, std::uint32_t *tmp)
pvpgn::bnet_hash
int bnet_hash(t_hash *hashout, unsigned int size, void const *datain)
Definition: xsha1.h:240
pvpgn::bn_short
bn_basic[2] bn_short
Definition: xsha1.h:39
pvpgn::bnhash_to_hash
void bnhash_to_hash(bn_int const *bnhash, t_hash *hash)
Definition: xsha1.h:443
pvpgn::hash_to_bnhash
void hash_to_bnhash(t_hash const *hash, bn_int *bnhash)
Definition: xsha1.h:461
pvpgn::bn_int
bn_basic[4] bn_int
Definition: xsha1.h:40
pvpgn::hash_init
static void hash_init(t_hash *hash)
Definition: xsha1.h:98
pvpgn::sha1_hash
int sha1_hash(t_hash *hashout, unsigned int size, void const *datain)
Definition: xsha1.h:296
pvpgn::bn_long
bn_basic[8] bn_long
Definition: xsha1.h:41
pvpgn::do_blizzard_hash
@ do_blizzard_hash
Definition: xsha1.h:89
pvpgn::hash_set_length
static void hash_set_length(std::uint32_t *dst, unsigned int size)
Definition: xsha1.h:275
pvpgn::hash_set_16
static void hash_set_16(std::uint32_t *dst, unsigned char const *src, unsigned int count, t_hash_variant hash_variant)
Definition: xsha1.h:179
pvpgn::t_hash
std::uint32_t[5] t_hash
Definition: xsha1.h:42
pvpgn::bn_int_set
int bn_int_set(bn_int *dst, std::uint32_t src)
Definition: xsha1.h:44
pvpgn::hash_eq
int hash_eq(t_hash const h1, t_hash const h2)
Definition: xsha1.h:364
pvpgn::bn_byte
bn_basic[1] bn_byte
Definition: xsha1.h:38
pvpgn::hash_get_str
const char * hash_get_str(t_hash const hash)
Definition: xsha1.h:383
ROTL32
#define ROTL32(x, n)
Definition: xsha1.h:31
pvpgn::do_sha1_hash
@ do_sha1_hash
Definition: xsha1.h:90
pvpgn::little_endian_hash_get_str
const char * little_endian_hash_get_str(t_hash const hash)
Definition: xsha1.h:399
pvpgn::bn_basic
std::uint8_t bn_basic
Definition: xsha1.h:37
(C) Copyright 1998-2012 by The Stratagus Project under the GNU General Public License.
All trademarks and copyrights on this page are owned by their respective owners.