]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules/extra/m_opersha256.cpp
Giving printf formats and not giving it arguments for them != cunning
[user/henk/code/inspircd.git] / src / modules / extra / 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 <stdint.h>
41 #include "users.h"
42 #include "channels.h"
43 #include "modules.h"
44 #include "helperfuncs.h"
45
46 static Server *Srv;
47
48 #define SHA256_DIGEST_SIZE (256 / 8)
49 #define SHA256_BLOCK_SIZE  (512 / 8)
50
51 struct SHA256Context
52 {
53         unsigned int tot_len;
54         unsigned int len;
55         unsigned char block[2 * SHA256_BLOCK_SIZE];
56         uint32_t h[8];
57 };
58
59 void SHA256Init(struct SHA256Context *ctx);
60 void SHA256Transform(struct SHA256Context *ctx, unsigned char *message, unsigned int block_nb);
61 void SHA256Update(struct SHA256Context *ctx, unsigned char *message, unsigned int len);
62 void SHA256Final(struct SHA256Context *ctx, unsigned char *digest);
63 void SHA256(const char *src, char *dest, int len);
64
65 #define SHFR(x, n)    (x >> n)
66 #define ROTR(x, n)   ((x >> n) | (x << ((sizeof(x) << 3) - n)))
67 #define ROTL(x, n)   ((x << n) | (x >> ((sizeof(x) << 3) - n)))
68 #define CH(x, y, z)  ((x & y) ^ (~x & z))
69 #define MAJ(x, y, z) ((x & y) ^ (x & z) ^ (y & z))
70
71 #define SHA256_F1(x) (ROTR(x,  2) ^ ROTR(x, 13) ^ ROTR(x, 22))
72 #define SHA256_F2(x) (ROTR(x,  6) ^ ROTR(x, 11) ^ ROTR(x, 25))
73 #define SHA256_F3(x) (ROTR(x,  7) ^ ROTR(x, 18) ^ SHFR(x,  3))
74 #define SHA256_F4(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHFR(x, 10))
75
76 #define UNPACK32(x, str)                       \
77 {                                              \
78         *((str) + 3) = (uint8_t) ((x)      );      \
79         *((str) + 2) = (uint8_t) ((x) >>  8);      \
80         *((str) + 1) = (uint8_t) ((x) >> 16);      \
81         *((str) + 0) = (uint8_t) ((x) >> 24);      \
82 }
83
84 #define PACK32(str, x)                         \
85 {                                              \
86         *(x) = ((uint32_t) *((str) + 3)      )     \
87         | ((uint32_t) *((str) + 2) <<  8)     \
88         | ((uint32_t) *((str) + 1) << 16)     \
89         | ((uint32_t) *((str) + 0) << 24);    \
90 }
91
92 /* Macros used for loops unrolling */
93
94 #define SHA256_SCR(i)                          \
95 {                                              \
96         w[i] =  SHA256_F4(w[i - 2]) + w[i - 7]     \
97         + SHA256_F3(w[i - 15]) + w[i - 16];  \
98 }
99
100 uint32_t sha256_h0[8] =
101 {
102         0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
103         0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
104 };
105
106 uint32_t sha256_k[64] =
107 {
108         0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
109         0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
110         0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
111         0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
112         0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
113         0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
114         0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
115         0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
116         0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
117         0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
118         0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
119         0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
120         0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
121         0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
122         0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
123         0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
124 };
125
126 void SHA256Init(struct SHA256Context *ctx)
127 {
128         for (int i = 0; i < 8; i++)
129                 ctx->h[i] = sha256_h0[i];
130         ctx->len = 0;
131         ctx->tot_len = 0;
132 }
133
134 void SHA256Transform(struct SHA256Context *ctx, unsigned char *message, unsigned int block_nb)
135 {
136         uint32_t w[64];
137         uint32_t wv[8];
138         unsigned char *sub_block;
139         for (unsigned int i = 1; i <= block_nb; i++)
140         {
141                 int j;
142                 sub_block = message + ((i - 1) << 6);
143
144                 for (j = 0; j < 16; j++)
145                         PACK32(&sub_block[j << 2], &w[j]);
146                 for (j = 16; j < 64; j++)
147                         SHA256_SCR(j);
148                 for (j = 0; j < 8; j++)
149                         wv[j] = ctx->h[j];
150                 for (j = 0; j < 64; j++)
151                 {
152                         uint32_t t1 = wv[7] + SHA256_F2(wv[4]) + CH(wv[4], wv[5], wv[6]) + sha256_k[j] + w[j];
153                         uint32_t t2 = SHA256_F1(wv[0]) + MAJ(wv[0], wv[1], wv[2]);
154                         wv[7] = wv[6];
155                         wv[6] = wv[5];
156                         wv[5] = wv[4];
157                         wv[4] = wv[3] + t1;
158                         wv[3] = wv[2];
159                         wv[2] = wv[1];
160                         wv[1] = wv[0];
161                         wv[0] = t1 + t2;
162                 }
163                 for (j = 0; j < 8; j++)
164                         ctx->h[j] += wv[j];
165         }
166 }
167
168 void SHA256Update(struct SHA256Context *ctx, unsigned char *message, unsigned int len)
169 {
170         unsigned int rem_len = SHA256_BLOCK_SIZE - ctx->len;
171         memcpy(&ctx->block[ctx->len], message, rem_len);
172         if (ctx->len + len < SHA256_BLOCK_SIZE)
173         {
174                 ctx->len += len;
175                 return;
176         }
177         unsigned int new_len = len - rem_len;
178         unsigned int block_nb = new_len / SHA256_BLOCK_SIZE;
179         unsigned char *shifted_message = message + rem_len;
180         SHA256Transform(ctx, ctx->block, 1);
181         SHA256Transform(ctx, shifted_message, block_nb);
182         rem_len = new_len % SHA256_BLOCK_SIZE;
183         memcpy(ctx->block, &shifted_message[block_nb << 6],rem_len);
184         ctx->len = rem_len;
185         ctx->tot_len += (block_nb + 1) << 6;
186 }
187
188 void SHA256Final(struct SHA256Context *ctx, unsigned char *digest)
189 {
190         unsigned int block_nb = (1 + ((SHA256_BLOCK_SIZE - 9) < (ctx->len % SHA256_BLOCK_SIZE)));
191         unsigned int len_b = (ctx->tot_len + ctx->len) << 3;
192         unsigned int pm_len = block_nb << 6;
193         memset(ctx->block + ctx->len, 0, pm_len - ctx->len);
194         ctx->block[ctx->len] = 0x80;
195         UNPACK32(len_b, ctx->block + pm_len - 4);
196         SHA256Transform(ctx, ctx->block, block_nb);
197         for (int i = 0 ; i < 8; i++)
198                 UNPACK32(ctx->h[i], &digest[i << 2]);
199 }
200
201 void SHA256(const char *src, char *dest, int len)
202 {
203         // Generate the hash
204         unsigned char bytehash[SHA256_DIGEST_SIZE];
205         struct SHA256Context ctx;
206         SHA256Init(&ctx);
207         SHA256Update(&ctx, (unsigned char *)src, (unsigned int)len);
208         SHA256Final(&ctx, bytehash);
209         // Convert it to hex
210         const char *hxc = "0123456789abcdef";
211         for (int i = 0, j = 0; i < SHA256_DIGEST_SIZE; i++)
212         {
213                 dest[j++] = hxc[bytehash[i] / 16];
214                 dest[j++] = hxc[bytehash[i] % 16];
215                 dest[j] = '\0';
216         }
217 }
218
219 class cmd_mksha256 : public command_t
220 {
221 public:
222         cmd_mksha256() : command_t("MKSHA256", 'o', 1)
223         {
224                 this->source = "m_opersha256.so";
225         }
226
227         void Handle(char **parameters, int pcnt, userrec *user)
228         {
229                 char buffer[SHA256_BLOCK_SIZE + 1];
230                 SHA256(parameters[0], buffer, strlen(parameters[0]));
231                 WriteServ(user->fd, "NOTICE %s :SHA256 hashed password for %s is %s", user->nick, parameters[0], buffer);
232         }
233 };
234
235 class ModuleOperSHA256 : public Module
236 {
237         cmd_mksha256 *mksha256cmd;
238 public:
239
240         ModuleOperSHA256(Server *Me) : Module::Module(Me)
241         {
242                 Srv = Me;
243                 mksha256cmd = new cmd_mksha256();
244                 Srv->AddCommand(mksha256cmd);
245         }
246
247         virtual ~ModuleOperSHA256()
248         {
249         }
250
251         void Implements(char *List)
252         {
253                 List[I_OnOperCompare] = 1;
254         }
255
256         virtual int OnOperCompare(const std::string &data, const std::string &input)
257         {
258                 if (data.length() == SHA256_BLOCK_SIZE) // If the data is as long as a hex sha256 hash, try it as that
259                 {
260                         char buffer[SHA256_BLOCK_SIZE + 1];
261                         SHA256(input.c_str(), buffer, strlen(input.c_str()));
262                         if (!strcasecmp(data.c_str(), buffer))
263                                 return 1;
264                         else
265                                 return -1;
266                 }
267                 return 0;
268         }
269
270         virtual Version GetVersion()
271         {
272                 return Version(1, 0, 0, 1, 0);
273         }
274 };
275
276
277 class ModuleOperSHA256Factory : public ModuleFactory
278 {
279 public:
280         ModuleOperSHA256Factory()
281         {
282         }
283
284         ~ModuleOperSHA256Factory()
285         {
286         }
287
288         virtual Module *CreateModule(Server* Me)
289         {
290                 return new ModuleOperSHA256(Me);
291         }
292
293 };
294
295 extern "C" void * init_module( void )
296 {
297         return new ModuleOperSHA256Factory;
298 }