mirror of
https://github.com/PurpleI2P/i2pd
synced 2024-11-10 00:00:29 +03:00
new session reply
This commit is contained in:
parent
80373623cd
commit
62e39ddfbd
@ -34,7 +34,16 @@ namespace garlic
|
||||
SHA256_Update (&ctx, buf, len);
|
||||
SHA256_Final (m_H, &ctx);
|
||||
}
|
||||
|
||||
|
||||
void ECIESX25519AEADRatchetSession::DHInitialize (const uint8_t * rootKey, const uint8_t * k, uint8_t * nextRootKey, uint8_t * ck)
|
||||
{
|
||||
uint8_t keydata[64];
|
||||
i2p::crypto::HKDF (rootKey, k, 32, "KDFDHRatchetStep", keydata); // keydata = HKDF(rootKey, k, "KDFDHRatchetStep", 64)
|
||||
memcpy (nextRootKey, keydata, 32); // nextRootKey = keydata[0:31]
|
||||
i2p::crypto::HKDF (keydata + 32, nullptr, 0, "TagAndKeyGenKeys", ck);
|
||||
// ck = [sessTag_ck, symmKey_ck] = HKDF(keydata[32:63], ZEROLEN, "TagAndKeyGenKeys", 64)
|
||||
}
|
||||
|
||||
bool ECIESX25519AEADRatchetSession::NewIncomingSession (const uint8_t * buf, size_t len, CloveHandler handleClove)
|
||||
{
|
||||
if (!GetOwner ()) return false;
|
||||
@ -165,11 +174,66 @@ namespace garlic
|
||||
LogPrint (eLogWarning, "Garlic: Payload section AEAD encryption failed");
|
||||
return false;
|
||||
}
|
||||
MixHash (out + offset, len + 16); // h = SHA256(h || ciphertext)
|
||||
MixHash (out + offset, 16); // h = SHA256(h || ciphertext)
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ECIESX25519AEADRatchetSession::NewSessionReplyMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen)
|
||||
{
|
||||
m_EphemeralKeys.GenerateKeys ();
|
||||
// we are Bob
|
||||
uint8_t tagsetKey[32], ck[64];
|
||||
i2p::crypto::HKDF (m_CK, nullptr, 0, "SessionReplyTags", tagsetKey, 32); // tagsetKey = HKDF(chainKey, ZEROLEN, "SessionReplyTags", 32)
|
||||
DHInitialize (m_CK, tagsetKey, tagsetKey, ck); // tagset_nsr = DH_INITIALIZE(chainKey, tagsetKey), nextRootKey?
|
||||
// Session Tag Ratchet
|
||||
uint8_t keydata[64];
|
||||
i2p::crypto::HKDF (ck, nullptr, 0, "STInitialization", keydata); // keydata = HKDF(sessTag_ck, ZEROLEN, "STInitialization", 64)
|
||||
// sessTag_chainKey = keydata[0:31], SESSTAG_CONSTANT = keydata[32:63]
|
||||
i2p::crypto::HKDF (keydata, keydata + 32, 32, "SessionTagKeyGen", keydata); // keydata_0 = HKDF(sessTag_chainkey, SESSTAG_CONSTANT, "SessionTagKeyGen", 64)
|
||||
// tag_0 = keydata_0[32:39]
|
||||
uint8_t * tag = keydata + 32;
|
||||
|
||||
size_t offset = 0;
|
||||
memcpy (out + offset, tag, 8);
|
||||
offset += 8;
|
||||
if (!i2p::crypto::GetElligator ()->Encode (m_EphemeralKeys.GetPublicKey (), out + offset)) // bepk
|
||||
{
|
||||
LogPrint (eLogError, "Garlic: Can't encode elligator");
|
||||
return false;
|
||||
}
|
||||
offset += 32;
|
||||
// KDF for Reply Key Section
|
||||
MixHash (tag, 8); // h = SHA256(h || tag)
|
||||
MixHash (m_EphemeralKeys.GetPublicKey (), 32); // h = SHA256(h || bepk)
|
||||
uint8_t sharedSecret[32];
|
||||
m_EphemeralKeys.Agree (m_RemoteStaticKey, sharedSecret); // sharedSecret = x25519(besk, aepk)
|
||||
i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK); // [chainKey, key] = HKDF(chainKey, sharedSecret, "", 64)
|
||||
uint8_t nonce[12];
|
||||
memset (nonce, 0, 12); // n = 0
|
||||
// calulate hash for zero length
|
||||
if (!i2p::crypto::AEADChaCha20Poly1305 (sharedSecret /* can be anything */, 0, m_H, 32, m_CK + 32, nonce, out + offset, 16, true)) // encrypt, ciphertext = ENCRYPT(k, n, ZEROLEN, ad)
|
||||
{
|
||||
LogPrint (eLogWarning, "Garlic: Reply key section AEAD encryption failed");
|
||||
return false;
|
||||
}
|
||||
MixHash (out + offset, 16); // h = SHA256(h || ciphertext)
|
||||
out += 16;
|
||||
// KDF for payload
|
||||
i2p::crypto::HKDF (m_CK, nullptr, 0, "STInitialization", keydata); // keydata = HKDF(chainKey, ZEROLEN, "", 64)
|
||||
// k_ab = keydata[0:31], k_ba = keydata[32:63]
|
||||
// tagset_ab = DH_INITIALIZE(chainKey, k_ab), tagset_ba = DH_INITIALIZE(chainKey, k_ba)
|
||||
i2p::crypto::HKDF (keydata + 32, nullptr, 0, "AttachPayloadKDF", keydata, 32); // k = HKDF(k_ba, ZEROLEN, "AttachPayloadKDF", 32)
|
||||
// encrypt payload
|
||||
if (!i2p::crypto::AEADChaCha20Poly1305 (payload, len, m_H, 32, keydata, nonce, out + offset, len + 16, true)) // encrypt
|
||||
{
|
||||
LogPrint (eLogWarning, "Garlic: Payload section AEAD encryption failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::shared_ptr<I2NPMessage> ECIESX25519AEADRatchetSession::WrapSingleMessage (std::shared_ptr<const I2NPMessage> msg)
|
||||
{
|
||||
auto m = NewI2NPMessage ();
|
||||
@ -185,6 +249,11 @@ namespace garlic
|
||||
return nullptr;
|
||||
len += 96;
|
||||
break;
|
||||
case eSessionStateNewSessionReceived:
|
||||
if (!NewSessionReplyMessage (payload.data (), payload.size (), buf, m->maxLen))
|
||||
return nullptr;
|
||||
len += 72;
|
||||
break;
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -48,10 +48,12 @@ namespace garlic
|
||||
private:
|
||||
|
||||
void MixHash (const uint8_t * buf, size_t len);
|
||||
void DHInitialize (const uint8_t * rootKey, const uint8_t * k, uint8_t * nextRootKey, uint8_t * ck); // ck is 64 buytes
|
||||
|
||||
void HandlePayload (const uint8_t * buf, size_t len, CloveHandler& handleClove);
|
||||
|
||||
bool NewOutgoingSessionMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen);
|
||||
bool NewSessionReplyMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen);
|
||||
std::vector<uint8_t> CreatePayload (std::shared_ptr<const I2NPMessage> msg);
|
||||
|
||||
private:
|
||||
|
Loading…
Reference in New Issue
Block a user