modifications to item encryption so as to match APIs

This commit is contained in:
csoler 2015-10-22 20:24:36 -04:00
parent 1c12178874
commit 21c31fb446
11 changed files with 230 additions and 106 deletions

View File

@ -414,6 +414,7 @@ bool GxsSecurity::initEncryption(GxsSecurity::MultiEncryptionContext& encryption
encryption_context.ek = new unsigned char *[keys.size()] ;
encryption_context.ekl = new int [keys.size()] ;
encryption_context.ids.resize(keys.size()) ;
EVP_PKEY **pubk = new EVP_PKEY *[keys.size()] ;
memset(pubk,0,keys.size()*sizeof(EVP_PKEY *)) ;
@ -437,6 +438,7 @@ bool GxsSecurity::initEncryption(GxsSecurity::MultiEncryptionContext& encryption
encryption_context.ek [i] = (unsigned char*)malloc(max_evp_key_size);
encryption_context.ekl[i] = max_evp_key_size ;
encryption_context.ids[i] = keys[i] ;
}
EVP_CIPHER_CTX_init(&encryption_context.ctx);

View File

@ -53,22 +53,35 @@ class GxsSecurity
class MultiEncryptionContext
{
public:
MultiEncryptionContext() { ekl = NULL; ek=NULL; nk=0 ; }
MultiEncryptionContext() { clear() ;}
~MultiEncryptionContext() { clear() ;}
void clear() ;
void clear()
{
for(uint32_t i=0;i<ids.size();++i)
free(ek[i]) ;
free(ekl) ;
free(ek) ;
ekl = NULL ;
ek = NULL ;
ids.clear() ;
}
// The functions below give access to the encrypted symmetric key to be used.
//
int n_encrypted_keys() const ;
RsGxsId encrypted_key_id (int i) ;
unsigned char *encrypted_key_data(int i) ;
int encrypted_key_size(int i) ;
int n_encrypted_keys() const { return ids.size();}
RsGxsId encrypted_key_id (int i) const { return ids[i];}
unsigned char *encrypted_key_data(int i) const { return ek[i];}
int encrypted_key_size(int i) { return ekl[i] ; }
const unsigned char *initialisation_vector() const { return iv ; }
protected:
std::vector<RsGxsId> ids; // array of destination ids
int *ekl ; // array of encrypted keys length
unsigned char **ek ; // array of encrypted keys
int nk ; // number of encrypted keys
EVP_CIPHER_CTX ctx; // EVP encryption context
unsigned char iv[EVP_MAX_IV_LENGTH]; // initialization vector of the cipher.
};
@ -102,6 +115,10 @@ class GxsSecurity
static bool initEncryption(MultiEncryptionContext& encryption_context, const std::list<RsTlvSecurityKey> &keys) ;
static bool initDecryption(MultiEncryptionContext& encryption_context, const RsTlvSecurityKey& key, unsigned char *IV, uint32_t IV_size, unsigned char *encrypted_session_key, uint32_t encrypted_session_key_size) ;
/*!
* Encrypts/decrypt data using envelope encryption using the key pre-computed in the encryption context passed as
* parameter.
*/
static bool encrypt(uint8_t *&out, uint32_t &outlen, const uint8_t *in, uint32_t inlen, MultiEncryptionContext& encryption_context) ;
static bool decrypt(uint8_t *&out, uint32_t &outlen, const uint8_t *in, uint32_t inlen, MultiEncryptionContext& encryption_context) ;

View File

@ -123,15 +123,11 @@ public:
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 getPublicKey(const RsGxsId &id, RsTlvSecurityKey &key) = 0;
virtual bool getOwnIds(std::list<RsGxsId>& ids) = 0;
virtual bool isOwnId(const RsGxsId& key_id) = 0 ;
virtual void timeStampKey(const RsGxsId& key_id) = 0 ;
// virtual void networkRequestPublicKey(const RsGxsId& key_id,const std::list<RsPeerId>& peer_ids) = 0 ;
// Key related interface - used for validating msgs and groups.
/*!
* Use to query a whether given key is available by its key reference
@ -166,9 +162,6 @@ public:
*/
virtual bool getKey(const RsGxsId &id, RsTlvSecurityKey &key) = 0;
virtual bool getPrivateKey(const RsGxsId &id, RsTlvSecurityKey &key) = 0; // For signing outgoing messages.
#ifdef SUSPENDED
#endif
};
class GixsReputation

