From eb5184ee09bf9f5ae9b3a8eb7efe89b7eb77c08d Mon Sep 17 00:00:00 2001 From: Stephen Shelton Date: Wed, 4 Dec 2019 13:13:41 -0700 Subject: [PATCH 1/4] Reinstate link test / update to use KeyManager --- llarp/config/key_manager.cpp | 18 +++++++ llarp/config/key_manager.hpp | 18 +++++++ test/link/test_llarp_link.cpp | 91 ++++++++++++++++++++++++----------- 3 files changed, 99 insertions(+), 28 deletions(-) diff --git a/llarp/config/key_manager.cpp b/llarp/config/key_manager.cpp index e9c603437..c4f2cfb29 100644 --- a/llarp/config/key_manager.cpp +++ b/llarp/config/key_manager.cpp @@ -119,18 +119,36 @@ namespace llarp return m_idKey; } + void + KeyManager::setIdentityKey(const llarp::SecretKey& key) + { + m_idKey = key; + } + const llarp::SecretKey& KeyManager::getEncryptionKey() const { return m_encKey; } + void + KeyManager::setEncryptionKey(const llarp::SecretKey& key) + { + m_encKey = key; + } + const llarp::SecretKey& KeyManager::getTransportKey() const { return m_transportKey; } + void + KeyManager::setTransportKey(const llarp::SecretKey& key) + { + m_transportKey = key; + } + bool KeyManager::backupKeyFilesByMoving() const { diff --git a/llarp/config/key_manager.hpp b/llarp/config/key_manager.hpp index 1d35590b7..e3c9af9e5 100644 --- a/llarp/config/key_manager.hpp +++ b/llarp/config/key_manager.hpp @@ -43,18 +43,36 @@ namespace llarp const llarp::SecretKey& getIdentityKey() const; + /// Set the identity key. This does not write anything to disk. + /// + /// @param key is the key that will be copied-from. + void + setIdentityKey(const llarp::SecretKey& key); + /// Obtain the encryption key (e.g. ~/.lokinet/encryption.private) /// /// @return a reference to the encryption key const llarp::SecretKey& getEncryptionKey() const; + /// Set the encryption key. This does not write anything to disk. + /// + /// @param key is the key that will be copied-from. + void + setEncryptionKey(const llarp::SecretKey& key); + /// Obtain the transport key (e.g. ~/.lokinet/transport.private) /// /// @return a reference to the transport key const llarp::SecretKey& getTransportKey() const; + /// Set the transport key. This does not write anything to disk. + /// + /// @param key is the key that will be copied-from. + void + setTransportKey(const llarp::SecretKey& key); + /// Obtain the self-signed RouterContact /// /// @param rc (out) will be modified to contian the RouterContact diff --git a/test/link/test_llarp_link.cpp b/test/link/test_llarp_link.cpp index f329fe2f9..f776e0ee2 100644 --- a/test/link/test_llarp_link.cpp +++ b/test/link/test_llarp_link.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -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(); + + SecretKey signingKey; CryptoManager::instance()->identity_keygen(signingKey); + keyManager->setIdentityKey(signingKey); + + SecretKey encryptionKey; CryptoManager::instance()->encryption_keygen(encryptionKey); + keyManager->setEncryptionKey(encryptionKey); + + SecretKey transportKey; + CryptoManager::instance()->encryption_keygen(transportKey); + keyManager->setTransportKey(transportKey); + + rc.pubkey = signingKey.toPublic(); rc.enckey = encryptionKey.toPublic(); } std::shared_ptr worker; - SecretKey signingKey; - SecretKey encryptionKey; + std::shared_ptr 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->getIdentityKey())) 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->getIdentityKey(), 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->getIdentityKey(), 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 }; From 66a058a2af939174f95da8a28534509c4beac586 Mon Sep 17 00:00:00 2001 From: Stephen Shelton Date: Fri, 6 Dec 2019 10:13:09 -0700 Subject: [PATCH 2/4] Make format --- llarp/config/key_manager.cpp | 103 +++++++++++++++---------------- llarp/config/key_manager.hpp | 40 ++++++------ llarp/dht/messages/findintro.cpp | 2 +- llarp/dht/messages/gotrouter.cpp | 4 +- llarp/ev/ev_win32.cpp | 4 +- llarp/iwp/iwp.cpp | 4 +- llarp/iwp/iwp.hpp | 4 +- llarp/iwp/linklayer.cpp | 10 +-- llarp/iwp/linklayer.hpp | 3 +- llarp/link/factory.hpp | 6 +- llarp/link/server.cpp | 5 +- llarp/link/server.hpp | 4 +- llarp/messages/relay.cpp | 4 +- llarp/messages/relay_commit.cpp | 4 +- llarp/messages/relay_status.cpp | 6 +- llarp/router/router.cpp | 17 +++-- llarp/router/router.hpp | 2 +- llarp/service/protocol.cpp | 4 +- llarp/util/bencode.cpp | 5 +- llarp/util/bencode.h | 3 +- llarp/util/bencode.hpp | 4 +- 21 files changed, 115 insertions(+), 123 deletions(-) diff --git a/llarp/config/key_manager.cpp b/llarp/config/key_manager.cpp index c4f2cfb29..6eda6f238 100644 --- a/llarp/config/key_manager.cpp +++ b/llarp/config/key_manager.cpp @@ -12,40 +12,38 @@ /// 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) { } 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; @@ -54,9 +52,9 @@ namespace llarp // 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 not rc.VerifySignature()) { - if (! genIfAbsent) + if(!genIfAbsent) { LogError("Our RouterContact ", m_rcPath, " is invalid or out of date"); return false; @@ -64,49 +62,47 @@ 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, m_idKey, 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, m_encKey, 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, m_transportKey, transportKeygen)) return false; m_initialized = true; @@ -153,52 +149,51 @@ namespace llarp KeyManager::backupKeyFilesByMoving() const { 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 files = { - m_rcPath, - m_idKeyPath, - m_encKeyPath, - m_transportKeyPath - }; + std::vector< std::string > files = {m_rcPath, m_idKeyPath, m_encKeyPath, + m_transportKeyPath}; - for (auto& filepath : files) + for(auto& filepath : files) { std::error_code ec; bool exists = fs::exists(filepath, ec); - if (ec) + if(ec) { - LogError("Could not determine status of file ", filepath, ": ", ec.message()); + LogError("Could not determine status of file ", filepath, ": ", + ec.message()); return false; } - if (not exists) + if(not exists) { LogInfo("File ", filepath, " doesn't exist; no backup needed"); continue; } fs::path newFilepath = findFreeBackupFilename(filepath); - if (newFilepath.empty()) + if(newFilepath.empty()) { LogWarn("Could not find an appropriate backup filename for", filepath); return false; } - LogInfo("Backing up (moving) key file ", filepath, " to ", newFilepath, "..."); + LogInfo("Backing up (moving) key file ", filepath, " to ", newFilepath, + "..."); fs::rename(filepath, newFilepath, ec); - if (ec) { + if(ec) + { LogError("Failed to move key file ", ec.message()); return false; } @@ -209,15 +204,14 @@ namespace llarp bool KeyManager::loadOrCreateKey( - const std::string& filepath, - llarp::SecretKey& key, - std::function 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; @@ -226,7 +220,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; @@ -240,7 +234,7 @@ namespace llarp bool KeyManager::loadIdentityFromLokid() { - CURL *curl = curl_easy_init(); + CURL* curl = curl_easy_init(); if(curl) { bool ret = false; @@ -251,7 +245,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); @@ -307,7 +301,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()); } @@ -318,7 +312,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(m_idKey))); break; } else diff --git a/llarp/config/key_manager.hpp b/llarp/config/key_manager.hpp index e3c9af9e5..5d88f728c 100644 --- a/llarp/config/key_manager.hpp +++ b/llarp/config/key_manager.hpp @@ -8,30 +8,31 @@ 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 + { /// 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 @@ -80,15 +81,14 @@ namespace llarp bool getRouterContact(llarp::RouterContact& rc) const; - private: - + private: std::string m_rcPath; std::string m_idKeyPath; std::string m_encKeyPath; std::string m_transportKeyPath; std::atomic_bool m_initialized; - 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; @@ -105,10 +105,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 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 diff --git a/llarp/dht/messages/findintro.cpp b/llarp/dht/messages/findintro.cpp index fcac8e893..f317bf1e5 100644 --- a/llarp/dht/messages/findintro.cpp +++ b/llarp/dht/messages/findintro.cpp @@ -27,7 +27,7 @@ namespace llarp return false; if(!BEncodeMaybeVerifyVersion("V", version, LLARP_PROTO_VERSION, read, k, - val)) + val)) return false; return read; diff --git a/llarp/dht/messages/gotrouter.cpp b/llarp/dht/messages/gotrouter.cpp index a6c6b1d87..e66b59907 100644 --- a/llarp/dht/messages/gotrouter.cpp +++ b/llarp/dht/messages/gotrouter.cpp @@ -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; diff --git a/llarp/ev/ev_win32.cpp b/llarp/ev/ev_win32.cpp index 18fa91c44..9ec07c6b4 100644 --- a/llarp/ev/ev_win32.cpp +++ b/llarp/ev/ev_win32.cpp @@ -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) { diff --git a/llarp/iwp/iwp.cpp b/llarp/iwp/iwp.cpp index eddaa6c3d..d6c323938 100644 --- a/llarp/iwp/iwp.cpp +++ b/llarp/iwp/iwp.cpp @@ -9,7 +9,7 @@ namespace llarp namespace iwp { LinkLayer_ptr - NewInboundLink(std::shared_ptr 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, GetRCFunc getrc, + NewOutboundLink(std::shared_ptr< KeyManager > keyManager, GetRCFunc getrc, LinkMessageHandler h, SignBufferFunc sign, SessionEstablishedHandler est, SessionRenegotiateHandler reneg, TimeoutHandler timeout, diff --git a/llarp/iwp/iwp.hpp b/llarp/iwp/iwp.hpp index 86433eb58..bec91fe3f 100644 --- a/llarp/iwp/iwp.hpp +++ b/llarp/iwp/iwp.hpp @@ -11,13 +11,13 @@ namespace llarp namespace iwp { LinkLayer_ptr - NewInboundLink(std::shared_ptr 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, GetRCFunc getrc, + NewOutboundLink(std::shared_ptr< KeyManager > keyManager, GetRCFunc getrc, LinkMessageHandler h, SignBufferFunc sign, SessionEstablishedHandler est, SessionRenegotiateHandler reneg, TimeoutHandler timeout, diff --git a/llarp/iwp/linklayer.cpp b/llarp/iwp/linklayer.cpp index 4cc1aefa6..5b7de3807 100644 --- a/llarp/iwp/linklayer.cpp +++ b/llarp/iwp/linklayer.cpp @@ -8,14 +8,14 @@ namespace llarp { namespace iwp { - LinkLayer::LinkLayer(std::shared_ptr 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} { } diff --git a/llarp/iwp/linklayer.hpp b/llarp/iwp/linklayer.hpp index 50d8fc4fe..075f5e9f1 100644 --- a/llarp/iwp/linklayer.hpp +++ b/llarp/iwp/linklayer.hpp @@ -17,7 +17,7 @@ namespace llarp { struct LinkLayer final : public ILinkLayer { - LinkLayer(std::shared_ptr 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; diff --git a/llarp/link/factory.hpp b/llarp/link/factory.hpp index 648a9be77..4b4bb43ee 100644 --- a/llarp/link/factory.hpp +++ b/llarp/link/factory.hpp @@ -22,9 +22,9 @@ namespace llarp }; using Factory = std::function< LinkLayer_ptr( - std::shared_ptr, 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 diff --git a/llarp/link/server.cpp b/llarp/link/server.cpp index 7ade923ae..b3e9ffadc 100644 --- a/llarp/link/server.cpp +++ b/llarp/link/server.cpp @@ -11,8 +11,9 @@ namespace llarp { static constexpr size_t MaxSessionsPerKey = 16; - ILinkLayer::ILinkLayer(std::shared_ptr keyManager, GetRCFunc getrc, - LinkMessageHandler handler, SignBufferFunc signbuf, + ILinkLayer::ILinkLayer(std::shared_ptr< KeyManager > keyManager, + GetRCFunc getrc, LinkMessageHandler handler, + SignBufferFunc signbuf, SessionEstablishedHandler establishedSession, SessionRenegotiateHandler reneg, TimeoutHandler timeout, SessionClosedHandler closed, diff --git a/llarp/link/server.hpp b/llarp/link/server.hpp index 41acb9592..64900e5e5 100644 --- a/llarp/link/server.hpp +++ b/llarp/link/server.hpp @@ -52,7 +52,7 @@ namespace llarp struct ILinkLayer { - ILinkLayer(std::shared_ptr keyManager, GetRCFunc getrc, + ILinkLayer(std::shared_ptr< KeyManager > keyManager, GetRCFunc getrc, LinkMessageHandler handler, SignBufferFunc signFunc, SessionEstablishedHandler sessionEstablish, SessionRenegotiateHandler renegotiate, TimeoutHandler timeout, @@ -179,7 +179,7 @@ namespace llarp SessionClosedHandler SessionClosed; SessionRenegotiateHandler SessionRenegotiate; PumpDoneHandler PumpDone; - std::shared_ptr keyManager; + std::shared_ptr< KeyManager > keyManager; std::shared_ptr< Logic > logic() diff --git a/llarp/messages/relay.cpp b/llarp/messages/relay.cpp index 3c54b078b..3497665a8 100644 --- a/llarp/messages/relay.cpp +++ b/llarp/messages/relay.cpp @@ -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; diff --git a/llarp/messages/relay_commit.cpp b/llarp/messages/relay_commit.cpp index 7d0630fee..f8cc5585c 100644 --- a/llarp/messages/relay_commit.cpp +++ b/llarp/messages/relay_commit.cpp @@ -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") { diff --git a/llarp/messages/relay_status.cpp b/llarp/messages/relay_status.cpp index 46f4d38ac..7b9c32685 100644 --- a/llarp/messages/relay_status.cpp +++ b/llarp/messages/relay_status.cpp @@ -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; diff --git a/llarp/router/router.cpp b/llarp/router/router.cpp index 90958777f..74777093b 100644 --- a/llarp/router/router.cpp +++ b/llarp/router/router.cpp @@ -49,7 +49,7 @@ namespace llarp , inbound_link_msg_parser(this) , _hiddenServiceContext(this) { - m_keyManager = std::make_shared(); + 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(); + _identity = m_keyManager->getIdentityKey(); _encryption = m_keyManager->getEncryptionKey(); - 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; diff --git a/llarp/router/router.hpp b/llarp/router/router.hpp index 1bdddb9b3..f0fe8b944 100644 --- a/llarp/router/router.hpp +++ b/llarp/router/router.hpp @@ -461,7 +461,7 @@ namespace llarp llarp_time_t m_LastStatsReport = 0; - std::shared_ptr m_keyManager; + std::shared_ptr< llarp::KeyManager > m_keyManager; bool ShouldReportStats(llarp_time_t now) const; diff --git a/llarp/service/protocol.cpp b/llarp/service/protocol.cpp index a74e80b85..68d47ad3a 100644 --- a/llarp/service/protocol.cpp +++ b/llarp/service/protocol.cpp @@ -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; diff --git a/llarp/util/bencode.cpp b/llarp/util/bencode.cpp index aef39d385..bb40b13c4 100644 --- a/llarp/util/bencode.cpp +++ b/llarp/util/bencode.cpp @@ -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); diff --git a/llarp/util/bencode.h b/llarp/util/bencode.h index 07a612338..4caac8dcf 100644 --- a/llarp/util/bencode.h +++ b/llarp/util/bencode.h @@ -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); diff --git a/llarp/util/bencode.hpp b/llarp/util/bencode.hpp index 05cd575f4..a3f062ee0 100644 --- a/llarp/util/bencode.hpp +++ b/llarp/util/bencode.hpp @@ -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) { From 11410a27484c296a009fd0c6588e6e56aa853266 Mon Sep 17 00:00:00 2001 From: Stephen Shelton Date: Fri, 6 Dec 2019 10:31:19 -0700 Subject: [PATCH 3/4] Avoid trivial getters/setters in KeyManager --- llarp/config/key_manager.cpp | 50 +++++------------------------------ llarp/config/key_manager.hpp | 44 +++--------------------------- llarp/link/server.cpp | 4 +-- llarp/router/router.cpp | 4 +-- test/link/test_llarp_link.cpp | 12 ++++----- 5 files changed, 21 insertions(+), 93 deletions(-) diff --git a/llarp/config/key_manager.cpp b/llarp/config/key_manager.cpp index 6eda6f238..ec598f37c 100644 --- a/llarp/config/key_manager.cpp +++ b/llarp/config/key_manager.cpp @@ -81,7 +81,7 @@ namespace llarp // 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 @@ -94,7 +94,7 @@ namespace llarp 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) @@ -102,49 +102,13 @@ namespace llarp 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; - } - - void - KeyManager::setIdentityKey(const llarp::SecretKey& key) - { - m_idKey = key; - } - - const llarp::SecretKey& - KeyManager::getEncryptionKey() const - { - return m_encKey; - } - - void - KeyManager::setEncryptionKey(const llarp::SecretKey& key) - { - m_encKey = key; - } - - const llarp::SecretKey& - KeyManager::getTransportKey() const - { - return m_transportKey; - } - - void - KeyManager::setTransportKey(const llarp::SecretKey& key) - { - m_transportKey = key; - } - bool KeyManager::backupKeyFilesByMoving() const { @@ -278,7 +242,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()) { @@ -290,9 +254,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; } @@ -313,7 +277,7 @@ namespace llarp if(ret) { LogInfo("Got Identity Keys from lokid: ", - RouterID(seckey_topublic(m_idKey))); + RouterID(seckey_topublic(identityKey))); break; } else diff --git a/llarp/config/key_manager.hpp b/llarp/config/key_manager.hpp index 5d88f728c..9b7e84313 100644 --- a/llarp/config/key_manager.hpp +++ b/llarp/config/key_manager.hpp @@ -38,42 +38,6 @@ namespace llarp 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; - - /// Set the identity key. This does not write anything to disk. - /// - /// @param key is the key that will be copied-from. - void - setIdentityKey(const llarp::SecretKey& key); - - /// Obtain the encryption key (e.g. ~/.lokinet/encryption.private) - /// - /// @return a reference to the encryption key - const llarp::SecretKey& - getEncryptionKey() const; - - /// Set the encryption key. This does not write anything to disk. - /// - /// @param key is the key that will be copied-from. - void - setEncryptionKey(const llarp::SecretKey& key); - - /// Obtain the transport key (e.g. ~/.lokinet/transport.private) - /// - /// @return a reference to the transport key - const llarp::SecretKey& - getTransportKey() const; - - /// Set the transport key. This does not write anything to disk. - /// - /// @param key is the key that will be copied-from. - void - setTransportKey(const llarp::SecretKey& key); - /// Obtain the self-signed RouterContact /// /// @param rc (out) will be modified to contian the RouterContact @@ -81,6 +45,10 @@ namespace llarp bool getRouterContact(llarp::RouterContact& rc) const; + llarp::SecretKey identityKey; + llarp::SecretKey encryptionKey; + llarp::SecretKey transportKey; + private: std::string m_rcPath; std::string m_idKeyPath; @@ -93,10 +61,6 @@ namespace llarp 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; diff --git a/llarp/link/server.cpp b/llarp/link/server.cpp index b3e9ffadc..ca4e24023 100644 --- a/llarp/link/server.cpp +++ b/llarp/link/server.cpp @@ -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) { } diff --git a/llarp/router/router.cpp b/llarp/router/router.cpp index 74777093b..81f7a121f 100644 --- a/llarp/router/router.cpp +++ b/llarp/router/router.cpp @@ -208,8 +208,8 @@ namespace llarp #endif } - _identity = m_keyManager->getIdentityKey(); - _encryption = m_keyManager->getEncryptionKey(); + _identity = m_keyManager->identityKey; + _encryption = m_keyManager->encryptionKey; if(_identity.IsZero()) return false; diff --git a/test/link/test_llarp_link.cpp b/test/link/test_llarp_link.cpp index f776e0ee2..4a8b24f6a 100644 --- a/test/link/test_llarp_link.cpp +++ b/test/link/test_llarp_link.cpp @@ -29,15 +29,15 @@ struct LinkLayerTest : public test::LlarpTest< llarp::sodium::CryptoLibSodium > SecretKey signingKey; CryptoManager::instance()->identity_keygen(signingKey); - keyManager->setIdentityKey(signingKey); + keyManager->identityKey = signingKey; SecretKey encryptionKey; CryptoManager::instance()->encryption_keygen(encryptionKey); - keyManager->setEncryptionKey(encryptionKey); + keyManager->encryptionKey = encryptionKey; SecretKey transportKey; CryptoManager::instance()->encryption_keygen(transportKey); - keyManager->setTransportKey(transportKey); + keyManager->transportKey = transportKey; rc.pubkey = signingKey.toPublic(); @@ -105,7 +105,7 @@ struct LinkLayerTest : public test::LlarpTest< llarp::sodium::CryptoLibSodium > rc.addrs.emplace_back(); if(!link->GetOurAddressInfo(rc.addrs[0])) return false; - if(!rc.Sign(keyManager->getIdentityKey())) + if(!rc.Sign(keyManager->identityKey)) return false; return link->Start(logic, worker); } @@ -227,7 +227,7 @@ TEST_F(LinkLayerTest, TestIWP) // SignBufferFunc [&](Signature& sig, const llarp_buffer_t& buf) -> bool { - return m_crypto.sign(sig, Alice.keyManager->getIdentityKey(), buf); + return m_crypto.sign(sig, Alice.keyManager->identityKey, buf); }, // SessionEstablishedHandler @@ -294,7 +294,7 @@ TEST_F(LinkLayerTest, TestIWP) // SignBufferFunc [&](Signature& sig, const llarp_buffer_t& buf) -> bool { - return m_crypto.sign(sig, Bob.keyManager->getIdentityKey(), buf); + return m_crypto.sign(sig, Bob.keyManager->identityKey, buf); }, //SessionEstablishedHandler From 2c6226f54a9c379102347400d78b5186a2e7aec6 Mon Sep 17 00:00:00 2001 From: Stephen Shelton Date: Fri, 6 Dec 2019 11:21:14 -0700 Subject: [PATCH 4/4] Backup SNApp keys when migrating to new ed25519 crypto --- llarp/config/key_manager.cpp | 77 ++++++++++++-------- llarp/config/key_manager.hpp | 18 +++++ llarp/router/abstractrouter.hpp | 5 ++ llarp/router/router.hpp | 6 ++ llarp/service/endpoint.cpp | 3 +- llarp/service/identity.cpp | 18 ++++- llarp/service/identity.hpp | 5 +- test/service/test_llarp_service_identity.cpp | 8 +- 8 files changed, 100 insertions(+), 40 deletions(-) diff --git a/llarp/config/key_manager.cpp b/llarp/config/key_manager.cpp index ec598f37c..f0310f35e 100644 --- a/llarp/config/key_manager.cpp +++ b/llarp/config/key_manager.cpp @@ -21,7 +21,7 @@ curl_RecvIdentKey(char* ptr, size_t, size_t nmemb, void* userdata) namespace llarp { - KeyManager::KeyManager() : m_initialized(false) + KeyManager::KeyManager() : m_initialized(false), m_needBackup(false) { } @@ -49,10 +49,14 @@ namespace llarp 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) { @@ -110,7 +114,7 @@ namespace llarp } bool - KeyManager::backupKeyFilesByMoving() const + KeyManager::backupFileByMoving(const std::string& filepath) { auto findFreeBackupFilename = [](const fs::path& filepath) { for(int i = 0; i < 9; i++) @@ -125,42 +129,51 @@ namespace llarp 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; diff --git a/llarp/config/key_manager.hpp b/llarp/config/key_manager.hpp index 9b7e84313..6bdfdca77 100644 --- a/llarp/config/key_manager.hpp +++ b/llarp/config/key_manager.hpp @@ -21,6 +21,16 @@ namespace llarp 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(); @@ -45,6 +55,13 @@ namespace llarp bool getRouterContact(llarp::RouterContact& rc) const; + /// 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; @@ -55,6 +72,7 @@ namespace llarp std::string m_encKeyPath; std::string m_transportKeyPath; std::atomic_bool m_initialized; + std::atomic_bool m_needBackup; bool m_usingLokid = false; std::string m_lokidRPCAddr = "127.0.0.1:22023"; diff --git a/llarp/router/abstractrouter.hpp b/llarp/router/abstractrouter.hpp index 556ad9469..b23c5f4bd 100644 --- a/llarp/router/abstractrouter.hpp +++ b/llarp/router/abstractrouter.hpp @@ -1,6 +1,8 @@ #ifndef LLARP_ABSTRACT_ROUTER_HPP #define LLARP_ABSTRACT_ROUTER_HPP +#include +#include #include #include #include @@ -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; diff --git a/llarp/router/router.hpp b/llarp/router/router.hpp index f0fe8b944..dd458e620 100644 --- a/llarp/router/router.hpp +++ b/llarp/router/router.hpp @@ -127,6 +127,12 @@ namespace llarp return _exitContext; } + std::shared_ptr< KeyManager > + keyManager() const + { + return m_keyManager; + } + const SecretKey & identity() const override { diff --git a/llarp/service/endpoint.cpp b/llarp/service/endpoint.cpp index 1f9d3e306..0050d2665 100644 --- a/llarp/service/endpoint.cpp +++ b/llarp/service/endpoint.cpp @@ -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; diff --git a/llarp/service/identity.cpp b/llarp/service/identity.cpp index d4e373c07..b2c8796c8 100644 --- a/llarp/service/identity.cpp +++ b/llarp/service/identity.cpp @@ -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(); diff --git a/llarp/service/identity.hpp b/llarp/service/identity.hpp index 1b94ec34b..71da652de 100644 --- a/llarp/service/identity.hpp +++ b/llarp/service/identity.hpp @@ -1,8 +1,10 @@ #ifndef LLARP_SERVICE_IDENTITY_HPP #define LLARP_SERVICE_IDENTITY_HPP +#include #include #include +#include #include #include #include @@ -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, diff --git a/test/service/test_llarp_service_identity.cpp b/test/service/test_llarp_service_identity.cpp index 46e7b8677..ad726e3c8 100644 --- a/test/service/test_llarp_service_identity.cpp +++ b/test/service/test_llarp_service_identity.cpp @@ -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)); }