started to move FT encryption into p3turtle

This commit is contained in:
csoler 2018-03-22 14:41:50 +01:00
parent 3407604a54
commit 00a6bd5b73
No known key found for this signature in database
GPG key ID: 7BCA522266C0804C
4 changed files with 342 additions and 26 deletions

View file

@ -24,6 +24,7 @@
*/
#include "util/rsdir.h"
#include "retroshare/rspeers.h"
#include "rsgxsnettunnel.h"
#define DEBUG_RSGXSNETTUNNEL 1
@ -42,7 +43,7 @@ bool RsGxsNetTunnelService::manage(const RsGxsGroupId& group_id)
RsStackMutex stack(mGxsNetTunnelMtx); /********** STACK LOCKED MTX ******/
RsGxsNetTunnelGroupInfo& info(mClientGroups[group_id]) ;
RsGxsNetTunnelGroupInfo& info(mGroups[group_id]) ;
time_t now = time(NULL) ;
@ -73,15 +74,15 @@ bool RsGxsNetTunnelService::release(const RsGxsGroupId& group_id)
// Here we need to clean the stuff that was created by this group id.
auto it = mClientGroups.find(group_id) ;
auto it = mGroups.find(group_id) ;
if(it == mClientGroups.end())
if(it == mGroups.end())
{
std::cerr << "RsGxsNetTunnelService::release(): Weird. Cannot release client group " << group_id << " that is not known." << std::endl;
return false ;
}
mClientGroups.erase(it) ;
mGroups.erase(it) ;
RsFileHash hash = calculateGroupHash(group_id) ;
@ -89,12 +90,66 @@ bool RsGxsNetTunnelService::release(const RsGxsGroupId& group_id)
return true ;
}
bool RsGxsNetTunnelService::sendData(const unsigned char *data,uint32_t size,const RsGxsNetTunnelVirtualPeerId& virtual_peer)
class ItemAutoDelete
{
// The data is encrypted using chacha20+SHA256 and sent to the turtle router.
public:
ItemAutoDelete(RsItem *& item) : mItem(item) {}
~ItemAutoDelete() { delete mItem; mItem=NULL ; }
RsItem *& mItem;
};
bool RsGxsNetTunnelService::sendItem(RsItem *& item,const RsGxsNetTunnelVirtualPeerId& virtual_peer)
{
// The item is serialized and encrypted using chacha20+SHA256, using the generic turtle encryption, and then sent to the turtle router.
ItemAutoDelete iad(item) ; // This ensures the item is deleted whatsoever when leaving
// 1 - find the virtual peer and the proper master key to encrypt with, and check that all the info is known
auto it = mVirtualPeers.find(virtual_peer) ;
if(it == mVirtualPeers.end())
{
std::cerr << "(EE) RsGxsNetTunnelService::sendData(): cannot find virtual peer " << virtual_peer << ". Data is dropped." << std::endl;
return false ;
}
auto it2 = mGroups.find(it->second.first);
if(it2 == mGroups.end())
{
std::cerr << "(EE) RsGxsNetTunnelService::sendData(): cannot find virtual peer " << virtual_peer << ". Data is dropped." << std::endl;
return false ;
}
auto it3 = it2->second.virtual_peers.find(it->second.second);
if(it3 == it2->second.virtual_peers.end())
{
std::cerr << "(EE) RsGxsNetTunnelService::sendData(): cannot find turtle virtual peer " << it->second.second << ". Data is dropped." << std::endl;
return false ;
}
if(it3->second.vpid_status != RsGxsNetTunnelVirtualPeerInfo::RS_GXS_NET_TUNNEL_VP_STATUS_ACTIVE)
{
std::cerr << "(EE) RsGxsNetTunnelService::sendData(): virtual peer " << it->second.second << " is not active. Data is dropped." << std::endl;
return false ;
}
// 2 - encrypt and send the item.
RsTurtleGenericDataItem *encrypted_turtle_item = NULL ;
NOT_IMPLEMENTED();
return false ;
// if(!p3Turtle::encryptItem(item,it3->second.encryption_master_key,encrypted_turtle_item))
// {
// std::cerr << "(EE) RsGxsNetTunnelService::sendData(): cannot encrypt. Something's wrong. Data is dropped." << std::endl;
// return false ;
// }
mTurtle->sendTurtleData(it->second.second,encrypted_turtle_item) ;
return true ;
}
bool RsGxsNetTunnelService::getVirtualPeers(const RsGxsGroupId&, std::list<RsPeerId>& peers)
@ -104,14 +159,60 @@ bool RsGxsNetTunnelService::getVirtualPeers(const RsGxsGroupId&, std::list<RsPee
return false ;
}
RsGxsNetTunnelVirtualPeerInfo RsGxsNetTunnelService::makeVirtualPeerIdForGroup(const RsGxsGroupId& group_id) const
RsGxsNetTunnelVirtualPeerId RsGxsNetTunnelService::makeServerVirtualPeerIdForGroup(const RsGxsGroupId& group_id) const
{
NOT_IMPLEMENTED();
return RsGxsNetTunnelVirtualPeerInfo();
assert(RsPeerId::SIZE_IN_BYTES <= Sha1CheckSum::SIZE_IN_BYTES) ;
// We compute sha1( SSL_id | group_id | mRandomBias ) and trunk it to 16 bytes in order to compute a RsPeerId
RsPeerId ssl_id = rsPeers->getOwnId() ;
unsigned char mem[RsPeerId::SIZE_IN_BYTES + RsGxsGroupId::SIZE_IN_BYTES + RS_GXS_TUNNEL_CONST_RANDOM_BIAS_SIZE];
memcpy(mem ,ssl_id.toByteArray() ,RsPeerId::SIZE_IN_BYTES) ;
memcpy(mem+RsPeerId::SIZE_IN_BYTES ,group_id.toByteArray(),RsGxsGroupId::SIZE_IN_BYTES) ;
memcpy(mem+RsPeerId::SIZE_IN_BYTES+RsGxsGroupId::SIZE_IN_BYTES,mRandomBias ,RS_GXS_TUNNEL_CONST_RANDOM_BIAS_SIZE) ;
return RsGxsNetTunnelVirtualPeerId(RsDirUtil::sha1sum(mem,RsPeerId::SIZE_IN_BYTES+RsGxsGroupId::SIZE_IN_BYTES+RS_GXS_TUNNEL_CONST_RANDOM_BIAS_SIZE).toByteArray());
}
void RsGxsNetTunnelService::dump() const
{
NOT_IMPLEMENTED();
RS_STACK_MUTEX(mGxsNetTunnelMtx);
static std::string group_status_str[3] = {
std::string("[RS_GXS_NET_TUNNEL_GRP_STATUS_UNKNOWN ]"),
std::string("[RS_GXS_NET_TUNNEL_GRP_STATUS_TUNNELS_REQUESTED]"),
std::string("[RS_GXS_NET_TUNNEL_GRP_STATUS_VPIDS_AVAILABLE ]")
};
static std::string vpid_status_str[3] = {
std::string("[RS_GXS_NET_TUNNEL_VP_STATUS_UNKNOWN ]"),
std::string("[RS_GXS_NET_TUNNEL_VP_STATUS_TUNNEL_OK ]"),
std::string("[RS_GXS_NET_TUNNEL_VP_STATUS_ACTIVE ]")
};
std::cerr << "GxsNetTunnelService dump: " << std::endl;
std::cerr << "Managed GXS groups: " << std::endl;
for(auto it(mGroups.begin());it!=mGroups.end();++it)
{
std::cerr << " " << it->first << " hash: " << it->second.hash << " status: " << group_status_str[it->second.group_status] << "] Last contact: " << time(NULL) - it->second.last_contact << " secs ago" << std::endl;
for(auto it2(it->second.virtual_peers.begin());it2!=it->second.virtual_peers.end();++it2)
std::cerr << " turtle:" << it2->first << " status: " << vpid_status_str[it2->second.vpid_status] << " s: "
<< (int)it2->second.side << " last seen " << time(NULL)-it2->second.last_contact
<< " ekey: " << RsUtil::BinToHex(it2->second.encryption_master_key,RS_GXS_TUNNEL_CONST_EKEY_SIZE)
<< " pending (" << it2->second.incoming_items.size() << "," << it2->second.outgoing_items.size() << ")" << std::endl;
}
std::cerr << "Virtual peers: " << std::endl;
for(auto it(mVirtualPeers.begin());it!=mVirtualPeers.end();++it)
std::cerr << " GXS Peer:" << it->first << " group_id: " << it->second.first << " Turtle:" << it->second.second << std::endl;
std::cerr << "Hashes: " << std::endl;
for(auto it(mHandledHashes.begin());it!=mHandledHashes.end();++it)
std::cerr << " hash: " << it->first << " GroupId: " << it->second << std::endl;
}
//===========================================================================================================================================//
@ -151,7 +252,7 @@ void RsGxsNetTunnelService::addVirtualPeer(const TurtleFileHash& hash, const Tur
const RsGxsGroupId group_id(it->second) ;
RsGxsNetTunnelGroupInfo& ginfo( mClientGroups[group_id] ) ;
RsGxsNetTunnelGroupInfo& ginfo( mGroups[group_id] ) ;
ginfo.group_status = RsGxsNetTunnelGroupInfo::RS_GXS_NET_TUNNEL_GRP_STATUS_VPIDS_AVAILABLE ;
RsGxsNetTunnelVirtualPeerInfo& vpinfo( ginfo.virtual_peers[vpid] ) ;
@ -161,7 +262,7 @@ void RsGxsNetTunnelService::addVirtualPeer(const TurtleFileHash& hash, const Tur
vpinfo.side = dir ;
vpinfo.last_contact = time(NULL) ;
generateEncryptionKey(group_id,vpid,vpinfo.encryption_key );
generateEncryptionKey(group_id,vpid,vpinfo.encryption_master_key );
}
void RsGxsNetTunnelService::removeVirtualPeer(const TurtleFileHash& hash, const TurtleVirtualPeerId& vpid)
@ -176,7 +277,7 @@ void RsGxsNetTunnelService::removeVirtualPeer(const TurtleFileHash& hash, const
const RsGxsGroupId group_id(it->second) ;
RsGxsNetTunnelGroupInfo& ginfo( mClientGroups[group_id] ) ;
RsGxsNetTunnelGroupInfo& ginfo( mGroups[group_id] ) ;
ginfo.virtual_peers.erase(vpid);
@ -189,6 +290,21 @@ RsFileHash RsGxsNetTunnelService::calculateGroupHash(const RsGxsGroupId& group_i
return RsDirUtil::sha1sum(group_id.toByteArray(),RsGxsGroupId::SIZE_IN_BYTES) ;
}
void RsGxsNetTunnelService::generateEncryptionKey(const RsGxsGroupId& group_id,const TurtleVirtualPeerId& vpid,unsigned char key[RS_GXS_TUNNEL_CONST_EKEY_SIZE]) const
{
// The key is generated as H(group_id | vpid)
// Because group_id is not known it shouldn't be possible to recover the key by observing the traffic.
assert(Sha256CheckSum::SIZE_IN_BYTES == 32) ;
unsigned char mem[RsGxsGroupId::SIZE_IN_BYTES + TurtleVirtualPeerId::SIZE_IN_BYTES] ;
memcpy(mem ,group_id.toByteArray(),RsGxsGroupId::SIZE_IN_BYTES) ;
memcpy(mem+RsGxsGroupId::SIZE_IN_BYTES,vpid.toByteArray() ,TurtleVirtualPeerId::SIZE_IN_BYTES) ;
memcpy( key, RsDirUtil::sha256sum(mem,RsGxsGroupId::SIZE_IN_BYTES+TurtleVirtualPeerId::SIZE_IN_BYTES).toByteArray(), RS_GXS_TUNNEL_CONST_EKEY_SIZE ) ;
}
//===========================================================================================================================================//
// Service parts //
//===========================================================================================================================================//

View file

@ -75,11 +75,16 @@ struct RsGxsNetTunnelVirtualPeerInfo
RsGxsNetTunnelVirtualPeerInfo() : vpid_status(RS_GXS_NET_TUNNEL_VP_STATUS_UNKNOWN) { memset(encryption_master_key,0,16) ; }
uint8_t vpid_status ;
RsGxsNetTunnelVirtualPeerId net_service_virtual_peer ;
uint8_t vpid_status ; // status of the peer
uint8_t side ; // client/server
uint8_t encryption_master_key[16] ; // key from which the encryption key is derived for each virtual peer (using H(master_key | random IV))
time_t last_contact ; // last time some data was sent/recvd
RsGxsNetTunnelVirtualPeerId net_service_virtual_peer ; // anonymised peer that is used to communicate with client services
RsGxsGroupId group_id ; // group id
std::list<RsItem*> incoming_items ;
std::list<RsItem*> outgoing_items ;
};
struct RsGxsNetTunnelGroupInfo
@ -115,10 +120,24 @@ public:
*/
bool release(const RsGxsGroupId&group_id) ;
/*!
* sends data to this virtual peer ID
* \brief sendItem
* send data to this virtual peer, and takes memory ownership (deletes the item)
* \param item item to send
* \param virtual_peer destination virtual peer
* \return
* true if succeeded.
*/
bool sendData(const unsigned char *data,uint32_t size,const RsGxsNetTunnelVirtualPeerId& virtual_peer) ; // send data to this virtual peer
bool sendItem(RsItem *& item, const RsGxsNetTunnelVirtualPeerId& virtual_peer) ;
/*!
* \brief receivedItem
* returns the next received item from the given virtual peer.
* \param virtual_peer
* \return
*/
RsItem *receivedItem(const RsGxsNetTunnelVirtualPeerId& virtual_peer) ;
/*!
* \brief Get the list of active virtual peers for a given group. This implies that the tunnel is up and
@ -147,11 +166,13 @@ protected:
p3turtle *mTurtle ;
private:
std::map<RsGxsGroupId,RsGxsNetTunnelGroupInfo> mClientGroups ; // groups on the client side
std::map<RsGxsGroupId,RsGxsNetTunnelGroupInfo> mServerGroups ; // groups on the server side
static const uint32_t RS_GXS_TUNNEL_CONST_RANDOM_BIAS_SIZE = 16 ;
static const uint32_t RS_GXS_TUNNEL_CONST_EKEY_SIZE = 32 ;
std::map<RsGxsNetTunnelVirtualPeerId, std::pair<RsGxsGroupId,TurtleVirtualPeerId> > mVirtualPeers ; // current virtual peers, with the (group,turtle vpid) they are for
std::map<RsFileHash, RsGxsGroupId> mHandledHashes ; // hashes asked to turtle
std::map<RsGxsGroupId,RsGxsNetTunnelGroupInfo> mGroups ; // groups on the client and server side
std::map<RsGxsNetTunnelVirtualPeerId, std::pair<RsGxsGroupId,TurtleVirtualPeerId> > mVirtualPeers ; // current virtual peers,
std::map<RsFileHash, RsGxsGroupId> mHandledHashes ; // hashes asked to turtle
/*!
* \brief Generates the hash to request tunnels for this group. This hash is only used by turtle, and is used to
@ -165,12 +186,12 @@ private:
* tunnel ID and turtle virtual peer id. This allows RsGxsNetService to keep sync-ing the data consistently.
*/
RsGxsNetTunnelVirtualPeerInfo makeVirtualPeerIdForGroup(const RsGxsGroupId&group_id) const ;
RsGxsNetTunnelVirtualPeerId makeServerVirtualPeerIdForGroup(const RsGxsGroupId&group_id) const ;
void generateEncryptionKey(const RsGxsGroupId& group_id,const TurtleVirtualPeerId& vpid) const ;
void generateEncryptionKey(const RsGxsGroupId& group_id,const TurtleVirtualPeerId& vpid,unsigned char key[RS_GXS_TUNNEL_CONST_EKEY_SIZE]) const ;
uint8_t mRandomBias[16] ; // constant accross reboots. Allows to disguise the real SSL id while providing a consistent value accross time.
uint8_t mRandomBias[RS_GXS_TUNNEL_CONST_RANDOM_BIAS_SIZE] ; // constant accross reboots. Allows to disguise the real SSL id while providing a consistent value accross time.
RsMutex mGxsNetTunnelMtx;
mutable RsMutex mGxsNetTunnelMtx;
};