1 /* +------------------------------------+
2 * | Inspire Internet Relay Chat Daemon |
3 * +------------------------------------+
5 * InspIRCd: (C) 2002-2007 InspIRCd Development Team
6 * See: http://www.inspircd.org/wiki/index.php/Credits
8 * This program is free but copyrighted software; see
9 * the file COPYING for details.
11 * ---------------------------------------------------
14 /* m_sha256 - Based on m_opersha256 written by Special <john@yarbbles.com>
15 * Modified and improved by Craig Edwards, December 2006.
18 * FIPS 180-2 SHA-224/256/384/512 implementation
19 * Last update: 05/23/2005
20 * Issue date: 04/30/2005
22 * Copyright (C) 2005 Olivier Gay <olivier.gay@a3.epfl.ch>
23 * All rights reserved.
25 * Redistribution and use in source and binary forms, with or without
26 * modification, are permitted provided that the following conditions
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.
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
50 /* $ModDesc: Allows for SHA-256 encrypted oper passwords */
51 /* $ModDep: m_hash.h */
53 #include "inspircd_config.h"
65 typedef unsigned int uint32_t;
68 /** An sha 256 context, used by m_opersha256
70 class SHA256Context : public classbase
75 unsigned char block[2 * SHA256_BLOCK_SIZE];
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))
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))
90 #define UNPACK32(x, str) \
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); \
98 #define PACK32(str, x) \
100 *(x) = ((uint32_t) *((str) + 3) ) \
101 | ((uint32_t) *((str) + 2) << 8) \
102 | ((uint32_t) *((str) + 1) << 16) \
103 | ((uint32_t) *((str) + 0) << 24); \
106 /* Macros used for loops unrolling */
108 #define SHA256_SCR(i) \
110 w[i] = SHA256_F4(w[i - 2]) + w[i - 7] \
111 + SHA256_F3(w[i - 15]) + w[i - 16]; \
114 const unsigned int sha256_h0[8] =
116 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
117 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
120 uint32_t sha256_k[64] =
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
140 class ModuleSHA256 : public Module
142 void SHA256Init(struct SHA256Context *ctx, const unsigned int* key)
146 for (int i = 0; i < 8; i++)
151 for (int i = 0; i < 8; i++)
152 ctx->h[i] = sha256_h0[i];
158 void SHA256Transform(struct SHA256Context *ctx, unsigned char *message, unsigned int block_nb)
162 unsigned char *sub_block;
163 for (unsigned int i = 1; i <= block_nb; i++)
166 sub_block = message + ((i - 1) << 6);
168 for (j = 0; j < 16; j++)
169 PACK32(&sub_block[j << 2], &w[j]);
170 for (j = 16; j < 64; j++)
172 for (j = 0; j < 8; j++)
174 for (j = 0; j < 64; j++)
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]);
187 for (j = 0; j < 8; j++)
192 void SHA256Update(struct SHA256Context *ctx, unsigned char *message, unsigned int len)
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)
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);
209 ctx->tot_len += (block_nb + 1) << 6;
212 void SHA256Final(struct SHA256Context *ctx, unsigned char *digest)
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]);
225 void SHA256(const char *src, char *dest, int len, const char* hxc, const unsigned int* key = NULL)
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);
234 for (int i = 0, j = 0; i < SHA256_DIGEST_SIZE; i++)
236 dest[j++] = hxc[bytehash[i] / 16];
237 dest[j++] = hxc[bytehash[i] % 16];
247 ModuleSHA256(InspIRCd* Me) : Module::Module(Me), key(NULL), chars(NULL)
249 ServerInstance->PublishInterface("HashRequest", this);
252 virtual ~ModuleSHA256()
254 ServerInstance->UnpublishInterface("HashRequest", this);
257 void Implements(char *List)
259 List[I_OnRequest] = 1;
262 virtual char* OnRequest(Request* request)
264 HashRequest* SHA = (HashRequest*)request;
265 if (strcmp("KEY", request->GetId()) == 0)
267 this->key = (unsigned int*)SHA->GetKeyData();
269 else if (strcmp("HEX", request->GetId()) == 0)
271 this->chars = (char*)SHA->GetOutputs();
273 else if (strcmp("SUM", request->GetId()) == 0)
275 static char data[MAXBUF];
276 SHA256((const char*)SHA->GetHashData(), data, strlen(SHA->GetHashData()), chars ? chars : "0123456789abcdef", key);
279 else if (strcmp("NAME", request->GetId()) == 0)
283 else if (strcmp("RESET", request->GetId()) == 0)
291 virtual Version GetVersion()
293 return Version(1, 1, 0, 1, VF_VENDOR|VF_SERVICEPROVIDER, API_VERSION);
298 class ModuleSHA256Factory : public ModuleFactory
301 ModuleSHA256Factory()
305 ~ModuleSHA256Factory()
309 virtual Module *CreateModule(InspIRCd* Me)
311 return new ModuleSHA256(Me);
316 extern "C" void * init_module( void )
318 return new ModuleSHA256Factory;