mirror of
https://github.com/RetroShare/RetroShare.git
synced 2025-01-13 08:29:32 -05:00
merging distrib split into trunk
suppressed p3distrib in services git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@4600 b45a01b8-16f6-495d-af2f-9b41ad6348cc
This commit is contained in:
parent
dc0f4ef68a
commit
7e8d8aea9c
File diff suppressed because it is too large
Load Diff
@ -1,9 +1,9 @@
|
||||
/*
|
||||
* libretroshare/src/services: p3distrib.h
|
||||
* libretroshare/src/distrib: p3distrib.h
|
||||
*
|
||||
* 3P/PQI network interface for RetroShare.
|
||||
*
|
||||
* Copyright 2004-2008 by Robert Fernie.
|
||||
* Copyright 2004-2011 by Robert Fernie.
|
||||
* 2010-2011 Christopher Evi-Parker
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
@ -56,42 +56,6 @@
|
||||
|
||||
const uint32_t GROUP_MAX_FWD_OFFSET = (60 * 60 * 24 * 2); /* 2 Days */
|
||||
|
||||
/************* The Messages that are serialised ****************/
|
||||
|
||||
#if 0
|
||||
|
||||
class RsConfigDistrib: public RsSerialType
|
||||
{
|
||||
public:
|
||||
|
||||
RsConfigDistrib();
|
||||
|
||||
};
|
||||
|
||||
class RsSerialDistrib: public RsSerialType
|
||||
{
|
||||
public:
|
||||
|
||||
RsSerialDistrib();
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/************* The Messages that are serialised ****************/
|
||||
|
||||
#if 0
|
||||
const uint32_t GROUP_KEY_TYPE_MASK = 0x000f;
|
||||
const uint32_t GROUP_KEY_DISTRIB_MASK = 0x00f0;
|
||||
|
||||
const uint32_t GROUP_KEY_TYPE_PUBLIC_ONLY = 0x0001;
|
||||
const uint32_t GROUP_KEY_TYPE_FULL = 0x0002;
|
||||
const uint32_t GROUP_KEY_DISTRIB_PUBLIC = 0x0010;
|
||||
const uint32_t GROUP_KEY_DISTRIB_PRIVATE = 0x0020;
|
||||
const uint32_t GROUP_KEY_DISTRIB_ADMIN = 0x0040;
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* A data structure to store dummy (missing) msgs.
|
||||
@ -243,26 +207,9 @@ const uint32_t GRP_SUBSCRIBED = 0x0005;
|
||||
const uint32_t GRP_UNSUBSCRIBED = 0x0006;
|
||||
|
||||
|
||||
typedef std::map<std::string, std::list<CacheData> > CacheOptData;
|
||||
|
||||
|
||||
typedef std::pair<std::string, pugi::xml_node > grpNodePair; // (is loaded, iterator pointing to node)
|
||||
|
||||
// these make up a cache list
|
||||
typedef std::pair<std::string, uint16_t> pCacheId; //(pid, subid)
|
||||
typedef std::pair<std::string, pCacheId> grpCachePair; // (grpid, cid)
|
||||
|
||||
/*!
|
||||
* grp node content for faster access
|
||||
*/
|
||||
struct nodeCache
|
||||
{
|
||||
bool cached;
|
||||
pugi::xml_node_iterator it;
|
||||
pCacheId cid;
|
||||
std::set<pCacheId> cIdSet;
|
||||
pugi::xml_node node;
|
||||
};
|
||||
|
||||
//! Cache based service to implement group messaging
|
||||
/*!
|
||||
*
|
||||
@ -338,87 +285,6 @@ class p3GroupDistrib: public CacheSource, public CacheStore, public p3Config, pu
|
||||
void HistoricalCachesDone(); // called when Stored Caches have been added to Pending List.
|
||||
|
||||
|
||||
|
||||
private:
|
||||
|
||||
/*!
|
||||
* called when all historical caches have been loaded
|
||||
*/
|
||||
void HistoricalCachesLoaded();
|
||||
|
||||
/*!
|
||||
* This updates the cache document with pending msg and grp cache data
|
||||
*/
|
||||
void updateCacheDocument();
|
||||
|
||||
/*!
|
||||
* @param grpIter this is a list of iterators point to newly added grp nodes
|
||||
*/
|
||||
void locked_updateCacheTableGrp(const std::vector<grpNodePair>& grpNodes, bool historical);
|
||||
|
||||
/*!
|
||||
* @param msgCacheMap each entry a set of cache ids that are to be loaded if grpId(entry) is requested to be cached
|
||||
*/
|
||||
void locked_updateCacheTableMsg(const std::map<std::string, std::set<pCacheId> >& msgCacheMap);
|
||||
|
||||
/*!
|
||||
* @param grpId indicates which grp entry to update
|
||||
* @param cached pass as true to update entry as true and vice versa
|
||||
*/
|
||||
void locked_updateCacheTableEntry(const std::string& grpId, bool cached);
|
||||
|
||||
|
||||
/*!
|
||||
* TODO: will be used to unpack cache doc from config load
|
||||
* @param cacheBinDoc contains cache document as binary
|
||||
*/
|
||||
bool loadCacheDoc(RsDistribConfigData& cacheBinDoc);
|
||||
|
||||
|
||||
/*!
|
||||
* to find if grps messages have been loaded (assumes grps have been loaded first)
|
||||
* @param cached true if grp has been loaded, false if not
|
||||
* @return true is grp entry does not exist in table, false if not
|
||||
*/
|
||||
bool locked_historyCached(const std::string& grpId, bool& cached);
|
||||
|
||||
/*!
|
||||
* @param cache cache data id
|
||||
* @return false if cache entry does not exist in table
|
||||
*/
|
||||
bool locked_historyCached(const pCacheId& cId);
|
||||
|
||||
/*!
|
||||
* builds cache table from loaded cached document
|
||||
* @return false if cache document is empty
|
||||
*/
|
||||
bool locked_buildCacheTable(void);
|
||||
|
||||
/*!
|
||||
* if grp's message is not loaded, load it, and update cache table
|
||||
* @param grpId group whose messages to load if not cached
|
||||
*/
|
||||
void locked_processHistoryCached(const std::string& grpId);
|
||||
|
||||
|
||||
/*!
|
||||
* loads cache data which contains location of cache files belonging
|
||||
* to group
|
||||
* @param grpId grp for which to get list of cache data
|
||||
* @param cDataSet cache data belonging to grp is loaded into this list
|
||||
*/
|
||||
void locked_getHistoryCacheData(const std::string& grpId, std::list<CacheData>& cDataSet);
|
||||
|
||||
/*!
|
||||
* encrypts and saves cache file
|
||||
*/
|
||||
bool locked_saveHistoryCacheFile();
|
||||
|
||||
/*!
|
||||
* decrypte and save cache file
|
||||
*/
|
||||
bool locked_loadHistoryCacheFile();
|
||||
|
||||
private:
|
||||
|
||||
/* these lists are filled by the overloaded fns... then cleared by the thread */
|
||||
@ -429,9 +295,8 @@ class p3GroupDistrib: public CacheSource, public CacheStore, public p3Config, pu
|
||||
int loadAnyCache(const CacheData &data, bool local, bool historical);
|
||||
|
||||
/* load cache files */
|
||||
void loadFileGroups(const std::string &filename, const std::string &src, bool local, bool historical, const pCacheId& cid);
|
||||
void loadFileMsgs(const std::string &filename, uint16_t cacheSubId, const std::string &src, uint32_t ts, bool local, bool historical);
|
||||
void locked_loadFileMsgs(const std::string &filename, uint16_t cacheSubId, const std::string &src, uint32_t ts, bool local, bool historical);
|
||||
void loadFileGroups(const std::string &filename, const std::string &src, bool local, bool historical);
|
||||
void loadFileMsgs(const std::string &filename, const CacheData& , bool local, bool historical);
|
||||
bool backUpKeys(const std::list<RsDistribGrpKey* > &keysToBackUp, std::string grpId);
|
||||
void locked_sharePubKey();
|
||||
|
||||
@ -439,12 +304,28 @@ class p3GroupDistrib: public CacheSource, public CacheStore, public p3Config, pu
|
||||
* Attempt to load public key from recvd list if it exists for grpId
|
||||
* @param grpId the id for the group for which private publish key is wanted
|
||||
*/
|
||||
bool attemptPublishKeysRecvd();
|
||||
bool attemptPublishKeysRecvd();
|
||||
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
* Simply load cache opt messages
|
||||
* @param data
|
||||
*/
|
||||
void loadCacheOptMsgs(const CacheData& data, const std::string& grpId);
|
||||
|
||||
protected:
|
||||
|
||||
/* load cache msgs */
|
||||
|
||||
/*!
|
||||
* processes cache opt request by loading data for group
|
||||
* @param grpId the group to process request for
|
||||
* @return false if group does not exist
|
||||
*/
|
||||
bool processCacheOptReq(std::string grpId);
|
||||
|
||||
/*!
|
||||
* msg is loaded to its group and republished,
|
||||
* msg decrypted if grp is private
|
||||
@ -688,26 +569,6 @@ class p3GroupDistrib: public CacheSource, public CacheStore, public p3Config, pu
|
||||
*/
|
||||
virtual bool locked_editGroup(std::string grpId, GroupInfo& gi);
|
||||
|
||||
/*!
|
||||
* Encrypts data using envelope encryption (taken from open ssl's evp_sealinit )
|
||||
* only full publish key holders can encrypt data for given group
|
||||
*@param out
|
||||
*@param outlen
|
||||
*@param in
|
||||
*@param inlen
|
||||
*/
|
||||
virtual bool encrypt(void *&out, int &outlen, const void *in, int inlen, std::string grpId);
|
||||
|
||||
|
||||
/**
|
||||
* Decrypts data using evelope decryption (taken from open ssl's evp_sealinit )
|
||||
* only full publish key holders can decrypt data for a group
|
||||
*@param out where decrypted data is written to
|
||||
*@param outlen
|
||||
*@param in
|
||||
*@param inlen
|
||||
*/
|
||||
virtual bool decrypt(void *&out, int &outlen, const void *in, int inlen, std::string grpId);
|
||||
|
||||
/***************************************************************************************/
|
||||
/***************************************************************************************/
|
||||
@ -730,12 +591,6 @@ class p3GroupDistrib: public CacheSource, public CacheStore, public p3Config, pu
|
||||
*/
|
||||
virtual pqistore *createStore(BinInterface *bio, const std::string &src, uint32_t bioflags);
|
||||
|
||||
/*!
|
||||
* checks to see if admin signature is valid
|
||||
* @param newGrp grp to validate
|
||||
* @return true if group's signature is valid
|
||||
*/
|
||||
virtual bool validateDistribGrp(RsDistribGrp *newGrp);
|
||||
virtual bool locked_checkGroupInfo(GroupInfo &info, RsDistribGrp *newGrp);
|
||||
virtual bool locked_updateGroupInfo(GroupInfo &info, RsDistribGrp *newGrp);
|
||||
virtual bool locked_checkGroupKeys(GroupInfo &info);
|
||||
@ -755,15 +610,6 @@ class p3GroupDistrib: public CacheSource, public CacheStore, public p3Config, pu
|
||||
*/
|
||||
virtual bool locked_updateGroupPublishKey(GroupInfo &info, RsDistribGrpKey *newKey);
|
||||
|
||||
|
||||
/*!
|
||||
* uses groupinfo public key to verify signature of signed message
|
||||
* @param info groupinfo for which msg is meant for
|
||||
* @param msg
|
||||
* @return false if verfication of signature is not passed
|
||||
*/
|
||||
virtual bool locked_validateDistribSignedMsg(GroupInfo &info, RsDistribSignedMsg *msg);
|
||||
|
||||
/*!
|
||||
* Use this to retrieve packed message from a signed message
|
||||
* @param newMsg signed message
|
||||
@ -871,28 +717,31 @@ RsDistribDummyMsg *locked_getGroupDummyMsg(const std::string& grpId, const std::
|
||||
std::set<std::string> mPubKeyAvailableGrpId; // groups id for which public keys are available
|
||||
time_t mLastKeyPublishTime, mLastRecvdKeyTime;
|
||||
|
||||
////////////// cache optimisation ////////////////
|
||||
int mCount;
|
||||
/// table containing new msg cache data to be added to xml doc ( grpid, (cid,pid) )
|
||||
std::vector<grpCachePair> mGrpHistPending;
|
||||
|
||||
/// table containing new grp cache data to be added to xml doc (grpid, (cid,pid) )
|
||||
std::vector<grpCachePair> mMsgHistPending;
|
||||
/**** cache opt ****/
|
||||
|
||||
std::set<pCacheId> mCachePairsInTable, mCacheFailedTable;
|
||||
/*
|
||||
* 1. when rs starts it loads only subscribed groups
|
||||
* 2. and for unsubscribed groups these are store with their grp to cache mappings
|
||||
* 3. when user clicks on a group this activates process cache which loads cache for only that group
|
||||
*
|
||||
*/
|
||||
|
||||
std::list<CacheDataPending> mPendingHistCaches;
|
||||
/// stores map of grp to cache mapping
|
||||
CacheOptData mGrpCacheMap;
|
||||
|
||||
/// group subscribed to at start of rs
|
||||
std::set<std::string> mSubscribedGrp;
|
||||
|
||||
/// unsubscribed groups that are already loaded
|
||||
std::set<std::string> mCacheOptLoaded;
|
||||
|
||||
/// current exception group
|
||||
std::string mCurrGrpException;
|
||||
|
||||
std::map<CacheId, CacheData> mLocalHistCachesAvail;
|
||||
|
||||
time_t mLastCacheDocUpdate;
|
||||
bool mUpdateCacheDoc, mHistoricalCachesLoaded;
|
||||
|
||||
std::map<std::string, nodeCache> mCacheTable; // (cid, node)
|
||||
|
||||
/// contains information on cached data
|
||||
pugi::xml_document mCacheDoc;
|
||||
|
||||
};
|
||||
|
||||
|
483
libretroshare/src/distrib/p3distribsecurity.cc
Normal file
483
libretroshare/src/distrib/p3distribsecurity.cc
Normal file
@ -0,0 +1,483 @@
|
||||
/*
|
||||
* libretroshare/src/distrib: p3distribverify.cc
|
||||
*
|
||||
*
|
||||
* Copyright 2008-2010 by Robert Fernie
|
||||
* 2011 Christopher Evi-Parker
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License Version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
* USA.
|
||||
*
|
||||
* Please report all bugs and problems to "retroshare@lunamutt.com".
|
||||
*
|
||||
*/
|
||||
|
||||
#include "p3distribsecurity.h"
|
||||
#include "pqi/authgpg.h"
|
||||
#include "retroshare/rsdistrib.h"
|
||||
#include "retroshare/rspeers.h"
|
||||
|
||||
|
||||
p3DistribSecurity::p3DistribSecurity()
|
||||
{
|
||||
}
|
||||
|
||||
p3DistribSecurity::~p3DistribSecurity()
|
||||
{
|
||||
}
|
||||
|
||||
RSA *p3DistribSecurity::extractPublicKey(RsTlvSecurityKey& key)
|
||||
{
|
||||
const unsigned char *keyptr = (const unsigned char *) key.keyData.bin_data;
|
||||
long keylen = key.keyData.bin_len;
|
||||
|
||||
/* extract admin key */
|
||||
RSA *rsakey = d2i_RSAPublicKey(NULL, &(keyptr), keylen);
|
||||
|
||||
return rsakey;
|
||||
}
|
||||
|
||||
|
||||
bool p3DistribSecurity::validateDistribSignedMsg(GroupInfo & info, RsDistribSignedMsg *newMsg)
|
||||
{
|
||||
#ifdef DISTRIB_DEBUG
|
||||
std::cerr << "p3GroupDistrib::locked_validateDistribSignedMsg()";
|
||||
std::cerr << std::endl;
|
||||
std::cerr << "GroupInfo -> distribGrp:";
|
||||
std::cerr << std::endl;
|
||||
info.distribGroup->print(std::cerr, 10);
|
||||
std::cerr << std::endl;
|
||||
std::cerr << "RsDistribSignedMsg: ";
|
||||
std::cerr << std::endl;
|
||||
newMsg->print(std::cerr, 10);
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
|
||||
#ifdef DISTRIB_DEBUG
|
||||
std::cerr << "p3GroupDistrib::locked_validateDistribSignedMsg() publish KeyId: " << newMsg->publishSignature.keyId << std::endl;
|
||||
std::cerr << "p3GroupDistrib::locked_validateDistribSignedMsg() personal KeyId: " << newMsg->personalSignature.keyId << std::endl;
|
||||
#endif
|
||||
|
||||
/********************* check signature *******************/
|
||||
|
||||
/* find the right key */
|
||||
RsTlvSecurityKeySet &keyset = info.distribGroup->publishKeys;
|
||||
|
||||
std::map<std::string, RsTlvSecurityKey>::iterator kit;
|
||||
kit = keyset.keys.find(newMsg->publishSignature.keyId);
|
||||
|
||||
if (kit == keyset.keys.end())
|
||||
{
|
||||
#ifdef DISTRIB_DEBUG
|
||||
std::cerr << "p3GroupDistrib::locked_validateDistribSignedMsg() Missing Publish Key";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
/* check signature timeperiod */
|
||||
if ((newMsg->timestamp < kit->second.startTS) ||
|
||||
(newMsg->timestamp > kit->second.endTS))
|
||||
{
|
||||
#ifdef DISTRIB_DEBUG
|
||||
std::cerr << "p3GroupDistrib::locked_validateDistribSignedMsg() TS out of range";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
/* decode key */
|
||||
const unsigned char *keyptr = (const unsigned char *) kit->second.keyData.bin_data;
|
||||
long keylen = kit->second.keyData.bin_len;
|
||||
unsigned int siglen = newMsg->publishSignature.signData.bin_len;
|
||||
unsigned char *sigbuf = (unsigned char *) newMsg->publishSignature.signData.bin_data;
|
||||
|
||||
#ifdef DISTRIB_DEBUG
|
||||
std::cerr << "p3GroupDistrib::locked_validateDistribSignedMsg() Decode Key";
|
||||
std::cerr << " keylen: " << keylen << " siglen: " << siglen;
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
|
||||
/* extract admin key */
|
||||
RSA *rsakey = d2i_RSAPublicKey(NULL, &(keyptr), keylen);
|
||||
|
||||
if (!rsakey)
|
||||
{
|
||||
#ifdef DISTRIB_DEBUG
|
||||
std::cerr << "p3GroupDistrib::locked_validateDistribSignedMsg()";
|
||||
std::cerr << " Invalid RSA Key";
|
||||
std::cerr << std::endl;
|
||||
|
||||
unsigned long err = ERR_get_error();
|
||||
std::cerr << "RSA Load Failed .... CODE(" << err << ")" << std::endl;
|
||||
std::cerr << ERR_error_string(err, NULL) << std::endl;
|
||||
|
||||
kit->second.print(std::cerr, 10);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
EVP_PKEY *signKey = EVP_PKEY_new();
|
||||
EVP_PKEY_assign_RSA(signKey, rsakey);
|
||||
|
||||
/* calc and check signature */
|
||||
EVP_MD_CTX *mdctx = EVP_MD_CTX_create();
|
||||
|
||||
EVP_VerifyInit(mdctx, EVP_sha1());
|
||||
EVP_VerifyUpdate(mdctx, newMsg->packet.bin_data, newMsg->packet.bin_len);
|
||||
int signOk = EVP_VerifyFinal(mdctx, sigbuf, siglen, signKey);
|
||||
|
||||
/* clean up */
|
||||
EVP_PKEY_free(signKey);
|
||||
EVP_MD_CTX_destroy(mdctx);
|
||||
|
||||
/* now verify Personal signature */
|
||||
if ((signOk == 1) && ((info.grpFlags & RS_DISTRIB_AUTHEN_MASK) & RS_DISTRIB_AUTHEN_REQ))
|
||||
{
|
||||
unsigned int personalsiglen =
|
||||
newMsg->personalSignature.signData.bin_len;
|
||||
unsigned char *personalsigbuf = (unsigned char *)
|
||||
newMsg->personalSignature.signData.bin_data;
|
||||
|
||||
RsPeerDetails signerDetails;
|
||||
std::string gpg_fpr;
|
||||
if (AuthGPG::getAuthGPG()->getGPGDetails(newMsg->personalSignature.keyId, signerDetails))
|
||||
{
|
||||
gpg_fpr = signerDetails.fpr;
|
||||
}
|
||||
|
||||
bool gpgSign = AuthGPG::getAuthGPG()->VerifySignBin(
|
||||
newMsg->packet.bin_data, newMsg->packet.bin_len,
|
||||
personalsigbuf, personalsiglen, gpg_fpr);
|
||||
if (gpgSign) {
|
||||
#ifdef DISTRIB_DEBUG
|
||||
std::cerr << "p3GroupDistrib::locked_validateDistribSignedMsg() Success for gpg signature." << std::endl;
|
||||
#endif
|
||||
signOk = 1;
|
||||
} else {
|
||||
#ifdef DISTRIB_DEBUG
|
||||
std::cerr << "p3GroupDistrib::locked_validateDistribSignedMsg() Fail for gpg signature." << std::endl;
|
||||
#endif
|
||||
signOk = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (signOk == 1)
|
||||
{
|
||||
#ifdef DISTRIB_DEBUG
|
||||
std::cerr << "p3GroupDistrib::locked_validateDistribSignedMsg() Signature OK";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef DISTRIB_DEBUG
|
||||
std::cerr << "p3GroupDistrib::locked_validateDistribSignedMsg() Signature invalid";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::string p3DistribSecurity::getBinDataSign(void *data, int len)
|
||||
{
|
||||
unsigned char *tmp = (unsigned char *) data;
|
||||
|
||||
// copy first CERTSIGNLEN bytes...
|
||||
if (len > CERTSIGNLEN)
|
||||
{
|
||||
len = CERTSIGNLEN;
|
||||
}
|
||||
|
||||
std::ostringstream id;
|
||||
for(uint32_t i = 0; i < CERTSIGNLEN; i++)
|
||||
{
|
||||
id << std::hex << std::setw(2) << std::setfill('0')
|
||||
<< (uint16_t) (((uint8_t *) (tmp))[i]);
|
||||
}
|
||||
std::string Id = id.str();
|
||||
|
||||
return Id;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool p3DistribSecurity::encrypt(void *& out, int & outlen, const void *in, int inlen, EVP_PKEY *privateKey)
|
||||
{
|
||||
|
||||
|
||||
#ifdef DISTRIB_DEBUG
|
||||
std::cerr << "p3DistribSecurity::encrypt() " << std::endl;
|
||||
#endif
|
||||
|
||||
RSA *rsa_publish_pub = NULL;
|
||||
EVP_PKEY *public_key = NULL;
|
||||
|
||||
RSA* rsa_publish = EVP_PKEY_get1_RSA(privateKey);
|
||||
rsa_publish_pub = RSAPublicKey_dup(rsa_publish);
|
||||
|
||||
|
||||
if(rsa_publish_pub != NULL){
|
||||
public_key = EVP_PKEY_new();
|
||||
EVP_PKEY_assign_RSA(public_key, rsa_publish_pub);
|
||||
}else{
|
||||
#ifdef DISTRIB_DEBUG
|
||||
std::cerr << "p3DistribSecurity(): Could not generate publish key " << grpId
|
||||
<< std::endl;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
EVP_CIPHER_CTX ctx;
|
||||
int eklen, net_ekl;
|
||||
unsigned char *ek;
|
||||
unsigned char iv[EVP_MAX_IV_LENGTH];
|
||||
EVP_CIPHER_CTX_init(&ctx);
|
||||
int out_currOffset = 0;
|
||||
int out_offset = 0;
|
||||
|
||||
int max_evp_key_size = EVP_PKEY_size(public_key);
|
||||
ek = (unsigned char*)malloc(max_evp_key_size);
|
||||
const EVP_CIPHER *cipher = EVP_aes_128_cbc();
|
||||
int cipher_block_size = EVP_CIPHER_block_size(cipher);
|
||||
int size_net_ekl = sizeof(net_ekl);
|
||||
|
||||
int max_outlen = inlen + cipher_block_size + EVP_MAX_IV_LENGTH + max_evp_key_size + size_net_ekl;
|
||||
|
||||
// intialize context and send store encrypted cipher in ek
|
||||
if(!EVP_SealInit(&ctx, EVP_aes_128_cbc(), &ek, &eklen, iv, &public_key, 1)) return false;
|
||||
|
||||
// now assign memory to out accounting for data, and cipher block size, key length, and key length val
|
||||
out = new unsigned char[inlen + cipher_block_size + size_net_ekl + eklen + EVP_MAX_IV_LENGTH];
|
||||
|
||||
net_ekl = htonl(eklen);
|
||||
memcpy((unsigned char*)out + out_offset, &net_ekl, size_net_ekl);
|
||||
out_offset += size_net_ekl;
|
||||
|
||||
memcpy((unsigned char*)out + out_offset, ek, eklen);
|
||||
out_offset += eklen;
|
||||
|
||||
memcpy((unsigned char*)out + out_offset, iv, EVP_MAX_IV_LENGTH);
|
||||
out_offset += EVP_MAX_IV_LENGTH;
|
||||
|
||||
// now encrypt actual data
|
||||
if(!EVP_SealUpdate(&ctx, (unsigned char*) out + out_offset, &out_currOffset, (unsigned char*) in, inlen)) return false;
|
||||
|
||||
// move along to partial block space
|
||||
out_offset += out_currOffset;
|
||||
|
||||
// add padding
|
||||
if(!EVP_SealFinal(&ctx, (unsigned char*) out + out_offset, &out_currOffset)) return false;
|
||||
|
||||
// move to end
|
||||
out_offset += out_currOffset;
|
||||
|
||||
// make sure offset has not gone passed valid memory bounds
|
||||
if(out_offset > max_outlen) return false;
|
||||
|
||||
// free encrypted key data
|
||||
free(ek);
|
||||
|
||||
outlen = out_offset;
|
||||
return true;
|
||||
|
||||
delete[] ek;
|
||||
|
||||
#ifdef DISTRIB_DEBUG
|
||||
std::cerr << "p3DistribSecurity::encrypt() finished with outlen : " << outlen << std::endl;
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool p3DistribSecurity::decrypt(void *& out, int & outlen, const void *in, int inlen, EVP_PKEY *privateKey)
|
||||
{
|
||||
|
||||
#ifdef DISTRIB_DEBUG
|
||||
std::cerr << "p3DistribSecurity::decrypt() " << std::endl;
|
||||
#endif
|
||||
|
||||
EVP_CIPHER_CTX ctx;
|
||||
int eklen = 0, net_ekl = 0;
|
||||
unsigned char *ek = NULL;
|
||||
unsigned char iv[EVP_MAX_IV_LENGTH];
|
||||
ek = (unsigned char*)malloc(EVP_PKEY_size(privateKey));
|
||||
EVP_CIPHER_CTX_init(&ctx);
|
||||
|
||||
int in_offset = 0, out_currOffset = 0;
|
||||
int size_net_ekl = sizeof(net_ekl);
|
||||
|
||||
memcpy(&net_ekl, (unsigned char*)in, size_net_ekl);
|
||||
eklen = ntohl(net_ekl);
|
||||
in_offset += size_net_ekl;
|
||||
|
||||
memcpy(ek, (unsigned char*)in + in_offset, eklen);
|
||||
in_offset += eklen;
|
||||
|
||||
memcpy(iv, (unsigned char*)in + in_offset, EVP_MAX_IV_LENGTH);
|
||||
in_offset += EVP_MAX_IV_LENGTH;
|
||||
|
||||
const EVP_CIPHER* cipher = EVP_aes_128_cbc();
|
||||
|
||||
if(!EVP_OpenInit(&ctx, cipher, ek, eklen, iv, privateKey)) return false;
|
||||
|
||||
out = new unsigned char[inlen - in_offset];
|
||||
|
||||
if(!EVP_OpenUpdate(&ctx, (unsigned char*) out, &out_currOffset, (unsigned char*)in + in_offset, inlen - in_offset)) return false;
|
||||
|
||||
in_offset += out_currOffset;
|
||||
outlen += out_currOffset;
|
||||
|
||||
if(!EVP_OpenFinal(&ctx, (unsigned char*)out + out_currOffset, &out_currOffset)) return false;
|
||||
|
||||
outlen += out_currOffset;
|
||||
|
||||
free(ek);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string p3DistribSecurity::getRsaKeySign(RSA *pubkey)
|
||||
{
|
||||
int len = BN_num_bytes(pubkey -> n);
|
||||
unsigned char tmp[len];
|
||||
BN_bn2bin(pubkey -> n, tmp);
|
||||
|
||||
// copy first CERTSIGNLEN bytes...
|
||||
if (len > CERTSIGNLEN)
|
||||
{
|
||||
len = CERTSIGNLEN;
|
||||
}
|
||||
|
||||
std::ostringstream id;
|
||||
for(uint32_t i = 0; i < CERTSIGNLEN; i++)
|
||||
{
|
||||
id << std::hex << std::setw(2) << std::setfill('0')
|
||||
<< (uint16_t) (((uint8_t *) (tmp))[i]);
|
||||
}
|
||||
std::string rsaId = id.str();
|
||||
|
||||
return rsaId;
|
||||
}
|
||||
|
||||
|
||||
bool p3DistribSecurity::validateDistribGrp(RsDistribGrp *newGrp)
|
||||
{
|
||||
#ifdef DISTRIB_DEBUG
|
||||
std::cerr << "p3GroupDistrib::validateDistribGrp()";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
|
||||
/* check signature */
|
||||
RsSerialType *serialType = new RsDistribSerialiser();
|
||||
|
||||
|
||||
|
||||
/* copy out signature (shallow copy) */
|
||||
RsTlvKeySignature tmpSign = newGrp->adminSignature;
|
||||
unsigned char *sigbuf = (unsigned char *) tmpSign.signData.bin_data;
|
||||
unsigned int siglen = tmpSign.signData.bin_len;
|
||||
|
||||
/* clear signature */
|
||||
newGrp->adminSignature.ShallowClear();
|
||||
|
||||
uint32_t size = serialType->size(newGrp);
|
||||
char* data = new char[size];
|
||||
|
||||
serialType->serialise(newGrp, data, &size);
|
||||
|
||||
|
||||
const unsigned char *keyptr = (const unsigned char *) newGrp->adminKey.keyData.bin_data;
|
||||
long keylen = newGrp->adminKey.keyData.bin_len;
|
||||
|
||||
/* extract admin key */
|
||||
RSA *rsakey = d2i_RSAPublicKey(NULL, &(keyptr), keylen);
|
||||
|
||||
EVP_PKEY *key = EVP_PKEY_new();
|
||||
EVP_PKEY_assign_RSA(key, rsakey);
|
||||
|
||||
/* calc and check signature */
|
||||
EVP_MD_CTX *mdctx = EVP_MD_CTX_create();
|
||||
|
||||
EVP_VerifyInit(mdctx, EVP_sha1());
|
||||
EVP_VerifyUpdate(mdctx, data, size);
|
||||
int ans = EVP_VerifyFinal(mdctx, sigbuf, siglen, key);
|
||||
|
||||
|
||||
/* restore signature */
|
||||
newGrp->adminSignature = tmpSign;
|
||||
tmpSign.ShallowClear();
|
||||
|
||||
/* clean up */
|
||||
EVP_PKEY_free(key);
|
||||
delete serialType;
|
||||
EVP_MD_CTX_destroy(mdctx);
|
||||
delete[] data;
|
||||
|
||||
if (ans == 1)
|
||||
return true;
|
||||
|
||||
#ifdef DISTRIB_DEBUG
|
||||
std::cerr << "p3GroupDistrib::validateDistribGrp() Signature invalid";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void p3DistribSecurity::setRSAPublicKey(RsTlvSecurityKey & key, RSA *rsa_pub)
|
||||
{
|
||||
unsigned char data[10240]; /* more than enough space */
|
||||
unsigned char *ptr = data;
|
||||
int reqspace = i2d_RSAPublicKey(rsa_pub, &ptr);
|
||||
|
||||
key.keyData.setBinData(data, reqspace);
|
||||
|
||||
std::string keyId = getRsaKeySign(rsa_pub);
|
||||
key.keyId = keyId;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void p3DistribSecurity::setRSAPrivateKey(RsTlvSecurityKey & key, RSA *rsa_priv)
|
||||
{
|
||||
unsigned char data[10240]; /* more than enough space */
|
||||
unsigned char *ptr = data;
|
||||
int reqspace = i2d_RSAPrivateKey(rsa_priv, &ptr);
|
||||
|
||||
key.keyData.setBinData(data, reqspace);
|
||||
|
||||
std::string keyId = getRsaKeySign(rsa_priv);
|
||||
key.keyId = keyId;
|
||||
}
|
||||
|
||||
|
||||
|
||||
RSA *p3DistribSecurity::extractPrivateKey(RsTlvSecurityKey & key)
|
||||
{
|
||||
const unsigned char *keyptr = (const unsigned char *) key.keyData.bin_data;
|
||||
long keylen = key.keyData.bin_len;
|
||||
|
||||
/* extract admin key */
|
||||
RSA *rsakey = d2i_RSAPrivateKey(NULL, &(keyptr), keylen);
|
||||
|
||||
return rsakey;
|
||||
}
|
||||
|
||||
|
133
libretroshare/src/distrib/p3distribsecurity.h
Normal file
133
libretroshare/src/distrib/p3distribsecurity.h
Normal file
@ -0,0 +1,133 @@
|
||||
/*
|
||||
* libretroshare/src/distrib: p3distribverify.h
|
||||
*
|
||||
* 3P/PQI network interface for RetroShare.
|
||||
*
|
||||
* Copyright 2008-2010 by Robert Fernie
|
||||
* 2011 Christopher Evi-Parker
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License Version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This library 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
* USA.
|
||||
*
|
||||
* Please report all bugs and problems to "retroshare@lunamutt.com".
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef P3DISTRIBVERIFY_H_
|
||||
#define P3DISTRIBVERIFY_H_
|
||||
|
||||
|
||||
#include <openssl/ssl.h>
|
||||
#include <openssl/evp.h>
|
||||
|
||||
#include "serialiser/rstlvkeys.h"
|
||||
#include "distrib/p3distrib.h"
|
||||
|
||||
|
||||
/*!
|
||||
* This contains functionality for performing security
|
||||
* operations needed to validate data received in p3GroupDistrib
|
||||
* Also has functionality to receive data
|
||||
*/
|
||||
class p3DistribSecurity {
|
||||
|
||||
public:
|
||||
|
||||
p3DistribSecurity();
|
||||
~p3DistribSecurity();
|
||||
|
||||
/*!
|
||||
* extracts the public key from an RsTlvSecurityKey
|
||||
* @param key RsTlvSecurityKey to extract public RSA key from
|
||||
* @return pointer to the public RSA key if successful, null otherwise
|
||||
*/
|
||||
static RSA *extractPublicKey(RsTlvSecurityKey &key);
|
||||
|
||||
/*!
|
||||
* extracts the public key from an RsTlvSecurityKey
|
||||
* @param key RsTlvSecurityKey to extract private RSA key from
|
||||
* @return pointer to the private RSA key if successful, null otherwise
|
||||
*/
|
||||
static RSA *extractPrivateKey(RsTlvSecurityKey &key);
|
||||
|
||||
/*!
|
||||
* stores the rsa public key in a RsTlvSecurityKey
|
||||
* @param key RsTlvSecurityKey to store the public rsa key in
|
||||
* @param rsa_pub
|
||||
*/
|
||||
static void setRSAPublicKey(RsTlvSecurityKey &key, RSA *rsa_pub);
|
||||
|
||||
/*!
|
||||
* stores the rsa private key in a RsTlvSecurityKey
|
||||
* @param key stores the rsa private key in a RsTlvSecurityKey
|
||||
* @param rsa_priv the rsa private key to store
|
||||
*/
|
||||
static void setRSAPrivateKey(RsTlvSecurityKey &key, RSA *rsa_priv);
|
||||
|
||||
/*!
|
||||
* extracts signature from RSA key
|
||||
* @param pubkey
|
||||
* @return signature of RSA key in hex format
|
||||
*/
|
||||
static std::string getRsaKeySign(RSA *pubkey);
|
||||
|
||||
/*!
|
||||
* extracts the signature and stores it in a string
|
||||
* in hex format
|
||||
* @param data
|
||||
* @param len
|
||||
* @return
|
||||
*/
|
||||
static std::string getBinDataSign(void *data, int len);
|
||||
|
||||
/*!
|
||||
* Encrypts data using envelope encryption (taken from open ssl's evp_sealinit )
|
||||
* only full publish key holders can encrypt data for given group
|
||||
*@param out
|
||||
*@param outlen
|
||||
*@param in
|
||||
*@param inlen
|
||||
*/
|
||||
static bool encrypt(void *&out, int &outlen, const void *in, int inlen, EVP_PKEY *privateKey);
|
||||
|
||||
|
||||
/**
|
||||
* Decrypts data using evelope decryption (taken from open ssl's evp_sealinit )
|
||||
* only full publish key holders can decrypt data for a group
|
||||
* @param out where decrypted data is written to
|
||||
* @param outlen
|
||||
* @param in
|
||||
* @param inlen
|
||||
* @return false if encryption failed
|
||||
*/
|
||||
static bool decrypt(void *&out, int &outlen, const void *in, int inlen, EVP_PKEY *privateKey);
|
||||
|
||||
/*!
|
||||
* uses grp signature to check if group has been
|
||||
* tampered with
|
||||
* @param newGrp
|
||||
* @return true if group valid false otherwise
|
||||
*/
|
||||
static bool validateDistribGrp(RsDistribGrp *newGrp);
|
||||
|
||||
/*!
|
||||
* uses groupinfo public key to verify signature of signed message
|
||||
* @param info groupinfo for which msg is meant for
|
||||
* @param msg
|
||||
* @return false if verfication of signature is not passed
|
||||
*/
|
||||
static bool validateDistribSignedMsg(GroupInfo &info, RsDistribSignedMsg *msg);
|
||||
};
|
||||
|
||||
#endif /* P3DISTRIBVERIFY_H_ */
|
@ -411,7 +411,6 @@ HEADERS += serialiser/rsbaseitems.h \
|
||||
HEADERS += services/p3channels.h \
|
||||
services/p3chatservice.h \
|
||||
services/p3disc.h \
|
||||
services/p3distrib.h \
|
||||
services/p3forums.h \
|
||||
services/p3gamelauncher.h \
|
||||
services/p3gameservice.h \
|
||||
@ -420,6 +419,9 @@ HEADERS += services/p3channels.h \
|
||||
services/p3service.h \
|
||||
services/p3statusservice.h \
|
||||
services/p3tunnel.h
|
||||
|
||||
HEADERS += distrib/p3distrib.h \
|
||||
distrib/p3distribsecurity.h
|
||||
# services/p3blogs.h \
|
||||
|
||||
HEADERS += turtle/p3turtle.h \
|
||||
@ -538,7 +540,6 @@ SOURCES += serialiser/rsbaseitems.cc \
|
||||
SOURCES += services/p3channels.cc \
|
||||
services/p3chatservice.cc \
|
||||
services/p3disc.cc \
|
||||
services/p3distrib.cc \
|
||||
services/p3forums.cc \
|
||||
services/p3gamelauncher.cc \
|
||||
services/p3msgservice.cc \
|
||||
@ -547,7 +548,9 @@ SOURCES += services/p3channels.cc \
|
||||
services/p3statusservice.cc
|
||||
# removed because getPeer() doesn t exist services/p3tunnel.cc
|
||||
|
||||
|
||||
SOURCES += distrib/p3distrib.cc \
|
||||
distrib/p3distribsecurity.cc
|
||||
|
||||
SOURCES += turtle/p3turtle.cc \
|
||||
turtle/rsturtleitem.cc
|
||||
# turtle/turtlerouting.cc \
|
||||
|
@ -28,7 +28,7 @@
|
||||
|
||||
#include "retroshare/rsblogs.h"
|
||||
#include "retroshare/rsfiles.h"
|
||||
#include "services/p3distrib.h"
|
||||
#include "distrib/p3distrib.h"
|
||||
|
||||
#include "serialiser/rstlvtypes.h"
|
||||
#include "serialiser/rsblogitems.h"
|
||||
|
@ -186,6 +186,8 @@ bool p3Channels::getChannelMessage(std::string cId, std::string mId, ChannelMsgI
|
||||
std::list<std::string> msgIds;
|
||||
std::list<std::string>::iterator it;
|
||||
|
||||
processCacheOptReq(cId);
|
||||
|
||||
RsStackMutex stack(distribMtx); /***** STACK LOCKED MUTEX *****/
|
||||
|
||||
RsDistribMsg *msg = locked_getGroupMsg(cId, mId);
|
||||
|
@ -28,7 +28,7 @@
|
||||
|
||||
#include "retroshare/rschannels.h"
|
||||
#include "retroshare/rsfiles.h"
|
||||
#include "services/p3distrib.h"
|
||||
#include "distrib/p3distrib.h"
|
||||
|
||||
#include "serialiser/rstlvtypes.h"
|
||||
#include "serialiser/rschannelitems.h"
|
||||
|
@ -294,6 +294,8 @@ bool p3Forums::getForumThreadMsgList(const std::string &fId, const std::string &
|
||||
|
||||
bool p3Forums::getForumMessage(const std::string &fId, const std::string &mId, ForumMsgInfo &info)
|
||||
{
|
||||
processCacheOptReq(fId);
|
||||
|
||||
RsStackMutex stack(distribMtx); /***** STACK LOCKED MUTEX *****/
|
||||
|
||||
RsDistribMsg *msg = locked_getGroupMsg(fId, mId);
|
||||
@ -437,6 +439,7 @@ std::string p3Forums::createForumMsg(std::string fId, std::string pId,
|
||||
RsForumMsg *fmsg = new RsForumMsg();
|
||||
fmsg->grpId = fId;
|
||||
fmsg->parentId = pId;
|
||||
processCacheOptReq(fId);
|
||||
|
||||
{
|
||||
RsStackMutex stack(distribMtx); /***** STACK LOCKED MUTEX *****/
|
||||
|
@ -27,7 +27,7 @@
|
||||
*/
|
||||
|
||||
#include "retroshare/rsforums.h"
|
||||
#include "services/p3distrib.h"
|
||||
#include "distrib/p3distrib.h"
|
||||
#include "serialiser/rsforumitems.h"
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user