mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2025-01-22 21:37:17 +01:00
indetification of incoming garlic messages
This commit is contained in:
parent
152e579f7e
commit
2fc16ee13d
|
@ -824,8 +824,8 @@ namespace client
|
|||
|
||||
i2p::data::CryptoKeyType LeaseSetDestination::GetPreferredCryptoType () const
|
||||
{
|
||||
if (SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RARCHET))
|
||||
return 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_RATCHET;
|
||||
return i2p::data::CRYPTO_KEY_TYPE_ELGAMAL;
|
||||
}
|
||||
|
||||
|
|
|
@ -229,7 +229,12 @@ namespace client
|
|||
// implements LocalDestination
|
||||
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 (); };
|
||||
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; };
|
||||
|
||||
protected:
|
||||
|
|
|
@ -127,7 +127,7 @@ namespace garlic
|
|||
if (!GetOwner ()) return false;
|
||||
// we are Bob
|
||||
// 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))
|
||||
{
|
||||
|
@ -138,7 +138,7 @@ namespace garlic
|
|||
MixHash (m_Aepk, 32); // h = SHA256(h || aepk)
|
||||
|
||||
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)
|
||||
|
||||
// decrypt flags/static
|
||||
|
@ -160,7 +160,7 @@ namespace garlic
|
|||
{
|
||||
// static key, fs is apk
|
||||
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)
|
||||
}
|
||||
else // all zeros flags
|
||||
|
@ -242,7 +242,7 @@ namespace garlic
|
|||
// encrypt static key section
|
||||
uint8_t nonce[12];
|
||||
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 ");
|
||||
return false;
|
||||
|
@ -250,7 +250,7 @@ namespace garlic
|
|||
MixHash (out + offset, 48); // h = SHA256(h || ciphertext)
|
||||
offset += 48;
|
||||
// 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)
|
||||
// encrypt payload
|
||||
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];
|
||||
m_EphemeralKeys.Agree (bepk, sharedSecret); // sharedSecret = x25519(aesk, bepk)
|
||||
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)
|
||||
uint8_t nonce[12];
|
||||
CreateNonce (0, nonce);
|
||||
|
|
|
@ -466,8 +466,9 @@ namespace garlic
|
|||
LogPrint (eLogWarning, "Garlic: message length ", length, " exceeds I2NP message length ", msg->GetLength ());
|
||||
return;
|
||||
}
|
||||
auto mod = length & 0x0f; // %16
|
||||
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
|
||||
if (it != m_Tags.end ())
|
||||
{
|
||||
|
@ -487,15 +488,11 @@ namespace garlic
|
|||
}
|
||||
else
|
||||
{
|
||||
// tag not found. Handle depending on encryption type
|
||||
if (SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RARCHET))
|
||||
{
|
||||
HandleECIESx25519 (buf, length);
|
||||
return;
|
||||
}
|
||||
// otherwise assume ElGamal/AES
|
||||
// AES tag not found. Handle depending on encryption type
|
||||
// try ElGamal/AES first if leading block is 514
|
||||
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);
|
||||
uint8_t iv[32]; // IV is first 16 bytes
|
||||
|
@ -504,6 +501,9 @@ namespace garlic
|
|||
decryption->Decrypt(buf + 514, length - 514, buf + 514);
|
||||
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
|
||||
LogPrint (eLogError, "Garlic: Failed to decrypt message");
|
||||
}
|
||||
|
@ -679,8 +679,8 @@ namespace garlic
|
|||
std::shared_ptr<GarlicRoutingSession> GarlicDestination::GetRoutingSession (
|
||||
std::shared_ptr<const i2p::data::RoutingDestination> destination, bool attachLeaseSet)
|
||||
{
|
||||
if (destination->GetEncryptionType () == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RARCHET &&
|
||||
SupportsEncryptionType (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_RATCHET))
|
||||
{
|
||||
ECIESX25519AEADRatchetSessionPtr session;
|
||||
uint8_t staticKey[32];
|
||||
|
|
|
@ -412,7 +412,7 @@ namespace data
|
|||
case CRYPTO_KEY_TYPE_ELGAMAL:
|
||||
return std::make_shared<i2p::crypto::ElGamalEncryptor>(key);
|
||||
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);
|
||||
break;
|
||||
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:
|
||||
return std::make_shared<i2p::crypto::ECIESGOSTR3410Decryptor>(key);
|
||||
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);
|
||||
break;
|
||||
default:
|
||||
|
@ -754,7 +754,7 @@ namespace data
|
|||
case CRYPTO_KEY_TYPE_ECIES_GOSTR3410_CRYPTO_PRO_A_SHA256_AES256CBC:
|
||||
i2p::crypto::CreateECIESGOSTR3410RandomKeys (priv, pub);
|
||||
break;
|
||||
case CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RARCHET:
|
||||
case CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET:
|
||||
i2p::crypto::CreateECIESX25519AEADRatchetRandomKeys (priv, pub);
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -56,7 +56,7 @@ namespace data
|
|||
|
||||
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_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_GOSTR3410_CRYPTO_PRO_A_SHA256_AES256CBC = 65281; // TODO: use GOST R 34.11 instead SHA256 and GOST 28147-89 instead AES
|
||||
|
||||
|
|
Loading…
Reference in a new issue