From 2cac9b03ff1ae00bc1b93ca9bd68b22a3cc8b165 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 6 Feb 2019 13:36:03 -0500 Subject: [PATCH] common code for offline signatures --- libi2pd/LeaseSet.cpp | 48 +++++++++++-------------------------------- libi2pd/LeaseSet.h | 29 ++++++++++++++++++++++++-- libi2pd/Streaming.cpp | 40 +++++++++++++++--------------------- libi2pd/Streaming.h | 2 +- 4 files changed, 57 insertions(+), 62 deletions(-) diff --git a/libi2pd/LeaseSet.cpp b/libi2pd/LeaseSet.cpp index e33f7974..d384f350 100644 --- a/libi2pd/LeaseSet.cpp +++ b/libi2pd/LeaseSet.cpp @@ -285,27 +285,15 @@ namespace data uint16_t expires = bufbe16toh (buf + offset); offset += 2; // expires (seconds) SetExpirationTime ((timestamp + expires)*1000LL); // in milliseconds uint16_t flags = bufbe16toh (buf + offset); offset += 2; // flags - std::unique_ptr transientVerifier; if (flags & 0x0001) { // transient key - if (offset + 6 >= len) return; - const uint8_t * signedData = buf + offset; - uint32_t expiresTimestamp = bufbe32toh (buf + offset); offset += 4; // expires timestamp - if (expiresTimestamp < i2p::util::GetSecondsSinceEpoch ()) - { - LogPrint (eLogWarning, "LeaseSet2: transient key expired"); + m_TransientVerifier = ProcessOfflineSignature (identity, buf, len, offset); + if (!m_TransientVerifier) + { + LogPrint (eLogError, "LeaseSet2: offline signature failed"); return; - } - uint16_t keyType = bufbe16toh (buf + offset); offset += 2; - transientVerifier.reset (i2p::data::IdentityEx::CreateVerifier (keyType)); - if (!transientVerifier) return; - auto keyLen = transientVerifier->GetPublicKeyLen (); - if (offset + keyLen >= len) return; - transientVerifier->SetPublicKey (buf + offset); offset += keyLen; - if (offset + identity->GetSignatureLen () >= len) return; - if (!identity->Verify (signedData, keyLen + 6, buf + offset)) return; - offset += identity->GetSignatureLen (); + } } // type specific part size_t s = 0; @@ -322,10 +310,10 @@ namespace data } if (!s) return; offset += s; - if (verifySignature || transientVerifier) + if (verifySignature || m_TransientVerifier) { // verify signature - bool verified = transientVerifier ? VerifySignature (transientVerifier, buf, len, offset) : + bool verified = m_TransientVerifier ? VerifySignature (m_TransientVerifier, buf, len, offset) : VerifySignature (identity, buf, len, offset); SetIsValid (verified); } @@ -443,33 +431,21 @@ namespace data uint16_t expires = bufbe16toh (buf + offset); offset += 2; // expires (seconds) SetExpirationTime ((timestamp + expires)*1000LL); // in milliseconds uint16_t flags = bufbe16toh (buf + offset); offset += 2; // flags - std::unique_ptr transientVerifier; if (flags & 0x0001) { // transient key - if (offset + 6 >= len) return; - const uint8_t * signedData = buf + offset; - uint32_t expiresTimestamp = bufbe32toh (buf + offset); offset += 4; // expires timestamp - if (expiresTimestamp < i2p::util::GetSecondsSinceEpoch ()) + m_TransientVerifier = ProcessOfflineSignature (blindedVerifier, buf, len, offset); + if (!m_TransientVerifier) { - LogPrint (eLogWarning, "LeaseSet2: transient key expired"); + LogPrint (eLogError, "LeaseSet2: offline signature failed"); return; - } - uint16_t keyType = bufbe16toh (buf + offset); offset += 2; - transientVerifier.reset (i2p::data::IdentityEx::CreateVerifier (keyType)); - if (!transientVerifier) return; - auto keyLen = transientVerifier->GetPublicKeyLen (); - if (offset + keyLen >= len) return; - transientVerifier->SetPublicKey (buf + offset); offset += keyLen; - if (offset + blindedVerifier->GetSignatureLen () >= len) return; - if (!blindedVerifier->Verify (signedData, keyLen + 6, buf + offset)) return; - offset += blindedVerifier->GetSignatureLen (); + } } // outer ciphertext if (offset + 2 > len) return; uint16_t lenOuterCiphertext = bufbe16toh (buf + offset); offset += 2 + lenOuterCiphertext; // verify signature - bool verified = transientVerifier ? VerifySignature (transientVerifier, buf, len, offset) : + bool verified = m_TransientVerifier ? VerifySignature (m_TransientVerifier, buf, len, offset) : VerifySignature (blindedVerifier, buf, len, offset); SetIsValid (verified); } diff --git a/libi2pd/LeaseSet.h b/libi2pd/LeaseSet.h index 3a9adae5..fbe3d7e4 100644 --- a/libi2pd/LeaseSet.h +++ b/libi2pd/LeaseSet.h @@ -8,6 +8,7 @@ #include #include "Identity.h" #include "Timestamp.h" +#include "I2PEndian.h" namespace i2p { @@ -77,7 +78,8 @@ namespace data bool operator== (const LeaseSet& other) const { return m_BufferLen == other.m_BufferLen && !memcmp (m_Buffer, other.m_Buffer, m_BufferLen); }; virtual uint8_t GetStoreType () const { return NETDB_STORE_TYPE_LEASESET; }; - + virtual std::shared_ptr GetTransientVerifier () const { return nullptr; }; + // implements RoutingDestination std::shared_ptr GetIdentity () const { return m_Identity; }; void Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx) const; @@ -128,8 +130,9 @@ namespace data LeaseSet2 (uint8_t storeType, const uint8_t * buf, size_t len, bool storeLeases = true); uint8_t GetStoreType () const { return m_StoreType; }; + std::shared_ptr GetTransientVerifier () const { return m_TransientVerifier; }; void Update (const uint8_t * buf, size_t len, bool verifySignature); - + // implements RoutingDestination void Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx) const; @@ -148,9 +151,31 @@ namespace data private: uint8_t m_StoreType; + std::shared_ptr m_TransientVerifier; std::shared_ptr m_Encryptor; // for standardLS2 }; + // also called from Streaming.cpp + template + std::shared_ptr ProcessOfflineSignature (const Verifier& verifier, const uint8_t * buf, size_t len, size_t& offset) + { + if (offset + 6 >= len) return nullptr; + const uint8_t * signedData = buf + offset; + uint32_t expiresTimestamp = bufbe32toh (buf + offset); offset += 4; // expires timestamp + if (expiresTimestamp < i2p::util::GetSecondsSinceEpoch ()) return nullptr; + uint16_t keyType = bufbe16toh (buf + offset); offset += 2; + std::shared_ptr transientVerifier (i2p::data::IdentityEx::CreateVerifier (keyType)); + if (!transientVerifier) return nullptr; + auto keyLen = transientVerifier->GetPublicKeyLen (); + if (offset + keyLen >= len) return nullptr; + transientVerifier->SetPublicKey (buf + offset); offset += keyLen; + if (offset + verifier->GetSignatureLen () >= len) return nullptr; + if (!verifier->Verify (signedData, keyLen + 6, buf + offset)) return nullptr; + offset += verifier->GetSignatureLen (); + return transientVerifier; + } + +//------------------------------------------------------------------------------------ class LocalLeaseSet { public: diff --git a/libi2pd/Streaming.cpp b/libi2pd/Streaming.cpp index 79fcbc02..1e10a6ad 100644 --- a/libi2pd/Streaming.cpp +++ b/libi2pd/Streaming.cpp @@ -288,33 +288,27 @@ namespace stream LogPrint (eLogInfo, "Streaming: offline signature without identity"); return false; } - const uint8_t * signedData = optionData; - uint32_t expiresTimestamp = bufbe32toh (optionData); optionData += 4; // expires timestamp - if (expiresTimestamp < i2p::util::GetSecondsSinceEpoch ()) + // if we have it in LeaseSet already we don't neet parse it again + if (m_RemoteLeaseSet) m_TransientVerifier = m_RemoteLeaseSet->GetTransientVerifier (); + if (m_TransientVerifier) { - LogPrint (eLogInfo, "Streaming: offline signature transient key expired"); - return false; + // skip option data + optionData += 6; // timestamp and key type + optionData += m_TransientVerifier->GetPublicKeyLen (); // public key + optionData += m_RemoteIdentity->GetSignatureLen (); // signature } - uint16_t keyType = bufbe16toh (optionData); optionData += 2; // key type - m_TransientVerifier.reset (i2p::data::IdentityEx::CreateVerifier (keyType)); - if (!m_TransientVerifier) - { - LogPrint (eLogInfo, "Streaming: Unknown transient key type ", (int)keyType); - return false; - } - auto keyLen = m_TransientVerifier->GetPublicKeyLen (); - if ((optionData - packet->GetOptionData ()) + keyLen + m_RemoteIdentity->GetSignatureLen () > optionSize) + else { - LogPrint (eLogInfo, "Streaming: Option data is too short ", (int)optionSize); - return false; + // transient key + size_t offset = 0; + m_TransientVerifier = i2p::data::ProcessOfflineSignature (m_RemoteIdentity, optionData, optionSize - (optionData - packet->GetOptionData ()), offset); + optionData += offset; + if (!m_TransientVerifier) + { + LogPrint (eLogError, "Streaming: offline signature failed"); + return false; + } } - m_TransientVerifier->SetPublicKey (optionData); optionData += keyLen; // key - if (!m_RemoteIdentity->Verify (signedData, keyLen + 6, optionData)) - { - LogPrint (eLogError, "Streaming: Transient key signature verification failed"); - return false; - } - optionData += m_RemoteIdentity->GetSignatureLen (); // signature } if (flags & PACKET_FLAG_SIGNATURE_INCLUDED) diff --git a/libi2pd/Streaming.h b/libi2pd/Streaming.h index 56f6b0e0..ba52464f 100644 --- a/libi2pd/Streaming.h +++ b/libi2pd/Streaming.h @@ -218,7 +218,7 @@ namespace stream bool m_IsAckSendScheduled; StreamingDestination& m_LocalDestination; std::shared_ptr m_RemoteIdentity; - std::unique_ptr m_TransientVerifier; // in case of offline key + std::shared_ptr m_TransientVerifier; // in case of offline key std::shared_ptr m_RemoteLeaseSet; std::shared_ptr m_RoutingSession; std::shared_ptr m_CurrentRemoteLease;