diff --git a/src/protocol/CryptionHandler.cpp b/src/protocol/CryptionHandler.cpp index cb920e6..fb6ff19 100644 --- a/src/protocol/CryptionHandler.cpp +++ b/src/protocol/CryptionHandler.cpp @@ -5,11 +5,9 @@ #include #include #include -#include "../misc/base64.h" #include "misc/memtracker.h" #include "misc/digest.h" #include "CryptionHandler.h" -#include "../misc/sassert.h" using namespace std; using namespace ts; @@ -29,7 +27,7 @@ void CryptionHandler::reset() { this->useDefaultChipherKeyNonce = true; this->iv_struct_length = 0; memset(this->iv_struct, 0, sizeof(this->iv_struct)); - memcpy(this->current_mac, CryptionHandler::default_mac, sizeof(CryptionHandler::default_mac)); + memcpy(this->current_mac, this->default_mac, sizeof(this->default_mac)); for(auto& cache : this->cache_key_client) cache.generation = 0xFFEF; @@ -37,82 +35,80 @@ void CryptionHandler::reset() { cache.generation = 0xFFEF; } -#define SHARED_KEY_BUFFER_LENGTH (256) bool CryptionHandler::setupSharedSecret(const std::string& alpha, const std::string& beta, ecc_key *publicKey, ecc_key *ownKey, std::string &error) { - size_t buffer_length = SHARED_KEY_BUFFER_LENGTH; - uint8_t buffer[SHARED_KEY_BUFFER_LENGTH]; + size_t bufferLength = 128; + uint8_t* buffer = new uint8_t[bufferLength]; int err; - if((err = ecc_shared_secret(ownKey, publicKey, buffer, (unsigned long*) &buffer_length)) != CRYPT_OK){ + if((err = ecc_shared_secret(ownKey, publicKey, buffer, (unsigned long*) &bufferLength)) != CRYPT_OK){ + delete[] buffer; error = "Could not calculate shared secret. Message: " + string(error_to_string(err)); return false; } - - auto result = this->setupSharedSecret(alpha, beta, string((const char*) buffer, buffer_length), error); - return result; + auto result = this->setupSharedSecret(alpha, beta, string((const char*) buffer, bufferLength), error); + delete[] buffer; + return result; } -bool CryptionHandler::setupSharedSecret(const std::string& alpha, const std::string& beta, const std::string& sharedKey, std::string &error) { +bool CryptionHandler::setupSharedSecret(const std::string& alpha, const std::string& beta, const std::string &sharedKey, std::string &error) { auto secret_hash = digest::sha1(sharedKey); - assert(secret_hash.length() == SHA_DIGEST_LENGTH); - uint8_t iv_buffer[SHA_DIGEST_LENGTH]; - memcpy(iv_buffer, alpha.data(), 10); - memcpy(&iv_buffer[10], beta.data(), 10); + char ivStruct[SHA_DIGEST_LENGTH]; + memcpy(ivStruct, alpha.data(), 10); + memcpy(&ivStruct[10], beta.data(), 10); - for (int index = 0; index < SHA_DIGEST_LENGTH; index++) { - iv_buffer[index] ^= (uint8_t) secret_hash[index]; - } + for (int index = 0; index < SHA_DIGEST_LENGTH; index++) { + ivStruct[index] ^= (uint8_t) secret_hash[index]; + } { lock_guard lock(this->cache_key_lock); - memcpy(this->iv_struct, iv_buffer, SHA_DIGEST_LENGTH); + memcpy(this->iv_struct, ivStruct, SHA_DIGEST_LENGTH); this->iv_struct_length = SHA_DIGEST_LENGTH; - uint8_t mac_buffer[SHA_DIGEST_LENGTH]; - digest::sha1((const char*) iv_buffer, SHA_DIGEST_LENGTH, mac_buffer); - memcpy(this->current_mac, mac_buffer, 8); + auto iv_hash = digest::sha1(ivStruct, SHA_DIGEST_LENGTH); + memcpy(this->current_mac, iv_hash.data(), 8); this->useDefaultChipherKeyNonce = false; } - return true; + return true; } void _fe_neg(fe h, const fe f) { - int32_t f0 = f[0]; - int32_t f1 = f[1]; - int32_t f2 = f[2]; - int32_t f3 = f[3]; - int32_t f4 = f[4]; - int32_t f5 = f[5]; - int32_t f6 = f[6]; - int32_t f7 = f[7]; - int32_t f8 = f[8]; - int32_t f9 = f[9]; - int32_t h0 = -f0; - int32_t h1 = -f1; - int32_t h2 = -f2; - int32_t h3 = -f3; - int32_t h4 = -f4; - int32_t h5 = -f5; - int32_t h6 = -f6; - int32_t h7 = -f7; - int32_t h8 = -f8; - int32_t h9 = -f9; + int32_t f0 = f[0]; + int32_t f1 = f[1]; + int32_t f2 = f[2]; + int32_t f3 = f[3]; + int32_t f4 = f[4]; + int32_t f5 = f[5]; + int32_t f6 = f[6]; + int32_t f7 = f[7]; + int32_t f8 = f[8]; + int32_t f9 = f[9]; + int32_t h0 = -f0; + int32_t h1 = -f1; + int32_t h2 = -f2; + int32_t h3 = -f3; + int32_t h4 = -f4; + int32_t h5 = -f5; + int32_t h6 = -f6; + int32_t h7 = -f7; + int32_t h8 = -f8; + int32_t h9 = -f9; - h[0] = h0; - h[1] = h1; - h[2] = h2; - h[3] = h3; - h[4] = h4; - h[5] = h5; - h[6] = h6; - h[7] = h7; - h[8] = h8; - h[9] = h9; + h[0] = h0; + h[1] = h1; + h[2] = h2; + h[3] = h3; + h[4] = h4; + h[5] = h5; + h[6] = h6; + h[7] = h7; + h[8] = h8; + h[9] = h9; } -inline void keyMul(uint8_t(& target_buffer)[32], const uint8_t* publicKey /* compressed */, const uint8_t* privateKey /* uncompressed */, bool negate){ +inline std::string keyMul(const uint8_t* publicKey /* compressed */, const uint8_t* privateKey /* uncompressed */, bool negate){ ge_p3 keyA{}; ge_p2 result{}; @@ -123,32 +119,34 @@ inline void keyMul(uint8_t(& target_buffer)[32], const uint8_t* publicKey /* com } ge_scalarmult_vartime(&result, privateKey, &keyA); - ge_tobytes(target_buffer, &result); + char buffer[32]; + ge_tobytes((uint8_t*) buffer, &result); + return string(buffer, 32); } bool CryptionHandler::setupSharedSecretNew(const std::string &alpha, const std::string &beta, const char* privateKey /* uncompressed */, const char* publicKey /* compressed */) { - if(alpha.length() != 10 || beta.length() != 54) - return false; + assert(alpha.length() == 10); + assert(beta.length() == 54); - uint8_t shared[32]; - uint8_t shared_iv[64]; - - ed25519_key_exchange(shared, (uint8_t*) publicKey, (uint8_t*) privateKey); - keyMul(shared, reinterpret_cast(publicKey), reinterpret_cast(privateKey), true); //Remote key get negated - digest::sha512((char*) shared, 32, shared_iv); + string shared; + string sharedIv; + shared.resize(32, '\0'); + sharedIv.resize(64, '\0'); + ed25519_key_exchange((uint8_t*) shared.data(), (uint8_t*) publicKey, (uint8_t*) privateKey); + shared = keyMul(reinterpret_cast(publicKey), reinterpret_cast(privateKey), true); //Remote key get negated + sharedIv = digest::sha512(shared); auto xor_key = alpha + beta; for(int i = 0; i < 64; i++) - shared_iv[i] ^= (uint8_t) xor_key[i]; + sharedIv[i] ^= xor_key[i]; { lock_guard lock(this->cache_key_lock); - memcpy(this->iv_struct, shared_iv, 64); + memcpy(this->iv_struct, sharedIv.data(), 64); this->iv_struct_length = 64; - uint8_t mac_buffer[SHA_DIGEST_LENGTH]; - digest::sha1((char*) this->iv_struct, 64, mac_buffer); - memcpy(this->current_mac, mac_buffer, 8); + auto digest_buffer = digest::sha1((char*) this->iv_struct, 64); + memcpy(this->current_mac, digest_buffer.data(), 8); this->useDefaultChipherKeyNonce = false; } @@ -167,7 +165,6 @@ bool CryptionHandler::generate_key_nonce(protocol::BasicPacket* packet, bool use ); } -#define GENERATE_BUFFER_LENGTH (128) bool CryptionHandler::generate_key_nonce( bool to_server, /* its from the client to the server */ protocol::PacketType type, @@ -178,8 +175,8 @@ bool CryptionHandler::generate_key_nonce( uint8_t (& nonce)[16] ) { if (this->useDefaultChipherKeyNonce || use_default) { - memcpy(key, CryptionHandler::default_key, 16); - memcpy(nonce, CryptionHandler::default_nonce, 16); + memcpy(key, this->default_key, 16); + memcpy(nonce, this->default_nonce, 16); return true; } @@ -191,11 +188,9 @@ bool CryptionHandler::generate_key_nonce( auto& key_cache = key_cache_array[type]; if(key_cache.generation != generation) { - const size_t buffer_length = 6 + this->iv_struct_length; - sassert(buffer_length < GENERATE_BUFFER_LENGTH); - - char buffer[GENERATE_BUFFER_LENGTH]; - memset(buffer, 0, buffer_length); + const size_t buffer_length = 6 + this->iv_struct_length; + char* buffer = new char[buffer_length]; + memset(buffer, 0, 6 + this->iv_struct_length); if (to_server) { buffer[0] = 0x31; @@ -206,13 +201,13 @@ bool CryptionHandler::generate_key_nonce( le2be32(generation, buffer, 2); memcpy(&buffer[6], this->iv_struct, this->iv_struct_length); - digest::sha256(buffer, buffer_length, key_cache.key_nonce); + auto key_nonce = digest::sha256(buffer, 6 + this->iv_struct_length); - /* memcpy(key_cache.key, key_nonce.data(), 16); memcpy(key_cache.nonce, key_nonce.data() + 16, 16); - */ - key_cache.generation = generation; + key_cache.generation = generation; + + delete[] buffer; } memcpy(key, key_cache.key, 16); @@ -239,10 +234,9 @@ bool CryptionHandler::verify_encryption(const pipes::buffer_view &packet, uint16 auto length = data.length(); - /* static shareable void buffer */ - const static unsigned long void_target_length = 2048; - static uint8_t void_target_buffer[2048]; - if(void_target_length < length) + const unsigned long target_length = 2048; + uint8_t target_buffer[2048]; + if(target_length < length) return false; err = eax_decrypt_verify_memory(find_cipher("rijndael"), @@ -253,10 +247,10 @@ bool CryptionHandler::verify_encryption(const pipes::buffer_view &packet, uint16 (uint8_t *) header.data_ptr(), /* example header */ (unsigned long) header.length(), /* header length */ (const unsigned char *) data.data_ptr(), - (unsigned long) data.length(), - (unsigned char *) void_target_buffer, + (unsigned long) data.length(), + (unsigned char *) target_buffer, (unsigned char *) mac.data_ptr(), - (unsigned long) mac.length(), + (unsigned long) mac.length(), &success ); @@ -264,7 +258,7 @@ bool CryptionHandler::verify_encryption(const pipes::buffer_view &packet, uint16 } bool CryptionHandler::decryptPacket(protocol::BasicPacket *packet, std::string &error, bool use_default) { - int err; + int err; int success = false; auto header = packet->header(); @@ -276,6 +270,14 @@ bool CryptionHandler::decryptPacket(protocol::BasicPacket *packet, std::string & return false; } + size_t target_length = 2048; + uint8_t target_buffer[2048]; + auto length = data.length(); + if(target_length < length) { + error = "buffer too large"; + return false; + } + err = eax_decrypt_verify_memory(find_cipher("rijndael"), (uint8_t *) key, /* the key */ (unsigned long) 16, /* key is 16 bytes */ @@ -284,10 +286,10 @@ bool CryptionHandler::decryptPacket(protocol::BasicPacket *packet, std::string & (uint8_t *) header.data_ptr(), /* example header */ (unsigned long) header.length(), /* header length */ (const unsigned char *) data.data_ptr(), - (unsigned long) data.length(), - (unsigned char *) data.data_ptr(), + (unsigned long) data.length(), + (unsigned char *) target_buffer, (unsigned char *) packet->mac().data_ptr(), - (unsigned long) packet->mac().length(), + (unsigned long) packet->mac().length(), &success ); @@ -300,8 +302,9 @@ bool CryptionHandler::decryptPacket(protocol::BasicPacket *packet, std::string & return false; } + packet->data(pipes::buffer_view{target_buffer, length}); packet->setEncrypted(false); - return true; + return true; } bool CryptionHandler::encryptPacket(protocol::BasicPacket *packet, std::string &error, bool use_default) { @@ -313,8 +316,8 @@ bool CryptionHandler::encryptPacket(protocol::BasicPacket *packet, std::string & size_t length = packet->data().length(); - size_t tag_length = 8; - char tag_buffer[8]; + size_t tag_length = 8; + char tag_buffer[8]; size_t target_length = 2048; uint8_t target_buffer[2048]; @@ -324,53 +327,52 @@ bool CryptionHandler::encryptPacket(protocol::BasicPacket *packet, std::string & } int err; - if((err = eax_encrypt_authenticate_memory(find_cipher("rijndael"), - (uint8_t *) key, /* the key */ - (unsigned long) 16, /* key is 16 bytes */ - (uint8_t *) nonce, /* the nonce */ - (unsigned long) 16, /* nonce is 16 bytes */ - (uint8_t *) packet->header().data_ptr(), /* example header */ - (unsigned long) packet->header().length(), /* header length */ - (uint8_t *) packet->data().data_ptr(), /* The plain text */ - (unsigned long) packet->data().length(), /* Plain text length */ - // (uint8_t *) packet->data().data_ptr(), /* The result buffer */ - (uint8_t *) target_buffer, /* The result buffer */ - (uint8_t *) tag_buffer, - (unsigned long *) &tag_length - )) != CRYPT_OK){ - error = "eax_encrypt_authenticate_memory(...) returned " + to_string(err) + "/" + error_to_string(err); - return false; - } - assert(tag_length == 8); + if((err = eax_encrypt_authenticate_memory(find_cipher("rijndael"), + (uint8_t *) key, /* the key */ + (unsigned long) 16, /* key is 16 bytes */ + (uint8_t *) nonce, /* the nonce */ + (unsigned long) 16, /* nonce is 16 bytes */ + (uint8_t *) packet->header().data_ptr(), /* example header */ + (unsigned long) packet->header().length(), /* header length */ + (uint8_t *) packet->data().data_ptr(), /* The plain text */ + (unsigned long) packet->data().length(), /* Plain text length */ + (uint8_t *) target_buffer, /* The result buffer */ + (uint8_t *) tag_buffer, + (unsigned long *) &tag_length + )) != CRYPT_OK){ + error = "eax_encrypt_authenticate_memory(...) returned " + to_string(err) + "/" + error_to_string(err); + return false; + } + assert(tag_length == 8); packet->data(pipes::buffer_view{target_buffer, length}); - packet->mac().write(tag_buffer, tag_length); + packet->mac().write(tag_buffer, tag_length); packet->setEncrypted(true); - return true; + return true; } bool CryptionHandler::progressPacketIn(protocol::BasicPacket* packet, std::string& error, bool use_default) { - while(blocked) - this_thread::yield(); + while(blocked) + this_thread::sleep_for(chrono::microseconds(100)); - if(packet->isEncrypted()){ - bool success = decryptPacket(packet, error, use_default); - if(success) packet->setEncrypted(false); - return success; - } - return true; + if(packet->isEncrypted()){ + bool success = decryptPacket(packet, error, use_default); + if(success) packet->setEncrypted(false); + return success; + } + return true; } bool CryptionHandler::progressPacketOut(protocol::BasicPacket* packet, std::string& error, bool use_default) { - while(blocked) - this_thread::yield(); + while(blocked) + this_thread::sleep_for(chrono::microseconds(100)); - if(packet->has_flag(PacketFlag::Unencrypted)) { - packet->mac().write(this->current_mac, 8); - } else { - bool success = encryptPacket(packet, error, use_default); - if(success) packet->setEncrypted(true); - return success; - } - return true; + if(packet->has_flag(PacketFlag::Unencrypted)) { + packet->mac().write(this->current_mac, 8); + } else { + bool success = encryptPacket(packet, error, use_default); + if(success) packet->setEncrypted(true); + return success; + } + return true; }