EvEmu  0.8.4
11 September 2021
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
ShaModule.h
Go to the documentation of this file.
1 /*
2  ------------------------------------------------------------------------------------
3  LICENSE:
4  ------------------------------------------------------------------------------------
5  This file is part of EVEmu: EVE Online Server Emulator
6  Copyright 2006 - 2021 The EVEmu Team
7  For the latest information visit https://evemu.dev
8  ------------------------------------------------------------------------------------
9  This program is free software; you can redistribute it and/or modify it under
10  the terms of the GNU Lesser General Public License as published by the Free Software
11  Foundation; either version 2 of the License, or (at your option) any later
12  version.
13 
14  This program is distributed in the hope that it will be useful, but WITHOUT
15  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16  FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
17 
18  You should have received a copy of the GNU Lesser General Public License along with
19  this program; if not, write to the Free Software Foundation, Inc., 59 Temple
20  Place - Suite 330, Boston, MA 02111-1307, USA, or go to
21  http://www.gnu.org/copyleft/lesser.txt.
22  ------------------------------------------------------------------------------------
23  Author: Captnoord
24 */
25 
26 #ifndef _SHA_MODULE_H
27 #define _SHA_MODULE_H
28 
38 class ShaModule
39 {
40 public:
41 
42  /* ------------------------------------------------------------------------
43  *
44  * Majority of this code is part of Python. The original
45  * headers are copied below.
46  *
47  * Several changes have been made to make it more compatible with the
48  * Evemu and its desired interface. Even Stole this comment header.
49  *
50  */
51 
52  /* Endianness testing and definitions */
53 #define TestEndianness(variable) {int i=1; variable=PCT_BIG_ENDIAN;\
54  if (*((char*)&i)==1) variable=PCT_LITTLE_ENDIAN;}
55 
56 #define PCT_LITTLE_ENDIAN 1
57 #define PCT_BIG_ENDIAN 0
58 
59  // Some useful types
60  typedef uint8 SHA_BYTE;
61  typedef uint32 SHA_INT32; // 32-bit integer
62 
63  // The SHA block size and message digest sizes, in bytes
64 
65 #define SHA_BLOCKSIZE 64
66 #define SHA_DIGESTSIZE 20
67 
68  // The structure for storing SHS info
69 
70  typedef struct {
71  SHA_INT32 digest[5]; /* Message digest */
72  SHA_INT32 count_lo, count_hi; /* 64-bit bit count */
73  SHA_BYTE data[SHA_BLOCKSIZE]; /* SHA data buffer */
75  int local; /* unprocessed amount in data */
76  } SHAobject;
77 
78  /* When run on a little-endian CPU we need to perform byte reversal on an
79  array of longwords. */
80 
81  static void longReverse(SHA_INT32 *buffer, int byteCount, int Endianness)
82  {
83  SHA_INT32 value;
84 
85  if ( Endianness == PCT_BIG_ENDIAN )
86  return;
87 
88  byteCount /= sizeof(*buffer);
89  while (byteCount--) {
90  value = *buffer;
91  value = ( ( value & 0xFF00FF00L ) >> 8 ) | \
92  ( ( value & 0x00FF00FFL ) << 8 );
93  *buffer++ = ( value << 16 ) | ( value >> 16 );
94  }
95  }
96 
97  static void SHAcopy(SHAobject *src, SHAobject *dest)
98  {
99  dest->Endianness = src->Endianness;
100  dest->local = src->local;
101  dest->count_lo = src->count_lo;
102  dest->count_hi = src->count_hi;
103  memcpy(dest->digest, src->digest, sizeof(src->digest));
104  memcpy(dest->data, src->data, sizeof(src->data));
105  }
106 
107 
108  /* ------------------------------------------------------------------------
109  *
110  * This code for the SHA algorithm was noted as public domain. The original
111  * headers are pasted below.
112  *
113  * Several changes have been made to make it more compatible with the
114  * Python environment and desired interface.
115  *
116  */
117 
118  /* NIST Secure Hash Algorithm */
119  /* heavily modified by Uwe Hollerbach <uh@alumni.caltech edu> */
120  /* from Peter C. Gutmann's implementation as found in */
121  /* Applied Cryptography by Bruce Schneier */
122  /* Further modifications to include the "UNRAVEL" stuff, below */
123 
124  /* This code is in the public domain */
125 
126  /* UNRAVEL should be fastest & biggest */
127  /* UNROLL_LOOPS should be just as big, but slightly slower */
128  /* both undefined should be smallest and slowest */
129 
130 #define UNRAVEL
131  /* #define UNROLL_LOOPS */
132 
133  /* The SHA f()-functions. The f1 and f3 functions can be optimized to
134  save one boolean operation each - thanks to Rich Schroeppel,
135  rcs@cs.arizona.edu for discovering this */
136 
137  /*#define f1(x,y,z) ((x & y) | (~x & z)) // Rounds 0-19 */
138 #define f1(x,y,z) (z ^ (x & (y ^ z))) /* Rounds 0-19 */
139 #define f2(x,y,z) (x ^ y ^ z) /* Rounds 20-39 */
140  /*#define f3(x,y,z) ((x & y) | (x & z) | (y & z)) // Rounds 40-59 */
141 #define f3(x,y,z) ((x & y) | (z & (x | y))) /* Rounds 40-59 */
142 #define f4(x,y,z) (x ^ y ^ z) /* Rounds 60-79 */
143 
144  /* SHA constants */
145 
146 #define CONST1 0x5a827999L /* Rounds 0-19 */
147 #define CONST2 0x6ed9eba1L /* Rounds 20-39 */
148 #define CONST3 0x8f1bbcdcL /* Rounds 40-59 */
149 #define CONST4 0xca62c1d6L /* Rounds 60-79 */
150 
151  /* 32-bit rotate */
152 
153 #define R32(x,n) ((x << n) | (x >> (32 - n)))
154 
155  /* the generic case, for when the overall rotation is not unraveled */
156 
157 #define FG(n) \
158  T = R32(A,5) + f##n(B,C,D) + E + *WP++ + CONST##n; \
159  E = D; D = C; C = R32(B,30); B = A; A = T
160 
161  /* specific cases, for when the overall rotation is unraveled */
162 
163 #define FA(n) \
164  T = R32(A,5) + f##n(B,C,D) + E + *WP++ + CONST##n; B = R32(B,30)
165 
166 #define FB(n) \
167  E = R32(T,5) + f##n(A,B,C) + D + *WP++ + CONST##n; A = R32(A,30)
168 
169 #define FC(n) \
170  D = R32(E,5) + f##n(T,A,B) + C + *WP++ + CONST##n; T = R32(T,30)
171 
172 #define FD(n) \
173  C = R32(D,5) + f##n(E,T,A) + B + *WP++ + CONST##n; E = R32(E,30)
174 
175 #define FE(n) \
176  B = R32(C,5) + f##n(D,E,T) + A + *WP++ + CONST##n; D = R32(D,30)
177 
178 #define FT(n) \
179  A = R32(B,5) + f##n(C,D,E) + T + *WP++ + CONST##n; C = R32(C,30)
180 
181  /* do SHA transformation */
182 
183  static void
185  {
186  int i;
187  SHA_INT32 T, A, B, C, D, E, W[80], *WP;
188 
189  memcpy(W, sha_info->data, sizeof(sha_info->data));
190  longReverse(W, (int)sizeof(sha_info->data), sha_info->Endianness);
191 
192  for (i = 16; i < 80; ++i) {
193  W[i] = W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16];
194 
195  /* extra rotation fix */
196  W[i] = R32(W[i], 1);
197  }
198  A = sha_info->digest[0];
199  B = sha_info->digest[1];
200  C = sha_info->digest[2];
201  D = sha_info->digest[3];
202  E = sha_info->digest[4];
203  WP = W;
204 #ifdef UNRAVEL
205  FA(1); FB(1); FC(1); FD(1); FE(1); FT(1); FA(1); FB(1); FC(1); FD(1);
206  FE(1); FT(1); FA(1); FB(1); FC(1); FD(1); FE(1); FT(1); FA(1); FB(1);
207  FC(2); FD(2); FE(2); FT(2); FA(2); FB(2); FC(2); FD(2); FE(2); FT(2);
208  FA(2); FB(2); FC(2); FD(2); FE(2); FT(2); FA(2); FB(2); FC(2); FD(2);
209  FE(3); FT(3); FA(3); FB(3); FC(3); FD(3); FE(3); FT(3); FA(3); FB(3);
210  FC(3); FD(3); FE(3); FT(3); FA(3); FB(3); FC(3); FD(3); FE(3); FT(3);
211  FA(4); FB(4); FC(4); FD(4); FE(4); FT(4); FA(4); FB(4); FC(4); FD(4);
212  FE(4); FT(4); FA(4); FB(4); FC(4); FD(4); FE(4); FT(4); FA(4); FB(4);
213  sha_info->digest[0] += E;
214  sha_info->digest[1] += T;
215  sha_info->digest[2] += A;
216  sha_info->digest[3] += B;
217  sha_info->digest[4] += C;
218 #else /* !UNRAVEL */
219 #ifdef UNROLL_LOOPS
220  FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1);
221  FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1);
222  FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2);
223  FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2);
224  FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3);
225  FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3);
226  FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4);
227  FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4);
228 #else /* !UNROLL_LOOPS */
229  for (i = 0; i < 20; ++i) { FG(1); }
230  for (i = 20; i < 40; ++i) { FG(2); }
231  for (i = 40; i < 60; ++i) { FG(3); }
232  for (i = 60; i < 80; ++i) { FG(4); }
233 #endif /* !UNROLL_LOOPS */
234  sha_info->digest[0] += A;
235  sha_info->digest[1] += B;
236  sha_info->digest[2] += C;
237  sha_info->digest[3] += D;
238  sha_info->digest[4] += E;
239 #endif /* !UNRAVEL */
240  }
241 
242  /* initialize the SHA digest */
243 
244  static void
245  sha_init(SHAobject *sha_info)
246  {
247  TestEndianness(sha_info->Endianness)
248 
249  sha_info->digest[0] = 0x67452301L;
250  sha_info->digest[1] = 0xefcdab89L;
251  sha_info->digest[2] = 0x98badcfeL;
252  sha_info->digest[3] = 0x10325476L;
253  sha_info->digest[4] = 0xc3d2e1f0L;
254  sha_info->count_lo = 0L;
255  sha_info->count_hi = 0L;
256  sha_info->local = 0;
257  }
258 
259  /* update the SHA digest */
260  static void
261  sha_update(SHAobject *sha_info, const SHA_BYTE *buffer, int count)
262  {
263  int i;
264  SHA_INT32 clo;
265 
266  clo = sha_info->count_lo + ((SHA_INT32) count << 3);
267  if (clo < sha_info->count_lo) {
268  ++sha_info->count_hi;
269  }
270  sha_info->count_lo = clo;
271  sha_info->count_hi += (SHA_INT32) count >> 29;
272  if (sha_info->local) {
273  i = SHA_BLOCKSIZE - sha_info->local;
274  if (i > count) {
275  i = count;
276  }
277  memcpy(((SHA_BYTE *) sha_info->data) + sha_info->local, buffer, i);
278  count -= i;
279  buffer += i;
280  sha_info->local += i;
281  if (sha_info->local == SHA_BLOCKSIZE) {
282  sha_transform(sha_info);
283  }
284  else {
285  return;
286  }
287  }
288  while (count >= SHA_BLOCKSIZE) {
289  memcpy(sha_info->data, buffer, SHA_BLOCKSIZE);
290  buffer += SHA_BLOCKSIZE;
291  count -= SHA_BLOCKSIZE;
292  sha_transform(sha_info);
293  }
294  memcpy(sha_info->data, buffer, count);
295  sha_info->local = count;
296  }
297 
298  static void
299  sha_update(SHAobject *sha_info, const std::wstring &value)
300  {
301  sha_update( sha_info,
302  reinterpret_cast< const SHA_BYTE* >( value.c_str() ),
303  value.size() * sizeof( wchar_t ) );
304  }
305 
306  /* finish computing the SHA digest */
307 
308  static void
309  sha_final(unsigned char digest[20], SHAobject *sha_info)
310  {
311  int count;
312  SHA_INT32 lo_bit_count, hi_bit_count;
313 
314  lo_bit_count = sha_info->count_lo;
315  hi_bit_count = sha_info->count_hi;
316  count = (int) ((lo_bit_count >> 3) & 0x3f);
317  ((SHA_BYTE *) sha_info->data)[count++] = 0x80;
318  if (count > SHA_BLOCKSIZE - 8) {
319  memset(((SHA_BYTE *) sha_info->data) + count, 0,
320  SHA_BLOCKSIZE - count);
321  sha_transform(sha_info);
322  memset((SHA_BYTE *) sha_info->data, 0, SHA_BLOCKSIZE - 8);
323  }
324  else {
325  memset(((SHA_BYTE *) sha_info->data) + count, 0,
326  SHA_BLOCKSIZE - 8 - count);
327  }
328 
329  /* GJS: note that we add the hi/lo in big-endian. sha_transform will
330  swap these values into host-order. */
331  sha_info->data[56] = (hi_bit_count >> 24) & 0xff;
332  sha_info->data[57] = (hi_bit_count >> 16) & 0xff;
333  sha_info->data[58] = (hi_bit_count >> 8) & 0xff;
334  sha_info->data[59] = (hi_bit_count >> 0) & 0xff;
335  sha_info->data[60] = (lo_bit_count >> 24) & 0xff;
336  sha_info->data[61] = (lo_bit_count >> 16) & 0xff;
337  sha_info->data[62] = (lo_bit_count >> 8) & 0xff;
338  sha_info->data[63] = (lo_bit_count >> 0) & 0xff;
339  sha_transform(sha_info);
340  digest[ 0] = (unsigned char) ((sha_info->digest[0] >> 24) & 0xff);
341  digest[ 1] = (unsigned char) ((sha_info->digest[0] >> 16) & 0xff);
342  digest[ 2] = (unsigned char) ((sha_info->digest[0] >> 8) & 0xff);
343  digest[ 3] = (unsigned char) ((sha_info->digest[0] ) & 0xff);
344  digest[ 4] = (unsigned char) ((sha_info->digest[1] >> 24) & 0xff);
345  digest[ 5] = (unsigned char) ((sha_info->digest[1] >> 16) & 0xff);
346  digest[ 6] = (unsigned char) ((sha_info->digest[1] >> 8) & 0xff);
347  digest[ 7] = (unsigned char) ((sha_info->digest[1] ) & 0xff);
348  digest[ 8] = (unsigned char) ((sha_info->digest[2] >> 24) & 0xff);
349  digest[ 9] = (unsigned char) ((sha_info->digest[2] >> 16) & 0xff);
350  digest[10] = (unsigned char) ((sha_info->digest[2] >> 8) & 0xff);
351  digest[11] = (unsigned char) ((sha_info->digest[2] ) & 0xff);
352  digest[12] = (unsigned char) ((sha_info->digest[3] >> 24) & 0xff);
353  digest[13] = (unsigned char) ((sha_info->digest[3] >> 16) & 0xff);
354  digest[14] = (unsigned char) ((sha_info->digest[3] >> 8) & 0xff);
355  digest[15] = (unsigned char) ((sha_info->digest[3] ) & 0xff);
356  digest[16] = (unsigned char) ((sha_info->digest[4] >> 24) & 0xff);
357  digest[17] = (unsigned char) ((sha_info->digest[4] >> 16) & 0xff);
358  digest[18] = (unsigned char) ((sha_info->digest[4] >> 8) & 0xff);
359  digest[19] = (unsigned char) ((sha_info->digest[4] ) & 0xff);
360  }
361 
362  static void
363  sha_digest(SHAobject *self, uint8 *digest)
364  {
365  if (digest == NULL)
366  return;
367  SHAobject temp;
368  SHAcopy(self, &temp);
369  sha_final(digest, &temp);
370  }
371 
372  static void
373  sha_digest(SHAobject *self, std::string &digest)
374  {
375  if (digest.size() < SHA_DIGESTSIZE)
376  digest.resize(SHA_DIGESTSIZE);
377 
378  SHAobject temp;
379  SHAcopy(self, &temp);
380  sha_final((unsigned char*)&digest[0], &temp);
381  }
382 
390  static std::string
391  Hexify(const char* data, size_t len)
392  {
393  char *hex_digest;
394  size_t i, j;
395  std::string retval;
396  retval.resize(len * 2);
397  hex_digest = &retval[0];
398 
399  for(i=j=0; i<len; i++) {
400  char c;
401  c = (data[i] >> 4) & 0xf;
402  c = (c>9) ? c+'a'-10 : c + '0';
403  hex_digest[j++] = c;
404  c = (data[i] & 0xf);
405  c = (c>9) ? c+'a'-10 : c + '0';
406  hex_digest[j++] = c;
407  }
408  return retval;
409  }
410 
411  static std::string
413  {
414  unsigned char digest[SHA_DIGESTSIZE];
415  SHAobject temp;
416  std::string retval;
417  char *hex_digest;
418  int i, j;
419 
420  /* Get the raw (binary) digest value */
421  SHAcopy(self, &temp);
422  sha_final(digest, &temp);
423 
424  /* Create a new string */
425  //retval = PyString_FromStringAndSize(NULL, sizeof(digest) * 2);
426  retval.resize(sizeof(digest) * 2);
427  hex_digest = &retval[0];
428 
429  /* Make hex version of the digest */
430  for(i=j=0; i<(int)sizeof(digest); i++) {
431  char c;
432  c = (digest[i] >> 4) & 0xf;
433  c = (c>9) ? c+'a'-10 : c + '0';
434  hex_digest[j++] = c;
435  c = (digest[i] & 0xf);
436  c = (c>9) ? c+'a'-10 : c + '0';
437  hex_digest[j++] = c;
438  }
439  return retval;
440  }
441 };
442 
443 #endif//_SHA_MODULE_H
unsigned __int8 uint8
Definition: eve-compat.h:46
#define FG(n)
Definition: ShaModule.h:157
uint32 SHA_INT32
Definition: ShaModule.h:61
static void sha_update(SHAobject *sha_info, const std::wstring &value)
Definition: ShaModule.h:299
static void sha_final(unsigned char digest[20], SHAobject *sha_info)
Definition: ShaModule.h:309
#define FA(n)
Definition: ShaModule.h:163
#define FB(n)
Definition: ShaModule.h:166
#define FC(n)
Definition: ShaModule.h:169
#define SHA_DIGESTSIZE
Definition: ShaModule.h:66
static void sha_digest(SHAobject *self, uint8 *digest)
Definition: ShaModule.h:363
uint8 SHA_BYTE
Definition: ShaModule.h:60
#define SHA_BLOCKSIZE
Definition: ShaModule.h:65
#define PCT_BIG_ENDIAN
Definition: ShaModule.h:57
static void sha_digest(SHAobject *self, std::string &digest)
Definition: ShaModule.h:373
SHA_INT32 digest[5]
Definition: ShaModule.h:71
#define FE(n)
Definition: ShaModule.h:175
unsigned __int32 uint32
Definition: eve-compat.h:50
SHA_BYTE data[SHA_BLOCKSIZE]
Definition: ShaModule.h:73
static void SHAcopy(SHAobject *src, SHAobject *dest)
Definition: ShaModule.h:97
static std::string SHA_hexdigest(SHAobject *self)
Definition: ShaModule.h:412
#define FD(n)
Definition: ShaModule.h:172
SHA_INT32 count_lo
Definition: ShaModule.h:72
const double E
Definition: Trig.h:19
static void sha_transform(SHAobject *sha_info)
Definition: ShaModule.h:184
static std::string Hexify(const char *data, size_t len)
Definition: ShaModule.h:391
#define TestEndianness(variable)
Definition: ShaModule.h:53
Sha1 module for username + password hashes.
Definition: ShaModule.h:38
#define FT(n)
Definition: ShaModule.h:178
static void longReverse(SHA_INT32 *buffer, int byteCount, int Endianness)
Definition: ShaModule.h:81
#define R32(x, n)
Definition: ShaModule.h:153
SHA_INT32 count_hi
Definition: ShaModule.h:72
static void sha_update(SHAobject *sha_info, const SHA_BYTE *buffer, int count)
Definition: ShaModule.h:261
static void sha_init(SHAobject *sha_info)
Definition: ShaModule.h:245