Browse Source

common code for offline signatures

pull/1295/head
orignal 5 years ago
parent
commit
2cac9b03ff
  1. 42
      libi2pd/LeaseSet.cpp
  2. 25
      libi2pd/LeaseSet.h
  3. 40
      libi2pd/Streaming.cpp
  4. 2
      libi2pd/Streaming.h

42
libi2pd/LeaseSet.cpp

@ -285,27 +285,15 @@ namespace data
uint16_t expires = bufbe16toh (buf + offset); offset += 2; // expires (seconds) uint16_t expires = bufbe16toh (buf + offset); offset += 2; // expires (seconds)
SetExpirationTime ((timestamp + expires)*1000LL); // in milliseconds SetExpirationTime ((timestamp + expires)*1000LL); // in milliseconds
uint16_t flags = bufbe16toh (buf + offset); offset += 2; // flags uint16_t flags = bufbe16toh (buf + offset); offset += 2; // flags
std::unique_ptr<i2p::crypto::Verifier> transientVerifier;
if (flags & 0x0001) if (flags & 0x0001)
{ {
// transient key // transient key
if (offset + 6 >= len) return; m_TransientVerifier = ProcessOfflineSignature (identity, buf, len, offset);
const uint8_t * signedData = buf + offset; if (!m_TransientVerifier)
uint32_t expiresTimestamp = bufbe32toh (buf + offset); offset += 4; // expires timestamp
if (expiresTimestamp < i2p::util::GetSecondsSinceEpoch ())
{ {
LogPrint (eLogWarning, "LeaseSet2: transient key expired"); LogPrint (eLogError, "LeaseSet2: offline signature failed");
return; 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 // type specific part
size_t s = 0; size_t s = 0;
@ -322,10 +310,10 @@ namespace data
} }
if (!s) return; if (!s) return;
offset += s; offset += s;
if (verifySignature || transientVerifier) if (verifySignature || m_TransientVerifier)
{ {
// verify signature // 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); VerifySignature (identity, buf, len, offset);
SetIsValid (verified); SetIsValid (verified);
} }
@ -443,33 +431,21 @@ namespace data
uint16_t expires = bufbe16toh (buf + offset); offset += 2; // expires (seconds) uint16_t expires = bufbe16toh (buf + offset); offset += 2; // expires (seconds)
SetExpirationTime ((timestamp + expires)*1000LL); // in milliseconds SetExpirationTime ((timestamp + expires)*1000LL); // in milliseconds
uint16_t flags = bufbe16toh (buf + offset); offset += 2; // flags uint16_t flags = bufbe16toh (buf + offset); offset += 2; // flags
std::unique_ptr<i2p::crypto::Verifier> transientVerifier;
if (flags & 0x0001) if (flags & 0x0001)
{ {
// transient key // transient key
if (offset + 6 >= len) return; m_TransientVerifier = ProcessOfflineSignature (blindedVerifier, buf, len, offset);
const uint8_t * signedData = buf + offset; if (!m_TransientVerifier)
uint32_t expiresTimestamp = bufbe32toh (buf + offset); offset += 4; // expires timestamp
if (expiresTimestamp < i2p::util::GetSecondsSinceEpoch ())
{ {
LogPrint (eLogWarning, "LeaseSet2: transient key expired"); LogPrint (eLogError, "LeaseSet2: offline signature failed");
return; 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 // outer ciphertext
if (offset + 2 > len) return; if (offset + 2 > len) return;
uint16_t lenOuterCiphertext = bufbe16toh (buf + offset); offset += 2 + lenOuterCiphertext; uint16_t lenOuterCiphertext = bufbe16toh (buf + offset); offset += 2 + lenOuterCiphertext;
// verify signature // 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); VerifySignature (blindedVerifier, buf, len, offset);
SetIsValid (verified); SetIsValid (verified);
} }

25
libi2pd/LeaseSet.h

@ -8,6 +8,7 @@
#include <memory> #include <memory>
#include "Identity.h" #include "Identity.h"
#include "Timestamp.h" #include "Timestamp.h"
#include "I2PEndian.h"
namespace i2p namespace i2p
{ {
@ -77,6 +78,7 @@ namespace data
bool operator== (const LeaseSet& other) const bool operator== (const LeaseSet& other) const
{ return m_BufferLen == other.m_BufferLen && !memcmp (m_Buffer, other.m_Buffer, m_BufferLen); }; { 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 uint8_t GetStoreType () const { return NETDB_STORE_TYPE_LEASESET; };
virtual std::shared_ptr<const i2p::crypto::Verifier> GetTransientVerifier () const { return nullptr; };
// implements RoutingDestination // implements RoutingDestination
std::shared_ptr<const IdentityEx> GetIdentity () const { return m_Identity; }; std::shared_ptr<const IdentityEx> GetIdentity () const { return m_Identity; };
@ -128,6 +130,7 @@ namespace data
LeaseSet2 (uint8_t storeType, const uint8_t * buf, size_t len, bool storeLeases = true); LeaseSet2 (uint8_t storeType, const uint8_t * buf, size_t len, bool storeLeases = true);
uint8_t GetStoreType () const { return m_StoreType; }; uint8_t GetStoreType () const { return m_StoreType; };
std::shared_ptr<const i2p::crypto::Verifier> GetTransientVerifier () const { return m_TransientVerifier; };
void Update (const uint8_t * buf, size_t len, bool verifySignature); void Update (const uint8_t * buf, size_t len, bool verifySignature);
// implements RoutingDestination // implements RoutingDestination
@ -148,9 +151,31 @@ namespace data
private: private:
uint8_t m_StoreType; uint8_t m_StoreType;
std::shared_ptr<i2p::crypto::Verifier> m_TransientVerifier;
std::shared_ptr<i2p::crypto::CryptoKeyEncryptor> m_Encryptor; // for standardLS2 std::shared_ptr<i2p::crypto::CryptoKeyEncryptor> m_Encryptor; // for standardLS2
}; };
// also called from Streaming.cpp
template<typename Verifier>
std::shared_ptr<i2p::crypto::Verifier> 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<i2p::crypto::Verifier> 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 class LocalLeaseSet
{ {
public: public:

40
libi2pd/Streaming.cpp

@ -288,33 +288,27 @@ namespace stream
LogPrint (eLogInfo, "Streaming: offline signature without identity"); LogPrint (eLogInfo, "Streaming: offline signature without identity");
return false; return false;
} }
const uint8_t * signedData = optionData; // if we have it in LeaseSet already we don't neet parse it again
uint32_t expiresTimestamp = bufbe32toh (optionData); optionData += 4; // expires timestamp if (m_RemoteLeaseSet) m_TransientVerifier = m_RemoteLeaseSet->GetTransientVerifier ();
if (expiresTimestamp < i2p::util::GetSecondsSinceEpoch ()) if (m_TransientVerifier)
{ {
LogPrint (eLogInfo, "Streaming: offline signature transient key expired"); // skip option data
return false; optionData += 6; // timestamp and key type
} optionData += m_TransientVerifier->GetPublicKeyLen (); // public key
uint16_t keyType = bufbe16toh (optionData); optionData += 2; // key type optionData += m_RemoteIdentity->GetSignatureLen (); // signature
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 (); else
if ((optionData - packet->GetOptionData ()) + keyLen + m_RemoteIdentity->GetSignatureLen () > optionSize)
{
LogPrint (eLogInfo, "Streaming: Option data is too short ", (int)optionSize);
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"); // transient key
return false; 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;
}
} }
optionData += m_RemoteIdentity->GetSignatureLen (); // signature
} }
if (flags & PACKET_FLAG_SIGNATURE_INCLUDED) if (flags & PACKET_FLAG_SIGNATURE_INCLUDED)

2
libi2pd/Streaming.h

@ -218,7 +218,7 @@ namespace stream
bool m_IsAckSendScheduled; bool m_IsAckSendScheduled;
StreamingDestination& m_LocalDestination; StreamingDestination& m_LocalDestination;
std::shared_ptr<const i2p::data::IdentityEx> m_RemoteIdentity; std::shared_ptr<const i2p::data::IdentityEx> m_RemoteIdentity;
std::unique_ptr<i2p::crypto::Verifier> m_TransientVerifier; // in case of offline key std::shared_ptr<const i2p::crypto::Verifier> m_TransientVerifier; // in case of offline key
std::shared_ptr<const i2p::data::LeaseSet> m_RemoteLeaseSet; std::shared_ptr<const i2p::data::LeaseSet> m_RemoteLeaseSet;
std::shared_ptr<i2p::garlic::GarlicRoutingSession> m_RoutingSession; std::shared_ptr<i2p::garlic::GarlicRoutingSession> m_RoutingSession;
std::shared_ptr<const i2p::data::Lease> m_CurrentRemoteLease; std::shared_ptr<const i2p::data::Lease> m_CurrentRemoteLease;

Loading…
Cancel
Save