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