mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2026-10-06 14:18:27 +00:00
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
209 lines
5.1 KiB
C++
209 lines
5.1 KiB
C++
/*
|
|
* Copyright (c) 2013-2025, The PurpleI2P Project
|
|
*
|
|
* This file is part of Purple i2pd project and licensed under BSD3
|
|
*
|
|
* See full license text in LICENSE file at top of project tree
|
|
*/
|
|
|
|
#ifndef CRYPTO_KEY_H__
|
|
#define CRYPTO_KEY_H__
|
|
|
|
#include <inttypes.h>
|
|
#include "Crypto.h"
|
|
#include "Identity.h"
|
|
|
|
namespace i2p
|
|
{
|
|
namespace crypto
|
|
{
|
|
class CryptoKeyEncryptor
|
|
{
|
|
public:
|
|
|
|
virtual ~CryptoKeyEncryptor () {};
|
|
virtual void Encrypt (const uint8_t * data, uint8_t * encrypted) = 0;
|
|
};
|
|
|
|
class CryptoKeyDecryptor
|
|
{
|
|
public:
|
|
|
|
virtual ~CryptoKeyDecryptor () {};
|
|
virtual bool Decrypt (const uint8_t * encrypted, uint8_t * data) = 0;
|
|
virtual size_t GetPublicKeyLen () const = 0; // we need it to set key in LS2
|
|
};
|
|
|
|
// ElGamal
|
|
class ElGamalEncryptor: public CryptoKeyEncryptor // for destination
|
|
{
|
|
public:
|
|
|
|
ElGamalEncryptor (const uint8_t * pub);
|
|
void Encrypt (const uint8_t * data, uint8_t * encrypted) override; // 222 bytes data, 514 bytes encrypted
|
|
|
|
private:
|
|
|
|
uint8_t m_PublicKey[256];
|
|
};
|
|
|
|
class ElGamalDecryptor: public CryptoKeyDecryptor // for destination
|
|
{
|
|
public:
|
|
|
|
ElGamalDecryptor (const uint8_t * priv);
|
|
bool Decrypt (const uint8_t * encrypted, uint8_t * data) override; // 514 bytes encrypted, 222 bytes data
|
|
size_t GetPublicKeyLen () const override { return 256; };
|
|
|
|
private:
|
|
|
|
uint8_t m_PrivateKey[256];
|
|
};
|
|
|
|
// ECIES P256
|
|
|
|
class ECIESP256Encryptor: public CryptoKeyEncryptor
|
|
{
|
|
public:
|
|
|
|
ECIESP256Encryptor (const uint8_t * pub);
|
|
~ECIESP256Encryptor ();
|
|
void Encrypt (const uint8_t * data, uint8_t * encrypted) override;
|
|
|
|
private:
|
|
|
|
EC_GROUP * m_Curve;
|
|
EC_POINT * m_PublicKey;
|
|
};
|
|
|
|
|
|
class ECIESP256Decryptor: public CryptoKeyDecryptor
|
|
{
|
|
public:
|
|
|
|
ECIESP256Decryptor (const uint8_t * priv);
|
|
~ECIESP256Decryptor ();
|
|
bool Decrypt (const uint8_t * encrypted, uint8_t * data) override;
|
|
size_t GetPublicKeyLen () const override { return 64; };
|
|
|
|
private:
|
|
|
|
EC_GROUP * m_Curve;
|
|
BIGNUM * m_PrivateKey;
|
|
};
|
|
|
|
void CreateECIESP256RandomKeys (uint8_t * priv, uint8_t * pub);
|
|
|
|
// ECIES GOST R 34.10
|
|
|
|
class ECIESGOSTR3410Encryptor: public CryptoKeyEncryptor
|
|
{
|
|
public:
|
|
|
|
ECIESGOSTR3410Encryptor (const uint8_t * pub);
|
|
~ECIESGOSTR3410Encryptor ();
|
|
void Encrypt (const uint8_t * data, uint8_t * encrypted) override;
|
|
|
|
private:
|
|
|
|
EC_POINT * m_PublicKey;
|
|
};
|
|
|
|
|
|
class ECIESGOSTR3410Decryptor: public CryptoKeyDecryptor
|
|
{
|
|
public:
|
|
|
|
ECIESGOSTR3410Decryptor (const uint8_t * priv);
|
|
~ECIESGOSTR3410Decryptor ();
|
|
bool Decrypt (const uint8_t * encrypted, uint8_t * data) override;
|
|
size_t GetPublicKeyLen () const override { return 64; };
|
|
|
|
private:
|
|
|
|
BIGNUM * m_PrivateKey;
|
|
};
|
|
|
|
void CreateECIESGOSTR3410RandomKeys (uint8_t * priv, uint8_t * pub);
|
|
|
|
// ECIES-X25519-AEAD-Ratchet
|
|
|
|
class ECIESX25519AEADRatchetEncryptor: public CryptoKeyEncryptor
|
|
{
|
|
public:
|
|
|
|
ECIESX25519AEADRatchetEncryptor (const uint8_t * pub);
|
|
~ECIESX25519AEADRatchetEncryptor () {};
|
|
void Encrypt (const uint8_t *, uint8_t * pub) override;
|
|
// copies m_PublicKey to pub
|
|
|
|
private:
|
|
|
|
uint8_t m_PublicKey[32];
|
|
};
|
|
|
|
class ECIESX25519AEADRatchetDecryptor: public CryptoKeyDecryptor
|
|
{
|
|
public:
|
|
|
|
ECIESX25519AEADRatchetDecryptor (const uint8_t * priv, bool calculatePublic = false);
|
|
~ECIESX25519AEADRatchetDecryptor () {};
|
|
bool Decrypt (const uint8_t * epub, uint8_t * sharedSecret) override;
|
|
// agree with static and return in sharedSecret (32 bytes)
|
|
size_t GetPublicKeyLen () const override { return 32; };
|
|
const uint8_t * GetPubicKey () const { return m_StaticKeys.GetPublicKey (); };
|
|
|
|
private:
|
|
|
|
X25519Keys m_StaticKeys;
|
|
};
|
|
|
|
void CreateECIESX25519AEADRatchetRandomKeys (uint8_t * priv, uint8_t * pub); // including hybrid
|
|
|
|
constexpr size_t GetCryptoPrivateKeyLen (i2p::data::CryptoKeyType type)
|
|
{
|
|
switch (type)
|
|
{
|
|
case i2p::data::CRYPTO_KEY_TYPE_ELGAMAL: return 256;
|
|
case i2p::data::CRYPTO_KEY_TYPE_ECIES_P256_SHA256_AES256CBC: return 256; // actual size is 32, but we use 256 for compatibility with old keys files
|
|
case i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD: return 32;
|
|
// ML-KEM hybrid
|
|
case i2p::data::CRYPTO_KEY_TYPE_ECIES_MLKEM512_X25519_AEAD:
|
|
case i2p::data::CRYPTO_KEY_TYPE_ECIES_MLKEM768_X25519_AEAD:
|
|
case i2p::data::CRYPTO_KEY_TYPE_ECIES_MLKEM1024_X25519_AEAD:
|
|
return 32;
|
|
};
|
|
return 0;
|
|
}
|
|
|
|
constexpr size_t GetCryptoPublicKeyLen (i2p::data::CryptoKeyType type)
|
|
{
|
|
switch (type)
|
|
{
|
|
case i2p::data::CRYPTO_KEY_TYPE_ELGAMAL: return 256;
|
|
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:
|
|
case i2p::data::CRYPTO_KEY_TYPE_ECIES_MLKEM768_X25519_AEAD:
|
|
case i2p::data::CRYPTO_KEY_TYPE_ECIES_MLKEM1024_X25519_AEAD:
|
|
return 32;
|
|
};
|
|
return 0;
|
|
}
|
|
|
|
struct LocalEncryptionKey
|
|
{
|
|
std::vector<uint8_t> pub, priv;
|
|
i2p::data::CryptoKeyType keyType;
|
|
std::shared_ptr<CryptoKeyDecryptor> decryptor;
|
|
|
|
LocalEncryptionKey (i2p::data::CryptoKeyType t);
|
|
void GenerateKeys ();
|
|
void CreateDecryptor ();
|
|
};
|
|
}
|
|
}
|
|
|
|
#endif
|