mirror of
				https://github.com/PurpleI2P/i2pd.git
				synced 2025-11-04 00:20:46 +00:00 
			
		
		
		
	indetification of incoming garlic messages
This commit is contained in:
		
							parent
							
								
									152e579f7e
								
							
						
					
					
						commit
						2fc16ee13d
					
				
					 6 changed files with 30 additions and 25 deletions
				
			
		| 
						 | 
					@ -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;   
 | 
				
			||||||
	}	
 | 
						}	
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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];
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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…
	
	Add table
		Add a link
		
	
		Reference in a new issue