Reset crypt handler

This commit is contained in:
WolverinDEV 2019-07-07 18:01:03 +02:00
parent ee8e5b9dd5
commit d48c0f99f5

View File

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