diff options
-rw-r--r-- | include/modules/encryption.h | 79 | ||||
-rw-r--r-- | modules/encryption/enc_md5.cpp | 64 | ||||
-rw-r--r-- | modules/encryption/enc_old.cpp | 26 | ||||
-rw-r--r-- | modules/encryption/enc_sha1.cpp | 67 | ||||
-rw-r--r-- | modules/encryption/enc_sha256.cpp | 74 |
5 files changed, 128 insertions, 182 deletions
diff --git a/include/modules/encryption.h b/include/modules/encryption.h index 39eab638b..6b13fcf41 100644 --- a/include/modules/encryption.h +++ b/include/modules/encryption.h @@ -13,26 +13,89 @@ namespace Encryption { - typedef std::pair<const unsigned char *, size_t> Hash; - typedef std::pair<const uint32_t *, size_t> IV; - + /** Base class for encryption contexts. */ class Context { public: virtual ~Context() = default; + + /** Updates the encryption context with the specified data. + * @param str The data to update the context with. + */ + inline void Update(const Anope::string &str) + { + Update(reinterpret_cast<const unsigned char *>(str.c_str()), str.length()); + } + + /** Updates the encryption context with the specified data. + * @param data The data to update the context with. + * @param len The length of the data. + */ virtual void Update(const unsigned char *data, size_t len) = 0; - virtual void Finalize() = 0; - virtual Hash GetFinalizedHash() = 0; + + /** Finalises the encryption context and returns the digest. */ + virtual Anope::string Finalize() = 0; }; + /** Provider of encryption contexts. */ class Provider : public Service { public: - Provider(Module *creator, const Anope::string &sname) : Service(creator, "Encryption::Provider", sname) { } + /** The byte size of the block cipher. */ + const size_t block_size; + + /** The byte size of the resulting digest. */ + const size_t digest_size; + + /** Creates a provider of encryption contexts. + * @param creator The module that created this provider. + * @param algorithm The name of the encryption algorithm. + * @param bs The byte size of the block cipher. + * @param ds The byte size of the resulting digest. + */ + Provider(Module *creator, const Anope::string &algorithm, size_t bs, size_t ds) + : Service(creator, "Encryption::Provider", algorithm) + , block_size(bs) + , digest_size(ds) + { + } + virtual ~Provider() = default; - virtual Context *CreateContext(IV * = NULL) = 0; - virtual IV GetDefaultIV() = 0; + /** Creates a new encryption context. */ + virtual std::unique_ptr<Context> CreateContext() = 0; + + template<typename... Args> + Anope::string Encrypt(Args &&...args) + { + auto context = CreateContext(); + context->Update(std::forward<Args>(args)...); + return context->Finalize(); + } + }; + + /** Helper template for creating simple providers of encryption contexts. */ + template <typename T> + class SimpleProvider final + : public Provider + { + public: + /** Creates a simple provider of encryption contexts. + * @param creator The module that created this provider. + * @param algorithm The name of the encryption algorithm. + * @param bs The byte size of the block cipher. + * @param ds The byte size of the resulting digest. + */ + SimpleProvider(Module *creator, const Anope::string &algorithm, size_t bs, size_t ds) + : Provider(creator, algorithm, bs, ds) + { + } + + /** @copydoc Encryption::Provider::CreateContext. */ + std::unique_ptr<Context> CreateContext() override + { + return std::make_unique<T>(); + } }; } diff --git a/modules/encryption/enc_md5.cpp b/modules/encryption/enc_md5.cpp index 5123e6d11..a05e3aa13 100644 --- a/modules/encryption/enc_md5.cpp +++ b/modules/encryption/enc_md5.cpp @@ -92,7 +92,6 @@ class MD5Context final unsigned state[4]; /* state (ABCD) */ unsigned count[2]; /* number of bits, modulo 2^64 (lsb first) */ unsigned char buffer[64]; /* input buffer */ - unsigned char digest[16]; /* final digest */ /* Constants for MD5Transform routine. */ @@ -229,19 +228,10 @@ class MD5Context final } public: - MD5Context(Encryption::IV *iv = NULL) + MD5Context() { - if (iv != NULL) - { - if (iv->second != 4) - throw CoreException("Invalid IV size"); - /* Load magic initialization constants. */ - for (int i = 0; i < 4; ++i) - this->state[i] = iv->first[i]; - } - else - for (int i = 0; i < 4; ++i) - this->state[i] = md5_iv[i]; + for (int i = 0; i < 4; ++i) + this->state[i] = md5_iv[i]; this->count[0] = this->count[1] = 0; memset(this->buffer, 0, sizeof(this->buffer)); @@ -286,7 +276,7 @@ public: /* MD5 finalization. Ends an MD5 message-digest opera * the message digest and zeroizing the context. */ - void Finalize() override + Anope::string Finalize() override { unsigned char bits[8]; unsigned index, padLen; @@ -301,6 +291,7 @@ public: /* Append length (before padding) */ this->Update(bits, 8); + unsigned char digest[16]; /* final digest */ /* Store state in digest */ this->Encode(digest, this->state, 16); @@ -308,45 +299,21 @@ public: memset(this->state, 0, sizeof(this->state)); memset(this->count, 0, sizeof(this->count)); memset(this->buffer, 0, sizeof(this->buffer)); - } - - Encryption::Hash GetFinalizedHash() override - { - Encryption::Hash hash; - hash.first = this->digest; - hash.second = sizeof(this->digest); - return hash; - } -}; - -class MD5Provider final - : public Encryption::Provider -{ -public: - MD5Provider(Module *creator) : Encryption::Provider(creator, "md5") { } - Encryption::Context *CreateContext(Encryption::IV *iv) override - { - return new MD5Context(iv); - } - - Encryption::IV GetDefaultIV() override - { - Encryption::IV iv; - iv.first = md5_iv; - iv.second = sizeof(md5_iv) / sizeof(uint32_t); - return iv; + return Anope::string(reinterpret_cast<const char *>(&digest), sizeof(digest)); } }; class EMD5 final : public Module { - MD5Provider md5provider; +private: + Encryption::SimpleProvider<MD5Context> md5provider; public: - EMD5(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, ENCRYPTION | VENDOR), - md5provider(this) + EMD5(const Anope::string &modname, const Anope::string &creator) + : Module(modname, creator, ENCRYPTION | VENDOR) + , md5provider(this, "md5", 16, 64) { if (ModuleManager::FindFirstOf(ENCRYPTION) == this) throw ModuleException("enc_md5 is deprecated and can not be used as a primary encryption method"); @@ -354,14 +321,7 @@ public: EventReturn OnEncrypt(const Anope::string &src, Anope::string &dest) override { - MD5Context context; - - context.Update(reinterpret_cast<const unsigned char *>(src.c_str()), src.length()); - context.Finalize(); - - Encryption::Hash hash = context.GetFinalizedHash(); - - Anope::string buf = "md5:" + Anope::Hex(reinterpret_cast<const char *>(hash.first), hash.second); + Anope::string buf = "md5:" + Anope::Hex(md5provider.Encrypt(src)); Log(LOG_DEBUG_2) << "(enc_md5) hashed password from [" << src << "] to [" << buf << "]"; dest = buf; diff --git a/modules/encryption/enc_old.cpp b/modules/encryption/enc_old.cpp index 0b1cd9884..f2344aeff 100644 --- a/modules/encryption/enc_old.cpp +++ b/modules/encryption/enc_old.cpp @@ -18,20 +18,16 @@ class OldMD5Provider final : public Encryption::Provider { public: - OldMD5Provider(Module *creator) : Encryption::Provider(creator, "oldmd5") { } - - Encryption::Context *CreateContext(Encryption::IV *iv) override + OldMD5Provider(Module *creator) + : Encryption::Provider(creator, "oldmd5", 16, 64) { - if (md5) - return md5->CreateContext(iv); - return NULL; } - Encryption::IV GetDefaultIV() override + std::unique_ptr<Encryption::Context> CreateContext() override { if (md5) - return md5->GetDefaultIV(); - return Encryption::IV(static_cast<const uint32_t *>(NULL), 0); + return md5->CreateContext(); + return nullptr; } }; @@ -60,17 +56,12 @@ public: if (!md5) return EVENT_CONTINUE; - Encryption::Context *context = md5->CreateContext(); - context->Update(reinterpret_cast<const unsigned char *>(src.c_str()), src.length()); - context->Finalize(); - - Encryption::Hash hash = context->GetFinalizedHash(); - char digest[32], digest2[16]; memset(digest, 0, sizeof(digest)); - if (hash.second > sizeof(digest)) + auto hash = md5->Encrypt(src); + if (hash.length() > sizeof(digest)) throw CoreException("Hash too large"); - memcpy(digest, hash.first, hash.second); + memcpy(digest, hash.data(), hash.length()); for (int i = 0; i < 32; i += 2) digest2[i / 2] = XTOI(digest[i]) << 4 | XTOI(digest[i + 1]); @@ -79,7 +70,6 @@ public: Log(LOG_DEBUG_2) << "(enc_old) hashed password from [" << src << "] to [" << buf << "]"; dest = buf; - delete context; return EVENT_ALLOW; } diff --git a/modules/encryption/enc_sha1.cpp b/modules/encryption/enc_sha1.cpp index 07d6d094d..4f5ca1955 100644 --- a/modules/encryption/enc_sha1.cpp +++ b/modules/encryption/enc_sha1.cpp @@ -60,7 +60,6 @@ class SHA1Context final uint32_t state[5]; uint32_t count[2]; unsigned char buffer[64]; - unsigned char digest[20]; void Transform(const unsigned char buf[64]) { @@ -108,22 +107,13 @@ class SHA1Context final } public: - SHA1Context(Encryption::IV *iv = NULL) + SHA1Context() { - if (iv != NULL) - { - if (iv->second != 5) - throw CoreException("Invalid IV size"); - for (int i = 0; i < 5; ++i) - this->state[i] = iv->first[i]; - } - else - for (int i = 0; i < 5; ++i) - this->state[i] = sha1_iv[i]; + for (int i = 0; i < 5; ++i) + this->state[i] = sha1_iv[i]; this->count[0] = this->count[1] = 0; memset(this->buffer, 0, sizeof(this->buffer)); - memset(this->digest, 0, sizeof(this->digest)); } void Update(const unsigned char *data, size_t len) override @@ -147,7 +137,7 @@ public: memcpy(&this->buffer[j], &data[i], len - i); } - void Finalize() override + Anope::string Finalize() override { uint32_t i; unsigned char finalcount[8]; @@ -158,8 +148,10 @@ public: while ((this->count[0] & 504) != 448) this->Update(reinterpret_cast<const unsigned char *>("\0"), 1); this->Update(finalcount, 8); /* Should cause a SHA1Transform() */ + unsigned char digest[20]; + memset(digest, 0, sizeof(digest)); for (i = 0; i < 20; ++i) - this->digest[i] = static_cast<unsigned char>((this->state[i>>2] >> ((3 - (i & 3)) * 8)) & 255); + digest[i] = static_cast<unsigned char>((this->state[i>>2] >> ((3 - (i & 3)) * 8)) & 255); /* Wipe variables */ memset(this->buffer, 0, sizeof(this->buffer)); @@ -168,45 +160,21 @@ public: memset(&finalcount, 0, sizeof(finalcount)); this->Transform(this->buffer); - } - - Encryption::Hash GetFinalizedHash() override - { - Encryption::Hash hash; - hash.first = this->digest; - hash.second = sizeof(this->digest); - return hash; - } -}; - -class SHA1Provider final - : public Encryption::Provider -{ -public: - SHA1Provider(Module *creator) : Encryption::Provider(creator, "sha1") { } - Encryption::Context *CreateContext(Encryption::IV *iv) override - { - return new SHA1Context(iv); - } - - Encryption::IV GetDefaultIV() override - { - Encryption::IV iv; - iv.first = sha1_iv; - iv.second = sizeof(sha1_iv) / sizeof(uint32_t); - return iv; + return Anope::string(reinterpret_cast<const char *>(&digest), sizeof(digest)); } }; class ESHA1 final : public Module { - SHA1Provider sha1provider; +private: + Encryption::SimpleProvider<SHA1Context> sha1provider; public: - ESHA1(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, ENCRYPTION | VENDOR), - sha1provider(this) + ESHA1(const Anope::string &modname, const Anope::string &creator) + : Module(modname, creator, ENCRYPTION | VENDOR) + , sha1provider(this, "sha1", 20, 64) { if (ModuleManager::FindFirstOf(ENCRYPTION) == this) throw ModuleException("enc_sha1 is deprecated and can not be used as a primary encryption method"); @@ -214,14 +182,7 @@ public: EventReturn OnEncrypt(const Anope::string &src, Anope::string &dest) override { - SHA1Context context; - - context.Update(reinterpret_cast<const unsigned char *>(src.c_str()), src.length()); - context.Finalize(); - - Encryption::Hash hash = context.GetFinalizedHash(); - - Anope::string buf = "sha1:" + Anope::Hex(reinterpret_cast<const char *>(hash.first), hash.second); + Anope::string buf = "sha1:" + Anope::Hex(sha1provider.Encrypt(src)); Log(LOG_DEBUG_2) << "(enc_sha1) hashed password from [" << src << "] to [" << buf << "]"; dest = buf; diff --git a/modules/encryption/enc_sha256.cpp b/modules/encryption/enc_sha256.cpp index 97bd5dd9d..506c07328 100644 --- a/modules/encryption/enc_sha256.cpp +++ b/modules/encryption/enc_sha256.cpp @@ -151,26 +151,22 @@ class SHA256Context final unsigned len; unsigned char block[2 * SHA256_BLOCK_SIZE]; uint32_t h[8]; - unsigned char digest[SHA256_DIGEST_SIZE]; public: - SHA256Context(Encryption::IV *iv) + SHA256Context() { - if (iv != NULL) - { - if (iv->second != 8) - throw CoreException("Invalid IV size"); - for (int i = 0; i < 8; ++i) - this->h[i] = iv->first[i]; - } - else - for (int i = 0; i < 8; ++i) - this->h[i] = sha256_h0[i]; + for (int i = 0; i < 8; ++i) + this->h[i] = sha256_h0[i]; this->tot_len = 0; this->len = 0; memset(this->block, 0, sizeof(this->block)); - memset(this->digest, 0, sizeof(this->digest)); + } + + void SetIV(uint32_t* iv) + { + for (int i = 0; i < 8; ++i) + this->h[i] = iv[i]; } void Update(const unsigned char *message, size_t mlen) override @@ -195,7 +191,7 @@ public: this->tot_len += (block_nb + 1) << 6; } - void Finalize() override + Anope::string Finalize() override { unsigned block_nb = 1 + ((SHA256_BLOCK_SIZE - 9) < (this->len % SHA256_BLOCK_SIZE)); unsigned len_b = (this->tot_len + this->len) << 3; @@ -204,43 +200,20 @@ public: this->block[this->len] = 0x80; UNPACK32(len_b, this->block + pm_len - 4); this->Transform(this->block, block_nb); + unsigned char digest[SHA256_DIGEST_SIZE]; + memset(digest, 0, sizeof(digest)); for (int i = 0 ; i < 8; ++i) - UNPACK32(this->h[i], &this->digest[i << 2]); - } + UNPACK32(this->h[i], &digest[i << 2]); - Encryption::Hash GetFinalizedHash() override - { - Encryption::Hash hash; - hash.first = this->digest; - hash.second = SHA256_DIGEST_SIZE; - return hash; - } -}; - -class SHA256Provider final - : public Encryption::Provider -{ -public: - SHA256Provider(Module *creator) : Encryption::Provider(creator, "sha256") { } - - Encryption::Context *CreateContext(Encryption::IV *iv) override - { - return new SHA256Context(iv); - } - - Encryption::IV GetDefaultIV() override - { - Encryption::IV iv; - iv.first = sha256_h0; - iv.second = sizeof(sha256_h0) / sizeof(uint32_t); - return iv; + return Anope::string(reinterpret_cast<const char *>(&digest), sizeof(digest)); } }; class ESHA256 final : public Module { - SHA256Provider sha256provider; +private: + Encryption::SimpleProvider<SHA256Context> sha256provider; unsigned iv[8]; bool use_iv; @@ -275,8 +248,9 @@ class ESHA256 final } public: - ESHA256(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, ENCRYPTION | VENDOR), - sha256provider(this) + ESHA256(const Anope::string &modname, const Anope::string &creator) + : Module(modname, creator, ENCRYPTION | VENDOR) + , sha256provider(this, "sha256", SHA256_BLOCK_SIZE, SHA256_DIGEST_SIZE) { use_iv = false; } @@ -288,15 +262,13 @@ public: else use_iv = false; - Encryption::IV initialization(this->iv, 8); - SHA256Context ctx(&initialization); + SHA256Context ctx; + ctx.SetIV(this->iv); ctx.Update(reinterpret_cast<const unsigned char *>(src.c_str()), src.length()); - ctx.Finalize(); - - Encryption::Hash hash = ctx.GetFinalizedHash(); + auto hash = ctx.Finalize(); std::stringstream buf; - buf << "sha256:" << Anope::Hex(reinterpret_cast<const char *>(hash.first), hash.second) << ":" << GetIVString(); + buf << "sha256:" << Anope::Hex(hash) << ":" << GetIVString(); Log(LOG_DEBUG_2) << "(enc_sha256) hashed password from [" << src << "] to [" << buf.str() << " ]"; dest = buf.str(); return EVENT_ALLOW; |