mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2025-01-22 21:37:17 +01:00
extract client auth data
This commit is contained in:
parent
485f105555
commit
14f0d6d26b
|
@ -1,7 +1,9 @@
|
|||
#include <string.h>
|
||||
#include <unordered_map>
|
||||
#include "I2PEndian.h"
|
||||
#include "Crypto.h"
|
||||
#include "Log.h"
|
||||
#include "Tag.h"
|
||||
#include "Timestamp.h"
|
||||
#include "NetDb.hpp"
|
||||
#include "Tunnel.h"
|
||||
|
@ -497,17 +499,26 @@ namespace data
|
|||
std::vector<uint8_t> outerPlainText (lenOuterPlaintext);
|
||||
i2p::crypto::ChaCha20 (outerCiphertext + 32, lenOuterPlaintext, keys, keys + 32, outerPlainText.data ());
|
||||
// inner key
|
||||
// innerInput = authCookie || subcredential || publishedTimestamp, TODO: non-empty authCookie
|
||||
// innerInput = authCookie || subcredential || publishedTimestamp
|
||||
// innerSalt = innerCiphertext[0:32]
|
||||
// keys = HKDF(innerSalt, innerInput, "ELS2_L2K", 44)
|
||||
// skip 1 byte flags
|
||||
i2p::crypto::HKDF (outerPlainText.data () + 1, subcredential, 36, "ELS2_L2K", keys); // no authCookie
|
||||
uint8_t innerInput[68];
|
||||
size_t authDataLen = ExtractClientAuthData (outerPlainText.data (), lenOuterPlaintext, nullptr /*TODO*/, subcredential, innerInput);
|
||||
if (authDataLen > 0)
|
||||
{
|
||||
memcpy (innerInput + 32, subcredential, 36);
|
||||
i2p::crypto::HKDF (outerPlainText.data () + 1, innerInput, 68, "ELS2_L2K", keys);
|
||||
}
|
||||
else
|
||||
// no authData presented, innerInput = subcredential || publishedTimestamp
|
||||
// skip 1 byte flags
|
||||
i2p::crypto::HKDF (outerPlainText.data () + 1, subcredential, 36, "ELS2_L2K", keys); // no authCookie
|
||||
// decrypt Layer 2
|
||||
// innerKey = keys[0:31]
|
||||
// innerIV = keys[32:43]
|
||||
size_t lenInnerPlaintext = lenOuterPlaintext - 32 - 1;
|
||||
size_t lenInnerPlaintext = lenOuterPlaintext - 32 - 1 - authDataLen;
|
||||
std::vector<uint8_t> innerPlainText (lenInnerPlaintext);
|
||||
i2p::crypto::ChaCha20 (outerPlainText.data () + 32 + 1, lenInnerPlaintext, keys, keys + 32, innerPlainText.data ());
|
||||
i2p::crypto::ChaCha20 (outerPlainText.data () + 32 + 1 + authDataLen, lenInnerPlaintext, keys, keys + 32, innerPlainText.data ());
|
||||
if (innerPlainText[0] == NETDB_STORE_TYPE_STANDARD_LEASESET2 || innerPlainText[0] == NETDB_STORE_TYPE_META_LEASESET2)
|
||||
{
|
||||
// override store type and buffer
|
||||
|
@ -521,6 +532,49 @@ namespace data
|
|||
}
|
||||
}
|
||||
|
||||
size_t LeaseSet2::ExtractClientAuthData (const uint8_t * buf, size_t len, const uint8_t * secret, const uint8_t * subcredential, uint8_t * authCookie) const
|
||||
{
|
||||
size_t offset = 0;
|
||||
uint8_t flag = buf[offset]; offset++; // flag
|
||||
if (flag & 0x01) // client auth
|
||||
{
|
||||
if (flag & 0x0E) // PSK, bits 3-1 are set to 1
|
||||
{
|
||||
const uint8_t * authSalt = buf + offset; authSalt += 32; // authSalt
|
||||
uint16_t numClients = bufbe16toh (buf + offset); offset += 2; // clients
|
||||
std::unordered_map<uint64_t, i2p::data::Tag<32> > authClients;
|
||||
for (int i = 0; i < numClients; i++)
|
||||
{
|
||||
uint64_t clientID = buf64toh (buf + offset); offset += 8; // clientID_i, don't care about endianess
|
||||
authClients.emplace (clientID, buf + offset);
|
||||
offset += 32; // clientCookie_i
|
||||
}
|
||||
// calculate authCookie
|
||||
if (secret)
|
||||
{
|
||||
uint8_t authInput[68];
|
||||
memcpy (authInput, secret, 32);
|
||||
memcpy (authInput, subcredential, 36);
|
||||
uint8_t okm[64]; // 52 actual data
|
||||
i2p::crypto::HKDF (authSalt, authInput, 68, "ELS2PSKA", okm);
|
||||
uint64_t clientID = buf64toh (okm + 44); // clientID_i = okm[44:51]
|
||||
auto it = authClients.find (clientID);
|
||||
if (it != authClients.end ())
|
||||
// clientKey_i = okm[0:31]
|
||||
// clientIV_i = okm[32:43]
|
||||
i2p::crypto::ChaCha20 (it->second, 32, okm, okm + 32, authCookie);
|
||||
else
|
||||
LogPrint (eLogError, "LeaseSet2: Client cookie for clientID_i ", clientID, " not found");
|
||||
}
|
||||
else
|
||||
LogPrint (eLogError, "LeaseSet2: Can't calculate authCookie: psk_i is not provided");
|
||||
}
|
||||
else
|
||||
LogPrint (eLogError, "LeaseSet2: unknown client auth type ", (int)flag);
|
||||
}
|
||||
return offset - 1;
|
||||
}
|
||||
|
||||
void LeaseSet2::Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx) const
|
||||
{
|
||||
auto encryptor = m_Encryptor; // TODO: atomic
|
||||
|
|
|
@ -156,6 +156,7 @@ namespace data
|
|||
bool VerifySignature (Verifier& verifier, const uint8_t * buf, size_t len, size_t signatureOffset);
|
||||
|
||||
uint64_t ExtractTimestamp (const uint8_t * buf, size_t len) const;
|
||||
size_t ExtractClientAuthData (const uint8_t * buf, size_t len, const uint8_t * secret, const uint8_t * subcredential, uint8_t * authCookie) const; // subcredential is subcredential + timestamp, return length of autData without flag
|
||||
|
||||
private:
|
||||
|
||||
|
|
Loading…
Reference in a new issue