1 /* +------------------------------------+
2 * | Inspire Internet Relay Chat Daemon |
3 * +------------------------------------+
5 * InspIRCd is copyright (C) 2002-2006 ChatSpike-Dev.
7 * <brain@chatspike.net>
8 * <Craig@chatspike.net>
10 * Written by Craig Edwards, Craig McLure, and others.
11 * This program is free but copyrighted software; see
12 * the file COPYING for details.
14 * ---------------------------------------------------
17 /* m_sha256 - Based on m_opersha256 written by Special <john@yarbbles.com>
18 * Modified and improved by Craig Edwards, December 2006.
21 * FIPS 180-2 SHA-224/256/384/512 implementation
22 * Last update: 05/23/2005
23 * Issue date: 04/30/2005
25 * Copyright (C) 2005 Olivier Gay <olivier.gay@a3.epfl.ch>
26 * All rights reserved.
28 * Redistribution and use in source and binary forms, with or without
29 * modification, are permitted provided that the following conditions
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.
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
53 /* $ModDesc: Allows for SHA-256 encrypted oper passwords */
54 /* $ModDep: m_hash.h */
56 #include "inspircd_config.h"
68 typedef unsigned int uint32_t;
71 /** An sha 256 context, used by m_opersha256
73 class SHA256Context : public classbase
78 unsigned char block[2 * SHA256_BLOCK_SIZE];
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))
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))
93 #define UNPACK32(x, str) \
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); \
101 #define PACK32(str, x) \
103 *(x) = ((uint32_t) *((str) + 3) ) \
104 | ((uint32_t) *((str) + 2) << 8) \
105 | ((uint32_t) *((str) + 1) << 16) \
106 | ((uint32_t) *((str) + 0) << 24); \
109 /* Macros used for loops unrolling */
111 #define SHA256_SCR(i) \
113 w[i] = SHA256_F4(w[i - 2]) + w[i - 7] \
114 + SHA256_F3(w[i - 15]) + w[i - 16]; \
117 const unsigned int sha256_h0[8] =
119 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
120 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
123 uint32_t sha256_k[64] =
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
143 class ModuleSHA256 : public Module
145 void SHA256Init(struct SHA256Context *ctx, const unsigned int* key)
149 for (int i = 0; i < 8; i++)
154 for (int i = 0; i < 8; i++)
155 ctx->h[i] = sha256_h0[i];
161 void SHA256Transform(struct SHA256Context *ctx, unsigned char *message, unsigned int block_nb)
165 unsigned char *sub_block;
166 for (unsigned int i = 1; i <= block_nb; i++)
169 sub_block = message + ((i - 1) << 6);
171 for (j = 0; j < 16; j++)
172 PACK32(&sub_block[j << 2], &w[j]);
173 for (j = 16; j < 64; j++)
175 for (j = 0; j < 8; j++)
177 for (j = 0; j < 64; j++)
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]);
190 for (j = 0; j < 8; j++)
195 void SHA256Update(struct SHA256Context *ctx, unsigned char *message, unsigned int len)
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)
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);
212 ctx->tot_len += (block_nb + 1) << 6;
215 void SHA256Final(struct SHA256Context *ctx, unsigned char *digest)
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]);
228 void SHA256(const char *src, char *dest, int len, const char* hxc, const unsigned int* key = NULL)
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);
237 for (int i = 0, j = 0; i < SHA256_DIGEST_SIZE; i++)
239 dest[j++] = hxc[bytehash[i] / 16];
240 dest[j++] = hxc[bytehash[i] % 16];
250 ModuleSHA256(InspIRCd* Me) : Module::Module(Me), key(NULL), chars(NULL)
252 ServerInstance->PublishInterface("HashRequest", this);
255 virtual ~ModuleSHA256()
257 ServerInstance->UnpublishInterface("HashRequest", this);
260 void Implements(char *List)
262 List[I_OnRequest] = 1;
265 virtual char* OnRequest(Request* request)
267 HashRequest* SHA = (HashRequest*)request;
268 if (strcmp("KEY", request->GetId()) == 0)
270 this->key = (unsigned int*)SHA->GetKeyData();
272 else if (strcmp("HEX", request->GetId()) == 0)
274 this->chars = (char*)SHA->GetOutputs();
276 else if (strcmp("SUM", request->GetId()) == 0)
278 static char data[MAXBUF];
279 SHA256((const char*)SHA->GetHashData(), data, strlen(SHA->GetHashData()), chars ? chars : "0123456789abcdef", key);
282 else if (strcmp("NAME", request->GetId()) == 0)
286 else if (strcmp("RESET", request->GetId()) == 0)
294 virtual Version GetVersion()
296 return Version(1, 1, 0, 1, VF_VENDOR|VF_SERVICEPROVIDER, API_VERSION);
301 class ModuleSHA256Factory : public ModuleFactory
304 ModuleSHA256Factory()
308 ~ModuleSHA256Factory()
312 virtual Module *CreateModule(InspIRCd* Me)
314 return new ModuleSHA256(Me);
319 extern "C" void * init_module( void )
321 return new ModuleSHA256Factory;