anope

- supernets anope source code & configuration
git clone git://git.acid.vegas/anope.git
Log | Files | Refs | Archive | README

enc_sha256.cpp (10641B)

      1 /* This module generates and compares password hashes using SHA256 algorithms.
      2  *
      3  * If an intruder gets access to your system or uses a brute force attack,
      4  * salt will not provide much value.
      5  * IMPORTANT: DATA HASHES CANNOT BE "DECRYPTED" BACK TO PLAIN TEXT.
      6  *
      7  * Modified for Anope.
      8  * (C) 2003-2022 Anope Team
      9  * Contact us at team@anope.org
     10  *
     11  * Taken from InspIRCd (https://www.inspircd.org/),
     12  * see https://wiki.inspircd.org/Credits
     13  *
     14  * This program is free but copyrighted software; see
     15  * the file COPYING for details.
     16  */
     17 
     18 /* FIPS 180-2 SHA-224/256/384/512 implementation
     19  * Last update: 05/23/2005
     20  * Issue date:  04/30/2005
     21  *
     22  * Copyright (C) 2005 Olivier Gay <olivier.gay@a3.epfl.ch>
     23  * All rights reserved.
     24  *
     25  * Redistribution and use in source and binary forms, with or without
     26  * modification, are permitted provided that the following conditions
     27  * are met:
     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.
     36  *
     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
     47  * SUCH DAMAGE.
     48  */
     49 
     50 #include "module.h"
     51 #include "modules/encryption.h"
     52 
     53 static const unsigned SHA256_DIGEST_SIZE = 256 / 8;
     54 static const unsigned SHA256_BLOCK_SIZE = 512 / 8;
     55 
     56 inline static uint32_t SHFR(uint32_t x, uint32_t n) { return x >> n; }
     57 inline static uint32_t ROTR(uint32_t x, uint32_t n) { return (x >> n) | (x << ((sizeof(x) << 3) - n)); }
     58 inline static uint32_t CH(uint32_t x, uint32_t y, uint32_t z) { return (x & y) ^ (~x & z); }
     59 inline static uint32_t MAJ(uint32_t x, uint32_t y, uint32_t z) { return (x & y) ^ (x & z) ^ (y & z); }
     60 
     61 inline static uint32_t SHA256_F1(uint32_t x) { return ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22); }
     62 inline static uint32_t SHA256_F2(uint32_t x) { return ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25); }
     63 inline static uint32_t SHA256_F3(uint32_t x) { return ROTR(x, 7) ^ ROTR(x, 18) ^ SHFR(x, 3); }
     64 inline static uint32_t SHA256_F4(uint32_t x) { return ROTR(x, 17) ^ ROTR(x, 19) ^ SHFR(x, 10); }
     65 
     66 inline static void UNPACK32(unsigned x, unsigned char *str)
     67 {
     68 	str[3] = static_cast<uint8_t>(x);
     69 	str[2] = static_cast<uint8_t>(x >> 8);
     70 	str[1] = static_cast<uint8_t>(x >> 16);
     71 	str[0] = static_cast<uint8_t>(x >> 24);
     72 }
     73 
     74 inline static void PACK32(unsigned char *str, uint32_t &x)
     75 {
     76 	x = static_cast<uint32_t>(str[3]) | static_cast<uint32_t>(str[2]) << 8 | static_cast<uint32_t>(str[1]) << 16 | static_cast<uint32_t>(str[0]) << 24;
     77 }
     78 
     79 /* Macros used for loops unrolling */
     80 
     81 inline static void SHA256_SCR(uint32_t w[64], int i)
     82 {
     83 	w[i] = SHA256_F4(w[i - 2]) + w[i - 7] + SHA256_F3(w[i - 15]) + w[i - 16];
     84 }
     85 
     86 static const uint32_t sha256_h0[8] =
     87 {
     88 	0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
     89 	0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
     90 };
     91 
     92 static const uint32_t sha256_k[64] =
     93 {
     94 	0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
     95 	0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
     96 	0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
     97 	0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
     98 	0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
     99 	0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
    100 	0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
    101 	0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
    102 	0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
    103 	0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
    104 	0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
    105 	0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
    106 	0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
    107 	0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
    108 	0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
    109 	0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
    110 };
    111 
    112 /** An sha256 context
    113  */
    114 class SHA256Context : public Encryption::Context
    115 {
    116 	void Transform(unsigned char *message, unsigned block_nb)
    117 	{
    118 		uint32_t w[64], wv[8];
    119 		unsigned char *sub_block;
    120 		for (unsigned i = 1; i <= block_nb; ++i)
    121 		{
    122 			int j;
    123 			sub_block = message + ((i - 1) << 6);
    124 
    125 			for (j = 0; j < 16; ++j)
    126 				PACK32(&sub_block[j << 2], w[j]);
    127 			for (j = 16; j < 64; ++j)
    128 				SHA256_SCR(w, j);
    129 			for (j = 0; j < 8; ++j)
    130 				wv[j] = this->h[j];
    131 			for (j = 0; j < 64; ++j)
    132 			{
    133 				uint32_t t1 = wv[7] + SHA256_F2(wv[4]) + CH(wv[4], wv[5], wv[6]) + sha256_k[j] + w[j];
    134 				uint32_t t2 = SHA256_F1(wv[0]) + MAJ(wv[0], wv[1], wv[2]);
    135 				wv[7] = wv[6];
    136 				wv[6] = wv[5];
    137 				wv[5] = wv[4];
    138 				wv[4] = wv[3] + t1;
    139 				wv[3] = wv[2];
    140 				wv[2] = wv[1];
    141 				wv[1] = wv[0];
    142 				wv[0] = t1 + t2;
    143 			}
    144 			for (j = 0; j < 8; ++j)
    145 				this->h[j] += wv[j];
    146 		}
    147 	}
    148 
    149 	unsigned tot_len;
    150 	unsigned len;
    151 	unsigned char block[2 * SHA256_BLOCK_SIZE];
    152 	uint32_t h[8];
    153 	unsigned char digest[SHA256_DIGEST_SIZE];
    154 
    155  public:
    156 	SHA256Context(Encryption::IV *iv)
    157 	{
    158 		if (iv != NULL)
    159 		{
    160 			if (iv->second != 8)
    161 				throw CoreException("Invalid IV size");
    162 			for (int i = 0; i < 8; ++i)
    163 				this->h[i] = iv->first[i];
    164 		}
    165 		else
    166 			for (int i = 0; i < 8; ++i)
    167 				this->h[i] = sha256_h0[i];
    168 
    169 		this->tot_len = 0;
    170 		this->len = 0;
    171 		memset(this->block, 0, sizeof(this->block));
    172 		memset(this->digest, 0, sizeof(this->digest));
    173 	}
    174 
    175 	void Update(const unsigned char *message, size_t mlen) anope_override
    176 	{
    177 		unsigned tmp_len = SHA256_BLOCK_SIZE - this->len, rem_len = mlen < tmp_len ? mlen : tmp_len;
    178 
    179 		memcpy(&this->block[this->len], message, rem_len);
    180 		if (this->len + mlen < SHA256_BLOCK_SIZE)
    181 		{
    182 			this->len += mlen;
    183 			return;
    184 		}
    185 		unsigned new_len = mlen - rem_len, block_nb = new_len / SHA256_BLOCK_SIZE;
    186 		unsigned char *shifted_message = new unsigned char[mlen - rem_len];
    187 		memcpy(shifted_message, message + rem_len, mlen - rem_len);
    188 		this->Transform(this->block, 1);
    189 		this->Transform(shifted_message, block_nb);
    190 		rem_len = new_len % SHA256_BLOCK_SIZE;
    191 		memcpy(this->block, &shifted_message[block_nb << 6], rem_len);
    192 		delete [] shifted_message;
    193 		this->len = rem_len;
    194 		this->tot_len += (block_nb + 1) << 6;
    195 	}
    196 
    197 	void Finalize() anope_override
    198 	{
    199 		unsigned block_nb = 1 + ((SHA256_BLOCK_SIZE - 9) < (this->len % SHA256_BLOCK_SIZE));
    200 		unsigned len_b = (this->tot_len + this->len) << 3;
    201 		unsigned pm_len = block_nb << 6;
    202 		memset(this->block + this->len, 0, pm_len - this->len);
    203 		this->block[this->len] = 0x80;
    204 		UNPACK32(len_b, this->block + pm_len - 4);
    205 		this->Transform(this->block, block_nb);
    206 		for (int i = 0 ; i < 8; ++i)
    207 			UNPACK32(this->h[i], &this->digest[i << 2]);
    208 	}
    209 
    210 	Encryption::Hash GetFinalizedHash() anope_override
    211 	{
    212 		Encryption::Hash hash;
    213 		hash.first = this->digest;
    214 		hash.second = SHA256_DIGEST_SIZE;
    215 		return hash;
    216 	}
    217 };
    218 
    219 class SHA256Provider : public Encryption::Provider
    220 {
    221  public:
    222 	SHA256Provider(Module *creator) : Encryption::Provider(creator, "sha256") { }
    223 
    224 	Encryption::Context *CreateContext(Encryption::IV *iv) anope_override
    225 	{
    226 		return new SHA256Context(iv);
    227 	}
    228 
    229 	Encryption::IV GetDefaultIV() anope_override
    230 	{
    231 		Encryption::IV iv;
    232 		iv.first = sha256_h0;
    233 		iv.second = sizeof(sha256_h0) / sizeof(uint32_t);
    234 		return iv;
    235 	}
    236 };
    237 
    238 class ESHA256 : public Module
    239 {
    240 	SHA256Provider sha256provider;
    241 
    242 	unsigned iv[8];
    243 	bool use_iv;
    244 
    245 	/* initializes the IV with a new random value */
    246 	void NewRandomIV()
    247 	{
    248 		for (int i = 0; i < 8; ++i)
    249 			iv[i] = static_cast<uint32_t>(rand());
    250 	}
    251 
    252 	/* returns the IV as base64-encrypted string */
    253 	Anope::string GetIVString()
    254 	{
    255 		char buf[33];
    256 		for (int i = 0; i < 8; ++i)
    257 			UNPACK32(iv[i], reinterpret_cast<unsigned char *>(&buf[i << 2]));
    258 		buf[32] = '\0';
    259 		return Anope::Hex(buf, 32);
    260 	}
    261 
    262 	/* splits the appended IV from the password string so it can be used for the next encryption */
    263 	/* password format:  <hashmethod>:<password_b64>:<iv_b64> */
    264 	void GetIVFromPass(const Anope::string &password)
    265 	{
    266 		size_t pos = password.find(':');
    267 		Anope::string buf = password.substr(password.find(':', pos + 1) + 1, password.length());
    268 		char buf2[33];
    269 		Anope::Unhex(buf, buf2, sizeof(buf2));
    270 		for (int i = 0 ; i < 8; ++i)
    271 			PACK32(reinterpret_cast<unsigned char *>(&buf2[i << 2]), iv[i]);
    272 	}
    273 
    274  public:
    275 	ESHA256(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, ENCRYPTION | VENDOR),
    276 		sha256provider(this)
    277 	{
    278 
    279 
    280 		use_iv = false;
    281 	}
    282 
    283 	EventReturn OnEncrypt(const Anope::string &src, Anope::string &dest) anope_override
    284 	{
    285 		if (!use_iv)
    286 			NewRandomIV();
    287 		else
    288 			use_iv = false;
    289 
    290 		Encryption::IV initialization(this->iv, 8);
    291 		SHA256Context ctx(&initialization);
    292 		ctx.Update(reinterpret_cast<const unsigned char *>(src.c_str()), src.length());
    293 		ctx.Finalize();
    294 
    295 		Encryption::Hash hash = ctx.GetFinalizedHash();
    296 
    297 		std::stringstream buf;
    298 		buf << "sha256:" << Anope::Hex(reinterpret_cast<const char *>(hash.first), hash.second) << ":" << GetIVString();
    299 		Log(LOG_DEBUG_2) << "(enc_sha256) hashed password from [" << src << "] to [" << buf.str() << " ]";
    300 		dest = buf.str();
    301 		return EVENT_ALLOW;
    302 	}
    303 
    304 	void OnCheckAuthentication(User *, IdentifyRequest *req) anope_override
    305 	{
    306 		const NickAlias *na = NickAlias::Find(req->GetAccount());
    307 		if (na == NULL)
    308 			return;
    309 		NickCore *nc = na->nc;
    310 
    311 		size_t pos = nc->pass.find(':');
    312 		if (pos == Anope::string::npos)
    313 			return;
    314 		Anope::string hash_method(nc->pass.begin(), nc->pass.begin() + pos);
    315 		if (!hash_method.equals_cs("sha256"))
    316 			return;
    317 
    318 		GetIVFromPass(nc->pass);
    319 		use_iv = true;
    320 		Anope::string buf;
    321 		this->OnEncrypt(req->GetPassword(), buf);
    322 		if (nc->pass.equals_cs(buf))
    323 		{
    324 			/* if we are NOT the first module in the list,
    325 			 * we want to re-encrypt the pass with the new encryption
    326 			 */
    327 			if (ModuleManager::FindFirstOf(ENCRYPTION) != this)
    328 				Anope::Encrypt(req->GetPassword(), nc->pass);
    329 			req->Success(this);
    330 		}
    331 	}
    332 };
    333 
    334 MODULE_INIT(ESHA256)