]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules/m_sha256.cpp
Add extra /map info (connection uptime, and lag time) to /MAP for opers. Adds feature...
[user/henk/code/inspircd.git] / src / modules / m_sha256.cpp
1 /*       +------------------------------------+
2  *       | Inspire Internet Relay Chat Daemon |
3  *       +------------------------------------+
4  *
5  *  InspIRCd: (C) 2002-2007 InspIRCd Development Team
6  * See: http://www.inspircd.org/wiki/index.php/Credits
7  *
8  * This program is free but copyrighted software; see
9  *            the file COPYING for details.
10  *
11  * ---------------------------------------------------
12  */
13
14 /* m_sha256 - Based on m_opersha256 written by Special <john@yarbbles.com>
15  * Modified and improved by Craig Edwards, December 2006.
16  *
17  *
18  * FIPS 180-2 SHA-224/256/384/512 implementation
19  * Last update: 05/23/2005
20  * Issue date:  04/30/2005
21  *
22  * Copyright (C) 2005 Olivier Gay <olivier.gay@a3.epfl.ch>
23  * All rights reserved.
24  *
25  * Redistribution and use in source and binary forms, with or without
26  * modification, are permitted provided that the following conditions
27  * are met:
28  * 1. Redistributions of source code must retain the above copyright
29  *    notice, this list of conditions and the following disclaimer.
30  * 2. Redistributions in binary form must reproduce the above copyright
31  *    notice, this list of conditions and the following disclaimer in the
32  *    documentation and/or other materials provided with the distribution.
33  * 3. Neither the name of the project nor the names of its contributors
34  *    may be used to endorse or promote products derived from this software
35  *    without specific prior written permission.
36  *
37  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
38  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
39  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
40  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
41  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
42  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
43  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
44  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
45  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
46  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47  * SUCH DAMAGE.
48  */
49
50 /* $ModDesc: Allows for SHA-256 encrypted oper passwords */
51 /* $ModDep: m_hash.h */
52
53 #include "inspircd_config.h"
54 #ifdef HAS_STDINT
55 #include <stdint.h>
56 #endif
57 #include "users.h"
58 #include "channels.h"
59 #include "modules.h"
60 #include "inspircd.h"
61
62 #include "m_hash.h"
63
64 #ifndef HAS_STDINT
65 typedef unsigned int uint32_t;
66 #endif
67
68 /** An sha 256 context, used by m_opersha256
69  */
70 class SHA256Context : public classbase
71 {
72  public:
73         unsigned int tot_len;
74         unsigned int len;
75         unsigned char block[2 * SHA256_BLOCK_SIZE];
76         uint32_t h[8];
77 };
78
79 #define SHFR(x, n)    (x >> n)
80 #define ROTR(x, n)   ((x >> n) | (x << ((sizeof(x) << 3) - n)))
81 #define ROTL(x, n)   ((x << n) | (x >> ((sizeof(x) << 3) - n)))
82 #define CH(x, y, z)  ((x & y) ^ (~x & z))
83 #define MAJ(x, y, z) ((x & y) ^ (x & z) ^ (y & z))
84
85 #define SHA256_F1(x) (ROTR(x,  2) ^ ROTR(x, 13) ^ ROTR(x, 22))
86 #define SHA256_F2(x) (ROTR(x,  6) ^ ROTR(x, 11) ^ ROTR(x, 25))
87 #define SHA256_F3(x) (ROTR(x,  7) ^ ROTR(x, 18) ^ SHFR(x,  3))
88 #define SHA256_F4(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHFR(x, 10))
89
90 #define UNPACK32(x, str)                       \
91 {                                             \
92         *((str) + 3) = (uint8_t) ((x)      );      \
93         *((str) + 2) = (uint8_t) ((x) >>  8);      \
94         *((str) + 1) = (uint8_t) ((x) >> 16);      \
95         *((str) + 0) = (uint8_t) ((x) >> 24);      \
96 }
97
98 #define PACK32(str, x)                   \
99 {                                             \
100         *(x) = ((uint32_t) *((str) + 3)      )     \
101         | ((uint32_t) *((str) + 2) <<  8)     \
102         | ((uint32_t) *((str) + 1) << 16)     \
103         | ((uint32_t) *((str) + 0) << 24);    \
104 }
105
106 /* Macros used for loops unrolling */
107
108 #define SHA256_SCR(i)                     \
109 {                                             \
110         w[i] =  SHA256_F4(w[i - 2]) + w[i - 7]     \
111         + SHA256_F3(w[i - 15]) + w[i - 16];  \
112 }
113
114 const unsigned int sha256_h0[8] =
115 {
116         0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
117         0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
118 };
119
120 uint32_t sha256_k[64] =
121 {
122         0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
123         0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
124         0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
125         0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
126         0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
127         0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
128         0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
129         0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
130         0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
131         0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
132         0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
133         0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
134         0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
135         0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
136         0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
137         0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
138 };
139
140 class ModuleSHA256 : public Module
141 {
142         void SHA256Init(struct SHA256Context *ctx, const unsigned int* key)
143         {
144                 if (key)
145                 {
146                         for (int i = 0; i < 8; i++)
147                                 ctx->h[i] = key[i];
148                 }
149                 else
150                 {
151                         for (int i = 0; i < 8; i++)
152                                 ctx->h[i] = sha256_h0[i];
153                 }
154                 ctx->len = 0;
155                 ctx->tot_len = 0;
156         }
157
158         void SHA256Transform(struct SHA256Context *ctx, unsigned char *message, unsigned int block_nb)
159         {
160                 uint32_t w[64];
161                 uint32_t wv[8];
162                 unsigned char *sub_block;
163                 for (unsigned int i = 1; i <= block_nb; i++)
164                 {
165                         int j;
166                         sub_block = message + ((i - 1) << 6);
167         
168                         for (j = 0; j < 16; j++)
169                                 PACK32(&sub_block[j << 2], &w[j]);
170                         for (j = 16; j < 64; j++)
171                                 SHA256_SCR(j);
172                         for (j = 0; j < 8; j++)
173                                 wv[j] = ctx->h[j];
174                         for (j = 0; j < 64; j++)
175                         {
176                                 uint32_t t1 = wv[7] + SHA256_F2(wv[4]) + CH(wv[4], wv[5], wv[6]) + sha256_k[j] + w[j];
177                                 uint32_t t2 = SHA256_F1(wv[0]) + MAJ(wv[0], wv[1], wv[2]);
178                                 wv[7] = wv[6];
179                                 wv[6] = wv[5];
180                                 wv[5] = wv[4];
181                                 wv[4] = wv[3] + t1;
182                                 wv[3] = wv[2];
183                                 wv[2] = wv[1];
184                                 wv[1] = wv[0];
185                                 wv[0] = t1 + t2;
186                         }
187                         for (j = 0; j < 8; j++)
188                                 ctx->h[j] += wv[j];
189                 }
190         }
191         
192         void SHA256Update(struct SHA256Context *ctx, unsigned char *message, unsigned int len)
193         {
194                 unsigned int rem_len = SHA256_BLOCK_SIZE - ctx->len;
195                 memcpy(&ctx->block[ctx->len], message, rem_len);
196                 if (ctx->len + len < SHA256_BLOCK_SIZE)
197                 {
198                         ctx->len += len;
199                         return;
200                 }
201                 unsigned int new_len = len - rem_len;
202                 unsigned int block_nb = new_len / SHA256_BLOCK_SIZE;
203                 unsigned char *shifted_message = message + rem_len;
204                 SHA256Transform(ctx, ctx->block, 1);
205                 SHA256Transform(ctx, shifted_message, block_nb);
206                 rem_len = new_len % SHA256_BLOCK_SIZE;
207                 memcpy(ctx->block, &shifted_message[block_nb << 6],rem_len);
208                 ctx->len = rem_len;
209                 ctx->tot_len += (block_nb + 1) << 6;
210         }
211         
212         void SHA256Final(struct SHA256Context *ctx, unsigned char *digest)
213         {
214                 unsigned int block_nb = (1 + ((SHA256_BLOCK_SIZE - 9) < (ctx->len % SHA256_BLOCK_SIZE)));
215                 unsigned int len_b = (ctx->tot_len + ctx->len) << 3;
216                 unsigned int pm_len = block_nb << 6;
217                 memset(ctx->block + ctx->len, 0, pm_len - ctx->len);
218                 ctx->block[ctx->len] = 0x80;
219                 UNPACK32(len_b, ctx->block + pm_len - 4);
220                 SHA256Transform(ctx, ctx->block, block_nb);
221                 for (int i = 0 ; i < 8; i++)
222                         UNPACK32(ctx->h[i], &digest[i << 2]);
223         }
224         
225         void SHA256(const char *src, char *dest, int len, const char* hxc, const unsigned int* key = NULL)
226         {
227                 // Generate the hash
228                 unsigned char bytehash[SHA256_DIGEST_SIZE];
229                 struct SHA256Context ctx;
230                 SHA256Init(&ctx, key);
231                 SHA256Update(&ctx, (unsigned char *)src, (unsigned int)len);
232                 SHA256Final(&ctx, bytehash);
233                 // Convert it to hex
234                 for (int i = 0, j = 0; i < SHA256_DIGEST_SIZE; i++)
235                 {
236                         dest[j++] = hxc[bytehash[i] / 16];
237                         dest[j++] = hxc[bytehash[i] % 16];
238                         dest[j] = '\0';
239                 }
240         }
241
242         unsigned int* key;
243         char* chars;
244
245  public:
246
247         ModuleSHA256(InspIRCd* Me) : Module::Module(Me), key(NULL), chars(NULL)
248         {
249                 ServerInstance->PublishInterface("HashRequest", this);
250         }
251
252         virtual ~ModuleSHA256()
253         {
254                 ServerInstance->UnpublishInterface("HashRequest", this);
255         }
256
257         void Implements(char *List)
258         {
259                 List[I_OnRequest] = 1;
260         }
261
262         virtual char* OnRequest(Request* request)
263         {
264                 HashRequest* SHA = (HashRequest*)request;
265                 if (strcmp("KEY", request->GetId()) == 0)
266                 {
267                         this->key = (unsigned int*)SHA->GetKeyData();
268                 }
269                 else if (strcmp("HEX", request->GetId()) == 0)
270                 {
271                         this->chars = (char*)SHA->GetOutputs();
272                 }
273                 else if (strcmp("SUM", request->GetId()) == 0)
274                 {
275                         static char data[MAXBUF];
276                         SHA256((const char*)SHA->GetHashData(), data, strlen(SHA->GetHashData()), chars ? chars : "0123456789abcdef", key);
277                         return data;
278                 }
279                 else if (strcmp("NAME", request->GetId()) == 0)
280                 {
281                         return "sha256";
282                 }
283                 else if (strcmp("RESET", request->GetId()) == 0)
284                 {
285                         this->chars = NULL;
286                         this->key = NULL;
287                 }
288                 return NULL;
289         }
290
291         virtual Version GetVersion()
292         {
293                 return Version(1, 1, 0, 1, VF_VENDOR|VF_SERVICEPROVIDER, API_VERSION);
294         }
295 };
296
297
298 class ModuleSHA256Factory : public ModuleFactory
299 {
300 public:
301         ModuleSHA256Factory()
302         {
303         }
304
305         ~ModuleSHA256Factory()
306         {
307         }
308
309         virtual Module *CreateModule(InspIRCd* Me)
310         {
311                 return new ModuleSHA256(Me);
312         }
313
314 };
315
316 extern "C" void * init_module( void )
317 {
318         return new ModuleSHA256Factory;
319 }