View File

@ -34,6 +34,7 @@
#include "retroshare/rsgxsflags.h"
#include "retroshare/rsgxscircles.h"
#include "pgp/pgpauxutils.h"
#include "util/rsmemory.h"
/***
* #define NXS_NET_DEBUG 1
@ -2475,14 +2476,18 @@ void RsGxsNetService::locked_genSendMsgsTransaction(NxsTransaction* tr)
if(grpId.isNull())
grpId = item->grpId;
else if(grpId != item->grpId)
{
std::cerr << "RsGxsNetService::locked_genSendMsgsTransaction(): transaction on two different groups! ERROR!" << std::endl;
return ;
}
}
#ifdef NXS_NET_DEBUG
else
{
#ifdef NXS_NET_DEBUG
std::cerr << "RsGxsNetService::locked_genSendMsgsTransaction(): item failed to caste to RsNxsSyncMsgItem* "
<< std::endl;
#endif
std::cerr << "RsGxsNetService::locked_genSendMsgsTransaction(): item failed to caste to RsNxsSyncMsgItem* " << std::endl;
}
#endif
}
mDataStore->retrieveNxsMsgs(msgIds, msgs, false, false);
@ -2533,11 +2538,23 @@ void RsGxsNetService::locked_genSendMsgsTransaction(NxsTransaction* tr)
// now if transaction is limited to an external group, encrypt it for members of the group.
if()
encryptTransaction(newTr,circl_EId
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;
ServerMsgMap::const_iterator cit = mServerMsgUpdateMap.find(grpId);
if(cit != mServerMsgUpdateMap.end())
@ -2558,6 +2575,8 @@ void RsGxsNetService::locked_genSendMsgsTransaction(NxsTransaction* tr)
ntr->PeerId(tr->mTransaction->PeerId());
sendItem(ntr);
// Encryption will happen here if needed.
locked_addTransaction(newTr);
return;
@ -2571,9 +2590,7 @@ bool RsGxsNetService::locked_addTransaction(NxsTransaction* tr)
const RsPeerId& peer = tr->mTransaction->PeerId();
uint32_t transN = tr->mTransaction->transactionNumber;
TransactionIdMap& transMap = mTransactions[peer];
bool transNumExist = transMap.find(transN)
!= transMap.end();
bool transNumExist = transMap.find(transN) != transMap.end();
if(transNumExist)
{
@ -2589,11 +2606,11 @@ bool RsGxsNetService::locked_addTransaction(NxsTransaction* tr)
std::cerr << "Added transaction number " << transN << std::endl;
#endif
transMap[transN] = tr;
if(!tr->destination_circle.isNull())
encryptTransaction(tr);
transMap[transN] = tr;
return true;
}
@ -2615,14 +2632,26 @@ bool RsGxsNetService::encryptTransaction(NxsTransaction *tr)
}
std::cerr << " Dest Ids: " << std::endl;
std::list<RsTlvSecurityKey> recipient_keys ;
for(std::list<RsGxsId>::const_iterator it(recipients.begin());it!=recipients.end();++it)
std::cerr << " " << *it << std::endl;
{
RsTlvSecurityKey pkey ;
if(!rsIdentity->getKey(*it,pkey))
{
std::cerr << "(EE) Cannot retrieve public key " << *it << " for circle encryption." << std::endl;
// we should probably request the key.
continue ;
}
std::cerr << " added key " << *it << std::endl;
recipient_keys.push_back(pkey) ;
}
// 2 - call GXSSecurity to make a header item that encrypts for the given list of peers.
GxsSecurity::MultiEncryptionContext muctx ;
GxsSecurity::initMultiEncryption(muctx,recipients);
GxsSecurity::initEncryption(muctx,recipient_keys);
// 3 - serialise and encrypt each message, converting it into a NxsEncryptedDataItem
@ -2640,15 +2669,15 @@ bool RsGxsNetService::encryptTransaction(NxsTransaction *tr)
}
unsigned char *encrypted_data = NULL ;
unsigned char *encrypted_len = 0 ;
uint32_t encrypted_len = 0 ;
if(!GxsSecurity::encrypt(muctx,tempmem,tempmemsize,encryted_data, encryted_len))
if(!GxsSecurity::encrypt(muctx,tempmem,size,encrypted_data, encrypted_len))
{
std::cerr << " (EE) Cannot multi-encrypt item. Something went wrong." << std::endl;
continue ;
}
RsNxsEncryptedDataItem *enc_item = new RsNxsEncryptedDataItem() ;
RsNxsEncryptedDataItem *enc_item = new RsNxsEncryptedDataItem(mServType) ;
enc_item->aes_encrypted_data.bin_len = encrypted_len ;
enc_item->aes_encrypted_data.bin_data = encrypted_data ;
@ -2666,11 +2695,11 @@ bool RsGxsNetService::encryptTransaction(NxsTransaction *tr)
// 5 - make session key item and push it front.
RsNxsSessionKeyItem *session_key_item = new RsNxsSessionKeyItem() ;
RsNxsSessionKeyItem *session_key_item = new RsNxsSessionKeyItem(mServType) ;
memcpy(session_key_item->initialization_vector,muctx.IV,EVP_MAX_IV_LENGTH) ;
memcpy(session_key_item->iv,muctx.initialisation_vector(),EVP_MAX_IV_LENGTH) ;
for(int i=0;i<muctx->n_encrypted_keys();++i)
for(int i=0;i<muctx.n_encrypted_keys();++i)
{
std::cerr << " addign session key for ID " << muctx.encrypted_key_id(i) << std::endl;
RsTlvBinaryData data ;
@ -2681,6 +2710,8 @@ bool RsGxsNetService::encryptTransaction(NxsTransaction *tr)
}
tr->mItems.push_front(session_key_item) ;
return true ;
}
bool RsGxsNetService::decryptTransaction(NxsTransaction *tr)
@ -2707,8 +2738,26 @@ bool RsGxsNetService::decryptTransaction(NxsTransaction *tr)
// we don't own that identity.
GxsSecurity::MultiEncryptionContext muctx ;
RsGxsId private_key_id ;
bool found = false ;
if(!GxsSecurity::initDecryption(muctx,key,esk.initialization_vector.bin_data,esk.initialization_vector.bin_len,ek.bin_data,ek.bin_len))
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 ;
std::cerr << " found appropriate private key to decrypt session key: " << it->first << std::endl;
break ;
}
if(!found)
{
std::cerr << " (EE) no private key for this encrypted transaction. Cannot decrypt!" << std::endl;
return false ;
}
if(!GxsSecurity::initDecryption(private_key_id,esk->iv,EVP_MAX_IV_LENGTH,ek.bin_data,ek.bin_len))
{
std::cerr << " (EE) cannot decrypt transaction. initDecryption() failed." << std::endl;
return false ;
@ -2717,8 +2766,8 @@ bool RsGxsNetService::decryptTransaction(NxsTransaction *tr)
// 3 - Using session key, decrypt all packets, by calling GXSSecurity.
std::list<RsNxsItem*> decrypted_items ;
RsNxsEncryptedDataItem encrypted_item ;
RsNxsSerialiser serial ;
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)))
@ -2726,17 +2775,24 @@ bool RsGxsNetService::decryptTransaction(NxsTransaction *tr)
unsigned char *tempmem;
uint32_t tempmemsize ;
if(!GxsSecurity::decrypt(muctx,tempmem,tempmemsize,encrypted_item->aes_encrypted_data.bin_data, encrypted_item.aes_encrypted_data.bin_len))
if(!GxsSecurity::decrypt(muctx,tempmem,tempmemsize,encrypted_item->aes_encrypted_data.bin_data, encrypted_item->aes_encrypted_data.bin_len))
{
std::cerr << " (EE) Cannot decrypt item. Something went wrong. Skipping this item." << std::endl;
continue ;
}
RsNxsItem *item = serial.deserialise(tempmem,tempmemsize) ;
RsItem *ditem = serial.deserialise(tempmem,&tempmemsize) ;
std::cerr << " Decrypted an item of type " << std::hex << item->getType() << std::dec << std::endl;
std::cerr << " Decrypted an item of type " << std::hex << ditem->PacketId() << std::dec << std::endl;
decrypted_items.push_back(item) ;
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) ;
}
@ -2748,7 +2804,7 @@ bool RsGxsNetService::decryptTransaction(NxsTransaction *tr)
for(std::list<RsNxsItem*>::const_iterator it(tr->mItems.begin());it!=tr->mItems.end();++it)
delete *it ;
tr->mItems = encrypted_items ;
tr->mItems = decrypted_items ;
return true ;
}

View File

@ -437,6 +437,11 @@ private:
void locked_stampPeerGroupUpdateTime(const RsPeerId& pid,const RsGxsGroupId& grpId,time_t tm,uint32_t n_messages) ;
/*!
* encrypts/decrypts the transaction for the destination circle id.
*/
bool encryptTransaction(NxsTransaction *tr);
bool decryptTransaction(NxsTransaction *tr);
private:

