2 * InspIRCd -- Internet Relay Chat Daemon
4 * Copyright (C) 2020 Elizabeth Myers <elizabeth@interlinked.me>
5 * Copyright (C) 2020 Daniel Vassdal <shutter@canternet.org>
7 * This file is part of InspIRCd. InspIRCd is free software: you can
8 * redistribute it and/or modify it under the terms of the GNU General Public
9 * License as published by the Free Software Foundation, version 2.
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 /// $CompilerFlags: find_compiler_flags("libargon2" "")
22 /// $LinkerFlags: find_linker_flags("libargon2" "-largon2")
24 /// $PackageInfo: require_system("arch") argon2 pkgconf
25 /// $PackageInfo: require_system("darwin") argon2 pkg-config
26 /// $PackageInfo: require_system("debian" "9.0") libargon2-0 pkg-config
27 /// $PackageInfo: require_system("ubuntu" "18.04") libargon2-0-dev pkg-config
31 #include "modules/hash.h"
34 # pragma GCC diagnostic push
37 // Fix warnings about the use of `long long` on C++03
39 # pragma clang diagnostic ignored "-Wc++11-long-long"
40 #elif defined __GNUC__
41 # pragma GCC diagnostic ignored "-Wlong-long"
49 static Argon2_version SanitizeArgon2Version(unsigned long version)
51 // Note, 10 is 0x10, and 13 is 0x13. Referring to it as
52 // dec 10 or 13 in the config file, for the name to
57 return ARGON2_VERSION_10;
59 return ARGON2_VERSION_13;
62 ServerInstance->Logs->Log("MODULE", LOG_DEFAULT, "Unknown Argon2 version (%lu) specified; assuming 13",
64 return ARGON2_VERSION_13;
74 Argon2_version version;
78 // Nothing interesting happens here.
81 ProviderConfig(const std::string& tagname, ProviderConfig* def)
83 ConfigTag* tag = ServerInstance->Config->ConfValue(tagname);
85 uint32_t def_iterations = def ? def->iterations : 3;
86 this->iterations = tag->getUInt("iterations", def_iterations, 1);
88 uint32_t def_lanes = def ? def->lanes : 1;
89 this->lanes = tag->getUInt("lanes", def_lanes, ARGON2_MIN_LANES, ARGON2_MAX_LANES);
91 uint32_t def_memory = def ? def->memory : 131072; // 128 MiB
92 this->memory = tag->getUInt("memory", def_memory, ARGON2_MIN_MEMORY, ARGON2_MAX_MEMORY);
94 uint32_t def_outlen = def ? def->outlen : 32;
95 this->outlen = tag->getUInt("length", def_outlen, ARGON2_MIN_OUTLEN, ARGON2_MAX_OUTLEN);
97 uint32_t def_saltlen = def ? def->saltlen : 16;
98 this->saltlen = tag->getUInt("saltlength", def_saltlen, ARGON2_MIN_SALT_LENGTH, ARGON2_MAX_SALT_LENGTH);
100 uint32_t def_threads = def ? def->threads : 1;
101 this->threads = tag->getUInt("threads", def_threads, ARGON2_MIN_THREADS, ARGON2_MAX_THREADS);
103 uint32_t def_version = def ? def->version : 13;
104 this->version = SanitizeArgon2Version(tag->getUInt("version", def_version));
108 class HashArgon2 : public HashProvider
111 const Argon2_type argon2Type;
114 ProviderConfig config;
116 bool Compare(const std::string& input, const std::string& hash) CXX11_OVERRIDE
118 int result = argon2_verify(
124 return result == ARGON2_OK;
127 std::string GenerateRaw(const std::string& data) CXX11_OVERRIDE
129 const std::string salt = ServerInstance->GenRandomStr(config.saltlen, false);
131 size_t encodedLen = argon2_encodedlen(
139 std::vector<char> raw_data(config.outlen);
140 std::vector<char> encoded_data(encodedLen + 1);
142 int argonResult = argon2_hash(
157 if (argonResult != ARGON2_OK)
158 throw ModuleException("Argon2 hashing failed!: " + std::string(argon2_error_message(argonResult)));
160 // This isn't the raw version, but we don't have
161 // the facilities to juggle around the extra state required
162 // to do anything useful with them if we don't encode them.
163 // So we pretend this is the raw version, and instead make
164 // ToPrintable return its input.
165 return std::string(&encoded_data[0], encoded_data.size());
168 std::string ToPrintable(const std::string& raw) CXX11_OVERRIDE
173 HashArgon2(Module* parent, const std::string& hashName, Argon2_type type)
174 : HashProvider(parent, hashName)
181 class ModuleArgon2 : public Module
190 : argon2i(this, "argon2i", Argon2_i)
191 , argon2d(this, "argon2d", Argon2_d)
192 , argon2id(this, "argon2id", Argon2_id)
196 Version GetVersion() CXX11_OVERRIDE
198 return Version("Allows other modules to generate Argon2 hashes.", VF_VENDOR);
201 void ReadConfig(ConfigStatus& status) CXX11_OVERRIDE
203 ProviderConfig defaultConfig("argon2", NULL);
204 argon2i.config = ProviderConfig("argon2i", &defaultConfig);
205 argon2d.config = ProviderConfig("argon2d", &defaultConfig);
206 argon2id.config = ProviderConfig("argon2id", &defaultConfig);
210 MODULE_INIT(ModuleArgon2)
212 // This needs to be down here because of warnings from macros.
214 # pragma GCC diagnostic pop