sockowner
socktype
sodbc
-sodcrypto
sodiumsigners
sokolov
somedata
./pdns/sillyrecords.cc
./pdns/snmp-agent.cc
./pdns/snmp-agent.hh
-./pdns/sodcrypto.cc
-./pdns/sodcrypto.hh
./pdns/sortlist.cc
./pdns/sortlist.hh
./pdns/speedtest.cc
#include "dolog.hh"
#include "dnsdist.hh"
#include "dnsdist-console.hh"
-#include "sodcrypto.hh"
+#include "dnsdist-crypto.hh"
#include "threadname.hh"
GlobalStateHolder<NetmaskGroup> g_consoleACL;
}
}
-static ConsoleCommandResult sendMessageToServer(int fd, const std::string& line, SodiumNonce& readingNonce, SodiumNonce& writingNonce, const bool outputEmptyLine)
+static ConsoleCommandResult sendMessageToServer(int fd, const std::string& line, dnsdist::crypto::authenticated::Nonce& readingNonce, dnsdist::crypto::authenticated::Nonce& writingNonce, const bool outputEmptyLine)
{
- string msg = sodEncryptSym(line, g_consoleKey, writingNonce);
+ string msg = dnsdist::crypto::authenticated::encryptSym(line, g_consoleKey, writingNonce);
const auto msgLen = msg.length();
if (msgLen > std::numeric_limits<uint32_t>::max()) {
cerr << "Encrypted message is too long to be sent to the server, "<< std::to_string(msgLen) << " > " << std::numeric_limits<uint32_t>::max() << endl;
msg.clear();
msg.resize(len);
readn2(fd, msg.data(), len);
- msg = sodDecryptSym(msg, g_consoleKey, readingNonce);
+ msg = dnsdist::crypto::authenticated::decryptSym(msg, g_consoleKey, readingNonce);
cout << msg;
cout.flush();
void doClient(ComboAddress server, const std::string& command)
{
- if (!sodIsValidKey(g_consoleKey)) {
+ if (!dnsdist::crypto::authenticated::isValidKey(g_consoleKey)) {
cerr << "The currently configured console key is not valid, please configure a valid key using the setKey() directive" << endl;
return;
}
}
SConnect(fd.getHandle(), server);
setTCPNoDelay(fd.getHandle());
- SodiumNonce theirs, ours, readingNonce, writingNonce;
+ dnsdist::crypto::authenticated::Nonce theirs, ours, readingNonce, writingNonce;
ours.init();
writen2(fd.getHandle(), ours.value.data(), ours.value.size());
setTCPNoDelay(conn.getFD());
- SodiumNonce theirs, ours, readingNonce, writingNonce;
+ dnsdist::crypto::authenticated::Nonce theirs, ours, readingNonce, writingNonce;
ours.init();
readn2(conn.getFD(), theirs.value.data(), theirs.value.size());
writen2(conn.getFD(), ours.value.data(), ours.value.size());
line.resize(len);
readn2(conn.getFD(), line.data(), len);
- line = sodDecryptSym(line, g_consoleKey, readingNonce);
+ line = dnsdist::crypto::authenticated::decryptSym(line, g_consoleKey, readingNonce);
string response;
try {
catch (const LuaContext::SyntaxErrorException& e) {
response = "Error: " + string(e.what()) + ": ";
}
- response = sodEncryptSym(response, g_consoleKey, writingNonce);
+ response = dnsdist::crypto::authenticated::encryptSym(response, g_consoleKey, writingNonce);
putMsgLen32(conn.getFD(), response.length());
writen2(conn.getFD(), response.c_str(), response.length());
}
while ((sock = SAccept(acceptFD.getHandle(), client)) >= 0) {
FDWrapper socket(sock);
- if (!sodIsValidKey(g_consoleKey)) {
+ if (!dnsdist::crypto::authenticated::isValidKey(g_consoleKey)) {
vinfolog("Control connection from %s dropped because we don't have a valid key configured, please configure one using setKey()", client.toStringWithPort());
continue;
}
#include "dnsdist-carbon.hh"
#include "dnsdist-concurrent-connections.hh"
#include "dnsdist-console.hh"
+#include "dnsdist-crypto.hh"
#include "dnsdist-dynblocks.hh"
#include "dnsdist-discovery.hh"
#include "dnsdist-ecs.hh"
#include "doh.hh"
#include "doq-common.hh"
#include "dolog.hh"
-#include "sodcrypto.hh"
#include "threadname.hh"
#ifdef HAVE_LIBSSL
}
g_consoleEnabled = true;
-#ifdef HAVE_LIBSODIUM
+#if defined(HAVE_LIBSODIUM) || defined(HAVE_LIBCRYPTO)
if (g_configurationDone && g_consoleKey.empty()) {
warnlog("Warning, the console has been enabled via 'controlSocket()' but no key has been set with 'setKey()' so all connections will fail until a key has been set");
}
luaCtx.writeFunction("addConsoleACL", [](const std::string& netmask) {
setLuaSideEffect();
-#ifndef HAVE_LIBSODIUM
- warnlog("Allowing remote access to the console while libsodium support has not been enabled is not secure, and will result in cleartext communications");
+#if !defined(HAVE_LIBSODIUM) && !defined(HAVE_LIBCRYPTO)
+ warnlog("Allowing remote access to the console while neither libsodium not libcrypto support has been enabled is not secure, and will result in cleartext communications");
#endif
g_consoleACL.modify([netmask](NetmaskGroup& nmg) { nmg.addMask(netmask); });
luaCtx.writeFunction("setConsoleACL", [](LuaTypeOrArrayOf<std::string> inp) {
setLuaSideEffect();
-#ifndef HAVE_LIBSODIUM
- warnlog("Allowing remote access to the console while libsodium support has not been enabled is not secure, and will result in cleartext communications");
+#if !defined(HAVE_LIBSODIUM) && !defined(HAVE_LIBCRYPTO)
+ warnlog("Allowing remote access to the console while neither libsodium nor libcrypto support has not been enabled is not secure, and will result in cleartext communications");
#endif
NetmaskGroup nmg;
luaCtx.writeFunction("showConsoleACL", []() {
setLuaNoSideEffect();
-#ifndef HAVE_LIBSODIUM
- warnlog("Allowing remote access to the console while libsodium support has not been enabled is not secure, and will result in cleartext communications");
+#if !defined(HAVE_LIBSODIUM) && !defined(HAVE_LIBCRYPTO)
+ warnlog("Allowing remote access to the console while neither libsodium nor libcrypto support has not been enabled is not secure, and will result in cleartext communications");
#endif
auto aclEntries = g_consoleACL.getLocal()->toStringVector();
luaCtx.writeFunction("makeKey", []() {
setLuaNoSideEffect();
- g_outputBuffer = "setKey(" + newKey() + ")\n";
+ g_outputBuffer = "setKey(" + dnsdist::crypto::authenticated::newKey() + ")\n";
});
luaCtx.writeFunction("setKey", [](const std::string& key) {
if (!g_configurationDone && !g_consoleKey.empty()) { // this makes sure the commandline -k key prevails over dnsdist.conf
return; // but later setKeys() trump the -k value again
}
-#ifndef HAVE_LIBSODIUM
- warnlog("Calling setKey() while libsodium support has not been enabled is not secure, and will result in cleartext communications");
+#if !defined(HAVE_LIBSODIUM) && !defined(HAVE_LIBCRYPTO)
+ warnlog("Calling setKey() while neither libsodium nor libcrypto support has been enabled is not secure, and will result in cleartext communications");
#endif
setLuaSideEffect();
luaCtx.writeFunction("testCrypto", [](boost::optional<string> optTestMsg) {
setLuaNoSideEffect();
-#ifdef HAVE_LIBSODIUM
+#if defined(HAVE_LIBSODIUM) || defined(HAVE_LIBCRYPTO)
try {
string testmsg;
testmsg = "testStringForCryptoTests";
}
- SodiumNonce sn, sn2;
+ dnsdist::crypto::authenticated::Nonce sn, sn2;
sn.init();
sn2 = sn;
- string encrypted = sodEncryptSym(testmsg, g_consoleKey, sn);
- string decrypted = sodDecryptSym(encrypted, g_consoleKey, sn2);
+ string encrypted = dnsdist::crypto::authenticated::encryptSym(testmsg, g_consoleKey, sn);
+ string decrypted = dnsdist::crypto::authenticated::decryptSym(encrypted, g_consoleKey, sn2);
sn.increment();
sn2.increment();
- encrypted = sodEncryptSym(testmsg, g_consoleKey, sn);
- decrypted = sodDecryptSym(encrypted, g_consoleKey, sn2);
+ encrypted = dnsdist::crypto::authenticated::encryptSym(testmsg, g_consoleKey, sn);
+ decrypted = dnsdist::crypto::authenticated::decryptSym(encrypted, g_consoleKey, sn2);
if (testmsg == decrypted)
g_outputBuffer = "Everything is ok!\n";
#include "dnsdist-cache.hh"
#include "dnsdist-carbon.hh"
#include "dnsdist-console.hh"
+#include "dnsdist-crypto.hh"
#include "dnsdist-discovery.hh"
#include "dnsdist-dnsparser.hh"
#include "dnsdist-dynblocks.hh"
#include "gettime.hh"
#include "lock.hh"
#include "misc.hh"
-#include "sodcrypto.hh"
#include "sstuff.hh"
#include "threadname.hh"
cout<<"-c,--client Operate as a client, connect to dnsdist. This reads\n";
cout<<" controlSocket from your configuration file, but also\n";
cout<<" accepts an IP:PORT argument\n";
-#ifdef HAVE_LIBSODIUM
+#if defined(HAVE_LIBSODIUM) || defined(HAVE_LIBCRYPTO)
cout<<"-k,--setkey KEY Use KEY for encrypted communication to dnsdist. This\n";
cout<<" is similar to setting setKey in the configuration file.\n";
cout<<" NOTE: this will leak this key in your shell's history\n";
g_ACL.modify([optstring](NetmaskGroup& nmg) { nmg.addMask(optstring); });
break;
case 'k':
-#ifdef HAVE_LIBSODIUM
+#if defined HAVE_LIBSODIUM || defined(HAVE_LIBCRYPTO)
if (B64Decode(string(optarg), g_consoleKey) < 0) {
cerr<<"Unable to decode key '"<<optarg<<"'."<<endl;
// NOLINTNEXTLINE(concurrency-mt-unsafe): only one thread at this point
exit(EXIT_FAILURE);
}
#else
- cerr<<"dnsdist has been built without libsodium, -k/--setkey is unsupported."<<endl;
+ cerr<<"dnsdist has been built without libsodium or libcrypto, -k/--setkey is unsupported."<<endl;
// NOLINTNEXTLINE(concurrency-mt-unsafe): only one thread at this point
exit(EXIT_FAILURE);
#endif
infolog("Console ACL allowing connections from: %s", acls.c_str());
}
-#ifdef HAVE_LIBSODIUM
+#if defined(HAVE_LIBSODIUM) || defined(HAVE_LIBCRYPTO)
if (g_consoleEnabled && g_consoleKey.empty()) {
warnlog("Warning, the console has been enabled via 'controlSocket()' but no key has been set with 'setKey()' so all connections will fail until a key has been set");
}
dnsdist-carbon.cc dnsdist-carbon.hh \
dnsdist-concurrent-connections.hh \
dnsdist-console.cc dnsdist-console.hh \
+ dnsdist-crypto.cc dnsdist-crypto.hh \
dnsdist-discovery.cc dnsdist-discovery.hh \
dnsdist-dnscrypt.cc \
dnsdist-dnsparser.cc dnsdist-dnsparser.hh \
remote_logger.cc remote_logger.hh \
sholder.hh \
snmp-agent.cc snmp-agent.hh \
- sodcrypto.cc sodcrypto.hh \
sstuff.hh \
stat_t.hh \
statnode.cc statnode.hh \
dnsdist-backoff.hh \
dnsdist-cache.cc dnsdist-cache.hh \
dnsdist-concurrent-connections.hh \
+ dnsdist-crypto.cc dnsdist-crypto.hh \
dnsdist-dnsparser.cc dnsdist-dnsparser.hh \
dnsdist-doh-common.cc dnsdist-doh-common.hh \
dnsdist-downstream-connection.hh \
proxy-protocol.cc proxy-protocol.hh \
qtype.cc qtype.hh \
sholder.hh \
- sodcrypto.cc \
sstuff.hh \
stat_t.hh \
statnode.cc statnode.hh \
#include <iostream>
#include <arpa/inet.h>
+#include "dnsdist-crypto.hh"
+
#include "namespaces.hh"
#include "noinitvector.hh"
#include "misc.hh"
#include "base64.hh"
-#include "sodcrypto.hh"
+namespace dnsdist::crypto::authenticated
+{
#ifdef HAVE_LIBSODIUM
-
string newKey(bool base64Encoded)
{
std::string key;
return "\"" + Base64Encode(key) + "\"";
}
-bool sodIsValidKey(const std::string& key)
+bool isValidKey(const std::string& key)
{
return key.size() == crypto_secretbox_KEYBYTES;
}
-std::string sodEncryptSym(const std::string_view& msg, const std::string& key, SodiumNonce& nonce, bool incrementNonce)
+std::string encryptSym(const std::string_view& msg, const std::string& key, Nonce& nonce, bool incrementNonce)
{
- if (!sodIsValidKey(key)) {
+ if (!isValidKey(key)) {
throw std::runtime_error("Invalid encryption key of size " + std::to_string(key.size()) + " (" + std::to_string(crypto_secretbox_KEYBYTES) + " expected), use setKey() to set a valid key");
}
return ciphertext;
}
-std::string sodDecryptSym(const std::string_view& msg, const std::string& key, SodiumNonce& nonce, bool incrementNonce)
+std::string decryptSym(const std::string_view& msg, const std::string& key, Nonce& nonce, bool incrementNonce)
{
std::string decrypted;
throw std::runtime_error("Could not decrypt message of size " + std::to_string(msg.length()));
}
- if (!sodIsValidKey(key)) {
+ if (!isValidKey(key)) {
throw std::runtime_error("Invalid decryption key of size " + std::to_string(key.size()) + ", use setKey() to set a valid key");
}
msg.length(),
nonce.value.data(),
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
- reinterpret_cast<const unsigned char*>(key.data())) != 0) {
+ reinterpret_cast<const unsigned char*>(key.data()))
+ != 0) {
throw std::runtime_error("Could not decrypt message, please check that the key configured with setKey() is correct");
}
return decrypted;
}
-void SodiumNonce::init()
+void Nonce::init()
{
randombytes_buf(value.data(), value.size());
}
-void SodiumNonce::merge(const SodiumNonce& lower, const SodiumNonce& higher)
+#elif defined(HAVE_LIBCRYPTO)
+#include <openssl/evp.h>
+#include <openssl/rand.h>
+
+static constexpr size_t s_CHACHA20_POLY1305_KEY_SIZE = 32U;
+static constexpr size_t s_POLY1305_BLOCK_SIZE = 16U;
+
+string newKey(bool base64Encoded)
+{
+ std::string key;
+ key.resize(s_CHACHA20_POLY1305_KEY_SIZE);
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
+ if (RAND_priv_bytes(reinterpret_cast<unsigned char*>(key.data()), key.size()) != 1) {
+ throw std::runtime_error("Could not initialize random number generator for cryptographic functions");
+ }
+ if (!base64Encoded) {
+ return key;
+ }
+ return "\"" + Base64Encode(key) + "\"";
+}
+
+bool isValidKey(const std::string& key)
+{
+ return key.size() == s_CHACHA20_POLY1305_KEY_SIZE;
+}
+
+std::string encryptSym(const std::string_view& msg, const std::string& key, Nonce& nonce, bool incrementNonce)
+{
+ if (!isValidKey(key)) {
+ throw std::runtime_error("Invalid encryption key of size " + std::to_string(key.size()) + " (" + std::to_string(s_CHACHA20_POLY1305_KEY_SIZE) + " expected), use setKey() to set a valid key");
+ }
+
+ // Each thread gets its own cipher context
+ static thread_local auto ctx = std::unique_ptr<EVP_CIPHER_CTX, decltype(&EVP_CIPHER_CTX_free)>(nullptr, EVP_CIPHER_CTX_free);
+
+ if (!ctx) {
+ ctx = std::unique_ptr<EVP_CIPHER_CTX, decltype(&EVP_CIPHER_CTX_free)>(EVP_CIPHER_CTX_new(), EVP_CIPHER_CTX_free);
+ if (!ctx) {
+ throw std::runtime_error("encryptSym: EVP_CIPHER_CTX_new() could not initialize cipher context");
+ }
+
+ if (EVP_EncryptInit_ex(ctx.get(), EVP_chacha20_poly1305(), nullptr, nullptr, nullptr) != 1) {
+ throw std::runtime_error("encryptSym: EVP_EncryptInit_ex() could not initialize encryption operation");
+ }
+ }
+
+ std::string ciphertext;
+ /* plus one so we can access the last byte in EncryptFinal which does nothing for this algo */
+ ciphertext.resize(s_POLY1305_BLOCK_SIZE + msg.length() + 1);
+ int outLength{0};
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
+ if (EVP_EncryptInit_ex(ctx.get(), nullptr, nullptr, reinterpret_cast<const unsigned char*>(key.c_str()), nonce.value.data()) != 1) {
+ throw std::runtime_error("encryptSym: EVP_EncryptInit_ex() could not initialize encryption key and IV");
+ }
+
+ if (!msg.empty()) {
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
+ if (EVP_EncryptUpdate(ctx.get(),
+ reinterpret_cast<unsigned char*>(&ciphertext.at(s_POLY1305_BLOCK_SIZE)), &outLength,
+ reinterpret_cast<const unsigned char*>(msg.data()), msg.length())
+ != 1) {
+ throw std::runtime_error("encryptSym: EVP_EncryptUpdate() could not encrypt message");
+ }
+ }
+
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
+ if (EVP_EncryptFinal_ex(ctx.get(), reinterpret_cast<unsigned char*>(&ciphertext.at(s_POLY1305_BLOCK_SIZE + outLength)), &outLength) != 1) {
+ throw std::runtime_error("encryptSym: EVP_EncryptFinal_ex() could finalize message encryption");
+ ;
+ }
+
+ /* Get the tag */
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
+ if (EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_AEAD_GET_TAG, s_POLY1305_BLOCK_SIZE, ciphertext.data()) != 1) {
+ throw std::runtime_error("encryptSym: EVP_CIPHER_CTX_ctrl() could not get tag");
+ }
+
+ if (incrementNonce) {
+ nonce.increment();
+ }
+
+ ciphertext.resize(ciphertext.size() - 1);
+ return ciphertext;
+}
+
+std::string decryptSym(const std::string_view& msg, const std::string& key, Nonce& nonce, bool incrementNonce)
+{
+ if (msg.length() < s_POLY1305_BLOCK_SIZE) {
+ throw std::runtime_error("Could not decrypt message of size " + std::to_string(msg.length()));
+ }
+
+ if (!isValidKey(key)) {
+ throw std::runtime_error("Invalid decryption key of size " + std::to_string(key.size()) + ", use setKey() to set a valid key");
+ }
+
+ if (msg.length() == s_POLY1305_BLOCK_SIZE) {
+ if (incrementNonce) {
+ nonce.increment();
+ }
+ return std::string();
+ }
+
+ // Each thread gets its own cipher context
+ static thread_local auto ctx = std::unique_ptr<EVP_CIPHER_CTX, decltype(&EVP_CIPHER_CTX_free)>(nullptr, EVP_CIPHER_CTX_free);
+ if (!ctx) {
+ ctx = std::unique_ptr<EVP_CIPHER_CTX, decltype(&EVP_CIPHER_CTX_free)>(EVP_CIPHER_CTX_new(), EVP_CIPHER_CTX_free);
+ if (!ctx) {
+ throw std::runtime_error("decryptSym: EVP_CIPHER_CTX_new() could not initialize cipher context");
+ }
+
+ if (EVP_DecryptInit_ex(ctx.get(), EVP_chacha20_poly1305(), nullptr, nullptr, nullptr) != 1) {
+ throw std::runtime_error("decryptSym: EVP_DecryptInit_ex() could not initialize decryption operation");
+ }
+ }
+
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
+ if (EVP_DecryptInit_ex(ctx.get(), nullptr, nullptr, reinterpret_cast<const unsigned char*>(key.c_str()), nonce.value.data()) != 1) {
+ throw std::runtime_error("decryptSym: EVP_DecryptInit_ex() could not initialize decryption key and IV");
+ }
+
+ const auto tag = msg.substr(0, s_POLY1305_BLOCK_SIZE);
+ std::string decrypted;
+ /* plus one so we can access the last byte in DecryptFinal, which does nothing */
+ decrypted.resize(msg.length() - s_POLY1305_BLOCK_SIZE + 1);
+ int outLength{0};
+ if (msg.size() > s_POLY1305_BLOCK_SIZE) {
+ if (!EVP_DecryptUpdate(ctx.get(),
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
+ reinterpret_cast<unsigned char*>(decrypted.data()), &outLength,
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
+ reinterpret_cast<const unsigned char*>(&msg.at(s_POLY1305_BLOCK_SIZE)), msg.size() - s_POLY1305_BLOCK_SIZE)) {
+ throw std::runtime_error("Could not decrypt message (update failed), please check that the key configured with setKey() is correct");
+ }
+ }
+
+ /* Set expected tag value. Works in OpenSSL 1.0.1d and later */
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast): sorry, OpenSSL's API is terrible
+ if (!EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_AEAD_SET_TAG, s_POLY1305_BLOCK_SIZE, const_cast<char*>(tag.data()))) {
+ throw std::runtime_error("Could not decrypt message (invalid tag), please check that the key configured with setKey() is correct");
+ }
+
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
+ if (!EVP_DecryptFinal_ex(ctx.get(), reinterpret_cast<unsigned char*>(&decrypted.at(outLength)), &outLength)) {
+ throw std::runtime_error("Could not decrypt message (final failed), please check that the key configured with setKey() is correct");
+ }
+
+ if (incrementNonce) {
+ nonce.increment();
+ }
+
+ decrypted.resize(decrypted.size() - 1);
+ return decrypted;
+}
+
+void Nonce::init()
+{
+ if (RAND_priv_bytes(value.data(), value.size()) != 1) {
+ throw std::runtime_error("Could not initialize random number generator for cryptographic functions");
+ }
+}
+#endif
+
+#if defined(HAVE_LIBSODIUM) || defined(HAVE_LIBCRYPTO)
+void Nonce::merge(const Nonce& lower, const Nonce& higher)
{
constexpr size_t halfSize = std::tuple_size<decltype(value)>{} / 2;
memcpy(value.data(), lower.value.data(), halfSize);
memcpy(value.data() + halfSize, higher.value.data() + halfSize, halfSize);
}
-void SodiumNonce::increment()
+void Nonce::increment()
{
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
auto* ptr = reinterpret_cast<uint32_t*>(value.data());
}
#else
-void SodiumNonce::init()
+void Nonce::init()
{
}
-void SodiumNonce::merge(const SodiumNonce& lower, const SodiumNonce& higher)
+void Nonce::merge(const Nonce& lower, const Nonce& higher)
{
}
-void SodiumNonce::increment()
+void Nonce::increment()
{
}
-std::string sodEncryptSym(const std::string_view& msg, const std::string& key, SodiumNonce& nonce, bool incrementNonce)
+std::string encryptSym(const std::string_view& msg, const std::string& key, Nonce& nonce, bool incrementNonce)
{
return std::string(msg);
}
-std::string sodDecryptSym(const std::string_view& msg, const std::string& key, SodiumNonce& nonce, bool incrementNonce)
+std::string decryptSym(const std::string_view& msg, const std::string& key, Nonce& nonce, bool incrementNonce)
{
return std::string(msg);
}
return "\"plaintext\"";
}
-bool sodIsValidKey(const std::string& key)
+bool isValidKey(const std::string& key)
{
return true;
}
#endif
+}
#include <cinttypes>
#include <sodium.h>
#endif
-struct SodiumNonce
+namespace dnsdist::crypto::authenticated
+{
+struct Nonce
{
- SodiumNonce() = default;
- SodiumNonce(const SodiumNonce&) = default;
- SodiumNonce(SodiumNonce&&) = default;
- SodiumNonce& operator=(const SodiumNonce&) = default;
- SodiumNonce& operator=(SodiumNonce&&) = default;
- ~SodiumNonce() = default;
+ Nonce() = default;
+ Nonce(const Nonce&) = default;
+ Nonce(Nonce&&) = default;
+ Nonce& operator=(const Nonce&) = default;
+ Nonce& operator=(Nonce&&) = default;
+ ~Nonce() = default;
void init();
- void merge(const SodiumNonce& lower, const SodiumNonce& higher);
+ void merge(const Nonce& lower, const Nonce& higher);
void increment();
-#if !defined(HAVE_LIBSODIUM)
- std::array<unsigned char, 1> value{};
-#else
+#if defined(HAVE_LIBSODIUM)
std::array<unsigned char, crypto_secretbox_NONCEBYTES> value{};
+#elif defined(HAVE_LIBCRYPTO)
+ // IV is 96 bits
+ std::array<unsigned char, 12> value{};
+#else
+ std::array<unsigned char, 1> value{};
#endif
};
-std::string sodEncryptSym(const std::string_view& msg, const std::string& key, SodiumNonce& nonce, bool incrementNonce = true);
-std::string sodDecryptSym(const std::string_view& msg, const std::string& key, SodiumNonce& nonce, bool incrementNonce = true);
+std::string encryptSym(const std::string_view& msg, const std::string& key, Nonce& nonce, bool incrementNonce = true);
+std::string decryptSym(const std::string_view& msg, const std::string& key, Nonce& nonce, bool incrementNonce = true);
std::string newKey(bool base64Encoded = true);
-bool sodIsValidKey(const std::string& key);
+bool isValidKey(const std::string& key);
-namespace dnsdist::crypto::authenticated
-{
constexpr size_t getEncryptedSize(size_t plainTextSize)
{
#if defined(HAVE_LIBSODIUM)
return plainTextSize + crypto_secretbox_MACBYTES;
+#elif defined(HAVE_LIBCRYPTO)
+ return plainTextSize + 16;
#else
return plainTextSize;
#endif
controlSocket('192.0.2.53:5199')
-Enabling the console without encryption enabled is not recommended. Note that encryption requires building dnsdist with libsodium support enabled.
+Enabling the console without encryption enabled is not recommended. Note that encryption requires building dnsdist with either libsodium or libcrypto support enabled.
-Once you have a libsodium-enabled dnsdist, the first step to enable encryption is to generate a key with :func:`makeKey`::
+Once you have a console-enabled dnsdist, the first step to enable encryption is to generate a key with :func:`makeKey`::
$ ./dnsdist -l 127.0.0.1:5300
[..]
that is used on the server (set with **setKey()**). Note that this
will leak the key into your shell's history and into the systems
running process list. Only available when dnsdist is compiled with
- libsodium support.
+ libsodium or libcrypto support.
-e, --execute <command> Connect to dnsdist and execute *command*.
-h, --help Display a helpful message and exit.
-l, --local <address> Bind to *address*, Supply as many addresses (using multiple
#include "dolog.hh"
#include "iputils.hh"
#include "misc.hh"
-#include "sodcrypto.hh"
#include "sstuff.hh"
#include "threadname.hh"
#include "base64.hh"
namespace dnsdist::doq
{
-static const std::string s_quicRetryTokenKey = newKey(false);
+static const std::string s_quicRetryTokenKey = dnsdist::crypto::authenticated::newKey(false);
PacketBuffer mintToken(const PacketBuffer& dcid, const ComboAddress& peer)
{
try {
- SodiumNonce nonce;
+ dnsdist::crypto::authenticated::Nonce nonce;
nonce.init();
const auto addrBytes = peer.toByteString();
plainTextToken.insert(plainTextToken.end(), addrBytes.begin(), addrBytes.end());
plainTextToken.insert(plainTextToken.end(), dcid.begin(), dcid.end());
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
- const auto encryptedToken = sodEncryptSym(std::string_view(reinterpret_cast<const char*>(plainTextToken.data()), plainTextToken.size()), s_quicRetryTokenKey, nonce, false);
+ const auto encryptedToken = dnsdist::crypto::authenticated::encryptSym(std::string_view(reinterpret_cast<const char*>(plainTextToken.data()), plainTextToken.size()), s_quicRetryTokenKey, nonce, false);
// a bit sad, let's see if we can do better later
auto encryptedTokenPacket = PacketBuffer(encryptedToken.begin(), encryptedToken.end());
encryptedTokenPacket.insert(encryptedTokenPacket.begin(), nonce.value.begin(), nonce.value.end());
std::optional<PacketBuffer> validateToken(const PacketBuffer& token, const ComboAddress& peer)
{
try {
- SodiumNonce nonce;
+ dnsdist::crypto::authenticated::Nonce nonce;
auto addrBytes = peer.toByteString();
const uint64_t now = time(nullptr);
const auto minimumSize = nonce.value.size() + sizeof(now) + addrBytes.size();
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
auto cipher = std::string_view(reinterpret_cast<const char*>(&token.at(nonce.value.size())), token.size() - nonce.value.size());
- auto plainText = sodDecryptSym(cipher, s_quicRetryTokenKey, nonce, false);
+ auto plainText = dnsdist::crypto::authenticated::decryptSym(cipher, s_quicRetryTokenKey, nonce, false);
if (plainText.size() <= sizeof(now) + addrBytes.size()) {
return std::nullopt;
#include "dolog.hh"
#include "noinitvector.hh"
-#include "sodcrypto.hh"
#include "sstuff.hh"
#include "libssl.hh"
+#include "dnsdist-crypto.hh"
namespace dnsdist::doq
{
DOQ_UNSPECIFIED_ERROR = 5
};
-static constexpr size_t MAX_TOKEN_LEN = dnsdist::crypto::authenticated::getEncryptedSize(std::tuple_size<decltype(SodiumNonce::value)>{} /* nonce */ + sizeof(uint64_t) /* TTD */ + 16 /* IPv6 */ + QUICHE_MAX_CONN_ID_LEN);
+static constexpr size_t MAX_TOKEN_LEN = dnsdist::crypto::authenticated::getEncryptedSize(std::tuple_size<decltype(dnsdist::crypto::authenticated::Nonce::value)>{} /* nonce */ + sizeof(uint64_t) /* TTD */ + 16 /* IPv6 */ + QUICHE_MAX_CONN_ID_LEN);
static constexpr size_t MAX_DATAGRAM_SIZE = 1200;
static constexpr size_t LOCAL_CONN_ID_LEN = 16;
static constexpr std::array<uint8_t, 4> DOQ_ALPN{'\x03', 'd', 'o', 'q'};
#include "dolog.hh"
#include "iputils.hh"
#include "misc.hh"
-#include "sodcrypto.hh"
#include "sstuff.hh"
#include "threadname.hh"