Skip to content

Commit

Permalink
dnsdist: Refactoring of SodiumNonce and friends
Browse files Browse the repository at this point in the history
  • Loading branch information
rgacogne committed Oct 9, 2023
1 parent 95e36fb commit b5db7ee
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 66 deletions.
2 changes: 1 addition & 1 deletion pdns/base64.hh
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,5 @@
#pragma once
#include <string>

template<typename Container> int B64Decode(const std::string& src, Container& dst);
template<typename Container> int B64Decode(const std::string& strInput, Container& strOutput);
std::string Base64Encode (const std::string& src);
8 changes: 4 additions & 4 deletions pdns/dnsdist-console.cc
Original file line number Diff line number Diff line change
Expand Up @@ -236,8 +236,8 @@ void doClient(ComboAddress server, const std::string& command)
SodiumNonce theirs, ours, readingNonce, writingNonce;
ours.init();

writen2(fd.getHandle(), (const char*)ours.value, sizeof(ours.value));
readn2(fd.getHandle(), (char*)theirs.value, sizeof(theirs.value));
writen2(fd.getHandle(), ours.value.data(), ours.value.size());
readn2(fd.getHandle(), theirs.value.data(), theirs.value.size());
readingNonce.merge(ours, theirs);
writingNonce.merge(theirs, ours);

Expand Down Expand Up @@ -868,8 +868,8 @@ static void controlClientThread(ConsoleConnection&& conn)

SodiumNonce theirs, ours, readingNonce, writingNonce;
ours.init();
readn2(conn.getFD(), (char*)theirs.value, sizeof(theirs.value));
writen2(conn.getFD(), (char*)ours.value, sizeof(ours.value));
readn2(conn.getFD(), theirs.value.data(), theirs.value.size());
writen2(conn.getFD(), ours.value.data(), ours.value.size());
readingNonce.merge(ours, theirs);
writingNonce.merge(theirs, ours);

Expand Down
71 changes: 55 additions & 16 deletions pdns/sodcrypto.cc
Original file line number Diff line number Diff line change
Expand Up @@ -20,49 +20,54 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <iostream>
#include <arpa/inet.h>

#include "namespaces.hh"
#include "noinitvector.hh"
#include "misc.hh"
#include "base64.hh"
#include "sodcrypto.hh"


#ifdef HAVE_LIBSODIUM

string newKey()
{
std::string key;
key.resize(crypto_secretbox_KEYBYTES);

randombytes_buf(reinterpret_cast<unsigned char*>(&key.at(0)), key.size());
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
randombytes_buf(reinterpret_cast<unsigned char*>(key.data()), key.size());

return "\""+Base64Encode(key)+"\"";
return "\"" + Base64Encode(key) + "\"";
}

bool sodIsValidKey(const std::string& key)
{
return key.size() == crypto_secretbox_KEYBYTES;
}

std::string sodEncryptSym(const std::string& msg, const std::string& key, SodiumNonce& nonce)
std::string sodEncryptSym(const std::string_view& msg, const std::string& key, SodiumNonce& nonce)
{
if (!sodIsValidKey(key)) {
throw std::runtime_error("Invalid encryption key of size " + std::to_string(key.size()) + ", use setKey() to set a valid key");
}

std::string ciphertext;
ciphertext.resize(msg.length() + crypto_secretbox_MACBYTES);
crypto_secretbox_easy(reinterpret_cast<unsigned char*>(&ciphertext.at(0)),
reinterpret_cast<const unsigned char*>(msg.c_str()),
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
crypto_secretbox_easy(reinterpret_cast<unsigned char*>(ciphertext.data()),
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
reinterpret_cast<const unsigned char*>(msg.data()),
msg.length(),
nonce.value,
reinterpret_cast<const unsigned char*>(key.c_str()));
nonce.value.data(),
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
reinterpret_cast<const unsigned char*>(key.data()));

nonce.increment();
return ciphertext;
}

