Browse Source

indetification of incoming garlic messages

pull/1515/head
orignal 5 years ago
parent
commit
2fc16ee13d
  1. 4
      libi2pd/Destination.cpp
  2. 7
      libi2pd/Destination.h
  3. 12
      libi2pd/ECIESX25519AEADRatchetSession.cpp
  4. 24
      libi2pd/Garlic.cpp
  5. 6
      libi2pd/Identity.cpp
  6. 2
      libi2pd/Identity.h

4
libi2pd/Destination.cpp

@ -824,8 +824,8 @@ namespace client
i2p::data::CryptoKeyType LeaseSetDestination::GetPreferredCryptoType () const i2p::data::CryptoKeyType LeaseSetDestination::GetPreferredCryptoType () const
{ {
if (SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RARCHET)) if (SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET))
return i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RARCHET; return i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET;
return i2p::data::CRYPTO_KEY_TYPE_ELGAMAL; return i2p::data::CRYPTO_KEY_TYPE_ELGAMAL;
} }

7
libi2pd/Destination.h

@ -229,7 +229,12 @@ namespace client
// implements LocalDestination // implements LocalDestination
bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, i2p::data::CryptoKeyType preferredCrypto) const; bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, i2p::data::CryptoKeyType preferredCrypto) const;
std::shared_ptr<const i2p::data::IdentityEx> GetIdentity () const { return m_Keys.GetPublic (); }; std::shared_ptr<const i2p::data::IdentityEx> GetIdentity () const { return m_Keys.GetPublic (); };
bool SupportsEncryptionType (i2p::data::CryptoKeyType keyType) const { return m_EncryptionKeyType == keyType; }; bool SupportsEncryptionType (i2p::data::CryptoKeyType keyType) const
{
return keyType == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET ?
m_EncryptionKeyType == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET :
m_EncryptionKeyType < i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET;
}
const uint8_t * GetEncryptionPublicKey (i2p::data::CryptoKeyType keyType) const { return m_EncryptionPublicKey; }; const uint8_t * GetEncryptionPublicKey (i2p::data::CryptoKeyType keyType) const { return m_EncryptionPublicKey; };
protected: protected:

12
libi2pd/ECIESX25519AEADRatchetSession.cpp

@ -127,7 +127,7 @@ namespace garlic
if (!GetOwner ()) return false; if (!GetOwner ()) return false;
// we are Bob // we are Bob
// KDF1 // KDF1
MixHash (GetOwner ()->GetEncryptionPublicKey (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RARCHET), 32); // h = SHA256(h || bpk) MixHash (GetOwner ()->GetEncryptionPublicKey (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET), 32); // h = SHA256(h || bpk)
if (!i2p::crypto::GetElligator ()->Decode (buf, m_Aepk)) if (!i2p::crypto::GetElligator ()->Decode (buf, m_Aepk))
{ {
@ -138,7 +138,7 @@ namespace garlic
MixHash (m_Aepk, 32); // h = SHA256(h || aepk) MixHash (m_Aepk, 32); // h = SHA256(h || aepk)
uint8_t sharedSecret[32]; uint8_t sharedSecret[32];
GetOwner ()->Decrypt (m_Aepk, sharedSecret, nullptr, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RARCHET); // x25519(bsk, aepk) GetOwner ()->Decrypt (m_Aepk, sharedSecret, nullptr, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET); // x25519(bsk, aepk)
i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK); // [chainKey, key] = HKDF(chainKey, sharedSecret, "", 64) i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK); // [chainKey, key] = HKDF(chainKey, sharedSecret, "", 64)
// decrypt flags/static // decrypt flags/static
@ -160,7 +160,7 @@ namespace garlic
{ {
// static key, fs is apk // static key, fs is apk
memcpy (m_RemoteStaticKey, fs, 32); memcpy (m_RemoteStaticKey, fs, 32);
GetOwner ()->Decrypt (fs, sharedSecret, nullptr, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RARCHET); // x25519(bsk, apk) GetOwner ()->Decrypt (fs, sharedSecret, nullptr, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET); // x25519(bsk, apk)
i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK); // [chainKey, key] = HKDF(chainKey, sharedSecret, "", 64) i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK); // [chainKey, key] = HKDF(chainKey, sharedSecret, "", 64)
} }
else // all zeros flags else // all zeros flags
@ -242,7 +242,7 @@ namespace garlic
// encrypt static key section // encrypt static key section
uint8_t nonce[12]; uint8_t nonce[12];
CreateNonce (0, nonce); CreateNonce (0, nonce);
if (!i2p::crypto::AEADChaCha20Poly1305 (GetOwner ()->GetEncryptionPublicKey (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RARCHET), 32, m_H, 32, m_CK + 32, nonce, out + offset, 48, true)) // encrypt if (!i2p::crypto::AEADChaCha20Poly1305 (GetOwner ()->GetEncryptionPublicKey (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET), 32, m_H, 32, m_CK + 32, nonce, out + offset, 48, true)) // encrypt
{ {
LogPrint (eLogWarning, "Garlic: Static section AEAD encryption failed "); LogPrint (eLogWarning, "Garlic: Static section AEAD encryption failed ");
return false; return false;
@ -250,7 +250,7 @@ namespace garlic
MixHash (out + offset, 48); // h = SHA256(h || ciphertext) MixHash (out + offset, 48); // h = SHA256(h || ciphertext)
offset += 48; offset += 48;
// KDF2 // KDF2
GetOwner ()->Decrypt (m_RemoteStaticKey, sharedSecret, nullptr, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RARCHET); // x25519 (ask, bpk) GetOwner ()->Decrypt (m_RemoteStaticKey, sharedSecret, nullptr, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET); // x25519 (ask, bpk)
i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK); // [chainKey, key] = HKDF(chainKey, sharedSecret, "", 64) i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK); // [chainKey, key] = HKDF(chainKey, sharedSecret, "", 64)
// encrypt payload // encrypt payload
if (!i2p::crypto::AEADChaCha20Poly1305 (payload, len, m_H, 32, m_CK + 32, nonce, out + offset, len + 16, true)) // encrypt if (!i2p::crypto::AEADChaCha20Poly1305 (payload, len, m_H, 32, m_CK + 32, nonce, out + offset, len + 16, true)) // encrypt
@ -355,7 +355,7 @@ namespace garlic
uint8_t sharedSecret[32]; uint8_t sharedSecret[32];
m_EphemeralKeys.Agree (bepk, sharedSecret); // sharedSecret = x25519(aesk, bepk) m_EphemeralKeys.Agree (bepk, sharedSecret); // sharedSecret = x25519(aesk, bepk)
i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK, 32); // chainKey = HKDF(chainKey, sharedSecret, "", 32) i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK, 32); // chainKey = HKDF(chainKey, sharedSecret, "", 32)
GetOwner ()->Decrypt (bepk, sharedSecret, nullptr, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RARCHET); // x25519 (ask, bepk) GetOwner ()->Decrypt (bepk, sharedSecret, nullptr, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET); // x25519 (ask, bepk)
i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK); // [chainKey, key] = HKDF(chainKey, sharedSecret, "", 64) i2p::crypto::HKDF (m_CK, sharedSecret, 32, "", m_CK); // [chainKey, key] = HKDF(chainKey, sharedSecret, "", 64)
uint8_t nonce[12]; uint8_t nonce[12];
CreateNonce (0, nonce); CreateNonce (0, nonce);

