mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2025-04-23 17:36:37 +02: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
Reference in a new issue