diff --git a/libi2pd/Crypto.cpp b/libi2pd/Crypto.cpp index 76963a18..794ea324 100644 --- a/libi2pd/Crypto.cpp +++ b/libi2pd/Crypto.cpp @@ -442,9 +442,8 @@ namespace crypto // encrypt CBCEncryption encryption; encryption.SetKey (shared); - encryption.SetIV (iv); encrypted[257] = 0; - encryption.Encrypt (m, 256, encrypted + 258); + encryption.Encrypt (m, 256, iv, encrypted + 258); EC_POINT_free (p); BN_CTX_end (ctx); BN_CTX_free (ctx); @@ -477,8 +476,7 @@ namespace crypto uint8_t m[256]; CBCDecryption decryption; decryption.SetKey (shared); - decryption.SetIV (iv); - decryption.Decrypt (encrypted + 258, 256, m); + decryption.Decrypt (encrypted + 258, 256, iv, m); // verify and copy uint8_t hash[32]; SHA256 (m + 33, 222, hash); @@ -560,7 +558,6 @@ namespace crypto CBCEncryption::CBCEncryption () { m_Ctx = EVP_CIPHER_CTX_new (); - //memset ((uint8_t *)m_LastBlock, 0, 16); } CBCEncryption::~CBCEncryption () @@ -569,10 +566,10 @@ namespace crypto EVP_CIPHER_CTX_free (m_Ctx); } - void CBCEncryption::Encrypt (const uint8_t * in, std::size_t len, uint8_t * out) + void CBCEncryption::Encrypt (const uint8_t * in, size_t len, const uint8_t * iv, uint8_t * out) { // len/16 - EVP_EncryptInit_ex (m_Ctx, EVP_aes_256_cbc(), NULL, m_Key, m_IV); + EVP_EncryptInit_ex (m_Ctx, EVP_aes_256_cbc(), NULL, m_Key, iv); EVP_CIPHER_CTX_set_padding (m_Ctx, 0); int l; EVP_EncryptUpdate (m_Ctx, out, &l, in, len); @@ -582,7 +579,6 @@ namespace crypto CBCDecryption::CBCDecryption () { m_Ctx = EVP_CIPHER_CTX_new (); - //memset ((uint8_t *)m_IV, 0, 16); } CBCDecryption::~CBCDecryption () @@ -591,10 +587,10 @@ namespace crypto EVP_CIPHER_CTX_free (m_Ctx); } - void CBCDecryption::Decrypt (const uint8_t * in, std::size_t len, uint8_t * out) + void CBCDecryption::Decrypt (const uint8_t * in, size_t len, const uint8_t * iv, uint8_t * out) { // len/16 - EVP_DecryptInit_ex (m_Ctx, EVP_aes_256_cbc(), NULL, m_Key, m_IV); + EVP_DecryptInit_ex (m_Ctx, EVP_aes_256_cbc(), NULL, m_Key, iv); EVP_CIPHER_CTX_set_padding (m_Ctx, 0); int l; EVP_DecryptUpdate (m_Ctx, out, &l, in, len); @@ -603,18 +599,18 @@ namespace crypto void TunnelEncryption::Encrypt (const uint8_t * in, uint8_t * out) { - m_IVEncryption.Encrypt (in, out); // iv - m_LayerEncryption.SetIV (out); - m_LayerEncryption.Encrypt (in + 16, i2p::tunnel::TUNNEL_DATA_ENCRYPTED_SIZE, out + 16); // data - m_IVEncryption.Encrypt (out, out); // double iv + uint8_t iv[16]; + m_IVEncryption.Encrypt (in, iv); // iv + m_LayerEncryption.Encrypt (in + 16, i2p::tunnel::TUNNEL_DATA_ENCRYPTED_SIZE, iv, out + 16); // data + m_IVEncryption.Encrypt (iv, out); // double iv } void TunnelDecryption::Decrypt (const uint8_t * in, uint8_t * out) { - m_IVDecryption.Decrypt (in, out); // iv - m_LayerDecryption.SetIV (out); - m_LayerDecryption.Decrypt (in + 16, i2p::tunnel::TUNNEL_DATA_ENCRYPTED_SIZE, out + 16); // data - m_IVDecryption.Decrypt (out, out); // double iv + uint8_t iv[16]; + m_IVDecryption.Decrypt (in, iv); // iv + m_LayerDecryption.Decrypt (in + 16, i2p::tunnel::TUNNEL_DATA_ENCRYPTED_SIZE, iv, out + 16); // data + m_IVDecryption.Decrypt (iv, out); // double iv } // AEAD/ChaCha20/Poly1305 diff --git a/libi2pd/Crypto.h b/libi2pd/Crypto.h index d153ee89..1666bfeb 100644 --- a/libi2pd/Crypto.h +++ b/libi2pd/Crypto.h @@ -93,7 +93,7 @@ namespace crypto ECBEncryption (); ~ECBEncryption (); - void SetKey (const AESKey& key) { m_Key = key; }; + void SetKey (const uint8_t * key) { m_Key = key; }; void Encrypt(const uint8_t * in, uint8_t * out); private: @@ -109,7 +109,7 @@ namespace crypto ECBDecryption (); ~ECBDecryption (); - void SetKey (const AESKey& key) { m_Key = key; }; + void SetKey (const uint8_t * key) { m_Key = key; }; void Decrypt (const uint8_t * in, uint8_t * out); private: @@ -125,15 +125,12 @@ namespace crypto CBCEncryption (); ~CBCEncryption (); - void SetKey (const AESKey& key) { m_Key = key; }; // 32 bytes - void SetIV (const uint8_t * iv) { m_IV = iv; }; // 16 bytes - - void Encrypt (const uint8_t * in, std::size_t len, uint8_t * out); + void SetKey (const uint8_t * key) { m_Key = key; }; // 32 bytes + void Encrypt (const uint8_t * in, size_t len, const uint8_t * iv, uint8_t * out); private: AESKey m_Key; - i2p::data::Tag<16> m_IV; EVP_CIPHER_CTX * m_Ctx; }; @@ -144,15 +141,12 @@ namespace crypto CBCDecryption (); ~CBCDecryption (); - void SetKey (const AESKey& key) { m_Key = key; }; // 32 bytes - void SetIV (const uint8_t * iv) { m_IV = iv; }; // 16 bytes - - void Decrypt (const uint8_t * in, std::size_t len, uint8_t * out); + void SetKey (const uint8_t * key) { m_Key = key; }; // 32 bytes + void Decrypt (const uint8_t * in, size_t len, const uint8_t * iv, uint8_t * out); private: AESKey m_Key; - i2p::data::Tag<16> m_IV; EVP_CIPHER_CTX * m_Ctx; }; diff --git a/libi2pd/Garlic.cpp b/libi2pd/Garlic.cpp index c93579e0..83511c26 100644 --- a/libi2pd/Garlic.cpp +++ b/libi2pd/Garlic.cpp @@ -160,7 +160,7 @@ namespace garlic uint8_t iv[32]; // IV is first 16 bytes SHA256(elGamal.preIV, 32, iv); m_Destination->Encrypt ((uint8_t *)&elGamal, buf); - m_Encryption.SetIV (iv); + m_IV = iv; buf += 514; len += 514; } @@ -170,7 +170,7 @@ namespace garlic memcpy (buf, tag, 32); uint8_t iv[32]; // IV is first 16 bytes SHA256(tag, 32, iv); - m_Encryption.SetIV (iv); + m_IV = iv; buf += 32; len += 32; } @@ -210,7 +210,7 @@ namespace garlic size_t rem = blockSize % 16; if (rem) blockSize += (16-rem); //padding - m_Encryption.Encrypt(buf, blockSize, buf); + m_Encryption.Encrypt(buf, blockSize, m_IV, buf); return blockSize; } @@ -514,8 +514,7 @@ namespace garlic { uint8_t iv[32]; // IV is first 16 bytes SHA256(buf, 32, iv); - decryption->SetIV (iv); - decryption->Decrypt (buf + 32, length - 32, buf + 32); + decryption->Decrypt (buf + 32, length - 32, iv, buf + 32); HandleAESBlock (buf + 32, length - 32, decryption, msg->from); found = true; } @@ -533,8 +532,7 @@ namespace garlic auto decryption = std::make_shared(elGamal.sessionKey); uint8_t iv[32]; // IV is first 16 bytes SHA256(elGamal.preIV, 32, iv); - decryption->SetIV (iv); - decryption->Decrypt(buf + 514, length - 514, buf + 514); + decryption->Decrypt(buf + 514, length - 514, iv, buf + 514); HandleAESBlock (buf + 514, length - 514, decryption, msg->from); } else if (SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD)) diff --git a/libi2pd/Garlic.h b/libi2pd/Garlic.h index 8401f052..b39d5fde 100644 --- a/libi2pd/Garlic.h +++ b/libi2pd/Garlic.h @@ -205,6 +205,7 @@ namespace garlic std::map > m_UnconfirmedTagsMsgs; // msgID->tags i2p::crypto::CBCEncryption m_Encryption; + i2p::data::Tag<16> m_IV; public: diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index 6630a351..d0c6b002 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -120,8 +120,7 @@ namespace transport // encrypt X i2p::crypto::CBCEncryption encryption; encryption.SetKey (m_RemoteIdentHash); - encryption.SetIV (m_IV); - encryption.Encrypt (GetPub (), 32, m_SessionRequestBuffer); // X + encryption.Encrypt (GetPub (), 32, m_IV, m_SessionRequestBuffer); // X memcpy (m_IV, m_SessionRequestBuffer + 16, 16); // save last block as IV for SessionCreated // encryption key for next block if (!KDF1Alice ()) return false; @@ -161,8 +160,7 @@ namespace transport // encrypt Y i2p::crypto::CBCEncryption encryption; encryption.SetKey (i2p::context.GetIdentHash ()); - encryption.SetIV (m_IV); - encryption.Encrypt (GetPub (), 32, m_SessionCreatedBuffer); // Y + encryption.Encrypt (GetPub (), 32, m_IV, m_SessionCreatedBuffer); // Y // encryption key for next block (m_K) if (!KDF2Bob ()) return false; uint8_t options[16]; @@ -208,8 +206,7 @@ namespace transport // decrypt X i2p::crypto::CBCDecryption decryption; decryption.SetKey (i2p::context.GetIdentHash ()); - decryption.SetIV (i2p::context.GetNTCP2IV ()); - decryption.Decrypt (m_SessionRequestBuffer, 32, GetRemotePub ()); + decryption.Decrypt (m_SessionRequestBuffer, 32, i2p::context.GetNTCP2IV (), GetRemotePub ()); memcpy (m_IV, m_SessionRequestBuffer + 16, 16); // save last block as IV for SessionCreated // decryption key for next block if (!KDF1Bob ()) @@ -268,8 +265,7 @@ namespace transport // decrypt Y i2p::crypto::CBCDecryption decryption; decryption.SetKey (m_RemoteIdentHash); - decryption.SetIV (m_IV); - decryption.Decrypt (m_SessionCreatedBuffer, 32, GetRemotePub ()); + decryption.Decrypt (m_SessionCreatedBuffer, 32, m_IV, GetRemotePub ()); // decryption key for next block (m_K) if (!KDF2Alice ()) { diff --git a/libi2pd/TransitTunnel.cpp b/libi2pd/TransitTunnel.cpp index 8284dc14..883034fe 100644 --- a/libi2pd/TransitTunnel.cpp +++ b/libi2pd/TransitTunnel.cpp @@ -434,8 +434,7 @@ namespace tunnel else { encryption.SetKey (clearText + ECIES_BUILD_REQUEST_RECORD_REPLY_KEY_OFFSET); - encryption.SetIV (clearText + ECIES_BUILD_REQUEST_RECORD_REPLY_IV_OFFSET); - encryption.Encrypt(reply, TUNNEL_BUILD_RECORD_SIZE, reply); + encryption.Encrypt(reply, TUNNEL_BUILD_RECORD_SIZE, clearText + ECIES_BUILD_REQUEST_RECORD_REPLY_IV_OFFSET, reply); } } return true; diff --git a/libi2pd/TunnelConfig.cpp b/libi2pd/TunnelConfig.cpp index e19b515d..fe0e8573 100644 --- a/libi2pd/TunnelConfig.cpp +++ b/libi2pd/TunnelConfig.cpp @@ -79,8 +79,7 @@ namespace tunnel uint8_t * record = records + index*TUNNEL_BUILD_RECORD_SIZE; i2p::crypto::CBCDecryption decryption; decryption.SetKey (replyKey); - decryption.SetIV (replyIV); - decryption.Decrypt(record, TUNNEL_BUILD_RECORD_SIZE, record); + decryption.Decrypt(record, TUNNEL_BUILD_RECORD_SIZE, replyIV, record); } void ECIESTunnelHopConfig::EncryptECIES (const uint8_t * plainText, size_t len, uint8_t * encrypted) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 6353a683..fb03d434 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -65,6 +65,10 @@ set(test-eddsa_SRCS test-eddsa.cpp ) +set(test-aes_SRCS + test-aes.cpp +) + add_executable(test-http-merge_chunked ${test-http-merge_chunked_SRCS}) add_executable(test-http-req ${test-http-req_SRCS}) add_executable(test-http-res ${test-http-res_SRCS}) @@ -77,6 +81,7 @@ add_executable(test-aeadchacha20poly1305 ${test-aeadchacha20poly1305_SRCS}) add_executable(test-blinding ${test-blinding_SRCS}) add_executable(test-elligator ${test-elligator_SRCS}) add_executable(test-eddsa ${test-eddsa_SRCS}) +add_executable(test-aes ${test-aes_SRCS}) set(LIBS libi2pd @@ -101,6 +106,7 @@ target_link_libraries(test-aeadchacha20poly1305 ${LIBS}) target_link_libraries(test-blinding ${LIBS}) target_link_libraries(test-elligator ${LIBS}) target_link_libraries(test-eddsa ${LIBS}) +target_link_libraries(test-aes ${LIBS}) add_test(test-http-merge_chunked ${TEST_PATH}/test-http-merge_chunked) add_test(test-http-req ${TEST_PATH}/test-http-req) @@ -114,3 +120,4 @@ add_test(test-aeadchacha20poly1305 ${TEST_PATH}/test-aeadchacha20poly1305) add_test(test-blinding ${TEST_PATH}/test-blinding) add_test(test-elligator ${TEST_PATH}/test-elligator) add_test(test-eddsa ${TEST_PATH}/test-eddsa) +add_test(test-aes ${TEST_PATH}/test-aes) diff --git a/tests/Makefile b/tests/Makefile index 51a11dfe..b020427d 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -8,7 +8,7 @@ LIBI2PD = ../libi2pd.a TESTS = \ test-http-merge_chunked test-http-req test-http-res test-http-url test-http-url_decode \ test-gost test-gost-sig test-base-64 test-aeadchacha20poly1305 test-blinding \ - test-elligator test-eddsa + test-elligator test-eddsa test-aes ifneq (, $(findstring mingw, $(SYS))$(findstring windows-gnu, $(SYS))$(findstring cygwin, $(SYS))) CXXFLAGS += -DWIN32_LEAN_AND_MEAN @@ -56,6 +56,9 @@ test-elligator: test-elligator.cpp $(LIBI2PD) test-eddsa: test-eddsa.cpp $(LIBI2PD) $(CXX) $(CXXFLAGS) $(NEEDED_CXXFLAGS) $(INCFLAGS) $(LDFLAGS) -o $@ $^ $(LDLIBS) +test-aes: test-aes.cpp $(LIBI2PD) + $(CXX) $(CXXFLAGS) $(NEEDED_CXXFLAGS) $(INCFLAGS) $(LDFLAGS) -o $@ $^ $(LDLIBS) + run: $(TESTS) @for TEST in $(TESTS); do echo Running $$TEST; ./$$TEST ; done diff --git a/tests/test-aes.cpp b/tests/test-aes.cpp new file mode 100644 index 00000000..15f4de1e --- /dev/null +++ b/tests/test-aes.cpp @@ -0,0 +1,69 @@ +#include +#include +#include + +#include "Crypto.h" + +uint8_t ecb_key1[32] = +{ + 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81, + 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4 +}; + +uint8_t ecb_plain1[16] = +{ + 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a +}; + +uint8_t ecb_cipher1[16] = +{ + 0xf3, 0xee, 0xd1, 0xbd, 0xb5, 0xd2, 0xa0, 0x3c, 0x06, 0x4b, 0x5a, 0x7e, 0x3d, 0xb1, 0x81, 0xf8 +}; + +uint8_t cbc_key1[32] = +{ + 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81, + 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4 +}; + +uint8_t cbc_iv1[16] = +{ + 0xF5, 0x8C, 0x4C, 0x04, 0xD6, 0xE5, 0xF1, 0xBA, 0x77, 0x9E, 0xAB, 0xFB, 0x5F, 0x7B, 0xFB, 0xD6 +}; + +uint8_t cbc_plain1[16] = +{ + 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51 +}; + +uint8_t cbc_cipher1[16] = +{ + 0x9c, 0xfc, 0x4e, 0x96, 0x7e, 0xdb, 0x80, 0x8d, 0x67, 0x9f, 0x77, 0x7b, 0xc6, 0x70, 0x2c, 0x7d +}; + +int main () +{ + // ECB encrypt test1 + i2p::crypto::ECBEncryption ecbencryption; + ecbencryption.SetKey (ecb_key1); + uint8_t out[16]; + ecbencryption.Encrypt (ecb_plain1, out); + assert (memcmp (ecb_cipher1, out, 16) == 0); + + // ECB decrypt test1 + i2p::crypto::ECBDecryption ecbdecryption; + ecbdecryption.SetKey (ecb_key1); + ecbdecryption.Decrypt (ecb_cipher1, out); + assert (memcmp (ecb_plain1, out, 16) == 0); + // CBC encrypt test + i2p::crypto::CBCEncryption cbcencryption; + cbcencryption.SetKey (cbc_key1); + cbcencryption.Encrypt (cbc_plain1, 16, cbc_iv1, out); + assert (memcmp (cbc_cipher1, out, 16) == 0); + // CBC decrypt test + i2p::crypto::CBCDecryption cbcdecryption; + cbcdecryption.SetKey (cbc_key1); + cbcdecryption.Decrypt (cbc_cipher1, 16, cbc_iv1, out); + assert (memcmp (cbc_plain1, out, 16) == 0); +} +