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)