View File

@ -69,7 +69,7 @@ public:
RsNxsTransacItem* mTransaction;
std::list<RsNxsItem*> mItems; // items received or sent
mGxsCircleId destination_circle;
RsGxsCircleId destination_circle;
};
/*!

View File

@ -1,5 +1,6 @@
#include "rsnxsitems.h"
#include "rsbaseserial.h"
#include "util/rsprint.h"
#include <iomanip>
/***
@ -392,7 +393,21 @@ bool RsNxsSessionKeyItem::serialise(void *data, uint32_t& size) const
if(!serialise_header(data,size,tlvsize,offset))
return false ;
ok &= encrypted_key_data.SetTlv(data, size, &offset) ;
if(offset + EVP_MAX_IV_LENGTH >= size)
{
std::cerr << "RsNxsSessionKeyItem::serialize(): error. Not enough room for IV !" << std::endl;
return false ;
}
memcpy(&((uint8_t*)data)[offset],iv,EVP_MAX_IV_LENGTH) ;
offset += EVP_MAX_IV_LENGTH ;
ok &= setRawUInt32(data, size, &offset, encrypted_session_keys.size());
for(std::map<RsGxsId,RsTlvBinaryData>::const_iterator it(encrypted_session_keys.begin());it!=encrypted_session_keys.end();++it)
{
ok &= it->first.serialise(data, size, offset) ;
ok &= it->second.SetTlv(data, size, &offset) ;
}
if(offset != tlvsize)
{
@ -757,7 +772,27 @@ RsNxsSessionKeyItem *RsNxsSerialiser::deserialNxsSessionKeyItem(void* data,
RsNxsSessionKeyItem* item = new RsNxsSessionKeyItem(SERVICE_TYPE);
ok &= item->encrypted_key_data.GetTlv(data,*size,&offset) ;
if(offset + EVP_MAX_IV_LENGTH >= *size)
{
std::cerr << __PRETTY_FUNCTION__ << ": not enough room for IV." << std::endl;
return NULL ;
}
memcpy(item->iv,&((uint8_t*)data)[offset],EVP_MAX_IV_LENGTH) ;
offset += EVP_MAX_IV_LENGTH ;
uint32_t n ;
ok &= getRawUInt32(data, *size, &offset, &n) ;
for(uint32_t i=0;ok && i<n;++i)
{
RsGxsId gxs_id ;
RsTlvBinaryData bdata(0) ;
ok &= gxs_id.deserialise(data,*size,offset) ;
ok &= bdata.GetTlv(data,*size,&offset) ;
item->encrypted_session_keys[gxs_id] = bdata ;
}
if (offset != *size)
{
@ -931,7 +966,11 @@ uint32_t RsNxsSessionKeyItem::serial_size() const
{
uint32_t s = 8; // header size
s += encrypted_key_data.TlvSize() ;
s += EVP_MAX_IV_LENGTH ; // iv
s += 4 ; // encrypted_session_keys.size() ;
for(std::map<RsGxsId,RsTlvBinaryData>::const_iterator it(encrypted_session_keys.begin());it!=encrypted_session_keys.end();++it)
s += it->first.serial_size() + it->second.TlvSize() ;
return s;
}
@ -1002,8 +1041,12 @@ void RsNxsTransacItem::clear(){
void RsNxsEncryptedDataItem::clear(){
aes_encrypted_data.TlvClear() ;
}
void RsNxsSessionKeyItem::clear(){
encrypted_key_data.TlvClear() ;
void RsNxsSessionKeyItem::clear()
{
for(std::map<RsGxsId,RsTlvBinaryData>::iterator it(encrypted_session_keys.begin());it!=encrypted_session_keys.end();++it)
it->second.TlvClear() ;
encrypted_session_keys.clear() ;
}
std::ostream& RsNxsSyncGrpReqItem::print(std::ostream &out, uint16_t indent)
@ -1176,12 +1219,12 @@ std::ostream& RsNxsSessionKeyItem::print(std::ostream &out, uint16_t indent)
{
printRsItemBase(out, "RsNxsSessionKeyItem", indent);
out << "encrypted key data: " << std::hex << std::setw(2) << std::setfill('0') ;
out << " iv: " << RsUtil::BinToHex((char*)iv,EVP_MAX_IV_LENGTH) << std::endl;
for(uint32_t i=0;i<std::min(50u,encrypted_key_data.bin_len);++i)
out << (int)((unsigned char*)encrypted_key_data.bin_data)[i] ;
out << " encrypted keys: " << std::endl;
out << std::dec << std::endl;
for(std::map<RsGxsId,RsTlvBinaryData>::const_iterator it(encrypted_session_keys.begin());it!=encrypted_session_keys.end();++it)
out << " id=" << it->first << ": ekey=" << RsUtil::BinToHex((char*)it->second.bin_data,it->second.bin_len) << std::endl;
printRsItemEnd(out ,"RsNxsSessionKeyItem", indent);
return out;
@ -1190,12 +1233,12 @@ std::ostream& RsNxsEncryptedDataItem::print(std::ostream &out, uint16_t indent)
{
printRsItemBase(out, "RsNxsEncryptedDataItem", indent);
out << "encrypted data: " << std::hex << std::setw(2) << std::setfill('0') ;
out << " encrypted data: " << RsUtil::BinToHex((char*)aes_encrypted_data.bin_data,std::min(50u,aes_encrypted_data.bin_len)) ;
for(uint32_t i=0;i<std::min(50u,aes_encrypted_data.bin_len);++i)
out << (int)((unsigned char *)aes_encrypted_data.bin_data)[i] ;
if(aes_encrypted_data.bin_len > 50u)
out << "..." ;
out << std::dec << std::endl;
out << std::endl;
printRsItemEnd(out ,"RsNxsSessionKeyItem", indent);
return out;

View File

@ -28,6 +28,7 @@
#include <map>
#include <openssl/ssl.h>
#include "serialiser/rsserviceids.h"
#include "serialiser/rsserial.h"
@ -228,7 +229,7 @@ class RsNxsSessionKeyItem : public RsNxsItem
public:
RsNxsSessionKeyItem(uint16_t servtype) : RsNxsItem(servtype, RS_PKT_SUBTYPE_NXS_SESSION_KEY_ITEM),encrypted_key_data(servtype) { clear(); }
RsNxsSessionKeyItem(uint16_t servtype) : RsNxsItem(servtype, RS_PKT_SUBTYPE_NXS_SESSION_KEY_ITEM) { clear(); }
virtual ~RsNxsSessionKeyItem() {}
virtual bool serialise(void *data,uint32_t& size) const;
@ -239,8 +240,8 @@ public:
/// Session key encrypted for the whole group
///
RsTlvBinaryData initialisation_vector ;
std::map<RsGxsId, RsTlvBinaryData> encrypted_session_keys;
uint8_t iv[EVP_MAX_IV_LENGTH] ; // initialisation vector
std::map<RsGxsId, RsTlvBinaryData> encrypted_session_keys; // encrypted session keys
};
/*!
* Use to send to peer list of grps

View File

@ -185,7 +185,7 @@ const uint16_t TLV_TYPE_BIN_IMAGE = 0x0130; /* Used (Generic - Forums) */
const uint16_t TLV_TYPE_BIN_FILEDATA = 0x0140; /* Used - ACTIVE! */
const uint16_t TLV_TYPE_BIN_SERIALISE = 0x0150; /* Used (Generic - Distrib) */
const uint16_t TLV_TYPE_BIN_GENERIC = 0x0160; /* Used (DSDV Data) */
const uint16_t TLV_TYPE_BIN_ENCRYPTED = 0x0170; /* Encrypted data
const uint16_t TLV_TYPE_BIN_ENCRYPTED = 0x0170; /* Encrypted data */
/**** Compound Types ****/

