mirror of
				https://github.com/PurpleI2P/i2pd.git
				synced 2025-11-04 00:20:46 +00:00 
			
		
		
		
	handle any incoming post quantum crypto type
This commit is contained in:
		
							parent
							
								
									67fe6faf2d
								
							
						
					
					
						commit
						bbfe81cb79
					
				
					 6 changed files with 41 additions and 43 deletions
				
			
		| 
						 | 
					@ -1556,11 +1556,12 @@ namespace client
 | 
				
			||||||
#endif		
 | 
					#endif		
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool ClientDestination::SupportsRatchets () const
 | 
						i2p::data::CryptoKeyType ClientDestination::GetRatchetsHighestCryptoType () const
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		if (m_EncryptionKeys.empty ()) return false;
 | 
							if (m_EncryptionKeys.empty ()) return 0;
 | 
				
			||||||
		return m_EncryptionKeys.rbegin ()->first >= i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD;
 | 
							auto cryptoType = m_EncryptionKeys.rbegin ()->first; 
 | 
				
			||||||
	}	
 | 
							return cryptoType >= i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD ? cryptoType : 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
	const uint8_t * ClientDestination::GetEncryptionPublicKey (i2p::data::CryptoKeyType keyType) const
 | 
						const uint8_t * ClientDestination::GetEncryptionPublicKey (i2p::data::CryptoKeyType keyType) const
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -283,7 +283,7 @@ namespace client
 | 
				
			||||||
		protected:
 | 
							protected:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// GarlicDestionation
 | 
								// GarlicDestionation
 | 
				
			||||||
			bool SupportsRatchets () const override;
 | 
								i2p::data::CryptoKeyType GetRatchetsHighestCryptoType () const override;
 | 
				
			||||||
			// LeaseSetDestination
 | 
								// LeaseSetDestination
 | 
				
			||||||
			void CleanupDestination () override;
 | 
								void CleanupDestination () override;
 | 
				
			||||||
			i2p::data::CryptoKeyType GetPreferredCryptoType () const override { return m_PreferredCryptoType; }
 | 
								i2p::data::CryptoKeyType GetPreferredCryptoType () const override { return m_PreferredCryptoType; }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -266,40 +266,40 @@ namespace garlic
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		buf += 32; len -= 32;
 | 
							buf += 32; len -= 32;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		uint64_t n = 0;
 | 
					 | 
				
			||||||
		uint8_t sharedSecret[32];
 | 
							uint8_t sharedSecret[32];
 | 
				
			||||||
		bool decrypted = false;
 | 
							bool decrypted = false;
 | 
				
			||||||
 | 
							auto cryptoType = GetOwner ()->GetRatchetsHighestCryptoType ();
 | 
				
			||||||
#if OPENSSL_PQ
 | 
					#if OPENSSL_PQ
 | 
				
			||||||
		if (GetOwner ()->SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD))
 | 
							if (cryptoType > i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD) // we support post quantum
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			i2p::crypto::InitNoiseIKStateMLKEM (GetNoiseState (), i2p::data::CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD,
 | 
								i2p::crypto::InitNoiseIKStateMLKEM (GetNoiseState (), cryptoType, GetOwner ()->GetEncryptionPublicKey (cryptoType)); // bpk
 | 
				
			||||||
				GetOwner ()->GetEncryptionPublicKey (i2p::data::CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD)); // bpk
 | 
					 | 
				
			||||||
			MixHash (m_Aepk, 32); // h = SHA256(h || aepk)
 | 
								MixHash (m_Aepk, 32); // h = SHA256(h || aepk)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (GetOwner ()->Decrypt (m_Aepk, sharedSecret, i2p::data::CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD)) // x25519(bsk, aepk)
 | 
								if (GetOwner ()->Decrypt (m_Aepk, sharedSecret, cryptoType)) // x25519(bsk, aepk)
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				MixKey (sharedSecret);
 | 
									MixKey (sharedSecret);
 | 
				
			||||||
				
 | 
					
 | 
				
			||||||
				uint8_t nonce[12], encapsKey[i2p::crypto::MLKEM512_KEY_LENGTH];
 | 
									auto keyLen = i2p::crypto::GetMLKEMPublicKeyLen (cryptoType);
 | 
				
			||||||
				CreateNonce (n, nonce);
 | 
									std::vector<uint8_t> encapsKey(keyLen);
 | 
				
			||||||
				if (Decrypt (buf, encapsKey, i2p::crypto::MLKEM512_KEY_LENGTH))
 | 
									if (Decrypt (buf, encapsKey.data (), keyLen))
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
					decrypted = true; // encaps section has right hash 
 | 
										decrypted = true; // encaps section has right hash 
 | 
				
			||||||
					MixHash (buf, i2p::crypto::MLKEM512_KEY_LENGTH + 16);
 | 
										MixHash (buf, keyLen + 16);
 | 
				
			||||||
					buf += i2p::crypto::MLKEM512_KEY_LENGTH + 16;
 | 
										buf += keyLen + 16;
 | 
				
			||||||
					len -= i2p::crypto::MLKEM512_KEY_LENGTH + 16;
 | 
										len -= keyLen + 16;
 | 
				
			||||||
					n++;
 | 
					 | 
				
			||||||
					
 | 
										
 | 
				
			||||||
					m_PQKeys = i2p::crypto::CreateMLKEMKeys (i2p::data::CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD);
 | 
										m_PQKeys = i2p::crypto::CreateMLKEMKeys (cryptoType);
 | 
				
			||||||
					m_PQKeys->SetPublicKey (encapsKey);
 | 
										m_PQKeys->SetPublicKey (encapsKey.data ());
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}	
 | 
								}	
 | 
				
			||||||
		}	
 | 
							}	
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
		if (!decrypted)
 | 
							if (!decrypted)
 | 
				
			||||||
		{	
 | 
							{	
 | 
				
			||||||
			if (GetOwner ()->SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD))
 | 
								if (cryptoType == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD ||
 | 
				
			||||||
 | 
								    GetOwner ()->SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD))
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
 | 
									cryptoType = i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD;
 | 
				
			||||||
				i2p::crypto::InitNoiseIKState (GetNoiseState (), GetOwner ()->GetEncryptionPublicKey (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD)); // bpk
 | 
									i2p::crypto::InitNoiseIKState (GetNoiseState (), GetOwner ()->GetEncryptionPublicKey (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD)); // bpk
 | 
				
			||||||
				MixHash (m_Aepk, 32); // h = SHA256(h || aepk)
 | 
									MixHash (m_Aepk, 32); // h = SHA256(h || aepk)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -318,8 +318,7 @@ namespace garlic
 | 
				
			||||||
		}	
 | 
							}	
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// decrypt flags/static
 | 
							// decrypt flags/static
 | 
				
			||||||
		uint8_t nonce[12], fs[32];
 | 
							uint8_t fs[32];
 | 
				
			||||||
		CreateNonce (n, nonce);
 | 
					 | 
				
			||||||
		if (!Decrypt (buf, fs, 32))
 | 
							if (!Decrypt (buf, fs, 32))
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			LogPrint (eLogWarning, "Garlic: Flags/static section AEAD verification failed ");
 | 
								LogPrint (eLogWarning, "Garlic: Flags/static section AEAD verification failed ");
 | 
				
			||||||
| 
						 | 
					@ -332,16 +331,8 @@ namespace garlic
 | 
				
			||||||
		bool isStatic = !i2p::data::Tag<32> (fs).IsZero ();
 | 
							bool isStatic = !i2p::data::Tag<32> (fs).IsZero ();
 | 
				
			||||||
		if (isStatic)
 | 
							if (isStatic)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			// static key, fs is apk
 | 
								// static key, fs is apk	
 | 
				
			||||||
#if OPENSSL_PQ
 | 
								SetRemoteStaticKey (cryptoType, fs); 
 | 
				
			||||||
			if (m_PQKeys)
 | 
					 | 
				
			||||||
			{	
 | 
					 | 
				
			||||||
				SetRemoteStaticKey (i2p::data::CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD, fs);
 | 
					 | 
				
			||||||
				CreateNonce (0, nonce); // reset nonce
 | 
					 | 
				
			||||||
			}	
 | 
					 | 
				
			||||||
			else	
 | 
					 | 
				
			||||||
#endif			
 | 
					 | 
				
			||||||
				SetRemoteStaticKey (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD, fs); 
 | 
					 | 
				
			||||||
			if (!GetOwner ()->Decrypt (fs, sharedSecret, m_RemoteStaticKeyType)) // x25519(bsk, apk)
 | 
								if (!GetOwner ()->Decrypt (fs, sharedSecret, m_RemoteStaticKeyType)) // x25519(bsk, apk)
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				LogPrint (eLogWarning, "Garlic: Incorrect Alice static key");
 | 
									LogPrint (eLogWarning, "Garlic: Incorrect Alice static key");
 | 
				
			||||||
| 
						 | 
					@ -349,8 +340,6 @@ namespace garlic
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			MixKey (sharedSecret);
 | 
								MixKey (sharedSecret);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		else // all zeros flags
 | 
					 | 
				
			||||||
			CreateNonce (1, nonce);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// decrypt payload
 | 
							// decrypt payload
 | 
				
			||||||
		std::vector<uint8_t> payload (len - 16); // we must save original ciphertext
 | 
							std::vector<uint8_t> payload (len - 16); // we must save original ciphertext
 | 
				
			||||||
| 
						 | 
					@ -966,7 +955,8 @@ namespace garlic
 | 
				
			||||||
		size_t len = CreatePayload (msg, m_State != eSessionStateEstablished, payload);
 | 
							size_t len = CreatePayload (msg, m_State != eSessionStateEstablished, payload);
 | 
				
			||||||
		if (!len) return nullptr;
 | 
							if (!len) return nullptr;
 | 
				
			||||||
#if OPENSSL_PQ
 | 
					#if OPENSSL_PQ
 | 
				
			||||||
		auto m = NewI2NPMessage (len + (m_State == eSessionStateEstablished ? 28 : i2p::crypto::MLKEM512_KEY_LENGTH + 116));
 | 
							auto m = NewI2NPMessage (len + (m_State == eSessionStateEstablished ? 28 :
 | 
				
			||||||
 | 
								i2p::crypto::GetMLKEMPublicKeyLen (m_RemoteStaticKeyType) + 116));
 | 
				
			||||||
#else		
 | 
					#else		
 | 
				
			||||||
		auto m = NewI2NPMessage (len + 100); // 96 + 4
 | 
							auto m = NewI2NPMessage (len + 100); // 96 + 4
 | 
				
			||||||
#endif		
 | 
					#endif		
 | 
				
			||||||
| 
						 | 
					@ -994,8 +984,8 @@ namespace garlic
 | 
				
			||||||
					return nullptr;
 | 
										return nullptr;
 | 
				
			||||||
				len += 72;
 | 
									len += 72;
 | 
				
			||||||
#if OPENSSL_PQ
 | 
					#if OPENSSL_PQ
 | 
				
			||||||
				if (m_RemoteStaticKeyType == i2p::data::CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD)
 | 
									if (m_RemoteStaticKeyType >= i2p::data::CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD)
 | 
				
			||||||
					len += i2p::crypto::MLKEM512_CIPHER_TEXT_LENGTH + 16;
 | 
										len += i2p::crypto::GetMLKEMPublicKeyLen (m_RemoteStaticKeyType) + 16;
 | 
				
			||||||
#endif				
 | 
					#endif				
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
			case eSessionStateNewSessionReplySent:
 | 
								case eSessionStateNewSessionReplySent:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -498,7 +498,8 @@ namespace garlic
 | 
				
			||||||
		buf += 4; // length
 | 
							buf += 4; // length
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		bool found = false;
 | 
							bool found = false;
 | 
				
			||||||
		if (SupportsRatchets ())
 | 
							bool supportsRatchets = SupportsRatchets ();
 | 
				
			||||||
 | 
							if (supportsRatchets)
 | 
				
			||||||
			// try ECIESx25519 tag
 | 
								// try ECIESx25519 tag
 | 
				
			||||||
			found = HandleECIESx25519TagMessage (buf, length);
 | 
								found = HandleECIESx25519TagMessage (buf, length);
 | 
				
			||||||
		if (!found)
 | 
							if (!found)
 | 
				
			||||||
| 
						 | 
					@ -535,7 +536,7 @@ namespace garlic
 | 
				
			||||||
					decryption->Decrypt(buf + 514, length - 514, iv, buf + 514);
 | 
										decryption->Decrypt(buf + 514, length - 514, iv, buf + 514);
 | 
				
			||||||
					HandleAESBlock (buf + 514, length - 514, decryption, msg->from);
 | 
										HandleAESBlock (buf + 514, length - 514, decryption, msg->from);
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				else if (SupportsRatchets ())
 | 
									else if (supportsRatchets)
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
					// otherwise ECIESx25519
 | 
										// otherwise ECIESx25519
 | 
				
			||||||
					auto ts = i2p::util::GetMillisecondsSinceEpoch ();
 | 
										auto ts = i2p::util::GetMillisecondsSinceEpoch ();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -266,6 +266,10 @@ namespace garlic
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			virtual std::shared_ptr<const i2p::data::LocalLeaseSet> GetLeaseSet () = 0; // TODO
 | 
								virtual std::shared_ptr<const i2p::data::LocalLeaseSet> GetLeaseSet () = 0; // TODO
 | 
				
			||||||
			virtual std::shared_ptr<i2p::tunnel::TunnelPool> GetTunnelPool () const = 0;
 | 
								virtual std::shared_ptr<i2p::tunnel::TunnelPool> GetTunnelPool () const = 0;
 | 
				
			||||||
 | 
								virtual i2p::data::CryptoKeyType GetRatchetsHighestCryptoType () const 
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									return GetIdentity ()->GetCryptoKeyType () >= i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD ? GetIdentity ()->GetCryptoKeyType () : 0;
 | 
				
			||||||
 | 
								}	
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		protected:
 | 
							protected:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -279,11 +283,10 @@ namespace garlic
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			void SaveTags ();
 | 
								void SaveTags ();
 | 
				
			||||||
			void LoadTags ();
 | 
								void LoadTags ();
 | 
				
			||||||
 | 
					 | 
				
			||||||
			virtual bool SupportsRatchets () const { return GetIdentity ()->GetCryptoKeyType () >= i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD; }
 | 
					 | 
				
			||||||
			
 | 
								
 | 
				
			||||||
		private:
 | 
							private:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								bool SupportsRatchets () const { return GetRatchetsHighestCryptoType () > 0; }
 | 
				
			||||||
			void HandleAESBlock (uint8_t * buf, size_t len, std::shared_ptr<AESDecryption> decryption,
 | 
								void HandleAESBlock (uint8_t * buf, size_t len, std::shared_ptr<AESDecryption> decryption,
 | 
				
			||||||
				std::shared_ptr<i2p::tunnel::InboundTunnel> from);
 | 
									std::shared_ptr<i2p::tunnel::InboundTunnel> from);
 | 
				
			||||||
			void HandleGarlicPayload (uint8_t * buf, size_t len, std::shared_ptr<i2p::tunnel::InboundTunnel> from);
 | 
								void HandleGarlicPayload (uint8_t * buf, size_t len, std::shared_ptr<i2p::tunnel::InboundTunnel> from);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -109,7 +109,10 @@ namespace client
 | 
				
			||||||
		protected:
 | 
							protected:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// GarlicDestination
 | 
								// GarlicDestination
 | 
				
			||||||
			bool SupportsRatchets () const override { return (bool)m_ECIESx25519Decryptor; }
 | 
								i2p::data::CryptoKeyType GetRatchetsHighestCryptoType () const override 
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									return m_ECIESx25519Decryptor ? i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD : 0;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
			// LeaseSetDestination
 | 
								// LeaseSetDestination
 | 
				
			||||||
			void CleanupDestination () override;
 | 
								void CleanupDestination () override;
 | 
				
			||||||
			i2p::data::CryptoKeyType GetPreferredCryptoType () const override;
 | 
								i2p::data::CryptoKeyType GetPreferredCryptoType () const override;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue