From 00a6bd5b73b0a7a76ad46e4f9535f4d69cd7e193 Mon Sep 17 00:00:00 2001 From: csoler Date: Thu, 22 Mar 2018 14:41:50 +0100 Subject: [PATCH] started to move FT encryption into p3turtle --- libretroshare/src/gxs/rsgxsnettunnel.cc | 144 ++++++++++++++++++-- libretroshare/src/gxs/rsgxsnettunnel.h | 45 +++++-- libretroshare/src/turtle/p3turtle.cc | 172 ++++++++++++++++++++++++ libretroshare/src/turtle/p3turtle.h | 7 + 4 files changed, 342 insertions(+), 26 deletions(-) diff --git a/libretroshare/src/gxs/rsgxsnettunnel.cc b/libretroshare/src/gxs/rsgxsnettunnel.cc index 2a960dd7a..e9c389454 100644 --- a/libretroshare/src/gxs/rsgxsnettunnel.cc +++ b/libretroshare/src/gxs/rsgxsnettunnel.cc @@ -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& peers) @@ -104,14 +159,60 @@ bool RsGxsNetTunnelService::getVirtualPeers(const RsGxsGroupId&, std::listgetOwnId() ; + + 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 // //===========================================================================================================================================// diff --git a/libretroshare/src/gxs/rsgxsnettunnel.h b/libretroshare/src/gxs/rsgxsnettunnel.h index 03a676c07..2f6cb0eae 100644 --- a/libretroshare/src/gxs/rsgxsnettunnel.h +++ b/libretroshare/src/gxs/rsgxsnettunnel.h @@ -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 incoming_items ; + std::list 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 mClientGroups ; // groups on the client side - std::map 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 > mVirtualPeers ; // current virtual peers, with the (group,turtle vpid) they are for - std::map mHandledHashes ; // hashes asked to turtle + std::map mGroups ; // groups on the client and server side + + std::map > mVirtualPeers ; // current virtual peers, + std::map 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; }; diff --git a/libretroshare/src/turtle/p3turtle.cc b/libretroshare/src/turtle/p3turtle.cc index 8217db2fa..f01f7390e 100644 --- a/libretroshare/src/turtle/p3turtle.cc +++ b/libretroshare/src/turtle/p3turtle.cc @@ -2080,6 +2080,178 @@ std::string p3turtle::getPeerNameForVirtualPeerId(const RsPeerId& virtual_peer_i return name; } +#ifdef TODO +static const uint32_t ENCRYPTED_FT_INITIALIZATION_VECTOR_SIZE = 12 ; +static const uint32_t ENCRYPTED_FT_AUTHENTICATION_TAG_SIZE = 16 ; +static const uint32_t ENCRYPTED_FT_HEADER_SIZE = 4 ; +static const uint32_t ENCRYPTED_FT_EDATA_SIZE = 4 ; + +static const uint8_t ENCRYPTED_FT_FORMAT_AEAD_CHACHA20_POLY1305 = 0x01 ; +static const uint8_t ENCRYPTED_FT_FORMAT_AEAD_CHACHA20_SHA256 = 0x02 ; + +bool p3turtle::encryptItem(const RsItem *item,uint8_t *encryption_master_key,RsTurtleGenericDataItem *& encrypted_item) +{ + uint8_t initialization_vector[ENCRYPTED_FT_INITIALIZATION_VECTOR_SIZE] ; + + RSRandom::random_bytes(initialization_vector,ENCRYPTED_FT_INITIALIZATION_VECTOR_SIZE) ; + +#ifdef SERVER_DEBUG + FTSERVER_DEBUG() << "ftServer::Encrypting ft item." << std::endl; + FTSERVER_DEBUG() << " random nonce : " << RsUtil::BinToHex(initialization_vector,ENCRYPTED_FT_INITIALIZATION_VECTOR_SIZE) << std::endl; +#endif + + uint32_t item_serialized_size = RsGenericSerializer().size(clear_item) ; + uint32_t total_data_size = ENCRYPTED_FT_HEADER_SIZE + ENCRYPTED_FT_INITIALIZATION_VECTOR_SIZE + ENCRYPTED_FT_EDATA_SIZE + item_serialized_size + ENCRYPTED_FT_AUTHENTICATION_TAG_SIZE ; + +#ifdef SERVER_DEBUG + FTSERVER_DEBUG() << " clear part size : " << size(clear_item) << std::endl; + FTSERVER_DEBUG() << " total item size : " << total_data_size << std::endl; +#endif + + encrypted_item = new RsTurtleGenericDataItem ; + encrypted_item->data_bytes = rs_malloc( total_data_size ) ; + encrypted_item->data_size = total_data_size ; + + if(encrypted_item->data_bytes == NULL) + return false ; + + uint8_t *edata = (uint8_t*)encrypted_item->data_bytes ; + uint32_t edata_size = item_serialized_size; + uint32_t offset = 0; + + edata[0] = 0xae ; + edata[1] = 0xad ; + edata[2] = ENCRYPTED_FT_FORMAT_AEAD_CHACHA20_SHA256 ; // means AEAD_chacha20_sha256 + edata[3] = 0x01 ; + + offset += ENCRYPTED_FT_HEADER_SIZE; + uint32_t aad_offset = offset ; + uint32_t aad_size = ENCRYPTED_FT_INITIALIZATION_VECTOR_SIZE + ENCRYPTED_FT_EDATA_SIZE ; + + memcpy(&edata[offset], initialization_vector, ENCRYPTED_FT_INITIALIZATION_VECTOR_SIZE) ; + offset += ENCRYPTED_FT_INITIALIZATION_VECTOR_SIZE ; + + edata[offset+0] = (edata_size >> 0) & 0xff ; + edata[offset+1] = (edata_size >> 8) & 0xff ; + edata[offset+2] = (edata_size >> 16) & 0xff ; + edata[offset+3] = (edata_size >> 24) & 0xff ; + + offset += ENCRYPTED_FT_EDATA_SIZE ; + + uint32_t ser_size = (uint32_t)((int)total_data_size - (int)offset); + + serialise(clear_item,&edata[offset], &ser_size); + +#ifdef SERVER_DEBUG + FTSERVER_DEBUG() << " clear item : " << RsUtil::BinToHex(&edata[offset],std::min(50,(int)total_data_size-(int)offset)) << "(...)" << std::endl; +#endif + + uint32_t clear_item_offset = offset ; + offset += edata_size ; + + uint32_t authentication_tag_offset = offset ; + assert(ENCRYPTED_FT_AUTHENTICATION_TAG_SIZE + offset == total_data_size) ; + + uint8_t encryption_key[32] ; + deriveEncryptionKey(hash,encryption_key) ; + + if(edata[2] == ENCRYPTED_FT_FORMAT_AEAD_CHACHA20_POLY1305) + librs::crypto::AEAD_chacha20_poly1305(encryption_key,initialization_vector,&edata[clear_item_offset],edata_size, &edata[aad_offset],aad_size, &edata[authentication_tag_offset],true) ; + else if(edata[2] == ENCRYPTED_FT_FORMAT_AEAD_CHACHA20_SHA256) + librs::crypto::AEAD_chacha20_sha256 (encryption_key,initialization_vector,&edata[clear_item_offset],edata_size, &edata[aad_offset],aad_size, &edata[authentication_tag_offset],true) ; + else + return false ; + +#ifdef SERVER_DEBUG + FTSERVER_DEBUG() << " encryption key : " << RsUtil::BinToHex(encryption_key,32) << std::endl; + FTSERVER_DEBUG() << " authen. tag : " << RsUtil::BinToHex(&edata[authentication_tag_offset],ENCRYPTED_FT_AUTHENTICATION_TAG_SIZE) << std::endl; + FTSERVER_DEBUG() << " final item : " << RsUtil::BinToHex(&edata[0],std::min(50u,total_data_size)) << "(...)" << std::endl; +#endif + + return true ; +} + +// Decrypts the given item using aead-chacha20-poly1305 +bool p3turtle::decryptItem(RsTurtleGenericDataItem *item, uint8_t* encryption_master_key, RsItem *& decrypted_item) +{ + uint8_t encryption_key[32] ; + deriveEncryptionKey(hash,encryption_key) ; + + uint8_t *edata = (uint8_t*)encrypted_item->data_bytes ; + uint32_t offset = 0; + + if(encrypted_item->data_size < ENCRYPTED_FT_HEADER_SIZE + ENCRYPTED_FT_INITIALIZATION_VECTOR_SIZE + ENCRYPTED_FT_EDATA_SIZE) return false ; + + if(edata[0] != 0xae) return false ; + if(edata[1] != 0xad) return false ; + if(edata[2] != ENCRYPTED_FT_FORMAT_AEAD_CHACHA20_POLY1305 && edata[2] != ENCRYPTED_FT_FORMAT_AEAD_CHACHA20_SHA256) return false ; + if(edata[3] != 0x01) return false ; + + offset += ENCRYPTED_FT_HEADER_SIZE ; + uint32_t aad_offset = offset ; + uint32_t aad_size = ENCRYPTED_FT_EDATA_SIZE + ENCRYPTED_FT_INITIALIZATION_VECTOR_SIZE ; + + uint8_t *initialization_vector = &edata[offset] ; + +#ifdef SERVER_DEBUG + FTSERVER_DEBUG() << "ftServer::decrypting ft item." << std::endl; + FTSERVER_DEBUG() << " item data : " << RsUtil::BinToHex(edata,std::min(50u,encrypted_item->data_size)) << "(...)" << std::endl; + FTSERVER_DEBUG() << " hash : " << hash << std::endl; + FTSERVER_DEBUG() << " encryption key : " << RsUtil::BinToHex(encryption_key,32) << std::endl; + FTSERVER_DEBUG() << " random nonce : " << RsUtil::BinToHex(initialization_vector,ENCRYPTED_FT_INITIALIZATION_VECTOR_SIZE) << std::endl; +#endif + + offset += ENCRYPTED_FT_INITIALIZATION_VECTOR_SIZE ; + + uint32_t edata_size = 0 ; + edata_size += ((uint32_t)edata[offset+0]) << 0 ; + edata_size += ((uint32_t)edata[offset+1]) << 8 ; + edata_size += ((uint32_t)edata[offset+2]) << 16 ; + edata_size += ((uint32_t)edata[offset+3]) << 24 ; + + if(edata_size + ENCRYPTED_FT_EDATA_SIZE + ENCRYPTED_FT_AUTHENTICATION_TAG_SIZE + ENCRYPTED_FT_INITIALIZATION_VECTOR_SIZE + ENCRYPTED_FT_HEADER_SIZE != encrypted_item->data_size) + { + FTSERVER_ERROR() << " ERROR: encrypted data size is " << edata_size << ", should be " << encrypted_item->data_size - (ENCRYPTED_FT_EDATA_SIZE + ENCRYPTED_FT_AUTHENTICATION_TAG_SIZE + ENCRYPTED_FT_INITIALIZATION_VECTOR_SIZE + ENCRYPTED_FT_HEADER_SIZE ) << std::endl; + return false ; + } + + offset += ENCRYPTED_FT_EDATA_SIZE ; + uint32_t clear_item_offset = offset ; + + uint32_t authentication_tag_offset = offset + edata_size ; +#ifdef SERVER_DEBUG + FTSERVER_DEBUG() << " authen. tag : " << RsUtil::BinToHex(&edata[authentication_tag_offset],ENCRYPTED_FT_AUTHENTICATION_TAG_SIZE) << std::endl; +#endif + + bool result ; + + if(edata[2] == ENCRYPTED_FT_FORMAT_AEAD_CHACHA20_POLY1305) + result = librs::crypto::AEAD_chacha20_poly1305(encryption_key,initialization_vector,&edata[clear_item_offset],edata_size, &edata[aad_offset],aad_size, &edata[authentication_tag_offset],false) ; + else if(edata[2] == ENCRYPTED_FT_FORMAT_AEAD_CHACHA20_SHA256) + result = librs::crypto::AEAD_chacha20_sha256 (encryption_key,initialization_vector,&edata[clear_item_offset],edata_size, &edata[aad_offset],aad_size, &edata[authentication_tag_offset],false) ; + else + return false ; + +#ifdef SERVER_DEBUG + FTSERVER_DEBUG() << " authen. result : " << result << std::endl; + FTSERVER_DEBUG() << " decrypted daya : " << RsUtil::BinToHex(&edata[clear_item_offset],std::min(50u,edata_size)) << "(...)" << std::endl; +#endif + + if(!result) + { + FTSERVER_ERROR() << "(EE) decryption/authentication went wrong." << std::endl; + return false ; + } + + decrypted_item = dynamic_cast(deserialise(&edata[clear_item_offset],&edata_size)) ; + + if(decrypted_item == NULL) + return false ; + + return true ; +} +#endif + void p3turtle::getInfo( std::vector >& hashes_info, std::vector >& tunnels_info, std::vector& search_reqs_info, diff --git a/libretroshare/src/turtle/p3turtle.h b/libretroshare/src/turtle/p3turtle.h index 0c230b88b..2f7512753 100644 --- a/libretroshare/src/turtle/p3turtle.h +++ b/libretroshare/src/turtle/p3turtle.h @@ -332,6 +332,13 @@ class p3turtle: public p3Service, public RsTurtle, public p3Config /// Send a data request into the correct tunnel for the given file hash void sendTurtleData(const RsPeerId& virtual_peer_id, RsTurtleGenericTunnelItem *item) ; +#ifdef TODO + /// Encrypts/decrypts an item, using a autenticated construction + chacha20, based on the given 32 bytes master key. + /// + static bool encryptItem(const RsItem *item, uint8_t* encryption_master_key, RsTurtleGenericDataItem *& encrypted_item) ; + static bool decryptItem(RsTurtleGenericDataItem *item,uint8_t *encryption_master_key,RsItem *& decrypted_item) ; +#endif + private: //--------------------------- Admin/Helper functions -------------------------//