diff --git a/libretroshare/src/crypto/chacha20.cpp b/libretroshare/src/crypto/chacha20.cpp index b2b61e182..b49948457 100644 --- a/libretroshare/src/crypto/chacha20.cpp +++ b/libretroshare/src/crypto/chacha20.cpp @@ -307,18 +307,18 @@ static void print(const chacha20_state& s) static void add(chacha20_state& s,const chacha20_state& t) { for(uint32_t i=0;i<16;++i) s.c[i] += t.c[i] ; } -static uint8_t read16bits(char s) -{ - if(s >= '0' && s <= '9') - return s - '0' ; - else if(s >= 'a' && s <= 'f') - return s - 'a' + 10 ; - else if(s >= 'A' && s <= 'F') - return s - 'A' + 10 ; - else - throw std::runtime_error("Not an hex string!") ; -} - +// static uint8_t read16bits(char s) +// { +// if(s >= '0' && s <= '9') +// return s - '0' ; +// else if(s >= 'a' && s <= 'f') +// return s - 'a' + 10 ; +// else if(s >= 'A' && s <= 'F') +// return s - 'A' + 10 ; +// else +// throw std::runtime_error("Not an hex string!") ; +// } +// // static uint256_32 create_256bit_int(const std::string& s) // { // uint256_32 r(0,0,0,0,0,0,0,0) ; @@ -431,6 +431,12 @@ void poly1305_tag(uint8_t key[32],uint8_t *message,uint32_t size,uint8_t tag[16] tag[12] = (acc.b[3] >> 0) & 0xff ; tag[13] = (acc.b[3] >> 8) & 0xff ; tag[14] = (acc.b[3] >>16) & 0xff ; tag[15] = (acc.b[3] >>24) & 0xff ; } +void AEAD_chacha20_poly1305(uint8_t key[32], uint8_t nonce[12],uint8_t *data,uint32_t data_size,uint8_t *aad,uint32_t aad_size,uint8_t tag[16]) +{ +#warning this part is not implemented yet. + memset(tag,0xff,16) ; +} + void perform_tests() { std::cerr << "Testing Chacha20" << std::endl; diff --git a/libretroshare/src/crypto/chacha20.h b/libretroshare/src/crypto/chacha20.h index 77f266193..bc6f86a03 100644 --- a/libretroshare/src/crypto/chacha20.h +++ b/libretroshare/src/crypto/chacha20.h @@ -62,7 +62,18 @@ namespace librs * \param size size of the data * \param tag generated poly1305 tag. */ - static void AEAD_chacha20_poly1305(uint8_t key[32], uint8_t nonce[12],uint8_t *data,uint32_t data_size,uint8_t *aad,uint8_t *aad_size,uint8_t tag[16]) ; + static void AEAD_chacha20_poly1305(uint8_t key[32], uint8_t nonce[12],uint8_t *data,uint32_t data_size,uint8_t *aad,uint32_t aad_size,uint8_t tag[16]) ; + + /*! + * \brief constant_time_memcmp + * Provides a constant time comparison of two memory chunks. The implementation comes from the FreeBSD implementation. + * + * \param m1 memory block 1 + * \param m2 memory block 2 + * \param size common size of m1 and m2 + * \return + */ + static bool constant_time_memcmp(const uint8_t *m1,const uint8_t *m2,uint32_t size) ; /*! * \brief perform_tests diff --git a/libretroshare/src/ft/ftserver.cc b/libretroshare/src/ft/ftserver.cc index 832530ade..382dbb4a9 100644 --- a/libretroshare/src/ft/ftserver.cc +++ b/libretroshare/src/ft/ftserver.cc @@ -27,6 +27,8 @@ #include #include "util/rsdebug.h" #include "util/rsdir.h" +#include "util/rsprint.h" +#include "crypto/chacha20.h" #include "retroshare/rstypes.h" #include "retroshare/rspeers.h" const int ftserverzone = 29539; @@ -984,6 +986,113 @@ bool ftServer::sendData(const RsPeerId& peerId, const RsFileHash& hash, uint64_t return true; } +// Encrypts the given item using aead-chacha20-poly1305 +// +// The format is the following +// +// [encryption format] [random initialization vector] [encrypted data size] [encrypted data] [authentication tag] +// 4 bytes 12 bytes 4 bytes variable 16 bytes +// +// +-------------------- authenticated data part ----------------------+ +// +// +// Encryption format: +// ae ad 00 01 : encryption using AEAD, format 00, version 01 +// +// + +void ftServer::deriveEncryptionKey(const RsFileHash& hash, uint8_t *key) +{ + // The encryption key is simply the 256 hash of the + SHA256_CTX sha_ctx ; + + if(SHA256_DIGEST_LENGTH != 32) + throw std::runtime_error("Warning: can't compute Sha1Sum with sum size != 32") ; + + SHA256_Init(&sha_ctx); + SHA256_Update(&sha_ctx, hash.toByteArray(), hash.SIZE_IN_BYTES); + SHA256_Final (key, &sha_ctx); +} + +bool ftServer::encryptItem(RsTurtleGenericTunnelItem *clear_item,const RsFileHash& hash,RsTurtleGenericDataItem *& encrypted_item) +{ + 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 ; + + uint8_t initialization_vector[ENCRYPTED_FT_INITIALIZATION_VECTOR_SIZE] ; + + RSRandom::random_bytes(initialization_vector,ENCRYPTED_FT_INITIALIZATION_VECTOR_SIZE) ; + + std::cerr << "ftServer::Encrypting ft item." << std::endl; + std::cerr << " random nonce : " << RsUtil::BinToHex(initialization_vector,ENCRYPTED_FT_INITIALIZATION_VECTOR_SIZE) << std::endl; + + uint32_t total_data_size = ENCRYPTED_FT_HEADER_SIZE + ENCRYPTED_FT_INITIALIZATION_VECTOR_SIZE + clear_item->serial_size() + ENCRYPTED_FT_AUTHENTICATION_TAG_SIZE ; + + std::cerr << " clear part size : " << clear_item->serial_size() << std::endl; + std::cerr << " total item size : " << total_data_size << std::endl; + + 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 = clear_item->serial_size() ; + uint32_t offset = 0; + + edata[0] = 0xae ; + edata[1] = 0xad ; + edata[2] = 0x00 ; + 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); + clear_item->serialize(&edata[offset], ser_size); + + std::cerr << " clear item : " << RsUtil::BinToHex(&edata[offset],std::min(50,(int)total_data_size-(int)offset)) << "(...)" << std::endl; + + 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) ; + + librs::crypto::AEAD_chacha20_poly1305(encryption_key,initialization_vector,&edata[clear_item_offset],edata_size, &edata[aad_offset],aad_size, &edata[authentication_tag_offset]) ; + + std::cerr << " encryption key : " << RsUtil::BinToHex(encryption_key,32) << std::endl; + std::cerr << " authen. tag : " << RsUtil::BinToHex(&edata[authentication_tag_offset],ENCRYPTED_FT_AUTHENTICATION_TAG_SIZE) << std::endl; + std::cerr << " final item : " << RsUtil::BinToHex(&edata[0],std::min(50u,total_data_size)) << "(...)" << std::endl; + + return true ; +} + +// Decrypts the given item using aead-chacha20-poly1305 + +bool ftServer::decryptItem(RsTurtleGenericTunnelItem *encrypted_item,const RsFileHash& hash,RsTurtleGenericDataItem *& decrypted_item) +{ + decrypted_item = NULL ; +} + // Dont delete the item. The client (p3turtle) is doing it after calling this. // void ftServer::receiveTurtleData(RsTurtleGenericTunnelItem *i, diff --git a/libretroshare/src/ft/ftserver.h b/libretroshare/src/ft/ftserver.h index c5d1d23eb..97e54ffd6 100644 --- a/libretroshare/src/ft/ftserver.h +++ b/libretroshare/src/ft/ftserver.h @@ -224,6 +224,10 @@ public: virtual bool sendSingleChunkCRCRequest(const RsPeerId& peer_id,const RsFileHash& hash,uint32_t chunk_number) ; virtual bool sendSingleChunkCRC(const RsPeerId& peer_id,const RsFileHash& hash,uint32_t chunk_number,const Sha1CheckSum& crc) ; + static void deriveEncryptionKey(const RsFileHash& hash, uint8_t *key); + static bool encryptItem(RsTurtleGenericTunnelItem *clear_item,const RsFileHash& hash,RsTurtleGenericDataItem *& encrypted_item); + static bool decryptItem(RsTurtleGenericTunnelItem *encrypted_item,const RsFileHash& hash,RsTurtleGenericDataItem *& decrypted_item); + /*************** Internal Transfer Fns *************************/ virtual int tick(); diff --git a/libretroshare/src/turtle/rsturtleitem.h b/libretroshare/src/turtle/rsturtleitem.h index 11e1969e7..db210b49c 100644 --- a/libretroshare/src/turtle/rsturtleitem.h +++ b/libretroshare/src/turtle/rsturtleitem.h @@ -35,6 +35,7 @@ class RsTurtleItem: public RsItem public: RsTurtleItem(uint8_t turtle_subtype) : RsItem(RS_PKT_VERSION_SERVICE,RS_SERVICE_TYPE_TURTLE,turtle_subtype) {} +#warning we need some consts here virtual bool serialize(void *data,uint32_t& size) = 0 ; // Isn't it better that items can serialize themselves ? virtual uint32_t serial_size() = 0 ; // deserialise is handled using a constructor