24
libi2pd/Garlic.cpp

@ -466,8 +466,9 @@ namespace garlic
LogPrint (eLogWarning, "Garlic: message length ", length, " exceeds I2NP message length ", msg->GetLength ()); LogPrint (eLogWarning, "Garlic: message length ", length, " exceeds I2NP message length ", msg->GetLength ());
return; return;
} }
auto mod = length & 0x0f; // %16
buf += 4; // length buf += 4; // length
auto it = m_Tags.find (SessionTag(buf)); auto it = !mod ? m_Tags.find (SessionTag(buf)) : m_Tags.end (); // AES block is multiple of 16
// AES tag might be used even if encryption type is not ElGamal/AES // AES tag might be used even if encryption type is not ElGamal/AES
if (it != m_Tags.end ()) if (it != m_Tags.end ())
{ {
@ -487,15 +488,11 @@ namespace garlic
} }
else else
{ {
// tag not found. Handle depending on encryption type // AES tag not found. Handle depending on encryption type
if (SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RARCHET)) // try ElGamal/AES first if leading block is 514
{
HandleECIESx25519 (buf, length);
return;
}
// otherwise assume ElGamal/AES
ElGamalBlock elGamal; ElGamalBlock elGamal;
if (length >= 514 && Decrypt (buf, (uint8_t *)&elGamal, m_Ctx, i2p::data::CRYPTO_KEY_TYPE_ELGAMAL)) if (mod == 2 && length >= 514 && SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ELGAMAL) &&
Decrypt (buf, (uint8_t *)&elGamal, m_Ctx, i2p::data::CRYPTO_KEY_TYPE_ELGAMAL))
{ {
auto decryption = std::make_shared<AESDecryption>(elGamal.sessionKey); auto decryption = std::make_shared<AESDecryption>(elGamal.sessionKey);
uint8_t iv[32]; // IV is first 16 bytes uint8_t iv[32]; // IV is first 16 bytes
@ -504,8 +501,11 @@ namespace garlic
decryption->Decrypt(buf + 514, length - 514, buf + 514); decryption->Decrypt(buf + 514, length - 514, buf + 514);
HandleAESBlock (buf + 514, length - 514, decryption, msg->from); HandleAESBlock (buf + 514, length - 514, decryption, msg->from);
} }
else if (SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET))
// otherwise ECIESx25519
HandleECIESx25519 (buf, length); // TODO: check tag first
else else
LogPrint (eLogError, "Garlic: Failed to decrypt message"); LogPrint (eLogError, "Garlic: Failed to decrypt message");
} }
} }
@ -679,8 +679,8 @@ namespace garlic
std::shared_ptr<GarlicRoutingSession> GarlicDestination::GetRoutingSession ( std::shared_ptr<GarlicRoutingSession> GarlicDestination::GetRoutingSession (
std::shared_ptr<const i2p::data::RoutingDestination> destination, bool attachLeaseSet) std::shared_ptr<const i2p::data::RoutingDestination> destination, bool attachLeaseSet)
{ {
if (destination->GetEncryptionType () == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RARCHET && if (destination->GetEncryptionType () == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET &&
SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RARCHET)) SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET))
{ {
ECIESX25519AEADRatchetSessionPtr session; ECIESX25519AEADRatchetSessionPtr session;
uint8_t staticKey[32]; uint8_t staticKey[32];

6
libi2pd/Identity.cpp

@ -412,7 +412,7 @@ namespace data
case CRYPTO_KEY_TYPE_ELGAMAL: case CRYPTO_KEY_TYPE_ELGAMAL:
return std::make_shared<i2p::crypto::ElGamalEncryptor>(key); return std::make_shared<i2p::crypto::ElGamalEncryptor>(key);
break; break;
case CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RARCHET: case CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET:
return std::make_shared<i2p::crypto::ECIESX25519AEADRatchetEncryptor>(key); return std::make_shared<i2p::crypto::ECIESX25519AEADRatchetEncryptor>(key);
break; break;
case CRYPTO_KEY_TYPE_ECIES_P256_SHA256_AES256CBC: case CRYPTO_KEY_TYPE_ECIES_P256_SHA256_AES256CBC:
@ -672,7 +672,7 @@ namespace data
case CRYPTO_KEY_TYPE_ECIES_GOSTR3410_CRYPTO_PRO_A_SHA256_AES256CBC: case CRYPTO_KEY_TYPE_ECIES_GOSTR3410_CRYPTO_PRO_A_SHA256_AES256CBC:
return std::make_shared<i2p::crypto::ECIESGOSTR3410Decryptor>(key); return std::make_shared<i2p::crypto::ECIESGOSTR3410Decryptor>(key);
break; break;
case CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RARCHET: case CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET:
return std::make_shared<i2p::crypto::ECIESX25519AEADRatchetDecryptor>(key); return std::make_shared<i2p::crypto::ECIESX25519AEADRatchetDecryptor>(key);
break; break;
default: default:
@ -754,7 +754,7 @@ namespace data
case CRYPTO_KEY_TYPE_ECIES_GOSTR3410_CRYPTO_PRO_A_SHA256_AES256CBC: case CRYPTO_KEY_TYPE_ECIES_GOSTR3410_CRYPTO_PRO_A_SHA256_AES256CBC:
i2p::crypto::CreateECIESGOSTR3410RandomKeys (priv, pub); i2p::crypto::CreateECIESGOSTR3410RandomKeys (priv, pub);
break; break;
case CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RARCHET: case CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET:
i2p::crypto::CreateECIESX25519AEADRatchetRandomKeys (priv, pub); i2p::crypto::CreateECIESX25519AEADRatchetRandomKeys (priv, pub);
break; break;
default: default:

2
libi2pd/Identity.h

@ -56,7 +56,7 @@ namespace data
const uint16_t CRYPTO_KEY_TYPE_ELGAMAL = 0; const uint16_t CRYPTO_KEY_TYPE_ELGAMAL = 0;
const uint16_t CRYPTO_KEY_TYPE_ECIES_P256_SHA256_AES256CBC = 1; const uint16_t CRYPTO_KEY_TYPE_ECIES_P256_SHA256_AES256CBC = 1;
const uint16_t CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RARCHET = 4; const uint16_t CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET = 4;
const uint16_t CRYPTO_KEY_TYPE_ECIES_P256_SHA256_AES256CBC_TEST = 65280; // TODO: remove later const uint16_t CRYPTO_KEY_TYPE_ECIES_P256_SHA256_AES256CBC_TEST = 65280; // TODO: remove later
const uint16_t CRYPTO_KEY_TYPE_ECIES_GOSTR3410_CRYPTO_PRO_A_SHA256_AES256CBC = 65281; // TODO: use GOST R 34.11 instead SHA256 and GOST 28147-89 instead AES const uint16_t CRYPTO_KEY_TYPE_ECIES_GOSTR3410_CRYPTO_PRO_A_SHA256_AES256CBC = 65281; // TODO: use GOST R 34.11 instead SHA256 and GOST 28147-89 instead AES

Loading…
Cancel
Save