--- /dev/null
+Copyright (c) 2015-2018, Frank Denis <j at pureftpd dot org>
+
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
--- /dev/null
+
+#include "ipcrypt.h"
+
+#define ROTL(X, R) (X) = (unsigned char) ((X) << (R)) | ((X) >> (8 - (R)))
+
+static void
+arx_fwd(unsigned char state[4])
+{
+ state[0] += state[1];
+ state[2] += state[3];
+ ROTL(state[1], 2);
+ ROTL(state[3], 5);
+ state[1] ^= state[0];
+ state[3] ^= state[2];
+ ROTL(state[0], 4);
+ state[0] += state[3];
+ state[2] += state[1];
+ ROTL(state[1], 3);
+ ROTL(state[3], 7);
+ state[1] ^= state[2];
+ state[3] ^= state[0];
+ ROTL(state[2], 4);
+}
+
+static void
+arx_bwd(unsigned char state[4])
+{
+ ROTL(state[2], 4);
+ state[1] ^= state[2];
+ state[3] ^= state[0];
+ ROTL(state[1], 5);
+ ROTL(state[3], 1);
+ state[0] -= state[3];
+ state[2] -= state[1];
+ ROTL(state[0], 4);
+ state[1] ^= state[0];
+ state[3] ^= state[2];
+ ROTL(state[1], 6);
+ ROTL(state[3], 3);
+ state[0] -= state[1];
+ state[2] -= state[3];
+}
+
+static inline void
+xor4(unsigned char *out, const unsigned char *x, const unsigned char *y)
+{
+ out[0] = x[0] ^ y[0];
+ out[1] = x[1] ^ y[1];
+ out[2] = x[2] ^ y[2];
+ out[3] = x[3] ^ y[3];
+}
+
+int
+ipcrypt_encrypt(unsigned char out[IPCRYPT_BYTES],
+ const unsigned char in[IPCRYPT_BYTES],
+ const unsigned char key[IPCRYPT_KEYBYTES])
+{
+ unsigned char state[4];
+
+ xor4(state, in, key);
+ arx_fwd(state);
+ xor4(state, state, key + 4);
+ arx_fwd(state);
+ xor4(state, state, key + 8);
+ arx_fwd(state);
+ xor4(out, state, key + 12);
+
+ return 0;
+}
+
+int
+ipcrypt_decrypt(unsigned char out[IPCRYPT_BYTES],
+ const unsigned char in[IPCRYPT_BYTES],
+ const unsigned char key[IPCRYPT_KEYBYTES])
+{
+ unsigned char state[4];
+
+ xor4(state, in, key + 12);
+ arx_bwd(state);
+ xor4(state, state, key + 8);
+ arx_bwd(state);
+ xor4(state, state, key + 4);
+ arx_bwd(state);
+ xor4(out, state, key);
+
+ return 0;
+}
--- /dev/null
+
+#ifndef ipcrypt_H
+#define ipcrypt_H
+
+#define IPCRYPT_BYTES 4
+#define IPCRYPT_KEYBYTES 16
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int ipcrypt_encrypt(unsigned char out[IPCRYPT_BYTES],
+ const unsigned char in[IPCRYPT_BYTES],
+ const unsigned char key[IPCRYPT_KEYBYTES]);
+
+int ipcrypt_decrypt(unsigned char out[IPCRYPT_BYTES],
+ const unsigned char in[IPCRYPT_BYTES],
+ const unsigned char key[IPCRYPT_KEYBYTES]);
+
+#ifdef __cplusplus
+} /* End of the 'extern "C"' block */
+#endif
+
+#endif
ednssubnet.cc \
gettime.cc gettime.hh \
gss_context.cc gss_context.hh \
+ ipcrypt.cc ipcrypt.hh ../ext/ipcrypt/ipcrypt.c ../ext/ipcrypt.h \
iputils.cc \
ixfr.cc ixfr.hh \
logger.cc \
test-dnsparser_cc.cc \
test-dnsparser_hh.cc \
test-dnsrecords_cc.cc \
+ test-ipcrypt_cc.cc \
test-iputils_hh.cc \
test-ixfr_cc.cc \
test-lock_hh.cc \
#include "dolog.hh"
#include "fstrm_logger.hh"
#include "remote_logger.hh"
+#include "ipcrypt.hh"
void setupLuaBindings(bool client)
{
g_lua.registerFunction<ComboAddress(ComboAddress::*)()>("mapToIPv4", [](const ComboAddress& ca) { return ca.mapToIPv4(); });
g_lua.registerFunction<bool(nmts_t::*)(const ComboAddress&)>("match", [](nmts_t& s, const ComboAddress& ca) { return s.match(ca); });
+ g_lua.registerFunction<ComboAddress(ComboAddress::*)(const std::string& key)>("ipencrypt", [](const ComboAddress& ca, const std::string& key) {
+ return encryptCA(ca, key);
+ });
+ g_lua.registerFunction<ComboAddress(ComboAddress::*)(const std::string& key)>("ipdecrypt", [](const ComboAddress& ca, const std::string& key) {
+ return decryptCA(ca, key);
+ });
+
/* DNSName */
g_lua.registerFunction("isPartOf", &DNSName::isPartOf);
g_lua.registerFunction<bool(DNSName::*)()>("chopOff", [](DNSName&dn ) { return dn.chopOff(); });
dnsdist_LDADD += $(RE2_LIBS)
endif
-if HAVE_DNS_OVER_TLS
if HAVE_GNUTLS
dnsdist_LDADD += -lgnutls
endif
if HAVE_LIBSSL
dnsdist_LDADD += $(LIBSSL_LIBS) $(LIBCRYPTO_LIBS)
-endif
+dnsdist_SOURCES += ipcrypt.cc ipcrypt.hh ext/ipcrypt/ipcrypt.c ext/ipcrypt/ipcrypt.h
endif
if !HAVE_LUA_HPP
AM_CONDITIONAL([HAVE_GNUTLS], [false])
AM_CONDITIONAL([HAVE_LIBSSL], [false])
+
+PDNS_CHECK_LIBCRYPTO
+
DNSDIST_ENABLE_DNS_OVER_TLS
+
AS_IF([test "x$enable_dns_over_tls" != "xno"], [
DNSDIST_WITH_GNUTLS
DNSDIST_WITH_LIBSSL
AS_IF([test "$HAVE_LIBSSL" = "1"], [
# we need libcrypto if libssl is enabled
- PDNS_CHECK_LIBCRYPTO
+
])
AS_IF([test "$HAVE_GNUTLS" = "0" -a "$HAVE_LIBSSL" = "0"], [
AC_MSG_ERROR([DNS over TLS support requested but neither GnuTLS nor OpenSSL are available])
--- /dev/null
+/home/ahu/git/pdns/ext/ipcrypt/LICENSE
\ No newline at end of file
--- /dev/null
+/home/ahu/git/pdns/ext/ipcrypt/ipcrypt.c
\ No newline at end of file
--- /dev/null
+/home/ahu/git/pdns/ext/ipcrypt/ipcrypt.h
\ No newline at end of file
--- /dev/null
+#include "ipcrypt.hh"
+#include "ext/ipcrypt/ipcrypt.h"
+#include <openssl/aes.h>
+
+static ComboAddress encryptCA4(const ComboAddress& ca, const std::string &key)
+{
+ if(key.size() != 16)
+ throw std::runtime_error("Need 128 bits of key for ipcrypt");
+
+ ComboAddress ret=ca;
+
+ // always returns 0, has no failure mode
+ ipcrypt_encrypt( (unsigned char*)&ret.sin4.sin_addr.s_addr,
+ (const unsigned char*) &ca.sin4.sin_addr.s_addr,
+ (const unsigned char*)key.c_str());
+ return ret;
+}
+
+static ComboAddress decryptCA4(const ComboAddress& ca, const std::string &key)
+{
+ if(key.size() != 16)
+ throw std::runtime_error("Need 128 bits of key for ipcrypt");
+
+ ComboAddress ret=ca;
+
+ // always returns 0, has no failure mode
+ ipcrypt_decrypt( (unsigned char*)&ret.sin4.sin_addr.s_addr,
+ (const unsigned char*) &ca.sin4.sin_addr.s_addr,
+ (const unsigned char*)key.c_str());
+ return ret;
+}
+
+
+static ComboAddress encryptCA6(const ComboAddress& ca, const std::string &key)
+{
+ if(key.size() != 16)
+ throw std::runtime_error("Need 128 bits of key for ipcrypt");
+
+ ComboAddress ret=ca;
+
+ AES_KEY wctx;
+ AES_set_encrypt_key((const unsigned char*)key.c_str(), 128, &wctx);
+ AES_encrypt((const unsigned char*)&ca.sin6.sin6_addr.s6_addr,
+ (unsigned char*)&ret.sin6.sin6_addr.s6_addr, &wctx);
+
+ return ret;
+}
+
+static ComboAddress decryptCA6(const ComboAddress& ca, const std::string &key)
+{
+ if(key.size() != 16)
+ throw std::runtime_error("Need 128 bits of key for ipcrypt");
+
+ ComboAddress ret=ca;
+ AES_KEY wctx;
+ AES_set_decrypt_key((const unsigned char*)key.c_str(), 128, &wctx);
+ AES_decrypt((const unsigned char*)&ca.sin6.sin6_addr.s6_addr,
+ (unsigned char*)&ret.sin6.sin6_addr.s6_addr, &wctx);
+
+ return ret;
+}
+
+
+ComboAddress encryptCA(const ComboAddress& ca, const std::string& key)
+{
+ if(ca.sin4.sin_family == AF_INET)
+ return encryptCA4(ca, key);
+ else if(ca.sin4.sin_family == AF_INET6)
+ return encryptCA6(ca, key);
+ else
+ throw std::runtime_error("ipcrypt can't encrypt non-IP addresses");
+}
+
+ComboAddress decryptCA(const ComboAddress& ca, const std::string& key)
+{
+ if(ca.sin4.sin_family == AF_INET)
+ return decryptCA4(ca, key);
+ else if(ca.sin4.sin_family == AF_INET6)
+ return decryptCA6(ca, key);
+ else
+ throw std::runtime_error("ipcrypt can't decrypt non-IP addresses");
+
+}
--- /dev/null
+#pragma once
+#include "iputils.hh"
+#include <string>
+
+ComboAddress encryptCA(const ComboAddress& ca, const std::string& key);
+ComboAddress decryptCA(const ComboAddress& ca, const std::string& key);
--- /dev/null
+#define BOOST_TEST_DYN_LINK
+#define BOOST_TEST_NO_MAIN
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include <boost/test/unit_test.hpp>
+#include "ipcrypt.hh"
+#include "misc.hh"
+
+using namespace boost;
+
+BOOST_AUTO_TEST_SUITE(test_ipcrypt_hh)
+
+BOOST_AUTO_TEST_CASE(test_ipcrypt4)
+{
+ ComboAddress ca("127.0.0.1");
+ std::string key="0123456789ABCDEF";
+ auto encrypted = encryptCA(ca, key);
+
+ auto decrypted = decryptCA(encrypted, key);
+ BOOST_CHECK_EQUAL(ca.toString(), decrypted.toString());
+}
+
+BOOST_AUTO_TEST_CASE(test_ipcrypt4_vector)
+{
+ vector<pair<string,string>> tests{ // test vector from https://github.com/veorq/ipcrypt
+ {{"127.0.0.1"},{"114.62.227.59"}},
+ {{"8.8.8.8"}, {"46.48.51.50"}},
+ {{"1.2.3.4"}, {"171.238.15.199"}}};
+
+ std::string key="some 16-byte key";
+
+ for(const auto& p : tests) {
+ auto encrypted = encryptCA(ComboAddress(p.first), key);
+ BOOST_CHECK_EQUAL(encrypted.toString(), p.second);
+ auto decrypted = decryptCA(encrypted, key);
+ BOOST_CHECK_EQUAL(decrypted.toString(), p.first);
+ }
+
+ ComboAddress ip("192.168.69.42"), out, dec;
+ string key2;
+ for(int n=0; n<16; ++n)
+ key2.append(1, (char)n+1);
+
+ for (unsigned int i = 0; i < 100000000UL; i++) {
+ out=encryptCA(ip, key2);
+ // dec=decryptCA(out, key2);
+ // BOOST_CHECK(ip==dec);
+ ip=out;
+ }
+
+ ComboAddress expected("93.155.197.186");
+
+ BOOST_CHECK_EQUAL(ip.toString(), expected.toString());
+}
+
+
+BOOST_AUTO_TEST_CASE(test_ipcrypt6)
+{
+ ComboAddress ca("::1");
+ std::string key="0123456789ABCDEF";
+ auto encrypted = encryptCA(ca, key);
+
+ auto decrypted = decryptCA(encrypted, key);
+ BOOST_CHECK_EQUAL(ca.toString(), decrypted.toString());
+}
+
+
+BOOST_AUTO_TEST_SUITE_END()