implemented per-item encryption and Vetting method compatibility layer

This commit is contained in:
csoler 2016-02-20 17:53:03 -05:00
parent b2a6bfbbd0
commit 6a4add8806
10 changed files with 533 additions and 390 deletions

View file

@ -98,7 +98,9 @@ static void setRSAPublicKeyData(RsTlvSecurityKey & key, RSA *rsa_pub)
bool GxsSecurity::checkPrivateKey(const RsTlvSecurityKey& key)
{
#ifdef GXS_SECURITY_DEBUG
std::cerr << "Checking private key " << key.keyId << " ..." << std::endl;
#endif
if( (key.keyFlags & RSTLV_KEY_TYPE_MASK) != RSTLV_KEY_TYPE_FULL)
{
@ -133,7 +135,9 @@ bool GxsSecurity::checkPrivateKey(const RsTlvSecurityKey& key)
}
bool GxsSecurity::checkPublicKey(const RsTlvSecurityKey& key)
{
#ifdef GXS_SECURITY_DEBUG
std::cerr << "Checking public key " << key.keyId << " ..." << std::endl;
#endif
if( (key.keyFlags & RSTLV_KEY_TYPE_MASK) != RSTLV_KEY_TYPE_PUBLIC_ONLY)
{
@ -229,7 +233,7 @@ bool GxsSecurity::extractPublicKey(const RsTlvSecurityKey& private_key,RsTlvSecu
{
std::cerr << std::endl;
std::cerr << "WARNING: GXS ID key pair " << private_key.keyId << " has inconsistent fingerprint. This is an old key " << std::endl;
std::cerr << " that is unsecured (can be faked easily) should not be used anymore. Please delete it." << std::endl;
std::cerr << " that is unsecure (can be faked easily). You should delete it!" << std::endl;
std::cerr << std::endl;
public_key.keyId = private_key.keyId ;
@ -875,7 +879,7 @@ bool GxsSecurity::decrypt(uint8_t *& out, uint32_t & outlen, const uint8_t *in,
//
// This method can be used to decrypt multi-encrypted data, if passing he correct encrypted key block (corresponding to the given key)
#ifdef DISTRIB_DEBUG
#ifdef GXS_SECURITY_DEBUG
std::cerr << "GxsSecurity::decrypt() " << std::endl;
#endif
RSA *rsa_publish = extractPrivateKey(key) ;
@ -891,7 +895,7 @@ bool GxsSecurity::decrypt(uint8_t *& out, uint32_t & outlen, const uint8_t *in,
}
else
{
#ifdef DISTRIB_DEBUG
#ifdef GXS_SECURITY_DEBUG
std::cerr << "GxsSecurity(): Could not generate publish key " << grpId
<< std::endl;
#endif
@ -1017,10 +1021,12 @@ bool GxsSecurity::decrypt(uint8_t *& out, uint32_t & outlen, const uint8_t *in,
throw std::runtime_error("Offset error") ;
encrypted_block_size = inlen - encrypted_block_offset ;
#ifdef GXS_SECURITY_DEBUG
std::cerr << " number of keys in envelop: " << number_of_keys << std::endl;
std::cerr << " IV offset : " << IV_offset << std::endl;
std::cerr << " encrypted block offset : " << encrypted_block_offset << std::endl;
std::cerr << " encrypted block size : " << encrypted_block_size << std::endl;
#endif
// decrypt
@ -1033,7 +1039,9 @@ bool GxsSecurity::decrypt(uint8_t *& out, uint32_t & outlen, const uint8_t *in,
RSA *rsa_private = extractPrivateKey(keys[j]) ;
EVP_PKEY *privateKey = NULL;
#ifdef GXS_SECURITY_DEBUG
std::cerr << " trying key " << keys[j].keyId << std::endl;
#endif
if(rsa_private != NULL)
{
@ -1051,7 +1059,9 @@ bool GxsSecurity::decrypt(uint8_t *& out, uint32_t & outlen, const uint8_t *in,
{
succeed = EVP_OpenInit(&ctx, EVP_aes_128_cbc(),in + encrypted_keys_offset + i*MULTI_ENCRYPTION_FORMAT_v001_ENCRYPTED_KEY_SIZE , MULTI_ENCRYPTION_FORMAT_v001_ENCRYPTED_KEY_SIZE, in+IV_offset, privateKey);
#ifdef GXS_SECURITY_DEBUG
std::cerr << " encrypted key at offset " << encrypted_keys_offset + i*MULTI_ENCRYPTION_FORMAT_v001_ENCRYPTED_KEY_SIZE << ": " << succeed << std::endl;
#endif
}
EVP_PKEY_free(privateKey) ;
@ -1060,7 +1070,9 @@ bool GxsSecurity::decrypt(uint8_t *& out, uint32_t & outlen, const uint8_t *in,
if(!succeed)
throw std::runtime_error("No matching key available.") ;
#ifdef GXS_SECURITY_DEBUG
std::cerr << " now decrypting with the matching key." << std::endl;
#endif
out = (uint8_t*)rs_malloc(encrypted_block_size) ;
@ -1079,7 +1091,9 @@ bool GxsSecurity::decrypt(uint8_t *& out, uint32_t & outlen, const uint8_t *in,
outlen += out_currOffset;
#ifdef GXS_SECURITY_DEBUG
std::cerr << " successfully decrypted block of size " << outlen << std::endl;
#endif
return true;
}
catch(std::exception& e)

View file

@ -211,7 +211,7 @@ class RsGcxs
virtual bool isLoaded(const RsGxsCircleId &circleId) = 0;
virtual bool loadCircle(const RsGxsCircleId &circleId) = 0;
virtual int canSend(const RsGxsCircleId &circleId, const RsPgpId &id) = 0;
virtual int canSend(const RsGxsCircleId &circleId, const RsPgpId &id,bool& should_encrypt) = 0;
virtual int canReceive(const RsGxsCircleId &circleId, const RsPgpId &id) = 0;
virtual bool recipients(const RsGxsCircleId &circleId, std::list<RsPgpId>& friendlist) = 0;
virtual bool recipients(const RsGxsCircleId &circleId, std::list<RsGxsId>& idlist) = 0;

View file

@ -279,6 +279,13 @@ static std::string nice_time_stamp(time_t now,time_t TS)
}
#endif
static const uint32_t RS_NXS_ITEM_ENCRYPTION_STATUS_UNKNOWN = 0x00 ;
static const uint32_t RS_NXS_ITEM_ENCRYPTION_STATUS_NO_ERROR = 0x01 ;
static const uint32_t RS_NXS_ITEM_ENCRYPTION_STATUS_CIRCLE_ERROR = 0x02 ;
static const uint32_t RS_NXS_ITEM_ENCRYPTION_STATUS_ENCRYPTION_ERROR = 0x03 ;
static const uint32_t RS_NXS_ITEM_ENCRYPTION_STATUS_SERIALISATION_ERROR = 0x04 ;
static const uint32_t RS_NXS_ITEM_ENCRYPTION_STATUS_GXS_KEY_MISSING = 0x05 ;
static std::ostream& gxsnetdebug(const RsPeerId& peer_id,const RsGxsGroupId& grp_id,uint32_t service_type)
{
static nullstream null ;
@ -1182,7 +1189,7 @@ void RsGxsNetService::locked_createTransactionFromPending(GrpRespPending* grpPen
}
void RsGxsNetService::locked_createTransactionFromPending(GrpCircleIdRequestVetting* grpPend)
bool RsGxsNetService::locked_createTransactionFromPending(GrpCircleIdRequestVetting* grpPend)
{
#ifdef NXS_NET_DEBUG_1
GXSNETDEBUG_P_(grpPend->mPeerId) << "locked_createTransactionFromPending(GrpCircleIdReq)" << std::endl;
@ -1193,6 +1200,7 @@ void RsGxsNetService::locked_createTransactionFromPending(GrpCircleIdRequestVett
for(; cit != grpPend->mGrpCircleV.end(); ++cit)
{
const GrpIdCircleVet& entry = *cit;
if(entry.mCleared)
{
#ifdef NXS_NET_DEBUG_1
@ -1206,6 +1214,26 @@ void RsGxsNetService::locked_createTransactionFromPending(GrpCircleIdRequestVett
gItem->transactionNumber = transN;
gItem->authorId = entry.mAuthorId;
// why it authorId not set here???
if(entry.mShouldEncrypt)
{
#ifdef NXS_NET_DEBUG_7
GXSNETDEBUG_PG(grpPend->mPeerId,entry.mGroupId) << " item for this grpId should be encrypted." << std::endl;
#endif
RsNxsItem *encrypted_item = NULL ;
uint32_t status = RS_NXS_ITEM_ENCRYPTION_STATUS_UNKNOWN ;
if(encryptSingleNxsItem(gItem, entry.mCircleId, encrypted_item,status))
{
itemL.push_back(encrypted_item) ;
delete gItem ;
}
#ifdef NXS_NET_DEBUG_7
else
GXSNETDEBUG_PG(grpPend->mPeerId,entry.mGroupId) << " Could not encrypt item for grpId " << entry.mGroupId << " for circle " << entry.mCircleId << ". Will try later. Adding to vetting list." << std::endl;
#endif
}
else
itemL.push_back(gItem);
}
#ifdef NXS_NET_DEBUG_1
@ -1216,9 +1244,11 @@ void RsGxsNetService::locked_createTransactionFromPending(GrpCircleIdRequestVett
if(!itemL.empty())
locked_pushGrpRespFromList(itemL, grpPend->mPeerId, transN);
return true ;
}
void RsGxsNetService::locked_createTransactionFromPending(MsgCircleIdsRequestVetting* msgPend)
bool RsGxsNetService::locked_createTransactionFromPending(MsgCircleIdsRequestVetting* msgPend)
{
std::vector<MsgIdCircleVet>::iterator vit = msgPend->mMsgs.begin();
std::list<RsNxsItem*> itemL;
@ -1236,13 +1266,33 @@ void RsGxsNetService::locked_createTransactionFromPending(MsgCircleIdsRequestVet
mItem->authorId = mic.mAuthorId;
mItem->PeerId(msgPend->mPeerId);
mItem->transactionNumber = transN;
itemL.push_back(mItem);
grp_id = msgPend->mGrpId ;
if(msgPend->mShouldEncrypt)
{
RsNxsItem *encrypted_item = NULL ;
uint32_t status = RS_NXS_ITEM_ENCRYPTION_STATUS_UNKNOWN ;
if(encryptSingleNxsItem(mItem,msgPend->mCircleId,encrypted_item,status))
{
itemL.push_back(encrypted_item) ;
delete mItem ;
}
else
{
std::cerr << "(EE) cannot encrypt Msg ids in circle-restriced response to grp " << msgPend->mGrpId << " for circle " << msgPend->mCircleId << std::endl;
return false ;
}
}
else
itemL.push_back(mItem);
}
if(!itemL.empty())
locked_pushMsgRespFromList(itemL, msgPend->mPeerId,grp_id, transN,msgPend->mCircleId);
locked_pushMsgRespFromList(itemL, msgPend->mPeerId,grp_id, transN);
return true ;
}
/*bool RsGxsNetService::locked_canReceive(const RsGxsGrpMetaData * const grpMeta
@ -2146,7 +2196,7 @@ void RsGxsNetService::processTransactions()
// Try to decrypt the items that need to be decrypted. This function returns true if the transaction is not encrypted.
if(decryptTransaction(tr))
if(processTransactionForDecryption(tr))
{
#ifdef NXS_NET_DEBUG_7
GXSNETDEBUG_P_(tr->mTransaction->PeerId()) << " successfully decrypted/processed transaction " << transN << ". Adding to completed list." << std::endl;
@ -3213,14 +3263,19 @@ void RsGxsNetService::runVetting()
{
GrpCircleIdRequestVetting* gcirv = static_cast<GrpCircleIdRequestVetting*>(gcv);
locked_createTransactionFromPending(gcirv);
if(!locked_createTransactionFromPending(gcirv))
{
++vit2 ;
continue ;
}
}
else if(gcv->getType() == GrpCircleVetting::MSG_ID_SEND_PEND)
{
MsgCircleIdsRequestVetting* mcirv = static_cast<MsgCircleIdsRequestVetting*>(gcv);
if(mcirv->cleared())
locked_createTransactionFromPending(mcirv);
if(!locked_createTransactionFromPending(mcirv))
continue ; // keep it in the list for retry
}
else
{
@ -3282,6 +3337,31 @@ void RsGxsNetService::locked_genSendMsgsTransaction(NxsTransaction* tr)
}
}
#ifdef CODE_TO_ENCRYPT_MESSAGE_DATA
// now if transaction is limited to an external group, encrypt it for members of the group.
RsGxsCircleId encryption_circle ;
std::map<RsGxsGroupId, RsGxsGrpMetaData*> grp;
grp[grpId] = NULL ;
mDataStore->retrieveGxsGrpMetaData(grp);
RsGxsGrpMetaData *grpMeta = grp[grpId] ;
if(grpMeta == NULL)
{
std::cerr << "(EE) cannot retrieve group meta data for message transaction " << tr->mTransaction->transactionNumber << std::endl;
return ;
}
encryption_circle = grpMeta->mCircleId ;
delete grpMeta ;
grp.clear() ;
#ifdef NXS_NET_DEBUG_7
GXSNETDEBUG_PG(tr->mTransaction->PeerId(),grpId) << " Msg transaction items will be encrypted for circle " << std::endl;
#endif
#endif
mDataStore->retrieveNxsMsgs(msgIds, msgs, false, false);
NxsTransaction* newTr = new NxsTransaction();
@ -3313,6 +3393,7 @@ void RsGxsNetService::locked_genSendMsgsTransaction(NxsTransaction* tr)
std::cerr << "(WW) message with ID " << msg->msgId << " in group " << msg->grpId << " exceeds size limit of " << MAX_ALLOWED_GXS_MESSAGE_SIZE << " bytes. Actual size is " << msg->msg.bin_len << " bytes. Message will be truncated and rejected at client." << std::endl;
msg->msg.bin_len = 1 ; // arbitrary small size, but not 0. No need to send the data since it's going to be rejected.
}
#ifdef NXS_FRAG
MsgFragments fragments;
fragmentMsg(*msg, fragments);
@ -3327,6 +3408,7 @@ void RsGxsNetService::locked_genSendMsgsTransaction(NxsTransaction* tr)
msgSize++;
}
#else
msg->count = 1; // only one piece. This is to keep compatibility if we ever implement fragmenting in the future.
msg->pos = 0;
@ -3334,6 +3416,31 @@ void RsGxsNetService::locked_genSendMsgsTransaction(NxsTransaction* tr)
msgSize++;
#endif
#ifdef CODE_TO_ENCRYPT_MESSAGE_DATA
// encrypt
if(!encryption_circle.isNull())
{
uint32_t status = RS_NXS_ITEM_ENCRYPTION_STATUS_UNKNOWN ;
RsNxsEncryptedDataItem encrypted_msg_item = NULL ;
if(encryptSingleNxsItem(msg,encryption_circle,encrypted_msg_item,status))
{
newTr->mItems.push_back(msg);
delete msg ;
}
else
{
}
}
else
{
newTr->mItems.push_back(msg);
msgSize++;
}
#endif
}
}
@ -3342,22 +3449,6 @@ void RsGxsNetService::locked_genSendMsgsTransaction(NxsTransaction* tr)
return;
}
// now if transaction is limited to an external group, encrypt it for members of the group.
std::map<RsGxsGroupId, RsGxsGrpMetaData*> grp;
grp[grpId] = NULL ;
mDataStore->retrieveGxsGrpMetaData(grp);
RsGxsGrpMetaData *grpMeta = grp[grpId] ;
if(grpMeta != NULL)
{
newTr->destination_circle = grpMeta->mCircleId ;
delete grpMeta ;
grp.clear() ;
}
// now send a transaction item and store the transaction data
uint32_t updateTS = 0;
@ -3384,8 +3475,6 @@ void RsGxsNetService::locked_genSendMsgsTransaction(NxsTransaction* tr)
#endif
ntr->PeerId(tr->mTransaction->PeerId());
// Encryption will happen here if needed.
if(locked_addTransaction(newTr))
sendItem(ntr);
else
@ -3418,24 +3507,105 @@ bool RsGxsNetService::locked_addTransaction(NxsTransaction* tr)
return false;
}
if(!tr->destination_circle.isNull())
{
#ifdef NXS_NET_DEBUG_7
GXSNETDEBUG_P_(peer) << " Calling transaction encryption on transaction " << transN << " for circle " << tr->destination_circle << std::endl;
#endif
if(!encryptTransaction(tr))
return false ;
}
#ifdef NXS_NET_DEBUG_7
else
GXSNETDEBUG_P_(peer) << " Transaction " << transN << " sent in clear since no circle restriction found!" << std::endl;
#endif
transMap[transN] = tr;
return true;
}
// Turns a single RsNxsItem into an encrypted one, suitable for the supplied destination circle.
// Returns false when the keys are not loaded. Question to solve: what do we do if we miss some keys??
// We should probably send anyway.
bool RsGxsNetService::encryptSingleNxsItem(RsNxsItem *item, const RsGxsCircleId& destination_circle, RsNxsItem *&encrypted_item, uint32_t& status)
{
encrypted_item = NULL ;
status = RS_NXS_ITEM_ENCRYPTION_STATUS_UNKNOWN ;
#ifdef NXS_NET_DEBUG_7
GXSNETDEBUG_P_ (item->PeerId()) << "Service " << std::hex << ((mServiceInfo.mServiceType >> 8)& 0xffff) << std::dec << " - Encrypting single item for peer " << item->PeerId() << ", for circle ID " << destination_circle << std::endl;
#endif
std::cerr << "RsGxsNetService::encryptSingleNxsItem()" << std::endl;
// 1 - Find out the list of GXS ids to encrypt for
// We could do smarter things (like see if the peer_id owns one of the circle's identities
// but for now we aim at the simplest solution: encrypt for all identities in the circle.
std::list<RsGxsId> recipients ;
if(!mCircles->recipients(destination_circle,recipients))
{
std::cerr << " (EE) Cannot encrypt transaction: recipients list not available. Should re-try later." << std::endl;
status = RS_NXS_ITEM_ENCRYPTION_STATUS_CIRCLE_ERROR ;
return false ;
}
#ifdef NXS_NET_DEBUG_7
GXSNETDEBUG_P_ (item->PeerId()) << " Dest Ids: " << std::endl;
#endif
std::vector<RsTlvSecurityKey> recipient_keys ;
for(std::list<RsGxsId>::const_iterator it(recipients.begin());it!=recipients.end();++it)
{
RsTlvSecurityKey pkey ;
if(!mGixs->getKey(*it,pkey))
{
std::cerr << " (EE) Cannot retrieve public key " << *it << " for circle encryption. Should retry later?" << std::endl;
// we should probably request the key?
status = RS_NXS_ITEM_ENCRYPTION_STATUS_GXS_KEY_MISSING ;
continue ;
}
#ifdef NXS_NET_DEBUG_7
GXSNETDEBUG_P_ (item->PeerId()) << " added key " << *it << std::endl;
#endif
recipient_keys.push_back(pkey) ;
}
// 2 - call GXSSecurity to make a header item that encrypts for the given list of peers.
#ifdef NXS_NET_DEBUG_7
GXSNETDEBUG_P_ (item->PeerId()) << " Encrypting..." << std::endl;
#endif
uint32_t size = item->serial_size() ;
RsTemporaryMemory tempmem( size ) ;
if(!item->serialise(tempmem,size))
{
std::cerr << " (EE) Cannot serialise item. Something went wrong." << std::endl;
status = RS_NXS_ITEM_ENCRYPTION_STATUS_SERIALISATION_ERROR ;
return false ;
}
unsigned char *encrypted_data = NULL ;
uint32_t encrypted_len = 0 ;
if(!GxsSecurity::encrypt(encrypted_data, encrypted_len,tempmem,size,recipient_keys))
{
std::cerr << " (EE) Cannot multi-encrypt item. Something went wrong." << std::endl;
status = RS_NXS_ITEM_ENCRYPTION_STATUS_ENCRYPTION_ERROR ;
return false ;
}
RsNxsEncryptedDataItem *enc_item = new RsNxsEncryptedDataItem(mServType) ;
enc_item->encrypted_data.bin_len = encrypted_len ;
enc_item->encrypted_data.bin_data = encrypted_data ;
// also copy all the important data.
enc_item->transactionNumber = item->transactionNumber ;
enc_item->PeerId(item->PeerId()) ;
encrypted_item = enc_item ;
#ifdef NXS_NET_DEBUG_7
GXSNETDEBUG_P_(item->PeerId()) << " encrypted item of size " << encrypted_len << std::endl;
#endif
status = RS_NXS_ITEM_ENCRYPTION_STATUS_NO_ERROR ;
return true ;
}
#ifdef TO_REMOVE
bool RsGxsNetService::encryptTransaction(NxsTransaction *tr)
{
#ifdef NXS_NET_DEBUG_7
@ -3585,8 +3755,8 @@ bool RsGxsNetService::encryptTransaction(NxsTransaction *tr)
RsNxsEncryptedDataItem *enc_item = new RsNxsEncryptedDataItem(mServType) ;
enc_item->aes_encrypted_data.bin_len = encrypted_len ;
enc_item->aes_encrypted_data.bin_data = encrypted_data ;
enc_item->encrypted_data.bin_len = encrypted_len ;
enc_item->encrypted_data.bin_data = encrypted_data ;
enc_item->transactionNumber = (*it)->transactionNumber ;
enc_item->PeerId((*it)->PeerId()) ;
@ -3603,117 +3773,19 @@ bool RsGxsNetService::encryptTransaction(NxsTransaction *tr)
return true ;
}
#endif
// Tries to decrypt the transaction. First load the keys and process all items.
// If keys are loaded, encrypted items that cannot be decrypted are discarded.
// Otherwise the transaction is untouched for retry later.
bool RsGxsNetService::decryptTransaction(NxsTransaction *tr)
bool RsGxsNetService::processTransactionForDecryption(NxsTransaction *tr)
{
#ifdef NXS_NET_DEBUG_7
RsPeerId peerId = tr->mTransaction->PeerId() ;
GXSNETDEBUG_P_(peerId) << "RsGxsNetService::decryptTransaction()" << std::endl;
GXSNETDEBUG_P_(peerId) << " Circle Id: " << tr->destination_circle << std::endl;
#endif
#ifdef USE_MULTI_ENCRYPTION_WITH_SESSION_KEY
// 1 - Checks that the transaction is encrypted. It should contain
// one packet with an encrypted session key for the group,
// and as many encrypted data items as necessary.
RsNxsSessionKeyItem *esk = NULL;
for(std::list<RsNxsItem*>::const_iterator it(tr->mItems.begin());it!=tr->mItems.end();++it)
if(NULL != (esk = dynamic_cast<RsNxsSessionKeyItem*>(*it)))
break ;
if(esk == NULL)
{
#ifdef NXS_NET_DEBUG_7
GXSNETDEBUG_P_(peerId) << " (II) nothing to decrypt. No session key packet in this transaction. Transaction is not encrypted" << std::endl;
#endif
return true ;
}
// 2 - Try to decrypt the session key. If not, return false. That probably means
// we don't own that identity.
GxsSecurity::MultiEncryptionContext muctx ;
RsGxsId private_key_id ;
RsTlvBinaryData ek ;
RsTlvSecurityKey private_key;
bool found = false ;
for(std::map<RsGxsId,RsTlvBinaryData>::const_iterator it(esk->encrypted_session_keys.begin());it!=esk->encrypted_session_keys.end();++it)
if(mGixs->havePrivateKey(it->first))
{
found = true ;
private_key_id = it->first ;
ek = it->second ;
if(!mGixs->getPrivateKey(private_key_id,private_key))
{
std::cerr << " (EE) Cannot find private key to decrypt incoming transaction, for ID " << it->first << ". This is a bug since the key is supposed ot be here." << std::endl;
return false;
}
#ifdef NXS_NET_DEBUG_7
GXSNETDEBUG_P_(peerId) << " found appropriate private key to decrypt session key: " << it->first << std::endl;
#endif
break ;
}
if(!found)
{
std::cerr << " (EE) no private key for this encrypted transaction. Cannot decrypt!" << std::endl;
return false ;
}
if(!GxsSecurity::initDecryption(muctx,private_key,esk->iv,EVP_MAX_IV_LENGTH,(unsigned char*)ek.bin_data,ek.bin_len))
{
std::cerr << " (EE) cannot decrypt transaction. initDecryption() failed." << std::endl;
return false ;
}
#ifdef NXS_NET_DEBUG_7
GXSNETDEBUG_P_(peerId) << " Session key successfully decrypted, with length " << ek.bin_len << std::endl;
GXSNETDEBUG_P_(peerId) << " Now, decrypting transaction items..." << std::endl;
#endif
// 3 - Using session key, decrypt all packets, by calling GXSSecurity.
std::list<RsNxsItem*> decrypted_items ;
RsNxsEncryptedDataItem *encrypted_item ;
RsNxsSerialiser serial(mServType) ;
for(std::list<RsNxsItem*>::const_iterator it(tr->mItems.begin());it!=tr->mItems.end();++it)
if(NULL != (encrypted_item = dynamic_cast<RsNxsEncryptedDataItem*>(*it)))
{
unsigned char *tempmem;
uint32_t tempmemsize ;
if(!GxsSecurity::decrypt(tempmem,tempmemsize,(uint8_t*)encrypted_item->aes_encrypted_data.bin_data, encrypted_item->aes_encrypted_data.bin_len,muctx))
{
std::cerr << " (EE) Cannot decrypt item. Something went wrong. Skipping this item." << std::endl;
continue ;
}
RsItem *ditem = serial.deserialise(tempmem,&tempmemsize) ;
#ifdef NXS_NET_DEBUG_7
GXSNETDEBUG_P_(peerId) << " Decrypted an item of type " << std::hex << ditem->PacketId() << std::dec << std::endl;
#endif
RsNxsItem *nxsi = dynamic_cast<RsNxsItem*>(ditem) ;
if(nxsi != NULL)
decrypted_items.push_back(nxsi) ;
else
{
std::cerr << " (EE) decrypted an item of unknown type!" << std::endl;
}
free(tempmem) ;
}
#else
std::list<RsNxsItem*> decrypted_items ;
std::vector<RsTlvSecurityKey> private_keys ;
@ -3770,7 +3842,7 @@ bool RsGxsNetService::decryptTransaction(NxsTransaction *tr)
std::cerr << " Trying to decrypt item..." ;
if(!GxsSecurity::decrypt(decrypted_mem,decrypted_len, (uint8_t*)encrypted_item->aes_encrypted_data.bin_data,encrypted_item->aes_encrypted_data.bin_len,private_keys))
if(!GxsSecurity::decrypt(decrypted_mem,decrypted_len, (uint8_t*)encrypted_item->encrypted_data.bin_data,encrypted_item->encrypted_data.bin_len,private_keys))
{
std::cerr << "Failed! Cannot decrypt this item." << std::endl;
decrypted_mem = NULL ; // for safety
@ -3807,7 +3879,6 @@ bool RsGxsNetService::decryptTransaction(NxsTransaction *tr)
delete encrypted_item ;
}
#endif
#ifdef NXS_NET_DEBUG_7
GXSNETDEBUG_P_(peerId) << " Decryption successful: replacing items with clear items" << std::endl;
@ -3947,7 +4018,9 @@ void RsGxsNetService::handleRecvSyncGroup(RsNxsSyncGrpReqItem *item)
// or if you need to add to the holding
// pen for peer to be vetted
if(canSendGrpId(peer, *grpMeta, toVet))
bool should_encrypt = false ;
if(canSendGrpId(peer, *grpMeta, toVet,should_encrypt))
{
RsNxsSyncGrpItem* gItem = new RsNxsSyncGrpItem(mServType);
gItem->flag = RsNxsSyncGrpItem::FLAG_RESPONSE;
@ -3956,7 +4029,38 @@ void RsGxsNetService::handleRecvSyncGroup(RsNxsSyncGrpReqItem *item)
gItem->authorId = grpMeta->mAuthorId;
gItem->PeerId(peer);
gItem->transactionNumber = transN;
if(should_encrypt)
{
#ifdef NXS_NET_DEBUG_7
GXSNETDEBUG_PG(peer,mit->first) << " item for this grpId should be encrypted." << std::endl;
#endif
RsNxsItem *encrypted_item = NULL ;
uint32_t status = RS_NXS_ITEM_ENCRYPTION_STATUS_UNKNOWN ;
if(encryptSingleNxsItem(gItem, grpMeta->mCircleId, encrypted_item,status))
{
itemL.push_back(encrypted_item) ;
delete gItem ;
}
else
{
switch(status)
{
case RS_NXS_ITEM_ENCRYPTION_STATUS_CIRCLE_ERROR:
case RS_NXS_ITEM_ENCRYPTION_STATUS_GXS_KEY_MISSING: toVet.push_back(GrpIdCircleVet(grpMeta->mGroupId, grpMeta->mCircleId, grpMeta->mAuthorId));
#ifdef NXS_NET_DEBUG_7
GXSNETDEBUG_PG(peer,mit->first) << " Could not encrypt item for grpId " << grpMeta->mGroupId << " for circle " << grpMeta->mCircleId << ". Will try later. Adding to vetting list." << std::endl;
#endif
break ;
default:
std::cerr << " Could not encrypt item for grpId " << grpMeta->mGroupId << " for circle " << grpMeta->mCircleId << ". Not sending it." << std::endl;
}
}
}
else
itemL.push_back(gItem);
#ifdef NXS_NET_DEBUG_0
GXSNETDEBUG_PG(peer,mit->first) << " sending item for Grp " << mit->first << " name=" << grpMeta->mGroupName << ", publishTS=" << std::dec<< time(NULL) - mit->second->mPublishTs << " secs ago to peer ID " << peer << std::endl;
#endif
@ -3965,9 +4069,7 @@ void RsGxsNetService::handleRecvSyncGroup(RsNxsSyncGrpReqItem *item)
}
if(!toVet.empty())
{
mPendingCircleVets.push_back(new GrpCircleIdRequestVetting(mCircles, mPgpUtils, toVet, peer));
}
#ifdef NXS_NET_DEBUG_0
GXSNETDEBUG_P_(peer) << " final list sent (after vetting): " << itemL.size() << " elements." << std::endl;
@ -3979,7 +4081,7 @@ void RsGxsNetService::handleRecvSyncGroup(RsNxsSyncGrpReqItem *item)
bool RsGxsNetService::canSendGrpId(const RsPeerId& sslId, RsGxsGrpMetaData& grpMeta, std::vector<GrpIdCircleVet>& toVet)
bool RsGxsNetService::canSendGrpId(const RsPeerId& sslId, RsGxsGrpMetaData& grpMeta, std::vector<GrpIdCircleVet>& toVet, bool& should_encrypt)
{
#ifdef NXS_NET_DEBUG_4
GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << "RsGxsNetService::canSendGrpId()"<< std::endl;
@ -4008,6 +4110,7 @@ bool RsGxsNetService::canSendGrpId(const RsPeerId& sslId, RsGxsGrpMetaData& grpM
#ifdef NXS_NET_DEBUG_4
GXSNETDEBUG_PG(sslId,grpMeta.mGroupId)<< " EXTERNAL_CIRCLE, will be sent encrypted."<< std::endl;
#endif
should_encrypt = true ;
return true ;
#ifdef TO_BE_REMOVED_OLD_VETTING_FOR_EXTERNAL_CIRCLES
@ -4067,7 +4170,9 @@ bool RsGxsNetService::canSendGrpId(const RsPeerId& sslId, RsGxsGrpMetaData& grpM
GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " circle Loaded - checking mCircles->canSend" << std::endl;
#endif
const RsPgpId& pgpId = mPgpUtils->getPGPId(sslId);
bool res = mCircles->canSend(internalCircleId, pgpId);
bool should_encrypt = false ;
bool res = mCircles->canSend(internalCircleId, pgpId,should_encrypt);
#ifdef NXS_NET_DEBUG_4
GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " answer is: " << res << std::endl;
#endif
@ -4135,7 +4240,6 @@ bool RsGxsNetService::checkCanRecvMsgFromPeer(const RsPeerId& sslId, const RsGxs
if(circleType == GXS_CIRCLE_TYPE_EXTERNAL)
{
#warning Here we can keep a test based on whether we are in the circle or not. Returning true also works but the transaction might turn out to be useless
#ifdef NXS_NET_DEBUG_4
GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " Circle type: EXTERNAL => returning true. Msgs will be encrypted." << std::endl;
#endif
@ -4192,7 +4296,8 @@ bool RsGxsNetService::checkCanRecvMsgFromPeer(const RsPeerId& sslId, const RsGxs
GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " circle Loaded - checking mCircles->canSend" << std::endl;
#endif
const RsPgpId& pgpId = mPgpUtils->getPGPId(sslId);
return mCircles->canSend(internalCircleId, pgpId);
bool should_encrypt ;
return mCircles->canSend(internalCircleId, pgpId,should_encrypt);
}
else
mCircles->loadCircle(internalCircleId); // request for next pass
@ -4337,13 +4442,30 @@ void RsGxsNetService::handleRecvSyncMessage(RsNxsSyncMsgReqItem *item)
mItem->authorId = m->mAuthorId;
mItem->PeerId(peer);
mItem->transactionNumber = transN;
itemL.push_back(mItem);
#ifdef NXS_NET_DEBUG_0
if(!should_encrypt_to_this_circle_id.isNull())
{
#ifdef NXS_NET_DEBUG_7
GXSNETDEBUG_PG(item->PeerId(),item->grpId) << " sending info item for msg id " << mItem->msgId << ". Transaction will be encrypted for group " << should_encrypt_to_this_circle_id << std::endl;
else
GXSNETDEBUG_PG(item->PeerId(),item->grpId) << " sending info item for msg id " << mItem->msgId ;
#endif
RsNxsItem *encrypted_item = NULL ;
uint32_t status = RS_NXS_ITEM_ENCRYPTION_STATUS_UNKNOWN ;
if(encryptSingleNxsItem(mItem, grpMeta->mCircleId, encrypted_item,status))
{
itemL.push_back(encrypted_item) ;
delete mItem ;
}
else
std::cerr << " (EE) Cannot encrypt msg meta data. MsgId=" << mItem->msgId << ", grpId=" << mItem->grpId << ", circleId=" << should_encrypt_to_this_circle_id << std::endl;
}
else
{
#ifdef NXS_NET_DEBUG_7
GXSNETDEBUG_PG(item->PeerId(),item->grpId) << " sending info item for msg id " << mItem->msgId << " in clear." << std::endl;
#endif
itemL.push_back(mItem);
}
}
if(!itemL.empty())
@ -4351,7 +4473,7 @@ void RsGxsNetService::handleRecvSyncMessage(RsNxsSyncMsgReqItem *item)
#ifdef NXS_NET_DEBUG_0
GXSNETDEBUG_PG(item->PeerId(),item->grpId) << " sending final msg info list of " << itemL.size() << " items." << std::endl;
#endif
locked_pushMsgRespFromList(itemL, peer, item->grpId,transN,should_encrypt_to_this_circle_id);
locked_pushMsgRespFromList(itemL, peer, item->grpId,transN);
}
#ifdef NXS_NET_DEBUG_0
else
@ -4369,7 +4491,7 @@ void RsGxsNetService::handleRecvSyncMessage(RsNxsSyncMsgReqItem *item)
delete *vit;
}
void RsGxsNetService::locked_pushMsgRespFromList(std::list<RsNxsItem*>& itemL, const RsPeerId& sslId, const RsGxsGroupId& grp_id,const uint32_t& transN,const RsGxsCircleId& destination_circle)
void RsGxsNetService::locked_pushMsgRespFromList(std::list<RsNxsItem*>& itemL, const RsPeerId& sslId, const RsGxsGroupId& grp_id,const uint32_t& transN)
{
#ifdef NXS_NET_DEBUG_1
GXSNETDEBUG_PG(sslId,grp_id) << "locked_pushMsgResponseFromList()" << std::endl;
@ -4392,7 +4514,6 @@ void RsGxsNetService::locked_pushMsgRespFromList(std::list<RsNxsItem*>& itemL, c
tr->mTransaction = new RsNxsTransacItem(*trItem);
tr->mTransaction->PeerId(mOwnId);
tr->mTimeOut = time(NULL) + mTransactionTimeOut;
tr->destination_circle = destination_circle;
ServerMsgMap::const_iterator cit = mServerMsgUpdateMap.find(grp_id);
@ -4508,7 +4629,12 @@ bool RsGxsNetService::canSendMsgIds(const std::vector<RsGxsMsgMetaData*>& msgMet
if(mCircles->isLoaded(internalCircleId))
{
const RsPgpId& pgpId = mPgpUtils->getPGPId(sslId);
bool res= mCircles->canSend(internalCircleId, pgpId);
bool should_encrypt = false ;
bool res= mCircles->canSend(internalCircleId, pgpId,should_encrypt);
if(should_encrypt)
std::cerr << "(EE) inconsistent response: vetting requests to encrypt circle of type YOUR_EYES_ONLY" << std::endl;
#ifdef NXS_NET_DEBUG_4
GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " Answer from circle::canSend(): " << res << std::endl;
#endif

View file

@ -349,22 +349,20 @@ private:
* @param toVet groupid/peer to vet are stored here if their circle id is not cached
* @return false, if you cannot send to this peer, true otherwise
*/
bool canSendGrpId(const RsPeerId& sslId, RsGxsGrpMetaData& grpMeta, std::vector<GrpIdCircleVet>& toVet);
bool canSendGrpId(const RsPeerId& sslId, RsGxsGrpMetaData& grpMeta, std::vector<GrpIdCircleVet>& toVet, bool &should_encrypt);
bool canSendMsgIds(const std::vector<RsGxsMsgMetaData*>& msgMetas, const RsGxsGrpMetaData&, const RsPeerId& sslId, RsGxsCircleId &should_encrypt_id);
bool checkCanRecvMsgFromPeer(const RsPeerId& sslId, const RsGxsGrpMetaData& meta);
void locked_createTransactionFromPending(MsgRespPending* grpPend);
void locked_createTransactionFromPending(GrpRespPending* msgPend);
void locked_createTransactionFromPending(GrpCircleIdRequestVetting* grpPend);
void locked_createTransactionFromPending(MsgCircleIdsRequestVetting* grpPend);
bool locked_createTransactionFromPending(GrpCircleIdRequestVetting* grpPend) ;
bool locked_createTransactionFromPending(MsgCircleIdsRequestVetting* grpPend) ;
void locked_pushGrpTransactionFromList(std::list<RsNxsItem*>& reqList, const RsPeerId& peerId, const uint32_t& transN); // forms a grp list request
void locked_pushMsgTransactionFromList(std::list<RsNxsItem*>& reqList, const RsPeerId& peerId, const uint32_t& transN); // forms a msg list request
void locked_pushGrpRespFromList(std::list<RsNxsItem*>& respList, const RsPeerId& peer, const uint32_t& transN);
void locked_pushMsgRespFromList(std::list<RsNxsItem*>& itemL, const RsPeerId& sslId, const RsGxsGroupId &grp_id, const uint32_t& transN,const RsGxsCircleId& destination_circle);
void locked_pushMsgRespFromList(std::list<RsNxsItem*>& itemL, const RsPeerId& sslId, const RsGxsGroupId &grp_id, const uint32_t& transN);
void syncWithPeers();
void syncGrpStatistics();
@ -454,8 +452,11 @@ private:
/*!
* encrypts/decrypts the transaction for the destination circle id.
*/
#ifdef TO_REMOVE
bool encryptTransaction(NxsTransaction *tr);
bool decryptTransaction(NxsTransaction *tr); // return false when the keys are not loaded => need retry later
#endif
bool encryptSingleNxsItem(RsNxsItem *item, const RsGxsCircleId& destination_circle, RsNxsItem *& encrypted_item, uint32_t &status) ;
bool processTransactionForDecryption(NxsTransaction *tr); // return false when the keys are not loaded => need retry later
void cleanRejectedMessages();
void processObserverNotifications();

View file

@ -222,12 +222,12 @@ bool GrpCircleVetting::expired()
{
return time(NULL) > (mTimeStamp + EXPIRY_PERIOD_OFFSET);
}
bool GrpCircleVetting::canSend(const SSLIdType& peerId, const RsGxsCircleId& circleId)
bool GrpCircleVetting::canSend(const SSLIdType& peerId, const RsGxsCircleId& circleId,bool& should_encrypt)
{
if(mCircles->isLoaded(circleId))
{
const RsPgpId& pgpId = mPgpUtils->getPGPId(peerId);
return mCircles->canSend(circleId, pgpId);
return mCircles->canSend(circleId, pgpId,should_encrypt);
}
mCircles->loadCircle(circleId);
@ -250,7 +250,7 @@ bool GrpCircleIdRequestVetting::cleared()
if(!gic.mCleared)
{
if(canSend(mPeerId, gic.mCircleId))
if(canSend(mPeerId, gic.mCircleId,gic.mShouldEncrypt))
{
gic.mCleared = true;
count++;
@ -285,7 +285,7 @@ MsgCircleIdsRequestVetting::MsgCircleIdsRequestVetting(RsGcxs* const circles,
bool MsgCircleIdsRequestVetting::cleared()
{
return canSend(mPeerId, mCircleId);
return canSend(mPeerId, mCircleId, mShouldEncrypt);
}

View file

@ -68,8 +68,6 @@ public:
*/
RsNxsTransacItem* mTransaction;
std::list<RsNxsItem*> mItems; // items received or sent
RsGxsCircleId destination_circle;
};
/*!
@ -216,7 +214,9 @@ public:
RsGxsGroupId mGroupId;
RsGxsCircleId mCircleId;
RsGxsId mAuthorId;
bool mCleared;
bool mShouldEncrypt;
};
class MsgIdCircleVet
@ -254,7 +254,7 @@ public:
virtual bool cleared() = 0;
protected:
bool canSend(const RsPeerId& peerId, const RsGxsCircleId& circleId);
bool canSend(const RsPeerId& peerId, const RsGxsCircleId& circleId, bool& should_encrypt);
private:
@ -288,6 +288,7 @@ public:
RsGxsGroupId mGrpId;
RsPeerId mPeerId;
RsGxsCircleId mCircleId;
bool mShouldEncrypt;
};

View file

@ -463,7 +463,7 @@ bool RsNxsEncryptedDataItem::serialise(void *data, uint32_t& size) const
return false ;
ok &= setRawUInt32(data, size, &offset, transactionNumber);
ok &= aes_encrypted_data.SetTlv(data, size, &offset) ;
ok &= encrypted_data.SetTlv(data, size, &offset) ;
if(offset != tlvsize)
{
@ -897,9 +897,9 @@ RsNxsEncryptedDataItem *RsNxsSerialiser::deserialNxsEncryptedDataItem(void* da
RsNxsEncryptedDataItem* item = new RsNxsEncryptedDataItem(SERVICE_TYPE);
ok &= getRawUInt32(data, *size, &offset, &(item->transactionNumber));
item->aes_encrypted_data.tlvtype = TLV_TYPE_BIN_ENCRYPTED ;
item->encrypted_data.tlvtype = TLV_TYPE_BIN_ENCRYPTED ;
ok &= item->aes_encrypted_data.GetTlv(data,*size,&offset) ;
ok &= item->encrypted_data.GetTlv(data,*size,&offset) ;
if (offset != *size)
{
@ -1046,7 +1046,7 @@ uint32_t RsNxsEncryptedDataItem::serial_size() const
uint32_t s = 8; // header size
s += 4; // transaction number
s += aes_encrypted_data.TlvSize() ;
s += encrypted_data.TlvSize() ;
return s;
}
@ -1127,7 +1127,7 @@ void RsNxsTransacItem::clear(){
transactionNumber = 0;
}
void RsNxsEncryptedDataItem::clear(){
aes_encrypted_data.TlvClear() ;
encrypted_data.TlvClear() ;
}
void RsNxsSessionKeyItem::clear()
{
@ -1337,9 +1337,9 @@ std::ostream& RsNxsEncryptedDataItem::print(std::ostream &out, uint16_t indent)
{
printRsItemBase(out, "RsNxsEncryptedDataItem", indent);
out << " encrypted data: " << RsUtil::BinToHex((char*)aes_encrypted_data.bin_data,std::min(50u,aes_encrypted_data.bin_len)) ;
out << " encrypted data: " << RsUtil::BinToHex((char*)encrypted_data.bin_data,std::min(50u,encrypted_data.bin_len)) ;
if(aes_encrypted_data.bin_len > 50u)
if(encrypted_data.bin_len > 50u)
out << "..." ;
out << std::endl;

View file

@ -277,9 +277,9 @@ class RsNxsEncryptedDataItem : public RsNxsItem
public:
RsNxsEncryptedDataItem(uint16_t servtype) : RsNxsItem(servtype, RS_PKT_SUBTYPE_NXS_ENCRYPTED_DATA_ITEM),aes_encrypted_data(servtype)
RsNxsEncryptedDataItem(uint16_t servtype) : RsNxsItem(servtype, RS_PKT_SUBTYPE_NXS_ENCRYPTED_DATA_ITEM),encrypted_data(servtype)
{
aes_encrypted_data.tlvtype = TLV_TYPE_BIN_ENCRYPTED ;
encrypted_data.tlvtype = TLV_TYPE_BIN_ENCRYPTED ;
clear();
}
virtual ~RsNxsEncryptedDataItem() {}
@ -292,7 +292,7 @@ public:
/// grpId of grp held by sending peer
///
RsTlvBinaryData aes_encrypted_data ;
RsTlvBinaryData encrypted_data ;
};

View file

@ -341,16 +341,17 @@ bool p3GxsCircles::loadCircle(const RsGxsCircleId &circleId)
return cache_request_load(circleId);
}
int p3GxsCircles::canSend(const RsGxsCircleId &circleId, const RsPgpId &id)
int p3GxsCircles::canSend(const RsGxsCircleId &circleId, const RsPgpId &id, bool& should_encrypt)
{
RsStackMutex stack(mCircleMtx); /********** STACK LOCKED MTX ******/
if (mCircleCache.is_cached(circleId))
{
RsGxsCircleCache &data = mCircleCache.ref(circleId);
should_encrypt = (data.mCircleType == GXS_CIRCLE_TYPE_EXTERNAL);
if (data.isAllowedPeer(id))
{
return 1;
}
return 0;
}
return -1;

View file

@ -175,7 +175,7 @@ virtual RsServiceInfo getServiceInfo();
virtual bool isLoaded(const RsGxsCircleId &circleId);
virtual bool loadCircle(const RsGxsCircleId &circleId);
virtual int canSend(const RsGxsCircleId &circleId, const RsPgpId &id);
virtual int canSend(const RsGxsCircleId &circleId, const RsPgpId &id, bool &should_encrypt);
virtual int canReceive(const RsGxsCircleId &circleId, const RsPgpId &id);
virtual bool recipients(const RsGxsCircleId &circleId, std::list<RsPgpId> &friendlist);
virtual bool recipients(const RsGxsCircleId &circleId, std::list<RsGxsId> &gxs_ids);