Merge pull request #945 from notlesh/key_manager_cleanup

Key manager cleanup (post 0.6-rc1)
pull/949/head^2
Stephen Shelton 5 years ago committed by GitHub
commit 68a604070b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -12,51 +12,53 @@
/// curl callback
static size_t
curl_RecvIdentKey(char *ptr, size_t, size_t nmemb, void *userdata)
curl_RecvIdentKey(char* ptr, size_t, size_t nmemb, void* userdata)
{
for(size_t idx = 0; idx < nmemb; idx++)
static_cast< std::vector< char > * >(userdata)->push_back(ptr[idx]);
static_cast< std::vector< char >* >(userdata)->push_back(ptr[idx]);
return nmemb;
}
namespace llarp
{
KeyManager::KeyManager()
: m_initialized(false)
KeyManager::KeyManager() : m_initialized(false), m_needBackup(false)
{
}
bool
KeyManager::initialize(const llarp::Config& config, bool genIfAbsent)
{
if (m_initialized)
if(m_initialized)
return false;
m_rcPath = config.router.ourRcFile();
m_idKeyPath = config.router.identKeyfile();
m_encKeyPath = config.router.encryptionKeyfile();
m_rcPath = config.router.ourRcFile();
m_idKeyPath = config.router.identKeyfile();
m_encKeyPath = config.router.encryptionKeyfile();
m_transportKeyPath = config.router.transportKeyfile();
m_usingLokid = config.lokid.whitelistRouters;
m_lokidRPCAddr = config.lokid.lokidRPCAddr;
m_lokidRPCUser = config.lokid.lokidRPCUser;
m_usingLokid = config.lokid.whitelistRouters;
m_lokidRPCAddr = config.lokid.lokidRPCAddr;
m_lokidRPCUser = config.lokid.lokidRPCUser;
m_lokidRPCPassword = config.lokid.lokidRPCPassword;
RouterContact rc;
bool exists = rc.Read(m_rcPath.c_str());
if (not exists and not genIfAbsent)
if(not exists and not genIfAbsent)
{
LogError("Could not read RouterContact at path ", m_rcPath);
return false;
}
// we need to back up keys if our self.signed doesn't appear to have a
// valid signature
m_needBackup = (not rc.VerifySignature());
// if our RC file can't be verified, assume it is out of date (e.g. uses
// older encryption) and needs to be regenerated. before doing so, backup
// files that will be overwritten
if (exists and not rc.VerifySignature())
if(exists and m_needBackup)
{
if (! genIfAbsent)
if(!genIfAbsent)
{
LogError("Our RouterContact ", m_rcPath, " is invalid or out of date");
return false;
@ -64,126 +66,114 @@ namespace llarp
else
{
LogWarn("Our RouterContact ", m_rcPath,
" seems out of date, backing up and regenerating private keys");
" seems out of date, backing up and regenerating private keys");
if (! backupKeyFilesByMoving())
if(!backupKeyFilesByMoving())
{
LogError("Could not mv some key files, please ensure key files"
LogError(
"Could not mv some key files, please ensure key files"
" are backed up if needed and remove");
return false;
}
}
}
if (not m_usingLokid)
if(not m_usingLokid)
{
// load identity key or create if needed
auto identityKeygen = [](llarp::SecretKey& key)
{
auto identityKeygen = [](llarp::SecretKey& key) {
// TODO: handle generating from service node seed
llarp::CryptoManager::instance()->identity_keygen(key);
};
if (not loadOrCreateKey(m_idKeyPath, m_idKey, identityKeygen))
if(not loadOrCreateKey(m_idKeyPath, identityKey, identityKeygen))
return false;
}
else
{
if (not loadIdentityFromLokid())
if(not loadIdentityFromLokid())
return false;
}
// load encryption key
auto encryptionKeygen = [](llarp::SecretKey& key)
{
auto encryptionKeygen = [](llarp::SecretKey& key) {
llarp::CryptoManager::instance()->encryption_keygen(key);
};
if (not loadOrCreateKey(m_encKeyPath, m_encKey, encryptionKeygen))
if(not loadOrCreateKey(m_encKeyPath, encryptionKey, encryptionKeygen))
return false;
// TODO: transport key (currently done in LinkLayer)
auto transportKeygen = [](llarp::SecretKey& key)
{
auto transportKeygen = [](llarp::SecretKey& key) {
key.Zero();
CryptoManager::instance()->encryption_keygen(key);
};
if (not loadOrCreateKey(m_transportKeyPath, m_transportKey, transportKeygen))
if(not loadOrCreateKey(m_transportKeyPath, transportKey, transportKeygen))
return false;
m_initialized = true;
return true;
}
const llarp::SecretKey&
KeyManager::getIdentityKey() const
{
return m_idKey;
}
const llarp::SecretKey&
KeyManager::getEncryptionKey() const
{
return m_encKey;
}
const llarp::SecretKey&
KeyManager::getTransportKey() const
{
return m_transportKey;
}
bool
KeyManager::backupKeyFilesByMoving() const
KeyManager::backupFileByMoving(const std::string& filepath)
{
auto findFreeBackupFilename = [](const fs::path& filepath) {
for (int i=0; i<9; i++)
for(int i = 0; i < 9; i++)
{
std::string ext("." + std::to_string(i) + ".bak");
fs::path newPath = filepath;
newPath += ext;
if (not fs::exists(newPath))
if(not fs::exists(newPath))
return newPath;
}
return fs::path();
};
std::vector<std::string> files = {
m_rcPath,
m_idKeyPath,
m_encKeyPath,
m_transportKeyPath
};
std::error_code ec;
bool exists = fs::exists(filepath, ec);
if(ec)
{
LogError("Could not determine status of file ", filepath, ": ",
ec.message());
return false;
}
for (auto& filepath : files)
if(not exists)
{
std::error_code ec;
bool exists = fs::exists(filepath, ec);
if (ec)
{
LogError("Could not determine status of file ", filepath, ": ", ec.message());
return false;
}
LogInfo("File ", filepath, " doesn't exist; no backup needed");
return true;
}
if (not exists)
{
LogInfo("File ", filepath, " doesn't exist; no backup needed");
continue;
}
fs::path newFilepath = findFreeBackupFilename(filepath);
if(newFilepath.empty())
{
LogWarn("Could not find an appropriate backup filename for", filepath);
return false;
}
fs::path newFilepath = findFreeBackupFilename(filepath);
if (newFilepath.empty())
{
LogWarn("Could not find an appropriate backup filename for", filepath);
return false;
}
LogInfo("Backing up (moving) key file ", filepath, " to ", newFilepath,
"...");
fs::rename(filepath, newFilepath, ec);
if(ec)
{
LogError("Failed to move key file ", ec.message());
return false;
}
LogInfo("Backing up (moving) key file ", filepath, " to ", newFilepath, "...");
return true;
}
fs::rename(filepath, newFilepath, ec);
if (ec) {
LogError("Failed to move key file ", ec.message());
bool
KeyManager::backupKeyFilesByMoving() const
{
std::vector< std::string > files = {m_rcPath, m_idKeyPath, m_encKeyPath,
m_transportKeyPath};
for(auto& filepath : files)
{
if(not backupFileByMoving(filepath))
return false;
}
}
return true;
@ -191,15 +181,14 @@ namespace llarp
bool
KeyManager::loadOrCreateKey(
const std::string& filepath,
llarp::SecretKey& key,
std::function<void(llarp::SecretKey& key)> keygen)
const std::string& filepath, llarp::SecretKey& key,
std::function< void(llarp::SecretKey& key) > keygen)
{
fs::path path(filepath);
std::error_code ec;
if (! fs::exists(path, ec))
if(!fs::exists(path, ec))
{
if (ec)
if(ec)
{
LogError("Error checking key", filepath, ec.message());
return false;
@ -208,7 +197,7 @@ namespace llarp
LogInfo("Generating new key", filepath);
keygen(key);
if (! key.SaveToFile(filepath.c_str()))
if(!key.SaveToFile(filepath.c_str()))
{
LogError("Failed to save new key");
return false;
@ -222,7 +211,7 @@ namespace llarp
bool
KeyManager::loadIdentityFromLokid()
{
CURL *curl = curl_easy_init();
CURL* curl = curl_easy_init();
if(curl)
{
bool ret = false;
@ -233,7 +222,7 @@ namespace llarp
curl_easy_setopt(curl, CURLOPT_HTTPAUTH, (long)CURLAUTH_ANY);
const auto auth = m_lokidRPCUser + ":" + m_lokidRPCPassword;
curl_easy_setopt(curl, CURLOPT_USERPWD, auth.c_str());
curl_slist *list = nullptr;
curl_slist* list = nullptr;
list = curl_slist_append(list, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list);
@ -266,7 +255,7 @@ namespace llarp
continue;
const auto k =
(*itr)["service_node_ed25519_privkey"].get< std::string >();
if(k.size() != (m_idKey.size() * 2))
if(k.size() != (identityKey.size() * 2))
{
if(k.empty())
{
@ -278,9 +267,9 @@ namespace llarp
}
return false;
}
if(not HexDecode(k.c_str(), m_idKey.data(), m_idKey.size()))
if(not HexDecode(k.c_str(), identityKey.data(), identityKey.size()))
continue;
if(CryptoManager::instance()->check_identity_privkey(m_idKey))
if(CryptoManager::instance()->check_identity_privkey(identityKey))
{
ret = true;
}
@ -289,7 +278,7 @@ namespace llarp
LogError("lokid gave bogus identity key");
}
}
catch(nlohmann::json::exception &ex)
catch(nlohmann::json::exception& ex)
{
LogError("Bad response from lokid: ", ex.what());
}
@ -300,7 +289,8 @@ namespace llarp
}
if(ret)
{
LogInfo("Got Identity Keys from lokid: ", RouterID(seckey_topublic(m_idKey)));
LogInfo("Got Identity Keys from lokid: ",
RouterID(seckey_topublic(identityKey)));
break;
}
else

@ -8,53 +8,46 @@
namespace llarp
{
/// KeyManager manages the cryptographic keys stored on disk for the local node.
/// This includes private keys as well as the self-signed router contact file
/// (e.g. "self.signed").
/// KeyManager manages the cryptographic keys stored on disk for the local
/// node. This includes private keys as well as the self-signed router contact
/// file (e.g. "self.signed").
///
/// Keys are either read from disk if they exist and are valid (see below) or are
/// generated and written to disk.
///
/// In addition, the KeyManager detects when the keys obsolete (e.g. as a result
/// of a software upgrade) and backs up existing keys before writing out new ones.
struct KeyManager {
/// Keys are either read from disk if they exist and are valid (see below) or
/// are generated and written to disk.
///
/// In addition, the KeyManager detects when the keys obsolete (e.g. as a
/// result of a software upgrade) and backs up existing keys before writing
/// out new ones.
struct KeyManager
{
/// Utility function to backup a file by moving it. Attempts to find a new
/// filename based on the original that doesn't exist, then moves it. The
/// pattern used is originalFile.N.bak where N is the lowest integer
/// matching a filename that doesn't exist.
///
/// @param filepath is the name of the original file to backup.
/// @return true if the file could be moved or didn't exist, false otherwise
static bool
backupFileByMoving(const std::string& filepath);
/// Constructor
KeyManager();
/// Initializes keys using the provided config, loading from disk and/or lokid
/// via HTTP request.
/// Initializes keys using the provided config, loading from disk and/or
/// lokid via HTTP request.
///
/// NOTE: Must be called prior to obtaining any keys.
/// NOTE: blocks on I/O
///
/// @param config should be a prepared config object
/// @param genIfAbsent determines whether or not we will create files if they
/// @param genIfAbsent determines whether or not we will create files if
/// they
/// do not exist.
/// @return true on success, false otherwise
bool
initialize(const llarp::Config& config, bool genIfAbsent);
/// Obtain the identity key (e.g. ~/.lokinet/identity.private)
///
/// @return a reference to the identity key
const llarp::SecretKey&
getIdentityKey() const;
/// Obtain the encryption key (e.g. ~/.lokinet/encryption.private)
///
/// @return a reference to the encryption key
const llarp::SecretKey&
getEncryptionKey() const;
/// Obtain the transport key (e.g. ~/.lokinet/transport.private)
///
/// @return a reference to the transport key
const llarp::SecretKey&
getTransportKey() const;
/// Obtain the self-signed RouterContact
///
/// @param rc (out) will be modified to contian the RouterContact
@ -62,23 +55,30 @@ namespace llarp
bool
getRouterContact(llarp::RouterContact& rc) const;
private:
/// Return whether or not we need to backup keys as we load them
bool
needBackup() const
{
return m_needBackup;
}
llarp::SecretKey identityKey;
llarp::SecretKey encryptionKey;
llarp::SecretKey transportKey;
private:
std::string m_rcPath;
std::string m_idKeyPath;
std::string m_encKeyPath;
std::string m_transportKeyPath;
std::atomic_bool m_initialized;
std::atomic_bool m_needBackup;
bool m_usingLokid = false;
bool m_usingLokid = false;
std::string m_lokidRPCAddr = "127.0.0.1:22023";
std::string m_lokidRPCUser;
std::string m_lokidRPCPassword;
llarp::SecretKey m_idKey;
llarp::SecretKey m_encKey;
llarp::SecretKey m_transportKey;
/// Backup each key file (by copying, e.g. foo -> foo.bak)
bool
backupKeyFilesByMoving() const;
@ -87,10 +87,8 @@ namespace llarp
///
/// @param keygen is a function that will generate the key if needed
static bool
loadOrCreateKey(
const std::string& filepath,
llarp::SecretKey& key,
std::function<void(llarp::SecretKey& key)> keygen);
loadOrCreateKey(const std::string& filepath, llarp::SecretKey& key,
std::function< void(llarp::SecretKey& key) > keygen);
/// Requests the identity key from lokid via HTTP (curl)
bool

@ -27,7 +27,7 @@ namespace llarp
return false;
if(!BEncodeMaybeVerifyVersion("V", version, LLARP_PROTO_VERSION, read, k,
val))
val))
return false;
return read;

@ -71,8 +71,8 @@ namespace llarp
return bencode_read_integer(val, &txid);
}
bool read = false;
if(!BEncodeMaybeVerifyVersion("V", version, LLARP_PROTO_VERSION, read, key,
val))
if(!BEncodeMaybeVerifyVersion("V", version, LLARP_PROTO_VERSION, read,
key, val))
return false;
return read;

@ -143,8 +143,8 @@ tun_ev_loop(void* unused)
while(true)
{
alert =
GetQueuedCompletionStatus(tun_event_queue, &size, &listener, &ovl, EV_TICK_INTERVAL);
alert = GetQueuedCompletionStatus(tun_event_queue, &size, &listener, &ovl,
EV_TICK_INTERVAL);
if(!alert)
{

@ -9,7 +9,7 @@ namespace llarp
namespace iwp
{
LinkLayer_ptr
NewInboundLink(std::shared_ptr<KeyManager> keyManager, GetRCFunc getrc,
NewInboundLink(std::shared_ptr< KeyManager > keyManager, GetRCFunc getrc,
LinkMessageHandler h, SignBufferFunc sign,
SessionEstablishedHandler est,
SessionRenegotiateHandler reneg, TimeoutHandler timeout,
@ -21,7 +21,7 @@ namespace llarp
}
LinkLayer_ptr
NewOutboundLink(std::shared_ptr<KeyManager> keyManager, GetRCFunc getrc,
NewOutboundLink(std::shared_ptr< KeyManager > keyManager, GetRCFunc getrc,
LinkMessageHandler h, SignBufferFunc sign,
SessionEstablishedHandler est,
SessionRenegotiateHandler reneg, TimeoutHandler timeout,

@ -11,13 +11,13 @@ namespace llarp
namespace iwp
{
LinkLayer_ptr
NewInboundLink(std::shared_ptr<KeyManager> keyManager, GetRCFunc getrc,
NewInboundLink(std::shared_ptr< KeyManager > keyManager, GetRCFunc getrc,
LinkMessageHandler h, SignBufferFunc sign,
SessionEstablishedHandler est,
SessionRenegotiateHandler reneg, TimeoutHandler timeout,
SessionClosedHandler closed, PumpDoneHandler pumpDone);
LinkLayer_ptr
NewOutboundLink(std::shared_ptr<KeyManager> keyManager, GetRCFunc getrc,
NewOutboundLink(std::shared_ptr< KeyManager > keyManager, GetRCFunc getrc,
LinkMessageHandler h, SignBufferFunc sign,
SessionEstablishedHandler est,
SessionRenegotiateHandler reneg, TimeoutHandler timeout,

@ -8,14 +8,14 @@ namespace llarp
{
namespace iwp
{
LinkLayer::LinkLayer(std::shared_ptr<KeyManager> keyManager, GetRCFunc getrc,
LinkMessageHandler h, SignBufferFunc sign,
SessionEstablishedHandler est,
LinkLayer::LinkLayer(std::shared_ptr< KeyManager > keyManager,
GetRCFunc getrc, LinkMessageHandler h,
SignBufferFunc sign, SessionEstablishedHandler est,
SessionRenegotiateHandler reneg,
TimeoutHandler timeout, SessionClosedHandler closed,
PumpDoneHandler pumpDone, bool allowInbound)
: ILinkLayer(keyManager, getrc, h, sign, est, reneg, timeout,
closed, pumpDone)
: ILinkLayer(keyManager, getrc, h, sign, est, reneg, timeout, closed,
pumpDone)
, permitInbound{allowInbound}
{
}

@ -17,7 +17,7 @@ namespace llarp
{
struct LinkLayer final : public ILinkLayer
{
LinkLayer(std::shared_ptr<KeyManager> keyManager, GetRCFunc getrc,
LinkLayer(std::shared_ptr< KeyManager > keyManager, GetRCFunc getrc,
LinkMessageHandler h, SignBufferFunc sign,
SessionEstablishedHandler est, SessionRenegotiateHandler reneg,
TimeoutHandler timeout, SessionClosedHandler closed,
@ -29,7 +29,6 @@ namespace llarp
NewOutboundSession(const RouterContact &rc,
const AddressInfo &ai) override;
const char *
Name() const override;

@ -22,9 +22,9 @@ namespace llarp
};
using Factory = std::function< LinkLayer_ptr(
std::shared_ptr<KeyManager>, GetRCFunc, LinkMessageHandler, SignBufferFunc,
SessionEstablishedHandler, SessionRenegotiateHandler, TimeoutHandler,
SessionClosedHandler, PumpDoneHandler) >;
std::shared_ptr< KeyManager >, GetRCFunc, LinkMessageHandler,
SignBufferFunc, SessionEstablishedHandler, SessionRenegotiateHandler,
TimeoutHandler, SessionClosedHandler, PumpDoneHandler) >;
/// get link type by name string
/// if invalid returns eLinkUnspec

@ -26,8 +26,8 @@ namespace llarp
, SessionClosed(std::move(closed))
, SessionRenegotiate(std::move(reneg))
, PumpDone(std::move(pumpDone))
, m_RouterEncSecret(keyManager->getEncryptionKey())
, m_SecretKey(keyManager->getTransportKey())
, m_RouterEncSecret(keyManager->encryptionKey)
, m_SecretKey(keyManager->transportKey)
{
}

@ -42,7 +42,7 @@ namespace llarp
if(!BEncodeMaybeReadDictEntry("p", pathid, read, key, buf))
return false;
if(!BEncodeMaybeVerifyVersion("v", version, LLARP_PROTO_VERSION, read, key,
buf))
buf))
return false;
if(!BEncodeMaybeReadDictEntry("x", X, read, key, buf))
return false;
@ -98,7 +98,7 @@ namespace llarp
if(!BEncodeMaybeReadDictEntry("p", pathid, read, key, buf))
return false;
if(!BEncodeMaybeVerifyVersion("v", version, LLARP_PROTO_VERSION, read, key,
buf))
buf))
return false;
if(!BEncodeMaybeReadDictEntry("x", X, read, key, buf))
return false;

@ -27,7 +27,7 @@ namespace llarp
}
bool read = false;
if(!BEncodeMaybeVerifyVersion("v", version, LLARP_PROTO_VERSION, read, key,
buf))
buf))
return false;
return read;
@ -135,7 +135,7 @@ namespace llarp
return nextRC->BDecode(buffer);
}
if(!BEncodeMaybeVerifyVersion("v", version, LLARP_PROTO_VERSION, read, *key,
buffer))
buffer))
return false;
if(*key == "w")
{

@ -76,8 +76,8 @@ namespace llarp
}
else if(key == "v")
{
if(!BEncodeMaybeVerifyVersion("v", version, LLARP_PROTO_VERSION, read, key,
buf))
if(!BEncodeMaybeVerifyVersion("v", version, LLARP_PROTO_VERSION, read,
key, buf))
{
return false;
}
@ -263,7 +263,7 @@ namespace llarp
if(!BEncodeMaybeReadDictInt("s", status, read, *key, buffer))
return false;
if(!BEncodeMaybeVerifyVersion("v", version, LLARP_PROTO_VERSION, read, *key,
buffer))
buffer))
return false;
return read;

@ -1,6 +1,8 @@
#ifndef LLARP_ABSTRACT_ROUTER_HPP
#define LLARP_ABSTRACT_ROUTER_HPP
#include <config/key_manager.hpp>
#include <memory>
#include <util/types.hpp>
#include <util/status.hpp>
#include <router/i_outbound_message_handler.hpp>
@ -84,6 +86,9 @@ namespace llarp
virtual exit::Context &
exitContext() = 0;
virtual std::shared_ptr< KeyManager >
keyManager() const = 0;
virtual const SecretKey &
identity() const = 0;

@ -49,7 +49,7 @@ namespace llarp
, inbound_link_msg_parser(this)
, _hiddenServiceContext(this)
{
m_keyManager = std::make_shared<KeyManager>();
m_keyManager = std::make_shared< KeyManager >();
// set rational defaults
this->ip4addr.sin_family = AF_INET;
@ -195,7 +195,6 @@ namespace llarp
bool
Router::EnsureIdentity()
{
if(whitelistRouters)
{
#if defined(ANDROID) || defined(IOS)
@ -209,12 +208,12 @@ namespace llarp
#endif
}
_identity = m_keyManager->getIdentityKey();
_encryption = m_keyManager->getEncryptionKey();
_identity = m_keyManager->identityKey;
_encryption = m_keyManager->encryptionKey;
if (_identity.IsZero())
if(_identity.IsZero())
return false;
if (_encryption.IsZero())
if(_encryption.IsZero())
return false;
return true;
@ -231,7 +230,7 @@ namespace llarp
}
_nodedb = nodedb;
if (not m_keyManager->initialize(*conf, true))
if(not m_keyManager->initialize(*conf, true))
return false;
if(!FromConfig(conf))
@ -524,8 +523,7 @@ namespace llarp
util::memFn(&IOutboundSessionMaker::OnConnectTimeout,
&_outboundSessionMaker),
util::memFn(&AbstractRouter::SessionClosed, this),
util::memFn(&AbstractRouter::PumpLL, this)
);
util::memFn(&AbstractRouter::PumpLL, this));
const auto &key = std::get< LinksConfig::Interface >(serverConfig);
int af = std::get< LinksConfig::AddressFamily >(serverConfig);
@ -1161,8 +1159,7 @@ namespace llarp
util::memFn(&IOutboundSessionMaker::OnConnectTimeout,
&_outboundSessionMaker),
util::memFn(&AbstractRouter::SessionClosed, this),
util::memFn(&AbstractRouter::PumpLL, this)
);
util::memFn(&AbstractRouter::PumpLL, this));
if(!link)
return false;

@ -127,6 +127,12 @@ namespace llarp
return _exitContext;
}
std::shared_ptr< KeyManager >
keyManager() const
{
return m_keyManager;
}
const SecretKey &
identity() const override
{
@ -461,7 +467,7 @@ namespace llarp
llarp_time_t m_LastStatsReport = 0;
std::shared_ptr<llarp::KeyManager> m_keyManager;
std::shared_ptr< llarp::KeyManager > m_keyManager;
bool
ShouldReportStats(llarp_time_t now) const;

@ -453,7 +453,8 @@ namespace llarp
const auto& keyfile = m_state->m_Keyfile;
if(!keyfile.empty())
{
if(!m_Identity.EnsureKeys(keyfile))
if(!m_Identity.EnsureKeys(keyfile,
Router()->keyManager()->needBackup()))
{
LogError("Can't ensure keyfile [", keyfile, "]");
return false;

@ -78,13 +78,27 @@ namespace llarp
}
bool
Identity::EnsureKeys(const std::string& fname)
Identity::EnsureKeys(const std::string& fname, bool needBackup)
{
std::array< byte_t, 4096 > tmp;
llarp_buffer_t buf(tmp);
std::error_code ec;
bool exists = fs::exists(fname, ec);
if(ec)
{
LogError("Could not query file status for ", fname);
return false;
}
if(exists and needBackup)
{
KeyManager::backupFileByMoving(fname);
exists = false;
}
// check for file
if(!fs::exists(fname, ec))
if(!exists)
{
// regen and encode
RegenerateKeys();

@ -1,8 +1,10 @@
#ifndef LLARP_SERVICE_IDENTITY_HPP
#define LLARP_SERVICE_IDENTITY_HPP
#include <config/key_manager.hpp>
#include <constants/proto.hpp>
#include <crypto/types.hpp>
#include <memory>
#include <service/info.hpp>
#include <service/intro_set.hpp>
#include <service/vanity.hpp>
@ -33,8 +35,9 @@ namespace llarp
bool
BEncode(llarp_buffer_t* buf) const;
/// @param needBackup determines whether existing keys will be cycled
bool
EnsureKeys(const std::string& fpath);
EnsureKeys(const std::string& fpath, bool needBackup);
bool
KeyExchange(path_dh_func dh, SharedSecret& sharedkey,

@ -163,8 +163,8 @@ namespace llarp
return false;
if(!BEncodeMaybeReadDictEntry("T", T, read, key, val))
return false;
if(!BEncodeMaybeVerifyVersion("V", version, LLARP_PROTO_VERSION, read, key,
val))
if(!BEncodeMaybeVerifyVersion("V", version, LLARP_PROTO_VERSION, read,
key, val))
return false;
if(!BEncodeMaybeReadDictEntry("Z", Z, read, key, val))
return false;

@ -139,9 +139,10 @@ bencode_discard(llarp_buffer_t* buf)
}
bool
bencode_write_uint64_entry(llarp_buffer_t* buff, const void* name, size_t sz, uint64_t i)
bencode_write_uint64_entry(llarp_buffer_t* buff, const void* name, size_t sz,
uint64_t i)
{
if (! bencode_write_bytestring(buff, name, sz))
if(!bencode_write_bytestring(buff, name, sz))
return false;
return bencode_write_uint64(buff, i);

@ -31,7 +31,8 @@ bencode_write_uint64(llarp_buffer_t* buff, uint64_t i);
/// Write a dictionary entry with a uint64_t value
bool
bencode_write_uint64_entry(llarp_buffer_t* buff, const void* name, size_t sz, uint64_t i);
bencode_write_uint64_entry(llarp_buffer_t* buff, const void* name, size_t sz,
uint64_t i);
bool
bencode_start_list(llarp_buffer_t* buff);

@ -104,8 +104,8 @@ namespace llarp
template < typename Item_t >
bool
BEncodeMaybeVerifyVersion(const char* k, Item_t& item, uint64_t expect,
bool& read, const llarp_buffer_t& key,
llarp_buffer_t* buf)
bool& read, const llarp_buffer_t& key,
llarp_buffer_t* buf)
{
if(key == k)
{

@ -3,6 +3,7 @@
#include <iwp/iwp.hpp>
#include <llarp_test.hpp>
#include <iwp/iwp.hpp>
#include <memory>
#include <messages/link_intro.hpp>
#include <messages/discard.hpp>
@ -17,23 +18,35 @@ using namespace ::testing;
struct LinkLayerTest : public test::LlarpTest< llarp::sodium::CryptoLibSodium >
{
static constexpr uint16_t AlicePort = 5000;
static constexpr uint16_t BobPort = 6000;
static constexpr uint16_t AlicePort = 41163;
static constexpr uint16_t BobPort = 8088;
struct Context
{
Context()
{
keyManager = std::make_shared<KeyManager>();
SecretKey signingKey;
CryptoManager::instance()->identity_keygen(signingKey);
keyManager->identityKey = signingKey;
SecretKey encryptionKey;
CryptoManager::instance()->encryption_keygen(encryptionKey);
keyManager->encryptionKey = encryptionKey;
SecretKey transportKey;
CryptoManager::instance()->encryption_keygen(transportKey);
keyManager->transportKey = transportKey;
rc.pubkey = signingKey.toPublic();
rc.enckey = encryptionKey.toPublic();
}
std::shared_ptr<thread::ThreadPool> worker;
SecretKey signingKey;
SecretKey encryptionKey;
std::shared_ptr<KeyManager> keyManager;
RouterContact rc;
@ -64,15 +77,6 @@ struct LinkLayerTest : public test::LlarpTest< llarp::sodium::CryptoLibSodium >
return rc.pubkey;
}
/// regenerate rc and rotate onion key
bool
Regen()
{
CryptoManager::instance()->encryption_keygen(encryptionKey);
rc.enckey = seckey_topublic(encryptionKey);
return rc.Sign(signingKey);
}
std::shared_ptr< ILinkLayer > link;
static std::string
@ -93,12 +97,15 @@ struct LinkLayerTest : public test::LlarpTest< llarp::sodium::CryptoLibSodium >
return false;
if(!link->Configure(loop, localLoopBack(), AF_INET, port))
return false;
// if(!link->GenEphemeralKeys()) TODO: reimplement GenEphemeralKeys
/*
* TODO: ephemeral key management
if(!link->GenEphemeralKeys())
return false;
*/
rc.addrs.emplace_back();
if(!link->GetOurAddressInfo(rc.addrs[0]))
return false;
if(!rc.Sign(signingKey))
if(!rc.Sign(keyManager->identityKey))
return false;
return link->Start(logic, worker);
}
@ -188,9 +195,6 @@ TEST_F(LinkLayerTest, TestIWP)
#ifdef WIN32
GTEST_SKIP();
#else
/*
* TODO: use KeyManager
*
auto sendDiscardMessage = [](ILinkSession* s, auto callback) -> bool {
// send discard message in reply to complete unit test
std::vector< byte_t> tmp(32);
@ -201,8 +205,13 @@ TEST_F(LinkLayerTest, TestIWP)
return s->SendMessageBuffer(std::move(tmp), callback);
};
Alice.link = iwp::NewInboundLink(
Alice.encryptionKey,
// KeyManager
Alice.keyManager,
// GetRCFunc
[&]() -> const RouterContact& { return Alice.GetRC(); },
// LinkMessageHandler
[&](ILinkSession* s, const llarp_buffer_t& buf) -> bool {
llarp_buffer_t copy(buf.base, buf.sz);
if(not Alice.gotLIM)
@ -215,9 +224,13 @@ TEST_F(LinkLayerTest, TestIWP)
}
return Alice.gotLIM;
},
// SignBufferFunc
[&](Signature& sig, const llarp_buffer_t& buf) -> bool {
return m_crypto.sign(sig, Alice.signingKey, buf);
return m_crypto.sign(sig, Alice.keyManager->identityKey, buf);
},
// SessionEstablishedHandler
[&](ILinkSession* s) -> bool {
const auto rc = s->GetRemoteRC();
if(rc.pubkey != Bob.GetRC().pubkey)
@ -231,20 +244,33 @@ TEST_F(LinkLayerTest, TestIWP)
});
return true;
},
// SessionRenegotiateHandler
[&](RouterContact, RouterContact) -> bool { return true; },
// TimeoutHandler
[&](ILinkSession* session) {
ASSERT_FALSE(session->IsEstablished());
Stop();
},
// SessionClosedHandler
[&](RouterID router) { ASSERT_EQ(router, Alice.GetRouterID()); },
[]() {})
;
// PumpDoneHandler
[]() {}
);
Bob.link = iwp::NewInboundLink(
Bob.encryptionKey, [&]() -> const RouterContact& { return Bob.GetRC(); },
// KeyManager
Bob.keyManager,
// GetRCFunc
[&]() -> const RouterContact& { return Bob.GetRC(); },
// LinkMessageHandler
[&](ILinkSession* s, const llarp_buffer_t& buf) -> bool {
llarp_buffer_t copy(buf.base, buf.sz);
@ -266,9 +292,12 @@ TEST_F(LinkLayerTest, TestIWP)
return false;
},
// SignBufferFunc
[&](Signature& sig, const llarp_buffer_t& buf) -> bool {
return m_crypto.sign(sig, Bob.signingKey, buf);
return m_crypto.sign(sig, Bob.keyManager->identityKey, buf);
},
//SessionEstablishedHandler
[&](ILinkSession* s) -> bool {
if(s->GetRemoteRC().pubkey != Alice.GetRC().pubkey)
return false;
@ -277,13 +306,21 @@ TEST_F(LinkLayerTest, TestIWP)
return true;
},
// SessionRenegotiateHandler
[&](RouterContact newrc, RouterContact oldrc) -> bool {
return newrc.pubkey == oldrc.pubkey;
},
// TimeoutHandler
[&](ILinkSession* session) { ASSERT_FALSE(session->IsEstablished()); },
// SessionClosedHandler
[&](RouterID router) { ASSERT_EQ(router, Alice.GetRouterID()); },
[]() {})
;
// PumpDoneHandler
[]() {}
);
ASSERT_TRUE(Alice.Start(m_logic, netLoop, AlicePort));
ASSERT_TRUE(Bob.Start(m_logic, netLoop, BobPort));
@ -294,7 +331,5 @@ TEST_F(LinkLayerTest, TestIWP)
ASSERT_TRUE(Alice.IsGucci());
ASSERT_TRUE(Bob.IsGucci());
ASSERT_TRUE(success);
*/
ASSERT_TRUE(false); // FIXME, see above
#endif
};

@ -83,13 +83,13 @@ TEST_F(ServiceIdentityTest, EnsureKeys)
.WillOnce(WithArg< 0 >(FillArg< PQKeyPair >(0x03)));
service::Identity identity;
ASSERT_TRUE(identity.EnsureKeys(p.string()));
ASSERT_TRUE(identity.EnsureKeys(p.string(), false));
ASSERT_TRUE(fs::exists(fs::status(p)));
// Verify what is on disk is what is what was generated
service::Identity other;
// No need to set more mocks, as we shouldn't need to re-keygen
ASSERT_TRUE(other.EnsureKeys(p.string()));
ASSERT_TRUE(other.EnsureKeys(p.string(), false));
ASSERT_EQ(identity, other);
}
@ -103,7 +103,7 @@ TEST_F(ServiceIdentityTest, EnsureKeysDir)
ASSERT_TRUE(fs::create_directory(p, code)) << code;
service::Identity identity;
ASSERT_FALSE(identity.EnsureKeys(p.string()));
ASSERT_FALSE(identity.EnsureKeys(p.string(), false));
}
TEST_F(ServiceIdentityTest, EnsureKeysBrokenFile)
@ -120,5 +120,5 @@ TEST_F(ServiceIdentityTest, EnsureKeysBrokenFile)
file.close();
service::Identity identity;
ASSERT_FALSE(identity.EnsureKeys(p.string()));
ASSERT_FALSE(identity.EnsureKeys(p.string(), false));
}

Loading…
Cancel
Save