Skip to content

Commit

Permalink
create new ECIESX25519AEADRatchet session if not found
Browse files Browse the repository at this point in the history
  • Loading branch information
orignal committed Jan 17, 2020
1 parent 00cb15d commit 451c394
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 24 deletions.
44 changes: 24 additions & 20 deletions libi2pd/ECIESX25519AEADRatchetSession.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ namespace garlic
SHA256_Update (&ctx, buf, len);
SHA256_Final (m_H, &ctx);
}

bool ECIESX25519AEADRatchetSession::NewIncomingSession (const uint8_t * buf, size_t len, CloveHandler handleClove)
{
if (!GetOwner ()) return false;
Expand All @@ -52,15 +52,14 @@ namespace garlic
buf += 32; len -= 32;
MixHash (aepk, 32); // h = SHA256(h || aepk)

uint8_t sharedSecret[32], keyData[64];
uint8_t sharedSecret[32];
GetOwner ()->Decrypt (aepk, sharedSecret, nullptr); // x25519(bsk, aepk)
i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", keyData); // keydata = HKDF(chainKey, sharedSecret, "", 64)
memcpy (m_CK, keyData, 32); // chainKey = keydata[0:31]

i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK); // [chainKey, key] = HKDF(chainKey, sharedSecret, "", 64)

// decrypt flags/static
uint8_t nonce[12], fs[32];
memset (nonce, 0, 12); // n = 0
if (!i2p::crypto::AEADChaCha20Poly1305 (buf, 32, m_H, 32, keyData + 32, nonce, fs, 32, false)) // decrypt
if (!i2p::crypto::AEADChaCha20Poly1305 (buf, 32, m_H, 32, m_CK + 32, nonce, fs, 32, false)) // decrypt
{
LogPrint (eLogWarning, "Garlic: Flags/static section AEAD verification failed ");
return false;
Expand All @@ -75,14 +74,13 @@ namespace garlic
if (isStatic)
{
// static key, fs is apk
memcpy (m_StaticKey, fs, 32);
memcpy (m_RemoteStaticKey, fs, 32);
GetOwner ()->Decrypt (fs, sharedSecret, nullptr); // x25519(bsk, apk)
i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", keyData); // keydata = HKDF(chainKey, sharedSecret, "", 64)
memcpy (m_CK, keyData, 32); // chainKey = keydata[0:31]
i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK); // [chainKey, key] = HKDF(chainKey, sharedSecret, "", 64)
}
else // all zeros flags
htole64buf (nonce + 4, 1); // n = 1
if (!i2p::crypto::AEADChaCha20Poly1305 (buf, len - 16, m_H, 32, keyData + 32, nonce, payload.data (), len - 16, false)) // decrypt
if (!i2p::crypto::AEADChaCha20Poly1305 (buf, len - 16, m_H, 32, m_CK + 32, nonce, payload.data (), len - 16, false)) // decrypt
{
LogPrint (eLogWarning, "Garlic: Payload section AEAD verification failed");
return false;
Expand Down Expand Up @@ -132,7 +130,7 @@ namespace garlic

bool ECIESX25519AEADRatchetSession::NewOutgoingSessionMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen)
{
// we are Alice, bpk is m_StaticKey
// we are Alice, bpk is m_RemoteStaticKey
size_t offset = 0;
if (!i2p::crypto::GetElligator ()->Encode (m_EphemeralKeys.GetPublicKey (), out + offset))
{
Expand All @@ -142,26 +140,32 @@ namespace garlic
offset += 32;

// KDF1
MixHash (m_StaticKey, 32); // h = SHA256(h || bpk)
MixHash (m_RemoteStaticKey, 32); // h = SHA256(h || bpk)
MixHash (m_EphemeralKeys.GetPublicKey (), 32); // h = SHA256(h || aepk)
uint8_t sharedSecret[32], keyData[64];
m_EphemeralKeys.Agree (m_StaticKey, nullptr); // x25519(aesk, bpk)
i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", keyData); // keydata = HKDF(chainKey, sharedSecret, "", 64)
memcpy (m_CK, keyData, 32); // chainKey = keydata[0:31]
uint8_t sharedSecret[32];
m_EphemeralKeys.Agree (m_RemoteStaticKey, nullptr); // x25519(aesk, bpk)
i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK); // [chainKey, key] = HKDF(chainKey, sharedSecret, "", 64)
// encrypt static key section
uint8_t nonce[12];
memset (nonce, 0, 12); // n = 0
if (!i2p::crypto::AEADChaCha20Poly1305 (GetOwner ()->GetEncryptionPublicKey (), 32, m_H, 32, keyData + 32, nonce, out + offset, 48, true)) // encrypt
if (!i2p::crypto::AEADChaCha20Poly1305 (GetOwner ()->GetEncryptionPublicKey (), 32, m_H, 32, m_CK + 32, nonce, out + offset, 48, true)) // encrypt
{
LogPrint (eLogWarning, "Garlic: Static section AEAD encryption failed ");
return false;
}
MixHash (out + offset, 48); // h = SHA256(h || ciphertext)
offset += 48;

// KDF2
// TODO: // x25519 (ask, bpk)

GetOwner ()->Decrypt (m_RemoteStaticKey, sharedSecret, nullptr); // x25519 (ask, bpk)
i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK); // [chainKey, key] = HKDF(chainKey, sharedSecret, "", 64)
// encrypt payload
if (!i2p::crypto::AEADChaCha20Poly1305 (payload, len, m_H, 32, m_CK + 32, nonce, out + offset, len + 16, true)) // encrypt
{
LogPrint (eLogWarning, "Garlic: Payload section AEAD encryption failed");
return false;
}
MixHash (out + offset, len + 16); // h = SHA256(h || ciphertext)

