diff --git a/libretroshare/src/grouter/p3grouter.cc b/libretroshare/src/grouter/p3grouter.cc index 5f2b6e7d0..1ba453d1b 100644 --- a/libretroshare/src/grouter/p3grouter.cc +++ b/libretroshare/src/grouter/p3grouter.cc @@ -1892,7 +1892,9 @@ bool p3GRouter::encryptDataItem(RsGRouterGenericDataItem *item,const RsGxsId& de uint32_t encrypted_size =0; uint32_t error_status ; - if(!mGixs->encryptData(item->data_bytes,item->data_size,encrypted_data,encrypted_size,destination_key,true,error_status)) + if(!mGixs->encryptData( item->data_bytes, item->data_size, encrypted_data, + encrypted_size, destination_key, error_status, + true )) { std::cerr << "(EE) Cannot encrypt: " ; if(error_status == RsGixs::RS_GIXS_ERROR_KEY_NOT_AVAILABLE) std::cerr << " key not available for ID = " << destination_key << std::endl; @@ -1926,7 +1928,9 @@ bool p3GRouter::decryptDataItem(RsGRouterGenericDataItem *item) uint32_t decrypted_size =0; uint32_t error_status ; - if(!mGixs->decryptData(item->data_bytes,item->data_size,decrypted_data,decrypted_size,item->destination_key,error_status)) + if(!mGixs->decryptData( item->data_bytes, item->data_size, decrypted_data, + decrypted_size, item->destination_key, error_status, + true )) { if(error_status == RsGixs::RS_GIXS_ERROR_KEY_NOT_AVAILABLE) std::cerr << "(EE) Cannot decrypt incoming message. Key " << item->destination_key << " unknown." << std::endl; diff --git a/libretroshare/src/gxs/rsgixs.h b/libretroshare/src/gxs/rsgixs.h index 2f2c0f0ec..6e8591a4a 100644 --- a/libretroshare/src/gxs/rsgixs.h +++ b/libretroshare/src/gxs/rsgixs.h @@ -103,7 +103,7 @@ typedef PGPIdType RsPgpId; class RsGixs { public: - + // TODO: cleanup this should be an enum! static const uint32_t RS_GIXS_ERROR_NO_ERROR = 0x0000 ; static const uint32_t RS_GIXS_ERROR_UNKNOWN = 0x0001 ; static const uint32_t RS_GIXS_ERROR_KEY_NOT_AVAILABLE = 0x0002 ; @@ -119,8 +119,17 @@ public: virtual bool signData(const uint8_t *data,uint32_t data_size,const RsGxsId& signer_id,RsTlvKeySignature& signature,uint32_t& signing_error) = 0 ; virtual bool validateData(const uint8_t *data,uint32_t data_size,const RsTlvKeySignature& signature,bool force_load,const RsIdentityUsage& info,uint32_t& signing_error) = 0 ; - virtual bool encryptData(const uint8_t *clear_data,uint32_t clear_data_size,uint8_t *& encrypted_data,uint32_t& encrypted_data_size,const RsGxsId& encryption_key_id,bool force_load,uint32_t& encryption_error) = 0 ; - virtual bool decryptData(const uint8_t *encrypted_data,uint32_t encrypted_data_size,uint8_t *& clear_data,uint32_t& clear_data_size,const RsGxsId& encryption_key_id,uint32_t& encryption_error) = 0 ; + virtual bool encryptData( const uint8_t *clear_data, + uint32_t clear_data_size, + uint8_t *& encrypted_data, + uint32_t& encrypted_data_size, + const RsGxsId& encryption_key_id, + uint32_t& encryption_error, bool force_load) = 0 ; + virtual bool decryptData( const uint8_t *encrypted_data, + uint32_t encrypted_data_size, + uint8_t *& clear_data, uint32_t& clear_data_size, + const RsGxsId& encryption_key_id, + uint32_t& encryption_error, bool force_load) = 0 ; virtual bool getOwnIds(std::list& ids) = 0; virtual bool isOwnId(const RsGxsId& key_id) = 0 ; diff --git a/libretroshare/src/serialiser/rsgxsmailitems.cc b/libretroshare/src/serialiser/rsgxsmailitems.cc index a3d624b44..40d71b220 100644 --- a/libretroshare/src/serialiser/rsgxsmailitems.cc +++ b/libretroshare/src/serialiser/rsgxsmailitems.cc @@ -25,7 +25,7 @@ bool RsGxsMailBaseItem::serialize(uint8_t* data, uint32_t size, uint32_t& offset) const { bool ok = setRsItemHeader(data, size, PacketId(), size); - ok = ok && (offset += 8); // Take in account the header + ok = ok && (offset += 8); // Take header in account ok = ok && setRawUInt8(data, size, &offset, cryptoType); ok = ok && recipientsHint.serialise(data, size, offset); return ok; @@ -36,10 +36,10 @@ bool RsGxsMailBaseItem::deserialize(const uint8_t* data, uint32_t& size, { void* dataPtr = reinterpret_cast(const_cast(data)); uint32_t rssize = getRsItemSize(dataPtr); - uint32_t roffset = offset + 8; + uint32_t roffset = offset + 8; // Take header in account bool ok = rssize <= size; uint8_t crType; - ok = ok && getRawUInt8(dataPtr, rssize, &offset, &crType); + ok = ok && getRawUInt8(dataPtr, rssize, &roffset, &crType); cryptoType = static_cast(crType); ok = ok && recipientsHint.deserialise(dataPtr, rssize, roffset); if(ok) { size = rssize; offset = roffset; } diff --git a/libretroshare/src/serialiser/rsgxsmailitems.h b/libretroshare/src/serialiser/rsgxsmailitems.h index f57439f43..278b18c48 100644 --- a/libretroshare/src/serialiser/rsgxsmailitems.h +++ b/libretroshare/src/serialiser/rsgxsmailitems.h @@ -38,7 +38,8 @@ struct RsGxsMailBaseItem : RsGxsMsgItem { RsGxsMailBaseItem(GxsMailItemsSubtypes subtype) : RsGxsMsgItem( RS_SERVICE_TYPE_GXS_MAIL, - static_cast(subtype) ) {} + static_cast(subtype) ), + cryptoType(UNDEFINED_ENCRYPTION) {} /// Values must fit into uint8_t enum EncryptionMode @@ -86,11 +87,10 @@ struct RsGxsMailBaseItem : RsGxsMsgItem */ RsGxsId recipientsHint; - void inline saltRecipientHint(const RsGxsId& salt) - { saltRecipientHint(recipientsHint, salt); } - void static inline saltRecipientHint(RsGxsId& hint, const RsGxsId& salt) { hint = hint | salt; } + void inline saltRecipientHint(const RsGxsId& salt) + { saltRecipientHint(recipientsHint, salt); } /** * @brief maybeRecipient given an id and an hint check if they match @@ -102,6 +102,8 @@ struct RsGxsMailBaseItem : RsGxsMsgItem */ bool static inline maybeRecipient(const RsGxsId& hint, const RsGxsId& id) { return (~id|hint) == allRecipientsHint; } + bool inline maybeRecipient(const RsGxsId& id) const + { return maybeRecipient(recipientsHint, id); } const static RsGxsId allRecipientsHint; @@ -137,9 +139,12 @@ struct RsGxsMailItem : RsGxsMailBaseItem uint32_t size() const { return RsGxsMailBaseItem::size() + payload.size(); } bool serialize(uint8_t* data, uint32_t size, uint32_t& offset) const { - return size < MAX_SIZE - && RsGxsMailBaseItem::serialize(data, size, offset) - && memcpy(data+offset, &payload[0], payload.size()); + bool ok = size < MAX_SIZE; + ok = ok && RsGxsMailBaseItem::serialize(data, size, offset); + uint32_t psz = payload.size(); + ok = ok && memcpy(data+offset, &payload[0], psz); + offset += psz; + return ok; } bool deserialize(const uint8_t* data, uint32_t& size, uint32_t& offset) { diff --git a/libretroshare/src/services/p3gxsmails.cpp b/libretroshare/src/services/p3gxsmails.cpp index 63a07f4d3..6083fbc9b 100644 --- a/libretroshare/src/services/p3gxsmails.cpp +++ b/libretroshare/src/services/p3gxsmails.cpp @@ -82,15 +82,15 @@ bool p3GxsMails::sendMail( GxsMailsClient::GxsMailSubServices service, // Public metadata item->meta.mAuthorId = own_gxsid; item->meta.mGroupId = preferredGroupId; + item->cryptoType = cm; typedef std::set::const_iterator siT; for(siT it = rcps.begin(); it != rcps.end(); ++it) - item->saltRecipientHint(*it); + item->saltRecipientHint(*it); // If there is jut one recipient salt with a random id to avoid leaking it if(rcps.size() == 1) item->saltRecipientHint(RsGxsId::random()); - /* At this point we do a lot of memory copying, it doesn't look pretty but * ATM haven't thinked of an elegant way to have the GxsMailSubServices * travelling encrypted withuot copying memory around or responsabilize the @@ -100,7 +100,7 @@ bool p3GxsMails::sendMail( GxsMailsClient::GxsMailSubServices service, uint32_t clearTextPldSize = size+2; item->payload.resize(clearTextPldSize); uint32_t _discard = 0; - setRawUInt16(&item->payload[0], clearTextPldSize, &_discard, serv); + setRawUInt16(&item->payload[0], 2, &_discard, serv); memcpy(&item->payload[2], data, size); switch (cm) @@ -119,7 +119,7 @@ bool p3GxsMails::sendMail( GxsMailsClient::GxsMailSubServices service, uint32_t encryptError = 0; if( idService.encryptData( &item->payload[0], clearTextPldSize, encryptedData, encryptedSize, - rcps, true, encryptError ) ) + rcps, encryptError, true ) ) { item->payload.resize(encryptedSize); memcpy(&item->payload[0], encryptedData, encryptedSize); @@ -143,6 +143,8 @@ bool p3GxsMails::sendMail( GxsMailsClient::GxsMailSubServices service, } uint32_t token; + std::cout << "p3GxsMails::sendEmail(...) sending mail to:"<< *recipients[0] + << " payload size: : " << item->payload.size() << std::endl; publishMsg(token, item); return true; } @@ -228,14 +230,89 @@ void p3GxsMails::handleResponse(uint32_t token, uint32_t req_type) case GXS_MAIL_SUBTYPE_MAIL: { RsGxsMailItem* msg = dynamic_cast(it); - if(msg) + if(!msg) + { + std::cerr << "p3GxsMails::handleResponse(...) " + << "GXS_MAIL_SUBTYPE_MAIL cast error, " + << "something really wrong is happening" + << std::endl; + break; + } + + + std::cout << "p3GxsMails::handleResponse(...) " + << "GXS_MAIL_SUBTYPE_MAIL got from: " + << msg->meta.mAuthorId + << " recipientsHint: " + << msg->recipientsHint << " cryptoType: " + << (uint32_t)msg->cryptoType + << " payload size: " << msg->payload.size() + << std::endl; + + std::set decryptIds; + std::list ownIds; + idService.getOwnIds(ownIds); + for(auto it = ownIds.begin(); it != ownIds.end(); ++it) + if(msg->maybeRecipient(*it)) decryptIds.insert(*it); + + if(decryptIds.empty()) { std::cout << "p3GxsMails::handleResponse(...) " - << "GXS_MAIL_SUBTYPE_MAIL got recipientsHint: " - << msg->recipientsHint << " cryptoType: " - << (uint32_t)msg->cryptoType - << " payload size: " << msg->payload.size() - << std::endl; + << "GXS_MAIL_SUBTYPE_MAIL hint match none" + << " of our own ids" << msg->recipientsHint + << std::endl; + + break; + } + + std::cout << "p3GxsMails::handleResponse(...) " + << "GXS_MAIL_SUBTYPE_MAIL hint: " + << msg->recipientsHint + << " match with own ids: "; + for(auto it=decryptIds.begin(); it != decryptIds.end(); ++it) + std::cout << *it; + std::cout << std::endl; + + switch (msg->cryptoType) + { + case RsGxsMailBaseItem::CLEAR_TEXT: + { + uint16_t csri = 0; + uint32_t off; + getRawUInt16(&msg->payload[0], 2, &off, &csri); + std::string str(reinterpret_cast(&msg->payload[2]), msg->payload.size()-2); + std::cout << "service: " << csri + << " got CLEAR_TEXT message: " + << str << std::endl; + break; + } + case RsGxsMailBaseItem::RSA: + { + uint8_t* decrypted_data = NULL; + uint32_t decrypted_data_size = 0; + uint32_t decryption_error; + if( idService.decryptData( + &msg->payload[0], + msg->payload.size(), decrypted_data, + decrypted_data_size, decryptIds, + decryption_error ) ) + { + uint16_t csri = *reinterpret_cast(decrypted_data); + std::string str(reinterpret_cast(decrypted_data+2), decrypted_data_size-2); + std::cout << "service: " << csri + << " got RSA message: " + << str << std::endl; + } + else std::cout << "p3GxsMails::handleResponse(...) " + << "GXS_MAIL_SUBTYPE_MAIL RSA decryption" + << " failed" << std::endl; + free(decrypted_data); + break; + } + default: + std::cout << "Unknown encryption type:" + << msg->cryptoType << std::endl; + break; } break; } @@ -247,6 +324,7 @@ void p3GxsMails::handleResponse(uint32_t token, uint32_t req_type) } } } + break; } default: std::cerr << "p3GxsMails::handleResponse(...) Unknown req_type: " @@ -271,14 +349,14 @@ void p3GxsMails::service_tick() std::string ciao("CiAone!"); sendMail( GxsMailsClient::MSG_SERVICE, gxsidA, gxsidB, reinterpret_cast(ciao.data()), - ciao.size()); + ciao.size(), RsGxsMailBaseItem::RSA ); } else if(idService.isOwnId(gxsidB)) { - std::string ciao("CiBone!"); + std::string ciao("CiBuono!"); sendMail( GxsMailsClient::MSG_SERVICE, gxsidB, gxsidA, reinterpret_cast(ciao.data()), - ciao.size()); + ciao.size(), RsGxsMailBaseItem::RSA ); } } diff --git a/libretroshare/src/services/p3gxsmails.h b/libretroshare/src/services/p3gxsmails.h index 197f5f5b3..cf05f7aae 100644 --- a/libretroshare/src/services/p3gxsmails.h +++ b/libretroshare/src/services/p3gxsmails.h @@ -125,8 +125,13 @@ private: /// @brief AuthenPolicy check nothing ATM TODO talk with Cyril how this should be static uint32_t AuthenPolicy() { return 0; } - /// Types to mark GXS queries and answhers - enum GxsReqResTypes { GROUPS_LIST, GROUP_CREATE, MAILS_UPDATE }; + /// Types to mark queries in tokens queue + enum GxsReqResTypes + { + GROUPS_LIST = 1, + GROUP_CREATE = 2, + MAILS_UPDATE = 3 + }; /// Store the id of the preferred GXS group to send emails RsGxsGroupId preferredGroupId; diff --git a/libretroshare/src/services/p3idservice.cc b/libretroshare/src/services/p3idservice.cc index 61722ebf8..022a92b6c 100644 --- a/libretroshare/src/services/p3idservice.cc +++ b/libretroshare/src/services/p3idservice.cc @@ -1036,7 +1036,13 @@ bool p3IdService::validateData(const uint8_t *data,uint32_t data_size,const RsTl return true ; } -bool p3IdService::encryptData(const uint8_t *decrypted_data,uint32_t decrypted_data_size,uint8_t *& encrypted_data,uint32_t& encrypted_data_size,const RsGxsId& encryption_key_id,bool force_load,uint32_t& error_status) +bool p3IdService::encryptData( const uint8_t *decrypted_data, + uint32_t decrypted_data_size, + uint8_t *& encrypted_data, + uint32_t& encrypted_data_size, + const RsGxsId& encryption_key_id, + uint32_t& error_status, + bool force_load ) { RsTlvPublicRSAKey encryption_key ; @@ -1071,7 +1077,7 @@ bool p3IdService::encryptData( const uint8_t* decrypted_data, uint8_t*& encrypted_data, uint32_t& encrypted_data_size, const std::set& encrypt_ids, - bool force_load, uint32_t& error_status ) + uint32_t& error_status, bool force_load ) { std::set keyNotYetFoundIds; @@ -1154,18 +1160,22 @@ bool p3IdService::encryptData( const uint8_t* decrypted_data, return true; } -bool p3IdService::decryptData(const uint8_t *encrypted_data,uint32_t encrypted_data_size,uint8_t *& decrypted_data,uint32_t& decrypted_size,const RsGxsId& key_id,uint32_t& error_status) +bool p3IdService::decryptData( const uint8_t *encrypted_data, + uint32_t encrypted_data_size, + uint8_t *& decrypted_data, + uint32_t& decrypted_size, + const RsGxsId& key_id, uint32_t& error_status, + bool force_load ) { RsTlvPrivateRSAKey encryption_key ; // Get the key, and let the cache find it. It's our own key, so we should be able to find it, even if it takes // some seconds. - for(int i=0;i<4;++i) - if(getPrivateKey(key_id,encryption_key)) - break ; - else - usleep(500*1000) ; // sleep half a sec. + int maxRounds = force_load ? 6 : 1; + for(int i=0; i& decrypt_ids, + uint32_t& error_status, + bool force_load ) +{ + std::set keyNotYetFoundIds; + + for( std::set::const_iterator it = decrypt_ids.begin(); + it != decrypt_ids.end(); ++it ) + { + const RsGxsId& gId(*it); + if(gId.isNull()) + { + std::cerr << "p3IdService::decryptData(...) (EE) got null GXS id" + << std::endl; + print_stacktrace(); + return false; + } + else keyNotYetFoundIds.insert(&gId); + } + + if(keyNotYetFoundIds.empty()) + { + std::cerr << "p3IdService::decryptData(...) (EE) got empty GXS ids set" + << std::endl; + print_stacktrace(); + return false; + } + + std::vector decryption_keys; + int maxRounds = force_load ? 6 : 1; + for( int i=0; i < maxRounds; ++i ) + { + for( std::set::iterator it = keyNotYetFoundIds.begin(); + it !=keyNotYetFoundIds.end(); ++it ) + { + RsTlvPrivateRSAKey decryption_key; + if( getPrivateKey(**it, decryption_key) + && !decryption_key.keyId.isNull() ) + { + decryption_keys.push_back(decryption_key); + keyNotYetFoundIds.erase(it); + } + } + + if(keyNotYetFoundIds.empty()) break; + else usleep(500*1000); + } + + if(!keyNotYetFoundIds.empty()) + { + std::cerr << "p3IdService::decryptData(...) (EE) Cannot get private key" + << " for: "; + for( std::set::iterator it = keyNotYetFoundIds.begin(); + it !=keyNotYetFoundIds.end(); ++it ) + std::cerr << **it << " "; + std::cerr << std::endl; + print_stacktrace(); + + error_status = RS_GIXS_ERROR_KEY_NOT_AVAILABLE; + return false; + } + + if(!GxsSecurity::decrypt( decrypted_data, decrypted_data_size, + encrypted_data, encrypted_data_size, + decryption_keys )) + { + std::cerr << "p3IdService::decryptData(...) (EE) Decryption failed." + << std::endl; + print_stacktrace(); + + error_status = RS_GIXS_ERROR_UNKNOWN; + return false ; + } + + for( std::set::const_iterator it = decrypt_ids.begin(); + it != decrypt_ids.end(); ++it ) + { + timeStampKey( *it, + RsIdentityUsage( + serviceType(), + RsIdentityUsage::IDENTITY_GENERIC_DECRYPTION ) ); + } + + error_status = RS_GIXS_ERROR_NO_ERROR; + return true; +} #ifdef TO_BE_REMOVED /********************************************************************************/ diff --git a/libretroshare/src/services/p3idservice.h b/libretroshare/src/services/p3idservice.h index 1f95fa241..c93581597 100644 --- a/libretroshare/src/services/p3idservice.h +++ b/libretroshare/src/services/p3idservice.h @@ -303,21 +303,32 @@ public: uint8_t*& encrypted_data, uint32_t& encrypted_data_size, const RsGxsId& encryption_key_id, - bool force_load, uint32_t& encryption_error); + uint32_t& error_status, + bool force_load = true ); bool encryptData( const uint8_t* decrypted_data, uint32_t decrypted_data_size, uint8_t*& encrypted_data, uint32_t& encrypted_data_size, const std::set& encrypt_ids, - bool force_load, uint32_t& error_status ); + uint32_t& error_status, bool force_loa = true ); virtual bool decryptData( const uint8_t* encrypted_data, uint32_t encrypted_data_size, uint8_t*& decrypted_data, uint32_t& decrypted_data_size, - const RsGxsId& encryption_key_id, - uint32_t& encryption_error ); + const RsGxsId& decryption_key_id, + uint32_t& error_status, + bool force_load = true ); + + virtual bool decryptData(const uint8_t* encrypted_data, + uint32_t encrypted_data_size, + uint8_t*& decrypted_data, + uint32_t& decrypted_data_size, + const std::set& decrypt_ids, + uint32_t& error_status, + bool force_load = true ); + virtual bool haveKey(const RsGxsId &id); virtual bool havePrivateKey(const RsGxsId &id);