diff --git a/libi2pd/LeaseSet.cpp b/libi2pd/LeaseSet.cpp index d8030a45..e0258831 100644 --- a/libi2pd/LeaseSet.cpp +++ b/libi2pd/LeaseSet.cpp @@ -907,5 +907,21 @@ namespace data // store hash m_StoreHash = blindedKey.GetStoreHash (); } + + LocalEncryptedLeaseSet2::LocalEncryptedLeaseSet2 (std::shared_ptr identity, const uint8_t * buf, size_t len): + LocalLeaseSet2 (NETDB_STORE_TYPE_ENCRYPTED_LEASESET2, identity, buf, len) + { + // fill inner LeaseSet2 + auto blindedKey = std::make_shared(identity); + i2p::data::LeaseSet2 ls (buf, len, blindedKey); // inner layer + if (ls.IsValid ()) + { + m_InnerLeaseSet = std::make_shared(ls.GetStoreType (), identity, ls.GetBuffer (), ls.GetBufferLen ()); + m_StoreHash = blindedKey->GetStoreHash (); + } + else + LogPrint (eLogError, "LeaseSet2: couldn't extract inner layer"); + } + } } diff --git a/libi2pd/LeaseSet.h b/libi2pd/LeaseSet.h index 7fd4eb90..ce330ba7 100644 --- a/libi2pd/LeaseSet.h +++ b/libi2pd/LeaseSet.h @@ -254,7 +254,7 @@ namespace data LocalLeaseSet2 (uint8_t storeType, const i2p::data::PrivateKeys& keys, uint16_t keyType, uint16_t keyLen, const uint8_t * encryptionPublicKey, std::vector > tunnels); - LocalLeaseSet2 (uint8_t storeType, std::shared_ptr identity, const uint8_t * buf, size_t len); + LocalLeaseSet2 (uint8_t storeType, std::shared_ptr identity, const uint8_t * buf, size_t len); // from I2CP virtual ~LocalLeaseSet2 () { delete[] m_Buffer; }; @@ -279,6 +279,8 @@ namespace data LocalEncryptedLeaseSet2 (std::shared_ptr ls, const i2p::data::PrivateKeys& keys, i2p::data::SigningKeyType blindedKeyType = i2p::data::SIGNING_KEY_TYPE_REDDSA_SHA512_ED25519); + LocalEncryptedLeaseSet2 (std::shared_ptr identity, const uint8_t * buf, size_t len); // from I2CP + const IdentHash& GetStoreHash () const { return m_StoreHash; }; std::shared_ptr GetInnerLeaseSet () const { return m_InnerLeaseSet; }; diff --git a/libi2pd_client/I2CP.cpp b/libi2pd_client/I2CP.cpp index dbcb3a6c..78190c89 100644 --- a/libi2pd_client/I2CP.cpp +++ b/libi2pd_client/I2CP.cpp @@ -70,7 +70,9 @@ namespace client void I2CPDestination::LeaseSet2Created (uint8_t storeType, const uint8_t * buf, size_t len) { - auto ls = std::make_shared (storeType, m_Identity, buf, len); + auto ls = (storeType == i2p::data::NETDB_STORE_TYPE_ENCRYPTED_LEASESET2) ? + std::make_shared (m_Identity, buf, len): + std::make_shared (storeType, m_Identity, buf, len); ls->SetExpirationTime (m_LeaseSetExpirationTime); SetLeaseSet (ls); } @@ -528,21 +530,35 @@ namespace client if (m_Destination) { uint8_t storeType = buf[offset]; offset++; // store type - // TODO: parse LS2 and obtain correct private keys lengths - size_t signingPrivateKeyLength = 0, encryptionPrivateKeyLength = 0; - if (storeType != i2p::data::NETDB_STORE_TYPE_META_LEASESET2) // no private keys for meta + i2p::data::LeaseSet2 ls (storeType, buf + offset, len - offset); // outer layer only for encrypted + if (!ls.IsValid ()) { - signingPrivateKeyLength = m_Destination->GetIdentity ()->GetSigningPrivateKeyLen (); // no offline keys - encryptionPrivateKeyLength = 256; // ElGamal only - if (len < offset + signingPrivateKeyLength + encryptionPrivateKeyLength) + LogPrint (eLogError, "I2CP: invalid LeaseSet2 of type ", storeType); + return; + } + offset += ls.GetBufferLen (); + // private keys + int numPrivateKeys = buf[offset]; offset++; + uint16_t currentKeyType = 0; + const uint8_t * currentKey = nullptr; + for (int i = 0; i < numPrivateKeys; i++) + { + if (offset + 4 > len) return; + uint16_t keyType = bufbe16toh (buf + offset); offset += 2; // encryption type + uint16_t keyLen = bufbe16toh (buf + offset); offset += 2; // private key length + if (offset + keyLen > len) return; + if (keyType > currentKeyType) { - LogPrint (eLogError, "I2CP: CreateLeaseSet2 message is too short ", len); - return; + currentKeyType = keyType; + currentKey = buf + offset; } - m_Destination->SetEncryptionPrivateKey (buf + len - encryptionPrivateKeyLength); - // ignore signing private key - } - m_Destination->LeaseSet2Created (storeType, buf + offset, len - offset - signingPrivateKeyLength - encryptionPrivateKeyLength); + offset += keyLen; + } + // TODO: support multiple keys + if (currentKey) + m_Destination->SetEncryptionPrivateKey (currentKey); + + m_Destination->LeaseSet2Created (storeType, ls.GetBuffer (), ls.GetBufferLen ()); } } else diff --git a/libi2pd_client/I2CP.h b/libi2pd_client/I2CP.h index 7a89a24a..0d235161 100644 --- a/libi2pd_client/I2CP.h +++ b/libi2pd_client/I2CP.h @@ -36,7 +36,7 @@ namespace client const uint8_t I2CP_DESTROY_SESSION_MESSAGE = 3; const uint8_t I2CP_REQUEST_VARIABLE_LEASESET_MESSAGE = 37; const uint8_t I2CP_CREATE_LEASESET_MESSAGE = 4; - const uint8_t I2CP_CREATE_LEASESET2_MESSAGE = 40; + const uint8_t I2CP_CREATE_LEASESET2_MESSAGE = 41; const uint8_t I2CP_SEND_MESSAGE_MESSAGE = 5; const uint8_t I2CP_SEND_MESSAGE_EXPIRES_MESSAGE = 36; const uint8_t I2CP_MESSAGE_PAYLOAD_MESSAGE = 31;