diff options
Diffstat (limited to 'include/modules/encryption.h')
-rw-r--r-- | include/modules/encryption.h | 138 |
1 files changed, 125 insertions, 13 deletions
diff --git a/include/modules/encryption.h b/include/modules/encryption.h index 7162ef255..c475f4fbd 100644 --- a/include/modules/encryption.h +++ b/include/modules/encryption.h @@ -9,27 +9,139 @@ * Based on the original code of Services by Andy Church. */ +#pragma once + 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() { } + 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: + /** 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; + + /** Checks whether a plain text value matches a hash created by this provider. */ + virtual bool Compare(const Anope::string &hash, const Anope::string &plain) + { + return !hash.empty() && hash.equals_cs(ToPrintable(Encrypt(plain))); + } + + /** Called on initialising a encryption provider to check it works properly. */ + void Check(const Anope::map<Anope::string> &checks) + { + for (const auto &[hash, plain] : checks) + { + if (!Compare(hash, plain)) + throw ModuleException("BUG: unable to generate " + this->name + " hashes safely! Please report this!"); + } + Log(LOG_DEBUG) << "The " << this->name << " encryption provider appears to be working correctly."; + } + + /** Creates a new encryption context. */ + virtual std::unique_ptr<Context> CreateContext() = 0; + + /** Quickly encrypts the specified values and returns the digest. */ + template<typename... Args> + Anope::string Encrypt(Args &&...args) + { + auto context = CreateContext(); + context->Update(std::forward<Args>(args)...); + return context->Finalize(); + } + + /** Calculates the RFC 2104 hash-based message authentication code for the specified data. */ + inline Anope::string HMAC(const Anope::string &key, const Anope::string &data) + { + if (!block_size) + return {}; + + auto keybuf = key.length() > block_size ? Encrypt(key) : key; + keybuf.resize(block_size); + + Anope::string hmac1; + Anope::string hmac2; + for (size_t i = 0; i < block_size; ++i) + { + hmac1.push_back(static_cast<char>(keybuf[i] ^ 0x5C)); + hmac2.push_back(static_cast<char>(keybuf[i] ^ 0x36)); + } + hmac2.append(data); + hmac1.append(Encrypt(hmac2)); + + return Encrypt(hmac1); + } + + /** Converts a hash to its printable form. */ + virtual Anope::string ToPrintable(const Anope::string &hash) + { + return Anope::Hex(hash); + } }; - class Provider : public Service + /** Helper template for creating simple providers of encryption contexts. */ + template <typename T> + class SimpleProvider final + : public Provider { - public: - Provider(Module *creator, const Anope::string &sname) : Service(creator, "Encryption::Provider", sname) { } - virtual ~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) + { + } - virtual Context *CreateContext(IV * = NULL) = 0; - virtual IV GetDefaultIV() = 0; + /** @copydoc Encryption::Provider::CreateContext. */ + std::unique_ptr<Context> CreateContext() override + { + return std::make_unique<T>(); + } }; } |