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