diff --git a/src/crypto/chacha20.cpp b/src/crypto/chacha20.cpp new file mode 100644 index 000000000..bee4f034e --- /dev/null +++ b/src/crypto/chacha20.cpp @@ -0,0 +1,1242 @@ +/* + * RetroShare C++ File sharing default variables + * + * file_sharing/file_sharing_defaults.h + * + * Copyright 2016 by Mr.Alice + * + * 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.project@gmail.com". + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "crypto/chacha20.h" +#include "util/rsprint.h" +#include "util/rsrandom.h" +#include "util/rsscopetimer.h" + +#define rotl(x,n) { x = (x << n) | (x >> (-n & 31)) ;} + +//#define DEBUG_CHACHA20 + +namespace librs { +namespace crypto { + +/*! + * \brief The uint256_32 struct + * This structure represents 256bits integers, to be used for computing poly1305 authentication tags. + */ +struct uint256_32 +{ + uint32_t b[8] ; + + uint256_32() { memset(&b[0],0,8*sizeof(uint32_t)) ; } + + uint256_32(uint32_t b7,uint32_t b6,uint32_t b5,uint32_t b4,uint32_t b3,uint32_t b2,uint32_t b1,uint32_t b0) + { + b[0]=b0; b[1]=b1; b[2]=b2; b[3]=b3; + b[4]=b4; b[5]=b5; b[6]=b6; b[7]=b7; + } + + static uint256_32 random() + { + uint256_32 r ; + for(uint32_t i=0;i<8;++i) + r.b[i] = RSRandom::random_u32(); + + return r; + } + + // constant cost == + bool operator==(const uint256_32& u) + { + bool res = true ; + + if(b[0] != u.b[0]) res = false ; + if(b[1] != u.b[1]) res = false ; + if(b[2] != u.b[2]) res = false ; + if(b[3] != u.b[3]) res = false ; + if(b[4] != u.b[4]) res = false ; + if(b[5] != u.b[5]) res = false ; + if(b[6] != u.b[6]) res = false ; + if(b[7] != u.b[7]) res = false ; + + return res ; + } + + // Constant cost sum. + // + void operator +=(const uint256_32& u) + { + uint64_t v(0) ; + + v += (uint64_t)b[0] + (uint64_t)u.b[0] ; b[0] = (uint32_t)v ; v >>= 32; + v += (uint64_t)b[1] + (uint64_t)u.b[1] ; b[1] = (uint32_t)v ; v >>= 32; + v += (uint64_t)b[2] + (uint64_t)u.b[2] ; b[2] = (uint32_t)v ; v >>= 32; + v += (uint64_t)b[3] + (uint64_t)u.b[3] ; b[3] = (uint32_t)v ; v >>= 32; + v += (uint64_t)b[4] + (uint64_t)u.b[4] ; b[4] = (uint32_t)v ; v >>= 32; + v += (uint64_t)b[5] + (uint64_t)u.b[5] ; b[5] = (uint32_t)v ; v >>= 32; + v += (uint64_t)b[6] + (uint64_t)u.b[6] ; b[6] = (uint32_t)v ; v >>= 32; + v += (uint64_t)b[7] + (uint64_t)u.b[7] ; b[7] = (uint32_t)v ; + } + void operator -=(const uint256_32& u) + { + *this += ~u ; + ++*this ; + } + void operator++() + { + for(int i=0;i<8;++i) + if( ++b[i] ) + break ; + } + + bool operator<(const uint256_32& u) const + { + for(int i=7;i>=0;--i) + if(b[i] < u.b[i]) + return true ; + else + if(b[i] > u.b[i]) + return false ; + + return false ; + } + uint256_32 operator~() const + { + uint256_32 r(*this) ; + + r.b[0] = ~b[0] ; + r.b[1] = ~b[1] ; + r.b[2] = ~b[2] ; + r.b[3] = ~b[3] ; + r.b[4] = ~b[4] ; + r.b[5] = ~b[5] ; + r.b[6] = ~b[6] ; + r.b[7] = ~b[7] ; + + return r ; + } + + void poly1305clamp() + { + b[0] &= 0x0fffffff; + b[1] &= 0x0ffffffc; + b[2] &= 0x0ffffffc; + b[3] &= 0x0ffffffc; + } + // Constant cost product. + // + void operator *=(const uint256_32& u) + { + uint256_32 r ; + + for(int i=0;i<8;++i) + for(int j=0;j<8;++j) + if(i+j < 8) + { + uint64_t s = (uint64_t)u.b[j]*(uint64_t)b[i] ; + + uint256_32 partial ; + partial.b[i+j] = (s & 0xffffffff) ; + + if(i+j+1 < 8) + partial.b[i+j+1] = (s >> 32) ; + + r += partial; + } + *this = r; + } + + static void print(const uint256_32& s) + { + fprintf(stdout,"%08x %08x %08x %08x %08x %08x %08x %08x",(uint32_t)s.b[7],(uint32_t)s.b[6],(uint32_t)s.b[5],(uint32_t)s.b[4], + (uint32_t)s.b[3],(uint32_t)s.b[2],(uint32_t)s.b[1],(uint32_t)s.b[0]) ; + } + static int max_non_zero_of_height_bits(uint8_t s) + { + for(int i=7;i>=0;--i) + if((s & (1<=0;--c) + if(b[c] != 0) + { + if( (b[c] & 0xff000000) != 0) return (c<<5) + 3*8 + max_non_zero_of_height_bits(b[c] >> 24) ; + if( (b[c] & 0x00ff0000) != 0) return (c<<5) + 2*8 + max_non_zero_of_height_bits(b[c] >> 16) ; + if( (b[c] & 0x0000ff00) != 0) return (c<<5) + 1*8 + max_non_zero_of_height_bits(b[c] >> 8) ; + + return c*32 + 0*8 + max_non_zero_of_height_bits(b[c]) ; + } + return -1; + } + void lshift(uint32_t n) + { + uint32_t p = n >> 5; // n/32 + uint32_t u = n & 0x1f ; // n%32 + + if(p > 0) + for(int i=7;i>=0;--i) + b[i] = (i>=(int)p)?b[i-p]:0 ; + + uint32_t r = 0 ; + + if(u>0) + for(int i=0;i<8;++i) + { + uint32_t r1 = (b[i] >> (31-u+1)) ; + b[i] = (b[i] << u) & 0xffffffff; + b[i] += r ; + r = r1 ; + } + } + void lshift() + { + uint32_t r ; + uint32_t r1 ; + + r1 = (b[0] >> 31) ; b[0] <<= 1; r = r1 ; + r1 = (b[1] >> 31) ; b[1] <<= 1; b[1] += r ; r = r1 ; + r1 = (b[2] >> 31) ; b[2] <<= 1; b[2] += r ; r = r1 ; + r1 = (b[3] >> 31) ; b[3] <<= 1; b[3] += r ; r = r1 ; + r1 = (b[4] >> 31) ; b[4] <<= 1; b[4] += r ; r = r1 ; + r1 = (b[5] >> 31) ; b[5] <<= 1; b[5] += r ; r = r1 ; + r1 = (b[6] >> 31) ; b[6] <<= 1; b[6] += r ; r = r1 ; + b[7] <<= 1; b[7] += r ; + } + void rshift() + { + uint32_t r ; + uint32_t r1 ; + + r1 = b[7] & 0x1; b[7] >>= 1 ; r = r1 ; + r1 = b[6] & 0x1; b[6] >>= 1 ; if(r) b[6] += 0x80000000 ; r = r1 ; + r1 = b[5] & 0x1; b[5] >>= 1 ; if(r) b[5] += 0x80000000 ; r = r1 ; + r1 = b[4] & 0x1; b[4] >>= 1 ; if(r) b[4] += 0x80000000 ; r = r1 ; + r1 = b[3] & 0x1; b[3] >>= 1 ; if(r) b[3] += 0x80000000 ; r = r1 ; + r1 = b[2] & 0x1; b[2] >>= 1 ; if(r) b[2] += 0x80000000 ; r = r1 ; + r1 = b[1] & 0x1; b[1] >>= 1 ; if(r) b[1] += 0x80000000 ; r = r1 ; + b[0] >>= 1 ; if(r) b[0] += 0x80000000 ; + } +}; + +// Compute quotient and modulo of n by p where both n and p are 256bits integers. +// +static void quotient(const uint256_32& n,const uint256_32& p,uint256_32& q,uint256_32& r) +{ + // simple algorithm: add up multiples of u while keeping below *this. Once done, substract. + + r = n ; + q = uint256_32(0,0,0,0,0,0,0,0) ; + + int bmax = n.max_non_zero_bit() - p.max_non_zero_bit(); + + uint256_32 m(0,0,0,0,0,0,0,0) ; + uint256_32 d = p ; + + m.b[bmax/32] = (1u << (bmax%32)) ; // set m to be 2^bmax + + d.lshift(bmax); + + for(int b=bmax;b>=0;--b,d.rshift(),m.rshift()) + if(! (r < d)) + { + r -= d ; + q += m ; + } +} +static void remainder(const uint256_32& n,const uint256_32& p,uint256_32& r) +{ + // simple algorithm: add up multiples of u while keeping below *this. Once done, substract. + + r = n ; + int bmax = n.max_non_zero_bit() - p.max_non_zero_bit(); + + uint256_32 d = p ; + d.lshift(bmax); + + for(int b=bmax;b>=0;--b,d.rshift()) + if(! (r < d)) + r -= d ; +} + +class chacha20_state +{ +public: + uint32_t c[16] ; + + chacha20_state(uint8_t key[32],uint32_t block_counter,uint8_t nounce[12]) + { + c[0] = 0x61707865 ; + c[1] = 0x3320646e ; + c[2] = 0x79622d32 ; + c[3] = 0x6b206574 ; + + c[ 4] = (uint32_t)key[0 ] + (((uint32_t)key[1 ])<<8) + (((uint32_t)key[2 ])<<16) + (((uint32_t)key[3 ])<<24); + c[ 5] = (uint32_t)key[4 ] + (((uint32_t)key[5 ])<<8) + (((uint32_t)key[6 ])<<16) + (((uint32_t)key[7 ])<<24); + c[ 6] = (uint32_t)key[8 ] + (((uint32_t)key[9 ])<<8) + (((uint32_t)key[10])<<16) + (((uint32_t)key[11])<<24); + c[ 7] = (uint32_t)key[12] + (((uint32_t)key[13])<<8) + (((uint32_t)key[14])<<16) + (((uint32_t)key[15])<<24); + c[ 8] = (uint32_t)key[16] + (((uint32_t)key[17])<<8) + (((uint32_t)key[18])<<16) + (((uint32_t)key[19])<<24); + c[ 9] = (uint32_t)key[20] + (((uint32_t)key[21])<<8) + (((uint32_t)key[22])<<16) + (((uint32_t)key[23])<<24); + c[10] = (uint32_t)key[24] + (((uint32_t)key[25])<<8) + (((uint32_t)key[26])<<16) + (((uint32_t)key[27])<<24); + c[11] = (uint32_t)key[28] + (((uint32_t)key[29])<<8) + (((uint32_t)key[30])<<16) + (((uint32_t)key[31])<<24); + + c[12] = block_counter ; + + c[13] = (uint32_t)nounce[0 ] + (((uint32_t)nounce[1 ])<<8) + (((uint32_t)nounce[2 ])<<16) + (((uint32_t)nounce[3 ])<<24); + c[14] = (uint32_t)nounce[4 ] + (((uint32_t)nounce[5 ])<<8) + (((uint32_t)nounce[6 ])<<16) + (((uint32_t)nounce[7 ])<<24); + c[15] = (uint32_t)nounce[8 ] + (((uint32_t)nounce[9 ])<<8) + (((uint32_t)nounce[10])<<16) + (((uint32_t)nounce[11])<<24); + } +}; + +static void quarter_round(uint32_t& a,uint32_t& b,uint32_t& c,uint32_t& d) +{ + a += b ; d ^= a; rotl(d,16) ; //d <<<=16 ; + c += d ; b ^= c; rotl(b,12) ; //b <<<=12 ; + a += b ; d ^= a; rotl(d,8) ; //d <<<=8 ; + c += d ; b ^= c; rotl(b,7) ; //b <<<=7 ; +} + +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 void apply_20_rounds(chacha20_state& s) +{ + chacha20_state t(s) ; + + for(uint32_t i=0;i<10;++i) + { + quarter_round(s.c[ 0],s.c[ 4],s.c[ 8],s.c[12]) ; + quarter_round(s.c[ 1],s.c[ 5],s.c[ 9],s.c[13]) ; + quarter_round(s.c[ 2],s.c[ 6],s.c[10],s.c[14]) ; + quarter_round(s.c[ 3],s.c[ 7],s.c[11],s.c[15]) ; + quarter_round(s.c[ 0],s.c[ 5],s.c[10],s.c[15]) ; + quarter_round(s.c[ 1],s.c[ 6],s.c[11],s.c[12]) ; + quarter_round(s.c[ 2],s.c[ 7],s.c[ 8],s.c[13]) ; + quarter_round(s.c[ 3],s.c[ 4],s.c[ 9],s.c[14]) ; + } + + add(s,t) ; +} + +#ifdef DEBUG_CHACHA20 +static void print(const chacha20_state& s) +{ + fprintf(stdout,"%08x %08x %08x %08x\n",s.c[0 ],s.c[1 ],s.c[2 ],s.c[3 ]) ; + fprintf(stdout,"%08x %08x %08x %08x\n",s.c[4 ],s.c[5 ],s.c[6 ],s.c[7 ]) ; + fprintf(stdout,"%08x %08x %08x %08x\n",s.c[8 ],s.c[9 ],s.c[10],s.c[11]) ; + fprintf(stdout,"%08x %08x %08x %08x\n",s.c[12],s.c[13],s.c[14],s.c[15]) ; +} +#endif + +void chacha20_encrypt(uint8_t key[32], uint32_t block_counter, uint8_t nonce[12], uint8_t *data, uint32_t size) +{ + for(uint32_t i=0;i> (8*(k%4))) & 0xff) ; + } +} + +struct poly1305_state +{ + uint256_32 r ; + uint256_32 s ; + uint256_32 p ; + uint256_32 a ; +}; + +static void poly1305_init(poly1305_state& s,uint8_t key[32]) +{ + s.r = uint256_32( 0,0,0,0, + ((uint32_t)key[12] << 0) + ((uint32_t)key[13] << 8) + ((uint32_t)key[14] << 16) + ((uint32_t)key[15] << 24), + ((uint32_t)key[ 8] << 0) + ((uint32_t)key[ 9] << 8) + ((uint32_t)key[10] << 16) + ((uint32_t)key[11] << 24), + ((uint32_t)key[ 4] << 0) + ((uint32_t)key[ 5] << 8) + ((uint32_t)key[ 6] << 16) + ((uint32_t)key[ 7] << 24), + ((uint32_t)key[ 0] << 0) + ((uint32_t)key[ 1] << 8) + ((uint32_t)key[ 2] << 16) + ((uint32_t)key[ 3] << 24) + ); + + s.r.poly1305clamp(); + + s.s = uint256_32( 0,0,0,0, + ((uint32_t)key[28] << 0) + ((uint32_t)key[29] << 8) + ((uint32_t)key[30] << 16) + ((uint32_t)key[31] << 24), + ((uint32_t)key[24] << 0) + ((uint32_t)key[25] << 8) + ((uint32_t)key[26] << 16) + ((uint32_t)key[27] << 24), + ((uint32_t)key[20] << 0) + ((uint32_t)key[21] << 8) + ((uint32_t)key[22] << 16) + ((uint32_t)key[23] << 24), + ((uint32_t)key[16] << 0) + ((uint32_t)key[17] << 8) + ((uint32_t)key[18] << 16) + ((uint32_t)key[19] << 24) + ); + + s.p = uint256_32(0,0,0,0x3,0xffffffff,0xffffffff,0xffffffff,0xfffffffb) ; + s.a = uint256_32(0,0,0, 0, 0, 0, 0, 0) ; +} + +// Warning: each call will automatically *pad* the data to a multiple of 16 bytes. +// +static void poly1305_add(poly1305_state& s,uint8_t *message,uint32_t size,bool pad_to_16_bytes=false) +{ +#ifdef DEBUG_CHACHA20 + std::cerr << "Poly1305: digesting " << RsUtil::BinToHex(message,size) << std::endl; +#endif + + for(uint32_t i=0;i<(size+15)/16;++i) + { + uint256_32 block ; + uint32_t j; + + for(j=0;j<16 && i*16+j < size;++j) + block.b[j/4] += ((uint64_t)message[i*16+j]) << (8*(j & 0x3)) ; + + if(pad_to_16_bytes) + block.b[4] += 0x01 ; + else + block.b[j/4] += 0x01 << (8*(j& 0x3)); + + s.a += block ; + s.a *= s.r ; + + uint256_32 q,rst; + remainder(s.a,s.p,rst) ; + s.a = rst ; + } +} + +static void poly1305_finish(poly1305_state& s,uint8_t tag[16]) +{ + s.a += s.s ; + + tag[ 0] = (s.a.b[0] >> 0) & 0xff ; tag[ 1] = (s.a.b[0] >> 8) & 0xff ; tag[ 2] = (s.a.b[0] >>16) & 0xff ; tag[ 3] = (s.a.b[0] >>24) & 0xff ; + tag[ 4] = (s.a.b[1] >> 0) & 0xff ; tag[ 5] = (s.a.b[1] >> 8) & 0xff ; tag[ 6] = (s.a.b[1] >>16) & 0xff ; tag[ 7] = (s.a.b[1] >>24) & 0xff ; + tag[ 8] = (s.a.b[2] >> 0) & 0xff ; tag[ 9] = (s.a.b[2] >> 8) & 0xff ; tag[10] = (s.a.b[2] >>16) & 0xff ; tag[11] = (s.a.b[2] >>24) & 0xff ; + tag[12] = (s.a.b[3] >> 0) & 0xff ; tag[13] = (s.a.b[3] >> 8) & 0xff ; tag[14] = (s.a.b[3] >>16) & 0xff ; tag[15] = (s.a.b[3] >>24) & 0xff ; +} + +void poly1305_tag(uint8_t key[32],uint8_t *message,uint32_t size,uint8_t tag[16]) +{ + poly1305_state s; + + poly1305_init (s,key); + poly1305_add(s,message,size) ; + poly1305_finish(s,tag); +} + +static void poly1305_key_gen(uint8_t key[32], uint8_t nonce[12], uint8_t generated_key[32]) +{ + uint32_t counter = 0 ; + + chacha20_state s(key,counter,nonce); + apply_20_rounds(s) ; + + for(uint32_t k=0;k<8;++k) + for(uint32_t i=0;i<4;++i) + generated_key[k*4 + i] = (s.c[k] >> 8*i) & 0xff ; +} + +bool constant_time_memory_compare(const uint8_t *m1,const uint8_t *m2,uint32_t size) +{ + return !CRYPTO_memcmp(m1,m2,size) ; +} + +bool 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],bool encrypt) +{ + // encrypt + tag. See RFC7539-2.8 + + uint8_t session_key[32]; + poly1305_key_gen(key,nonce,session_key); + + uint8_t lengths_vector[16] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } ; + + for(uint32_t i=0;i<4;++i) + { + lengths_vector[0+i] = ( aad_size >> (8*i)) & 0xff ; + lengths_vector[8+i] = (data_size >> (8*i)) & 0xff ; + } + + if(encrypt) + { + chacha20_encrypt(key,1,nonce,data,data_size); + + poly1305_state pls ; + + poly1305_init(pls,session_key); + + poly1305_add(pls,aad,aad_size,true); // add and pad the aad + poly1305_add(pls,data,data_size,true); // add and pad the cipher text + poly1305_add(pls,lengths_vector,16,true); // add the lengths + + poly1305_finish(pls,tag); + return true ; + } + else + { + poly1305_state pls ; + uint8_t computed_tag[16]; + + poly1305_init(pls,session_key); + + poly1305_add(pls,aad,aad_size,true); // add and pad the aad + poly1305_add(pls,data,data_size,true); // add and pad the cipher text + poly1305_add(pls,lengths_vector,16,true); // add the lengths + + poly1305_finish(pls,computed_tag); + + // decrypt + + chacha20_encrypt(key,1,nonce,data,data_size); + + return constant_time_memory_compare(tag,computed_tag,16) ; + } +} + +bool AEAD_chacha20_sha256(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],bool encrypt) +{ + // encrypt + tag. See RFC7539-2.8 + + if(encrypt) + { + chacha20_encrypt(key,1,nonce,data,data_size); + + uint8_t computed_tag[EVP_MAX_MD_SIZE]; + unsigned int md_size ; + + HMAC_CTX hmac_ctx ; + HMAC_CTX_init(&hmac_ctx) ; + + HMAC_Init(&hmac_ctx,key,32,EVP_sha256()) ; + HMAC_Update(&hmac_ctx,aad,aad_size) ; + HMAC_Update(&hmac_ctx,data,data_size) ; + HMAC_Final(&hmac_ctx,computed_tag,&md_size) ; + + assert(md_size >= 16); + + memcpy(tag,computed_tag,16) ; + + return true ; + } + else + { + uint8_t computed_tag[EVP_MAX_MD_SIZE]; + unsigned int md_size ; + + HMAC_CTX hmac_ctx ; + HMAC_CTX_init(&hmac_ctx) ; + + HMAC_Init(&hmac_ctx,key,32,EVP_sha256()) ; + HMAC_Update(&hmac_ctx,aad,aad_size) ; + HMAC_Update(&hmac_ctx,data,data_size) ; + HMAC_Final(&hmac_ctx,computed_tag,&md_size) ; + + // decrypt + + chacha20_encrypt(key,1,nonce,data,data_size); + + return constant_time_memory_compare(tag,computed_tag,16) ; + } +} + + +bool perform_tests() +{ + // RFC7539 - 2.1.1 + + std::cerr << " quarter round " ; + + uint32_t a = 0x11111111 ; + uint32_t b = 0x01020304 ; + uint32_t c = 0x9b8d6f43 ; + uint32_t d = 0x01234567 ; + + quarter_round(a,b,c,d) ; + + if(!(a == 0xea2a92f4)) return false ; + if(!(b == 0xcb1cf8ce)) return false ; + if(!(c == 0x4581472e)) return false ; + if(!(d == 0x5881c4bb)) return false ; + + std::cerr << " OK" << std::endl; + + // RFC7539 - 2.3.2 + + std::cerr << " RFC7539 - 2.3.2 " ; + + uint8_t key[32] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b, \ + 0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, \ + 0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f } ; + uint8_t nounce[12] = { 0x00,0x00,0x00,0x09,0x00,0x00,0x00,0x4a,0x00,0x00,0x00,0x00 } ; + + chacha20_state s(key,1,nounce) ; + +#ifdef DEBUG_CHACHA20 + print(s) ; +#endif + + apply_20_rounds(s) ; + +#ifdef DEBUG_CHACHA20 + fprintf(stdout,"\n") ; + + print(s) ; +#endif + + uint32_t check_vals[16] = { + 0xe4e7f110, 0x15593bd1, 0x1fdd0f50, 0xc47120a3, + 0xc7f4d1c7, 0x0368c033, 0x9aaa2204, 0x4e6cd4c3, + 0x466482d2, 0x09aa9f07, 0x05d7c214, 0xa2028bd9, + 0xd19c12b5, 0xb94e16de, 0xe883d0cb, 0x4e3c50a2 + }; + + for(uint32_t i=0;i<16;++i) + if(s.c[i] != check_vals[i]) + return false ; + + std::cerr << " OK" << std::endl; + + // RFC7539 - 2.4.2 + + std::cerr << " RFC7539 - 2.4.2 " ; + + uint8_t nounce2[12] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4a,0x00,0x00,0x00,0x00 } ; + + uint8_t plaintext[7*16+2] = { + 0x4c, 0x61, 0x64, 0x69, 0x65, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x47, 0x65, 0x6e, 0x74, 0x6c, + 0x65, 0x6d, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x61, 0x73, + 0x73, 0x20, 0x6f, 0x66, 0x20, 0x27, 0x39, 0x39, 0x3a, 0x20, 0x49, 0x66, 0x20, 0x49, 0x20, 0x63, + 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6f, 0x66, 0x66, 0x65, 0x72, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6f, + 0x6e, 0x6c, 0x79, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x74, 0x69, 0x70, 0x20, 0x66, 0x6f, 0x72, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x66, 0x75, 0x74, 0x75, 0x72, 0x65, 0x2c, 0x20, 0x73, 0x75, 0x6e, 0x73, + 0x63, 0x72, 0x65, 0x65, 0x6e, 0x20, 0x77, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x69, + 0x74, 0x2e + }; + + chacha20_encrypt(key,1,nounce2,plaintext,7*16+2) ; + +#ifdef DEBUG_CHACHA20 + fprintf(stdout,"CipherText: \n") ; + + for(uint32_t k=0;k<7*16+2;++k) + { + fprintf(stdout,"%02x ",plaintext[k]) ; + + if( (k % 16) == 15) + fprintf(stdout,"\n") ; + } + fprintf(stdout,"\n") ; +#endif + + uint8_t check_cipher_text[7*16+2] = { + 0x6e, 0x2e, 0x35, 0x9a, 0x25, 0x68, 0xf9, 0x80, 0x41, 0xba, 0x07, 0x28, 0xdd, 0x0d, 0x69, 0x81, + 0xe9, 0x7e, 0x7a, 0xec, 0x1d, 0x43, 0x60, 0xc2, 0x0a, 0x27, 0xaf, 0xcc, 0xfd, 0x9f, 0xae, 0x0b, + 0xf9, 0x1b, 0x65, 0xc5, 0x52, 0x47, 0x33, 0xab, 0x8f, 0x59, 0x3d, 0xab, 0xcd, 0x62, 0xb3, 0x57, + 0x16, 0x39, 0xd6, 0x24, 0xe6, 0x51, 0x52, 0xab, 0x8f, 0x53, 0x0c, 0x35, 0x9f, 0x08, 0x61, 0xd8, + 0x07, 0xca, 0x0d, 0xbf, 0x50, 0x0d, 0x6a, 0x61, 0x56, 0xa3, 0x8e, 0x08, 0x8a, 0x22, 0xb6, 0x5e, + 0x52, 0xbc, 0x51, 0x4d, 0x16, 0xcc, 0xf8, 0x06, 0x81, 0x8c, 0xe9, 0x1a, 0xb7, 0x79, 0x37, 0x36, + 0x5a, 0xf9, 0x0b, 0xbf, 0x74, 0xa3, 0x5b, 0xe6, 0xb4, 0x0b, 0x8e, 0xed, 0xf2, 0x78, 0x5e, 0x42, + 0x87, 0x4d + }; + + for(uint32_t i=0;i<7*16+2;++i) + if(!(check_cipher_text[i] == plaintext[i] )) + return false; + + std::cerr << " OK" << std::endl; + + // operators + + { uint256_32 uu(0,0,0,0,0,0,0,0 ) ; ++uu ; if(!(uu == uint256_32(0,0,0,0,0,0,0,1))) return false ; } + { uint256_32 uu(0,0,0,0,0,0,0,0xffffffff) ; ++uu ; if(!(uu == uint256_32(0,0,0,0,0,0,1,0))) return false ; } + { uint256_32 uu(0,0,0,0,0,0,0,0) ; uu = ~uu;++uu ; if(!(uu == uint256_32(0,0,0,0,0,0,0,0))) return false ; } + + std::cerr << " operator++ on 256bits numbers OK" << std::endl; + + // sums/diffs of numbers + + for(uint32_t i=0;i<100;++i) + { + uint256_32 a = uint256_32::random() ; + uint256_32 b = uint256_32::random() ; +#ifdef DEBUG_CHACHA20 + fprintf(stdout,"Adding ") ; + uint256_32::print(a) ; + fprintf(stdout,"\n to ") ; + uint256_32::print(b) ; +#endif + + uint256_32 c(a) ; + if(!(c == a) ) + return false; + + c += b ; + +#ifdef DEBUG_CHACHA20 + fprintf(stdout,"\n found ") ; + uint256_32::print(c) ; +#endif + + c -= b ; + +#ifdef DEBUG_CHACHA20 + fprintf(stdout,"\n subst ") ; + uint256_32::print(c) ; + fprintf(stdout,"\n") ; +#endif + + if(!(a == a)) return false ; + if(!(c == a)) return false ; + + uint256_32 vv(0,0,0,0,0,0,0,1) ; + vv -= a ; + vv += a ; + + if(!(vv == uint256_32(0,0,0,0,0,0,0,1))) return false ; + + } + uint256_32 vv(0,0,0,0,0,0,0,0) ; + uint256_32 ww(0,0,0,0,0,0,0,1) ; + vv -= ww ; + if(!(vv == ~uint256_32(0,0,0,0,0,0,0,0))) return false; + + std::cerr << " Sums / diffs of 256bits numbers OK" << std::endl; + + // check that (a-b)*(c-d) = ac - bc - ad + bd + + for(uint32_t i=0;i<100;++i) + { + uint256_32 a = uint256_32::random(); + uint256_32 b = uint256_32::random(); + uint256_32 c = uint256_32::random(); + uint256_32 d = uint256_32::random(); + + uint256_32 amb(a) ; + amb -= b; + uint256_32 cmd(c) ; + cmd -= d; + uint256_32 ambtcmd(amb); + ambtcmd *= cmd ; + + uint256_32 atc(a) ; atc *= c ; + uint256_32 btc(b) ; btc *= c ; + uint256_32 atd(a) ; atd *= d ; + uint256_32 btd(b) ; btd *= d ; + + uint256_32 atcmbtcmatdpbtd(atc) ; + atcmbtcmatdpbtd -= btc ; + atcmbtcmatdpbtd -= atd ; + atcmbtcmatdpbtd += btd ; + + if(!(atcmbtcmatdpbtd == ambtcmd)) return false ; + } + std::cerr << " (a-b)*(c-d) == ac-bc-ad+bd on random OK" << std::endl; + + // shifts + + for(uint32_t i=0;i<100;++i) + { + uint256_32 x = uint256_32::random(); + uint256_32 y(x) ; + + uint32_t r = x.b[0] & 0x1 ; + x.rshift() ; + x.lshift() ; + + x.b[0] += r ; + + if(!(x == y) ) return false ; + } + std::cerr << " left/right shifting OK" << std::endl; + + // test modulo by computing modulo and recomputing the product. + + for(uint32_t i=0;i<100;++i) + { + uint256_32 q1(0,0,0,0,0,0,0,0),r1(0,0,0,0,0,0,0,0) ; + + uint256_32 n1 = uint256_32::random(); + uint256_32 p1 = uint256_32::random(); + + if(RSRandom::random_f32() < 0.2) + { + p1.b[7] = 0 ; + + if(RSRandom::random_f32() < 0.1) + p1.b[6] = 0 ; + } + + quotient(n1,p1,q1,r1) ; +#ifdef DEBUG_CHACHA20 + fprintf(stdout,"result: q=") ; uint256_32::print(q1) ; fprintf(stdout," r=") ; uint256_32::print(r1) ; fprintf(stdout,"\n") ; +#endif + + uint256_32 res(q1) ; + q1 *= p1 ; + q1 += r1 ; + + if(!(q1 == n1)) return false ; + } + std::cerr << " Quotient/modulo on random numbers OK" << std::endl; + + // RFC7539 - 2.5 + // + { + uint8_t key[32] = { 0x85,0xd6,0xbe,0x78,0x57,0x55,0x6d,0x33,0x7f,0x44,0x52,0xfe,0x42,0xd5,0x06,0xa8,0x01,0x03,0x80,0x8a,0xfb,0x0d,0xb2,0xfd,0x4a,0xbf,0xf6,0xaf,0x41,0x49,0xf5,0x1b } ; + uint8_t tag[16] ; + std::string msg("Cryptographic Forum Research Group") ; + + poly1305_tag(key,(uint8_t*)msg.c_str(),msg.length(),tag) ; + + uint8_t test_tag[16] = { 0xa8,0x06,0x1d,0xc1,0x30,0x51,0x36,0xc6,0xc2,0x2b,0x8b,0xaf,0x0c,0x01,0x27,0xa9 }; + + if(!(constant_time_memory_compare(tag,test_tag,16))) return false ; + } + std::cerr << " RFC7539 - 2.5 OK" << std::endl; + + // RFC7539 - Poly1305 test vector #1 + // + { + uint8_t key[32] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } ; + uint8_t tag[16] ; + uint8_t text[64] ; + memset(text,0,64) ; + + poly1305_tag(key,text,64,tag) ; + + uint8_t test_tag[16] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }; + + if(!(constant_time_memory_compare(tag,test_tag,16)) ) return false ; + } + std::cerr << " RFC7539 poly1305 test vector #001 OK" << std::endl; + + // RFC7539 - Poly1305 test vector #2 + // + { + uint8_t key[32] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x36,0xe5,0xf6,0xb5,0xc5,0xe0,0x60,0x70,0xf0,0xef,0xca,0x96,0x22,0x7a,0x86,0x3e } ; + uint8_t tag[16] ; + + std::string msg("Any submission to the IETF intended by the Contributor for publication as all or part of an IETF Internet-Draft or RFC and any statement made within the context of an IETF activity is considered an \"IETF Contribution\". Such statements include oral statements in IETF sessions, as well as written and electronic communications made at any time or place, which are addressed to") ; + + poly1305_tag(key,(uint8_t*)msg.c_str(),msg.length(),tag) ; + + uint8_t test_tag[16] = { 0x36,0xe5,0xf6,0xb5,0xc5,0xe0,0x60,0x70,0xf0,0xef,0xca,0x96,0x22,0x7a,0x86,0x3e }; + + if(!(constant_time_memory_compare(tag,test_tag,16)) ) return false ; + } + std::cerr << " RFC7539 poly1305 test vector #002 OK" << std::endl; + + // RFC7539 - Poly1305 test vector #3 + // + { + uint8_t key[32] = { 0x36,0xe5,0xf6,0xb5,0xc5,0xe0,0x60,0x70,0xf0,0xef,0xca,0x96,0x22,0x7a,0x86,0x3e, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } ; + uint8_t tag[16] ; + + std::string msg("Any submission to the IETF intended by the Contributor for publication as all or part of an IETF Internet-Draft or RFC and any statement made within the context of an IETF activity is considered an \"IETF Contribution\". Such statements include oral statements in IETF sessions, as well as written and electronic communications made at any time or place, which are addressed to") ; + + poly1305_tag(key,(uint8_t*)msg.c_str(),msg.length(),tag) ; + + uint8_t test_tag[16] = { 0xf3,0x47,0x7e,0x7c,0xd9,0x54,0x17,0xaf,0x89,0xa6,0xb8,0x79,0x4c,0x31,0x0c,0xf0 } ; + + if(!(constant_time_memory_compare(tag,test_tag,16)) ) return false ; + } + std::cerr << " RFC7539 poly1305 test vector #003 OK" << std::endl; + + // RFC7539 - Poly1305 test vector #4 + // + { + uint8_t key[32] = { 0x1c ,0x92 ,0x40 ,0xa5 ,0xeb ,0x55 ,0xd3 ,0x8a ,0xf3 ,0x33 ,0x88 ,0x86 ,0x04 ,0xf6 ,0xb5 ,0xf0, + 0x47 ,0x39 ,0x17 ,0xc1 ,0x40 ,0x2b ,0x80 ,0x09 ,0x9d ,0xca ,0x5c ,0xbc ,0x20 ,0x70 ,0x75 ,0xc0 }; + uint8_t tag[16] ; + + std::string msg("'Twas brillig, and the slithy toves\nDid gyre and gimble in the wabe:\nAll mimsy were the borogoves,\nAnd the mome raths outgrabe.") ; + + poly1305_tag(key,(uint8_t*)msg.c_str(),msg.length(),tag) ; + + uint8_t test_tag[16] = { 0x45,0x41,0x66,0x9a,0x7e,0xaa,0xee,0x61,0xe7,0x08,0xdc,0x7c,0xbc,0xc5,0xeb,0x62 } ; + + if(!(constant_time_memory_compare(tag,test_tag,16)) ) return false ; + } + std::cerr << " RFC7539 poly1305 test vector #004 OK" << std::endl; + + // RFC7539 - Poly1305 test vector #5 + // + { + uint8_t key[32] = { 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; + uint8_t tag[16] ; + + uint8_t msg[] = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff }; + + poly1305_tag(key,msg,16,tag) ; + + uint8_t test_tag[16] = { 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } ; + + if(!(constant_time_memory_compare(tag,test_tag,16)) ) return false ; + } + std::cerr << " RFC7539 poly1305 test vector #005 OK" << std::endl; + + // RFC7539 - Poly1305 test vector #6 + // + { + uint8_t key[32] = { 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff }; + uint8_t tag[16] ; + + uint8_t msg[16] = { 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; + + poly1305_tag(key,msg,16,tag) ; + + uint8_t test_tag[16] = { 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } ; + + if(!(constant_time_memory_compare(tag,test_tag,16)) ) return false ; + } + std::cerr << " RFC7539 poly1305 test vector #006 OK" << std::endl; + + // RFC7539 - Poly1305 test vector #7 + // + { + uint8_t key[32] = { 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; + uint8_t tag[16] ; + + uint8_t msg[48] = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } ; + + poly1305_tag(key,msg,48,tag) ; + + uint8_t test_tag[16] = { 0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } ; + + if(!(constant_time_memory_compare(tag,test_tag,16)) ) return false ; + } + std::cerr << " RFC7539 poly1305 test vector #007 OK" << std::endl; + + // RFC7539 - Poly1305 test vector #8 + // + { + uint8_t key[32] = { 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; + uint8_t tag[16] ; + + uint8_t msg[48] = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xfb,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe, + 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01 } ; + + poly1305_tag(key,msg,48,tag) ; + + uint8_t test_tag[16] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } ; + + if(!(constant_time_memory_compare(tag,test_tag,16)) ) return false ; + } + std::cerr << " RFC7539 poly1305 test vector #008 OK" << std::endl; + + // RFC7539 - Poly1305 test vector #9 + // + { + uint8_t key[32] = { 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; + uint8_t tag[16] ; + + uint8_t msg[16] = { 0xfd,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff } ; + + poly1305_tag(key,msg,16,tag) ; + + uint8_t test_tag[16] = { 0xfa,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff } ; + + if(!(constant_time_memory_compare(tag,test_tag,16)) ) return false ; + } + std::cerr << " RFC7539 poly1305 test vector #009 OK" << std::endl; + + // RFC7539 - Poly1305 test vector #10 + // + { + uint8_t key[32] = { 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; + uint8_t tag[16] ; + + uint8_t msg[64] = { + 0xE3 ,0x35 ,0x94 ,0xD7 ,0x50 ,0x5E ,0x43 ,0xB9 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00, + 0x33 ,0x94 ,0xD7 ,0x50 ,0x5E ,0x43 ,0x79 ,0xCD ,0x01 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00, + 0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00, + 0x01 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 }; + + poly1305_tag(key,msg,64,tag) ; + + uint8_t test_tag[16] = { 0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x55,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } ; + + if(!(constant_time_memory_compare(tag,test_tag,16)) ) return false ; + } + std::cerr << " RFC7539 poly1305 test vector #010 OK" << std::endl; + + // RFC7539 - Poly1305 test vector #11 + // + { + uint8_t key[32] = { 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; + uint8_t tag[16] ; + + uint8_t msg[48] = { + 0xE3 ,0x35 ,0x94 ,0xD7 ,0x50 ,0x5E ,0x43 ,0xB9 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00, + 0x33 ,0x94 ,0xD7 ,0x50 ,0x5E ,0x43 ,0x79 ,0xCD ,0x01 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00, + 0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 } ; + + poly1305_tag(key,msg,48,tag) ; + + uint8_t test_tag[16] = { 0x13,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } ; + + if(!constant_time_memory_compare(tag,test_tag,16)) return false ; + } + std::cerr << " RFC7539 poly1305 test vector #011 OK" << std::endl; + + // RFC7539 - 2.6.2 + // + { + uint8_t key[32] = { 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f, + 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f }; + + uint8_t session_key[32] ; + uint8_t test_session_key[32] = { 0x8a,0xd5,0xa0,0x8b,0x90,0x5f,0x81,0xcc,0x81,0x50,0x40,0x27,0x4a,0xb2,0x94,0x71, + 0xa8,0x33,0xb6,0x37,0xe3,0xfd,0x0d,0xa5,0x08,0xdb,0xb8,0xe2,0xfd,0xd1,0xa6,0x46 }; + + uint8_t nonce[12] = { 0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07 }; + + poly1305_key_gen(key,nonce,session_key) ; + + if(!constant_time_memory_compare(session_key,test_session_key,32)) return false ; + } + std::cerr << " RFC7539 - 2.6.2 OK" << std::endl; + + // RFC7539 - Poly1305 key generation. Test vector #1 + // + { + uint8_t key[32] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; + + uint8_t nonce[12] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; + uint8_t session_key[32] ; + uint8_t test_session_key[32] = { 0x76,0xb8,0xe0,0xad,0xa0,0xf1,0x3d,0x90,0x40,0x5d,0x6a,0xe5,0x53,0x86,0xbd,0x28, + 0xbd,0xd2,0x19,0xb8,0xa0,0x8d,0xed,0x1a,0xa8,0x36,0xef,0xcc,0x8b,0x77,0x0d,0xc7 }; + + poly1305_key_gen(key,nonce,session_key) ; + + if(!constant_time_memory_compare(session_key,test_session_key,32)) return false ; + } + std::cerr << " RFC7539 poly1305 key gen. TVec #1 OK" << std::endl; + + // RFC7539 - Poly1305 key generation. Test vector #2 + // + { + uint8_t key[32] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01 }; + + uint8_t nonce[12] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02 }; + uint8_t session_key[32] ; + uint8_t test_session_key[32] = { 0xec,0xfa,0x25,0x4f,0x84,0x5f,0x64,0x74,0x73,0xd3,0xcb,0x14,0x0d,0xa9,0xe8,0x76, + 0x06,0xcb,0x33,0x06,0x6c,0x44,0x7b,0x87,0xbc,0x26,0x66,0xdd,0xe3,0xfb,0xb7,0x39 }; + + + + poly1305_key_gen(key,nonce,session_key) ; + + if(!constant_time_memory_compare(session_key,test_session_key,32)) return false ; + } + std::cerr << " RFC7539 poly1305 key gen. TVec #2 OK" << std::endl; + + // RFC7539 - Poly1305 key generation. Test vector #3 + // + { + uint8_t key[32] = { 0x1c,0x92,0x40,0xa5,0xeb,0x55,0xd3,0x8a,0xf3,0x33,0x88,0x86,0x04,0xf6,0xb5,0xf0, + 0x47,0x39,0x17,0xc1,0x40,0x2b,0x80,0x09,0x9d,0xca,0x5c,0xbc,0x20,0x70,0x75,0xc0 }; + + uint8_t nonce[12] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02 }; + uint8_t session_key[32] ; + uint8_t test_session_key[32] = { 0x96,0x5e,0x3b,0xc6,0xf9,0xec,0x7e,0xd9,0x56,0x08,0x08,0xf4,0xd2,0x29,0xf9,0x4b, + 0x13,0x7f,0xf2,0x75,0xca,0x9b,0x3f,0xcb,0xdd,0x59,0xde,0xaa,0xd2,0x33,0x10,0xae }; + + poly1305_key_gen(key,nonce,session_key) ; + + if(!constant_time_memory_compare(session_key,test_session_key,32)) return false ; + } + std::cerr << " RFC7539 poly1305 key gen. TVec #3 OK" << std::endl; + + // RFC7539 - 2.8.2 + // + { + uint8_t msg[7*16+2] = { + 0x4c,0x61,0x64,0x69,0x65,0x73,0x20,0x61,0x6e,0x64,0x20,0x47,0x65,0x6e,0x74,0x6c, + 0x65,0x6d,0x65,0x6e,0x20,0x6f,0x66,0x20,0x74,0x68,0x65,0x20,0x63,0x6c,0x61,0x73, + 0x73,0x20,0x6f,0x66,0x20,0x27,0x39,0x39,0x3a,0x20,0x49,0x66,0x20,0x49,0x20,0x63, + 0x6f,0x75,0x6c,0x64,0x20,0x6f,0x66,0x66,0x65,0x72,0x20,0x79,0x6f,0x75,0x20,0x6f, + 0x6e,0x6c,0x79,0x20,0x6f,0x6e,0x65,0x20,0x74,0x69,0x70,0x20,0x66,0x6f,0x72,0x20, + 0x74,0x68,0x65,0x20,0x66,0x75,0x74,0x75,0x72,0x65,0x2c,0x20,0x73,0x75,0x6e,0x73, + 0x63,0x72,0x65,0x65,0x6e,0x20,0x77,0x6f,0x75,0x6c,0x64,0x20,0x62,0x65,0x20,0x69, + 0x74,0x2e } ; + + uint8_t test_msg[7*16+2] = { + 0xd3,0x1a,0x8d,0x34,0x64,0x8e,0x60,0xdb,0x7b,0x86,0xaf,0xbc,0x53,0xef,0x7e,0xc2, + 0xa4,0xad,0xed,0x51,0x29,0x6e,0x08,0xfe,0xa9,0xe2,0xb5,0xa7,0x36,0xee,0x62,0xd6, + 0x3d,0xbe,0xa4,0x5e,0x8c,0xa9,0x67,0x12,0x82,0xfa,0xfb,0x69,0xda,0x92,0x72,0x8b, + 0x1a,0x71,0xde,0x0a,0x9e,0x06,0x0b,0x29,0x05,0xd6,0xa5,0xb6,0x7e,0xcd,0x3b,0x36, + 0x92,0xdd,0xbd,0x7f,0x2d,0x77,0x8b,0x8c,0x98,0x03,0xae,0xe3,0x28,0x09,0x1b,0x58, + 0xfa,0xb3,0x24,0xe4,0xfa,0xd6,0x75,0x94,0x55,0x85,0x80,0x8b,0x48,0x31,0xd7,0xbc, + 0x3f,0xf4,0xde,0xf0,0x8e,0x4b,0x7a,0x9d,0xe5,0x76,0xd2,0x65,0x86,0xce,0xc6,0x4b, + 0x61,0x16 }; + + uint8_t aad[12] = { 0x50,0x51,0x52,0x53,0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7 }; + uint8_t nonce[12] = { 0x07,0x00,0x00,0x00,0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47 }; + + uint8_t key[32] = { 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f, + 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f }; + uint8_t tag[16] ; + uint8_t test_tag[16] = { 0x1a,0xe1,0x0b,0x59,0x4f,0x09,0xe2,0x6a,0x7e,0x90,0x2e,0xcb,0xd0,0x60,0x06,0x91 }; + + AEAD_chacha20_poly1305(key,nonce,msg,7*16+2,aad,12,tag,true) ; + + if(!constant_time_memory_compare(msg,test_msg,7*16+2)) return false ; + if(!constant_time_memory_compare(tag,test_tag,16)) return false ; + + bool res = AEAD_chacha20_poly1305(key,nonce,msg,7*16+2,aad,12,tag,false) ; + + if(!res) return false ; + } + std::cerr << " RFC7539 - 2.8.2 OK" << std::endl; + + + // RFC7539 - AEAD checking and decryption + // + { + uint8_t key[32] = { 0x1c,0x92,0x40,0xa5,0xeb,0x55,0xd3,0x8a,0xf3,0x33,0x88,0x86,0x04,0xf6,0xb5,0xf0, + 0x47,0x39,0x17,0xc1,0x40,0x2b,0x80,0x09,0x9d,0xca,0x5c,0xbc,0x20,0x70,0x75,0xc0 }; + + uint8_t nonce[12] = { 0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08 }; + + uint8_t ciphertext[16*16 + 9] = { + 0x64,0xa0,0x86,0x15,0x75,0x86,0x1a,0xf4,0x60,0xf0,0x62,0xc7,0x9b,0xe6,0x43,0xbd, + 0x5e,0x80,0x5c,0xfd,0x34,0x5c,0xf3,0x89,0xf1,0x08,0x67,0x0a,0xc7,0x6c,0x8c,0xb2, + 0x4c,0x6c,0xfc,0x18,0x75,0x5d,0x43,0xee,0xa0,0x9e,0xe9,0x4e,0x38,0x2d,0x26,0xb0, + 0xbd,0xb7,0xb7,0x3c,0x32,0x1b,0x01,0x00,0xd4,0xf0,0x3b,0x7f,0x35,0x58,0x94,0xcf, + 0x33,0x2f,0x83,0x0e,0x71,0x0b,0x97,0xce,0x98,0xc8,0xa8,0x4a,0xbd,0x0b,0x94,0x81, + 0x14,0xad,0x17,0x6e,0x00,0x8d,0x33,0xbd,0x60,0xf9,0x82,0xb1,0xff,0x37,0xc8,0x55, + 0x97,0x97,0xa0,0x6e,0xf4,0xf0,0xef,0x61,0xc1,0x86,0x32,0x4e,0x2b,0x35,0x06,0x38, + 0x36,0x06,0x90,0x7b,0x6a,0x7c,0x02,0xb0,0xf9,0xf6,0x15,0x7b,0x53,0xc8,0x67,0xe4, + 0xb9,0x16,0x6c,0x76,0x7b,0x80,0x4d,0x46,0xa5,0x9b,0x52,0x16,0xcd,0xe7,0xa4,0xe9, + 0x90,0x40,0xc5,0xa4,0x04,0x33,0x22,0x5e,0xe2,0x82,0xa1,0xb0,0xa0,0x6c,0x52,0x3e, + 0xaf,0x45,0x34,0xd7,0xf8,0x3f,0xa1,0x15,0x5b,0x00,0x47,0x71,0x8c,0xbc,0x54,0x6a, + 0x0d,0x07,0x2b,0x04,0xb3,0x56,0x4e,0xea,0x1b,0x42,0x22,0x73,0xf5,0x48,0x27,0x1a, + 0x0b,0xb2,0x31,0x60,0x53,0xfa,0x76,0x99,0x19,0x55,0xeb,0xd6,0x31,0x59,0x43,0x4e, + 0xce,0xbb,0x4e,0x46,0x6d,0xae,0x5a,0x10,0x73,0xa6,0x72,0x76,0x27,0x09,0x7a,0x10, + 0x49,0xe6,0x17,0xd9,0x1d,0x36,0x10,0x94,0xfa,0x68,0xf0,0xff,0x77,0x98,0x71,0x30, + 0x30,0x5b,0xea,0xba,0x2e,0xda,0x04,0xdf,0x99,0x7b,0x71,0x4d,0x6c,0x6f,0x2c,0x29, + 0xa6,0xad,0x5c,0xb4,0x02,0x2b,0x02,0x70,0x9b }; + + uint8_t aad[12] = { 0xf3,0x33,0x88,0x86,0x00,0x00,0x00,0x00,0x00,0x00,0x4e,0x91 }; + + uint8_t received_tag[16] = { 0xee,0xad,0x9d,0x67,0x89,0x0c,0xbb,0x22,0x39,0x23,0x36,0xfe,0xa1,0x85,0x1f,0x38 }; + + if(!AEAD_chacha20_poly1305(key,nonce,ciphertext,16*16+9,aad,12,received_tag,false)) + return false ; + + uint8_t cleartext[16*16+9] = { + 0x49,0x6e,0x74,0x65,0x72,0x6e,0x65,0x74,0x2d,0x44,0x72,0x61,0x66,0x74,0x73,0x20, + 0x61,0x72,0x65,0x20,0x64,0x72,0x61,0x66,0x74,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65, + 0x6e,0x74,0x73,0x20,0x76,0x61,0x6c,0x69,0x64,0x20,0x66,0x6f,0x72,0x20,0x61,0x20, + 0x6d,0x61,0x78,0x69,0x6d,0x75,0x6d,0x20,0x6f,0x66,0x20,0x73,0x69,0x78,0x20,0x6d, + 0x6f,0x6e,0x74,0x68,0x73,0x20,0x61,0x6e,0x64,0x20,0x6d,0x61,0x79,0x20,0x62,0x65, + 0x20,0x75,0x70,0x64,0x61,0x74,0x65,0x64,0x2c,0x20,0x72,0x65,0x70,0x6c,0x61,0x63, + 0x65,0x64,0x2c,0x20,0x6f,0x72,0x20,0x6f,0x62,0x73,0x6f,0x6c,0x65,0x74,0x65,0x64, + 0x20,0x62,0x79,0x20,0x6f,0x74,0x68,0x65,0x72,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65, + 0x6e,0x74,0x73,0x20,0x61,0x74,0x20,0x61,0x6e,0x79,0x20,0x74,0x69,0x6d,0x65,0x2e, + 0x20,0x49,0x74,0x20,0x69,0x73,0x20,0x69,0x6e,0x61,0x70,0x70,0x72,0x6f,0x70,0x72, + 0x69,0x61,0x74,0x65,0x20,0x74,0x6f,0x20,0x75,0x73,0x65,0x20,0x49,0x6e,0x74,0x65, + 0x72,0x6e,0x65,0x74,0x2d,0x44,0x72,0x61,0x66,0x74,0x73,0x20,0x61,0x73,0x20,0x72, + 0x65,0x66,0x65,0x72,0x65,0x6e,0x63,0x65,0x20,0x6d,0x61,0x74,0x65,0x72,0x69,0x61, + 0x6c,0x20,0x6f,0x72,0x20,0x74,0x6f,0x20,0x63,0x69,0x74,0x65,0x20,0x74,0x68,0x65, + 0x6d,0x20,0x6f,0x74,0x68,0x65,0x72,0x20,0x74,0x68,0x61,0x6e,0x20,0x61,0x73,0x20, + 0x2f,0xe2,0x80,0x9c,0x77,0x6f,0x72,0x6b,0x20,0x69,0x6e,0x20,0x70,0x72,0x6f,0x67, + 0x72,0x65,0x73,0x73,0x2e,0x2f,0xe2,0x80,0x9d } ; + + if(!constant_time_memory_compare(cleartext,ciphertext,16*16+9)) + return false ; + } + std::cerr << " RFC7539 AEAD test vector #1 OK" << std::endl; + + // bandwidth test + // + + { + uint32_t SIZE = 1*1024*1024 ; + uint8_t *ten_megabyte_data = (uint8_t*)malloc(SIZE) ; + + uint8_t key[32] = { 0x1c,0x92,0x40,0xa5,0xeb,0x55,0xd3,0x8a,0xf3,0x33,0x88,0x86,0x04,0xf6,0xb5,0xf0, + 0x47,0x39,0x17,0xc1,0x40,0x2b,0x80,0x09,0x9d,0xca,0x5c,0xbc,0x20,0x70,0x75,0xc0 }; + + uint8_t nonce[12] = { 0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08 }; + uint8_t aad[12] = { 0xf3,0x33,0x88,0x86,0x00,0x00,0x00,0x00,0x00,0x00,0x4e,0x91 }; + + uint8_t received_tag[16] ; + + { + RsScopeTimer s("AEAD1") ; + chacha20_encrypt(key, 1, nonce, ten_megabyte_data,SIZE) ; + + std::cerr << " Chacha20 encryption speed : " << SIZE / (1024.0*1024.0) / s.duration() << " MB/s" << std::endl; + } + { + RsScopeTimer s("AEAD2") ; + AEAD_chacha20_poly1305(key,nonce,ten_megabyte_data,SIZE,aad,12,received_tag,true) ; + + std::cerr << " AEAD/poly1305 encryption speed: " << SIZE / (1024.0*1024.0) / s.duration() << " MB/s" << std::endl; + } + { + RsScopeTimer s("AEAD3") ; + AEAD_chacha20_sha256(key,nonce,ten_megabyte_data,SIZE,aad,12,received_tag,true) ; + + std::cerr << " AEAD/sha256 encryption speed : " << SIZE / (1024.0*1024.0) / s.duration() << " MB/s" << std::endl; + } + + free(ten_megabyte_data) ; + } + + return true; +} + +} +} + + diff --git a/src/crypto/chacha20.h b/src/crypto/chacha20.h new file mode 100644 index 000000000..ffce04605 --- /dev/null +++ b/src/crypto/chacha20.h @@ -0,0 +1,116 @@ +/* + * RetroShare C++ File sharing default variables + * + * crypto/chacha20.h + * + * Copyright 2016 by Mr.Alice + * + * 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.project@gmail.com". + * + */ + +#include + +namespace librs +{ + namespace crypto + { + /*! + * \brief chacha20_encrypt + * Performs in place encryption/decryption of the supplied data, using chacha20, using the supplied key and nonce. + * + * \param key secret encryption key. *Should never* be re-used. + * \param block_counter any integer. 0 is fine. + * \param nonce acts as an initialzation vector. /!\ it is extremely important to make sure that this nounce *is* everytime different. Using a purely random value is fine. + * \param data data that gets encrypted/decrypted in place + * \param size size of the data. + */ + void chacha20_encrypt(uint8_t key[32], uint32_t block_counter, uint8_t nonce[12], uint8_t *data, uint32_t size) ; + + /*! + * \brief poly1305_tag + * Computes an authentication tag for the supplied data, using the given secret key. + * \param key secret key. *Should not* be used multiple times. + * \param message message to generate a tag for + * \param size size of the message + * \param tag place where the tag is stored. + */ + + void poly1305_tag(uint8_t key[32],uint8_t *message,uint32_t size,uint8_t tag[16]); + + /*! + * \brief AEAD_chacha20_poly1305 + * Provides in-place authenticated encryption using the AEAD construction as described in RFC7539. + * The data is first encrypted in place then 16-padded and concatenated to its size, than concatenated to the + * 16-padded AAD (additional authenticated data) and its size, authenticated using poly1305. + * + * \param key key that is used to derive a one time secret key for poly1305 and that is also used to encrypt the data + * \param nonce nonce. *Should be unique* in order to make the chacha20 stream cipher unique. + * \param data data that is encrypted/decrypted in place. + * \param size size of the data + * \param aad additional authenticated data. Can be used to authenticate the nonce. + * \param aad_size + * \param tag generated poly1305 tag. + * \param encrypt true to encrypt, false to decrypt and check the tag. + * \return + * always true for encryption. + * authentication result for decryption. data is *always* xored to the cipher stream whatever the authentication result is. + */ + bool 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],bool encrypt_or_decrypt) ; + + /*! + * \brief AEAD_chacha20_sha256 + * Provides authenticated encryption using a simple construction that associates chacha20 encryption with HMAC authentication using + * the same 32 bytes key. The authenticated tag is the 16 first bytes of the sha256 HMAC. + * + * \param key encryption/authentication key + * \param nonce nonce. *Should be unique* in order to make chacha20 stream cipher unique. + * \param data data that is encrypted/decrypted in place + * \param data_size size of data to encrypt/authenticate + * \param aad additional authenticated data. Can be used to authenticate the nonce. + * \param aad_size + * \param tag 16 bytes authentication tag result + * \param encrypt true to encrypt, false to decrypt and check the tag. + * \return + * always true for encryption. + * authentication result for decryption. data is *always* xored to the cipher stream whatever the authentication result is. + */ + bool AEAD_chacha20_sha256(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],bool encrypt_or_decrypt) ; + + /*! + * \brief constant_time_memcmp + * Provides a constant time comparison of two memory chunks. Calls CRYPTO_memcmp. + * + * \param m1 memory block 1 + * \param m2 memory block 2 + * \param size common size of m1 and m2 + * \return + * false if the two chunks are different + * true if the two chunks are identical + */ + bool constant_time_memory_compare(const uint8_t *m1,const uint8_t *m2,uint32_t size) ; + + /*! + * \brief perform_tests + * Tests all methods in this class, using the tests supplied in RFC7539 + * \return + * true is all tests pass + */ + + bool perform_tests() ; + } +} diff --git a/src/file_sharing/dir_hierarchy.cc b/src/file_sharing/dir_hierarchy.cc index 07e395455..19d0b543a 100644 --- a/src/file_sharing/dir_hierarchy.cc +++ b/src/file_sharing/dir_hierarchy.cc @@ -299,8 +299,7 @@ bool InternalFileHierarchyStorage::updateSubFilesList(const DirectoryStorage::En std::cerr << "[directory storage] removing non existing file " << f.file_name << " at index " << d.subfiles[i] << std::endl; #endif - delete mNodes[d.subfiles[i]] ; - mNodes[d.subfiles[i]] = NULL ; + deleteNode(d.subfiles[i]) ; d.subfiles[i] = d.subfiles[d.subfiles.size()-1] ; d.subfiles.pop_back(); @@ -374,23 +373,29 @@ bool InternalFileHierarchyStorage::updateFile(const DirectoryStorage::EntryIndex return true; } +void InternalFileHierarchyStorage::deleteNode(uint32_t index) +{ + if(mNodes[index] != NULL) + { + delete mNodes[index] ; + mFreeNodes.push_back(index) ; + mNodes[index] = NULL ; + } +} + DirectoryStorage::EntryIndex InternalFileHierarchyStorage::allocateNewIndex() { - int found = -1; - for(uint32_t j=0;j& subdirs_hash,const std::vector& subfiles_array) @@ -534,8 +539,7 @@ bool InternalFileHierarchyStorage::updateDirEntry(const DirectoryStorage::EntryI std::cerr << "(EE) Cannot delete node of index " << it->second << " because it is not a file. Inconsistency error!" << std::endl; continue ; } - delete mNodes[it->second] ; - mNodes[it->second] = NULL ; + deleteNode(it->second) ; } // now update row and parent index for all subnodes @@ -590,12 +594,12 @@ bool InternalFileHierarchyStorage::setTS(const DirectoryStorage::EntryIndex& ind // Do a complete recursive sweep over sub-directories and files, and update the lst modf TS. This could be also performed by a cleanup method. -time_t InternalFileHierarchyStorage::recursUpdateLastModfTime(const DirectoryStorage::EntryIndex& dir_index) +time_t InternalFileHierarchyStorage::recursUpdateLastModfTime(const DirectoryStorage::EntryIndex& dir_index,bool& unfinished_files_present) { DirEntry& d(*static_cast(mNodes[dir_index])) ; time_t largest_modf_time = d.dir_modtime ; - bool unfinished_files_present = false ; + unfinished_files_present = false ; for(uint32_t i=0;i(mNodes[parent_index])->subdirs[dir_tab_index]; } -bool InternalFileHierarchyStorage::searchHash(const RsFileHash& hash,std::list& results) +bool InternalFileHierarchyStorage::searchHash(const RsFileHash& hash,DirectoryStorage::EntryIndex& result) { - DirectoryStorage::EntryIndex indx ; - - if(getIndexFromFileHash(hash,indx)) - { - results.clear(); - results.push_back(indx) ; - return true ; - } - else - return false; + return getIndexFromFileHash(hash,result); } class DirectoryStorageExprFileEntry: public RsRegularExpression::ExpFileEntry @@ -749,6 +749,8 @@ bool InternalFileHierarchyStorage::check(std::string& error_string) // checks co std::vector hits(mNodes.size(),0) ; // count hits of children. Should be 1 for all in the end. Otherwise there's an error. hits[0] = 1 ; // because 0 is never the child of anyone + mFreeNodes.clear(); + for(uint32_t i=0;itype() == FileStorageNode::TYPE_DIR) { @@ -796,13 +798,15 @@ bool InternalFileHierarchyStorage::check(std::string& error_string) // checks co } } } + else if(mNodes[i] == NULL) + mFreeNodes.push_back(i) ; for(uint32_t i=0;i mFreeNodes ; // keeps a list of free nodes in order to make insert effcieint std::vector mNodes;// uses pointers to keep information about valid/invalid objects. void compress() ; // use empty space in the vector, mostly due to deleted entries. This is a complicated operation, mostly due to @@ -142,7 +143,7 @@ public: // search. SearchHash is logarithmic. The other two are linear. - bool searchHash(const RsFileHash& hash,std::list& results); + bool searchHash(const RsFileHash& hash, DirectoryStorage::EntryIndex &result); int searchBoolExp(RsRegularExpression::Expression * exp, std::list &results) const ; int searchTerms(const std::list& terms, std::list &results) const ; // does a logical OR between items of the list of terms @@ -159,6 +160,10 @@ private: DirectoryStorage::EntryIndex allocateNewIndex(); + // Deletes an existing entry in mNodes, and keeps record of the indices that get freed. + + void deleteNode(DirectoryStorage::EntryIndex); + // Removes the given subdirectory from the parent node and all its pendign subdirs. Files are kept, and will go during the cleaning // phase. That allows to keep file information when moving them around. diff --git a/src/file_sharing/directory_storage.cc b/src/file_sharing/directory_storage.cc index 983846d9d..9c47b4c90 100644 --- a/src/file_sharing/directory_storage.cc +++ b/src/file_sharing/directory_storage.cc @@ -168,12 +168,6 @@ bool DirectoryStorage::updateHash(const EntryIndex& index,const RsFileHash& hash return mFileHierarchy->updateHash(index,hash); } -int DirectoryStorage::searchHash(const RsFileHash& hash, std::list &results) const -{ - RS_STACK_MUTEX(mDirStorageMtx) ; - return mFileHierarchy->searchHash(hash,results); -} - bool DirectoryStorage::load(const std::string& local_file_name) { RS_STACK_MUTEX(mDirStorageMtx) ; @@ -295,6 +289,36 @@ bool DirectoryStorage::getIndexFromDirHash(const RsFileHash& hash,EntryIndex& in /* Local Directory Storage */ /******************************************************************************************************************/ +RsFileHash LocalDirectoryStorage::makeEncryptedHash(const RsFileHash& hash) +{ + return RsDirUtil::sha1sum(hash.toByteArray(),hash.SIZE_IN_BYTES); +} +bool LocalDirectoryStorage::locked_findRealHash(const RsFileHash& hash, RsFileHash& real_hash) const +{ + std::map::const_iterator it = mEncryptedHashes.find(hash) ; + + if(it == mEncryptedHashes.end()) + return false ; + + real_hash = it->second ; + return true ; +} + +int LocalDirectoryStorage::searchHash(const RsFileHash& hash, RsFileHash& real_hash, EntryIndex& result) const +{ + RS_STACK_MUTEX(mDirStorageMtx) ; + + if(locked_findRealHash(hash,real_hash) && mFileHierarchy->searchHash(real_hash,result)) + return true ; + + if(mFileHierarchy->searchHash(hash,result)) + { + real_hash.clear(); + return true ; + } + return false ; +} + void LocalDirectoryStorage::setSharedDirectoryList(const std::list& lst) { RS_STACK_MUTEX(mDirStorageMtx) ; @@ -422,11 +446,13 @@ void LocalDirectoryStorage::updateTimeStamps() std::cerr << "Updating recursive TS for local shared dirs..." << std::endl; #endif - time_t last_modf_time = mFileHierarchy->recursUpdateLastModfTime(EntryIndex(0)) ; + bool unfinished_files_below ; + + time_t last_modf_time = mFileHierarchy->recursUpdateLastModfTime(EntryIndex(0),unfinished_files_below) ; mTSChanged = false ; #ifdef DEBUG_LOCAL_DIRECTORY_STORAGE - std::cerr << "LocalDirectoryStorage: global last modf time is " << last_modf_time << " (which is " << time(NULL) - last_modf_time << " secs ago)" << std::endl; + std::cerr << "LocalDirectoryStorage: global last modf time is " << last_modf_time << " (which is " << time(NULL) - last_modf_time << " secs ago), unfinished files below=" << unfinished_files_below << std::endl; #else // remove unused variable warning // variable is only used for debugging @@ -434,7 +460,15 @@ void LocalDirectoryStorage::updateTimeStamps() #endif } } +bool LocalDirectoryStorage::updateHash(const EntryIndex& index,const RsFileHash& hash) +{ + { + RS_STACK_MUTEX(mDirStorageMtx) ; + mEncryptedHashes[makeEncryptedHash(hash)] = hash ; + } + return mFileHierarchy->updateHash(index,hash); +} std::string LocalDirectoryStorage::locked_findRealRootFromVirtualFilename(const std::string& virtual_rootdir) const { /**** MUST ALREADY BE LOCKED ****/ @@ -724,7 +758,9 @@ RemoteDirectoryStorage::RemoteDirectoryStorage(const RsPeerId& pid,const std::st { load(fname) ; - std::cerr << "Loaded remote directory for peer " << pid << std::endl; + mLastSweepTime = time(NULL) - (RSRandom::random_u32() % DELAY_BETWEEN_REMOTE_DIRECTORIES_SWEEP) ; + + std::cerr << "Loaded remote directory for peer " << pid << ", inited last sweep time to " << time(NULL) - mLastSweepTime << " secs ago." << std::endl; #ifdef DEBUG_REMOTE_DIRECTORY_STORAGE mFileHierarchy->print(); #endif diff --git a/src/file_sharing/directory_storage.h b/src/file_sharing/directory_storage.h index 195573266..22282e6d3 100644 --- a/src/file_sharing/directory_storage.h +++ b/src/file_sharing/directory_storage.h @@ -53,7 +53,6 @@ class DirectoryStorage virtual int searchTerms(const std::list& terms, std::list &results) const ; virtual int searchBoolExp(RsRegularExpression::Expression * exp, std::list &results) const ; - virtual int searchHash(const RsFileHash& hash, std::list &results) const ; // gets/sets the various time stamps: // @@ -140,7 +139,9 @@ class DirectoryStorage // Updates relevant information for the file at the given index. bool updateFile(const EntryIndex& index,const RsFileHash& hash, const std::string& fname, uint64_t size, time_t modf_time) ; - bool updateHash(const EntryIndex& index,const RsFileHash& hash); + + // This is derived in LocalDirectoryStorage in order to also store H(H(F)) + virtual bool updateHash(const EntryIndex& index,const RsFileHash& hash); // Returns the hash of the directory at the given index and reverse. This hash is set as random the first time it is used (when updating directories). It will be // used by the sync system to designate the directory without referring to index (index could be used to figure out the existance of hidden directories) @@ -193,8 +194,15 @@ public: */ void checkSave() ; + /*! + * \brief lastSweepTime + * returns the last time a sweep has been done over the directory in order to check update TS. + * \return + */ + time_t& lastSweepTime() { return mLastSweepTime ; } private: time_t mLastSavedTime ; + time_t mLastSweepTime ; bool mChanged ; std::string mFileName; }; @@ -216,6 +224,20 @@ public: void updateShareFlags(const SharedDirInfo& info) ; bool convertSharedFilePath(const std::string& path_with_virtual_name,std::string& fullpath) ; + virtual bool updateHash(const EntryIndex& index,const RsFileHash& hash); + /*! + * \brief searchHash + * Looks into local database of shared files for the given hash. Also looks for files such that the hash of the hash + * matches the given hash, and returns the real hash. + * \param hash hash to look for + * \param real_hash hash such that H(real_hash) = hash, or null hash if not found. + * \param results Entry index of the file that is found + * \return + * true is a file is found + * false otherwise. + */ + virtual int searchHash(const RsFileHash& hash, RsFileHash &real_hash, EntryIndex &results) const ; + /*! * \brief updateTimeStamps * Checks recursive TS and update the if needed. @@ -261,6 +283,8 @@ public: bool serialiseDirEntry(const EntryIndex& indx, RsTlvBinaryData& bindata, const RsPeerId &client_id) ; private: + static RsFileHash makeEncryptedHash(const RsFileHash& hash); + bool locked_findRealHash(const RsFileHash& hash, RsFileHash& real_hash) const; std::string locked_getVirtualPath(EntryIndex indx) const ; std::string locked_getVirtualDirName(EntryIndex indx) const ; @@ -268,6 +292,7 @@ private: std::string locked_findRealRootFromVirtualFilename(const std::string& virtual_rootdir) const; std::map mLocalDirs ; // map is better for search. it->first=it->second.filename + std::map mEncryptedHashes; // map such that hash(it->second) = it->first std::string mFileName; bool mTSChanged ; diff --git a/src/file_sharing/directory_updater.cc b/src/file_sharing/directory_updater.cc index de92c6ee1..331e51822 100644 --- a/src/file_sharing/directory_updater.cc +++ b/src/file_sharing/directory_updater.cc @@ -54,10 +54,10 @@ void LocalDirectoryUpdater::setEnabled(bool b) if(mIsEnabled == b) return ; - if(b) - start("fs dir updater") ; - else + if(!b) shutdown(); + else if(!isRunning()) + start("fs dir updater") ; mIsEnabled = b ; } diff --git a/src/file_sharing/file_sharing_defaults.h b/src/file_sharing/file_sharing_defaults.h index 520fc61ea..b2b64afc9 100644 --- a/src/file_sharing/file_sharing_defaults.h +++ b/src/file_sharing/file_sharing_defaults.h @@ -28,7 +28,8 @@ static const uint32_t DELAY_BETWEEN_DIRECTORY_UPDATES = 600 ; // 10 minutes static const uint32_t DELAY_BETWEEN_REMOTE_DIRECTORY_SYNC_REQ = 120 ; // 2 minutes -static const uint32_t DELAY_BETWEEN_LOCAL_DIRECTORIES_TS_UPDATE = 20 ; // 20 sec. Buy we only update for real if something has changed. +static const uint32_t DELAY_BETWEEN_LOCAL_DIRECTORIES_TS_UPDATE = 20 ; // 20 sec. But we only update for real if something has changed. +static const uint32_t DELAY_BETWEEN_REMOTE_DIRECTORIES_SWEEP = 60 ; // 60 sec. static const std::string HASH_CACHE_DURATION_SS = "HASH_CACHE_DURATION" ; // key string to store hash remembering time static const std::string WATCH_FILE_DURATION_SS = "WATCH_FILES_DELAY" ; // key to store delay before re-checking for new files @@ -43,3 +44,8 @@ static const uint32_t MIN_INTERVAL_BETWEEN_REMOTE_DIRECTORY_SAVE = 23 ; // static const uint32_t MAX_DIR_SYNC_RESPONSE_DATA_SIZE = 20000 ; // Maximum RsItem data size in bytes for serialised directory transmission static const uint32_t DEFAULT_HASH_STORAGE_DURATION_DAYS = 30 ; // remember deleted/inaccessible files for 30 days + +static const uint32_t NB_FRIEND_INDEX_BITS = 10 ; // Do not change this! +static const uint32_t NB_ENTRY_INDEX_BITS = 22 ; // Do not change this! +static const uint32_t ENTRY_INDEX_BIT_MASK = 0x003fffff ; // used for storing (EntryIndex,Friend) couples into a 32bits pointer. Depends on the two values just before. Dont change! +static const uint32_t DELAY_BEFORE_DROP_REQUEST = 600; // every 10 min diff --git a/src/file_sharing/p3filelists.cc b/src/file_sharing/p3filelists.cc index 21875efad..3bbf5fb9a 100644 --- a/src/file_sharing/p3filelists.cc +++ b/src/file_sharing/p3filelists.cc @@ -46,11 +46,6 @@ static const uint32_t P3FILELISTS_UPDATE_FLAG_REMOTE_MAP_CHANGED = 0x0001 ; static const uint32_t P3FILELISTS_UPDATE_FLAG_LOCAL_DIRS_CHANGED = 0x0002 ; static const uint32_t P3FILELISTS_UPDATE_FLAG_REMOTE_DIRS_CHANGED = 0x0004 ; -static const uint32_t NB_FRIEND_INDEX_BITS = 10 ; -static const uint32_t NB_ENTRY_INDEX_BITS = 22 ; -static const uint32_t ENTRY_INDEX_BIT_MASK = 0x003fffff ; // used for storing (EntryIndex,Friend) couples into a 32bits pointer. -static const uint32_t DELAY_BEFORE_DROP_REQUEST = 55 ; // every 55 secs, for debugging. Should be evey 10 minutes or so. - p3FileDatabase::p3FileDatabase(p3ServiceControl *mpeers) : mServCtrl(mpeers), mFLSMtx("p3FileLists") { @@ -209,7 +204,7 @@ int p3FileDatabase::tick() for(uint32_t i=0;ipeerId()) != online_peers.end()) + if(online_peers.find(mRemoteDirectories[i]->peerId()) != online_peers.end() && mRemoteDirectories[i]->lastSweepTime() + DELAY_BETWEEN_REMOTE_DIRECTORIES_SWEEP < now) { #ifdef DEBUG_FILE_HIERARCHY P3FILELISTS_DEBUG() << "Launching recurs sweep of friend directory " << mRemoteDirectories[i]->peerId() << ". Content currently is:" << std::endl; @@ -217,6 +212,7 @@ int p3FileDatabase::tick() #endif locked_recursSweepRemoteDirectory(mRemoteDirectories[i],mRemoteDirectories[i]->root(),0) ; + mRemoteDirectories[i]->lastSweepTime() = now ; } mRemoteDirectories[i]->checkSave() ; @@ -345,7 +341,7 @@ bool p3FileDatabase::loadList(std::list& load) /* for each item, check it exists .... * - remove any that are dead (or flag?) */ - static const FileStorageFlags PERMISSION_MASK = DIR_FLAGS_BROWSABLE_OTHERS | DIR_FLAGS_NETWORK_WIDE_OTHERS | DIR_FLAGS_BROWSABLE_GROUPS | DIR_FLAGS_NETWORK_WIDE_GROUPS ; + static const FileStorageFlags PERMISSION_MASK = DIR_FLAGS_PERMISSIONS_MASK; #ifdef DEBUG_FILE_HIERARCHY P3FILELISTS_DEBUG() << "Load list" << std::endl; @@ -400,7 +396,6 @@ bool p3FileDatabase::loadList(std::list& load) info.virtualname = fi->file.name; info.shareflags = FileStorageFlags(fi->flags) ; info.shareflags &= PERMISSION_MASK ; - info.shareflags &= ~DIR_FLAGS_NETWORK_WIDE_GROUPS ; // disabling this flag for know, for consistency reasons for(std::set::const_iterator itt(fi->parent_groups.ids.begin());itt!=fi->parent_groups.ids.end();++itt) info.parent_groups.push_back(*itt) ; @@ -498,7 +493,6 @@ void p3FileDatabase::cleanup() #ifdef DEBUG_P3FILELISTS P3FILELISTS_DEBUG() << " removing pending request " << std::hex << it->first << std::dec << " for peer " << it->second.peer_id << ", because peer is offline or request is too old." << std::endl; #endif - std::map::iterator tmp(it); ++tmp; mPendingSyncRequests.erase(it) ; @@ -543,7 +537,7 @@ uint32_t p3FileDatabase::locked_getFriendIndex(const RsPeerId& pid) mUpdateFlags |= P3FILELISTS_UPDATE_FLAG_REMOTE_MAP_CHANGED ; #ifdef DEBUG_P3FILELISTS - P3FILELISTS_DEBUG() << " adding missing remote dir entry for friend " << *it << ", with index " << friend_index << std::endl; + P3FILELISTS_DEBUG() << " adding missing remote dir entry for friend " << pid << ", with index " << it->second << std::endl; #endif } @@ -570,7 +564,7 @@ uint32_t p3FileDatabase::locked_getFriendIndex(const RsPeerId& pid) mUpdateFlags |= P3FILELISTS_UPDATE_FLAG_REMOTE_MAP_CHANGED ; #ifdef DEBUG_P3FILELISTS - P3FILELISTS_DEBUG() << " adding missing remote dir entry for friend " << *it << ", with index " << friend_index << std::endl; + P3FILELISTS_DEBUG() << " adding missing remote dir entry for friend " << pid << ", with index " << it->second << std::endl; #endif } @@ -644,26 +638,25 @@ void p3FileDatabase::requestDirUpdate(void *ref) bool p3FileDatabase::findChildPointer( void *ref, int row, void *& result, FileSearchFlags flags ) const { - RS_STACK_MUTEX(mFLSMtx); + if (ref == NULL) + { + if(flags & RS_FILE_HINTS_LOCAL) + { + if(row != 0) + return false ; - result = NULL; + convertEntryIndexToPointer(0,0,result); - if (ref == NULL) - { - if(flags & RS_FILE_HINTS_LOCAL) - { - if(row != 0) return false; - - convertEntryIndexToPointer(0,0,result); - return true; - } - else if((uint32_t)row < mRemoteDirectories.size()) - { - convertEntryIndexToPointer(mRemoteDirectories[row]->root(), row+1, result); - return true; - } - else return false; - } + return true ; + } + else if((uint32_t)row < mRemoteDirectories.size()) + { + convertEntryIndexToPointer(mRemoteDirectories[row]->root(),row+1,result); + return true; + } + else + return false; + } uint32_t fi; DirectoryStorage::EntryIndex e ; @@ -999,16 +992,20 @@ bool p3FileDatabase::search(const RsFileHash &hash, FileSearchFlags hintflags, F if(hintflags & RS_FILE_HINTS_LOCAL) { - std::list res; - mLocalSharedDirs->searchHash(hash,res) ; + RsFileHash real_hash ; + EntryIndex indx; - if(res.empty()) + if(!mLocalSharedDirs->searchHash(hash,real_hash,indx)) return false; - EntryIndex indx = *res.begin() ; // no need to report duplicates - mLocalSharedDirs->getFileInfo(indx,info) ; + if(!real_hash.isNull()) + { + info.hash = real_hash ; + info.transfer_info_flags |= RS_FILE_REQ_ENCRYPTED ; + } + return true; } @@ -1457,25 +1454,23 @@ void p3FileDatabase::locked_recursSweepRemoteDirectory(RemoteDirectoryStorage *r p3FileDatabase::DirSyncRequestId p3FileDatabase::makeDirSyncReqId(const RsPeerId& peer_id,const RsFileHash& hash) { static uint64_t random_bias = RSRandom::random_u64(); - uint64_t r = 0 ; + + uint8_t mem[RsPeerId::SIZE_IN_BYTES + RsFileHash::SIZE_IN_BYTES]; + memcpy(mem,peer_id.toByteArray(),RsPeerId::SIZE_IN_BYTES) ; + memcpy(&mem[RsPeerId::SIZE_IN_BYTES],hash.toByteArray(),RsFileHash::SIZE_IN_BYTES) ; + + RsFileHash tmp = RsDirUtil::sha1sum(mem,RsPeerId::SIZE_IN_BYTES + RsFileHash::SIZE_IN_BYTES) ; // This is kind of arbitrary. The important thing is that the same ID needs to be generated every time for a given (peer_id,entry index) pair, in a way // that cannot be brute-forced or reverse-engineered, which explains the random bias and the usage of the hash, that is itself random. - for(uint32_t i=0;iflags; #ifdef DEBUG_P3FILELISTS - P3FILELISTS_DEBUG() << " Pushing req in pending list with peer id " << data.peer_id << std::endl; + P3FILELISTS_DEBUG() << " Pushing req " << std::hex << sync_req_id << std::dec << " in pending list with peer id " << data.peer_id << std::endl; #endif mPendingSyncRequests[sync_req_id] = data ; diff --git a/src/ft/ftcontroller.cc b/src/ft/ftcontroller.cc index 821bd1ea0..fdd7ab119 100644 --- a/src/ft/ftcontroller.cc +++ b/src/ft/ftcontroller.cc @@ -94,7 +94,7 @@ ftFileControl::ftFileControl(std::string fname, mTransfer(tm), mCreator(fc), mState(DOWNLOADING), mHash(hash), mSize(size), mFlags(flags), mCreateTime(0), mQueuePriority(0), mQueuePosition(0) { - return; + return; } ftController::ftController(ftDataMultiplex *dm, p3ServiceControl *sc, uint32_t ftServiceId) @@ -113,7 +113,8 @@ ftController::ftController(ftDataMultiplex *dm, p3ServiceControl *sc, uint32_t f { _max_active_downloads = 5 ; // default queue size _min_prioritized_transfers = 3 ; - /* TODO */ + mDefaultEncryptionPolicy = RS_FILE_CTRL_ENCRYPTION_POLICY_PERMISSIVE; + /* TODO */ cnt = 0 ; } @@ -580,7 +581,7 @@ void ftController::locked_checkQueueElement(uint32_t pos) _queue[pos]->mState = ftFileControl::DOWNLOADING ; if(_queue[pos]->mFlags & RS_FILE_REQ_ANONYMOUS_ROUTING) - mTurtle->monitorTunnels(_queue[pos]->mHash,mFtServer,true) ; + mFtServer->activateTunnels(_queue[pos]->mHash,mDefaultEncryptionPolicy,_queue[pos]->mFlags,true); } if(pos >= _max_active_downloads && _queue[pos]->mState != ftFileControl::QUEUED && _queue[pos]->mState != ftFileControl::PAUSED) @@ -589,8 +590,8 @@ void ftController::locked_checkQueueElement(uint32_t pos) _queue[pos]->mCreator->closeFile() ; if(_queue[pos]->mFlags & RS_FILE_REQ_ANONYMOUS_ROUTING) - mTurtle->stopMonitoringTunnels(_queue[pos]->mHash) ; - } + mFtServer->activateTunnels(_queue[pos]->mHash,mDefaultEncryptionPolicy,_queue[pos]->mFlags,false); + } } bool ftController::FlagFileComplete(const RsFileHash& hash) @@ -833,7 +834,7 @@ bool ftController::completeFile(const RsFileHash& hash) mDownloads.erase(it); if(flags & RS_FILE_REQ_ANONYMOUS_ROUTING) - mTurtle->stopMonitoringTunnels(hash_to_suppress) ; + mFtServer->activateTunnels(hash_to_suppress,mDefaultEncryptionPolicy,flags,false); } // UNLOCK: RS_STACK_MUTEX(ctrlMutex); @@ -976,6 +977,21 @@ bool ftController::FileRequest(const std::string& fname, const RsFileHash& hash if(alreadyHaveFile(hash, info)) return false ; + // the strategy for requesting encryption is the following: + // + // if policy is STRICT + // - disable clear, enforce encryption + // else + // - if not specified, use clear + // + if(mDefaultEncryptionPolicy == RS_FILE_CTRL_ENCRYPTION_POLICY_STRICT) + { + flags |= RS_FILE_REQ_ENCRYPTED ; + flags &= ~RS_FILE_REQ_UNENCRYPTED ; + } + else if(!(flags & ( RS_FILE_REQ_ENCRYPTED | RS_FILE_REQ_UNENCRYPTED ))) + flags |= RS_FILE_REQ_UNENCRYPTED ; + if(size == 0) // we treat this special case because { /* if no destpath - send to download directory */ @@ -1172,7 +1188,7 @@ bool ftController::FileRequest(const std::string& fname, const RsFileHash& hash // We check that flags are consistent. if(flags & RS_FILE_REQ_ANONYMOUS_ROUTING) - mTurtle->monitorTunnels(hash,mFtServer,true) ; + mFtServer->activateTunnels(hash,mDefaultEncryptionPolicy,flags,true); bool assume_availability = false; @@ -1273,7 +1289,7 @@ bool ftController::setChunkStrategy(const RsFileHash& hash,FileChunksInfo::Chunk bool ftController::FileCancel(const RsFileHash& hash) { - rsTurtle->stopMonitoringTunnels(hash) ; + mFtServer->activateTunnels(hash,mDefaultEncryptionPolicy,TransferRequestFlags(0),false); #ifdef CONTROL_DEBUG std::cerr << "ftController::FileCancel" << std::endl; @@ -1597,7 +1613,7 @@ bool ftController::FileDetails(const RsFileHash &hash, FileInfo &info) info.queue_position = it->second->mQueuePosition ; if(it->second->mFlags & RS_FILE_REQ_ANONYMOUS_ROUTING) - info.storage_permission_flags |= DIR_FLAGS_NETWORK_WIDE_OTHERS ; // file being downloaded anonymously are always anonymously available. + info.storage_permission_flags |= DIR_FLAGS_ANONYMOUS_DOWNLOAD ; // file being downloaded anonymously are always anonymously available. /* get list of sources from transferModule */ std::list peerIds; @@ -1811,6 +1827,7 @@ const std::string download_dir_ss("DOWN_DIR"); const std::string partial_dir_ss("PART_DIR"); const std::string default_chunk_strategy_ss("DEFAULT_CHUNK_STRATEGY"); const std::string free_space_limit_ss("FREE_SPACE_LIMIT"); +const std::string default_encryption_policy_ss("DEFAULT_ENCRYPTION_POLICY"); /* p3Config Interface */ @@ -1858,6 +1875,8 @@ bool ftController::saveList(bool &cleanup, std::list& saveData) break ; } + configMap[default_encryption_policy_ss] = (mDefaultEncryptionPolicy==RS_FILE_CTRL_ENCRYPTION_POLICY_PERMISSIVE)?"PERMISSIVE":"STRICT" ; + rs_sprintf(s, "%lu", RsDiscSpace::freeSpaceLimit()); configMap[free_space_limit_ss] = s ; @@ -2100,7 +2119,26 @@ bool ftController::loadConfigMap(std::map &configMap) setPartialsDirectory(mit->second); } - if (configMap.end() != (mit = configMap.find(default_chunk_strategy_ss))) + if (configMap.end() != (mit = configMap.find(default_encryption_policy_ss))) + { + if(mit->second == "STRICT") + { + mDefaultEncryptionPolicy = RS_FILE_CTRL_ENCRYPTION_POLICY_STRICT ; + std::cerr << "Note: loading default value for encryption policy: STRICT" << std::endl; + } + else if(mit->second == "PERMISSIVE") + { + mDefaultEncryptionPolicy = RS_FILE_CTRL_ENCRYPTION_POLICY_PERMISSIVE ; + std::cerr << "Note: loading default value for encryption policy: PERMISSIVE" << std::endl; + } + else + { + std::cerr << "(EE) encryption policy not recognized: \"" << mit->second << "\"" << std::endl; + mDefaultEncryptionPolicy = RS_FILE_CTRL_ENCRYPTION_POLICY_PERMISSIVE ; + } + } + + if (configMap.end() != (mit = configMap.find(default_chunk_strategy_ss))) { if(mit->second == "STREAMING") { @@ -2133,7 +2171,18 @@ bool ftController::loadConfigMap(std::map &configMap) return true; } -void ftController::setFreeDiskSpaceLimit(uint32_t size_in_mb) +void ftController::setDefaultEncryptionPolicy(uint32_t p) +{ + RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ + mDefaultEncryptionPolicy = p ; + IndicateConfigChanged(); +} +uint32_t ftController::defaultEncryptionPolicy() +{ + RsStackMutex stack(ctrlMutex); /******* LOCKED ********/ + return mDefaultEncryptionPolicy ; +} +void ftController::setFreeDiskSpaceLimit(uint32_t size_in_mb) { RsDiscSpace::setFreeSpaceLimit(size_in_mb) ; diff --git a/src/ft/ftcontroller.h b/src/ft/ftcontroller.h index 516b07050..c1ea26d0a 100644 --- a/src/ft/ftcontroller.h +++ b/src/ft/ftcontroller.h @@ -140,9 +140,11 @@ class ftController: public RsTickingThread, public pqiServiceMonitor, public p3C bool setChunkStrategy(const RsFileHash& hash,FileChunksInfo::ChunkStrategy s); void setDefaultChunkStrategy(FileChunksInfo::ChunkStrategy s); - FileChunksInfo::ChunkStrategy defaultChunkStrategy(); + void setDefaultEncryptionPolicy(uint32_t s); + FileChunksInfo::ChunkStrategy defaultChunkStrategy(); uint32_t freeDiskSpaceLimit() const ; void setFreeDiskSpaceLimit(uint32_t size_in_mb) ; + uint32_t defaultEncryptionPolicy(); bool FileCancel(const RsFileHash& hash); bool FileControl(const RsFileHash& hash, uint32_t flags); @@ -237,6 +239,7 @@ class ftController: public RsTickingThread, public pqiServiceMonitor, public p3C ftServer *mFtServer ; p3ServiceControl *mServiceCtrl; uint32_t mFtServiceId; + uint32_t mDefaultEncryptionPolicy ; uint32_t cnt ; RsMutex ctrlMutex; diff --git a/src/ft/ftextralist.cc b/src/ft/ftextralist.cc index 094e07c8d..84ba0692b 100644 --- a/src/ft/ftextralist.cc +++ b/src/ft/ftextralist.cc @@ -350,9 +350,10 @@ bool ftExtraList::search(const RsFileHash &hash, FileSearchFlags /*hintflags* // Now setup the file storage flags so that the client can know how to handle permissions // - info.storage_permission_flags = DIR_FLAGS_BROWSABLE_OTHERS ; +#warning make sure this is right + info.storage_permission_flags = FileStorageFlags(0) ;//DIR_FLAGS_BROWSABLE_OTHERS ; - if(info.transfer_info_flags & RS_FILE_REQ_ANONYMOUS_ROUTING) info.storage_permission_flags |= DIR_FLAGS_NETWORK_WIDE_OTHERS ; + if(info.transfer_info_flags & RS_FILE_REQ_ANONYMOUS_ROUTING) info.storage_permission_flags |= DIR_FLAGS_ANONYMOUS_DOWNLOAD ; return true; } diff --git a/src/ft/ftserver.cc b/src/ft/ftserver.cc index f259b388f..49644ba68 100644 --- a/src/ft/ftserver.cc +++ b/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; @@ -55,15 +57,18 @@ const int ftserverzone = 29539; * #define SERVER_DEBUG_CACHE 1 ***/ +#define FTSERVER_DEBUG() std::cerr << time(NULL) << " : FILE_SERVER : " << __FUNCTION__ << " : " +#define FTSERVER_ERROR() std::cerr << "(EE) FILE_SERVER ERROR : " + static const time_t FILE_TRANSFER_LOW_PRIORITY_TASKS_PERIOD = 5 ; // low priority tasks handling every 5 seconds - /* Setup */ +/* Setup */ ftServer::ftServer(p3PeerMgr *pm, p3ServiceControl *sc) - : p3Service(), - mPeerMgr(pm), mServiceCtrl(sc), - mFileDatabase(NULL), - mFtController(NULL), mFtExtra(NULL), - mFtDataplex(NULL), mFtSearch(NULL), srvMutex("ftServer") + : p3Service(), + mPeerMgr(pm), mServiceCtrl(sc), + mFileDatabase(NULL), + mFtController(NULL), mFtExtra(NULL), + mFtDataplex(NULL), mFtSearch(NULL), srvMutex("ftServer") { addSerialType(new RsFileTransferSerialiser()) ; } @@ -76,12 +81,12 @@ const uint16_t FILE_TRANSFER_MIN_MINOR_VERSION = 0; RsServiceInfo ftServer::getServiceInfo() { - return RsServiceInfo(RS_SERVICE_TYPE_FILE_TRANSFER, - FILE_TRANSFER_APP_NAME, - FILE_TRANSFER_APP_MAJOR_VERSION, - FILE_TRANSFER_APP_MINOR_VERSION, - FILE_TRANSFER_MIN_MAJOR_VERSION, - FILE_TRANSFER_MIN_MINOR_VERSION); + return RsServiceInfo(RS_SERVICE_TYPE_FILE_TRANSFER, + FILE_TRANSFER_APP_NAME, + FILE_TRANSFER_APP_MAJOR_VERSION, + FILE_TRANSFER_APP_MINOR_VERSION, + FILE_TRANSFER_MIN_MAJOR_VERSION, + FILE_TRANSFER_MIN_MINOR_VERSION); } @@ -102,9 +107,9 @@ void ftServer::setConfigDirectory(std::string path) RsDirUtil::checkCreateDirectory(remotecachedir) ; } - /* Control Interface */ +/* Control Interface */ - /* add Config Items (Extra, Controller) */ +/* add Config Items (Extra, Controller) */ void ftServer::addConfigComponents(p3ConfigMgr */*mgr*/) { /* NOT SURE ABOUT THIS ONE */ @@ -120,7 +125,7 @@ const RsPeerId& ftServer::OwnId() return null_id ; } - /* Final Setup (once everything is assigned) */ +/* Final Setup (once everything is assigned) */ void ftServer::SetupFtServer() { @@ -137,7 +142,7 @@ void ftServer::SetupFtServer() mFtDataplex = new ftDataMultiplex(ownId, this, mFtSearch); /* make Controller */ - mFtController = new ftController(mFtDataplex, mServiceCtrl, getServiceInfo().mServiceType); + mFtController = new ftController(mFtDataplex, mServiceCtrl, getServiceInfo().mServiceType); mFtController -> setFtSearchNExtra(mFtSearch, mFtExtra); std::string tmppath = "."; mFtController->setPartialsDirectory(tmppath); @@ -153,8 +158,8 @@ void ftServer::SetupFtServer() void ftServer::connectToFileDatabase(p3FileDatabase *fdb) { - mFileDatabase = fdb ; - mFtSearch->addSearchMode(fdb, RS_FILE_HINTS_LOCAL | RS_FILE_HINTS_REMOTE); + mFileDatabase = fdb ; + mFtSearch->addSearchMode(fdb, RS_FILE_HINTS_LOCAL | RS_FILE_HINTS_REMOTE); } void ftServer::connectToTurtleRouter(p3turtle *fts) { @@ -177,7 +182,7 @@ void ftServer::StartupThreads() /* startup Monitor Thread */ /* startup the FileMonitor (after cache load) */ /* start it up */ - mFileDatabase->startThreads(); + mFileDatabase->startThreads(); /* Controller thread */ mFtController->start("ft ctrl"); @@ -207,10 +212,10 @@ void ftServer::StopThreads() delete (mFtExtra); mFtExtra = NULL; - /* stop Monitor Thread */ - mFileDatabase->stopThreads(); - delete mFileDatabase; - mFileDatabase = NULL ; + /* stop Monitor Thread */ + mFileDatabase->stopThreads(); + delete mFileDatabase; + mFileDatabase = NULL ; } /***************************************************************/ @@ -230,17 +235,19 @@ bool ftServer::ResumeTransfers() bool ftServer::getFileData(const RsFileHash& hash, uint64_t offset, uint32_t& requested_size,uint8_t *data) { - return mFtDataplex->getFileData(hash, offset, requested_size,data); + return mFtDataplex->getFileData(hash, offset, requested_size,data); } bool ftServer::alreadyHaveFile(const RsFileHash& hash, FileInfo &info) { - return mFileDatabase->search(hash, RS_FILE_HINTS_LOCAL, info); + return mFileDatabase->search(hash, RS_FILE_HINTS_LOCAL, info); } bool ftServer::FileRequest(const std::string& fname, const RsFileHash& hash, uint64_t size, const std::string& dest, TransferRequestFlags flags, const std::list& srcIds) { - std::cerr << "Requesting " << fname << std::endl ; +#ifdef SERVER_DEBUG + FTSERVER_DEBUG() << "Requesting " << fname << std::endl ; +#endif if(!mFtController->FileRequest(fname, hash, size, dest, flags, srcIds)) return false ; @@ -248,6 +255,41 @@ bool ftServer::FileRequest(const std::string& fname, const RsFileHash& hash, uin return true ; } +bool ftServer::activateTunnels(const RsFileHash& hash,uint32_t encryption_policy,TransferRequestFlags flags,bool onoff) +{ + RsFileHash hash_of_hash ; + + encryptHash(hash,hash_of_hash) ; + mEncryptedHashes.insert(std::make_pair(hash_of_hash,hash)) ; + + if(onoff) + { +#ifdef SERVER_DEBUG + FTSERVER_DEBUG() << "Activating tunnels for hash " << hash << std::endl; +#endif + if(flags & RS_FILE_REQ_ENCRYPTED) + { +#ifdef SERVER_DEBUG + FTSERVER_DEBUG() << " flags require end-to-end encryption. Requesting hash of hash " << hash_of_hash << std::endl; +#endif + mTurtleRouter->monitorTunnels(hash_of_hash,this,true) ; + } + if((flags & RS_FILE_REQ_UNENCRYPTED) && (encryption_policy != RS_FILE_CTRL_ENCRYPTION_POLICY_STRICT)) + { +#ifdef SERVER_DEBUG + FTSERVER_DEBUG() << " flags require no end-to-end encryption. Requesting hash " << hash << std::endl; +#endif + mTurtleRouter->monitorTunnels(hash,this,true) ; + } + } + else + { + mTurtleRouter->stopMonitoringTunnels(hash_of_hash); + mTurtleRouter->stopMonitoringTunnels(hash); + } + return true ; +} + bool ftServer::setDestinationName(const RsFileHash& hash,const std::string& name) { return mFtController->setDestinationName(hash,name); @@ -268,11 +310,19 @@ void ftServer::setFreeDiskSpaceLimit(uint32_t s) { mFtController->setFreeDiskSpaceLimit(s) ; } -void ftServer::setDefaultChunkStrategy(FileChunksInfo::ChunkStrategy s) +void ftServer::setDefaultChunkStrategy(FileChunksInfo::ChunkStrategy s) { mFtController->setDefaultChunkStrategy(s) ; } -FileChunksInfo::ChunkStrategy ftServer::defaultChunkStrategy() +uint32_t ftServer::defaultEncryptionPolicy() +{ + return mFtController->defaultEncryptionPolicy() ; +} +void ftServer::setDefaultEncryptionPolicy(uint32_t s) +{ + mFtController->setDefaultEncryptionPolicy(s) ; +} +FileChunksInfo::ChunkStrategy ftServer::defaultChunkStrategy() { return mFtController->defaultChunkStrategy() ; } @@ -302,7 +352,7 @@ uint32_t ftServer::getQueueSize() { return mFtController->getQueueSize() ; } - /* Control of Downloads Priority. */ +/* Control of Downloads Priority. */ bool ftServer::changeQueuePosition(const RsFileHash& hash, QueueMove mv) { mFtController->moveInQueue(hash,mv) ; @@ -317,14 +367,14 @@ bool ftServer::getDownloadSpeed(const RsFileHash& hash, int & speed) { DwlSpeed _speed; int ret = mFtController->getPriority(hash, _speed); - if (ret) + if (ret) speed = _speed; return ret; } bool ftServer::clearDownload(const RsFileHash& /*hash*/) { - return true ; + return true ; } bool ftServer::FileDownloadChunksDetails(const RsFileHash& hash,FileChunksInfo& info) @@ -334,10 +384,10 @@ bool ftServer::FileDownloadChunksDetails(const RsFileHash& hash,FileChunksInfo& void ftServer::requestDirUpdate(void *ref) { - mFileDatabase->requestDirUpdate(ref) ; + mFileDatabase->requestDirUpdate(ref) ; } - /* Directory Handling */ +/* Directory Handling */ void ftServer::setDownloadDirectory(std::string path) { mFtController->setDownloadDirectory(path); @@ -364,12 +414,12 @@ std::string ftServer::getPartialsDirectory() bool ftServer::copyFile(const std::string& source, const std::string& dest) { - return mFtController->copyFile(source, dest); + return mFtController->copyFile(source, dest); } void ftServer::FileDownloads(std::list &hashs) { - mFtController->FileDownloads(hashs); + mFtController->FileDownloads(hashs); } bool ftServer::FileUploadChunksDetails(const RsFileHash& hash,const RsPeerId& peer_id,CompressedChunkMap& cmap) @@ -396,13 +446,13 @@ bool ftServer::FileDetails(const RsFileHash &hash, FileSearchFlags hintflags, Fi // file, we skip the call to fileDetails() for efficiency reasons. // FileInfo info2 ; - if(mFtController->FileDetails(hash, info2)) + if(mFtController->FileDetails(hash, info2)) info.fname = info2.fname ; return true ; } - if(hintflags & ~(RS_FILE_HINTS_UPLOAD | RS_FILE_HINTS_DOWNLOAD)) + if(hintflags & ~(RS_FILE_HINTS_UPLOAD | RS_FILE_HINTS_DOWNLOAD)) if(mFtSearch->search(hash, hintflags, info)) return true ; @@ -414,18 +464,18 @@ RsTurtleGenericTunnelItem *ftServer::deserialiseItem(void *data,uint32_t size) c uint32_t rstype = getRsItemId(data); #ifdef SERVER_DEBUG - std::cerr << "p3turtle: deserialising packet: " << std::endl ; + FTSERVER_DEBUG() << "p3turtle: deserialising packet: " << std::endl ; #endif - if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || (RS_SERVICE_TYPE_TURTLE != getRsItemService(rstype))) + if ((RS_PKT_VERSION_SERVICE != getRsItemVersion(rstype)) || (RS_SERVICE_TYPE_TURTLE != getRsItemService(rstype))) { - std::cerr << " Wrong type !!" << std::endl ; + FTSERVER_ERROR() << " Wrong type !!" << std::endl ; return NULL; /* wrong type */ } - try - { - switch(getRsItemSubType(rstype)) + try { + switch(getRsItemSubType(rstype)) + { case RS_TURTLE_SUBTYPE_FILE_REQUEST : return new RsTurtleFileRequestItem(data,size) ; case RS_TURTLE_SUBTYPE_FILE_DATA : return new RsTurtleFileDataItem(data,size) ; case RS_TURTLE_SUBTYPE_FILE_MAP_REQUEST : return new RsTurtleFileMapRequestItem(data,size) ; @@ -434,67 +484,149 @@ RsTurtleGenericTunnelItem *ftServer::deserialiseItem(void *data,uint32_t size) c case RS_TURTLE_SUBTYPE_CHUNK_CRC : return new RsTurtleChunkCrcItem(data,size) ; default: - return NULL ; + return NULL ; + } + } + catch(std::exception& e) + { + FTSERVER_ERROR() << "(EE) deserialisation error in " << __PRETTY_FUNCTION__ << ": " << e.what() << std::endl; + + return NULL ; } - } - catch(std::exception& e) - { - std::cerr << "(EE) deserialisation error in " << __PRETTY_FUNCTION__ << ": " << e.what() << std::endl; - - return NULL ; - } } -void ftServer::addVirtualPeer(const TurtleFileHash& hash,const TurtleVirtualPeerId& virtual_peer_id,RsTurtleGenericTunnelItem::Direction dir) +bool ftServer::isEncryptedSource(const RsPeerId& virtual_peer_id) { - if(dir == RsTurtleGenericTunnelItem::DIRECTION_SERVER) - mFtController->addFileSource(hash,virtual_peer_id) ; + RS_STACK_MUTEX(srvMutex) ; + + return mEncryptedPeerIds.find(virtual_peer_id) != mEncryptedPeerIds.end(); } -void ftServer::removeVirtualPeer(const TurtleFileHash& hash,const TurtleVirtualPeerId& virtual_peer_id) + +void ftServer::addVirtualPeer(const TurtleFileHash& hash,const TurtleVirtualPeerId& virtual_peer_id,RsTurtleGenericTunnelItem::Direction dir) { - mFtController->removeFileSource(hash,virtual_peer_id) ; +#ifdef SERVER_DEBUG + FTSERVER_DEBUG() << "adding virtual peer. Direction=" << dir << ", hash=" << hash << ", vpid=" << virtual_peer_id << std::endl; +#endif + RsFileHash real_hash ; + + { + if(findRealHash(hash,real_hash)) + { + RS_STACK_MUTEX(srvMutex) ; + mEncryptedPeerIds[virtual_peer_id] = hash ; + } + else + real_hash = hash; + } + + if(dir == RsTurtleGenericTunnelItem::DIRECTION_SERVER) + { +#ifdef SERVER_DEBUG + FTSERVER_DEBUG() << " direction is SERVER. Adding file source for end-to-end encrypted tunnel for real hash " << real_hash << ", virtual peer id = " << virtual_peer_id << std::endl; +#endif + mFtController->addFileSource(real_hash,virtual_peer_id) ; + } +} + +void ftServer::removeVirtualPeer(const TurtleFileHash& hash,const TurtleVirtualPeerId& virtual_peer_id) +{ + RsFileHash real_hash ; + if(findRealHash(hash,real_hash)) + mFtController->removeFileSource(real_hash,virtual_peer_id) ; + else + mFtController->removeFileSource(hash,virtual_peer_id) ; + + RS_STACK_MUTEX(srvMutex) ; + mEncryptedPeerIds.erase(virtual_peer_id) ; } bool ftServer::handleTunnelRequest(const RsFileHash& hash,const RsPeerId& peer_id) { - FileInfo info ; - bool res = FileDetails(hash, RS_FILE_HINTS_NETWORK_WIDE | RS_FILE_HINTS_LOCAL | RS_FILE_HINTS_EXTRA | RS_FILE_HINTS_SPEC_ONLY, info); + FileInfo info ; + RsFileHash real_hash ; + bool found = false ; - if( (!res) && FileDetails(hash,RS_FILE_HINTS_DOWNLOAD,info)) - { - // This file is currently being downloaded. Let's look if we already have a chunk or not. If not, no need to - // share the file! - - FileChunksInfo info2 ; - if(rsFiles->FileDownloadChunksDetails(hash, info2)) - for(uint32_t i=0;igetSharedDirectories(dirList); + mFileDatabase->getSharedDirectories(dirList); #ifdef SERVER_DEBUG for(it = dirList.begin(); it != dirList.end(); ++it) - { - std::cerr << "ftServer::removeSharedDirectory()"; - std::cerr << " existing: " << (*it).filename; - std::cerr << std::endl; - } + FTSERVER_DEBUG() << " existing: " << (*it).filename << std::endl; #endif for(it = dirList.begin();it!=dirList.end() && (*it).filename != dir;++it) ; if(it == dirList.end()) { - std::cerr << "(EE) ftServer::removeSharedDirectory(): Cannot Find Directory... Fail" << std::endl; + FTSERVER_ERROR() << "(EE) ftServer::removeSharedDirectory(): Cannot Find Directory... Fail" << std::endl; return false; } #ifdef SERVER_DEBUG - std::cerr << "ftServer::removeSharedDirectory()"; - std::cerr << " Updating Directories"; - std::cerr << std::endl; + FTSERVER_DEBUG() << " Updating Directories" << std::endl; #endif dirList.erase(it); - mFileDatabase->setSharedDirectories(dirList); + mFileDatabase->setSharedDirectories(dirList); return true; } @@ -684,7 +809,7 @@ void ftServer::setWatchPeriod(int minutes) { mFileDatabase->set bool ftServer::getShareDownloadDirectory() { std::list dirList; - mFileDatabase->getSharedDirectories(dirList); + mFileDatabase->getSharedDirectories(dirList); std::string dir = mFtController->getDownloadDirectory(); @@ -698,41 +823,76 @@ bool ftServer::getShareDownloadDirectory() bool ftServer::shareDownloadDirectory(bool share) { - if (share) - { + if (share) + { /* Share */ SharedDirInfo inf ; inf.filename = mFtController->getDownloadDirectory(); - inf.shareflags = DIR_FLAGS_NETWORK_WIDE_OTHERS ; + inf.shareflags = DIR_FLAGS_ANONYMOUS_DOWNLOAD ; return addSharedDirectory(inf); } - else - { - /* Unshare */ - std::string dir = mFtController->getDownloadDirectory(); - return removeSharedDirectory(dir); - } + else + { + /* Unshare */ + std::string dir = mFtController->getDownloadDirectory(); + return removeSharedDirectory(dir); + } } - /***************************************************************/ - /****************** End of RsFiles Interface *******************/ - /***************************************************************/ +/***************************************************************/ +/****************** End of RsFiles Interface *******************/ +/***************************************************************/ //bool ftServer::loadConfigMap(std::map &/*configMap*/) //{ // return true; //} - /***************************************************************/ - /********************** Data Flow **********************/ - /***************************************************************/ +/***************************************************************/ +/********************** Data Flow **********************/ +/***************************************************************/ - /* Client Send */ +bool ftServer::sendTurtleItem(const RsPeerId& peerId,const RsFileHash& hash,RsTurtleGenericTunnelItem *item) +{ + // we cannot look in the encrypted hash map, since the same hash--on this side of the FT--can be used with both + // encrypted and unencrypted peers ids. So the information comes from the virtual peer Id. + + RsFileHash encrypted_hash; + + if(findEncryptedHash(peerId,encrypted_hash)) + { + // we encrypt the item + +#ifdef SERVER_DEBUG + FTSERVER_DEBUG() << "Sending turtle item to peer ID " << peerId << " using encrypted tunnel." << std::endl; +#endif + + RsTurtleGenericDataItem *encrypted_item ; + + if(!encryptItem(item, hash, encrypted_item)) + return false ; + + delete item ; + + mTurtleRouter->sendTurtleData(peerId,encrypted_item) ; + } + else + { +#ifdef SERVER_DEBUG + FTSERVER_DEBUG() << "Sending turtle item to peer ID " << peerId << " using non uncrypted tunnel." << std::endl; +#endif + mTurtleRouter->sendTurtleData(peerId,item) ; + } + + return true ; +} + +/* Client Send */ bool ftServer::sendDataRequest(const RsPeerId& peerId, const RsFileHash& hash, uint64_t size, uint64_t offset, uint32_t chunksize) { #ifdef SERVER_DEBUG - std::cerr << "ftServer::sendDataRequest() to peer " << peerId << " for hash " << hash << ", offset=" << offset << ", chunk size="<< chunksize << std::endl; + FTSERVER_DEBUG() << "ftServer::sendDataRequest() to peer " << peerId << " for hash " << hash << ", offset=" << offset << ", chunk size="<< chunksize << std::endl; #endif if(mTurtleRouter->isTurtlePeer(peerId)) { @@ -741,10 +901,10 @@ bool ftServer::sendDataRequest(const RsPeerId& peerId, const RsFileHash& hash, u item->chunk_offset = offset ; item->chunk_size = chunksize ; - mTurtleRouter->sendTurtleData(peerId,item) ; + sendTurtleItem(peerId,hash,item) ; } else - { + { /* create a packet */ /* push to networking part */ RsFileTransferDataRequestItem *rfi = new RsFileTransferDataRequestItem(); @@ -769,12 +929,12 @@ bool ftServer::sendDataRequest(const RsPeerId& peerId, const RsFileHash& hash, u bool ftServer::sendChunkMapRequest(const RsPeerId& peerId,const RsFileHash& hash,bool is_client) { #ifdef SERVER_DEBUG - std::cerr << "ftServer::sendChunkMapRequest() to peer " << peerId << " for hash " << hash << std::endl; + FTSERVER_DEBUG() << "ftServer::sendChunkMapRequest() to peer " << peerId << " for hash " << hash << std::endl; #endif if(mTurtleRouter->isTurtlePeer(peerId)) { RsTurtleFileMapRequestItem *item = new RsTurtleFileMapRequestItem ; - mTurtleRouter->sendTurtleData(peerId,item) ; + sendTurtleItem(peerId,hash,item) ; } else { @@ -798,13 +958,13 @@ bool ftServer::sendChunkMapRequest(const RsPeerId& peerId,const RsFileHash& hash bool ftServer::sendChunkMap(const RsPeerId& peerId,const RsFileHash& hash,const CompressedChunkMap& map,bool is_client) { #ifdef SERVER_DEBUG - std::cerr << "ftServer::sendChunkMap() to peer " << peerId << " for hash " << hash << std::endl; + FTSERVER_DEBUG() << "ftServer::sendChunkMap() to peer " << peerId << " for hash " << hash << std::endl; #endif if(mTurtleRouter->isTurtlePeer(peerId)) { RsTurtleFileMapItem *item = new RsTurtleFileMapItem ; item->compressed_map = map ; - mTurtleRouter->sendTurtleData(peerId,item) ; + sendTurtleItem(peerId,hash,item) ; } else { @@ -829,14 +989,14 @@ bool ftServer::sendChunkMap(const RsPeerId& peerId,const RsFileHash& hash,const bool ftServer::sendSingleChunkCRCRequest(const RsPeerId& peerId,const RsFileHash& hash,uint32_t chunk_number) { #ifdef SERVER_DEBUG - std::cerr << "ftServer::sendSingleCRCRequest() to peer " << peerId << " for hash " << hash << ", chunk number=" << chunk_number << std::endl; + FTSERVER_DEBUG() << "ftServer::sendSingleCRCRequest() to peer " << peerId << " for hash " << hash << ", chunk number=" << chunk_number << std::endl; #endif if(mTurtleRouter->isTurtlePeer(peerId)) { RsTurtleChunkCrcRequestItem *item = new RsTurtleChunkCrcRequestItem; item->chunk_number = chunk_number ; - mTurtleRouter->sendTurtleData(peerId,item) ; + sendTurtleItem(peerId,hash,item) ; } else { @@ -860,7 +1020,7 @@ bool ftServer::sendSingleChunkCRCRequest(const RsPeerId& peerId,const RsFileHash bool ftServer::sendSingleChunkCRC(const RsPeerId& peerId,const RsFileHash& hash,uint32_t chunk_number,const Sha1CheckSum& crc) { #ifdef SERVER_DEBUG - std::cerr << "ftServer::sendSingleCRC() to peer " << peerId << " for hash " << hash << ", chunk number=" << chunk_number << std::endl; + FTSERVER_DEBUG() << "ftServer::sendSingleCRC() to peer " << peerId << " for hash " << hash << ", chunk number=" << chunk_number << std::endl; #endif if(mTurtleRouter->isTurtlePeer(peerId)) { @@ -868,7 +1028,7 @@ bool ftServer::sendSingleChunkCRC(const RsPeerId& peerId,const RsFileHash& hash, item->chunk_number = chunk_number ; item->check_sum = crc ; - mTurtleRouter->sendTurtleData(peerId,item) ; + sendTurtleItem(peerId,hash,item) ; } else { @@ -881,8 +1041,8 @@ bool ftServer::sendSingleChunkCRC(const RsPeerId& peerId,const RsFileHash& hash, /* file info */ rfi->hash = hash; /* ftr->hash; */ - rfi->check_sum = crc; - rfi->chunk_number = chunk_number; + rfi->check_sum = crc; + rfi->chunk_number = chunk_number; sendItem(rfi); } @@ -890,7 +1050,7 @@ bool ftServer::sendSingleChunkCRC(const RsPeerId& peerId,const RsFileHash& hash, return true ; } - /* Server Send */ +/* Server Send */ bool ftServer::sendData(const RsPeerId& peerId, const RsFileHash& hash, uint64_t size, uint64_t baseoffset, uint32_t chunksize, void *data) { /* create a packet */ @@ -900,12 +1060,7 @@ bool ftServer::sendData(const RsPeerId& peerId, const RsFileHash& hash, uint64_t uint32_t chunk; #ifdef SERVER_DEBUG - std::cerr << "ftServer::sendData() to " << peerId << std::endl; - std::cerr << "hash: " << hash; - std::cerr << " offset: " << baseoffset; - std::cerr << " chunk: " << chunksize; - std::cerr << " data: " << data; - std::cerr << std::endl; + FTSERVER_DEBUG() << "ftServer::sendData() to " << peerId << ", hash: " << hash << " offset: " << baseoffset << " chunk: " << chunksize << " data: " << data << std::endl; #endif while(tosend > 0) @@ -939,7 +1094,7 @@ bool ftServer::sendData(const RsPeerId& peerId, const RsFileHash& hash, uint64_t } memcpy(item->chunk_data,&(((uint8_t *) data)[offset]),chunk) ; - mTurtleRouter->sendTurtleData(peerId,item) ; + sendTurtleItem(peerId,hash,item) ; } else { @@ -965,12 +1120,7 @@ bool ftServer::sendData(const RsPeerId& peerId, const RsFileHash& hash, uint64_t /* print the data pointer */ #ifdef SERVER_DEBUG - std::cerr << "ftServer::sendData() Packet: " << std::endl; - std::cerr << " offset: " << rfd->fd.file_offset; - std::cerr << " chunk: " << chunk; - std::cerr << " len: " << rfd->fd.binData.bin_len; - std::cerr << " data: " << rfd->fd.binData.bin_data; - std::cerr << std::endl; + FTSERVER_DEBUG() << "ftServer::sendData() Packet: " << " offset: " << rfd->fd.file_offset << " chunk: " << chunk << " len: " << rfd->fd.binData.bin_len << " data: " << rfd->fd.binData.bin_data << std::endl; #endif } @@ -984,94 +1134,355 @@ 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 01 01 : encryption using AEAD, format 01 (authed with Poly1305 ), version 01 +// ae ad 02 01 : encryption using AEAD, format 02 (authed with HMAC Sha256), 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); +} + +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 ftServer::encryptItem(RsTurtleGenericTunnelItem *clear_item,const RsFileHash& hash,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 total_data_size = ENCRYPTED_FT_HEADER_SIZE + ENCRYPTED_FT_INITIALIZATION_VECTOR_SIZE + ENCRYPTED_FT_EDATA_SIZE + clear_item->serial_size() + ENCRYPTED_FT_AUTHENTICATION_TAG_SIZE ; + +#ifdef SERVER_DEBUG + FTSERVER_DEBUG() << " clear part size : " << clear_item->serial_size() << 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 = clear_item->serial_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); + clear_item->serialize(&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 ftServer::decryptItem(RsTurtleGenericDataItem *encrypted_item,const RsFileHash& hash,RsTurtleGenericTunnelItem *& 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 = deserialiseItem(&edata[clear_item_offset],edata_size) ; + + if(decrypted_item == NULL) + return false ; + + return true ; +} + +bool ftServer::encryptHash(const RsFileHash& hash, RsFileHash& hash_of_hash) +{ + hash_of_hash = RsDirUtil::sha1sum(hash.toByteArray(),hash.SIZE_IN_BYTES); + return true ; +} + +bool ftServer::findEncryptedHash(const RsPeerId& virtual_peer_id, RsFileHash& encrypted_hash) +{ + RS_STACK_MUTEX(srvMutex); + + std::map::const_iterator it = mEncryptedPeerIds.find(virtual_peer_id) ; + + if(it != mEncryptedPeerIds.end()) + { + encrypted_hash = it->second ; + return true ; + } + else + return false ; +} + +bool ftServer::findRealHash(const RsFileHash& hash, RsFileHash& real_hash) +{ + RS_STACK_MUTEX(srvMutex); + std::map::const_iterator it = mEncryptedHashes.find(hash) ; + + if(it != mEncryptedHashes.end()) + { + real_hash = it->second ; + return true ; + } + else + return false ; +} + // Dont delete the item. The client (p3turtle) is doing it after calling this. // void ftServer::receiveTurtleData(RsTurtleGenericTunnelItem *i, - const RsFileHash& hash, - const RsPeerId& virtual_peer_id, - RsTurtleGenericTunnelItem::Direction direction) + const RsFileHash& hash, + const RsPeerId& virtual_peer_id, + RsTurtleGenericTunnelItem::Direction direction) { + if(i->PacketSubType() == RS_TURTLE_SUBTYPE_GENERIC_DATA) + { +#ifdef SERVER_DEBUG + FTSERVER_DEBUG() << "Received encrypted data item. Trying to decrypt" << std::endl; +#endif + + RsFileHash real_hash ; + + if(!findRealHash(hash,real_hash)) + { + FTSERVER_ERROR() << "(EE) Cannot find real hash for encrypted data item with H(H(F))=" << hash << ". This is unexpected." << std::endl; + return ; + } + + RsTurtleGenericTunnelItem *decrypted_item ; + if(!decryptItem(dynamic_cast(i),real_hash,decrypted_item)) + { + FTSERVER_ERROR() << "(EE) decryption error." << std::endl; + return ; + } + + receiveTurtleData(decrypted_item, real_hash, virtual_peer_id,direction) ; + + delete decrypted_item ; + return ; + } + switch(i->PacketSubType()) { - case RS_TURTLE_SUBTYPE_FILE_REQUEST: - { - RsTurtleFileRequestItem *item = dynamic_cast(i) ; - if (item) - { + case RS_TURTLE_SUBTYPE_FILE_REQUEST: + { + RsTurtleFileRequestItem *item = dynamic_cast(i) ; + if (item) + { #ifdef SERVER_DEBUG - std::cerr << "ftServer::receiveTurtleData(): received file data request for " << hash << " from peer " << virtual_peer_id << std::endl; + FTSERVER_DEBUG() << "ftServer::receiveTurtleData(): received file data request for " << hash << " from peer " << virtual_peer_id << std::endl; #endif - getMultiplexer()->recvDataRequest(virtual_peer_id,hash,0,item->chunk_offset,item->chunk_size) ; - } - } - break ; + getMultiplexer()->recvDataRequest(virtual_peer_id,hash,0,item->chunk_offset,item->chunk_size) ; + } + } + break ; - case RS_TURTLE_SUBTYPE_FILE_DATA : - { - RsTurtleFileDataItem *item = dynamic_cast(i) ; - if (item) - { + case RS_TURTLE_SUBTYPE_FILE_DATA : + { + RsTurtleFileDataItem *item = dynamic_cast(i) ; + if (item) + { #ifdef SERVER_DEBUG - std::cerr << "ftServer::receiveTurtleData(): received file data for " << hash << " from peer " << virtual_peer_id << std::endl; + FTSERVER_DEBUG() << "ftServer::receiveTurtleData(): received file data for " << hash << " from peer " << virtual_peer_id << std::endl; #endif - getMultiplexer()->recvData(virtual_peer_id,hash,0,item->chunk_offset,item->chunk_size,item->chunk_data) ; + getMultiplexer()->recvData(virtual_peer_id,hash,0,item->chunk_offset,item->chunk_size,item->chunk_data) ; - item->chunk_data = NULL ; // this prevents deletion in the destructor of RsFileDataItem, because data will be deleted - // down _ft_server->getMultiplexer()->recvData()...in ftTransferModule::recvFileData - } - } - break ; + item->chunk_data = NULL ; // this prevents deletion in the destructor of RsFileDataItem, because data will be deleted + // down _ft_server->getMultiplexer()->recvData()...in ftTransferModule::recvFileData + } + } + break ; - case RS_TURTLE_SUBTYPE_FILE_MAP : - { - RsTurtleFileMapItem *item = dynamic_cast(i) ; - if (item) - { + case RS_TURTLE_SUBTYPE_FILE_MAP : + { + RsTurtleFileMapItem *item = dynamic_cast(i) ; + if (item) + { #ifdef SERVER_DEBUG - std::cerr << "ftServer::receiveTurtleData(): received chunk map for hash " << hash << " from peer " << virtual_peer_id << std::endl; + FTSERVER_DEBUG() << "ftServer::receiveTurtleData(): received chunk map for hash " << hash << " from peer " << virtual_peer_id << std::endl; #endif - getMultiplexer()->recvChunkMap(virtual_peer_id,hash,item->compressed_map,direction == RsTurtleGenericTunnelItem::DIRECTION_CLIENT) ; - } - } - break ; + getMultiplexer()->recvChunkMap(virtual_peer_id,hash,item->compressed_map,direction == RsTurtleGenericTunnelItem::DIRECTION_CLIENT) ; + } + } + break ; - case RS_TURTLE_SUBTYPE_FILE_MAP_REQUEST: - { - //RsTurtleFileMapRequestItem *item = dynamic_cast(i) ; + case RS_TURTLE_SUBTYPE_FILE_MAP_REQUEST: + { + //RsTurtleFileMapRequestItem *item = dynamic_cast(i) ; #ifdef SERVER_DEBUG - std::cerr << "ftServer::receiveTurtleData(): received chunkmap request for hash " << hash << " from peer " << virtual_peer_id << std::endl; + FTSERVER_DEBUG() << "ftServer::receiveTurtleData(): received chunkmap request for hash " << hash << " from peer " << virtual_peer_id << std::endl; #endif - getMultiplexer()->recvChunkMapRequest(virtual_peer_id,hash,direction == RsTurtleGenericTunnelItem::DIRECTION_CLIENT) ; - } - break ; + getMultiplexer()->recvChunkMapRequest(virtual_peer_id,hash,direction == RsTurtleGenericTunnelItem::DIRECTION_CLIENT) ; + } + break ; - case RS_TURTLE_SUBTYPE_CHUNK_CRC : - { - RsTurtleChunkCrcItem *item = dynamic_cast(i) ; - if (item) - { + case RS_TURTLE_SUBTYPE_CHUNK_CRC : + { + RsTurtleChunkCrcItem *item = dynamic_cast(i) ; + if (item) + { #ifdef SERVER_DEBUG - std::cerr << "ftServer::receiveTurtleData(): received single chunk CRC for hash " << hash << " from peer " << virtual_peer_id << std::endl; + FTSERVER_DEBUG() << "ftServer::receiveTurtleData(): received single chunk CRC for hash " << hash << " from peer " << virtual_peer_id << std::endl; #endif - getMultiplexer()->recvSingleChunkCRC(virtual_peer_id,hash,item->chunk_number,item->check_sum) ; - } - } - break ; + getMultiplexer()->recvSingleChunkCRC(virtual_peer_id,hash,item->chunk_number,item->check_sum) ; + } + } + break ; - case RS_TURTLE_SUBTYPE_CHUNK_CRC_REQUEST: - { - RsTurtleChunkCrcRequestItem *item = dynamic_cast(i) ; - if (item) - { + case RS_TURTLE_SUBTYPE_CHUNK_CRC_REQUEST: + { + RsTurtleChunkCrcRequestItem *item = dynamic_cast(i) ; + if (item) + { #ifdef SERVER_DEBUG - std::cerr << "ftServer::receiveTurtleData(): received single chunk CRC request for hash " << hash << " from peer " << virtual_peer_id << std::endl; + FTSERVER_DEBUG() << "ftServer::receiveTurtleData(): received single chunk CRC request for hash " << hash << " from peer " << virtual_peer_id << std::endl; #endif - getMultiplexer()->recvSingleChunkCRCRequest(virtual_peer_id,hash,item->chunk_number) ; - } - } - break ; - default: - std::cerr << "WARNING: Unknown packet type received: sub_id=" << reinterpret_cast(i->PacketSubType()) << ". Is somebody trying to poison you ?" << std::endl ; + getMultiplexer()->recvSingleChunkCRCRequest(virtual_peer_id,hash,item->chunk_number) ; + } + } + break ; + default: + FTSERVER_ERROR() << "WARNING: Unknown packet type received: sub_id=" << reinterpret_cast(i->PacketSubType()) << ". Is somebody trying to poison you ?" << std::endl ; } } @@ -1084,7 +1495,7 @@ int ftServer::tick() bool moreToTick = false ; if(handleIncoming()) - moreToTick = true; + moreToTick = true; static time_t last_law_priority_tasks_handling_time = 0 ; time_t now = time(NULL) ; @@ -1107,9 +1518,6 @@ int ftServer::handleIncoming() int nhandled = 0 ; RsItem *item = NULL ; -#ifdef SERVER_DEBUG - std::cerr << "ftServer::handleIncoming() " << std::endl; -#endif while(NULL != (item = recvItem())) { @@ -1117,87 +1525,87 @@ int ftServer::handleIncoming() switch(item->PacketSubType()) { - case RS_PKT_SUBTYPE_FT_DATA_REQUEST: - { - RsFileTransferDataRequestItem *f = dynamic_cast(item) ; - if (f) - { + case RS_PKT_SUBTYPE_FT_DATA_REQUEST: + { + RsFileTransferDataRequestItem *f = dynamic_cast(item) ; + if (f) + { #ifdef SERVER_DEBUG - std::cerr << "ftServer::handleIncoming: received data request for hash " << f->file.hash << ", offset=" << f->fileoffset << ", chunk size=" << f->chunksize << std::endl; + FTSERVER_DEBUG() << "ftServer::handleIncoming: received data request for hash " << f->file.hash << ", offset=" << f->fileoffset << ", chunk size=" << f->chunksize << std::endl; #endif - mFtDataplex->recvDataRequest(f->PeerId(), f->file.hash, f->file.filesize, f->fileoffset, f->chunksize); - } - } - break ; + mFtDataplex->recvDataRequest(f->PeerId(), f->file.hash, f->file.filesize, f->fileoffset, f->chunksize); + } + } + break ; - case RS_PKT_SUBTYPE_FT_DATA: - { - RsFileTransferDataItem *f = dynamic_cast(item) ; - if (f) - { + case RS_PKT_SUBTYPE_FT_DATA: + { + RsFileTransferDataItem *f = dynamic_cast(item) ; + if (f) + { #ifdef SERVER_DEBUG - std::cerr << "ftServer::handleIncoming: received data for hash " << f->fd.file.hash << ", offset=" << f->fd.file_offset << ", chunk size=" << f->fd.binData.bin_len << std::endl; + FTSERVER_DEBUG() << "ftServer::handleIncoming: received data for hash " << f->fd.file.hash << ", offset=" << f->fd.file_offset << ", chunk size=" << f->fd.binData.bin_len << std::endl; #endif - mFtDataplex->recvData(f->PeerId(), f->fd.file.hash, f->fd.file.filesize, f->fd.file_offset, f->fd.binData.bin_len, f->fd.binData.bin_data); + mFtDataplex->recvData(f->PeerId(), f->fd.file.hash, f->fd.file.filesize, f->fd.file_offset, f->fd.binData.bin_len, f->fd.binData.bin_data); - /* we've stolen the data part -> so blank before delete + /* we've stolen the data part -> so blank before delete */ - f->fd.binData.TlvShallowClear(); - } - } - break ; + f->fd.binData.TlvShallowClear(); + } + } + break ; - case RS_PKT_SUBTYPE_FT_CHUNK_MAP_REQUEST: - { - RsFileTransferChunkMapRequestItem *f = dynamic_cast(item) ; - if (f) - { + case RS_PKT_SUBTYPE_FT_CHUNK_MAP_REQUEST: + { + RsFileTransferChunkMapRequestItem *f = dynamic_cast(item) ; + if (f) + { #ifdef SERVER_DEBUG - std::cerr << "ftServer::handleIncoming: received chunkmap request for hash " << f->hash << ", client=" << f->is_client << std::endl; + FTSERVER_DEBUG() << "ftServer::handleIncoming: received chunkmap request for hash " << f->hash << ", client=" << f->is_client << std::endl; #endif - mFtDataplex->recvChunkMapRequest(f->PeerId(), f->hash,f->is_client) ; - } - } - break ; + mFtDataplex->recvChunkMapRequest(f->PeerId(), f->hash,f->is_client) ; + } + } + break ; - case RS_PKT_SUBTYPE_FT_CHUNK_MAP: - { - RsFileTransferChunkMapItem *f = dynamic_cast(item) ; - if (f) - { + case RS_PKT_SUBTYPE_FT_CHUNK_MAP: + { + RsFileTransferChunkMapItem *f = dynamic_cast(item) ; + if (f) + { #ifdef SERVER_DEBUG - std::cerr << "ftServer::handleIncoming: received chunkmap for hash " << f->hash << ", client=" << f->is_client << /*", map=" << f->compressed_map <<*/ std::endl; + FTSERVER_DEBUG() << "ftServer::handleIncoming: received chunkmap for hash " << f->hash << ", client=" << f->is_client << /*", map=" << f->compressed_map <<*/ std::endl; #endif - mFtDataplex->recvChunkMap(f->PeerId(), f->hash,f->compressed_map,f->is_client) ; - } - } - break ; + mFtDataplex->recvChunkMap(f->PeerId(), f->hash,f->compressed_map,f->is_client) ; + } + } + break ; - case RS_PKT_SUBTYPE_FT_CHUNK_CRC_REQUEST: - { - RsFileTransferSingleChunkCrcRequestItem *f = dynamic_cast(item) ; - if (f) - { + case RS_PKT_SUBTYPE_FT_CHUNK_CRC_REQUEST: + { + RsFileTransferSingleChunkCrcRequestItem *f = dynamic_cast(item) ; + if (f) + { #ifdef SERVER_DEBUG - std::cerr << "ftServer::handleIncoming: received single chunk crc req for hash " << f->hash << ", chunk number=" << f->chunk_number << std::endl; + FTSERVER_DEBUG() << "ftServer::handleIncoming: received single chunk crc req for hash " << f->hash << ", chunk number=" << f->chunk_number << std::endl; #endif - mFtDataplex->recvSingleChunkCRCRequest(f->PeerId(), f->hash,f->chunk_number) ; - } - } - break ; + mFtDataplex->recvSingleChunkCRCRequest(f->PeerId(), f->hash,f->chunk_number) ; + } + } + break ; - case RS_PKT_SUBTYPE_FT_CHUNK_CRC: - { - RsFileTransferSingleChunkCrcItem *f = dynamic_cast(item) ; - if (f) - { + case RS_PKT_SUBTYPE_FT_CHUNK_CRC: + { + RsFileTransferSingleChunkCrcItem *f = dynamic_cast(item) ; + if (f) + { #ifdef SERVER_DEBUG - std::cerr << "ftServer::handleIncoming: received single chunk crc req for hash " << f->hash << ", chunk number=" << f->chunk_number << ", checksum = " << f->check_sum << std::endl; + FTSERVER_DEBUG() << "ftServer::handleIncoming: received single chunk crc req for hash " << f->hash << ", chunk number=" << f->chunk_number << ", checksum = " << f->check_sum << std::endl; #endif - mFtDataplex->recvSingleChunkCRC(f->PeerId(), f->hash,f->chunk_number,f->check_sum); - } - } - break ; + mFtDataplex->recvSingleChunkCRC(f->PeerId(), f->hash,f->chunk_number,f->check_sum); + } + } + break ; } delete item ; @@ -1211,12 +1619,12 @@ int ftServer::handleIncoming() ********************************** *********************************/ - /***************************** CONFIG ****************************/ +/***************************** CONFIG ****************************/ bool ftServer::addConfiguration(p3ConfigMgr *cfgmgr) { /* add all the subbits to config mgr */ - cfgmgr->addConfiguration("ft_database.cfg", mFileDatabase); + cfgmgr->addConfiguration("ft_database.cfg", mFileDatabase); cfgmgr->addConfiguration("ft_extra.cfg", mFtExtra); cfgmgr->addConfiguration("ft_transfers.cfg", mFtController); diff --git a/src/ft/ftserver.h b/src/ft/ftserver.h index c5d1d23eb..bbb76a63a 100644 --- a/src/ft/ftserver.h +++ b/src/ft/ftserver.h @@ -135,7 +135,8 @@ public: virtual FileChunksInfo::ChunkStrategy defaultChunkStrategy() ; virtual uint32_t freeDiskSpaceLimit() const ; virtual void setFreeDiskSpaceLimit(uint32_t size_in_mb) ; - + virtual void setDefaultEncryptionPolicy(uint32_t policy) ; // RS_FILE_CTRL_ENCRYPTION_POLICY_STRICT/PERMISSIVE + virtual uint32_t defaultEncryptionPolicy() ; /*** * Control of Downloads Priority. @@ -156,6 +157,7 @@ public: virtual bool FileDetails(const RsFileHash &hash, FileSearchFlags hintflags, FileInfo &info); virtual bool FileDownloadChunksDetails(const RsFileHash& hash,FileChunksInfo& info) ; virtual bool FileUploadChunksDetails(const RsFileHash& hash,const RsPeerId& peer_id,CompressedChunkMap& map) ; + virtual bool isEncryptedSource(const RsPeerId& virtual_peer_id) ; /*** @@ -200,7 +202,7 @@ public: virtual std::string getPartialsDirectory(); virtual bool getSharedDirectories(std::list &dirs); - virtual bool setSharedDirectories(std::list &dirs); + virtual bool setSharedDirectories(const std::list &dirs); virtual bool addSharedDirectory(const SharedDirInfo& dir); virtual bool updateShareFlags(const SharedDirInfo& dir); // updates the flags. The directory should already exist ! virtual bool removeSharedDirectory(std::string dir); @@ -217,6 +219,8 @@ public: /*************** Data Transfer Interface ***********************/ /***************************************************************/ public: + virtual bool activateTunnels(const RsFileHash& hash,uint32_t default_encryption_policy,TransferRequestFlags flags,bool onoff); + virtual bool sendData(const RsPeerId& peerId, const RsFileHash& hash, uint64_t size, uint64_t offset, uint32_t chunksize, void *data); virtual bool sendDataRequest(const RsPeerId& peerId, const RsFileHash& hash, uint64_t size, uint64_t offset, uint32_t chunksize); virtual bool sendChunkMapRequest(const RsPeerId& peer_id,const RsFileHash& hash,bool is_client) ; @@ -224,6 +228,11 @@ 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); + + bool encryptItem(RsTurtleGenericTunnelItem *clear_item,const RsFileHash& hash,RsTurtleGenericDataItem *& encrypted_item); + bool decryptItem(RsTurtleGenericDataItem *encrypted_item, const RsFileHash& hash, RsTurtleGenericTunnelItem *&decrypted_item); + /*************** Internal Transfer Fns *************************/ virtual int tick(); @@ -237,6 +246,22 @@ protected: int handleIncoming() ; bool handleCacheData() ; + /*! + * \brief sendTurtleItem + * Sends the given item into a turtle tunnel, possibly encrypting it if the type of tunnel requires it, which is known from the hash itself. + * \param peerId Peer id to send to (this is a virtual peer id from turtle service) + * \param hash hash of the file. If the item needs to be encrypted + * \param item item to send. + * \return + * true if everything goes right + */ + bool sendTurtleItem(const RsPeerId& peerId,const RsFileHash& hash,RsTurtleGenericTunnelItem *item); + + // fnds out what is the real hash of encrypted hash hash + bool findRealHash(const RsFileHash& hash, RsFileHash& real_hash); + bool findEncryptedHash(const RsPeerId& virtual_peer_id, RsFileHash& encrypted_hash); + bool encryptHash(const RsFileHash& hash, RsFileHash& hash_of_hash); + private: /**** INTERNAL FUNCTIONS ***/ @@ -261,6 +286,9 @@ private: std::string mConfigPath; std::string mDownloadPath; std::string mPartialsPath; + + std::map mEncryptedHashes ; // This map is such that sha1(it->second) = it->first + std::map mEncryptedPeerIds ; // This map holds the hash to be used with each peer id }; diff --git a/src/ft/ftturtlefiletransferitem.cc b/src/ft/ftturtlefiletransferitem.cc index 4ec1123cc..b4ce91623 100644 --- a/src/ft/ftturtlefiletransferitem.cc +++ b/src/ft/ftturtlefiletransferitem.cc @@ -30,7 +30,7 @@ #include #include -uint32_t RsTurtleFileRequestItem::serial_size() +uint32_t RsTurtleFileRequestItem::serial_size() const { uint32_t s = 0 ; @@ -42,7 +42,7 @@ uint32_t RsTurtleFileRequestItem::serial_size() return s ; } -uint32_t RsTurtleFileDataItem::serial_size() +uint32_t RsTurtleFileDataItem::serial_size() const { uint32_t s = 0 ; @@ -55,7 +55,7 @@ uint32_t RsTurtleFileDataItem::serial_size() return s ; } -uint32_t RsTurtleFileMapRequestItem::serial_size() +uint32_t RsTurtleFileMapRequestItem::serial_size() const { uint32_t s = 0 ; @@ -66,7 +66,7 @@ uint32_t RsTurtleFileMapRequestItem::serial_size() return s ; } -uint32_t RsTurtleFileMapItem::serial_size() +uint32_t RsTurtleFileMapItem::serial_size() const { uint32_t s = 0 ; @@ -80,7 +80,7 @@ uint32_t RsTurtleFileMapItem::serial_size() return s ; } -uint32_t RsTurtleChunkCrcItem::serial_size() +uint32_t RsTurtleChunkCrcItem::serial_size() const { uint32_t s = 0 ; @@ -91,7 +91,7 @@ uint32_t RsTurtleChunkCrcItem::serial_size() return s ; } -uint32_t RsTurtleChunkCrcRequestItem::serial_size() +uint32_t RsTurtleChunkCrcRequestItem::serial_size() const { uint32_t s = 0 ; @@ -101,7 +101,7 @@ uint32_t RsTurtleChunkCrcRequestItem::serial_size() return s ; } -bool RsTurtleFileMapRequestItem::serialize(void *data,uint32_t& pktsize) +bool RsTurtleFileMapRequestItem::serialize(void *data,uint32_t& pktsize) const { uint32_t tlvsize = serial_size(); uint32_t offset = 0; @@ -134,7 +134,7 @@ bool RsTurtleFileMapRequestItem::serialize(void *data,uint32_t& pktsize) return ok; } -bool RsTurtleFileMapItem::serialize(void *data,uint32_t& pktsize) +bool RsTurtleFileMapItem::serialize(void *data,uint32_t& pktsize) const { uint32_t tlvsize = serial_size(); uint32_t offset = 0; @@ -171,7 +171,7 @@ bool RsTurtleFileMapItem::serialize(void *data,uint32_t& pktsize) return ok; } -bool RsTurtleChunkCrcRequestItem::serialize(void *data,uint32_t& pktsize) +bool RsTurtleChunkCrcRequestItem::serialize(void *data,uint32_t& pktsize) const { #ifdef P3TURTLE_DEBUG std::cerr << "RsTurtleChunkCrcRequestItem::serialize(): serializing packet:" << std::endl ; @@ -206,7 +206,7 @@ bool RsTurtleChunkCrcRequestItem::serialize(void *data,uint32_t& pktsize) return ok; } -bool RsTurtleChunkCrcItem::serialize(void *data,uint32_t& pktsize) +bool RsTurtleChunkCrcItem::serialize(void *data,uint32_t& pktsize) const { #ifdef P3TURTLE_DEBUG std::cerr << "RsTurtleChunkCrcRequestItem::serialize(): serializing packet:" << std::endl ; @@ -345,7 +345,7 @@ RsTurtleChunkCrcRequestItem::RsTurtleChunkCrcRequestItem(void *data,uint32_t pkt throw std::runtime_error("Unknown error while deserializing.") ; #endif } -bool RsTurtleFileRequestItem::serialize(void *data,uint32_t& pktsize) +bool RsTurtleFileRequestItem::serialize(void *data,uint32_t& pktsize) const { uint32_t tlvsize = serial_size(); uint32_t offset = 0; @@ -459,7 +459,7 @@ RsTurtleFileDataItem::RsTurtleFileDataItem(void *data,uint32_t pktsize) #endif } -bool RsTurtleFileDataItem::serialize(void *data,uint32_t& pktsize) +bool RsTurtleFileDataItem::serialize(void *data,uint32_t& pktsize) const { uint32_t tlvsize = serial_size(); uint32_t offset = 0; diff --git a/src/ft/ftturtlefiletransferitem.h b/src/ft/ftturtlefiletransferitem.h index 7bf2e8e43..8a886918e 100644 --- a/src/ft/ftturtlefiletransferitem.h +++ b/src/ft/ftturtlefiletransferitem.h @@ -44,8 +44,8 @@ class RsTurtleFileRequestItem: public RsTurtleGenericTunnelItem virtual std::ostream& print(std::ostream& o, uint16_t) ; protected: - virtual bool serialize(void *data,uint32_t& size) ; - virtual uint32_t serial_size() ; + virtual bool serialize(void *data,uint32_t& size) const; + virtual uint32_t serial_size() const; }; class RsTurtleFileDataItem: public RsTurtleGenericTunnelItem @@ -64,8 +64,8 @@ class RsTurtleFileDataItem: public RsTurtleGenericTunnelItem virtual std::ostream& print(std::ostream& o, uint16_t) ; - virtual bool serialize(void *data,uint32_t& size) ; - virtual uint32_t serial_size() ; + virtual bool serialize(void *data,uint32_t& size) const; + virtual uint32_t serial_size() const; }; class RsTurtleFileMapRequestItem: public RsTurtleGenericTunnelItem @@ -78,8 +78,8 @@ class RsTurtleFileMapRequestItem: public RsTurtleGenericTunnelItem virtual std::ostream& print(std::ostream& o, uint16_t) ; - virtual bool serialize(void *data,uint32_t& size) ; - virtual uint32_t serial_size() ; + virtual bool serialize(void *data,uint32_t& size) const; + virtual uint32_t serial_size() const; }; class RsTurtleFileMapItem: public RsTurtleGenericTunnelItem @@ -96,8 +96,8 @@ class RsTurtleFileMapItem: public RsTurtleGenericTunnelItem virtual std::ostream& print(std::ostream& o, uint16_t) ; - virtual bool serialize(void *data,uint32_t& size) ; - virtual uint32_t serial_size() ; + virtual bool serialize(void *data,uint32_t& size) const; + virtual uint32_t serial_size() const; }; class RsTurtleChunkCrcRequestItem: public RsTurtleGenericTunnelItem @@ -113,8 +113,8 @@ class RsTurtleChunkCrcRequestItem: public RsTurtleGenericTunnelItem virtual std::ostream& print(std::ostream& o, uint16_t) ; - virtual bool serialize(void *data,uint32_t& size) ; - virtual uint32_t serial_size() ; + virtual bool serialize(void *data,uint32_t& size) const; + virtual uint32_t serial_size() const; }; class RsTurtleChunkCrcItem: public RsTurtleGenericTunnelItem @@ -130,6 +130,6 @@ class RsTurtleChunkCrcItem: public RsTurtleGenericTunnelItem Sha1CheckSum check_sum ; virtual std::ostream& print(std::ostream& o, uint16_t) ; - virtual bool serialize(void *data,uint32_t& size) ; - virtual uint32_t serial_size() ; + virtual bool serialize(void *data,uint32_t& size) const; + virtual uint32_t serial_size() const; }; diff --git a/src/libretroshare.pro b/src/libretroshare.pro index bc51eb801..db7066c9d 100644 --- a/src/libretroshare.pro +++ b/src/libretroshare.pro @@ -294,7 +294,7 @@ mac { OBJECTS_DIR = temp/obj MOC_DIR = temp/moc #DEFINES = WINDOWS_SYS WIN32 STATICLIB MINGW - DEFINES *= MINIUPNPC_VERSION=13 + #DEFINES *= MINIUPNPC_VERSION=13 CONFIG += upnp_miniupnpc CONFIG += c++11 @@ -304,7 +304,7 @@ mac { #CONFIG += zcnatassist # Beautiful Hack to fix 64bit file access. - QMAKE_CXXFLAGS *= -Dfseeko64=fseeko -Dftello64=ftello -Dfopen64=fopen -Dvstatfs64=vstatfs + QMAKE_CXXFLAGS *= -Dfseeko64=fseeko -Dftello64=ftello -Dfopen64=fopen -Dvstatfs64=vstatfs #GPG_ERROR_DIR = ../../../../libgpg-error-1.7 #GPGME_DIR = ../../../../gpgme-1.1.8 @@ -314,6 +314,7 @@ mac { DEPENDPATH += . $$INC_DIR INCLUDEPATH += . $$INC_DIR + INCLUDEPATH += ../../../. # We need a explicit path here, to force using the home version of sqlite3 that really encrypts the database. LIBS += /usr/local/lib/libsqlcipher.a @@ -379,6 +380,8 @@ HEADERS += ft/ftchunkmap.h \ ft/fttransfermodule.h \ ft/ftturtlefiletransferitem.h +HEADERS += crypto/chacha20.h + HEADERS += directory_updater.h \ directory_list.h \ p3filelists.h @@ -537,6 +540,8 @@ SOURCES += ft/ftchunkmap.cc \ ft/fttransfermodule.cc \ ft/ftturtlefiletransferitem.cc +SOURCES += crypto/chacha20.cpp + SOURCES += chat/distantchat.cc \ chat/p3chatservice.cc \ chat/distributedchat.cc \ diff --git a/src/pqi/pqistreamer.cc b/src/pqi/pqistreamer.cc index a96c93148..aa52ec02c 100644 --- a/src/pqi/pqistreamer.cc +++ b/src/pqi/pqistreamer.cc @@ -64,6 +64,10 @@ static const int PQISTREAM_PACKET_SLICING_PROBE_DELAY = 60; // send every 6 static uint8_t PACKET_SLICING_PROBE_BYTES[8] = { 0x02, 0xaa, 0xbb, 0xcc, 0x00, 0x00, 0x00, 0x08 } ; +/* Change to true to disable packet slicing and/or packet grouping, if needed */ +#define DISABLE_PACKET_SLICING false +#define DISABLE_PACKET_GROUPING false + /* This removes the print statements (which hammer pqidebug) */ /*** #define RSITEM_DEBUG 1 @@ -629,7 +633,7 @@ int pqistreamer::handleoutgoing_locked() ++k ; } } - while(mPkt_wpending_size < (uint32_t)maxbytes && mPkt_wpending_size < PQISTREAM_OPTIMAL_PACKET_SIZE ) ; + while(mPkt_wpending_size < (uint32_t)maxbytes && mPkt_wpending_size < PQISTREAM_OPTIMAL_PACKET_SIZE && !DISABLE_PACKET_GROUPING) ; #ifdef DEBUG_PQISTREAMER if(k > 1) @@ -787,7 +791,7 @@ start_packet_read: if(!memcmp(block,PACKET_SLICING_PROBE_BYTES,8)) { - mAcceptsPacketSlicing = true ; + mAcceptsPacketSlicing = !DISABLE_PACKET_SLICING; #ifdef DEBUG_PACKET_SLICING std::cerr << "(II) Enabling packet slicing!" << std::endl; #endif @@ -815,7 +819,7 @@ continue_packet: #endif is_partial_packet = true ; - mAcceptsPacketSlicing = true ; // this is needed + mAcceptsPacketSlicing = !DISABLE_PACKET_SLICING; // this is needed } else extralen = getRsItemSize(block) - blen; // old style packet type diff --git a/src/retroshare/rsfiles.h b/src/retroshare/rsfiles.h index cd12396fb..a9b50d714 100644 --- a/src/retroshare/rsfiles.h +++ b/src/retroshare/rsfiles.h @@ -43,6 +43,9 @@ const uint32_t RS_FILE_CTRL_PAUSE = 0x00000100; const uint32_t RS_FILE_CTRL_START = 0x00000200; const uint32_t RS_FILE_CTRL_FORCE_CHECK = 0x00000400; +const uint32_t RS_FILE_CTRL_ENCRYPTION_POLICY_STRICT = 0x00000001 ; +const uint32_t RS_FILE_CTRL_ENCRYPTION_POLICY_PERMISSIVE = 0x00000002 ; + const uint32_t RS_FILE_RATE_TRICKLE = 0x00000001; const uint32_t RS_FILE_RATE_SLOW = 0x00000002; const uint32_t RS_FILE_RATE_STANDARD = 0x00000003; @@ -63,29 +66,32 @@ const uint32_t RS_FILE_PEER_OFFLINE = 0x00002000; // Flags used when requesting info about transfers, mostly to filter out the result. // -const FileSearchFlags RS_FILE_HINTS_CACHE_deprecated ( 0x00000001 ); -const FileSearchFlags RS_FILE_HINTS_EXTRA ( 0x00000002 ); -const FileSearchFlags RS_FILE_HINTS_LOCAL ( 0x00000004 ); -const FileSearchFlags RS_FILE_HINTS_REMOTE ( 0x00000008 ); -const FileSearchFlags RS_FILE_HINTS_DOWNLOAD ( 0x00000010 ); -const FileSearchFlags RS_FILE_HINTS_UPLOAD ( 0x00000020 ); -const FileSearchFlags RS_FILE_HINTS_SPEC_ONLY ( 0x01000000 ); +const FileSearchFlags RS_FILE_HINTS_CACHE_deprecated ( 0x00000001 ); +const FileSearchFlags RS_FILE_HINTS_EXTRA ( 0x00000002 ); +const FileSearchFlags RS_FILE_HINTS_LOCAL ( 0x00000004 ); +const FileSearchFlags RS_FILE_HINTS_REMOTE ( 0x00000008 ); +const FileSearchFlags RS_FILE_HINTS_DOWNLOAD ( 0x00000010 ); +const FileSearchFlags RS_FILE_HINTS_UPLOAD ( 0x00000020 ); +const FileSearchFlags RS_FILE_HINTS_SPEC_ONLY ( 0x01000000 ); -const FileSearchFlags RS_FILE_HINTS_NETWORK_WIDE ( 0x00000080 );// anonymously shared over network -const FileSearchFlags RS_FILE_HINTS_BROWSABLE ( 0x00000100 );// browsable by friends -const FileSearchFlags RS_FILE_HINTS_PERMISSION_MASK ( 0x00000180 );// OR of the last two flags. Used to filter out. +const FileSearchFlags RS_FILE_HINTS_NETWORK_WIDE ( 0x00000080 );// can be downloaded anonymously +const FileSearchFlags RS_FILE_HINTS_BROWSABLE ( 0x00000100 );// browsable by friends +const FileSearchFlags RS_FILE_HINTS_SEARCHABLE ( 0x00000200 );// can be searched anonymously +const FileSearchFlags RS_FILE_HINTS_PERMISSION_MASK ( 0x00000380 );// OR of the last tree flags. Used to filter out. // Flags used when requesting a transfer // const TransferRequestFlags RS_FILE_REQ_ANONYMOUS_ROUTING ( 0x00000040 ); // Use to ask turtle router to download the file. +const TransferRequestFlags RS_FILE_REQ_ENCRYPTED ( 0x00000080 ); // Asks for end-to-end encryption of file at the level of ftServer +const TransferRequestFlags RS_FILE_REQ_UNENCRYPTED ( 0x00000100 ); // Asks for no end-to-end encryption of file at the level of ftServer const TransferRequestFlags RS_FILE_REQ_ASSUME_AVAILABILITY ( 0x00000200 ); // Assume full source availability. Used for cache files. -const TransferRequestFlags RS_FILE_REQ_CACHE_deprecated ( 0x00000400 ); // Assume full source availability. Used for cache files. +const TransferRequestFlags RS_FILE_REQ_CACHE_deprecated ( 0x00000400 ); // Old stuff used for cache files. Not used anymore. const TransferRequestFlags RS_FILE_REQ_EXTRA ( 0x00000800 ); -const TransferRequestFlags RS_FILE_REQ_MEDIA ( 0x00001000 ); -const TransferRequestFlags RS_FILE_REQ_BACKGROUND ( 0x00002000 ); // To download slowly. +const TransferRequestFlags RS_FILE_REQ_MEDIA ( 0x00001000 ); +const TransferRequestFlags RS_FILE_REQ_BACKGROUND ( 0x00002000 ); // To download slowly. const TransferRequestFlags RS_FILE_REQ_NO_SEARCH ( 0x02000000 ); // disable searching for potential direct sources. -// const uint32_t RS_FILE_HINTS_SHARE_FLAGS_MASK = RS_FILE_HINTS_NETWORK_WIDE_OTHERS | RS_FILE_HINTS_BROWSABLE_OTHERS +// const uint32_t RS_FILE_HINTS_SHARE_FLAGS_MASK = RS_FILE_HINTS_NETWORK_WIDE_OTHERS | RS_FILE_HINTS_BROWSABLE_OTHERS // | RS_FILE_HINTS_NETWORK_WIDE_GROUPS | RS_FILE_HINTS_BROWSABLE_GROUPS ; /* Callback Codes */ @@ -96,7 +102,7 @@ struct SharedDirInfo { std::string filename ; std::string virtualname ; - FileStorageFlags shareflags ; // DIR_FLAGS_NETWORK_WIDE_OTHERS | DIR_FLAGS_BROWSABLE_GROUPS | ... + FileStorageFlags shareflags ; // combnation of DIR_FLAGS_ANONYMOUS_DOWNLOAD | DIR_FLAGS_BROWSABLE | ... std::list parent_groups ; }; @@ -141,6 +147,8 @@ class RsFiles virtual void setFreeDiskSpaceLimit(uint32_t size_in_mb) =0; virtual bool FileControl(const RsFileHash& hash, uint32_t flags) = 0; virtual bool FileClearCompleted() = 0; + virtual void setDefaultEncryptionPolicy(uint32_t policy)=0 ; // RS_FILE_CTRL_ENCRYPTION_POLICY_STRICT/PERMISSIVE + virtual uint32_t defaultEncryptionPolicy()=0 ; /*** * Control of Downloads Priority. @@ -159,6 +167,7 @@ class RsFiles virtual void FileDownloads(std::list &hashs) = 0; virtual bool FileUploads(std::list &hashs) = 0; virtual bool FileDetails(const RsFileHash &hash, FileSearchFlags hintflags, FileInfo &info) = 0; + virtual bool isEncryptedSource(const RsPeerId& virtual_peer_id) =0; /// Gives chunk details about the downloaded file with given hash. virtual bool FileDownloadChunksDetails(const RsFileHash& hash,FileChunksInfo& info) = 0 ; @@ -209,8 +218,9 @@ class RsFiles virtual std::string getDownloadDirectory() = 0; virtual std::string getPartialsDirectory() = 0; - virtual bool getSharedDirectories(std::list &dirs) = 0; - virtual bool addSharedDirectory(const SharedDirInfo& dir) = 0; + virtual bool getSharedDirectories(std::list& dirs) = 0; + virtual bool setSharedDirectories(const std::list& dirs) = 0; + virtual bool addSharedDirectory(const SharedDirInfo& dir) = 0; virtual bool updateShareFlags(const SharedDirInfo& dir) = 0; // updates the flags. The directory should already exist ! virtual bool removeSharedDirectory(std::string dir) = 0; diff --git a/src/retroshare/rstypes.h b/src/retroshare/rstypes.h index 0a8537bb7..aef2d118e 100644 --- a/src/retroshare/rstypes.h +++ b/src/retroshare/rstypes.h @@ -155,12 +155,13 @@ const FileStorageFlags DIR_FLAGS_PARENT ( 0x0001 ); const FileStorageFlags DIR_FLAGS_DETAILS ( 0x0002 ); // apparently unused const FileStorageFlags DIR_FLAGS_CHILDREN ( 0x0004 ); // apparently unused -const FileStorageFlags DIR_FLAGS_NETWORK_WIDE_OTHERS ( 0x0080 ); // Flags for directory sharing permissions. The last -const FileStorageFlags DIR_FLAGS_BROWSABLE_OTHERS ( 0x0100 ); // one should be the OR of the all four flags. -const FileStorageFlags DIR_FLAGS_NETWORK_WIDE_GROUPS ( 0x0200 ); -const FileStorageFlags DIR_FLAGS_BROWSABLE_GROUPS ( 0x0400 ); -const FileStorageFlags DIR_FLAGS_PERMISSIONS_MASK ( DIR_FLAGS_NETWORK_WIDE_OTHERS | DIR_FLAGS_BROWSABLE_OTHERS - | DIR_FLAGS_NETWORK_WIDE_GROUPS | DIR_FLAGS_BROWSABLE_GROUPS ); +const FileStorageFlags DIR_FLAGS_ANONYMOUS_DOWNLOAD ( 0x0080 ); // Flags for directory sharing permissions. The last +//const FileStorageFlags DIR_FLAGS_BROWSABLE_OTHERS ( 0x0100 ); // one should be the OR of the all four flags. +//const FileStorageFlags DIR_FLAGS_NETWORK_WIDE_GROUPS ( 0x0200 ); +const FileStorageFlags DIR_FLAGS_BROWSABLE ( 0x0400 ); +const FileStorageFlags DIR_FLAGS_ANONYMOUS_SEARCH ( 0x0800 ); +const FileStorageFlags DIR_FLAGS_PERMISSIONS_MASK ( DIR_FLAGS_ANONYMOUS_DOWNLOAD | /*DIR_FLAGS_BROWSABLE_OTHERS + DIR_FLAGS_NETWORK_WIDE_GROUPS*/ DIR_FLAGS_BROWSABLE | DIR_FLAGS_ANONYMOUS_SEARCH); const FileStorageFlags DIR_FLAGS_LOCAL ( 0x1000 ); const FileStorageFlags DIR_FLAGS_REMOTE ( 0x2000 ); diff --git a/src/rsserver/p3peers.cc b/src/rsserver/p3peers.cc index bd4e11cbd..d4b5fe332 100644 --- a/src/rsserver/p3peers.cc +++ b/src/rsserver/p3peers.cc @@ -1359,7 +1359,7 @@ FileSearchFlags p3Peers::computePeerPermissionFlags(const RsPeerId& peer_ssl_id, // very simple algorithm. // - bool found = false ; + bool found = directory_parent_groups.empty() ; // by default, empty list means browsable by everyone. RsPgpId pgp_id = getGPGId(peer_ssl_id) ; for(std::list::const_iterator it(directory_parent_groups.begin());it!=directory_parent_groups.end() && !found;++it) @@ -1378,13 +1378,15 @@ FileSearchFlags p3Peers::computePeerPermissionFlags(const RsPeerId& peer_ssl_id, // found = true ; } - bool network_wide = (share_flags & DIR_FLAGS_NETWORK_WIDE_OTHERS) ;//|| ( (share_flags & DIR_FLAGS_NETWORK_WIDE_GROUPS) && found) ; - bool browsable = (share_flags & DIR_FLAGS_BROWSABLE_OTHERS) || ( (share_flags & DIR_FLAGS_BROWSABLE_GROUPS) && found) ; + bool network_wide = (share_flags & DIR_FLAGS_ANONYMOUS_DOWNLOAD) ;//|| ( (share_flags & DIR_FLAGS_NETWORK_WIDE_GROUPS) && found) ; + bool browsable = (share_flags & DIR_FLAGS_BROWSABLE) && found ; + bool searchable = (share_flags & DIR_FLAGS_ANONYMOUS_SEARCH) ; FileSearchFlags final_flags ; if(network_wide) final_flags |= RS_FILE_HINTS_NETWORK_WIDE ; if(browsable ) final_flags |= RS_FILE_HINTS_BROWSABLE ; + if(searchable ) final_flags |= RS_FILE_HINTS_SEARCHABLE ; return final_flags ; } diff --git a/src/turtle/p3turtle.cc b/src/turtle/p3turtle.cc index 8208c08b8..bb4684f01 100644 --- a/src/turtle/p3turtle.cc +++ b/src/turtle/p3turtle.cc @@ -1729,7 +1729,7 @@ void RsTurtleStringSearchRequestItem::performLocalSearch(std::listsearch()" << std::endl ; #endif // now, search! - rsFiles->SearchKeywords(words, initialResults,RS_FILE_HINTS_LOCAL | RS_FILE_HINTS_NETWORK_WIDE,PeerId()); + rsFiles->SearchKeywords(words, initialResults,RS_FILE_HINTS_LOCAL | RS_FILE_HINTS_SEARCHABLE,PeerId()); #ifdef P3TURTLE_DEBUG std::cerr << initialResults.size() << " matches found." << std::endl ; @@ -1767,7 +1767,7 @@ void RsTurtleRegExpSearchRequestItem::performLocalSearch(std::listSearchBoolExp(exp,initialResults,RS_FILE_HINTS_LOCAL | RS_FILE_HINTS_NETWORK_WIDE,PeerId()); + rsFiles->SearchBoolExp(exp,initialResults,RS_FILE_HINTS_LOCAL | RS_FILE_HINTS_SEARCHABLE,PeerId()); result.clear() ; diff --git a/src/turtle/rsturtleitem.cc b/src/turtle/rsturtleitem.cc index 8139c9ad3..4095eceb1 100644 --- a/src/turtle/rsturtleitem.cc +++ b/src/turtle/rsturtleitem.cc @@ -16,7 +16,7 @@ // ---------------------------------- Packet sizes -----------------------------------// // -uint32_t RsTurtleStringSearchRequestItem::serial_size() +uint32_t RsTurtleStringSearchRequestItem::serial_size() const { uint32_t s = 0 ; @@ -27,7 +27,7 @@ uint32_t RsTurtleStringSearchRequestItem::serial_size() return s ; } -uint32_t RsTurtleRegExpSearchRequestItem::serial_size() +uint32_t RsTurtleRegExpSearchRequestItem::serial_size() const { uint32_t s = 0 ; @@ -48,7 +48,7 @@ uint32_t RsTurtleRegExpSearchRequestItem::serial_size() return s ; } -uint32_t RsTurtleSearchResultItem::serial_size() +uint32_t RsTurtleSearchResultItem::serial_size()const { uint32_t s = 0 ; @@ -67,7 +67,7 @@ uint32_t RsTurtleSearchResultItem::serial_size() return s ; } -uint32_t RsTurtleOpenTunnelItem::serial_size() +uint32_t RsTurtleOpenTunnelItem::serial_size()const { uint32_t s = 0 ; @@ -80,7 +80,7 @@ uint32_t RsTurtleOpenTunnelItem::serial_size() return s ; } -uint32_t RsTurtleTunnelOkItem::serial_size() +uint32_t RsTurtleTunnelOkItem::serial_size() const { uint32_t s = 0 ; @@ -91,7 +91,7 @@ uint32_t RsTurtleTunnelOkItem::serial_size() return s ; } -uint32_t RsTurtleGenericDataItem::serial_size() +uint32_t RsTurtleGenericDataItem::serial_size() const { uint32_t s = 0 ; @@ -159,7 +159,7 @@ RsItem *RsTurtleSerialiser::deserialise(void *data, uint32_t *size) } -bool RsTurtleStringSearchRequestItem::serialize(void *data,uint32_t& pktsize) +bool RsTurtleStringSearchRequestItem::serialize(void *data,uint32_t& pktsize) const { uint32_t tlvsize = serial_size(); uint32_t offset = 0; @@ -193,7 +193,7 @@ bool RsTurtleStringSearchRequestItem::serialize(void *data,uint32_t& pktsize) return ok; } -bool RsTurtleRegExpSearchRequestItem::serialize(void *data,uint32_t& pktsize) +bool RsTurtleRegExpSearchRequestItem::serialize(void *data,uint32_t& pktsize) const { uint32_t tlvsize = serial_size(); uint32_t offset = 0; @@ -313,7 +313,7 @@ RsTurtleRegExpSearchRequestItem::RsTurtleRegExpSearchRequestItem(void *data,uint #endif } -bool RsTurtleSearchResultItem::serialize(void *data,uint32_t& pktsize) +bool RsTurtleSearchResultItem::serialize(void *data,uint32_t& pktsize) const { uint32_t tlvsize = serial_size(); uint32_t offset = 0; @@ -398,7 +398,7 @@ RsTurtleSearchResultItem::RsTurtleSearchResultItem(void *data,uint32_t pktsize) #endif } -bool RsTurtleOpenTunnelItem::serialize(void *data,uint32_t& pktsize) +bool RsTurtleOpenTunnelItem::serialize(void *data,uint32_t& pktsize) const { uint32_t tlvsize = serial_size(); uint32_t offset = 0; @@ -464,7 +464,7 @@ RsTurtleOpenTunnelItem::RsTurtleOpenTunnelItem(void *data,uint32_t pktsize) #endif } -bool RsTurtleTunnelOkItem::serialize(void *data,uint32_t& pktsize) +bool RsTurtleTunnelOkItem::serialize(void *data,uint32_t& pktsize) const { uint32_t tlvsize = serial_size(); uint32_t offset = 0; @@ -572,7 +572,7 @@ RsTurtleGenericDataItem::RsTurtleGenericDataItem(void *data,uint32_t pktsize) #endif } -bool RsTurtleGenericDataItem::serialize(void *data,uint32_t& pktsize) +bool RsTurtleGenericDataItem::serialize(void *data,uint32_t& pktsize) const { uint32_t tlvsize = serial_size(); uint32_t offset = 0; diff --git a/src/turtle/rsturtleitem.h b/src/turtle/rsturtleitem.h index 11e1969e7..6cb1ad595 100644 --- a/src/turtle/rsturtleitem.h +++ b/src/turtle/rsturtleitem.h @@ -35,8 +35,8 @@ class RsTurtleItem: public RsItem public: RsTurtleItem(uint8_t turtle_subtype) : RsItem(RS_PKT_VERSION_SERVICE,RS_SERVICE_TYPE_TURTLE,turtle_subtype) {} - 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 + virtual bool serialize(void *data,uint32_t& size) const = 0 ; // Isn't it better that items can serialize themselves ? + virtual uint32_t serial_size() const = 0 ; // deserialise is handled using a constructor virtual void clear() {} }; @@ -63,8 +63,8 @@ class RsTurtleSearchResultItem: public RsTurtleItem virtual std::ostream& print(std::ostream& o, uint16_t) ; protected: - virtual bool serialize(void *data,uint32_t& size) ; - virtual uint32_t serial_size() ; + virtual bool serialize(void *data,uint32_t& size) const ; + virtual uint32_t serial_size() const ; }; class RsTurtleSearchRequestItem: public RsTurtleItem @@ -92,8 +92,8 @@ class RsTurtleStringSearchRequestItem: public RsTurtleSearchRequestItem virtual std::ostream& print(std::ostream& o, uint16_t) ; protected: - virtual bool serialize(void *data,uint32_t& size) ; - virtual uint32_t serial_size() ; + virtual bool serialize(void *data,uint32_t& size) const ; + virtual uint32_t serial_size() const ; }; class RsTurtleRegExpSearchRequestItem: public RsTurtleSearchRequestItem @@ -109,8 +109,8 @@ class RsTurtleRegExpSearchRequestItem: public RsTurtleSearchRequestItem virtual std::ostream& print(std::ostream& o, uint16_t) ; protected: - virtual bool serialize(void *data,uint32_t& size) ; - virtual uint32_t serial_size() ; + virtual bool serialize(void *data,uint32_t& size) const ; + virtual uint32_t serial_size() const ; }; /***********************************************************************************/ @@ -131,8 +131,8 @@ class RsTurtleOpenTunnelItem: public RsTurtleItem virtual std::ostream& print(std::ostream& o, uint16_t) ; protected: - virtual bool serialize(void *data,uint32_t& size) ; - virtual uint32_t serial_size() ; + virtual bool serialize(void *data,uint32_t& size) const ; + virtual uint32_t serial_size() const ; }; class RsTurtleTunnelOkItem: public RsTurtleItem @@ -147,8 +147,8 @@ class RsTurtleTunnelOkItem: public RsTurtleItem virtual std::ostream& print(std::ostream& o, uint16_t) ; protected: - virtual bool serialize(void *data,uint32_t& size) ; - virtual uint32_t serial_size() ; + virtual bool serialize(void *data,uint32_t& size) const ; + virtual uint32_t serial_size() const ; }; /***********************************************************************************/ @@ -208,8 +208,8 @@ class RsTurtleGenericDataItem: public RsTurtleGenericTunnelItem virtual std::ostream& print(std::ostream& o, uint16_t) ; protected: - virtual bool serialize(void *data,uint32_t& size) ; - virtual uint32_t serial_size() ; + virtual bool serialize(void *data,uint32_t& size) const ; + virtual uint32_t serial_size() const ; }; /***********************************************************************************/ diff --git a/src/util/rsthreads.cc b/src/util/rsthreads.cc index bf2f34042..8cd4a26d6 100644 --- a/src/util/rsthreads.cc +++ b/src/util/rsthreads.cc @@ -30,7 +30,17 @@ #include #include +#ifdef __APPLE__ +int __attribute__((weak)) pthread_setname_np(const char *__buf) ; +int RS_pthread_setname_np(pthread_t /*__target_thread*/, const char *__buf) { + return pthread_setname_np(__buf); +} +#else int __attribute__((weak)) pthread_setname_np(pthread_t __target_thread, const char *__buf) ; +int RS_pthread_setname_np(pthread_t __target_thread, const char *__buf) { + return pthread_setname_np(__target_thread, __buf); +} +#endif #ifdef RSMUTEX_DEBUG #include @@ -147,6 +157,11 @@ void RsTickingThread::fullstop() void RsThread::start(const std::string &threadName) { + if(isRunning()) + { + std::cerr << "(EE) RsThread \"" << threadName << "\" is already running. Will not start twice!" << std::endl; + return ; + } pthread_t tid; void *data = (void *)this ; @@ -167,19 +182,21 @@ void RsThread::start(const std::string &threadName) // set name if(pthread_setname_np) - if(!threadName.empty()) - { - // thread names are restricted to 16 characters including the terminating null byte - if(threadName.length() > 15) - { + { + if(!threadName.empty()) + { + // thread names are restricted to 16 characters including the terminating null byte + if(threadName.length() > 15) + { #ifdef DEBUG_THREADS - THREAD_DEBUG << "RsThread::start called with to long name '" << name << "' truncating..." << std::endl; + THREAD_DEBUG << "RsThread::start called with to long name '" << name << "' truncating..." << std::endl; #endif - pthread_setname_np(mTid, threadName.substr(0, 15).c_str()); - } else { - pthread_setname_np(mTid, threadName.c_str()); - } - } + RS_pthread_setname_np(mTid, threadName.substr(0, 15).c_str()); + } else { + RS_pthread_setname_np(mTid, threadName.c_str()); + } + } + } } else { diff --git a/tests/librssimulator/librssimulator.pro b/tests/librssimulator/librssimulator.pro index 9ef336b57..94c942f53 100644 --- a/tests/librssimulator/librssimulator.pro +++ b/tests/librssimulator/librssimulator.pro @@ -182,33 +182,40 @@ win32 { ################################# MacOSX ########################################## mac { - QMAKE_CC = $${QMAKE_CXX} - OBJECTS_DIR = temp/obj - MOC_DIR = temp/moc - #DEFINES = WINDOWS_SYS WIN32 STATICLIB MINGW - #DEFINES *= MINIUPNPC_VERSION=13 - DESTDIR = lib + QMAKE_CC = $${QMAKE_CXX} + OBJECTS_DIR = temp/obj + MOC_DIR = temp/moc + #DEFINES = WINDOWS_SYS WIN32 STATICLIB MINGW + #DEFINES *= MINIUPNPC_VERSION=13 + DESTDIR = lib - CONFIG += upnp_miniupnpc + CONFIG += upnp_miniupnpc - # zeroconf disabled at the end of libretroshare.pro (but need the code) - CONFIG += zeroconf - CONFIG += zcnatassist + # zeroconf disabled at the end of libretroshare.pro (but need the code) + #CONFIG += zeroconf + #CONFIG += zcnatassist - # Beautiful Hack to fix 64bit file access. - QMAKE_CXXFLAGS *= -Dfseeko64=fseeko -Dftello64=ftello -Dfopen64=fopen -Dvstatfs64=vstatfs + # Beautiful Hack to fix 64bit file access. + QMAKE_CXXFLAGS *= -Dfseeko64=fseeko -Dftello64=ftello -Dfopen64=fopen -Dvstatfs64=vstatfs - UPNPC_DIR = ../../../miniupnpc-1.0 - #GPG_ERROR_DIR = ../../../../libgpg-error-1.7 - #GPGME_DIR = ../../../../gpgme-1.1.8 + #UPNPC_DIR = ../../../miniupnpc-1.0 + #GPG_ERROR_DIR = ../../../../libgpg-error-1.7 + #GPGME_DIR = ../../../../gpgme-1.1.8 + #OPENPGPSDK_DIR = ../../openpgpsdk/src + #INCLUDEPATH += . $${UPNPC_DIR} + #INCLUDEPATH += $${OPENPGPSDK_DIR} - OPENPGPSDK_DIR = ../../openpgpsdk/src + #for(lib, LIB_DIR):exists($$lib/libminiupnpc.a){ LIBS += $$lib/libminiupnpc.a} + for(lib, LIB_DIR):LIBS += -L"$$lib" + for(bin, BIN_DIR):LIBS += -L"$$bin" - INCLUDEPATH += . $${UPNPC_DIR} - INCLUDEPATH += $${OPENPGPSDK_DIR} + DEPENDPATH += . $$INC_DIR + INCLUDEPATH += . $$INC_DIR + INCLUDEPATH += ../../../. - #../openpgpsdk - #INCLUDEPATH += . $${UPNPC_DIR} $${GPGME_DIR}/src $${GPG_ERROR_DIR}/src + # We need a explicit path here, to force using the home version of sqlite3 that really encrypts the database. + LIBS += /usr/local/lib/libsqlcipher.a + #LIBS += -lsqlite3 } ################################# FreeBSD ########################################## diff --git a/tests/unittests/libretroshare/crypto/chacha20_test.cc b/tests/unittests/libretroshare/crypto/chacha20_test.cc new file mode 100644 index 000000000..8cd203cb3 --- /dev/null +++ b/tests/unittests/libretroshare/crypto/chacha20_test.cc @@ -0,0 +1,12 @@ +#include + +// from libretroshare + +#include "crypto/chacha20.h" + +TEST(libretroshare_crypto, ChaCha20) +{ + std::cerr << "Testing Chacha20" << std::endl; + + EXPECT_TRUE(librs::crypto::perform_tests()) ; +} diff --git a/tests/unittests/unittests.pro b/tests/unittests/unittests.pro index e2eff8049..790ab1c6d 100644 --- a/tests/unittests/unittests.pro +++ b/tests/unittests/unittests.pro @@ -1,156 +1,156 @@ !include("../../retroshare.pri"): error("Could not include file ../../retroshare.pri") -QT += network xml script -CONFIG += bitdht - -CONFIG += gxs debug - -gxs { - DEFINES += RS_ENABLE_GXS -} - -TEMPLATE = app -TARGET = unittests - -OPENPGPSDK_DIR = ../../openpgpsdk/src -INCLUDEPATH *= $${OPENPGPSDK_DIR} ../openpgpsdk - -# it is impossible to use precompield googletest lib -# because googletest must be compiled with same compiler flags as the tests! -!exists(../googletest/googletest/src/gtest-all.cc){ - message(trying to git clone googletest...) - !system(git clone https://github.com/google/googletest.git ../googletest){ - error(Could not git clone googletest files. You can manually download them to /tests/googletest) - } -} - -INCLUDEPATH += \ - ../googletest/googletest/include \ - ../googletest/googletest - -SOURCES += ../googletest/googletest/src/gtest-all.cc - -################################# Linux ########################################## -# Put lib dir in QMAKE_LFLAGS so it appears before -L/usr/lib -linux-* { - #CONFIG += version_detail_bash_script - QMAKE_CXXFLAGS *= -D_FILE_OFFSET_BITS=64 - - PRE_TARGETDEPS *= ../../libretroshare/src/lib/libretroshare.a - PRE_TARGETDEPS *= ../../openpgpsdk/src/lib/libops.a - - LIBS += ../../libretroshare/src/lib/libretroshare.a - LIBS += ../librssimulator/lib/librssimulator.a - LIBS += ../../openpgpsdk/src/lib/libops.a -lbz2 - LIBS += -lssl -lupnp -lixml -lXss -lgnome-keyring - LIBS *= -lcrypto -ldl -lX11 -lz -lpthread - - #LIBS += ../../supportlibs/pegmarkdown/lib/libpegmarkdown.a - - no_sqlcipher { - DEFINES *= NO_SQLCIPHER - PKGCONFIG *= sqlite3 - } else { - # We need a explicit path here, to force using the home version of sqlite3 that really encrypts the database. - - SQLCIPHER_OK = $$system(pkg-config --exists sqlcipher && echo yes) - isEmpty(SQLCIPHER_OK) { - # We need a explicit path here, to force using the home version of sqlite3 that really encrypts the database. - - ! exists(../../../lib/sqlcipher/.libs/libsqlcipher.a) { - message(../../../lib/sqlcipher/.libs/libsqlcipher.a does not exist) - error(Please fix this and try again. Will stop now.) - } - - LIBS += ../../../lib/sqlcipher/.libs/libsqlcipher.a - INCLUDEPATH += ../../../lib/sqlcipher/src/ - INCLUDEPATH += ../../../lib/sqlcipher/tsrc/ - } else { - LIBS += -lsqlcipher - } - } - - - LIBS *= -lglib-2.0 - LIBS *= -rdynamic - DEFINES *= HAVE_XSS # for idle time, libx screensaver extensions - DEFINES *= HAS_GNOME_KEYRING -} - -linux-g++ { - OBJECTS_DIR = temp/linux-g++/obj -} - -linux-g++-64 { - OBJECTS_DIR = temp/linux-g++-64/obj -} - -#################### Cross compilation for windows under Linux ################### - -win32-x-g++ { - OBJECTS_DIR = temp/win32-x-g++/obj - - LIBS += ../../libretroshare/src/lib.win32xgcc/libretroshare.a - LIBS += ../../../../lib/win32-x-g++-v0.5/libssl.a - LIBS += ../../../../lib/win32-x-g++-v0.5/libcrypto.a - LIBS += ../../../../lib/win32-x-g++-v0.5/libgpgme.dll.a - LIBS += ../../../../lib/win32-x-g++-v0.5/libminiupnpc.a - LIBS += ../../../../lib/win32-x-g++-v0.5/libz.a - LIBS += -L${HOME}/.wine/drive_c/pthreads/lib -lpthreadGCE2 - LIBS += -lQtUiTools - LIBS += -lws2_32 -luuid -lole32 -liphlpapi -lcrypt32 -gdi32 - LIBS += -lole32 -lwinmm - - DEFINES *= WINDOWS_SYS WIN32 WIN32_CROSS_UBUNTU - - INCLUDEPATH += ../../../../gpgme-1.1.8/src/ - INCLUDEPATH += ../../../../libgpg-error-1.7/src/ - - RC_FILE = gui/images/retroshare_win.rc -} - -#################################### Windows ##################################### - -win32 { - # Switch on extra warnings - QMAKE_CFLAGS += -Wextra - QMAKE_CXXFLAGS += -Wextra - +QT += network xml script +CONFIG += bitdht + +CONFIG += gxs debug + +gxs { + DEFINES += RS_ENABLE_GXS +} + +TEMPLATE = app +TARGET = unittests + +OPENPGPSDK_DIR = ../../openpgpsdk/src +INCLUDEPATH *= $${OPENPGPSDK_DIR} ../openpgpsdk + +# it is impossible to use precompield googletest lib +# because googletest must be compiled with same compiler flags as the tests! +!exists(../googletest/googletest/src/gtest-all.cc){ + message(trying to git clone googletest...) + !system(git clone https://github.com/google/googletest.git ../googletest){ + error(Could not git clone googletest files. You can manually download them to /tests/googletest) + } +} + +INCLUDEPATH += \ + ../googletest/googletest/include \ + ../googletest/googletest + +SOURCES += ../googletest/googletest/src/gtest-all.cc + +################################# Linux ########################################## +# Put lib dir in QMAKE_LFLAGS so it appears before -L/usr/lib +linux-* { + #CONFIG += version_detail_bash_script + QMAKE_CXXFLAGS *= -D_FILE_OFFSET_BITS=64 + + PRE_TARGETDEPS *= ../../libretroshare/src/lib/libretroshare.a + PRE_TARGETDEPS *= ../../openpgpsdk/src/lib/libops.a + + LIBS += ../../libretroshare/src/lib/libretroshare.a + LIBS += ../librssimulator/lib/librssimulator.a + LIBS += ../../openpgpsdk/src/lib/libops.a -lbz2 + LIBS += -lssl -lupnp -lixml -lXss -lgnome-keyring + LIBS *= -lcrypto -ldl -lX11 -lz -lpthread + + #LIBS += ../../supportlibs/pegmarkdown/lib/libpegmarkdown.a + + no_sqlcipher { + DEFINES *= NO_SQLCIPHER + PKGCONFIG *= sqlite3 + } else { + # We need a explicit path here, to force using the home version of sqlite3 that really encrypts the database. + + SQLCIPHER_OK = $$system(pkg-config --exists sqlcipher && echo yes) + isEmpty(SQLCIPHER_OK) { + # We need a explicit path here, to force using the home version of sqlite3 that really encrypts the database. + + ! exists(../../../lib/sqlcipher/.libs/libsqlcipher.a) { + message(../../../lib/sqlcipher/.libs/libsqlcipher.a does not exist) + error(Please fix this and try again. Will stop now.) + } + + LIBS += ../../../lib/sqlcipher/.libs/libsqlcipher.a + INCLUDEPATH += ../../../lib/sqlcipher/src/ + INCLUDEPATH += ../../../lib/sqlcipher/tsrc/ + } else { + LIBS += -lsqlcipher + } + } + + + LIBS *= -lglib-2.0 + LIBS *= -rdynamic + DEFINES *= HAVE_XSS # for idle time, libx screensaver extensions + DEFINES *= HAS_GNOME_KEYRING +} + +linux-g++ { + OBJECTS_DIR = temp/linux-g++/obj +} + +linux-g++-64 { + OBJECTS_DIR = temp/linux-g++-64/obj +} + +#################### Cross compilation for windows under Linux ################### + +win32-x-g++ { + OBJECTS_DIR = temp/win32-x-g++/obj + + LIBS += ../../libretroshare/src/lib.win32xgcc/libretroshare.a + LIBS += ../../../../lib/win32-x-g++-v0.5/libssl.a + LIBS += ../../../../lib/win32-x-g++-v0.5/libcrypto.a + LIBS += ../../../../lib/win32-x-g++-v0.5/libgpgme.dll.a + LIBS += ../../../../lib/win32-x-g++-v0.5/libminiupnpc.a + LIBS += ../../../../lib/win32-x-g++-v0.5/libz.a + LIBS += -L${HOME}/.wine/drive_c/pthreads/lib -lpthreadGCE2 + LIBS += -lQtUiTools + LIBS += -lws2_32 -luuid -lole32 -liphlpapi -lcrypt32 -gdi32 + LIBS += -lole32 -lwinmm + + DEFINES *= WINDOWS_SYS WIN32 WIN32_CROSS_UBUNTU + + INCLUDEPATH += ../../../../gpgme-1.1.8/src/ + INCLUDEPATH += ../../../../libgpg-error-1.7/src/ + + RC_FILE = gui/images/retroshare_win.rc +} + +#################################### Windows ##################################### + +win32 { + # Switch on extra warnings + QMAKE_CFLAGS += -Wextra + QMAKE_CXXFLAGS += -Wextra + # solve linker warnings because of the order of the libraries QMAKE_LFLAGS += -Wl,--start-group - # Switch off optimization for release version - QMAKE_CXXFLAGS_RELEASE -= -O2 - QMAKE_CXXFLAGS_RELEASE += -O0 - QMAKE_CFLAGS_RELEASE -= -O2 - QMAKE_CFLAGS_RELEASE += -O0 - - # Switch on optimization for debug version - #QMAKE_CXXFLAGS_DEBUG += -O2 - #QMAKE_CFLAGS_DEBUG += -O2 - - OBJECTS_DIR = temp/obj - #LIBS += -L"D/Qt/2009.03/qt/plugins/imageformats" - #QTPLUGIN += qjpeg - - PRE_TARGETDEPS *= ../../libretroshare/src/lib/libretroshare.a - PRE_TARGETDEPS *= ../librssimulator/lib/librssimulator.a - PRE_TARGETDEPS *= ../../openpgpsdk/src/lib/libops.a - + # Switch off optimization for release version + QMAKE_CXXFLAGS_RELEASE -= -O2 + QMAKE_CXXFLAGS_RELEASE += -O0 + QMAKE_CFLAGS_RELEASE -= -O2 + QMAKE_CFLAGS_RELEASE += -O0 + + # Switch on optimization for debug version + #QMAKE_CXXFLAGS_DEBUG += -O2 + #QMAKE_CFLAGS_DEBUG += -O2 + + OBJECTS_DIR = temp/obj + #LIBS += -L"D/Qt/2009.03/qt/plugins/imageformats" + #QTPLUGIN += qjpeg + + PRE_TARGETDEPS *= ../../libretroshare/src/lib/libretroshare.a + PRE_TARGETDEPS *= ../librssimulator/lib/librssimulator.a + PRE_TARGETDEPS *= ../../openpgpsdk/src/lib/libops.a + for(lib, LIB_DIR):LIBS += -L"$$lib" for(bin, BIN_DIR):LIBS += -L"$$bin" - LIBS += ../../libretroshare/src/lib/libretroshare.a + LIBS += ../../libretroshare/src/lib/libretroshare.a LIBS += ../librssimulator/lib/librssimulator.a - LIBS += ../../openpgpsdk/src/lib/libops.a -lbz2 - LIBS += -L"$$PWD/../../../lib" - - LIBS += -lssl -lcrypto -lpthread -lminiupnpc -lz - LIBS += -luuid -lole32 -liphlpapi -lcrypt32 -lgdi32 + LIBS += ../../openpgpsdk/src/lib/libops.a -lbz2 + LIBS += -L"$$PWD/../../../lib" + + LIBS += -lssl -lcrypto -lpthread -lminiupnpc -lz + LIBS += -luuid -lole32 -liphlpapi -lcrypt32 -lgdi32 LIBS += -lwinmm - - DEFINES *= WINDOWS_SYS WIN32_LEAN_AND_MEAN _USE_32BIT_TIME_T - + + DEFINES *= WINDOWS_SYS WIN32_LEAN_AND_MEAN _USE_32BIT_TIME_T + # create lib directory message(CHK_DIR_EXISTS=$(CHK_DIR_EXISTS)) message(MKDIR=$(MKDIR)) @@ -166,227 +166,232 @@ win32 { # Qt 4 QMAKE_RC += --include-dir=$$_PRO_FILE_PWD_/../../libretroshare/src } -} - -##################################### MacOS ###################################### - -macx { - # ENABLE THIS OPTION FOR Univeral Binary BUILD. - CONFIG += ppc x86 - QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.4 - - CONFIG += version_detail_bash_script - LIBS += ../../libretroshare/src/lib/libretroshare.a - LIBS += ../librssimulator/lib/librssimulator.a - LIBS += ../../openpgpsdk/src/lib/libops.a -lbz2 - LIBS += -lssl -lcrypto -lz - #LIBS += -lssl -lcrypto -lz -lgpgme -lgpg-error -lassuan - LIBS += ../../../miniupnpc-1.0/libminiupnpc.a - LIBS += -framework CoreFoundation - LIBS += -framework Security - - gxs { - LIBS += ../../supportlibs/pegmarkdown/lib/libpegmarkdown.a - - LIBS += ../../../lib/libsqlcipher.a - #LIBS += -lsqlite3 - - } - - - INCLUDEPATH += . - #DEFINES* = MAC_IDLE # for idle feature - CONFIG -= uitools - - -} - -##################################### FreeBSD ###################################### - -freebsd-* { - INCLUDEPATH *= /usr/local/include/gpgme - LIBS *= ../../libretroshare/src/lib/libretroshare.a - LIBS *= ../librssimulator/lib/librssimulator.a - LIBS *= -lssl - LIBS *= -lgpgme - LIBS *= -lupnp - LIBS *= -lgnome-keyring - PRE_TARGETDEPS *= ../../libretroshare/src/lib/libretroshare.a - - gxs { - LIBS += ../../supportlibs/pegmarkdown/lib/libpegmarkdown.a - LIBS += -lsqlite3 - } - -} - -##################################### OpenBSD ###################################### - -openbsd-* { - INCLUDEPATH *= /usr/local/include - - PRE_TARGETDEPS *= ../../libretroshare/src/lib/libretroshare.a - PRE_TARGETDEPS *= ../../openpgpsdk/src/lib/libops.a - - LIBS *= ../../libretroshare/src/lib/libretroshare.a - LIBS *= ../librssimulator/lib/librssimulator.a - LIBS *= ../../openpgpsdk/src/lib/libops.a -lbz2 - LIBS *= -lssl -lcrypto - LIBS *= -lgpgme - LIBS *= -lupnp - LIBS *= -lgnome-keyring - PRE_TARGETDEPS *= ../../libretroshare/src/lib/libretroshare.a - - gxs { - LIBS += ../../supportlibs/pegmarkdown/lib/libpegmarkdown.a - LIBS += -lsqlite3 - } - - LIBS *= -rdynamic -} - - - -############################## Common stuff ###################################### - -# On Linux systems that alredy have libssl and libcrypto it is advisable -# to rename the patched version of SSL to something like libsslxpgp.a and libcryptoxpg.a - -# ########################################### - -bitdht { - LIBS += ../../libbitdht/src/lib/libbitdht.a - PRE_TARGETDEPS *= ../../libbitdht/src/lib/libbitdht.a -} - -win32 { -# must be added after bitdht - LIBS += -lws2_32 -} - -DEPENDPATH += . \ - -INCLUDEPATH += ../../libretroshare/src/ -INCLUDEPATH += ../librssimulator/ - -SOURCES += unittests.cc \ - -################################ Serialiser ################################ -HEADERS += libretroshare/serialiser/support.h \ - libretroshare/serialiser/rstlvutil.h \ - -SOURCES += libretroshare/serialiser/rsturtleitem_test.cc \ - libretroshare/serialiser/rsbaseitem_test.cc \ - libretroshare/serialiser/rsgxsupdateitem_test.cc \ - libretroshare/serialiser/rsmsgitem_test.cc \ - libretroshare/serialiser/rsstatusitem_test.cc \ - libretroshare/serialiser/rsnxsitems_test.cc \ - libretroshare/serialiser/rsgxsiditem_test.cc \ -# libretroshare/serialiser/rsphotoitem_test.cc \ - libretroshare/serialiser/tlvbase_test2.cc \ - libretroshare/serialiser/tlvrandom_test.cc \ - libretroshare/serialiser/tlvbase_test.cc \ - libretroshare/serialiser/tlvstack_test.cc \ - libretroshare/serialiser/tlvitems_test.cc \ -# libretroshare/serialiser/rsgrouteritem_test.cc \ - libretroshare/serialiser/tlvtypes_test.cc \ - libretroshare/serialiser/tlvkey_test.cc \ - libretroshare/serialiser/support.cc \ - libretroshare/serialiser/rstlvutil.cc \ - -# Still to convert these. -# libretroshare/serialiser/rsconfigitem_test.cc \ -# libretroshare/serialiser/rsgrouteritem_test.cc \ - - -################################## GXS ##################################### - -HEADERS += libretroshare/gxs/common/data_support.h \ - -SOURCES += libretroshare/gxs/common/data_support.cc \ - -HEADERS += libretroshare/gxs/nxs_test/nxsdummyservices.h \ - libretroshare/gxs/nxs_test/nxsgrptestscenario.h \ - libretroshare/gxs/nxs_test/nxsmsgtestscenario.h \ - libretroshare/gxs/nxs_test/nxsgrpsync_test.h \ - libretroshare/gxs/nxs_test/nxsmsgsync_test.h \ - libretroshare/gxs/nxs_test/nxstesthub.h \ - libretroshare/gxs/nxs_test/nxstestscenario.h \ - libretroshare/gxs/nxs_test/nxsgrpsyncdelayed.h - -SOURCES += libretroshare/gxs/nxs_test/nxsdummyservices.cc \ - libretroshare/gxs/nxs_test/nxsgrptestscenario.cc \ - libretroshare/gxs/nxs_test/nxsmsgtestscenario.cc \ - libretroshare/gxs/nxs_test/nxstesthub.cc \ - libretroshare/gxs/nxs_test/rsgxsnetservice_test.cc \ - libretroshare/gxs/nxs_test/nxsmsgsync_test.cc \ - libretroshare/gxs/nxs_test/nxsgrpsync_test.cc \ - libretroshare/gxs/nxs_test/nxsgrpsyncdelayed.cc - -HEADERS += libretroshare/gxs/gen_exchange/genexchangetester.h \ - libretroshare/gxs/gen_exchange/gxspublishmsgtest.h \ - libretroshare/gxs/gen_exchange/genexchangetestservice.h \ - libretroshare/gxs/gen_exchange/gxspublishgrouptest.h \ - libretroshare/gxs/gen_exchange/rsdummyservices.h \ - libretroshare/gxs/gen_exchange/gxsteststats.cpp - -# libretroshare/gxs/gen_exchange/gxsmsgrelatedtest.h \ - -SOURCES += libretroshare/gxs/gen_exchange/gxspublishgrouptest.cc \ - libretroshare/gxs/gen_exchange/gxsteststats.cpp \ - libretroshare/gxs/gen_exchange/gxspublishmsgtest.cc \ - libretroshare/gxs/gen_exchange/rsdummyservices.cc \ - libretroshare/gxs/gen_exchange/rsgenexchange_test.cc \ - libretroshare/gxs/gen_exchange/genexchangetester.cc \ - libretroshare/gxs/gen_exchange/genexchangetestservice.cc \ - -SOURCES += libretroshare/gxs/security/gxssecurity_test.cc - -# libretroshare/gxs/gen_exchange/gxsmsgrelatedtest.cc \ - -HEADERS += libretroshare/gxs/data_service/rsdataservice_test.h \ - -SOURCES += libretroshare/gxs/data_service/rsdataservice_test.cc \ - libretroshare/gxs/data_service/rsgxsdata_test.cc \ - - -################################ dbase ##################################### - - -#SOURCES += libretroshare/dbase/fisavetest.cc \ -# libretroshare/dbase/fitest2.cc \ -# libretroshare/dbase/searchtest.cc \ - -# libretroshare/dbase/ficachetest.cc \ -# libretroshare/dbase/fimontest.cc \ - - -############################### services ################################### - -SOURCES += libretroshare/services/status/status_test.cc \ - -############################### gxs ######################################## - -HEADERS += libretroshare/services/gxs/rsgxstestitems.h \ - libretroshare/services/gxs/gxstestservice.h \ - libretroshare/services/gxs/GxsIsolatedServiceTester.h \ - libretroshare/services/gxs/GxsPeerNode.h \ - libretroshare/services/gxs/GxsPairServiceTester.h \ - libretroshare/services/gxs/FakePgpAuxUtils.h \ - -# libretroshare/services/gxs/RsGxsNetServiceTester.h \ - -SOURCES += libretroshare/services/gxs/rsgxstestitems.cc \ - libretroshare/services/gxs/gxstestservice.cc \ - libretroshare/services/gxs/GxsIsolatedServiceTester.cc \ - libretroshare/services/gxs/GxsPeerNode.cc \ - libretroshare/services/gxs/GxsPairServiceTester.cc \ - libretroshare/services/gxs/FakePgpAuxUtils.cc \ - libretroshare/services/gxs/nxsbasic_test.cc \ - libretroshare/services/gxs/nxspair_tests.cc \ - libretroshare/services/gxs/gxscircle_tests.cc \ - -# libretroshare/services/gxs/gxscircle_mintest.cc \ - - -# libretroshare/services/gxs/RsGxsNetServiceTester.cc \ +} + +##################################### MacOS ###################################### + +macx { + # ENABLE THIS OPTION FOR Univeral Binary BUILD. + #CONFIG += ppc x86 + #QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.4 + + CONFIG += version_detail_bash_script + LIBS += ../../libretroshare/src/lib/libretroshare.a + LIBS += ../librssimulator/lib/librssimulator.a + LIBS += ../../openpgpsdk/src/lib/libops.a -lbz2 + LIBS += -lssl -lcrypto -lz + #LIBS += -lssl -lcrypto -lz -lgpgme -lgpg-error -lassuan + for(lib, LIB_DIR):exists($$lib/libminiupnpc.a){ LIBS += $$lib/libminiupnpc.a} + LIBS += -framework CoreFoundation + LIBS += -framework Security + + + for(lib, LIB_DIR):LIBS += -L"$$lib" + for(bin, BIN_DIR):LIBS += -L"$$bin" + + DEPENDPATH += . $$INC_DIR + INCLUDEPATH += . $$INC_DIR + + #LIBS += ../../supportlibs/pegmarkdown/lib/libpegmarkdown.a + + # We need a explicit path here, to force using the home version of sqlite3 that really encrypts the database. + LIBS += /usr/local/lib/libsqlcipher.a + #LIBS += -lsqlite3 + + #DEFINES* = MAC_IDLE # for idle feature + CONFIG -= uitools +} + +##################################### FreeBSD ###################################### + +freebsd-* { + INCLUDEPATH *= /usr/local/include/gpgme + LIBS *= ../../libretroshare/src/lib/libretroshare.a + LIBS *= ../librssimulator/lib/librssimulator.a + LIBS *= -lssl + LIBS *= -lgpgme + LIBS *= -lupnp + LIBS *= -lgnome-keyring + PRE_TARGETDEPS *= ../../libretroshare/src/lib/libretroshare.a + + gxs { + LIBS += ../../supportlibs/pegmarkdown/lib/libpegmarkdown.a + LIBS += -lsqlite3 + } + +} + +##################################### OpenBSD ###################################### + +openbsd-* { + INCLUDEPATH *= /usr/local/include + + PRE_TARGETDEPS *= ../../libretroshare/src/lib/libretroshare.a + PRE_TARGETDEPS *= ../../openpgpsdk/src/lib/libops.a + + LIBS *= ../../libretroshare/src/lib/libretroshare.a + LIBS *= ../librssimulator/lib/librssimulator.a + LIBS *= ../../openpgpsdk/src/lib/libops.a -lbz2 + LIBS *= -lssl -lcrypto + LIBS *= -lgpgme + LIBS *= -lupnp + LIBS *= -lgnome-keyring + PRE_TARGETDEPS *= ../../libretroshare/src/lib/libretroshare.a + + gxs { + LIBS += ../../supportlibs/pegmarkdown/lib/libpegmarkdown.a + LIBS += -lsqlite3 + } + + LIBS *= -rdynamic +} + + + +############################## Common stuff ###################################### + +# On Linux systems that alredy have libssl and libcrypto it is advisable +# to rename the patched version of SSL to something like libsslxpgp.a and libcryptoxpg.a + +# ########################################### + +bitdht { + LIBS += ../../libbitdht/src/lib/libbitdht.a + PRE_TARGETDEPS *= ../../libbitdht/src/lib/libbitdht.a +} + +win32 { +# must be added after bitdht + LIBS += -lws2_32 +} + +DEPENDPATH += . \ + +INCLUDEPATH += ../../libretroshare/src/ +INCLUDEPATH += ../librssimulator/ + +SOURCES += unittests.cc \ + +################################## Crypto ################################## + +SOURCES += libretroshare/crypto/chacha20_test.cc + +################################ Serialiser ################################ +HEADERS += libretroshare/serialiser/support.h \ + libretroshare/serialiser/rstlvutil.h \ + +SOURCES += libretroshare/serialiser/rsturtleitem_test.cc \ + libretroshare/serialiser/rsbaseitem_test.cc \ + libretroshare/serialiser/rsgxsupdateitem_test.cc \ + libretroshare/serialiser/rsmsgitem_test.cc \ + libretroshare/serialiser/rsstatusitem_test.cc \ + libretroshare/serialiser/rsnxsitems_test.cc \ + libretroshare/serialiser/rsgxsiditem_test.cc \ +# libretroshare/serialiser/rsphotoitem_test.cc \ + libretroshare/serialiser/tlvbase_test2.cc \ + libretroshare/serialiser/tlvrandom_test.cc \ + libretroshare/serialiser/tlvbase_test.cc \ + libretroshare/serialiser/tlvstack_test.cc \ + libretroshare/serialiser/tlvitems_test.cc \ +# libretroshare/serialiser/rsgrouteritem_test.cc \ + libretroshare/serialiser/tlvtypes_test.cc \ + libretroshare/serialiser/tlvkey_test.cc \ + libretroshare/serialiser/support.cc \ + libretroshare/serialiser/rstlvutil.cc \ + +# Still to convert these. +# libretroshare/serialiser/rsconfigitem_test.cc \ +# libretroshare/serialiser/rsgrouteritem_test.cc \ + + +################################## GXS ##################################### + +HEADERS += libretroshare/gxs/common/data_support.h \ + +SOURCES += libretroshare/gxs/common/data_support.cc \ + +HEADERS += libretroshare/gxs/nxs_test/nxsdummyservices.h \ + libretroshare/gxs/nxs_test/nxsgrptestscenario.h \ + libretroshare/gxs/nxs_test/nxsmsgtestscenario.h \ + libretroshare/gxs/nxs_test/nxsgrpsync_test.h \ + libretroshare/gxs/nxs_test/nxsmsgsync_test.h \ + libretroshare/gxs/nxs_test/nxstesthub.h \ + libretroshare/gxs/nxs_test/nxstestscenario.h \ + libretroshare/gxs/nxs_test/nxsgrpsyncdelayed.h + +SOURCES += libretroshare/gxs/nxs_test/nxsdummyservices.cc \ + libretroshare/gxs/nxs_test/nxsgrptestscenario.cc \ + libretroshare/gxs/nxs_test/nxsmsgtestscenario.cc \ + libretroshare/gxs/nxs_test/nxstesthub.cc \ + libretroshare/gxs/nxs_test/rsgxsnetservice_test.cc \ + libretroshare/gxs/nxs_test/nxsmsgsync_test.cc \ + libretroshare/gxs/nxs_test/nxsgrpsync_test.cc \ + libretroshare/gxs/nxs_test/nxsgrpsyncdelayed.cc + +HEADERS += libretroshare/gxs/gen_exchange/genexchangetester.h \ + libretroshare/gxs/gen_exchange/gxspublishmsgtest.h \ + libretroshare/gxs/gen_exchange/genexchangetestservice.h \ + libretroshare/gxs/gen_exchange/gxspublishgrouptest.h \ + libretroshare/gxs/gen_exchange/rsdummyservices.h \ + libretroshare/gxs/gen_exchange/gxsteststats.cpp + +# libretroshare/gxs/gen_exchange/gxsmsgrelatedtest.h \ + +SOURCES += libretroshare/gxs/gen_exchange/gxspublishgrouptest.cc \ + libretroshare/gxs/gen_exchange/gxsteststats.cpp \ + libretroshare/gxs/gen_exchange/gxspublishmsgtest.cc \ + libretroshare/gxs/gen_exchange/rsdummyservices.cc \ + libretroshare/gxs/gen_exchange/rsgenexchange_test.cc \ + libretroshare/gxs/gen_exchange/genexchangetester.cc \ + libretroshare/gxs/gen_exchange/genexchangetestservice.cc \ + +SOURCES += libretroshare/gxs/security/gxssecurity_test.cc + +# libretroshare/gxs/gen_exchange/gxsmsgrelatedtest.cc \ + +HEADERS += libretroshare/gxs/data_service/rsdataservice_test.h \ + +SOURCES += libretroshare/gxs/data_service/rsdataservice_test.cc \ + libretroshare/gxs/data_service/rsgxsdata_test.cc \ + + +################################ dbase ##################################### + + +#SOURCES += libretroshare/dbase/fisavetest.cc \ +# libretroshare/dbase/fitest2.cc \ +# libretroshare/dbase/searchtest.cc \ + +# libretroshare/dbase/ficachetest.cc \ +# libretroshare/dbase/fimontest.cc \ + + +############################### services ################################### + +SOURCES += libretroshare/services/status/status_test.cc \ + +############################### gxs ######################################## + +HEADERS += libretroshare/services/gxs/rsgxstestitems.h \ + libretroshare/services/gxs/gxstestservice.h \ + libretroshare/services/gxs/GxsIsolatedServiceTester.h \ + libretroshare/services/gxs/GxsPeerNode.h \ + libretroshare/services/gxs/GxsPairServiceTester.h \ + libretroshare/services/gxs/FakePgpAuxUtils.h \ + +# libretroshare/services/gxs/RsGxsNetServiceTester.h \ + +SOURCES += libretroshare/services/gxs/rsgxstestitems.cc \ + libretroshare/services/gxs/gxstestservice.cc \ + libretroshare/services/gxs/GxsIsolatedServiceTester.cc \ + libretroshare/services/gxs/GxsPeerNode.cc \ + libretroshare/services/gxs/GxsPairServiceTester.cc \ + libretroshare/services/gxs/FakePgpAuxUtils.cc \ + libretroshare/services/gxs/nxsbasic_test.cc \ + libretroshare/services/gxs/nxspair_tests.cc \ + libretroshare/services/gxs/gxscircle_tests.cc \ + +# libretroshare/services/gxs/gxscircle_mintest.cc \ + + +# libretroshare/services/gxs/RsGxsNetServiceTester.cc \