diff --git a/libi2pd/Crypto.cpp b/libi2pd/Crypto.cpp index 8ba99a15..5e8ba855 100644 --- a/libi2pd/Crypto.cpp +++ b/libi2pd/Crypto.cpp @@ -8,6 +8,9 @@ #include #include "TunnelBase.h" #include +#include "I2PEndian.h" +#include "ChaCha20.h" +#include "Poly1305.h" #include "Log.h" #include "Crypto.h" @@ -1057,6 +1060,32 @@ namespace crypto } } +// AEAD/ChaCha20/Poly1305 + + size_t AEADChaCha20Poly1305Encrypt (const uint8_t * msg, size_t msgLen, const uint8_t * ad, size_t adLen, const uint8_t * key, const uint8_t * nonce, uint8_t * buf, size_t len) + { + if (msgLen + 16 < len) return 0; + // generate one time poly key + uint8_t polyKey[64]; + memset(polyKey, 0, sizeof(polyKey)); + chacha20 (polyKey, 64, nonce, key, 0); + // encrypt data + memcpy (buf, msg, msgLen); + chacha20 (buf, msgLen, nonce, key, 1); + // create Poly1305 message + std::vector polyMsg(adLen + msgLen + 16); + size_t offset = 0; + memcpy (polyMsg.data (), ad, adLen); offset += adLen; + memcpy (polyMsg.data () + offset, buf, msgLen); offset += msgLen; // encrypted data + htole64buf (polyMsg.data () + offset, adLen); offset += 8; + htole64buf (polyMsg.data () + offset, msgLen); offset += 8; + // calculate Poly1305 tag and write in after encrypted data + Poly1305HMAC ((uint32_t *)(buf + msgLen), (uint32_t *)key, polyMsg.data (), offset); + return msgLen + 16; + } + +// init and terminate + /* std::vector > m_OpenSSLMutexes; static void OpensslLockingCallback(int mode, int type, const char * file, int line) { diff --git a/libi2pd/Crypto.h b/libi2pd/Crypto.h index 859f2d97..0600c48c 100644 --- a/libi2pd/Crypto.h +++ b/libi2pd/Crypto.h @@ -252,6 +252,10 @@ namespace crypto CBCDecryption m_LayerDecryption; }; +// AEAD/ChaCha20/Poly1305 + size_t AEADChaCha20Poly1305Encrypt (const uint8_t * msg, size_t msgLen, const uint8_t * ad, size_t adLen, const uint8_t * key, const uint8_t * nonce, uint8_t * buf, size_t len); + +// init and terminate void InitCrypto (bool precomputation); void TerminateCrypto (); } diff --git a/libi2pd/I2PEndian.h b/libi2pd/I2PEndian.h index d2250768..0798f688 100644 --- a/libi2pd/I2PEndian.h +++ b/libi2pd/I2PEndian.h @@ -113,7 +113,20 @@ inline void htobe64buf(void *buf, uint64_t big64) htobuf64(buf, htobe64(big64)); } +inline void htole16buf(void *buf, uint16_t big16) +{ + htobuf16(buf, htole16(big16)); +} +inline void htole32buf(void *buf, uint32_t big32) +{ + htobuf32(buf, htole32(big32)); +} + +inline void htole64buf(void *buf, uint64_t big64) +{ + htobuf64(buf, htole64(big64)); +} #endif // I2PENDIAN_H__ diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index 43ccc2dd..b3794354 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -6,8 +6,6 @@ #include "I2PEndian.h" #include "Crypto.h" #include "Ed25519.h" -#include "ChaCha20.h" -#include "Poly1305.h" #include "NTCP2.h" namespace i2p @@ -52,7 +50,7 @@ namespace transport m_Server.GetService ().post (std::bind (&NTCP2Session::Terminate, shared_from_this ())); } - bool NTCP2Session::KeyDerivationFunction1 (const uint8_t * rs, const uint8_t * pub, uint8_t * derived) + bool NTCP2Session::KeyDerivationFunction1 (const uint8_t * rs, const uint8_t * pub, uint8_t * derived, uint8_t * ad) { static const char protocolName[] = "Noise_XK_25519_ChaChaPoly_SHA256"; // 32 bytes uint8_t h[64], ck[33]; @@ -63,7 +61,7 @@ namespace transport SHA256 (h, 64, h); // h = SHA256(h || pub) memcpy (h + 32, pub, 32); - SHA256 (h, 64, h); + SHA256 (h, 64, ad); // x25519 between rs and priv uint8_t inputKeyMaterial[32]; BN_CTX * ctx = BN_CTX_new (); @@ -106,8 +104,8 @@ namespace transport encryption.SetIV (m_RemoteIV); encryption.Encrypt (x, 32, m_SessionRequestBuffer); // encryption key for next block - uint8_t key[32]; - KeyDerivationFunction1 (m_RemoteStaticKey, x, key); + uint8_t key[32], ad[32]; + KeyDerivationFunction1 (m_RemoteStaticKey, x, key, ad); // fill options uint8_t options[32]; // actual options size is 16 bytes memset (options, 0, 16); @@ -118,11 +116,9 @@ namespace transport htobe32buf (options + 8, i2p::util::GetSecondsSinceEpoch ()); // tsA // 4 bytes reserved // sign and encrypt options - i2p::crypto::Poly1305HMAC (((uint32_t *)options) + 4, (uint32_t *)key, options, 16); // calculate MAC first uint8_t nonce[12]; memset (nonce, 0, 12); // set nonce to zero - i2p::crypto::chacha20 (options, 16, nonce, key); // then encrypt - memcpy (m_SessionRequestBuffer + 32, options, 32); + i2p::crypto::AEADChaCha20Poly1305Encrypt (options, 16, ad, 32, key, nonce, m_SessionRequestBuffer + 32, 32); // send message boost::asio::async_write (m_Socket, boost::asio::buffer (m_SessionRequestBuffer, paddingLength + 64), boost::asio::transfer_all (), std::bind(&NTCP2Session::HandleSessionRequestSent, shared_from_this (), std::placeholders::_1, std::placeholders::_2)); diff --git a/libi2pd/NTCP2.h b/libi2pd/NTCP2.h index ca36d37b..8cdf6073 100644 --- a/libi2pd/NTCP2.h +++ b/libi2pd/NTCP2.h @@ -29,7 +29,7 @@ namespace transport private: - bool KeyDerivationFunction1 (const uint8_t * rs, const uint8_t * pub, uint8_t * derived); // for SessionRequest + bool KeyDerivationFunction1 (const uint8_t * rs, const uint8_t * pub, uint8_t * derived, uint8_t * ad); // for SessionRequest void CreateEphemeralKey (uint8_t * pub); void SendSessionRequest ();