move some files to lib folder, adding memory management for often used binary memory blocks to prevent memory fragmentation

This commit is contained in:
Dario 2019-11-03 12:22:35 +01:00
parent aa9169bd34
commit 6bae595aa2
32 changed files with 571 additions and 118 deletions

View File

@ -22,6 +22,7 @@ FILE(GLOB HTTPInterface "src/cpp/HTTPInterface/*.h" "src/cpp/HTTPInterface/*.cpp
FILE(GLOB JSONInterface "src/cpp/JSONInterface/*.h" "src/cpp/JSONInterface/*.cpp")
FILE(GLOB TASKS "src/cpp/tasks/*.cpp" "src/cpp/tasks/*.h")
FILE(GLOB SINGLETON_MANAGER "src/cpp/SingletonManager/*.h" "src/cpp/SingletonManager/*.cpp")
FILE(GLOB LIB_SRC "src/cpp/lib/*.h" "src/cpp/lib/*.cpp")
FILE(GLOB MODEL "src/cpp/model/*.h" "src/cpp/model/*.cpp")
FILE(GLOB CRYPTO "src/cpp/Crypto/*.h" "src/cpp/Crypto/*.cpp")
FILE(GLOB MAIN "src/cpp/*.cpp" "src/cpp/*.c" "src/cpp/*.h")
@ -30,7 +31,7 @@ FILE(GLOB PROTO_GRADIDO "src/cpp/proto/gradido/*.cc" "src/cpp/proto/gradido/*.h"
SET(LOCAL_SRCS
${TINF} ${MAIN} ${HTTPInterface}
${JSONInterface} ${CRYPTO} ${MODEL}
${SINGLETON_MANAGER} ${MYSQL} ${TASKS}
${SINGLETON_MANAGER} ${LIB_SRC} ${MYSQL} ${TASKS}
${PROTO_GRADIDO}
)
aux_source_directory("src/cpp" LOCAL_SRCS)
@ -44,6 +45,7 @@ source_group("tasks" FILES ${TASKS})
source_group("model" FILES ${MODEL})
source_group("mysql" FILES ${MYSQL})
source_group("SingletonManager" FILES ${SINGLETON_MANAGER})
source_group("lib" FILES ${LIB_SRC})
source_group("HTTP-Interface" FILES ${HTTPInterface})
source_group("Json-Interface" FILES ${JSONInterface})

View File

@ -23,13 +23,16 @@ KeyPair::KeyPair()
KeyPair::~KeyPair()
{
auto mm = MemoryManager::getInstance();
//printf("[KeyPair::~KeyPair] privkey: %d, soduium privkey: %d \n", mPrivateKey, mSodiumSecret);
if (mPrivateKey) {
delete mPrivateKey;
//delete mPrivateKey;
mm->releaseMemory(mPrivateKey);
mPrivateKey = nullptr;
}
if (mSodiumSecret) {
delete mSodiumSecret;
//delete mSodiumSecret;
mm->releaseMemory(mSodiumSecret);
mSodiumSecret = nullptr;
}
}
@ -81,22 +84,29 @@ bool KeyPair::generateFromPassphrase(const char* passphrase, Mnemonic* word_sour
public_key_t pbl_key_t;
ed25519_derive_public_key(&prv_key_t, &pbl_key_t);
auto mm = MemoryManager::getInstance();
//memcpy(private_key, prv_key_t.data, 32);
if (mPrivateKey) {
delete mPrivateKey;
if (!mPrivateKey) {
//delete mPrivateKey;
mPrivateKey = mm->getFreeMemory(ed25519_privkey_SIZE);
}
mPrivateKey = new ObfusArray(ed25519_privkey_SIZE, prv_key_t.data);
//mPrivateKey = new ObfusArray(ed25519_privkey_SIZE, prv_key_t.data);
memcpy(*mPrivateKey, prv_key_t.data, ed25519_privkey_SIZE);
memcpy(mPublicKey, pbl_key_t.data, ed25519_pubkey_SIZE);
unsigned char sodium_secret[crypto_sign_SECRETKEYBYTES];
crypto_sign_seed_keypair(mSodiumPublic, sodium_secret, *mPrivateKey);
if(mSodiumSecret) {
delete mSodiumSecret;
if (!mSodiumSecret) {
//delete mSodiumSecret;
//mm->releaseMemory(mSodiumSecret);
mSodiumSecret = mm->getFreeMemory(crypto_sign_SECRETKEYBYTES);
}
mSodiumSecret = new ObfusArray(crypto_sign_SECRETKEYBYTES, sodium_secret);
//unsigned char sodium_secret[crypto_sign_SECRETKEYBYTES];
crypto_sign_seed_keypair(mSodiumPublic, *mSodiumSecret, *mPrivateKey);
// print hex for all keys for debugging
/* printf("// ********** Keys ************* //\n");
@ -113,24 +123,27 @@ bool KeyPair::generateFromPassphrase(const char* passphrase, Mnemonic* word_sour
std::string KeyPair::getPubkeyHex()
{
size_t hexSize = crypto_sign_PUBLICKEYBYTES * 2 + 1;
char* hexString = (char*)malloc(hexSize);
const size_t hexSize = crypto_sign_PUBLICKEYBYTES * 2 + 1;
char hexString[hexSize];
memset(hexString, 0, hexSize);
sodium_bin2hex(hexString, hexSize, mSodiumPublic, crypto_sign_PUBLICKEYBYTES);
std::string pubHex = hexString;
free(hexString);
return pubHex;
return std::string(hexString);
}
std::string KeyPair::getHex(const unsigned char* data, size_t size)
{
auto mm = MemoryManager::getInstance();
size_t hexSize = size * 2 + 1;
char* hexString = (char*)malloc(hexSize);
memset(hexString, 0, hexSize);
sodium_bin2hex(hexString, hexSize, data, size);
std::string hex = hexString;
free(hexString);
auto hexMem = mm->getFreeMemory(hexSize);
//char* hexString = (char*)malloc(hexSize);
memset(*hexMem, 0, hexSize);
sodium_bin2hex(*hexMem, hexSize, data, size);
std::string hex = *hexMem;
// free(hexString);
mm->releaseMemory(hexMem);
return hex;
}

View File

@ -2,11 +2,14 @@
#define GRADIDO_LOGIN_SERVER_CRYPTO_KEY_PAIR
#include "Obfus_array.h"
#include "../SingletonManager/MemoryManager.h"
#include "mnemonic.h"
#include "ed25519/ed25519.h"
#include <sodium.h>
class UserWriteKeysIntoDB;
class UserGenerateKeys;
// TODO: https://libsodium.gitbook.io/doc/advanced/ed25519-curve25519
@ -26,14 +29,18 @@ public:
inline const unsigned char* getPublicKey() const { return mSodiumPublic; }
protected:
const ObfusArray* getPrivateKey() const { return mSodiumSecret; }
const MemoryBin* getPrivateKey() const { return mSodiumSecret; }
private:
ObfusArray* mPrivateKey;
ObfusArray* mSodiumSecret;
// 32 Byte
MemoryBin* mPrivateKey;
// 64 Byte
MemoryBin* mSodiumSecret;
// 32 Byte
unsigned char mPublicKey[ed25519_pubkey_SIZE];
// 32 Byte
unsigned char mSodiumPublic[crypto_sign_PUBLICKEYBYTES];
};

View File

@ -61,6 +61,7 @@ public:
~ObfusArray();
inline operator const unsigned char*() const {return &m_Data[m_offsetSize];}
inline operator unsigned char*() { return &m_Data[m_offsetSize]; }
inline size_t size() const { return m_dataSize;}

View File

@ -11,7 +11,7 @@
*
*/
#include "DRHashList.h"
#include "../lib/DRHashList.h"
#include <string>
#define PHRASE_WORD_COUNT 24

View File

@ -2,8 +2,8 @@
#define PAGE_REQUEST_MESSAGE_HANDLER_INCLUDED
//#include "../model/Session.h"
#include "../model/ErrorList.h"
#include "../model/Profiler.h"
#include "../lib/ErrorList.h"
#include "../lib/Profiler.h"
#include "Poco/Net/HTTPRequestHandler.h"

View File

@ -13,7 +13,7 @@
#include <list>
#include <string.h>
#include "../model/ErrorList.h"
#include "../lib/ErrorList.h"
#include "mysql.h"
#include "Poco/Data/Session.h"

View File

@ -1,7 +1,7 @@
#ifndef GRADIDO_LOGIN_SERVER_SINGLETON_MANAGER_CONNECTION_MANAGER_INCLUDE
#define GRADIDO_LOGIN_SERVER_SINGLETON_MANAGER_CONNECTION_MANAGER_INCLUDE
#include "../Crypto/DRHashList.h"
#include "../lib/DRHashList.h"
#include <string>
#include "Poco/Util/LayeredConfiguration.h"
@ -9,7 +9,7 @@
#include "../MySQL/Poco/Connector.h"
#include "Poco/Exception.h"
#include "../model/ErrorList.h"
#include "../lib/ErrorList.h"
enum ConnectionType {
CONNECTION_MYSQL_LOGIN_SERVER,

View File

@ -15,8 +15,8 @@
#include <list>
#include <map>
#include <cstring>
#include "../model/ErrorList.h"
#include "../Crypto/DRHash.h"
#include "../lib/ErrorList.h"
#include "../lib/DRHash.h"
#include "../tasks/CPUTask.h"
#include "Poco/Mutex.h"

View File

@ -0,0 +1,133 @@
#include "MemoryManager.h"
#include "ErrorManager.h"
#define _DEFAULT_PAGE_SIZE 10
MemoryBin::MemoryBin(Poco::UInt32 size)
: mSize(size), mData(nullptr)
{
mData = (unsigned char*)malloc(size);
}
MemoryBin::~MemoryBin()
{
if (mData) {
free(mData);
}
}
// *************************************************************
MemoryPageStack::MemoryPageStack(Poco::UInt16 size)
: mSize(size)
{
mMemoryBinStack.push(new MemoryBin(size));
}
MemoryPageStack::~MemoryPageStack()
{
lock();
while (mMemoryBinStack.size() > 0) {
auto memoryBin = mMemoryBinStack.top();
delete memoryBin;
mMemoryBinStack.pop();
}
mSize = 0;
unlock();
}
MemoryBin* MemoryPageStack::getFreeMemory()
{
lock();
if (!mSize) {
unlock();
return nullptr;
}
if (mMemoryBinStack.size() == 0) {
unlock();
return new MemoryBin(mSize);
}
auto memoryBin = mMemoryBinStack.top();
mMemoryBinStack.pop();
unlock();
return memoryBin;
}
void MemoryPageStack::releaseMemory(MemoryBin* memory)
{
if (!memory) return;
lock();
if (memory->size() != mSize) {
unlock();
throw new Poco::Exception("MemoryPageStack::releaseMemory wron memory page stack");
}
mMemoryBinStack.push(memory);
unlock();
}
// ***********************************************************************************
MemoryManager* MemoryManager::getInstance()
{
static MemoryManager only;
return &only;
}
MemoryManager::MemoryManager()
{
mMemoryPageStacks[0] = new MemoryPageStack(32); // pubkey
mMemoryPageStacks[1] = new MemoryPageStack(64); // privkey
mMemoryPageStacks[2] = new MemoryPageStack(65); // pubkey hex
mMemoryPageStacks[3] = new MemoryPageStack(96); // privkey encrypted
}
MemoryManager::~MemoryManager()
{
for (int i = 0; i < 4; i++) {
delete mMemoryPageStacks[i];
}
}
Poco::Int8 MemoryManager::getMemoryStackIndex(Poco::UInt16 size)
{
switch (size) {
case 32: return 0;
case 64: return 1;
case 65: return 2;
case 96: return 3;
default: return -1;
}
return -1;
}
MemoryBin* MemoryManager::getFreeMemory(Poco::UInt32 size)
{
if (size != (Poco::UInt32)((Poco::UInt16)size)) {
throw Poco::Exception("MemoryManager::getFreeMemory size is to large, only 16 Bit allowed");
}
auto index = getMemoryStackIndex(size);
if (index < 0) {
return new MemoryBin(size);
}
else {
return mMemoryPageStacks[index]->getFreeMemory();
}
return nullptr;
}
void MemoryManager::releaseMemory(MemoryBin* memory)
{
if (!memory) return;
auto index = getMemoryStackIndex(memory->size());
if (index < 0) {
delete memory;
}
else {
mMemoryPageStacks[index]->releaseMemory(memory);
}
}

View File

@ -0,0 +1,83 @@
/*!
*
* \author: einhornimmond
*
* \date: 01.11.19
*
* \brief: manage memory blocks to reduce dynamic memory allocation for preventing memory fragmentation,
* specially for key memory blocks of 32 and 64 byte
*/
#ifndef GRADIDO_LOGIN_SERVER_SINGLETON_MANAGER_MEMORY_MANAGER_H
#define GRADIDO_LOGIN_SERVER_SINGLETON_MANAGER_MEMORY_MANAGER_H
#include "Poco/Mutex.h"
//#include "../lib/DRMemoryList.h"
#include "../lib/MemoryPage.h"
#include "../lib/MultithreadContainer.h"
#include <list>
#define MEMORY_MANAGER_PAGE_SIZE 10
class MemoryPageStack;
class MemoryManager;
class MemoryBin
{
friend MemoryPageStack;
friend MemoryManager;
public:
inline operator unsigned char*() { return mData; }
inline operator char*() { return (char*)mData; }
inline operator void* () { return mData; }
inline operator const unsigned char*() const { return mData; }
inline size_t size() const { return static_cast<size_t>(mSize); }
inline operator size_t() const { return static_cast<size_t>(mSize); }
protected:
MemoryBin(Poco::UInt32 size);
~MemoryBin();
Poco::UInt16 mSize;
unsigned char* mData;
};
class MemoryPageStack : protected UniLib::lib::MultithreadContainer
{
public:
MemoryPageStack(Poco::UInt16 size);
~MemoryPageStack();
MemoryBin* getFreeMemory();
void releaseMemory(MemoryBin* memory);
protected:
std::stack<MemoryBin*> mMemoryBinStack;
Poco::UInt16 mSize;
};
class MemoryManager
{
public:
~MemoryManager();
static MemoryManager* getInstance();
MemoryBin* getFreeMemory(Poco::UInt32 size);
void releaseMemory(MemoryBin* memory);
protected:
Poco::Int8 getMemoryStackIndex(Poco::UInt16 size);
MemoryManager();
MemoryPageStack* mMemoryPageStacks[4];
};
#endif //GRADIDO_LOGIN_SERVER_SINGLETON_MANAGER_MEMORY_MANAGER_H

View File

@ -34,9 +34,6 @@ von Paul Glinker Rockstar Games Toronto
#ifndef __DR_CORE2_MEMORY_LIST__
#define __DR_CORE2_MEMORY_LIST__
#ifndef __CORE_2_MAIN_H__
#include "Core2Main.h"
#endif
template <typename FLDataType> class DRMemoryList
{
@ -60,10 +57,10 @@ template <typename FLDataType> class DRMemoryList
//Und die Instance freigeben
void FreeInstance(FLDataType* pInstance);
//liefert die anzahl der noch freien Speicherplätze zurück
int getFreeCount() {return m_iTop;}
int getObjectCount() {return m_iNumObject;}
FLDataType** getDataPointer() {return m_ppFreeObjects;}
//liefert die anzahl der noch freien Speicherplätze zurück
int getFreeCount() {return m_iTop;}
int getObjectCount() {return m_iNumObject;}
FLDataType** getDataPointer() {return m_ppFreeObjects;}
private:
FLDataType* m_pObjectData; //Zeiger auf den reservieretn Speicher

View File

@ -0,0 +1,96 @@
#include "MemoryPage.h"
#include "../SingletonManager/ErrorManager.h"
/*
unsigned char* m_pObjectData; //Zeiger auf den reservieretn Speicher
unsigned char** m_ppFreeObjects; //Zeiger auf die anderen Zeiger
Poco::UInt16 m_iNumObject; //Anzahl der Objecte
Poco::UInt16 m_ibFreeOnDestroy; //Weiß nicht
Poco::UInt16 m_iTop; //Keine Ahnung
Poco::UInt16 m_size;
*/
MemoryPage::MemoryPage(Poco::UInt16 iNumObjects, Poco::UInt16 objectSize)
: m_pObjectData(nullptr), m_ppFreeObjects(nullptr), m_iNumObject(iNumObjects), m_iTop(0), m_size(objectSize)
{
//Fehler abfangen
//ASSERT(iNumObjects > 0);
//if (iNumObjects <= 0) LOG_ERROR_VOID("not enough objects ");
//Speicher reservieren
m_pObjectData = (unsigned char*)malloc(objectSize * iNumObjects);
//m_pObjectData = new FLDataType[iNumObjects];
m_ppFreeObjects = new unsigned char*[iNumObjects];
//Checken ob der Speicher reserviert wurde
// ASSERT(m_pObjectData);
// ASSERT(m_ppFreeObjects);
// if (!m_pObjectData || !m_ppFreeObjects) LOG_ERROR_VOID("Es konnte kein Speicher reserviert werden!");
if (!m_pObjectData || !m_ppFreeObjects) {
auto em = ErrorManager::getInstance();
em->addError(new ParamError("MemoryPage", "error reserving memory, memory size:", std::to_string(objectSize * iNumObjects)));
em->sendErrorsAsEmail();
return;
}
//Zeiger zuweisen
FillStack();
}
MemoryPage::~MemoryPage()
{
if (m_pObjectData) {
free(m_pObjectData);
m_pObjectData = nullptr;
}
if (m_ppFreeObjects) {
delete[] m_ppFreeObjects;
m_ppFreeObjects = nullptr;
}
m_iNumObject = 0;
m_iTop = 0;
}
//****************************************************************************++
void MemoryPage::FillStack()
{
int iIndex = m_iNumObject - 1;
//Die Zeiger in m_ppFreeObjects werden von vorne nach hinten,
//von hinten nach vorne auf den reservierten Speicher ausgerichtet
for (m_iTop = 0; m_iTop < m_iNumObject; m_iTop++)
{
m_ppFreeObjects[m_iTop] = &(m_pObjectData[iIndex--]);
}
}
//*********************************************************************************
unsigned char* MemoryPage::NewInstance()
{
// ASSERT(m_iTop);
if (m_iTop <= 0)
{
return nullptr;
//LOG_ERROR("Kein Platz mehr in der Liste!", NULL);
}
return m_ppFreeObjects[--m_iTop];
}
//********************************************************************************
void MemoryPage::FreeInstance(unsigned char* pInstance)
{
//Fehler kontrolle
// ASSERT(pInstance >= &(m_pObjectData[0]) &&
// pInstance < &(m_pObjectData[m_iNumObject]));
// ASSERT(m_iTop < m_iNumObject);
m_ppFreeObjects[m_iTop++] = pInstance;
}

83
src/cpp/lib/MemoryPage.h Normal file
View File

@ -0,0 +1,83 @@
/*/*************************************************************************
* *
* Core, Core-Lib for my programs, Core doesn't need any libraries *
* Copyright (C) 2012, 2013, 2014 Dario Rekowski *
* Email: ***REMOVED*** Web: ***REMOVED*** *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
* *
***************************************************************************/
/*
Speichermanager mit Free Listen
Damit man häufig Speicher reservieren kann ohne den
Speicher zu defragmentieren.
Nach einem Artikel aus Gems4: "Speicherfragmentierung mit Templated Free-Lists bekämmpfen"
von Paul Glinker Rockstar Games Toronto
Programmierer: Dario Rekowski
@date 01.11.2019
removed template, use malloc and size
*/
//DRLogger Log;
//Deklaration
//#ifdef _TEMPLATEFREE_
#ifndef __DR_CORE2_MEMORY_LIST2__
#define __DR_CORE2_MEMORY_LIST2__
#include "Poco/Types.h"
class MemoryPage
{
public:
//Standard Konstruktor
MemoryPage(Poco::UInt16 iNumObjects, Poco::UInt16 objectSize);
//Deskonstruktor, wichtig!!
~MemoryPage();
//füllt den Zeigerstack (Stapel)
void FillStack();
//Liefert den Zeiger auf einen freien Spiecherplatz zurück
unsigned char* NewInstance();
//Und die Instance freigeben
void FreeInstance(unsigned char* pInstance);
//liefert die anzahl der noch freien Speicherplätze zurück
Poco::UInt16 getFreeCount() { return m_iTop; }
Poco::UInt16 getObjectCount() { return m_iNumObject; }
private:
unsigned char* m_pObjectData; //Zeiger auf den reservieretn Speicher
unsigned char** m_ppFreeObjects; //Zeiger auf die anderen Zeiger
Poco::UInt16 m_iNumObject; //Anzahl der Objecte
Poco::UInt16 m_iTop; //Keine Ahnung
Poco::UInt16 m_size;
};
//******************************************************************************++
//Funktionen
#endif //__DR_CORE2_MEMORY_LIST2__
//#endif //_TEMPLATEFREE_

View File

@ -3,6 +3,9 @@
#include "proto/gradido/TransactionBody.pb.h"
#include "model/User.h"
#include "model/Session.h"
int main(int argc, char** argv)
{
GOOGLE_PROTOBUF_VERIFY_VERSION;
@ -11,6 +14,7 @@ int main(int argc, char** argv)
printf("error initing sodium, early exit\n");
return -1;
}
printf("User size: %d Bytes, Session size: %d Bytes\n", sizeof(User), sizeof(Session));
Gradido_LoginServer app;
return app.run(argc, argv);

View File

@ -3,7 +3,7 @@
#include "Poco/Data/Session.h"
#include "../tasks/MultithreadContainer.h"
#include "../lib/MultithreadContainer.h"
#include "../tasks/CPUTask.h"
#include "../MySQL/MysqlTable.h"

View File

@ -10,10 +10,10 @@
#ifndef DR_LUA_WEB_MODULE_SESSION_SESSION_H
#define DR_LUA_WEB_MODULE_SESSION_SESSION_H
#include "ErrorList.h"
#include "../lib/ErrorList.h"
#include "User.h"
#include "../tasks/MultithreadContainer.h"
#include "../lib/MultithreadContainer.h"
#include "../tasks/ProcessingTransaction.h"
#include "Poco/Thread.h"

View File

@ -9,7 +9,7 @@
#ifndef GRADIDO_LOGIN_SERVER_MODEL_TRANSACTION_BASE_INCLUDE
#define GRADIDO_LOGIN_SERVER_MODEL_TRANSACTION_BASE_INCLUDE
#include "ErrorList.h"
#include "../lib/ErrorList.h"
#include "../proto/gradido/BasicTypes.pb.h"
class TransactionBase : public ErrorList

View File

@ -1,5 +1,4 @@
#include "User.h"
#include "Profiler.h"
#include "Session.h"
#include <sodium.h>
#include "ed25519/ed25519.h"
@ -10,6 +9,7 @@
#include "../SingletonManager/ErrorManager.h"
#include "../SingletonManager/SessionManager.h"
#include "Poco/Data/Binding.h"
using namespace Poco::Data::Keywords;
@ -44,7 +44,7 @@ int UserCreateCryptoKey::run()
int UserGenerateKeys::run()
{
Profiler timeUsed;
// always return true, cannot fail (only if low on memory)
mKeys.generateFromPassphrase(mPassphrase.data(), &ServerConfig::g_Mnemonic_WordLists[ServerConfig::MNEMONIC_BIP0039_SORTED_ORDER]);
@ -53,8 +53,6 @@ int UserGenerateKeys::run()
mUser->setPrivKey(mKeys.getPrivateKey());
}
//printf("[UserGenerateKeys::run] time: %s\n", timeUsed.string().data());
return 0;
}
@ -98,7 +96,6 @@ UserWriteKeysIntoDB::UserWriteKeysIntoDB(UniLib::controller::TaskPtr parent, Poc
int UserWriteKeysIntoDB::run()
{
Profiler timeUsed;
auto cm = ConnectionManager::getInstance();
auto em = ErrorManager::getInstance();
auto session = cm->getConnection(CONNECTION_MYSQL_LOGIN_SERVER);
@ -154,7 +151,6 @@ int UserWriteKeysIntoDB::run()
delete pprivkey_blob;
}
//printf("UserWritePrivKeyIntoDB time: %s\n", timeUsed.string().data());
return 0;
}
@ -220,10 +216,12 @@ User::User(const char* email)
}
if (!privkey.isNull()) {
auto privkey_value = privkey.value();
mPrivateKey = new ObfusArray(privkey_value.size(), privkey_value.content().data());
auto privkey_size = privkey_value.size();
//mPrivateKey = new ObfusArray(privkey_value.size(), privkey_value.content().data());
mPrivateKey = MemoryManager::getInstance()->getFreeMemory(privkey_size);
memcpy(*mPrivateKey, privkey_value.content().data(), privkey_size);
}
}
} catch(Poco::Exception& ex) {
addError(new ParamError("User::User", "mysql error", ex.displayText().data()));
@ -265,7 +263,10 @@ User::User(int user_id)
}
if (!privkey.isNull()) {
auto privkey_value = privkey.value();
mPrivateKey = new ObfusArray(privkey_value.size(), privkey_value.content().data());
auto privkey_size = privkey_value.size();
//mPrivateKey = new ObfusArray(privkey_value.size(), privkey_value.content().data());
mPrivateKey = MemoryManager::getInstance()->getFreeMemory(privkey_size);
memcpy(*mPrivateKey, privkey_value.content().data(), privkey_size);
}
}
}
@ -308,7 +309,10 @@ User::User(const unsigned char* pubkey_array)
if (!privkey.isNull()) {
auto privkey_value = privkey.value();
mPrivateKey = new ObfusArray(privkey_value.size(), privkey_value.content().data());
auto privkey_size = privkey_value.size();
//mPrivateKey = new ObfusArray(privkey_value.size(), privkey_value.content().data());
mPrivateKey = MemoryManager::getInstance()->getFreeMemory(privkey_size);
memcpy(*mPrivateKey, privkey_value.content().data(), privkey_size);
}
}
@ -325,12 +329,15 @@ User::~User()
#ifdef DEBUG_USER_DELETE_ENV
printf("[User::~User]\n");
#endif
auto mm = MemoryManager::getInstance();
if (mCryptoKey) {
delete mCryptoKey;
//delete mCryptoKey;
mm->releaseMemory(mCryptoKey);
mCryptoKey = nullptr;
}
if (mPrivateKey) {
delete mPrivateKey;
//delete mPrivateKey;
mm->releaseMemory(mPrivateKey);
mPrivateKey = nullptr;
}
}
@ -483,7 +490,7 @@ void User::setEmailChecked()
bool User::validatePwd(const std::string& pwd, ErrorList* validationErrorsToPrint)
{
auto mm = MemoryManager::getInstance();
auto cmpCryptoKey = createCryptoKey(pwd);
if (sizeof(User::passwordHashed) != crypto_shorthash_BYTES) {
throw Poco::Exception("crypto_shorthash_BYTES != sizeof(User::passwordHashed)");
@ -496,12 +503,14 @@ bool User::validatePwd(const std::string& pwd, ErrorList* validationErrorsToPrin
mCryptoKey = cmpCryptoKey;
}
else {
delete cmpCryptoKey;
//delete cmpCryptoKey;
mm->releaseMemory(cmpCryptoKey);
}
unlock();
return true;
}
delete cmpCryptoKey;
//delete cmpCryptoKey;
mm->releaseMemory(cmpCryptoKey);
unlock();
return false;
@ -588,10 +597,11 @@ void User::release()
}
ObfusArray* User::createCryptoKey(const std::string& password)
MemoryBin* User::createCryptoKey(const std::string& password)
{
Profiler timeUsed;
//Profiler timeUsed;
auto mm = MemoryManager::getInstance();
// TODO: put it in secure location, or use value from server config
static const unsigned char app_secret[] = { 0x21, 0xff, 0xbb, 0xc6, 0x16, 0xfe };
@ -611,9 +621,13 @@ ObfusArray* User::createCryptoKey(const std::string& password)
sha512_update(&context_sha512, app_secret, 6);
sha512_final(&context_sha512, hash512_salt);
unsigned char* key = (unsigned char *)malloc(crypto_box_SEEDBYTES); // 32U
if (crypto_pwhash(key, crypto_box_SEEDBYTES, password.data(), password.size(), hash512_salt, 10U, 33554432, 2) != 0) {
//unsigned char* key = (unsigned char *)malloc(crypto_box_SEEDBYTES); // 32U
//ObfusArray* key = new ObfusArray(crypto_box_SEEDBYTES);
auto key = mm->getFreeMemory(crypto_box_SEEDBYTES);
//Bin32Bytes* key = mm->get32Bytes();
if (crypto_pwhash(*key, key->size(), password.data(), password.size(), hash512_salt, 10U, 33554432, 2) != 0) {
lock();
addError(new ParamError(__FUNCTION__, " error creating pwd hash, maybe to much memory requestet? error:", strerror(errno)));
unlock();
@ -622,14 +636,14 @@ ObfusArray* User::createCryptoKey(const std::string& password)
return nullptr;
}
lock();
auto cryptoKey = new ObfusArray(crypto_box_SEEDBYTES, key);
unlock();
free(key);
// lock();
// auto cryptoKey = new ObfusArray(crypto_box_SEEDBYTES, key);
// unlock();
// free(key);
// mCryptoKey
//printf("[User::createCryptoKey] time used: %s\n", timeUsed.string().data());
return cryptoKey;
return key;
}
void User::fakeCreateCryptoKey()
@ -639,7 +653,7 @@ void User::fakeCreateCryptoKey()
bool User::generateKeys(bool savePrivkey, const std::string& passphrase, Session* session)
{
Profiler timeUsed;
//Profiler timeUsed;
duplicate();
UniLib::controller::TaskPtr generateKeysTask(new UserGenerateKeys(this, passphrase));
@ -671,7 +685,7 @@ bool User::generateKeys(bool savePrivkey, const std::string& passphrase, Session
}
ObfusArray* User::encrypt(const ObfusArray* data)
MemoryBin* User::encrypt(const MemoryBin* data)
{
if (!hasCryptoKey()) {
addError(new Error("User::encrypt", "hasn't crypto key"));
@ -684,27 +698,30 @@ ObfusArray* User::encrypt(const ObfusArray* data)
// we use a hardcoded value for nonce
memset(nonce, 31, crypto_secretbox_NONCEBYTES);
unsigned char* ciphertext = (unsigned char*)malloc(ciphertext_len);
memset(ciphertext, 0, ciphertext_len);
lock();
if (0 != crypto_secretbox_easy(ciphertext, *data, message_len, nonce, *mCryptoKey)) {
//unsigned char* ciphertext = (unsigned char*)malloc(ciphertext_len);
//ObfusArray* ciphertext = new ObfusArray(ciphertext_len);
auto mm = MemoryManager::getInstance();
auto ciphertext = mm->getFreeMemory(ciphertext_len);
memset(*ciphertext, 0, ciphertext_len);
if (0 != crypto_secretbox_easy(*ciphertext, *data, message_len, nonce, *mCryptoKey)) {
//printf("[%s] error encrypting message \n", __FUNCTION__);
addError(new Error("User::encrypt", "encrypting message failed"));
free(ciphertext);
unlock();
//free(ciphertext);
mm->releaseMemory(ciphertext);
return nullptr;
}
unlock();
//printf("[User::encrypt] encrypted: %s, ciphertext len: %u\n", KeyPair::getHex(ciphertext, ciphertext_len).data(), ciphertext_len);
auto resultObfus = new ObfusArray(ciphertext_len, ciphertext);
free(ciphertext);
//auto resultObfus = new ObfusArray(ciphertext_len, ciphertext);
//free(ciphertext);
return resultObfus;
return ciphertext;
}
ObfusArray* User::decrypt(const ObfusArray* encryptedData)
MemoryBin* User::decrypt(const MemoryBin* encryptedData)
{
if (!hasCryptoKey()) {
addError(new Error("User::decrypt", "hasn't crypto key"));
@ -714,13 +731,16 @@ ObfusArray* User::decrypt(const ObfusArray* encryptedData)
//ObfusArray* decrypetData = new ObfusArray(encryptedData->size() - crypto_secretbox_MACBYTES);
size_t decryptSize = encryptedData->size() - crypto_secretbox_MACBYTES;
unsigned char* decryptBuffer = (unsigned char*)malloc(decryptSize);
//unsigned char* decryptBuffer = (unsigned char*)malloc(decryptSize);
auto mm = MemoryManager::getInstance();
//ObfusArray* decryptedData = new ObfusArray(decryptSize);
auto decryptedData = mm->getFreeMemory(decryptSize);
unsigned char nonce[crypto_secretbox_NONCEBYTES];
// we use a hardcoded value for nonce
memset(nonce, 31, crypto_secretbox_NONCEBYTES);
if (crypto_secretbox_open_easy(decryptBuffer, *encryptedData, encryptedData->size(), nonce, *mCryptoKey)) {
free(decryptBuffer);
if (crypto_secretbox_open_easy(*decryptedData, *encryptedData, encryptedData->size(), nonce, *mCryptoKey)) {
mm->releaseMemory(decryptedData);
addError(new Error("User::decrypt", "error decrypting"));
return nullptr;
}
@ -728,36 +748,50 @@ ObfusArray* User::decrypt(const ObfusArray* encryptedData)
unsigned long long clen, const unsigned char *n,
const unsigned char *k);*/
ObfusArray* decryptedData = new ObfusArray(decryptSize, decryptBuffer);
free(decryptBuffer);
return decryptedData;
}
ObfusArray* User::sign(const unsigned char* message, size_t messageSize)
MemoryBin* User::sign(const unsigned char* message, size_t messageSize)
{
/*
if (!message || !messageSize) return nullptr;
if (!hasCryptoKey()) {
addError(new Error("User::sign", "hasn't crypto key"));
return nullptr;
}
//binArrayObj = new BinaryArray(crypto_sign_BYTES);
unsigned char* signBinBuffer = (unsigned char*)malloc(crypto_sign_BYTES);
crypto_sign_detached(signBinBuffer, NULL, message, messageSize, key->sodium_secret);
if (crypto_sign_verify_detached(binArrayObj->bytes, binArray, binArraySize, key->sodium_public) != 0) {
// Incorrect signature!
printf("c[KeyBuffer::%s] sign verify failed\n", __FUNCTION__);
if (!mPrivateKey) {
addError(new Error("User::sign", "hasn't privkey"));
return nullptr;
}
size_t hex_sig_size = crypto_sign_BYTES * 2;
char sig_hex[crypto_sign_BYTES * 2 + 1];
sodium_bin2hex(sig_hex, hex_sig_size + 1, binArrayObj->bytes, crypto_sign_BYTES);
printf("c[KeyBuffer::%s] signature hex: %s\n", __FUNCTION__, sig_hex);
*/
return nullptr;
//binArrayObj = new BinaryArray(crypto_sign_BYTES);
auto mm = MemoryManager::getInstance();
//auto signBinBuffer = (unsigned char*)malloc(crypto_sign_BYTES);
auto signBinBuffer = mm->getFreeMemory(crypto_sign_BYTES);
auto privKey = decrypt(mPrivateKey);
crypto_sign_detached(*signBinBuffer, NULL, message, messageSize, *privKey);
if (crypto_sign_verify_detached(*signBinBuffer, message, messageSize, *privKey) != 0) {
// Incorrect signature!
//printf("c[KeyBuffer::%s] sign verify failed\n", __FUNCTION__);
auto em = ErrorManager::getInstance();
em->addError(new Error("User::sign", "sign verify failed"));
em->sendErrorsAsEmail();
mm->releaseMemory(privKey);
mm->releaseMemory(signBinBuffer);
return nullptr;
}
// debug
const size_t hex_sig_size = crypto_sign_BYTES * 2 + 1;
char sig_hex[hex_sig_size];
sodium_bin2hex(sig_hex, hex_sig_size, *signBinBuffer, crypto_sign_BYTES);
printf("[User::sign] signature hex: %s\n", sig_hex);
mm->releaseMemory(privKey);
return signBinBuffer;
}
Poco::Data::Statement User::insertIntoDB(Poco::Data::Session session)
@ -848,7 +882,7 @@ const char* User::userStateToString(UserStates state)
return "- unknown -";
}
ObfusArray* User::getPrivKey()
MemoryBin* User::getPrivKey()
{
if (!mPrivateKey) {
addError(new Error("User::getPrivKey", "no private key saved"));
@ -861,7 +895,7 @@ ObfusArray* User::getPrivKey()
return decrypt(mPrivateKey);
}
bool User::setPrivKey(const ObfusArray* privKey)
bool User::setPrivKey(const MemoryBin* privKey)
{
if (!hasCryptoKey()) {
lock();

View File

@ -11,7 +11,8 @@
#include "Poco/JSON/Object.h"
#include "../tasks/CPUTask.h"
class NewUser;
#include "../SingletonManager/MemoryManager.h"
class UserCreateCryptoKey;
class UserWriteIntoDB;
class Session;
@ -41,7 +42,6 @@ enum UserFields
class User : public ErrorList
{
friend NewUser;
friend UserCreateCryptoKey;
friend UserWriteIntoDB;
friend UserWriteCryptoKeyHashIntoDB;
@ -90,9 +90,9 @@ public:
bool validatePwd(const std::string& pwd, ErrorList* validationErrorsToPrint);
bool validateIdentHash(HASH hash);
ObfusArray* encrypt(const ObfusArray* data);
ObfusArray* decrypt(const ObfusArray* encryptedData);
ObfusArray* sign(const unsigned char* message, size_t messageSize);
MemoryBin* encrypt(const MemoryBin* data);
MemoryBin* decrypt(const MemoryBin* encryptedData);
MemoryBin* sign(const unsigned char* message, size_t messageSize);
Poco::JSON::Object getJson();
@ -105,8 +105,8 @@ public:
protected:
typedef Poco::UInt64 passwordHashed;
ObfusArray* createCryptoKey(const std::string& password);
inline void setCryptoKey(ObfusArray* cryptoKey) { lock(); mCryptoKey = cryptoKey; unlock(); }
MemoryBin* createCryptoKey(const std::string& password);
inline void setCryptoKey(MemoryBin* cryptoKey) { lock(); mCryptoKey = cryptoKey; unlock(); }
//void detectState();
@ -118,8 +118,8 @@ protected:
inline void lock() { mWorkingMutex.lock(); }
inline void unlock() { mWorkingMutex.unlock(); }
ObfusArray* getPrivKey();
bool setPrivKey(const ObfusArray* privKey);
MemoryBin* getPrivKey();
bool setPrivKey(const MemoryBin* privKey);
private:
UserStates mState;
@ -133,7 +133,7 @@ private:
passwordHashed mPasswordHashed;
std::string mPublicHex;
ObfusArray* mPrivateKey;
MemoryBin* mPrivateKey;
// TODO: insert created if necessary
bool mEmailChecked;
@ -141,7 +141,7 @@ private:
// ************************ DB FIELDS END ******************************
// crypto key as obfus array
// only in memory, if user has typed in password
ObfusArray* mCryptoKey;
MemoryBin* mCryptoKey;
Poco::Mutex mWorkingMutex;
Poco::Mutex mReferenceMutex;

View File

@ -39,7 +39,7 @@
#include "Poco/AutoPtr.h"
#include "MultithreadQueue.h"
#include "../lib/MultithreadQueue.h"
namespace UniLib {
namespace controller {