View File

@ -36,10 +36,14 @@
/*!********************************** RsTlvFileBinaryData **********************************/
RsTlvBinaryData::RsTlvBinaryData()
:tlvtype(0), bin_len(0), bin_data(NULL)
{
}
RsTlvBinaryData::RsTlvBinaryData(uint16_t t)
:tlvtype(t), bin_len(0), bin_data(NULL)
{
return;
}
RsTlvBinaryData::RsTlvBinaryData(const RsTlvBinaryData &b)

View File

@ -35,26 +35,29 @@
class RsTlvBinaryData: public RsTlvItem
{
public:
public:
RsTlvBinaryData();
RsTlvBinaryData(uint16_t t);
RsTlvBinaryData(const RsTlvBinaryData& b); // as per rule of three
void operator=(const RsTlvBinaryData& b); // as per rule of three
virtual ~RsTlvBinaryData(); // as per rule of three
virtual uint32_t TlvSize() const;
virtual void TlvClear(); /*! Initialize fields to empty legal values ( "0", "", etc) */
virtual void TlvShallowClear(); /*! Don't delete the binary data */
virtual ~RsTlvBinaryData(); // as per rule of three
virtual uint32_t TlvSize() const;
virtual void TlvClear(); /*! Initialize fields to empty legal values ( "0", "", etc) */
virtual void TlvShallowClear(); /*! Don't delete the binary data */
/// Serialise.
/*! Serialise Tlv to buffer(*data) of 'size' bytes starting at *offset */
virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset) const;
/*! Serialise Tlv to buffer(*data) of 'size' bytes starting at *offset */
virtual bool SetTlv(void *data, uint32_t size, uint32_t *offset) const;
/// Deserialise.
/*! Deserialise Tlv buffer(*data) of 'size' bytes starting at *offset */
virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset);
virtual std::ostream &print(std::ostream &out, uint16_t indent) const; /*! Error/Debug util function */
/// Deserialise.
/*! Deserialise Tlv buffer(*data) of 'size' bytes starting at *offset */
virtual bool GetTlv(void *data, uint32_t size, uint32_t *offset);
virtual std::ostream &print(std::ostream &out, uint16_t indent) const; /*! Error/Debug util function */
// mallocs the necessary size, and copies data into the allocated buffer in bin_data
bool setBinData(const void *data, uint32_t size);
bool setBinData(const void *data, uint32_t size);
uint16_t tlvtype; /// set/checked against TLV input
uint32_t bin_len; /// size of malloc'ed data (not serialised)