Skip to content
Snippets Groups Projects
Commit c53e0f92 authored by Adrien Béraud's avatar Adrien Béraud
Browse files

libsodium

parent 3517c2e2
No related branches found
No related tags found
No related merge requests found
...@@ -20,6 +20,7 @@ option (OPENDHT_LTO "Build with LTO" OFF) ...@@ -20,6 +20,7 @@ option (OPENDHT_LTO "Build with LTO" OFF)
list (APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake") list (APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake")
find_package (PkgConfig) find_package (PkgConfig)
pkg_search_module(libuv libuv) pkg_search_module(libuv libuv)
pkg_search_module(libsodium libsodium)
find_package (GnuTLS 3.3 REQUIRED) find_package (GnuTLS 3.3 REQUIRED)
pkg_search_module (Nettle nettle) pkg_search_module (Nettle nettle)
find_package (Msgpack 1.2 REQUIRED) find_package (Msgpack 1.2 REQUIRED)
...@@ -167,7 +168,7 @@ if (OPENDHT_STATIC) ...@@ -167,7 +168,7 @@ if (OPENDHT_STATIC)
target_link_libraries(opendht-static ${argon2_LIBRARIES}) target_link_libraries(opendht-static ${argon2_LIBRARIES})
target_include_directories(opendht-static SYSTEM PRIVATE ${argon2_INCLUDE_DIRS}) target_include_directories(opendht-static SYSTEM PRIVATE ${argon2_INCLUDE_DIRS})
endif () endif ()
target_link_libraries(opendht-static ${GNUTLS_LIBRARIES} ${Nettle_LIBRARIES} ${libuv_LIBRARIES}) target_link_libraries(opendht-static ${GNUTLS_LIBRARIES} ${Nettle_LIBRARIES} ${libuv_LIBRARIES} ${libsodium_LIBRARIES})
install (TARGETS opendht-static DESTINATION ${CMAKE_INSTALL_LIBDIR} EXPORT opendht) install (TARGETS opendht-static DESTINATION ${CMAKE_INSTALL_LIBDIR} EXPORT opendht)
endif () endif ()
...@@ -188,7 +189,7 @@ if (OPENDHT_SHARED) ...@@ -188,7 +189,7 @@ if (OPENDHT_SHARED)
target_link_libraries(opendht ${argon2_LIBRARIES}) target_link_libraries(opendht ${argon2_LIBRARIES})
target_include_directories(opendht SYSTEM PRIVATE ${argon2_INCLUDE_DIRS}) target_include_directories(opendht SYSTEM PRIVATE ${argon2_INCLUDE_DIRS})
endif () endif ()
target_link_libraries(opendht ${GNUTLS_LIBRARIES} ${Nettle_LIBRARIES} ${libuv_LIBRARIES}) target_link_libraries(opendht ${GNUTLS_LIBRARIES} ${Nettle_LIBRARIES} ${libuv_LIBRARIES} ${libsodium_LIBRARIES})
install (TARGETS opendht DESTINATION ${CMAKE_INSTALL_LIBDIR} EXPORT opendht) install (TARGETS opendht DESTINATION ${CMAKE_INSTALL_LIBDIR} EXPORT opendht)
endif () endif ()
......
...@@ -28,6 +28,8 @@ extern "C" { ...@@ -28,6 +28,8 @@ extern "C" {
#include <gnutls/x509.h> #include <gnutls/x509.h>
} }
#include <sodium.h>
#include <vector> #include <vector>
#include <memory> #include <memory>
...@@ -525,6 +527,7 @@ public: ...@@ -525,6 +527,7 @@ public:
clean(); clean();
munlock(data_.data(), data_.size()*sizeof(T)); munlock(data_.data(), data_.size()*sizeof(T));
data_ = c.data_; data_ = c.data_;
mlock(data_.data(), data_.size()*sizeof(T));
return *this; return *this;
} }
secure_vector<T>& operator=(secure_vector<T>&& c) { secure_vector<T>& operator=(secure_vector<T>&& c) {
...@@ -545,6 +548,7 @@ public: ...@@ -545,6 +548,7 @@ public:
std::vector<T>& writable() { clean(); return data_; } std::vector<T>& writable() { clean(); return data_; }
const std::vector<T>& makeInsecure() const { return data_; } const std::vector<T>& makeInsecure() const { return data_; }
const uint8_t* data() const { return data_.data(); } const uint8_t* data() const { return data_.data(); }
uint8_t* data() { return data_.data(); }
void clean() { void clean() {
clean(data_.begin(), data_.end()); clean(data_.begin(), data_.end());
...@@ -588,8 +592,149 @@ private: ...@@ -588,8 +592,149 @@ private:
std::vector<T> data_; std::vector<T> data_;
}; };
template <class T, size_t N>
class OPENDHT_PUBLIC secure_array
{
public:
secure_array() {
mlock(data_.data(), data_.size()*sizeof(T));
}
explicit secure_array(T _item): data_( _item) {
mlock(data_.data(), data_.size()*sizeof(T));
}
explicit secure_array(const std::array<T,N>& c): data_(c) {
mlock(data_.data(), data_.size()*sizeof(T));
}
secure_array(secure_array<T,N> const&) = default;
secure_array(secure_array<T,N> &&) = delete;
~secure_array() { clean(); munlock(data_.data(), data_.size()*sizeof(T)); }
static secure_array<T,N> getRandom() {
secure_array<T,N> ret;
crypto::random_device rdev;
std::uniform_int_distribution<uint8_t> rand_byte;
std::generate_n((uint8_t*)ret.data_.data(), ret.size()*sizeof(T), std::bind(rand_byte, std::ref(rdev)));
return ret;
}
secure_array<T,N>& operator=(const secure_array<T,N>& c) {
if (&c == this)
return *this;
clean();
data_ = c.data_;
return *this;
}
secure_array<T,N>& operator=(secure_array<T,N>&& c) = delete;
std::array<T,N>& writable() { clean(); return data_; }
const std::array<T,N>& makeInsecure() const { return data_; }
const uint8_t* data() const { return data_.data(); }
uint8_t* data() { return data_.data(); }
void clean() {
clean(data_.begin(), data_.end());
}
size_t size() const { return data_.size(); }
private:
/**
* Securely wipe memory
*/
static void clean(const typename std::array<T,N>::iterator& i, const typename std::array<T,N>::iterator& j) {
volatile uint8_t* b = reinterpret_cast<uint8_t*>(&*i);
volatile uint8_t* e = reinterpret_cast<uint8_t*>(&*j);
std::fill(b, e, 0);
}
std::array<T, N> data_;
};
using SecureBlob = secure_vector<uint8_t>; using SecureBlob = secure_vector<uint8_t>;
class EcPublicKey : public std::array<uint8_t, crypto_box_PUBLICKEYBYTES> {
public:
Blob encrypt(const Blob& message) const {
Blob ret(crypto_box_SEALBYTES+message.size());
crypto_box_seal(ret.data(), message.data(), message.size(), data());
return ret;
}
};
class EcSecretKey {
public:
using KeyData = secure_array<uint8_t, crypto_box_SECRETKEYBYTES>;
static EcSecretKey generate() {
EcSecretKey ret;
crypto_box_keypair(ret.pk.data(), ret.key.data());
return ret;
}
const EcPublicKey& getPublicKey() const {
return pk;
}
Blob encrypt(const Blob& message, const EcPublicKey& pub) const {
Blob ret(crypto_box_NONCEBYTES+crypto_box_MACBYTES+message.size());
randombytes_buf(ret.data(), crypto_box_NONCEBYTES);
if (crypto_box_easy(ret.data()+crypto_box_NONCEBYTES, message.data(), message.size(), ret.data(),
pub.data(), key.data()) != 0) {
throw CryptoException("Can't encrypt data");
}
return ret;
}
Blob decrypt(const Blob& cypher) const {
if (cypher.size() <= crypto_box_SEALBYTES)
throw DecryptError("Unexpected cipher length");
Blob ret(cypher.size() - crypto_box_SEALBYTES);
if (crypto_box_seal_open(ret.data(), cypher.data(), cypher.size(), pk.data(), key.data()) != 0) {
throw DecryptError("Can't decrypt data");
}
return ret;
}
Blob decrypt(const Blob& cypher, const EcPublicKey& pub) const {
if (cypher.size() <= crypto_box_NONCEBYTES+crypto_box_MACBYTES)
throw DecryptError("Unexpected cipher length");
Blob ret(cypher.size() - crypto_box_NONCEBYTES - crypto_box_MACBYTES);
if (crypto_box_open_easy(ret.data(),
cypher.data()+crypto_box_NONCEBYTES,
cypher.size()-crypto_box_NONCEBYTES,
cypher.data(),
pub.data(), key.data()) != 0) {
throw DecryptError("Can't decrypt data");
}
return ret;
}
SecureBlob computeSecret(const EcPublicKey& pub, bool sending) const {
// shared key = h(q ‖ client_publickey ‖ server_publickey)
crypto_generichash_state h;
crypto_generichash_init(&h, nullptr, 0U, crypto_generichash_BYTES);
{
std::array<uint8_t, crypto_scalarmult_BYTES> q;
if (auto err = crypto_scalarmult(q.data(), key.data(), pub.data()))
throw CryptoException("Can't compute secret: " + std::to_string(err));
crypto_generichash_update(&h, q.data(), q.size());
}
{
const auto& sender_pk = sending ? pk : pub;
const auto& receiver_pk = sending ? pub : pk;
crypto_generichash_update(&h, sender_pk.data(), sender_pk.size());
crypto_generichash_update(&h, receiver_pk.data(), receiver_pk.size());
}
SecureBlob ret(crypto_generichash_BYTES);
crypto_generichash_final(&h, ret.data(), ret.size());
return ret;
}
private:
KeyData key;
EcPublicKey pk;
};
/** /**
* Generate an RSA key pair (4096 bits) and a certificate. * Generate an RSA key pair (4096 bits) and a certificate.
* @param name the name used in the generated certificate * @param name the name used in the generated certificate
......
...@@ -569,6 +569,9 @@ private: ...@@ -569,6 +569,9 @@ private:
std::set<Sp<TcpSocket>> pending_connect; std::set<Sp<TcpSocket>> pending_connect;
NodeCache cache {}; NodeCache cache {};
crypto::EcSecretKey id_key;
//crypto::EcSecretKey id_key;
/** /**
* A comparator to classify IP addresses, only considering the * A comparator to classify IP addresses, only considering the
* first 64 bits in IPv6. * first 64 bits in IPv6.
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include "utils.h" #include "utils.h"
#include "sockaddr.h" #include "sockaddr.h"
#include "uv_utils.h" #include "uv_utils.h"
#include "crypto.h"
#include <list> #include <list>
...@@ -37,6 +38,9 @@ struct Node { ...@@ -37,6 +38,9 @@ struct Node {
SockAddr addr; SockAddr addr;
Sp<TcpSocket> sock; Sp<TcpSocket> sock;
crypto::EcPublicKey last_known_pk;
//std::list<crypto::EcSecretKey>
time_point time {time_point::min()}; /* last time eared about */ time_point time {time_point::min()}; /* last time eared about */
time_point reply_time {time_point::min()}; /* time of last correct reply received */ time_point reply_time {time_point::min()}; /* time of last correct reply received */
......
...@@ -186,7 +186,8 @@ NetworkEngine::NetworkEngine(uv_loop_t* loop, const NetworkConfig& config, InfoH ...@@ -186,7 +186,8 @@ NetworkEngine::NetworkEngine(uv_loop_t* loop, const NetworkConfig& config, InfoH
decltype(NetworkEngine::onRefresh) onRefresh) : decltype(NetworkEngine::onRefresh) onRefresh) :
onError(onError), onNewNode(onNewNode), onReportedAddr(onReportedAddr), onPing(onPing), onFindNode(onFindNode), onError(onError), onNewNode(onNewNode), onReportedAddr(onReportedAddr), onPing(onPing), onFindNode(onFindNode),
onGetValues(onGetValues), onListen(onListen), onAnnounce(onAnnounce), onRefresh(onRefresh), myid(myid), onGetValues(onGetValues), onListen(onListen), onAnnounce(onAnnounce), onRefresh(onRefresh), myid(myid),
network(net), DHT_LOG(log), sock(std::make_shared<UdpSocket>(loop)), tcp_sock(std::make_shared<TcpSocket>(loop)), scheduler(scheduler) network(net), DHT_LOG(log), sock(std::make_shared<UdpSocket>(loop)), tcp_sock(std::make_shared<TcpSocket>(loop)),
id_key(crypto::EcSecretKey::generate()), scheduler(scheduler)
{ {
if (dht_socket >= 0) { if (dht_socket >= 0) {
if (!set_nonblocking(dht_socket, 1)) if (!set_nonblocking(dht_socket, 1))
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment