LeaseSet2: check declared key length before creating an encryptor

A key section in a standard LeaseSet2 carries both a key type and a key
length. The length is checked against the buffer, but the encryptor reads
a length fixed by the type instead: 256 bytes for ElGamal, 64 for ECIES
P256, 32 for X25519. A section that declares ElGamal with a length of zero
passes the check and then makes CreateEncryptor read 256 bytes past the end
of the message.

Key sections are parsed before the signature is verified, so no key material
is needed to trigger it.

GetCryptoPublicKeyLen returned 32 for ECIES P256, while the key is x and y,
32 bytes each; without fixing that too, the new check would still let a 32
byte P256 section through.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Awv7FvZTpGFsKFNeNyJaTE
This commit is contained in:
PobreGato
2026-09-14 21:43:53 -04:00
co-authored by Claude Opus 5
parent bc4dc2b272
commit 466e865e91
2 changed files with 7 additions and 2 deletions
+1 -1
View File
@@ -181,7 +181,7 @@ namespace crypto
switch (type)
{
case i2p::data::CRYPTO_KEY_TYPE_ELGAMAL: return 256;
case i2p::data::CRYPTO_KEY_TYPE_ECIES_P256_SHA256_AES256CBC: return 32;
case i2p::data::CRYPTO_KEY_TYPE_ECIES_P256_SHA256_AES256CBC: return 64; // x and y, 32 bytes each
case i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD: return 32;
// ML-KEM hybrid
case i2p::data::CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD:
+6 -1
View File
@@ -423,7 +423,12 @@ namespace data
if (keyType <= i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD) // skip PQ keys if not supported
#endif
{
if ((keyType == m_PreferredEncryptionType || !newEncryptor || keyType > newEncryptionType) &&
// encryptionKeyLen is the length the publisher declares, and it was
// checked against the buffer. The encryptor reads a length fixed by
// the key type instead, so a section declaring a short ElGamal key
// makes it read 256 bytes out of a few
if (encryptionKeyLen >= i2p::crypto::GetCryptoPublicKeyLen (keyType) &&
(keyType == m_PreferredEncryptionType || !newEncryptor || keyType > newEncryptionType) &&
(!dest || dest->SupportsEncryptionType (keyType)))
{
auto encryptor = i2p::data::IdentityEx::CreateEncryptor (keyType, buf + offset);