2012-08-12 16:46:21 -04:00
/*
2012-11-02 19:35:10 -04:00
* libretroshare / src / gxs : gxssecurity . cc
2012-08-12 16:46:21 -04:00
*
*
* Copyright 2008 - 2010 by Robert Fernie
2012-11-02 19:35:10 -04:00
* 2011 - 2012 Christopher Evi - Parker
2012-08-12 16:46:21 -04:00
*
* 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@lunamutt.com " .
*
*/
# include "gxssecurity.h"
# include "pqi/authgpg.h"
2014-05-15 17:00:44 -04:00
# include "util/rsdir.h"
2014-04-27 09:14:07 -04:00
//#include "retroshare/rspeers.h"
2012-08-12 16:46:21 -04:00
2014-05-04 08:48:42 -04:00
/****
* # define GXS_SECURITY_DEBUG 1
* * */
2012-10-23 17:52:51 -04:00
2014-06-12 06:28:23 -04:00
static RsGxsId getRsaKeyFingerprint ( RSA * pubkey )
2012-08-12 16:46:21 -04:00
{
2014-05-17 09:50:40 -04:00
int lenn = BN_num_bytes ( pubkey - > n ) ;
int lene = BN_num_bytes ( pubkey - > e ) ;
unsigned char * tmp = new unsigned char [ lenn + lene ] ;
BN_bn2bin ( pubkey - > n , tmp ) ;
BN_bn2bin ( pubkey - > e , & tmp [ lenn ] ) ;
Sha1CheckSum s = RsDirUtil : : sha1sum ( tmp , lenn + lene ) ;
delete [ ] tmp ;
// Copy first CERTSIGNLEN bytes from the hash of the public modulus and exponent
// We should not be using strings here, but a real ID. To be done later.
assert ( Sha1CheckSum : : SIZE_IN_BYTES > = CERTSIGNLEN ) ;
2014-06-12 06:28:23 -04:00
return RsGxsId ( s . toStdString ( ) . substr ( 0 , 2 * CERTSIGNLEN ) ) ;
2012-08-12 16:46:21 -04:00
}
2015-07-15 18:20:00 -04:00
static RSA * extractPrivateKey ( const RsTlvSecurityKey & key )
{
assert ( key . keyFlags & RSTLV_KEY_TYPE_FULL ) ;
const unsigned char * keyptr = ( const unsigned char * ) key . keyData . bin_data ;
long keylen = key . keyData . bin_len ;
/* extract admin key */
RSA * rsakey = d2i_RSAPrivateKey ( NULL , & ( keyptr ) , keylen ) ;
return rsakey ;
}
2014-05-17 09:50:40 -04:00
static RSA * extractPublicKey ( const RsTlvSecurityKey & key )
2012-08-12 16:46:21 -04:00
{
2015-01-10 02:30:26 -05:00
assert ( ! ( key . keyFlags & RSTLV_KEY_TYPE_FULL ) ) ;
2014-05-17 09:50:40 -04:00
const unsigned char * keyptr = ( const unsigned char * ) key . keyData . bin_data ;
long keylen = key . keyData . bin_len ;
/* extract admin key */
RSA * rsakey = d2i_RSAPublicKey ( NULL , & ( keyptr ) , keylen ) ;
return rsakey ;
2012-08-12 16:46:21 -04:00
}
2014-11-15 15:24:56 -05:00
static void setRSAPublicKeyData ( RsTlvSecurityKey & key , RSA * rsa_pub )
2014-05-17 09:50:40 -04:00
{
unsigned char * data = NULL ; // this works for OpenSSL > 0.9.7
int reqspace = i2d_RSAPublicKey ( rsa_pub , & data ) ;
key . keyData . setBinData ( data , reqspace ) ;
key . keyId = getRsaKeyFingerprint ( rsa_pub ) ;
2012-08-12 16:46:21 -04:00
2014-05-17 09:50:40 -04:00
free ( data ) ;
}
2015-07-15 18:20:00 -04:00
bool GxsSecurity : : checkPrivateKey ( const RsTlvSecurityKey & key )
{
std : : cerr < < " Checking private key " < < key . keyId < < " ... " < < std : : endl ;
if ( ( key . keyFlags & RSTLV_KEY_TYPE_MASK ) ! = RSTLV_KEY_TYPE_FULL )
{
std : : cerr < < " (WW) GxsSecurity::checkPrivateKey(): private key has wrong flags " < < std : : hex < < ( key . keyFlags & RSTLV_KEY_TYPE_MASK ) < < std : : dec < < " . This is unexpected. " < < std : : endl ;
return false ;
}
RSA * rsa_prv = : : extractPrivateKey ( key ) ;
if ( rsa_prv = = NULL )
{
std : : cerr < < " (WW) GxsSecurity::checkPrivateKey(): no private key can be extracted from key ID " < < key . keyId < < " . Key is corrupted? " < < std : : endl ;
return false ;
}
RSA * rsa_pub = RSAPublicKey_dup ( rsa_prv ) ;
RSA_free ( rsa_prv ) ;
if ( rsa_pub = = NULL )
{
std : : cerr < < " (WW) GxsSecurity::checkPrivateKey(): no public key can be extracted from key ID " < < key . keyId < < " . Key is corrupted? " < < std : : endl ;
return false ;
}
RsGxsId recomputed_key_id = getRsaKeyFingerprint ( rsa_pub ) ;
RSA_free ( rsa_pub ) ;
if ( recomputed_key_id ! = key . keyId )
{
std : : cerr < < " (WW) GxsSecurity::checkPrivateKey(): key " < < key . keyId < < " has wrong fingerprint " < < recomputed_key_id < < " ! This is unexpected. " < < std : : endl ;
return false ;
}
return true ;
}
bool GxsSecurity : : checkPublicKey ( const RsTlvSecurityKey & key )
{
std : : cerr < < " Checking public key " < < key . keyId < < " ... " < < std : : endl ;
if ( ( key . keyFlags & RSTLV_KEY_TYPE_MASK ) ! = RSTLV_KEY_TYPE_PUBLIC_ONLY )
{
std : : cerr < < " (WW) GxsSecurity::checkPublicKey(): public key has wrong flags " < < std : : hex < < ( key . keyFlags & RSTLV_KEY_TYPE_MASK ) < < std : : dec < < " . This is unexpected. " < < std : : endl ;
return false ;
}
RSA * rsa_pub = : : extractPublicKey ( key ) ;
if ( rsa_pub = = NULL )
{
std : : cerr < < " (WW) GxsSecurity::checkPublicKey(): no public key can be extracted from key ID " < < key . keyId < < " . Key is corrupted? " < < std : : endl ;
return false ;
}
RsGxsId recomputed_key_id = getRsaKeyFingerprint ( rsa_pub ) ;
RSA_free ( rsa_pub ) ;
if ( recomputed_key_id ! = key . keyId )
{
std : : cerr < < " (WW) GxsSecurity::checkPublicKey(): key " < < key . keyId < < " has wrong fingerprint " < < recomputed_key_id < < " ! This is unexpected. " < < std : : endl ;
return false ;
}
return true ;
}
2014-11-15 15:24:56 -05:00
static void setRSAPrivateKeyData ( RsTlvSecurityKey & key , RSA * rsa_priv )
2014-05-17 09:50:40 -04:00
{
unsigned char * data = NULL ;
int reqspace = i2d_RSAPrivateKey ( rsa_priv , & data ) ;
key . keyData . setBinData ( data , reqspace ) ;
key . keyId = getRsaKeyFingerprint ( rsa_priv ) ;
free ( data ) ;
}
bool GxsSecurity : : generateKeyPair ( RsTlvSecurityKey & public_key , RsTlvSecurityKey & private_key )
{
// admin keys
RSA * rsa = RSA_generate_key ( 2048 , 65537 , NULL , NULL ) ;
RSA * rsa_pub = RSAPublicKey_dup ( rsa ) ;
2014-11-15 15:24:56 -05:00
setRSAPublicKeyData ( public_key , rsa_pub ) ;
setRSAPrivateKeyData ( private_key , rsa ) ;
2014-05-17 09:50:40 -04:00
2014-11-15 15:24:56 -05:00
public_key . startTS = time ( NULL ) ;
public_key . endTS = public_key . startTS + 60 * 60 * 24 * 365 * 5 ; /* approx 5 years */
public_key . keyFlags = RSTLV_KEY_TYPE_PUBLIC_ONLY ;
2014-05-17 09:50:40 -04:00
2014-11-15 15:24:56 -05:00
private_key . startTS = public_key . startTS ;
private_key . endTS = 0 ; /* no end */
private_key . keyFlags = RSTLV_KEY_TYPE_FULL ;
2014-05-17 09:50:40 -04:00
// clean up
RSA_free ( rsa ) ;
RSA_free ( rsa_pub ) ;
return true ;
}
bool GxsSecurity : : extractPublicKey ( const RsTlvSecurityKey & private_key , RsTlvSecurityKey & public_key )
{
2014-11-15 15:24:56 -05:00
public_key . TlvClear ( ) ;
if ( ! ( private_key . keyFlags & RSTLV_KEY_TYPE_FULL ) )
return false ;
2014-05-17 09:50:40 -04:00
2014-11-15 15:24:56 -05:00
RSA * rsaPrivKey = extractPrivateKey ( private_key ) ;
2014-05-17 09:50:40 -04:00
2014-11-15 15:24:56 -05:00
if ( ! rsaPrivKey )
return false ;
2014-05-17 09:50:40 -04:00
2014-11-15 15:24:56 -05:00
RSA * rsaPubKey = RSAPublicKey_dup ( rsaPrivKey ) ;
RSA_free ( rsaPrivKey ) ;
2014-05-17 09:50:40 -04:00
2014-11-15 15:24:56 -05:00
if ( ! rsaPubKey )
return false ;
2014-05-17 09:50:40 -04:00
2014-11-15 15:24:56 -05:00
setRSAPublicKeyData ( public_key , rsaPubKey ) ;
RSA_free ( rsaPubKey ) ;
2014-05-17 09:50:40 -04:00
2014-11-15 15:24:56 -05:00
public_key . keyFlags = private_key . keyFlags & ( RSTLV_KEY_DISTRIB_MASK ) ; // keep the distrib flags
public_key . keyFlags | = RSTLV_KEY_TYPE_PUBLIC_ONLY ;
public_key . startTS = private_key . startTS ;
public_key . endTS = public_key . startTS + 60 * 60 * 24 * 365 * 5 ; /* approx 5 years */
2014-05-17 09:50:40 -04:00
2014-11-15 15:54:42 -05:00
// This code fixes a problem of old RSA keys where the fingerprint wasn't computed using SHA1(n,e) but
// using the first bytes of n (ouuuuch!). Still, these keys are valid and should produce a correct
// fingerprint. So we replace the public key fingerprint (that is normally recomputed) with the FP of
// the private key.
if ( public_key . keyId ! = private_key . keyId )
{
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 < < std : : endl ;
public_key . keyId = private_key . keyId ;
}
2014-11-15 15:24:56 -05:00
return true ;
2014-05-17 09:50:40 -04:00
}
2014-03-29 10:18:05 -04:00
bool GxsSecurity : : getSignature ( const char * data , uint32_t data_len , const RsTlvSecurityKey & privKey , RsTlvKeySignature & sign )
2012-11-02 19:35:10 -04:00
{
2014-03-29 10:18:05 -04:00
RSA * rsa_pub = extractPrivateKey ( privKey ) ;
2014-05-08 05:20:25 -04:00
if ( ! rsa_pub )
{
2014-06-12 06:28:23 -04:00
std : : cerr < < " GxsSecurity::getSignature(): Cannot create signature. Keydata is incomplete. " < < std : : endl ;
2014-05-08 05:20:25 -04:00
return false ;
}
2012-11-02 19:35:10 -04:00
EVP_PKEY * key_pub = EVP_PKEY_new ( ) ;
EVP_PKEY_assign_RSA ( key_pub , rsa_pub ) ;
/* calc and check signature */
EVP_MD_CTX * mdctx = EVP_MD_CTX_create ( ) ;
bool ok = EVP_SignInit ( mdctx , EVP_sha1 ( ) ) = = 1 ;
ok & = EVP_SignUpdate ( mdctx , data , data_len ) = = 1 ;
unsigned int siglen = EVP_PKEY_size ( key_pub ) ;
unsigned char sigbuf [ siglen ] ;
ok & = EVP_SignFinal ( mdctx , sigbuf , & siglen , key_pub ) = = 1 ;
// clean up
EVP_MD_CTX_destroy ( mdctx ) ;
EVP_PKEY_free ( key_pub ) ;
sign . signData . setBinData ( sigbuf , siglen ) ;
2014-06-12 06:28:23 -04:00
sign . keyId = RsGxsId ( privKey . keyId ) ;
2012-11-02 19:35:10 -04:00
return ok ;
}
2012-08-12 16:46:21 -04:00
2014-03-29 10:18:05 -04:00
bool GxsSecurity : : validateSignature ( const char * data , uint32_t data_len , const RsTlvSecurityKey & key , const RsTlvKeySignature & signature )
{
2015-06-22 17:35:39 -04:00
RSA * tmpkey = ( key . keyFlags & RSTLV_KEY_TYPE_FULL ) ? ( : : extractPrivateKey ( key ) ) : ( : : extractPublicKey ( key ) ) ;
RSA * rsakey = RSAPublicKey_dup ( tmpkey ) ; // always extract public key
RSA_free ( tmpkey ) ;
2014-03-29 10:18:05 -04:00
2014-05-08 05:20:25 -04:00
if ( ! rsakey )
{
std : : cerr < < " GxsSecurity::validateSignature(): Cannot validate signature. Keydata is incomplete. " < < std : : endl ;
2014-06-12 06:28:23 -04:00
key . print ( std : : cerr , 0 ) ;
2014-05-08 05:20:25 -04:00
return false ;
}
2014-03-29 10:18:05 -04:00
EVP_PKEY * signKey = EVP_PKEY_new ( ) ;
EVP_PKEY_assign_RSA ( signKey , rsakey ) ;
/* calc and check signature */
EVP_MD_CTX * mdctx = EVP_MD_CTX_create ( ) ;
EVP_VerifyInit ( mdctx , EVP_sha1 ( ) ) ;
EVP_VerifyUpdate ( mdctx , data , data_len ) ;
int signOk = EVP_VerifyFinal ( mdctx , ( unsigned char * ) signature . signData . bin_data , signature . signData . bin_len , signKey ) ;
/* clean up */
EVP_PKEY_free ( signKey ) ;
EVP_MD_CTX_destroy ( mdctx ) ;
return signOk ;
}
2015-05-19 17:28:46 -04:00
bool GxsSecurity : : validateNxsMsg ( const RsNxsMsg & msg , const RsTlvKeySignature & sign , const RsTlvSecurityKey & key )
2012-08-12 16:46:21 -04:00
{
2012-11-10 18:42:38 -05:00
# ifdef GXS_SECURITY_DEBUG
std : : cerr < < " GxsSecurity::validateNxsMsg() " ;
std : : cerr < < std : : endl ;
std : : cerr < < " RsNxsMsg : " ;
std : : cerr < < std : : endl ;
msg . print ( std : : cerr , 10 ) ;
std : : cerr < < std : : endl ;
# endif
2012-10-23 17:52:51 -04:00
2012-11-10 18:42:38 -05:00
RsGxsMsgMetaData & msgMeta = * ( msg . metaData ) ;
2012-10-23 17:52:51 -04:00
// /********************* check signature *******************/
2012-11-10 18:42:38 -05:00
/* check signature timeperiod */
2015-05-19 17:28:46 -04:00
if ( ( msgMeta . mPublishTs < key . startTS ) | | ( key . endTS ! = 0 & & msgMeta . mPublishTs > key . endTS ) )
2012-11-10 18:42:38 -05:00
{
# ifdef GXS_SECURITY_DEBUG
std : : cerr < < " GxsSecurity::validateNxsMsg() TS out of range " ;
std : : cerr < < std : : endl ;
# endif
return false ;
}
/* decode key */
const unsigned char * keyptr = ( const unsigned char * ) key . keyData . bin_data ;
long keylen = key . keyData . bin_len ;
unsigned int siglen = sign . signData . bin_len ;
unsigned char * sigbuf = ( unsigned char * ) sign . signData . bin_data ;
# ifdef DISTRIB_DEBUG
std : : cerr < < " GxsSecurity::validateNxsMsg() Decode Key " ;
std : : cerr < < " keylen: " < < keylen < < " siglen: " < < siglen ;
std : : cerr < < std : : endl ;
# endif
/* extract admin key */
2015-05-19 17:28:46 -04:00
RSA * rsakey = ( key . keyFlags & RSTLV_KEY_TYPE_FULL ) ? ( d2i_RSAPrivateKey ( NULL , & ( keyptr ) , keylen ) ) : ( d2i_RSAPublicKey ( NULL , & ( keyptr ) , keylen ) ) ;
2012-11-10 18:42:38 -05:00
if ( ! rsakey )
{
# ifdef GXS_SECURITY_DEBUG
std : : cerr < < " GxsSecurity::validateNxsMsg() " ;
std : : cerr < < " Invalid RSA Key " ;
std : : cerr < < std : : endl ;
key . print ( std : : cerr , 10 ) ;
# endif
}
RsTlvKeySignatureSet signSet = msgMeta . signSet ;
msgMeta . signSet . TlvClear ( ) ;
2013-02-07 18:04:16 -05:00
RsGxsMessageId msgId = msgMeta . mMsgId , origMsgId = msgMeta . mOrigMsgId ;
msgMeta . mOrigMsgId . clear ( ) ;
msgMeta . mMsgId . clear ( ) ;
2012-11-10 18:42:38 -05:00
uint32_t metaDataLen = msgMeta . serial_size ( ) ;
uint32_t allMsgDataLen = metaDataLen + msg . msg . bin_len ;
char * metaData = new char [ metaDataLen ] ;
char * allMsgData = new char [ allMsgDataLen ] ; // msgData + metaData
msgMeta . serialise ( metaData , & metaDataLen ) ;
// copy msg data and meta in allmsgData buffer
memcpy ( allMsgData , msg . msg . bin_data , msg . msg . bin_len ) ;
memcpy ( allMsgData + ( msg . msg . bin_len ) , metaData , metaDataLen ) ;
2014-05-15 17:55:34 -04:00
delete [ ] metaData ;
2012-11-10 18:42:38 -05:00
EVP_PKEY * signKey = EVP_PKEY_new ( ) ;
EVP_PKEY_assign_RSA ( signKey , rsakey ) ;
/* calc and check signature */
EVP_MD_CTX * mdctx = EVP_MD_CTX_create ( ) ;
EVP_VerifyInit ( mdctx , EVP_sha1 ( ) ) ;
EVP_VerifyUpdate ( mdctx , allMsgData , allMsgDataLen ) ;
int signOk = EVP_VerifyFinal ( mdctx , sigbuf , siglen , signKey ) ;
2014-05-15 17:55:34 -04:00
delete [ ] allMsgData ;
2012-11-10 18:42:38 -05:00
/* clean up */
EVP_PKEY_free ( signKey ) ;
EVP_MD_CTX_destroy ( mdctx ) ;
2013-02-07 18:04:16 -05:00
msgMeta . mOrigMsgId = origMsgId ;
msgMeta . mMsgId = msgId ;
msgMeta . signSet = signSet ;
2012-11-10 18:42:38 -05:00
if ( signOk = = 1 )
{
# ifdef GXS_SECURITY_DEBUG
std : : cerr < < " GxsSecurity::validateNxsMsg() Signature OK " ;
std : : cerr < < std : : endl ;
# endif
return true ;
}
# ifdef GXS_SECURITY_DEBUG
std : : cerr < < " GxsSecurity::validateNxsMsg() Signature invalid " ;
std : : cerr < < std : : endl ;
# endif
2012-10-23 17:52:51 -04:00
2012-11-02 19:35:10 -04:00
return false ;
2012-08-12 16:46:21 -04:00
}
2015-03-14 10:33:23 -04:00
bool GxsSecurity : : encrypt ( uint8_t * & out , uint32_t & outlen , const uint8_t * in , uint32_t inlen , const RsTlvSecurityKey & key )
2012-08-12 16:46:21 -04:00
{
# ifdef DISTRIB_DEBUG
2014-03-29 10:18:05 -04:00
std : : cerr < < " GxsSecurity::encrypt() " < < std : : endl ;
2012-08-12 16:46:21 -04:00
# endif
2015-06-22 17:35:39 -04:00
RSA * tmpkey = : : extractPublicKey ( key ) ;
RSA * rsa_publish_pub = RSAPublicKey_dup ( tmpkey ) ;
RSA_free ( tmpkey ) ;
2014-03-29 10:18:05 -04:00
EVP_PKEY * public_key = NULL ;
2012-08-12 16:46:21 -04:00
2014-03-29 10:18:05 -04:00
//RSA* rsa_publish = EVP_PKEY_get1_RSA(privateKey);
//rsa_publish_pub = RSAPublicKey_dup(rsa_publish);
2012-08-12 16:46:21 -04:00
2014-03-29 10:18:05 -04:00
if ( rsa_publish_pub ! = NULL )
{
public_key = EVP_PKEY_new ( ) ;
EVP_PKEY_assign_RSA ( public_key , rsa_publish_pub ) ;
2014-05-15 17:55:34 -04:00
}
else
{
2012-08-12 16:46:21 -04:00
# ifdef DISTRIB_DEBUG
2014-03-29 10:18:05 -04:00
std : : cerr < < " GxsSecurity(): Could not generate publish key " < < grpId
< < std : : endl ;
2012-08-12 16:46:21 -04:00
# endif
2014-03-29 10:18:05 -04:00
return false ;
}
2012-08-12 16:46:21 -04:00
2014-03-29 10:18:05 -04:00
EVP_CIPHER_CTX ctx ;
int eklen , net_ekl ;
unsigned char * ek ;
unsigned char iv [ EVP_MAX_IV_LENGTH ] ;
EVP_CIPHER_CTX_init ( & ctx ) ;
int out_currOffset = 0 ;
int out_offset = 0 ;
2012-08-12 16:46:21 -04:00
2014-03-29 10:18:05 -04:00
int max_evp_key_size = EVP_PKEY_size ( public_key ) ;
ek = ( unsigned char * ) malloc ( max_evp_key_size ) ;
const EVP_CIPHER * cipher = EVP_aes_128_cbc ( ) ;
int cipher_block_size = EVP_CIPHER_block_size ( cipher ) ;
int size_net_ekl = sizeof ( net_ekl ) ;
2012-08-12 16:46:21 -04:00
2014-03-29 10:18:05 -04:00
int max_outlen = inlen + cipher_block_size + EVP_MAX_IV_LENGTH + max_evp_key_size + size_net_ekl ;
2012-08-12 16:46:21 -04:00
2014-03-29 10:18:05 -04:00
// intialize context and send store encrypted cipher in ek
if ( ! EVP_SealInit ( & ctx , EVP_aes_128_cbc ( ) , & ek , & eklen , iv , & public_key , 1 ) ) return false ;
2012-08-12 16:46:21 -04:00
2014-03-29 10:18:05 -04:00
// now assign memory to out accounting for data, and cipher block size, key length, and key length val
2015-01-23 10:16:04 -05:00
out = ( uint8_t * ) malloc ( inlen + cipher_block_size + size_net_ekl + eklen + EVP_MAX_IV_LENGTH ) ;
if ( out = = NULL )
{
std : : cerr < < " gxssecurity::encrypt(): cnnot allocate memory of size " < < inlen + cipher_block_size + size_net_ekl + eklen + EVP_MAX_IV_LENGTH < < " to encrypt data. " < < std : : endl ;
return false ;
}
2012-08-12 16:46:21 -04:00
2014-03-29 10:18:05 -04:00
net_ekl = htonl ( eklen ) ;
memcpy ( ( unsigned char * ) out + out_offset , & net_ekl , size_net_ekl ) ;
out_offset + = size_net_ekl ;
2012-08-12 16:46:21 -04:00
2014-03-29 10:18:05 -04:00
memcpy ( ( unsigned char * ) out + out_offset , ek , eklen ) ;
out_offset + = eklen ;
2012-08-12 16:46:21 -04:00
2014-03-29 10:18:05 -04:00
memcpy ( ( unsigned char * ) out + out_offset , iv , EVP_MAX_IV_LENGTH ) ;
out_offset + = EVP_MAX_IV_LENGTH ;
2012-08-12 16:46:21 -04:00
2014-03-29 10:18:05 -04:00
// now encrypt actual data
2014-05-15 17:55:34 -04:00
if ( ! EVP_SealUpdate ( & ctx , ( unsigned char * ) out + out_offset , & out_currOffset , ( unsigned char * ) in , inlen ) )
{
2015-01-23 10:16:04 -05:00
free ( out ) ;
2014-05-15 17:55:34 -04:00
out = NULL ;
return false ;
}
2012-08-12 16:46:21 -04:00
2014-03-29 10:18:05 -04:00
// move along to partial block space
out_offset + = out_currOffset ;
2012-08-12 16:46:21 -04:00
2014-03-29 10:18:05 -04:00
// add padding
2014-05-15 17:55:34 -04:00
if ( ! EVP_SealFinal ( & ctx , ( unsigned char * ) out + out_offset , & out_currOffset ) )
{
2015-01-23 10:16:04 -05:00
free ( out ) ;
2014-05-15 17:55:34 -04:00
out = NULL ;
return false ;
}
2012-08-12 16:46:21 -04:00
2014-03-29 10:18:05 -04:00
// move to end
out_offset + = out_currOffset ;
2012-08-12 16:46:21 -04:00
2014-03-29 10:18:05 -04:00
// make sure offset has not gone passed valid memory bounds
2014-05-15 17:55:34 -04:00
if ( out_offset > max_outlen )
{
2015-01-23 10:16:04 -05:00
free ( out ) ;
2014-05-15 17:55:34 -04:00
out = NULL ;
return false ;
}
2012-08-12 16:46:21 -04:00
2014-03-29 10:18:05 -04:00
// free encrypted key data
free ( ek ) ;
2012-08-12 16:46:21 -04:00
2014-03-29 10:18:05 -04:00
outlen = out_offset ;
return true ;
2012-08-12 16:46:21 -04:00
}
2015-03-14 10:33:23 -04:00
bool GxsSecurity : : decrypt ( uint8_t * & out , uint32_t & outlen , const uint8_t * in , uint32_t inlen , const RsTlvSecurityKey & key )
2012-08-12 16:46:21 -04:00
{
# ifdef DISTRIB_DEBUG
2014-03-29 10:18:05 -04:00
std : : cerr < < " GxsSecurity::decrypt() " < < std : : endl ;
2012-08-12 16:46:21 -04:00
# endif
2015-06-22 17:35:39 -04:00
RSA * rsa_publish = extractPrivateKey ( key ) ;
2014-03-29 10:18:05 -04:00
EVP_PKEY * privateKey = NULL ;
//RSA* rsa_publish = EVP_PKEY_get1_RSA(privateKey);
//rsa_publish_pub = RSAPublicKey_dup(rsa_publish);
if ( rsa_publish ! = NULL )
{
privateKey = EVP_PKEY_new ( ) ;
EVP_PKEY_assign_RSA ( privateKey , rsa_publish ) ;
}
else
{
# ifdef DISTRIB_DEBUG
std : : cerr < < " GxsSecurity(): Could not generate publish key " < < grpId
< < std : : endl ;
# endif
return false ;
}
2012-08-12 16:46:21 -04:00
EVP_CIPHER_CTX ctx ;
int eklen = 0 , net_ekl = 0 ;
2015-01-05 14:26:50 -05:00
unsigned char * ek = ( unsigned char * ) malloc ( EVP_PKEY_size ( privateKey ) ) ;
2012-08-12 16:46:21 -04:00
unsigned char iv [ EVP_MAX_IV_LENGTH ] ;
EVP_CIPHER_CTX_init ( & ctx ) ;
int in_offset = 0 , out_currOffset = 0 ;
int size_net_ekl = sizeof ( net_ekl ) ;
memcpy ( & net_ekl , ( unsigned char * ) in , size_net_ekl ) ;
eklen = ntohl ( net_ekl ) ;
in_offset + = size_net_ekl ;
2015-01-05 14:26:50 -05:00
// Conservative limits to detect weird errors due to corrupted encoding.
2015-09-24 18:03:19 -04:00
if ( eklen < 0 | | eklen > 512 | | eklen + in_offset > ( int ) inlen )
2015-01-05 14:26:50 -05:00
{
std : : cerr < < " Error while deserialising encryption key length: eklen = " < < std : : dec < < eklen < < " . Giving up decryption. " < < std : : endl ;
free ( ek ) ;
return false ;
}
2014-09-14 15:23:23 -04:00
2012-08-12 16:46:21 -04:00
memcpy ( ek , ( unsigned char * ) in + in_offset , eklen ) ;
in_offset + = eklen ;
memcpy ( iv , ( unsigned char * ) in + in_offset , EVP_MAX_IV_LENGTH ) ;
in_offset + = EVP_MAX_IV_LENGTH ;
const EVP_CIPHER * cipher = EVP_aes_128_cbc ( ) ;
if ( ! EVP_OpenInit ( & ctx , cipher , ek , eklen , iv , privateKey ) ) return false ;
2014-05-15 17:55:34 -04:00
if ( inlen < in_offset )
{
std : : cerr < < " Severe error in " < < __PRETTY_FUNCTION__ < < " : cannot encrypt. " < < std : : endl ;
return false ;
}
2015-01-23 10:16:04 -05:00
out = ( uint8_t * ) malloc ( inlen - in_offset ) ;
if ( out = = NULL )
{
std : : cerr < < " gxssecurity::decrypt(): cannot allocate memory of size " < < inlen - in_offset < < " to decrypt data. " < < std : : endl ;
return false ;
}
2012-08-12 16:46:21 -04:00
2014-05-15 17:55:34 -04:00
if ( ! EVP_OpenUpdate ( & ctx , ( unsigned char * ) out , & out_currOffset , ( unsigned char * ) in + in_offset , inlen - in_offset ) )
{
2015-01-23 10:16:04 -05:00
free ( out ) ;
2014-05-15 17:55:34 -04:00
out = NULL ;
return false ;
}
2012-08-12 16:46:21 -04:00
2015-03-14 10:33:23 -04:00
outlen = out_currOffset ;
2012-08-12 16:46:21 -04:00
2014-05-15 17:55:34 -04:00
if ( ! EVP_OpenFinal ( & ctx , ( unsigned char * ) out + out_currOffset , & out_currOffset ) )
{
2015-01-23 10:16:04 -05:00
free ( out ) ;
2014-05-15 17:55:34 -04:00
out = NULL ;
return false ;
}
2012-08-12 16:46:21 -04:00
outlen + = out_currOffset ;
free ( ek ) ;
2014-05-15 17:55:34 -04:00
return true ;
2012-08-12 16:46:21 -04:00
}
2015-05-19 17:28:46 -04:00
bool GxsSecurity : : validateNxsGrp ( const RsNxsGrp & grp , const RsTlvKeySignature & sign , const RsTlvSecurityKey & key )
2012-08-12 16:46:21 -04:00
{
2013-03-10 11:08:04 -04:00
# ifdef GXS_SECURITY_DEBUG
std : : cerr < < " GxsSecurity::validateNxsGrp() " ;
std : : cerr < < std : : endl ;
std : : cerr < < " RsNxsGrp : " ;
std : : cerr < < std : : endl ;
grp . print ( std : : cerr , 10 ) ;
std : : cerr < < std : : endl ;
# endif
RsGxsGrpMetaData & grpMeta = * ( grp . metaData ) ;
/********************* check signature *******************/
/* check signature timeperiod */
2015-05-19 17:28:46 -04:00
if ( ( grpMeta . mPublishTs < key . startTS ) | | ( key . endTS ! = 0 & & grpMeta . mPublishTs > key . endTS ) )
2013-03-10 11:08:04 -04:00
{
# ifdef GXS_SECURITY_DEBUG
std : : cerr < < " GxsSecurity::validateNxsMsg() TS out of range " ;
std : : cerr < < std : : endl ;
# endif
return false ;
}
/* decode key */
const unsigned char * keyptr = ( const unsigned char * ) key . keyData . bin_data ;
long keylen = key . keyData . bin_len ;
unsigned int siglen = sign . signData . bin_len ;
unsigned char * sigbuf = ( unsigned char * ) sign . signData . bin_data ;
# ifdef DISTRIB_DEBUG
std : : cerr < < " GxsSecurity::validateNxsMsg() Decode Key " ;
std : : cerr < < " keylen: " < < keylen < < " siglen: " < < siglen ;
std : : cerr < < std : : endl ;
# endif
/* extract admin key */
2015-05-19 17:28:46 -04:00
RSA * rsakey = ( key . keyFlags & RSTLV_KEY_TYPE_FULL ) ? d2i_RSAPrivateKey ( NULL , & ( keyptr ) , keylen ) : d2i_RSAPublicKey ( NULL , & ( keyptr ) , keylen ) ;
2013-03-10 11:08:04 -04:00
if ( ! rsakey )
{
# ifdef GXS_SECURITY_DEBUG
std : : cerr < < " GxsSecurity::validateNxsGrp() " ;
std : : cerr < < " Invalid RSA Key " ;
std : : cerr < < std : : endl ;
key . print ( std : : cerr , 10 ) ;
# endif
}
RsTlvKeySignatureSet signSet = grpMeta . signSet ;
grpMeta . signSet . TlvClear ( ) ;
uint32_t metaDataLen = grpMeta . serial_size ( ) ;
uint32_t allGrpDataLen = metaDataLen + grp . grp . bin_len ;
char * metaData = new char [ metaDataLen ] ;
char * allGrpData = new char [ allGrpDataLen ] ; // msgData + metaData
grpMeta . serialise ( metaData , metaDataLen ) ;
// copy msg data and meta in allmsgData buffer
memcpy ( allGrpData , grp . grp . bin_data , grp . grp . bin_len ) ;
memcpy ( allGrpData + ( grp . grp . bin_len ) , metaData , metaDataLen ) ;
2014-05-15 17:55:34 -04:00
delete [ ] metaData ;
2013-03-10 11:08:04 -04:00
EVP_PKEY * signKey = EVP_PKEY_new ( ) ;
EVP_PKEY_assign_RSA ( signKey , rsakey ) ;
/* calc and check signature */
EVP_MD_CTX * mdctx = EVP_MD_CTX_create ( ) ;
EVP_VerifyInit ( mdctx , EVP_sha1 ( ) ) ;
EVP_VerifyUpdate ( mdctx , allGrpData , allGrpDataLen ) ;
int signOk = EVP_VerifyFinal ( mdctx , sigbuf , siglen , signKey ) ;
2014-05-15 17:55:34 -04:00
delete [ ] allGrpData ;
2013-03-10 11:08:04 -04:00
/* clean up */
EVP_PKEY_free ( signKey ) ;
EVP_MD_CTX_destroy ( mdctx ) ;
grpMeta . signSet = signSet ;
if ( signOk = = 1 )
{
# ifdef GXS_SECURITY_DEBUG
std : : cerr < < " GxsSecurity::validateNxsGrp() Signature OK " ;
std : : cerr < < std : : endl ;
# endif
return true ;
}
# ifdef GXS_SECURITY_DEBUG
std : : cerr < < " GxsSecurity::validateNxsGrp() Signature invalid " ;
std : : cerr < < std : : endl ;
# endif
return false ;
2012-08-12 16:46:21 -04:00
}