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)