std::string sodDecryptSym(const std::string& msg, const std::string& key, SodiumNonce& nonce)
std::string sodDecryptSym(const std::string_view& msg, const std::string& key, SodiumNonce& nonce)
{
std::string decrypted;

Expand All @@ -76,18 +81,54 @@ std::string sodDecryptSym(const std::string& msg, const std::string& key, Sodium

decrypted.resize(msg.length() - crypto_secretbox_MACBYTES);

if (crypto_secretbox_open_easy(reinterpret_cast<unsigned char*>(const_cast<char *>(decrypted.data())),
reinterpret_cast<const unsigned char*>(msg.c_str()),
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
if (crypto_secretbox_open_easy(reinterpret_cast<unsigned char*>(decrypted.data()),
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
reinterpret_cast<const unsigned char*>(msg.data()),
msg.length(),
nonce.value,
reinterpret_cast<const unsigned char*>(key.c_str())) != 0) {
nonce.value.data(),
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
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");
}

nonce.increment();
return decrypted;
}

void SodiumNonce::init()
{
randombytes_buf(value.data(), value.size());
}

void SodiumNonce::merge(const SodiumNonce& lower, const SodiumNonce& 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()
{
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
auto* ptr = reinterpret_cast<uint32_t*>(value.data());
uint32_t count = htonl(*ptr);
*ptr = ntohl(++count);
}

#else
void SodiumNonce::init()
{
}

void SodiumNonce::merge(const SodiumNonce& lower, const SodiumNonce& higher)
{
}

void SodiumNonce::increment()
{
}

std::string sodEncryptSym(const std::string& msg, const std::string& key, SodiumNonce& nonce)
{
return msg;
Expand All @@ -109,9 +150,7 @@ bool sodIsValidKey(const std::string& key)

#endif


#include "base64.hh"
#include <inttypes.h>
#include <cinttypes>

namespace anonpdns {
static char B64Decode1(char cInChar)
Expand Down
69 changes: 24 additions & 45 deletions pdns/sodcrypto.hh
Original file line number Diff line number Diff line change
Expand Up @@ -21,58 +21,37 @@
*/
#pragma once
#include "config.h"
#include <array>
#include <string>
#include <stdint.h>
#include <cstdint>
#include <cstring>

#include <arpa/inet.h>

#ifndef HAVE_LIBSODIUM
struct SodiumNonce
{
void init(){};
void merge(const SodiumNonce& lower, const SodiumNonce& higher) {};
void increment(){};
unsigned char value[1]{0};
};
#else
#if defined(HAVE_LIBSODIUM)
#include <sodium.h>
#endif

struct SodiumNonce
{
SodiumNonce()
{
memset(&value, 0, sizeof(value));
}

void init()
{
randombytes_buf(value, sizeof value);
}

void merge(const SodiumNonce& lower, const SodiumNonce& higher)
{
static const size_t halfSize = (sizeof value) / 2;
memcpy(value, lower.value, halfSize);
memcpy(value + halfSize, higher.value + halfSize, halfSize);
}

void increment()
{
uint32_t* p = (uint32_t*)value;
uint32_t count=htonl(*p);
*p=ntohl(++count);
}

string toString() const
{
return string((const char*)value, crypto_secretbox_NONCEBYTES);
}

unsigned char value[crypto_secretbox_NONCEBYTES];
};
SodiumNonce() = default;
SodiumNonce(const SodiumNonce&) = default;
SodiumNonce(SodiumNonce&&) = default;
SodiumNonce& operator=(const SodiumNonce&) = default;
SodiumNonce& operator=(SodiumNonce&&) = default;
~SodiumNonce() = default;

void init();
void merge(const SodiumNonce& lower, const SodiumNonce& higher);
void increment();

#if !defined(HAVE_LIBSODIUM)
std::array<unsigned char, 1> value{};
#else
std::array<unsigned char, crypto_secretbox_NONCEBYTES> value{};
#endif
};

std::string newKeypair();
std::string sodEncryptSym(const std::string& msg, const std::string& key, SodiumNonce&);
std::string sodDecryptSym(const std::string& msg, const std::string& key, SodiumNonce&);
std::string sodEncryptSym(const std::string_view& msg, const std::string& key, SodiumNonce&);
std::string sodDecryptSym(const std::string_view& msg, const std::string& key, SodiumNonce&);
std::string newKey();
bool sodIsValidKey(const std::string& key);

0 comments on commit b5db7ee

Please sign in to comment.