return true;
}

Expand Down
6 changes: 4 additions & 2 deletions libi2pd/ECIESX25519AEADRatchetSession.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#ifndef ECIES_X25519_AEAD_RATCHET_SESSION_H__
#define ECIES_X25519_AEAD_RATCHET_SESSION_H__

#include <string.h>
#include <inttypes.h>
#include <functional>
#include "Identity.h"
Expand Down Expand Up @@ -34,7 +35,8 @@ namespace garlic
std::shared_ptr<I2NPMessage> WrapSingleMessage (std::shared_ptr<const I2NPMessage> msg);

bool NewIncomingSession (const uint8_t * buf, size_t len, CloveHandler handleClove);
const uint8_t * GetStaticKey () const { return m_StaticKey; };
const uint8_t * GetRemoteStaticKey () const { return m_RemoteStaticKey; }
void SetRemoteStaticKey (const uint8_t * key) { memcpy (m_RemoteStaticKey, key, 32); }

private:

Expand All @@ -46,7 +48,7 @@ namespace garlic

private:

uint8_t m_H[32], m_CK[32], m_StaticKey[32];
uint8_t m_H[32], m_CK[64] /* [chainkey, key] */, m_RemoteStaticKey[32];
i2p::crypto::X25519Keys m_EphemeralKeys;
};
}
Expand Down
9 changes: 7 additions & 2 deletions libi2pd/Garlic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -664,7 +664,12 @@ namespace garlic
auto it = m_ECIESx25519Sessions.find (staticKey);
if (it != m_ECIESx25519Sessions.end ())
session = it->second;
// TODO: Alice
if (!session)
{
session = std::make_shared<ECIESX25519AEADRatchetSession> (this);
session->SetRemoteStaticKey (staticKey);
m_ECIESx25519Sessions.emplace (staticKey, session);
}
return session;
}
else
Expand Down Expand Up @@ -860,7 +865,7 @@ namespace garlic
if (session->NewIncomingSession (buf, len, std::bind (&GarlicDestination::HandleECIESx25519GarlicClove,
this, std::placeholders::_1, std::placeholders::_2)))
{
m_ECIESx25519Sessions.emplace (session->GetStaticKey (), session);
m_ECIESx25519Sessions.emplace (session->GetRemoteStaticKey (), session);
}
else
LogPrint (eLogError, "Garlic: can't decrypt ECIES-X25519-AEAD-Ratchet new session");
Expand Down

0 comments on commit 451c394

Please sign in to comment.