mirror of
https://github.com/RetroShare/RetroShare.git
synced 2025-01-28 16:27:01 -05:00
added single-block multiple encryption
This commit is contained in:
parent
763108f5fa
commit
08e4c90cc2
@ -34,6 +34,8 @@
|
||||
* #define GXS_SECURITY_DEBUG 1
|
||||
***/
|
||||
|
||||
static const uint32_t HEADER_MULTI_ENCRYPTION_FORMAT_v001 = 0xFACE;
|
||||
|
||||
static RsGxsId getRsaKeyFingerprint(RSA *pubkey)
|
||||
{
|
||||
int lenn = BN_num_bytes(pubkey -> n);
|
||||
@ -631,6 +633,149 @@ bool GxsSecurity::encrypt(uint8_t *& out, uint32_t &outlen, const uint8_t *in, u
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GxsSecurity::encrypt(uint8_t *& out, uint32_t &outlen, const uint8_t *in, uint32_t inlen, const std::vector<RsTlvSecurityKey>& keys)
|
||||
{
|
||||
#ifdef DISTRIB_DEBUG
|
||||
std::cerr << "GxsSecurity::encrypt() " << std::endl;
|
||||
#endif
|
||||
// Encrypts (in,inlen) into (out,outlen) using the given RSA public key.
|
||||
// The format of the encrypted data is:
|
||||
//
|
||||
// [--- ID ---|--- number of encrypted keys---| n * (--- Encrypted session key length ---|--- Encrypted session keys ---) |--- IV ---|---- Encrypted data ---]
|
||||
// 2 bytes 2 byte = n 1 byte = X X bytes EVP_MAX_IV_LENGTH Rest of packet
|
||||
//
|
||||
|
||||
out = NULL ;
|
||||
|
||||
try
|
||||
{
|
||||
std::vector<EVP_PKEY *> public_keys(keys.size(),NULL);
|
||||
|
||||
for(uint32_t i=0;i<keys.size();++i)
|
||||
{
|
||||
RSA *tmpkey = ::extractPublicKey(keys[i]) ;
|
||||
RSA *rsa_publish_pub = RSAPublicKey_dup(tmpkey) ;
|
||||
RSA_free(tmpkey) ;
|
||||
|
||||
if(rsa_publish_pub != NULL)
|
||||
{
|
||||
public_keys[i] = EVP_PKEY_new();
|
||||
EVP_PKEY_assign_RSA(public_keys[i], rsa_publish_pub);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "GxsSecurity(): Could not generate public key for key id " << keys[i].keyId << std::endl;
|
||||
throw std::runtime_error("Cannot extract public key") ;
|
||||
}
|
||||
}
|
||||
|
||||
EVP_CIPHER_CTX ctx;
|
||||
unsigned char iv[EVP_MAX_IV_LENGTH];
|
||||
EVP_CIPHER_CTX_init(&ctx);
|
||||
|
||||
std::vector<unsigned char *> ek(keys.size(),NULL) ;
|
||||
std::vector<int> eklen(keys.size(),0) ;
|
||||
|
||||
for(uint32_t i=0;i<keys.size();++i)
|
||||
{
|
||||
int max_evp_key_size = EVP_PKEY_size(public_keys[i]);
|
||||
ek[i] = (unsigned char*)rs_malloc(max_evp_key_size);
|
||||
if(ek[i] == NULL)
|
||||
throw std::runtime_error("malloc error on encrypted keys") ;
|
||||
}
|
||||
|
||||
static const int HEADER_SIZE = 2 ;
|
||||
static const int NUMBER_OF_KEYS_SIZE = 2 ;
|
||||
|
||||
const EVP_CIPHER *cipher = EVP_aes_128_cbc();
|
||||
int cipher_block_size = EVP_CIPHER_block_size(cipher);
|
||||
|
||||
// intialize context and send store encrypted cipher in ek
|
||||
if(!EVP_SealInit(&ctx, EVP_aes_128_cbc(), ek.data(), eklen.data(), iv, public_keys.data(), 1))
|
||||
return false;
|
||||
|
||||
int total_ek_size = 0 ;
|
||||
|
||||
for(uint32_t i=0;i<keys.size();++i)
|
||||
total_ek_size += eklen[i] + 1 ;
|
||||
|
||||
int max_outlen = HEADER_SIZE + NUMBER_OF_KEYS_SIZE + total_ek_size + EVP_MAX_IV_LENGTH + (inlen + cipher_block_size) ;
|
||||
|
||||
// now assign memory to out accounting for data, and cipher block size, key length, and key length val
|
||||
out = (uint8_t*)rs_malloc(max_outlen);
|
||||
|
||||
if(out == NULL)
|
||||
return false ;
|
||||
|
||||
int out_offset = 0;
|
||||
|
||||
// header
|
||||
|
||||
out[out_offset++] = HEADER_MULTI_ENCRYPTION_FORMAT_v001 & 0xff ;
|
||||
out[out_offset++] = (HEADER_MULTI_ENCRYPTION_FORMAT_v001 >> 8) & 0xff ;
|
||||
|
||||
// number of keys
|
||||
|
||||
out[out_offset++] = keys.size() & 0xff ;
|
||||
out[out_offset++] = (keys.size() >> 8) & 0xff ;
|
||||
|
||||
// encrypted keys, each preceeded with its length
|
||||
|
||||
for(uint32_t i=0;i<keys.size();++i)
|
||||
{
|
||||
if(eklen[i] > 0xff)
|
||||
{
|
||||
std::cerr << "(EE) eklen[i]=" << eklen[i] << " in " << __PRETTY_FUNCTION__ << " for key id " << keys[i].keyId << ". This is unexpected. Cannot encrypt." << std::endl;
|
||||
throw std::runtime_error("Encryption error") ;
|
||||
}
|
||||
out[out_offset++] = (unsigned char)eklen[i] ;
|
||||
|
||||
memcpy((unsigned char*)out + out_offset, ek[i],eklen[i]) ;
|
||||
out_offset += eklen[i] ;
|
||||
}
|
||||
|
||||
memcpy((unsigned char*)out + out_offset, iv, EVP_MAX_IV_LENGTH);
|
||||
out_offset += EVP_MAX_IV_LENGTH;
|
||||
|
||||
int out_currOffset = 0;
|
||||
|
||||
// now encrypt actual data
|
||||
if(!EVP_SealUpdate(&ctx, (unsigned char*) out + out_offset, &out_currOffset, (unsigned char*) in, inlen))
|
||||
throw std::runtime_error("Encryption error in SealUpdate()") ;
|
||||
|
||||
// move along to partial block space
|
||||
out_offset += out_currOffset;
|
||||
|
||||
// add padding
|
||||
if(!EVP_SealFinal(&ctx, (unsigned char*) out + out_offset, &out_currOffset))
|
||||
throw std::runtime_error("Encryption error in SealFinal()") ;
|
||||
|
||||
// move to end
|
||||
out_offset += out_currOffset;
|
||||
|
||||
// make sure offset has not gone passed valid memory bounds
|
||||
|
||||
if(out_offset > max_outlen)
|
||||
throw std::runtime_error("Memory used by encryption exceeds allocated memory block") ;
|
||||
|
||||
// free encrypted key data
|
||||
|
||||
for(uint32_t i=0;i<keys.size();++i)
|
||||
if(ek[i]) free(ek[i]);
|
||||
|
||||
outlen = out_offset;
|
||||
return true;
|
||||
}
|
||||
catch(std::exception& e)
|
||||
{
|
||||
std::cerr << "(EE) Exception caught while encrypting: " << e.what() << std::endl;
|
||||
|
||||
if(out) free(out) ;
|
||||
out = NULL ;
|
||||
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
bool GxsSecurity::initDecryption(GxsSecurity::MultiEncryptionContext& encryption_context, const RsTlvSecurityKey& key,unsigned char *IV,uint32_t IV_size,unsigned char *encrypted_session_key,uint32_t encrypted_session_key_size)
|
||||
{
|
||||
// prepare an array of encrypted keys ek and public keys puk
|
||||
|
@ -57,20 +57,20 @@ class GxsSecurity
|
||||
~MultiEncryptionContext() { clear() ;}
|
||||
|
||||
void clear()
|
||||
{
|
||||
for(uint32_t i=0;i<ids.size();++i)
|
||||
free(ek[i]) ;
|
||||
|
||||
if(ekl)
|
||||
free(ekl) ;
|
||||
if(ek)
|
||||
free(ek) ;
|
||||
|
||||
ekl = NULL ;
|
||||
ek = NULL ;
|
||||
|
||||
ids.clear() ;
|
||||
}
|
||||
{
|
||||
for(uint32_t i=0;i<ids.size();++i)
|
||||
free(ek[i]) ;
|
||||
|
||||
if(ekl)
|
||||
free(ekl) ;
|
||||
if(ek)
|
||||
free(ek) ;
|
||||
|
||||
ekl = NULL ;
|
||||
ek = NULL ;
|
||||
|
||||
ids.clear() ;
|
||||
}
|
||||
|
||||
// The functions below give access to the encrypted symmetric key to be used.
|
||||
//
|
||||
@ -110,21 +110,22 @@ class GxsSecurity
|
||||
*@param in
|
||||
*@param inlen
|
||||
*/
|
||||
static bool encrypt(uint8_t *&out, uint32_t &outlen, const uint8_t *in, uint32_t inlen, const RsTlvSecurityKey& key) ;
|
||||
static bool encrypt(uint8_t *&out, uint32_t &outlen, const uint8_t *in, uint32_t inlen, const RsTlvSecurityKey& key) ;
|
||||
static bool encrypt(uint8_t *&out, uint32_t &outlen, const uint8_t *in, uint32_t inlen, const std::vector<RsTlvSecurityKey>& keys) ;
|
||||
|
||||
/*!
|
||||
* Encrypts/decrypt data using envelope encryption using the key pre-computed in the encryption context passed as
|
||||
* parameter.
|
||||
*/
|
||||
static bool initEncryption(MultiEncryptionContext& encryption_context, const std::vector<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) ;
|
||||
static bool initEncryption(MultiEncryptionContext& encryption_context, const std::vector<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) ;
|
||||
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) ;
|
||||
|
||||
/**
|
||||
* Decrypts data using evelope decryption (taken from open ssl's evp_sealinit )
|
||||
@ -135,7 +136,7 @@ class GxsSecurity
|
||||
* @param inlen
|
||||
* @return false if encryption failed
|
||||
*/
|
||||
static bool decrypt(uint8_t *&out, uint32_t &outlen, const uint8_t *in, uint32_t inlen, const RsTlvSecurityKey& key) ;
|
||||
static bool decrypt(uint8_t *&out, uint32_t &outlen, const uint8_t *in, uint32_t inlen, const RsTlvSecurityKey& key) ;
|
||||
|
||||
/*!
|
||||
* uses grp signature to check if group has been
|
||||
|
Loading…
x
Reference in New Issue
Block a user