1 /* m_opersha256 - Written by Special <john@yarbbles.com>
3 * FIPS 180-2 SHA-224/256/384/512 implementation
4 * Last update: 05/23/2005
5 * Issue date: 04/30/2005
7 * Copyright (C) 2005 Olivier Gay <olivier.gay@a3.epfl.ch>
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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.
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
35 /* $ModDesc: Allows for SHA-256 encrypted oper passwords */
44 #include "helperfuncs.h"
48 #define SHA256_DIGEST_SIZE (256 / 8)
49 #define SHA256_BLOCK_SIZE (512 / 8)
55 unsigned char block[2 * SHA256_BLOCK_SIZE];
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);
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))
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))
76 #define UNPACK32(x, str) \
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); \
84 #define PACK32(str, x) \
86 *(x) = ((uint32_t) *((str) + 3) ) \
87 | ((uint32_t) *((str) + 2) << 8) \
88 | ((uint32_t) *((str) + 1) << 16) \
89 | ((uint32_t) *((str) + 0) << 24); \
92 /* Macros used for loops unrolling */
94 #define SHA256_SCR(i) \
96 w[i] = SHA256_F4(w[i - 2]) + w[i - 7] \
97 + SHA256_F3(w[i - 15]) + w[i - 16]; \
100 uint32_t sha256_h0[8] =
102 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
103 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
106 uint32_t sha256_k[64] =
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
126 void SHA256Init(struct SHA256Context *ctx)
128 for (int i = 0; i < 8; i++)
129 ctx->h[i] = sha256_h0[i];
134 void SHA256Transform(struct SHA256Context *ctx, unsigned char *message, unsigned int block_nb)
138 unsigned char *sub_block;
139 for (unsigned int i = 1; i <= block_nb; i++)
142 sub_block = message + ((i - 1) << 6);
144 for (j = 0; j < 16; j++)
145 PACK32(&sub_block[j << 2], &w[j]);
146 for (j = 16; j < 64; j++)
148 for (j = 0; j < 8; j++)
150 for (j = 0; j < 64; j++)
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]);
163 for (j = 0; j < 8; j++)
168 void SHA256Update(struct SHA256Context *ctx, unsigned char *message, unsigned int len)
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)
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);
185 ctx->tot_len += (block_nb + 1) << 6;
188 void SHA256Final(struct SHA256Context *ctx, unsigned char *digest)
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]);
201 void SHA256(const char *src, char *dest, int len)
204 unsigned char bytehash[SHA256_DIGEST_SIZE];
205 struct SHA256Context ctx;
207 SHA256Update(&ctx, (unsigned char *)src, (unsigned int)len);
208 SHA256Final(&ctx, bytehash);
210 const char *hxc = "0123456789abcdef";
211 for (int i = 0, j = 0; i < SHA256_DIGEST_SIZE; i++)
213 dest[j++] = hxc[bytehash[i] / 16];
214 dest[j++] = hxc[bytehash[i] % 16];
219 class cmd_mksha256 : public command_t
222 cmd_mksha256() : command_t("MKSHA256", 'o', 1)
224 this->source = "m_opersha256.so";
227 void Handle(char **parameters, int pcnt, userrec *user)
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);
235 class ModuleOperSHA256 : public Module
237 cmd_mksha256 *mksha256cmd;
240 ModuleOperSHA256(Server *Me) : Module::Module(Me)
243 mksha256cmd = new cmd_mksha256();
244 Srv->AddCommand(mksha256cmd);
247 virtual ~ModuleOperSHA256()
251 void Implements(char *List)
253 List[I_OnOperCompare] = 1;
256 virtual int OnOperCompare(const std::string &data, const std::string &input)
258 if (data.length() == SHA256_BLOCK_SIZE) // If the data is as long as a hex sha256 hash, try it as that
260 char buffer[SHA256_BLOCK_SIZE + 1];
261 SHA256(input.c_str(), buffer, strlen(input.c_str()));
262 if (!strcasecmp(data.c_str(), buffer))
270 virtual Version GetVersion()
272 return Version(1, 0, 0, 1, 0);
277 class ModuleOperSHA256Factory : public ModuleFactory
280 ModuleOperSHA256Factory()
284 ~ModuleOperSHA256Factory()
288 virtual Module *CreateModule(Server* Me)
290 return new ModuleOperSHA256(Me);
295 extern "C" void * init_module( void )
297 return new ModuleOperSHA256Factory;