anope

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

enc_sha1.cpp (9267B)

      1 /*
      2  *
      3  * Modified for Anope.
      4  * (C) 2006-2022 Anope Team
      5  * Contact us at team@anope.org
      6 
      7 SHA-1 in C
      8 By Steve Reid <steve@edmweb.com>
      9 100% Public Domain
     10 
     11 Test Vectors (from FIPS PUB 180-1)
     12 "abc"
     13   A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
     14 "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
     15   84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
     16 A million repetitions of "a"
     17   34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
     18 */
     19 
     20 /* #define LITTLE_ENDIAN * This should be #define'd if true. */
     21 
     22 #include "module.h"
     23 #include "modules/encryption.h"
     24 
     25 union CHAR64LONG16
     26 {
     27 	unsigned char c[64];
     28 	uint32_t l[16];
     29 };
     30 
     31 inline static uint32_t rol(uint32_t value, uint32_t bits) { return (value << bits) | (value >> (32 - bits)); }
     32 
     33 /* blk0() and blk() perform the initial expand. */
     34 /* I got the idea of expanding during the round function from SSLeay */
     35 inline static uint32_t blk0(CHAR64LONG16 &block, uint32_t i)
     36 {
     37 #ifdef LITTLE_ENDIAN
     38 	return block.l[i] = (rol(block.l[i], 24) & 0xFF00FF00) | (rol(block.l[i], 8) & 0x00FF00FF);
     39 #else
     40 	return block.l[i];
     41 #endif
     42 }
     43 inline static uint32_t blk(CHAR64LONG16 &block, uint32_t i) { return block.l[i & 15] = rol(block.l[(i + 13) & 15] ^ block.l[(i + 8) & 15] ^ block.l[(i + 2) & 15] ^ block.l[i & 15],1); }
     44 
     45 /* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
     46 inline static void R0(CHAR64LONG16 &block, uint32_t v, uint32_t &w, uint32_t x, uint32_t y, uint32_t &z, uint32_t i) { z += ((w & (x ^ y)) ^ y) + blk0(block, i) + 0x5A827999 + rol(v, 5); w = rol(w, 30); }
     47 inline static void R1(CHAR64LONG16 &block, uint32_t v, uint32_t &w, uint32_t x, uint32_t y, uint32_t &z, uint32_t i) { z += ((w & (x ^ y)) ^ y) + blk(block, i) + 0x5A827999 + rol(v, 5); w = rol(w, 30); }
     48 inline static void R2(CHAR64LONG16 &block, uint32_t v, uint32_t &w, uint32_t x, uint32_t y, uint32_t &z, uint32_t i) { z += (w ^ x ^ y) + blk(block, i) + 0x6ED9EBA1 + rol(v, 5); w = rol(w, 30); }
     49 inline static void R3(CHAR64LONG16 &block, uint32_t v, uint32_t &w, uint32_t x, uint32_t y, uint32_t &z, uint32_t i) { z += (((w | x) & y) | (w & x)) + blk(block, i) + 0x8F1BBCDC + rol(v, 5); w = rol(w, 30); }
     50 inline static void R4(CHAR64LONG16 &block, uint32_t v, uint32_t &w, uint32_t x, uint32_t y, uint32_t &z, uint32_t i) { z += (w ^ x ^ y) + blk(block, i) + 0xCA62C1D6 + rol(v, 5); w = rol(w, 30); }
     51 
     52 static const uint32_t sha1_iv[5] =
     53 {
     54 	0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0
     55 };
     56 
     57 class SHA1Context : public Encryption::Context
     58 {
     59 	uint32_t state[5];
     60 	uint32_t count[2];
     61 	unsigned char buffer[64];
     62 	unsigned char digest[20];
     63 
     64 	void Transform(const unsigned char buf[64])
     65 	{
     66 		uint32_t a, b, c, d, e;
     67 
     68 		CHAR64LONG16 block;
     69 		memcpy(block.c, buf, 64);
     70 
     71 		/* Copy context->state[] to working vars */
     72 		a = this->state[0];
     73 		b = this->state[1];
     74 		c = this->state[2];
     75 		d = this->state[3];
     76 		e = this->state[4];
     77 
     78 		/* 4 rounds of 20 operations each. Loop unrolled. */
     79 		R0(block, a, b, c, d, e, 0); R0(block, e, a, b, c, d, 1); R0(block, d, e, a, b, c, 2); R0(block, c, d, e, a, b, 3);
     80 		R0(block, b, c, d, e, a, 4); R0(block, a, b, c, d, e, 5); R0(block, e, a, b, c, d, 6); R0(block, d, e, a, b, c, 7);
     81 		R0(block, c, d, e, a, b, 8); R0(block, b, c, d, e, a, 9); R0(block, a, b, c, d, e, 10); R0(block, e, a, b, c, d, 11);
     82 		R0(block, d, e, a, b, c, 12); R0(block, c, d, e, a, b, 13); R0(block, b, c, d, e, a, 14); R0(block, a, b, c, d, e, 15);
     83 		R1(block, e, a, b, c, d, 16); R1(block, d, e, a, b, c, 17); R1(block, c, d, e, a, b, 18); R1(block, b, c, d, e, a, 19);
     84 		R2(block, a, b, c, d, e, 20); R2(block, e, a, b, c, d, 21); R2(block, d, e, a, b, c, 22); R2(block, c, d, e, a, b, 23);
     85 		R2(block, b, c, d, e, a, 24); R2(block, a, b, c, d, e, 25); R2(block, e, a, b, c, d, 26); R2(block, d, e, a, b, c, 27);
     86 		R2(block, c, d, e, a, b, 28); R2(block, b, c, d, e, a, 29); R2(block, a, b, c, d, e, 30); R2(block, e, a, b, c, d, 31);
     87 		R2(block, d, e, a, b, c, 32); R2(block, c, d, e, a, b, 33); R2(block, b, c, d, e, a, 34); R2(block, a, b, c, d, e, 35);
     88 		R2(block, e, a, b, c, d, 36); R2(block, d, e, a, b, c, 37); R2(block, c, d, e, a, b, 38); R2(block, b, c, d, e, a, 39);
     89 		R3(block, a, b, c, d, e, 40); R3(block, e, a, b, c, d, 41); R3(block, d, e, a, b, c, 42); R3(block, c, d, e, a, b, 43);
     90 		R3(block, b, c, d, e, a, 44); R3(block, a, b, c, d, e, 45); R3(block, e, a, b, c, d, 46); R3(block, d, e, a, b, c, 47);
     91 		R3(block, c, d, e, a, b, 48); R3(block, b, c, d, e, a, 49); R3(block, a, b, c, d, e, 50); R3(block, e, a, b, c, d, 51);
     92 		R3(block, d, e, a, b, c, 52); R3(block, c, d, e, a, b, 53); R3(block, b, c, d, e, a, 54); R3(block, a, b, c, d, e, 55);
     93 		R3(block, e, a, b, c, d, 56); R3(block, d, e, a, b, c, 57); R3(block, c, d, e, a, b, 58); R3(block, b, c, d, e, a, 59);
     94 		R4(block, a, b, c, d, e, 60); R4(block, e, a, b, c, d, 61); R4(block, d, e, a, b, c, 62); R4(block, c, d, e, a, b, 63);
     95 		R4(block, b, c, d, e, a, 64); R4(block, a, b, c, d, e, 65); R4(block, e, a, b, c, d, 66); R4(block, d, e, a, b, c, 67);
     96 		R4(block, c, d, e, a, b, 68); R4(block, b, c, d, e, a, 69); R4(block, a, b, c, d, e, 70); R4(block, e, a, b, c, d, 71);
     97 		R4(block, d, e, a, b, c, 72); R4(block, c, d, e, a, b, 73); R4(block, b, c, d, e, a, 74); R4(block, a, b, c, d, e, 75);
     98 		R4(block, e, a, b, c, d, 76); R4(block, d, e, a, b, c, 77); R4(block, c, d, e, a, b, 78); R4(block, b, c, d, e, a, 79);
     99 		/* Add the working vars back into context.state[] */
    100 		this->state[0] += a;
    101 		this->state[1] += b;
    102 		this->state[2] += c;
    103 		this->state[3] += d;
    104 		this->state[4] += e;
    105 		/* Wipe variables */
    106 		a = b = c = d = e = 0;
    107 	}
    108 
    109  public:
    110 	SHA1Context(Encryption::IV *iv = NULL)
    111 	{
    112 		if (iv != NULL)
    113 		{
    114 			if (iv->second != 5)
    115 				throw CoreException("Invalid IV size");
    116 			for (int i = 0; i < 5; ++i)
    117 				this->state[i] = iv->first[i];
    118 		}
    119 		else
    120 			for (int i = 0; i < 5; ++i)
    121 				this->state[i] = sha1_iv[i];
    122 
    123 		this->count[0] = this->count[1] = 0;
    124 		memset(this->buffer, 0, sizeof(this->buffer));
    125 		memset(this->digest, 0, sizeof(this->digest));
    126 	}
    127 
    128 	void Update(const unsigned char *data, size_t len) anope_override
    129 	{
    130 		uint32_t i, j;
    131 
    132 		j = (this->count[0] >> 3) & 63;
    133 		if ((this->count[0] += len << 3) < (len << 3))
    134 			++this->count[1];
    135 		this->count[1] += len >> 29;
    136 		if (j + len > 63)
    137 		{
    138 			memcpy(&this->buffer[j], data, (i = 64 - j));
    139 			this->Transform(this->buffer);
    140 			for (; i + 63 < len; i += 64)
    141 				this->Transform(&data[i]);
    142 			j = 0;
    143 		}
    144 		else
    145 			i = 0;
    146 		memcpy(&this->buffer[j], &data[i], len - i);
    147 	}
    148 
    149 	void Finalize() anope_override
    150 	{
    151 		uint32_t i;
    152 		unsigned char finalcount[8];
    153 
    154 		for (i = 0; i < 8; ++i)
    155 			finalcount[i] = static_cast<unsigned char>((this->count[i >= 4 ? 0 : 1] >> ((3 - (i & 3)) * 8)) & 255); /* Endian independent */
    156 		this->Update(reinterpret_cast<const unsigned char *>("\200"), 1);
    157 		while ((this->count[0] & 504) != 448)
    158 			this->Update(reinterpret_cast<const unsigned char *>("\0"), 1);
    159 		this->Update(finalcount, 8); /* Should cause a SHA1Transform() */
    160 		for (i = 0; i < 20; ++i)
    161 			this->digest[i] = static_cast<unsigned char>((this->state[i>>2] >> ((3 - (i & 3)) * 8)) & 255);
    162 
    163 		/* Wipe variables */
    164 		memset(this->buffer, 0, sizeof(this->buffer));
    165 		memset(this->state, 0, sizeof(this->state));
    166 		memset(this->count, 0, sizeof(this->count));
    167 		memset(&finalcount, 0, sizeof(finalcount));
    168 
    169 		this->Transform(this->buffer);
    170 	}
    171 
    172 	Encryption::Hash GetFinalizedHash() anope_override
    173 	{
    174 		Encryption::Hash hash;
    175 		hash.first = this->digest;
    176 		hash.second = sizeof(this->digest);
    177 		return hash;
    178 	}
    179 };
    180 
    181 class SHA1Provider : public Encryption::Provider
    182 {
    183  public:
    184 	SHA1Provider(Module *creator) : Encryption::Provider(creator, "sha1") { }
    185 
    186 	Encryption::Context *CreateContext(Encryption::IV *iv) anope_override
    187 	{
    188 		return new SHA1Context(iv);
    189 	}
    190 
    191 	Encryption::IV GetDefaultIV() anope_override
    192 	{
    193 		Encryption::IV iv;
    194 		iv.first = sha1_iv;
    195 		iv.second = sizeof(sha1_iv) / sizeof(uint32_t);
    196 		return iv;
    197 	}
    198 };
    199 
    200 class ESHA1 : public Module
    201 {
    202 	SHA1Provider sha1provider;
    203 
    204  public:
    205 	ESHA1(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, ENCRYPTION | VENDOR),
    206 		sha1provider(this)
    207 	{
    208 
    209 	}
    210 
    211 	EventReturn OnEncrypt(const Anope::string &src, Anope::string &dest) anope_override
    212 	{
    213 		SHA1Context context;
    214 
    215 		context.Update(reinterpret_cast<const unsigned char *>(src.c_str()), src.length());
    216 		context.Finalize();
    217 
    218 		Encryption::Hash hash = context.GetFinalizedHash();
    219 
    220 		Anope::string buf = "sha1:" + Anope::Hex(reinterpret_cast<const char *>(hash.first), hash.second);
    221 
    222 		Log(LOG_DEBUG_2) << "(enc_sha1) hashed password from [" << src << "] to [" << buf << "]";
    223 		dest = buf;
    224 		return EVENT_ALLOW;
    225 	}
    226 
    227 	void OnCheckAuthentication(User *, IdentifyRequest *req) anope_override
    228 	{
    229 		const NickAlias *na = NickAlias::Find(req->GetAccount());
    230 		if (na == NULL)
    231 			return;
    232 		NickCore *nc = na->nc;
    233 
    234 		size_t pos = nc->pass.find(':');
    235 		if (pos == Anope::string::npos)
    236 			return;
    237 		Anope::string hash_method(nc->pass.begin(), nc->pass.begin() + pos);
    238 		if (!hash_method.equals_cs("sha1"))
    239 			return;
    240 
    241 		Anope::string buf;
    242 		this->OnEncrypt(req->GetPassword(), buf);
    243 		if (nc->pass.equals_cs(buf))
    244 		{
    245 			if (ModuleManager::FindFirstOf(ENCRYPTION) != this)
    246 				Anope::Encrypt(req->GetPassword(), nc->pass);
    247 			req->Success(this);
    248 		}
    249 	}
    250 };
    251 
    252 MODULE_INIT(ESHA1)