From 527c492cf1c86ede062c49d45ebda17c8c6dfc68 Mon Sep 17 00:00:00 2001 From: danieldg Date: Sun, 21 Feb 2010 17:08:54 +0000 Subject: Add HMAC implementation to HashProvider git-svn-id: http://svn.inspircd.org/repository/trunk/inspircd@12508 e03df62e-2008-0410-955e-edbf42e46eb7 --- src/modules/hash.h | 70 ++++++++++++++++++++++++++++++ src/modules/m_cloaking.cpp | 2 +- src/modules/m_hash.h | 53 ---------------------- src/modules/m_md5.cpp | 5 +-- src/modules/m_password_hash.cpp | 29 ++----------- src/modules/m_ripemd160.cpp | 5 +-- src/modules/m_sha256.cpp | 8 ++-- src/modules/m_spanningtree/hmac.cpp | 44 +++++++++---------- src/modules/m_spanningtree/treesocket1.cpp | 1 - src/modules/m_sqlauth.cpp | 3 +- src/modules/m_sqloper.cpp | 3 +- 11 files changed, 106 insertions(+), 117 deletions(-) create mode 100644 src/modules/hash.h delete mode 100644 src/modules/m_hash.h (limited to 'src') diff --git a/src/modules/hash.h b/src/modules/hash.h new file mode 100644 index 000000000..7e93f0ddc --- /dev/null +++ b/src/modules/hash.h @@ -0,0 +1,70 @@ +/* +------------------------------------+ + * | Inspire Internet Relay Chat Daemon | + * +------------------------------------+ + * + * InspIRCd: (C) 2002-2010 InspIRCd Development Team + * See: http://wiki.inspircd.org/Credits + * + * This program is free but copyrighted software; see + * the file COPYING for details. + * + * --------------------------------------------------- + */ + +#ifndef __HASH_H__ +#define __HASH_H__ + +#include "modules.h" + +class HashProvider : public DataProvider +{ + public: + const unsigned int out_size; + const unsigned int block_size; + HashProvider(Module* mod, const std::string& Name, int osiz, int bsiz) + : DataProvider(mod, Name), out_size(osiz), block_size(bsiz) {} + virtual std::string sum(const std::string& data) = 0; + inline std::string hexsum(const std::string& data) + { + return BinToHex(sum(data)); + } + + inline std::string b64sum(const std::string& data) + { + return BinToBase64(sum(data), NULL, 0); + } + + /** Allows the IVs for the hash to be specified. As the choice of initial IV is + * important for the security of a hash, this should not be used except to + * maintain backwards compatability. This also allows you to change the hex + * sequence from its default of "0123456789abcdef", which does not improve the + * strength of the output, but helps confuse those attempting to implement it. + * + * Example: + * \code + * unsigned int iv[] = { 0xFFFFFFFF, 0x00000000, 0xAAAAAAAA, 0xCCCCCCCC }; + * std::string result = Hash.sumIV(iv, "fedcba9876543210", "data"); + * \endcode + */ + virtual std::string sumIV(unsigned int* IV, const char* HexMap, const std::string &sdata) = 0; + + /** HMAC algorithm, RFC 2104 */ + std::string hmac(const std::string& key, const std::string& msg) + { + std::string hmac1, hmac2; + std::string kbuf = key.length() > block_size ? sum(key) : key; + kbuf.resize(block_size); + + for (size_t n = 0; n < block_size; n++) + { + hmac1.push_back(static_cast(kbuf[n] ^ 0x5C)); + hmac2.push_back(static_cast(kbuf[n] ^ 0x36)); + } + hmac2.append(msg); + hmac1.append(sum(hmac2)); + return sum(hmac1); + } +}; + +#endif + diff --git a/src/modules/m_cloaking.cpp b/src/modules/m_cloaking.cpp index 56a2f5d43..0d6e2b00a 100644 --- a/src/modules/m_cloaking.cpp +++ b/src/modules/m_cloaking.cpp @@ -12,7 +12,7 @@ */ #include "inspircd.h" -#include "m_hash.h" +#include "hash.h" /* $ModDesc: Provides masking of user hostnames */ diff --git a/src/modules/m_hash.h b/src/modules/m_hash.h deleted file mode 100644 index edc9688b8..000000000 --- a/src/modules/m_hash.h +++ /dev/null @@ -1,53 +0,0 @@ -/* +------------------------------------+ - * | Inspire Internet Relay Chat Daemon | - * +------------------------------------+ - * - * InspIRCd: (C) 2002-2010 InspIRCd Development Team - * See: http://wiki.inspircd.org/Credits - * - * This program is free but copyrighted software; see - * the file COPYING for details. - * - * --------------------------------------------------- - */ - -#ifndef __HASH_H__ -#define __HASH_H__ - -#include "modules.h" - -#define SHA256_DIGEST_SIZE (256 / 8) -#define SHA256_BLOCK_SIZE (512 / 8) - -class HashProvider : public DataProvider -{ - public: - HashProvider(Module* mod, const std::string& Name) : DataProvider(mod, Name) {} - virtual std::string sum(const std::string& data) = 0; - inline std::string hexsum(const std::string& data) - { - return BinToHex(sum(data)); - } - - inline std::string b64sum(const std::string& data) - { - return BinToBase64(sum(data), NULL, 0); - } - - /** Allows the IVs for the hash to be specified. As the choice of initial IV is - * important for the security of a hash, this should not be used except to - * maintain backwards compatability. This also allows you to change the hex - * sequence from its default of "0123456789abcdef", which does not improve the - * strength of the output, but helps confuse those attempting to implement it. - * - * Example: - * \code - * unsigned int iv[] = { 0xFFFFFFFF, 0x00000000, 0xAAAAAAAA, 0xCCCCCCCC }; - * std::string result = Hash.sumIV(iv, "fedcba9876543210", "data"); - * \endcode - */ - virtual std::string sumIV(unsigned int* IV, const char* HexMap, const std::string &sdata) = 0; -}; - -#endif - diff --git a/src/modules/m_md5.cpp b/src/modules/m_md5.cpp index c6761926a..a6df62dd9 100644 --- a/src/modules/m_md5.cpp +++ b/src/modules/m_md5.cpp @@ -12,13 +12,12 @@ */ /* $ModDesc: Allows for MD5 encrypted oper passwords */ -/* $ModDep: m_hash.h */ #include "inspircd.h" #ifdef HAS_STDINT #include #endif -#include "m_hash.h" +#include "hash.h" /* The four core functions - F1 is optimized somewhat */ #define F1(x, y, z) (z ^ (x & (y ^ z))) @@ -273,7 +272,7 @@ class MD5Provider : public HashProvider return res; } - MD5Provider(Module* parent) : HashProvider(parent, "hash/md5") {} + MD5Provider(Module* parent) : HashProvider(parent, "hash/md5", 16, 64) {} }; class ModuleMD5 : public Module diff --git a/src/modules/m_password_hash.cpp b/src/modules/m_password_hash.cpp index d27856b3e..7d2b9fc79 100644 --- a/src/modules/m_password_hash.cpp +++ b/src/modules/m_password_hash.cpp @@ -14,20 +14,7 @@ /* $ModDesc: Allows for hashed oper passwords */ #include "inspircd.h" -#include "m_hash.h" - -static std::string hmac(HashProvider* hp, const std::string& key, const std::string& msg) -{ - std::string hmac1, hmac2; - for (size_t n = 0; n < key.length(); n++) - { - hmac1.push_back(static_cast(key[n] ^ 0x5C)); - hmac2.push_back(static_cast(key[n] ^ 0x36)); - } - hmac2.append(msg); - hmac1.append(hp->sum(hmac2)); - return hp->sum(hmac1); -} +#include "hash.h" /* Handle /MKPASSWD */ @@ -51,8 +38,8 @@ class CommandMkpasswd : public Command user->WriteServ("NOTICE %s :Unknown hash type", user->nick.c_str()); return; } - std::string salt = GenRandomStr(6, false); - std::string target = hmac(hp, salt, stuff); + std::string salt = ServerInstance->GenRandomStr(6, false); + std::string target = hp->hmac(salt, stuff); std::string str = BinToBase64(salt) + "$" + BinToBase64(target, NULL, 0); user->WriteServ("NOTICE %s :%s hashed password for %s is %s", @@ -109,15 +96,7 @@ class ModuleOperHash : public Module std::string salt = Base64ToBin(data.substr(0, sep)); std::string target = Base64ToBin(data.substr(sep + 1)); - std::string hmac1, hmac2; - for (size_t n = 0; n < salt.length(); n++) - { - hmac1.push_back(static_cast(salt[n] ^ 0x5C)); - hmac2.push_back(static_cast(salt[n] ^ 0x36)); - } - hmac2.append(input); - hmac1.append(hp->sum(hmac2)); - if (target == hp->sum(hmac1)) + if (target == hp->hmac(salt, input)) return MOD_RES_ALLOW; else return MOD_RES_DENY; diff --git a/src/modules/m_ripemd160.cpp b/src/modules/m_ripemd160.cpp index 44e16c86f..c126db661 100644 --- a/src/modules/m_ripemd160.cpp +++ b/src/modules/m_ripemd160.cpp @@ -48,7 +48,6 @@ /* $ModDesc: Allows for RIPEMD-160 encrypted oper passwords */ -/* $ModDep: m_hash.h */ /* macro definitions */ @@ -56,7 +55,7 @@ #ifdef HAS_STDINT #include #endif -#include "m_hash.h" +#include "hash.h" #define RMDsize 160 @@ -448,7 +447,7 @@ public: return ""; } - RIProv(Module* m) : HashProvider(m, "hash/ripemd160") {} + RIProv(Module* m) : HashProvider(m, "hash/ripemd160", 20, 64) {} }; class ModuleRIPEMD160 : public Module diff --git a/src/modules/m_sha256.cpp b/src/modules/m_sha256.cpp index 679a97ae0..707853a49 100644 --- a/src/modules/m_sha256.cpp +++ b/src/modules/m_sha256.cpp @@ -48,18 +48,20 @@ */ /* $ModDesc: Allows for SHA-256 encrypted oper passwords */ -/* $ModDep: m_hash.h */ #include "inspircd.h" #ifdef HAS_STDINT #include #endif -#include "m_hash.h" +#include "hash.h" #ifndef HAS_STDINT typedef unsigned int uint32_t; #endif +#define SHA256_DIGEST_SIZE (256 / 8) +#define SHA256_BLOCK_SIZE (512 / 8) + /** An sha 256 context, used by m_opersha256 */ class SHA256Context @@ -257,7 +259,7 @@ class HashSHA256 : public HashProvider return ""; } - HashSHA256(Module* parent) : HashProvider(parent, "hash/sha256") {} + HashSHA256(Module* parent) : HashProvider(parent, "hash/sha256", 32, 64) {} }; class ModuleSHA256 : public Module diff --git a/src/modules/m_spanningtree/hmac.cpp b/src/modules/m_spanningtree/hmac.cpp index 52128b17b..e339598af 100644 --- a/src/modules/m_spanningtree/hmac.cpp +++ b/src/modules/m_spanningtree/hmac.cpp @@ -14,7 +14,7 @@ #include "inspircd.h" #include "socket.h" #include "xline.h" -#include "../m_hash.h" +#include "../hash.h" #include "../ssl.h" #include "socketengine.h" @@ -56,31 +56,23 @@ std::string TreeSocket::MakePass(const std::string &password, const std::string HashProvider* sha256 = ServerInstance->Modules->FindDataService("hash/sha256"); if (Utils->ChallengeResponse && sha256 && !challenge.empty()) { - /* This is how HMAC is supposed to be done: - * - * sha256( (pass xor 0x5c) + sha256((pass xor 0x36) + m) ) - * - * 5c and 36 were chosen as part of the HMAC standard, because they - * flip the bits in a way likely to strengthen the function. - */ - std::string hmac1, hmac2; - - for (size_t n = 0; n < password.length(); n++) + if (proto_version < 1202) { - hmac1.push_back(static_cast(password[n] ^ 0x5C)); - hmac2.push_back(static_cast(password[n] ^ 0x36)); - } + /* This is how HMAC is done in InspIRCd 1.2: + * + * sha256( (pass xor 0x5c) + sha256((pass xor 0x36) + m) ) + * + * 5c and 36 were chosen as part of the HMAC standard, because they + * flip the bits in a way likely to strengthen the function. + */ + std::string hmac1, hmac2; + + for (size_t n = 0; n < password.length(); n++) + { + hmac1.push_back(static_cast(password[n] ^ 0x5C)); + hmac2.push_back(static_cast(password[n] ^ 0x36)); + } - if (proto_version >= 1202) - { - hmac2.append(challenge); - std::string hmac = sha256->hexsum(hmac1 + sha256->sum(hmac2)); - - return "AUTH:" + hmac; - } - else - { - // version 1.2 used a weaker HMAC, using hex output in the intermediate step hmac2.append(challenge); hmac2 = sha256->hexsum(hmac2); @@ -89,6 +81,10 @@ std::string TreeSocket::MakePass(const std::string &password, const std::string return "HMAC-SHA256:"+ hmac; } + else + { + return "AUTH:" + BinToBase64(sha256->hmac(password, challenge)); + } } else if (!challenge.empty() && !sha256) ServerInstance->Logs->Log("m_spanningtree",DEFAULT,"Not authenticating to server using SHA256/HMAC because we don't have m_sha256 loaded!"); diff --git a/src/modules/m_spanningtree/treesocket1.cpp b/src/modules/m_spanningtree/treesocket1.cpp index 596f31041..f1925afad 100644 --- a/src/modules/m_spanningtree/treesocket1.cpp +++ b/src/modules/m_spanningtree/treesocket1.cpp @@ -14,7 +14,6 @@ #include "inspircd.h" #include "socket.h" #include "xline.h" -#include "../m_hash.h" #include "socketengine.h" #include "main.h" diff --git a/src/modules/m_sqlauth.cpp b/src/modules/m_sqlauth.cpp index 88de06d1a..59faf0c3d 100644 --- a/src/modules/m_sqlauth.cpp +++ b/src/modules/m_sqlauth.cpp @@ -14,10 +14,9 @@ #include "inspircd.h" #include "m_sqlv2.h" #include "m_sqlutils.h" -#include "m_hash.h" +#include "hash.h" /* $ModDesc: Allow/Deny connections based upon an arbitary SQL table */ -/* $ModDep: m_sqlv2.h m_sqlutils.h m_hash.h */ class ModuleSQLAuth : public Module { diff --git a/src/modules/m_sqloper.cpp b/src/modules/m_sqloper.cpp index b4cdc760a..871ef7d46 100644 --- a/src/modules/m_sqloper.cpp +++ b/src/modules/m_sqloper.cpp @@ -14,10 +14,9 @@ #include "inspircd.h" #include "m_sqlv2.h" #include "m_sqlutils.h" -#include "m_hash.h" +#include "hash.h" /* $ModDesc: Allows storage of oper credentials in an SQL table */ -/* $ModDep: m_sqlv2.h m_sqlutils.h m_hash.h */ typedef std::map hashymodules; -- cgit v1.2.3