2012-03-26 17:17:04 -04:00
# include <stdexcept>
# include <sstream>
# include <iostream>
# include <iomanip>
# include <stdlib.h>
2012-03-27 16:48:21 -04:00
# include <string.h>
2012-03-26 17:17:04 -04:00
extern " C " {
# include <openpgpsdk/util.h>
2012-03-27 16:48:21 -04:00
# include <openpgpsdk/crypto.h>
2012-03-27 17:45:43 -04:00
# include <openpgpsdk/armour.h>
2012-03-27 16:48:21 -04:00
# include <openpgpsdk/keyring.h>
2012-03-27 17:45:43 -04:00
# include <openpgpsdk/readerwriter.h>
2012-04-01 17:10:54 -04:00
# include <openpgpsdk/validate.h>
2012-04-29 07:57:03 -04:00
# include <openpgpsdk/../../src/parse_local.h>
2012-03-26 17:17:04 -04:00
}
# include "pgphandler.h"
2012-04-29 07:57:03 -04:00
# include "retroshare/rsiface.h" // For rsicontrol.
2012-03-26 17:17:04 -04:00
2012-05-01 04:53:32 -04:00
PassphraseCallback PGPHandler : : _passphrase_callback = NULL ;
2012-03-26 17:17:04 -04:00
std : : string PGPIdType : : toStdString ( ) const
{
2012-03-27 16:48:21 -04:00
static const char out [ 16 ] = { ' 0 ' , ' 1 ' , ' 2 ' , ' 3 ' , ' 4 ' , ' 5 ' , ' 6 ' , ' 7 ' , ' 8 ' , ' 9 ' , ' A ' , ' B ' , ' C ' , ' D ' , ' E ' , ' F ' } ;
std : : string res ;
2012-03-26 17:17:04 -04:00
for ( int j = 0 ; j < KEY_ID_SIZE ; j + + )
2012-03-27 16:48:21 -04:00
{
res + = out [ ( bytes [ j ] > > 4 ) ] ;
res + = out [ bytes [ j ] & 0xf ] ;
}
2012-03-26 17:17:04 -04:00
2012-03-27 16:48:21 -04:00
return res ;
2012-03-26 17:17:04 -04:00
}
2012-04-04 15:27:07 -04:00
std : : string PGPFingerprintType : : toStdString ( ) const
{
static const char out [ 16 ] = { ' 0 ' , ' 1 ' , ' 2 ' , ' 3 ' , ' 4 ' , ' 5 ' , ' 6 ' , ' 7 ' , ' 8 ' , ' 9 ' , ' A ' , ' B ' , ' C ' , ' D ' , ' E ' , ' F ' } ;
std : : string res ;
for ( int j = 0 ; j < KEY_FINGERPRINT_SIZE ; j + + )
{
res + = out [ ( bytes [ j ] > > 4 ) ] ;
res + = out [ bytes [ j ] & 0xf ] ;
}
return res ;
}
2012-03-26 17:17:04 -04:00
2012-04-04 15:27:07 -04:00
PGPIdType PGPIdType : : fromUserId_hex ( const std : : string & s )
2012-03-26 17:17:04 -04:00
{
int n = 0 ;
if ( s . length ( ) ! = KEY_ID_SIZE * 2 )
throw std : : runtime_error ( " PGPIdType::PGPIdType: can only init from 16 chars hexadecimal string " ) ;
2012-04-04 15:27:07 -04:00
PGPIdType res ;
2012-03-26 17:17:04 -04:00
for ( int i = 0 ; i < KEY_ID_SIZE ; + + i )
{
2012-04-04 15:27:07 -04:00
res . bytes [ i ] = 0 ;
2012-03-26 17:17:04 -04:00
for ( int k = 0 ; k < 2 ; + + k )
{
char b = s [ n + + ] ;
if ( b > = ' A ' & & b < = ' F ' )
2012-04-04 15:27:07 -04:00
res . bytes [ i ] + = ( b - ' A ' + 10 ) < < 4 * ( 1 - k ) ;
2012-03-26 17:17:04 -04:00
else if ( b > = ' a ' & & b < = ' f ' )
2012-04-04 15:27:07 -04:00
res . bytes [ i ] + = ( b - ' a ' + 10 ) < < 4 * ( 1 - k ) ;
2012-03-26 17:17:04 -04:00
else if ( b > = ' 0 ' & & b < = ' 9 ' )
2012-04-04 15:27:07 -04:00
res . bytes [ i ] + = ( b - ' 0 ' ) < < 4 * ( 1 - k ) ;
2012-03-26 17:17:04 -04:00
else
throw std : : runtime_error ( " PGPIdType::Sha1CheckSum: can't init from non pure hexadecimal string " ) ;
}
}
2012-04-04 15:27:07 -04:00
return res ;
2012-03-26 17:17:04 -04:00
}
2012-04-04 15:27:07 -04:00
PGPIdType PGPIdType : : fromFingerprint_hex ( const std : : string & s )
{
if ( s . length ( ) ! = PGPFingerprintType : : KEY_FINGERPRINT_SIZE * 2 )
throw std : : runtime_error ( " PGPIdType::PGPIdType: can only init from 40 chars hexadecimal string " ) ;
PGPIdType res ;
2012-04-08 10:52:01 -04:00
int n = 2 * PGPFingerprintType : : KEY_FINGERPRINT_SIZE - 2 * PGPIdType : : KEY_ID_SIZE ;
2012-04-04 15:27:07 -04:00
for ( int i = 0 ; i < PGPIdType : : KEY_ID_SIZE ; + + i )
{
res . bytes [ i ] = 0 ;
for ( int k = 0 ; k < 2 ; + + k )
{
char b = s [ n + + ] ;
if ( b > = ' A ' & & b < = ' F ' )
res . bytes [ i ] + = ( b - ' A ' + 10 ) < < 4 * ( 1 - k ) ;
else if ( b > = ' a ' & & b < = ' f ' )
res . bytes [ i ] + = ( b - ' a ' + 10 ) < < 4 * ( 1 - k ) ;
else if ( b > = ' 0 ' & & b < = ' 9 ' )
res . bytes [ i ] + = ( b - ' 0 ' ) < < 4 * ( 1 - k ) ;
else
throw std : : runtime_error ( " PGPIdType::Sha1CheckSum: can't init from non pure hexadecimal string " ) ;
}
}
return res ;
}
PGPFingerprintType PGPFingerprintType : : fromFingerprint_hex ( const std : : string & s )
{
int n = 0 ;
if ( s . length ( ) ! = PGPFingerprintType : : KEY_FINGERPRINT_SIZE * 2 )
throw std : : runtime_error ( " PGPIdType::PGPIdType: can only init from 40 chars hexadecimal string " ) ;
PGPFingerprintType res ;
for ( int i = 0 ; i < PGPFingerprintType : : KEY_FINGERPRINT_SIZE ; + + i )
{
res . bytes [ i ] = 0 ;
2012-03-26 17:17:04 -04:00
2012-04-04 15:27:07 -04:00
for ( int k = 0 ; k < 2 ; + + k )
{
char b = s [ n + + ] ;
if ( b > = ' A ' & & b < = ' F ' )
res . bytes [ i ] + = ( b - ' A ' + 10 ) < < 4 * ( 1 - k ) ;
else if ( b > = ' a ' & & b < = ' f ' )
res . bytes [ i ] + = ( b - ' a ' + 10 ) < < 4 * ( 1 - k ) ;
else if ( b > = ' 0 ' & & b < = ' 9 ' )
res . bytes [ i ] + = ( b - ' 0 ' ) < < 4 * ( 1 - k ) ;
else
throw std : : runtime_error ( " PGPIdType::Sha1CheckSum: can't init from non pure hexadecimal string " ) ;
}
}
return res ;
}
2012-03-27 16:48:21 -04:00
PGPIdType : : PGPIdType ( const unsigned char b [ ] )
{
2012-04-04 15:27:07 -04:00
memcpy ( bytes , b , KEY_ID_SIZE ) ;
}
PGPFingerprintType : : PGPFingerprintType ( const unsigned char b [ ] )
{
memcpy ( bytes , b , KEY_FINGERPRINT_SIZE ) ;
2012-03-27 16:48:21 -04:00
}
2012-04-04 15:27:07 -04:00
2012-03-26 17:17:04 -04:00
uint64_t PGPIdType : : toUInt64 ( ) const
{
uint64_t res = 0 ;
for ( int i = 0 ; i < KEY_ID_SIZE ; + + i )
res = ( res < < 8 ) + bytes [ i ] ;
return res ;
}
2012-04-01 08:52:15 -04:00
ops_keyring_t * PGPHandler : : allocateOPSKeyring ( )
{
ops_keyring_t * kr = ( ops_keyring_t * ) malloc ( sizeof ( ops_keyring_t ) ) ;
kr - > nkeys = 0 ;
kr - > nkeys_allocated = 0 ;
kr - > keys = 0 ;
return kr ;
}
2012-05-01 04:53:32 -04:00
void PGPHandler : : setPassphraseCallback ( PassphraseCallback cb )
{
_passphrase_callback = cb ;
}
PGPHandler : : PGPHandler ( const std : : string & pubring , const std : : string & secring )
: pgphandlerMtx ( std : : string ( " PGPHandler " ) ) , _pubring_path ( pubring ) , _secring_path ( secring )
2012-03-26 17:17:04 -04:00
{
2012-05-01 04:53:32 -04:00
if ( _passphrase_callback = = NULL )
{
std : : cerr < < " WARNING: before created a PGPHandler, you need to init the passphrase callback using PGPHandler::setPassphraseCallback() " < < std : : endl ;
exit ( - 1 ) ;
}
2012-03-26 17:17:04 -04:00
// Allocate public and secret keyrings.
//
2012-04-01 08:52:15 -04:00
_pubring = allocateOPSKeyring ( ) ;
_secring = allocateOPSKeyring ( ) ;
2012-03-26 17:17:04 -04:00
// Read public and secret keyrings from supplied files.
//
if ( ops_false = = ops_keyring_read_from_file ( _pubring , false , pubring . c_str ( ) ) )
throw std : : runtime_error ( " PGPHandler::readKeyRing(): cannot read pubring. " ) ;
2012-04-01 08:52:15 -04:00
const ops_keydata_t * keydata ;
int i = 0 ;
while ( ( keydata = ops_keyring_get_key_by_index ( _pubring , i ) ) ! = NULL )
{
2012-04-09 13:03:47 -04:00
initCertificateInfo ( _public_keyring_map [ PGPIdType ( keydata - > key_id ) . toStdString ( ) ] , keydata , i ) ;
2012-04-01 08:52:15 -04:00
+ + i ;
}
2012-03-26 17:17:04 -04:00
std : : cerr < < " Pubring read successfully. " < < std : : endl ;
if ( ops_false = = ops_keyring_read_from_file ( _secring , false , secring . c_str ( ) ) )
throw std : : runtime_error ( " PGPHandler::readKeyRing(): cannot read secring. " ) ;
2012-04-01 08:52:15 -04:00
i = 0 ;
while ( ( keydata = ops_keyring_get_key_by_index ( _secring , i ) ) ! = NULL )
{
2012-04-09 13:03:47 -04:00
initCertificateInfo ( _secret_keyring_map [ PGPIdType ( keydata - > key_id ) . toStdString ( ) ] , keydata , i ) ;
2012-04-01 08:52:15 -04:00
+ + i ;
}
2012-03-26 17:17:04 -04:00
std : : cerr < < " Secring read successfully. " < < std : : endl ;
}
2012-04-09 13:03:47 -04:00
void PGPHandler : : initCertificateInfo ( PGPCertificateInfo & cert , const ops_keydata_t * keydata , uint32_t index )
{
// Parse certificate name
//
2012-04-22 07:36:34 -04:00
if ( keydata - > uids ! = NULL )
{
std : : string namestring ( ( char * ) keydata - > uids [ 0 ] . user_id ) ;
cert . _name = " " ;
2012-04-29 07:57:03 -04:00
uint32_t i = 0 ;
2012-04-22 07:36:34 -04:00
while ( i < namestring . length ( ) & & namestring [ i ] ! = ' ( ' & & namestring [ i ] ! = ' < ' ) { cert . _name + = namestring [ i ] ; + + i ; }
2012-04-09 13:03:47 -04:00
2012-04-22 07:36:34 -04:00
std : : string & next = ( namestring [ i ] = = ' ( ' ) ? cert . _comment : cert . _email ;
+ + i ;
next = " " ;
while ( i < namestring . length ( ) & & namestring [ i ] ! = ' ) ' & & namestring [ i ] ! = ' > ' ) { next + = namestring [ i ] ; + + i ; }
2012-04-09 13:03:47 -04:00
2012-04-22 07:36:34 -04:00
while ( i < namestring . length ( ) & & namestring [ i ] ! = ' ( ' & & namestring [ i ] ! = ' < ' ) { next + = namestring [ i ] ; + + i ; }
2012-04-26 15:37:15 -04:00
if ( i < namestring . length ( ) )
{
std : : string & next2 = ( namestring [ i ] = = ' ( ' ) ? cert . _comment : cert . _email ;
+ + i ;
next2 = " " ;
while ( i < namestring . length ( ) & & namestring [ i ] ! = ' ) ' & & namestring [ i ] ! = ' > ' ) { next2 + = namestring [ i ] ; + + i ; }
}
2012-04-22 07:36:34 -04:00
}
2012-04-09 13:03:47 -04:00
cert . _trustLvl = 1 ; // to be setup accordingly
2012-05-01 04:53:32 -04:00
cert . _validLvl = 1 ; // to be setup accordingly
2012-04-09 13:03:47 -04:00
cert . _key_index = index ;
2012-04-26 15:37:15 -04:00
cert . _flags = 0 ;
2012-04-09 13:03:47 -04:00
2012-04-22 07:36:34 -04:00
ops_fingerprint_t f ;
ops_fingerprint ( & f , & keydata - > key . pkey ) ;
cert . _fpr = PGPFingerprintType ( f . fingerprint ) ;
2012-04-09 13:03:47 -04:00
}
2012-03-26 17:17:04 -04:00
PGPHandler : : ~ PGPHandler ( )
{
std : : cerr < < " Freeing PGPHandler. Deleting keyrings. " < < std : : endl ;
2012-04-01 08:52:15 -04:00
// no need to free the the _map_ elements. They will be freed by the following calls:
//
2012-03-26 17:17:04 -04:00
ops_keyring_free ( _pubring ) ;
ops_keyring_free ( _secring ) ;
free ( _pubring ) ;
free ( _secring ) ;
}
2012-03-27 16:48:21 -04:00
2012-04-09 13:03:47 -04:00
bool PGPHandler : : printKeys ( ) const
{
2012-04-22 07:36:34 -04:00
std : : cerr < < " Printing details of all " < < std : : dec < < _public_keyring_map . size ( ) < < " keys: " < < std : : endl ;
2012-04-09 13:03:47 -04:00
for ( std : : map < std : : string , PGPCertificateInfo > : : const_iterator it ( _public_keyring_map . begin ( ) ) ; it ! = _public_keyring_map . end ( ) ; it + + )
{
std : : cerr < < " PGP Key: " < < it - > first < < std : : endl ;
std : : cerr < < " \t Name : " < < it - > second . _name < < std : : endl ;
std : : cerr < < " \t Email : " < < it - > second . _email < < std : : endl ;
std : : cerr < < " \t OwnSign : " < < ( it - > second . _flags & PGPCertificateInfo : : PGP_CERTIFICATE_FLAG_HAS_OWN_SIGNATURE ) < < std : : endl ;
std : : cerr < < " \t Accept Connect: " < < ( it - > second . _flags & PGPCertificateInfo : : PGP_CERTIFICATE_FLAG_HAS_OWN_SIGNATURE ) < < std : : endl ;
std : : cerr < < " \t trustLvl : " < < it - > second . _trustLvl < < std : : endl ;
std : : cerr < < " \t validLvl : " < < it - > second . _validLvl < < std : : endl ;
2012-04-22 07:36:34 -04:00
std : : cerr < < " \t fingerprint : " < < it - > second . _fpr . toStdString ( ) < < std : : endl ;
2012-04-09 13:03:47 -04:00
std : : set < std : : string > : : const_iterator sit ;
for ( sit = it - > second . signers . begin ( ) ; sit ! = it - > second . signers . end ( ) ; sit + + )
{
std : : cerr < < " \t \t Signer ID: " < < * sit < < " , Name: " ;
const PGPCertificateInfo * info = PGPHandler : : getCertificateInfo ( PGPIdType : : fromUserId_hex ( * sit ) ) ;
if ( info ! = NULL )
std : : cerr < < info - > _name ;
std : : cerr < < std : : endl ;
}
}
return true ;
}
const PGPCertificateInfo * PGPHandler : : getCertificateInfo ( const PGPIdType & id ) const
2012-03-27 16:48:21 -04:00
{
2012-04-09 13:03:47 -04:00
std : : map < std : : string , PGPCertificateInfo > : : const_iterator it ( _public_keyring_map . find ( id . toStdString ( ) ) ) ;
2012-03-27 16:48:21 -04:00
2012-04-09 13:03:47 -04:00
if ( it ! = _public_keyring_map . end ( ) )
return & it - > second ;
else
return NULL ;
2012-03-27 16:48:21 -04:00
}
bool PGPHandler : : availableGPGCertificatesWithPrivateKeys ( std : : list < PGPIdType > & ids )
{
// go through secret keyring, and check that we have the pubkey as well.
//
const ops_keydata_t * keydata = NULL ;
int i = 0 ;
while ( ( keydata = ops_keyring_get_key_by_index ( _secring , i + + ) ) ! = NULL )
{
// check that the key is in the pubring as well
if ( ops_keyring_find_key_by_id ( _pubring , keydata - > key_id ) ! = NULL )
ids . push_back ( PGPIdType ( keydata - > key_id ) ) ;
}
return true ;
}
2012-05-01 04:53:32 -04:00
ops_parse_cb_return_t cb_get_passphrase ( const ops_parser_content_t * content_ , ops_parse_cb_info_t * cbinfo ) // __attribute__((unused)))
2012-04-08 10:52:01 -04:00
{
const ops_parser_content_union_t * content = & content_ - > content ;
// validate_key_cb_arg_t *arg=ops_parse_cb_get_arg(cbinfo);
// ops_error_t **errors=ops_parse_cb_get_errors(cbinfo);
2012-04-29 07:57:03 -04:00
bool prev_was_bad = false ;
2012-04-08 10:52:01 -04:00
switch ( content_ - > tag )
{
2012-04-29 07:57:03 -04:00
case OPS_PARSER_CMD_GET_SK_PASSPHRASE_PREV_WAS_BAD : prev_was_bad = true ;
2012-04-08 10:52:01 -04:00
case OPS_PARSER_CMD_GET_SK_PASSPHRASE :
2012-04-29 07:57:03 -04:00
{
std : : string passwd ;
2012-05-01 04:53:32 -04:00
std : : string uid_hint = std : : string ( ( const char * ) cbinfo - > cryptinfo . keydata - > uids [ 0 ] . user_id ) ;
uid_hint + = " ( " + PGPIdType ( cbinfo - > cryptinfo . keydata - > key_id ) . toStdString ( ) + " ) " ;
2012-04-29 07:57:03 -04:00
2012-05-01 04:53:32 -04:00
passwd = PGPHandler : : passphraseCallback ( ) ( NULL , uid_hint . c_str ( ) , NULL , prev_was_bad ) ;
// if (rsicontrol->getNotify().askForPassword(uid_hint, prev_was_bad, passwd) == false)
// return OPS_RELEASE_MEMORY;
2012-04-29 07:57:03 -04:00
* ( content - > secret_key_passphrase . passphrase ) = ( char * ) ops_mallocz ( passwd . length ( ) + 1 ) ;
memcpy ( * ( content - > secret_key_passphrase . passphrase ) , passwd . c_str ( ) , passwd . length ( ) ) ;
return OPS_KEEP_MEMORY ;
}
break ;
2012-04-08 10:52:01 -04:00
default :
break ;
}
return OPS_RELEASE_MEMORY ;
}
2012-03-27 16:48:21 -04:00
bool PGPHandler : : GeneratePGPCertificate ( const std : : string & name , const std : : string & email , const std : : string & passwd , PGPIdType & pgpId , std : : string & errString )
{
static const int KEY_NUMBITS = 2048 ;
ops_user_id_t uid ;
2012-04-01 12:43:23 -04:00
char * s = strdup ( ( name + " " + email + " (Generated by RetroShare) " ) . c_str ( ) ) ;
2012-03-27 16:48:21 -04:00
uid . user_id = ( unsigned char * ) s ;
2012-03-29 17:51:37 -04:00
unsigned long int e = 17 ; // some prime number
2012-03-27 16:48:21 -04:00
ops_keydata_t * key = ops_rsa_create_selfsigned_keypair ( KEY_NUMBITS , e , & uid ) ;
2012-04-01 12:43:23 -04:00
free ( s ) ;
2012-03-27 16:48:21 -04:00
if ( ! key )
return false ;
2012-04-01 08:52:15 -04:00
// 1 - get a passphrase for encrypting.
2012-04-08 10:52:01 -04:00
std : : string passphrase = _passphrase_callback ( NULL , PGPIdType ( key - > key_id ) . toStdString ( ) . c_str ( ) , " Please enter passwd for encrypting your key : " , false ) ;
2012-03-27 16:48:21 -04:00
2012-04-01 08:52:15 -04:00
// 2 - save the private key encrypted to a temporary memory buffer
ops_create_info_t * cinfo = NULL ;
ops_memory_t * buf = NULL ;
ops_setup_memory_write ( & cinfo , & buf , 0 ) ;
ops_write_transferable_secret_key ( key , ( unsigned char * ) passphrase . c_str ( ) , passphrase . length ( ) , ops_false , cinfo ) ;
2012-04-01 12:43:23 -04:00
ops_keydata_free ( key ) ;
2012-04-01 08:52:15 -04:00
// 3 - read the file into a keyring
ops_keyring_t * tmp_keyring = allocateOPSKeyring ( ) ;
if ( ! ops_keyring_read_from_mem ( tmp_keyring , ops_false , buf ) )
{
std : : cerr < < " Cannot re-read key from memory!! " < < std : : endl ;
return false ;
}
ops_teardown_memory_write ( cinfo , buf ) ; // cleanup memory
// 4 - copy the private key to the private keyring
pgpId = PGPIdType ( tmp_keyring - > keys [ 0 ] . key_id ) ;
addNewKeyToOPSKeyring ( _secring , tmp_keyring - > keys [ 0 ] ) ;
2012-04-09 13:03:47 -04:00
initCertificateInfo ( _secret_keyring_map [ pgpId . toStdString ( ) ] , & tmp_keyring - > keys [ 0 ] , _secring - > nkeys - 1 ) ;
2012-04-01 08:52:15 -04:00
std : : cerr < < " Added new secret key with id " < < pgpId . toStdString ( ) < < " to secret keyring. " < < std : : endl ;
2012-04-01 17:10:54 -04:00
// 5 - copy the private key to the public keyring
addNewKeyToOPSKeyring ( _pubring , tmp_keyring - > keys [ 0 ] ) ;
2012-04-09 13:03:47 -04:00
initCertificateInfo ( _public_keyring_map [ pgpId . toStdString ( ) ] , & tmp_keyring - > keys [ 0 ] , _pubring - > nkeys - 1 ) ;
2012-04-01 17:10:54 -04:00
std : : cerr < < " Added new public key with id " < < pgpId . toStdString ( ) < < " to public keyring. " < < std : : endl ;
// 6 - clean
2012-03-29 17:51:37 -04:00
2012-04-01 08:52:15 -04:00
ops_keyring_free ( tmp_keyring ) ;
free ( tmp_keyring ) ;
2012-03-29 17:51:37 -04:00
return true ;
}
std : : string PGPHandler : : makeRadixEncodedPGPKey ( const ops_keydata_t * key )
{
2012-03-27 17:45:43 -04:00
ops_boolean_t armoured = ops_true ;
ops_create_info_t * cinfo ;
2012-04-01 08:52:15 -04:00
ops_memory_t * buf = NULL ;
2012-03-27 17:45:43 -04:00
ops_setup_memory_write ( & cinfo , & buf , 0 ) ;
ops_write_transferable_public_key ( key , armoured , cinfo ) ;
2012-03-29 17:51:37 -04:00
ops_writer_close ( cinfo ) ;
2012-03-27 17:45:43 -04:00
2012-03-29 17:51:37 -04:00
std : : string akey ( ( char * ) ops_memory_get_data ( buf ) , ops_memory_get_length ( buf ) ) ;
2012-03-27 17:45:43 -04:00
2012-03-29 17:51:37 -04:00
ops_teardown_memory_write ( cinfo , buf ) ;
2012-03-27 17:45:43 -04:00
2012-03-29 17:51:37 -04:00
return akey ;
}
2012-04-01 08:52:15 -04:00
const ops_keydata_t * PGPHandler : : getSecretKey ( const PGPIdType & id ) const
{
2012-04-09 13:03:47 -04:00
std : : map < std : : string , PGPCertificateInfo > : : const_iterator res = _secret_keyring_map . find ( id . toStdString ( ) ) ;
2012-04-01 08:52:15 -04:00
if ( res = = _secret_keyring_map . end ( ) )
return NULL ;
else
2012-04-09 13:03:47 -04:00
return ops_keyring_get_key_by_index ( _secring , res - > second . _key_index ) ;
2012-04-01 08:52:15 -04:00
}
const ops_keydata_t * PGPHandler : : getPublicKey ( const PGPIdType & id ) const
{
2012-04-09 13:03:47 -04:00
std : : map < std : : string , PGPCertificateInfo > : : const_iterator res = _public_keyring_map . find ( id . toStdString ( ) ) ;
2012-04-01 08:52:15 -04:00
if ( res = = _public_keyring_map . end ( ) )
return NULL ;
else
2012-04-09 13:03:47 -04:00
return ops_keyring_get_key_by_index ( _pubring , res - > second . _key_index ) ;
2012-04-01 08:52:15 -04:00
}
2012-03-29 17:51:37 -04:00
std : : string PGPHandler : : SaveCertificateToString ( const PGPIdType & id , bool include_signatures )
{
2012-04-01 08:52:15 -04:00
const ops_keydata_t * key = getPublicKey ( id ) ;
2012-03-29 17:51:37 -04:00
if ( key = = NULL )
{
std : : cerr < < " Cannot output key " < < id . toStdString ( ) < < " : not found in keyring. " < < std : : endl ;
return " " ;
}
return makeRadixEncodedPGPKey ( key ) ;
2012-03-27 16:48:21 -04:00
}
2012-04-01 08:52:15 -04:00
void PGPHandler : : addNewKeyToOPSKeyring ( ops_keyring_t * kr , const ops_keydata_t & key )
{
kr - > keys = ( ops_keydata_t * ) realloc ( kr - > keys , ( kr - > nkeys + 1 ) * sizeof ( ops_keydata_t ) ) ;
memset ( & kr - > keys [ kr - > nkeys ] , 0 , sizeof ( ops_keydata_t ) ) ;
ops_keydata_copy ( & kr - > keys [ kr - > nkeys ] , & key ) ;
kr - > nkeys + + ;
}
bool PGPHandler : : LoadCertificateFromString ( const std : : string & pgp_cert , PGPIdType & id , std : : string & error_string )
{
ops_keyring_t * tmp_keyring = allocateOPSKeyring ( ) ;
ops_memory_t * mem = ops_memory_new ( ) ;
ops_memory_add ( mem , ( unsigned char * ) pgp_cert . c_str ( ) , pgp_cert . length ( ) ) ;
if ( ! ops_keyring_read_from_mem ( tmp_keyring , ops_true , mem ) )
{
ops_keyring_free ( tmp_keyring ) ;
2012-04-01 12:43:23 -04:00
free ( tmp_keyring ) ;
2012-04-01 08:52:15 -04:00
ops_memory_release ( mem ) ;
2012-04-01 12:43:23 -04:00
free ( mem ) ;
2012-04-01 08:52:15 -04:00
std : : cerr < < " Could not read key. Format error? " < < std : : endl ;
error_string = std : : string ( " Could not read key. Format error? " ) ;
return false ;
}
ops_memory_release ( mem ) ;
2012-04-01 12:43:23 -04:00
free ( mem ) ;
2012-04-01 08:52:15 -04:00
error_string . clear ( ) ;
std : : cerr < < " Key read correctly: " < < std : : endl ;
ops_keyring_list ( tmp_keyring ) ;
const ops_keydata_t * keydata = NULL ;
int i = 0 ;
while ( ( keydata = ops_keyring_get_key_by_index ( tmp_keyring , i + + ) ) ! = NULL )
{
id = PGPIdType ( keydata - > key_id ) ;
addNewKeyToOPSKeyring ( _pubring , * keydata ) ;
2012-04-09 13:03:47 -04:00
initCertificateInfo ( _public_keyring_map [ id . toStdString ( ) ] , keydata , _pubring - > nkeys - 1 ) ;
2012-04-01 08:52:15 -04:00
}
std : : cerr < < " Added the key in the main public keyring. " < < std : : endl ;
ops_keyring_free ( tmp_keyring ) ;
2012-04-01 12:43:23 -04:00
free ( tmp_keyring ) ;
2012-04-01 08:52:15 -04:00
return true ;
}
2012-04-08 10:52:01 -04:00
bool PGPHandler : : encryptTextToFile ( const PGPIdType & key_id , const std : : string & text , const std : : string & outfile )
{
const char * filename = " armour_nocompress_sign.asc " ;
ops_create_info_t * info ;
int fd = ops_setup_file_write ( & info , outfile . c_str ( ) , ops_true ) ;
const ops_keydata_t * public_key = getPublicKey ( key_id ) ;
if ( public_key = = NULL )
{
std : : cerr < < " Cannot get public key of id " < < key_id . toStdString ( ) < < std : : endl ;
return false ;
}
if ( fd < 0 )
{
fprintf ( stderr , " Cannot write to %s \n " , filename ) ;
return false ;
}
ops_encrypt_stream ( info , public_key , NULL , ops_false , ops_true ) ;
ops_write ( text . c_str ( ) , text . length ( ) , info ) ;
ops_writer_close ( info ) ;
ops_create_info_delete ( info ) ;
return true ;
}
// ops_parse_cb_return_t pgphandler_callback_write_parsed(const ops_parser_content_t *content_, ops_parse_cb_info_t *cbinfo)
// {
// ops_parser_content_union_t* content =(ops_parser_content_union_t *)&content_->content;
// static ops_boolean_t skipping;
//
// if(content_->tag != OPS_PTAG_CT_UNARMOURED_TEXT && skipping)
// {
// puts("...end of skip");
// skipping=ops_false;
// }
//
// switch(content_->tag)
// {
// case OPS_PTAG_CT_UNARMOURED_TEXT:
// printf("OPS_PTAG_CT_UNARMOURED_TEXT\n");
// if(!skipping)
// {
// puts("Skipping...");
// skipping=ops_true;
// }
// fwrite(content->unarmoured_text.data, 1, content->unarmoured_text.length, stdout);
// break;
//
// case OPS_PTAG_CT_PK_SESSION_KEY:
// return callback_pk_session_key(content_, cbinfo);
// break;
//
// case OPS_PARSER_CMD_GET_SECRET_KEY:
// return callback_cmd_get_secret_key(content_, cbinfo);
// break;
//
// case OPS_PARSER_CMD_GET_SK_PASSPHRASE:
// // return callback_cmd_get_secret_key_passphrase(content_,cbinfo);
// return cbinfo->cryptinfo.cb_get_passphrase(content_, cbinfo);
// break;
//
// case OPS_PTAG_CT_LITERAL_DATA_BODY:
// return callback_literal_data(content_, cbinfo);
// break;
//
// case OPS_PTAG_CT_ARMOUR_HEADER:
// case OPS_PTAG_CT_ARMOUR_TRAILER:
// case OPS_PTAG_CT_ENCRYPTED_PK_SESSION_KEY:
// case OPS_PTAG_CT_COMPRESSED:
// case OPS_PTAG_CT_LITERAL_DATA_HEADER:
// case OPS_PTAG_CT_SE_IP_DATA_BODY:
// case OPS_PTAG_CT_SE_IP_DATA_HEADER:
// case OPS_PTAG_CT_SE_DATA_BODY:
// case OPS_PTAG_CT_SE_DATA_HEADER:
//
// // Ignore these packets
// // They're handled in ops_parse_one_packet()
// // and nothing else needs to be done
// break;
//
// default:
// // return callback_general(content_,cbinfo);
// break;
// // fprintf(stderr,"Unexpected packet tag=%d (0x%x)\n",content_->tag,
// // content_->tag);
// // assert(0);
// }
//
// return OPS_RELEASE_MEMORY;
// }
bool PGPHandler : : decryptTextFromFile ( const PGPIdType & key_id , std : : string & text , const std : : string & inputfile )
{
unsigned char * out_buf = NULL ;
std : : string buf ;
FILE * f = fopen ( inputfile . c_str ( ) , " rb " ) ;
char c ;
while ( ( c = getc ( f ) ) ! = EOF )
buf + = c ;
fclose ( f ) ;
2012-04-22 07:36:34 -04:00
std : : cerr < < " PGPHandler::decryptTextFromFile: read a file of length " < < std : : dec < < buf . length ( ) < < std : : endl ;
std : : cerr < < " buf= \" " < < buf < < " \" " < < std : : endl ;
2012-04-08 10:52:01 -04:00
int out_length ;
ops_boolean_t res = ops_decrypt_memory ( ( const unsigned char * ) buf . c_str ( ) , buf . length ( ) , & out_buf , & out_length , _secring , ops_true , cb_get_passphrase ) ;
text = std : : string ( ( char * ) out_buf , out_length ) ;
return ( bool ) res ;
}
2012-04-01 08:52:15 -04:00
bool PGPHandler : : SignDataBin ( const PGPIdType & id , const void * data , const uint32_t len , unsigned char * sign , unsigned int * signlen )
{
// need to find the key and to decrypt it.
const ops_keydata_t * key = getSecretKey ( id ) ;
if ( ! key )
{
std : : cerr < < " Cannot sign: no secret key with id " < < id . toStdString ( ) < < std : : endl ;
return false ;
}
2012-04-08 10:52:01 -04:00
std : : string passphrase = _passphrase_callback ( NULL , PGPIdType ( key - > key_id ) . toStdString ( ) . c_str ( ) , " Please enter passwd for encrypting your key : " , false ) ;
2012-04-01 08:52:15 -04:00
ops_secret_key_t * secret_key = ops_decrypt_secret_key_from_data ( key , passphrase . c_str ( ) ) ;
if ( ! secret_key )
{
std : : cerr < < " Key decryption went wrong. Wrong passwd? " < < std : : endl ;
return false ;
}
// then do the signature.
2012-05-01 04:53:32 -04:00
ops_memory_t * memres = ops_sign_buf ( data , len , ( ops_sig_type_t ) 0x00 , secret_key , ops_false , ops_false ) ;
2012-04-01 08:52:15 -04:00
if ( ! memres )
return false ;
uint32_t tlen = std : : min ( * signlen , ( uint32_t ) ops_memory_get_length ( memres ) ) ;
memcpy ( sign , ops_memory_get_data ( memres ) , tlen ) ;
* signlen = tlen ;
2012-04-01 12:43:23 -04:00
ops_memory_release ( memres ) ;
free ( memres ) ;
ops_secret_key_free ( secret_key ) ;
free ( secret_key ) ;
2012-04-01 08:52:15 -04:00
return true ;
}
2012-04-04 15:27:07 -04:00
bool PGPHandler : : getKeyFingerprint ( const PGPIdType & id , PGPFingerprintType & fp ) const
2012-04-01 17:10:54 -04:00
{
2012-04-04 15:27:07 -04:00
const ops_keydata_t * key = getPublicKey ( id ) ;
2012-04-01 17:10:54 -04:00
2012-04-04 15:27:07 -04:00
if ( key = = NULL )
return false ;
2012-04-01 17:10:54 -04:00
2012-04-04 15:27:07 -04:00
ops_fingerprint_t f ;
ops_fingerprint ( & f , & key - > key . pkey ) ;
2012-04-01 17:10:54 -04:00
2012-04-04 15:27:07 -04:00
fp = PGPFingerprintType ( f . fingerprint ) ;
2012-04-01 17:10:54 -04:00
2012-04-04 15:27:07 -04:00
return true ;
}
2012-04-26 15:37:15 -04:00
bool PGPHandler : : VerifySignBin ( const void * literal_data , uint32_t literal_data_length , unsigned char * sign , unsigned int sign_len , const PGPFingerprintType & key_fingerprint )
2012-04-04 15:27:07 -04:00
{
PGPIdType id = PGPIdType : : fromFingerprint_hex ( key_fingerprint . toStdString ( ) ) ;
const ops_keydata_t * key = getPublicKey ( id ) ;
if ( key = = NULL )
{
std : : cerr < < " No key returned by fingerprint " < < key_fingerprint . toStdString ( ) < < " , and ID " < < id . toStdString ( ) < < " , signature verification failed! " < < std : : endl ;
return false ;
}
// Check that fingerprint is the same.
const ops_public_key_t * pkey = & key - > key . pkey ;
ops_fingerprint_t fp ;
ops_fingerprint ( & fp , pkey ) ;
if ( key_fingerprint ! = PGPFingerprintType ( fp . fingerprint ) )
{
std : : cerr < < " Key fingerprint does not match " < < key_fingerprint . toStdString ( ) < < " , for ID " < < id . toStdString ( ) < < " , signature verification failed! " < < std : : endl ;
return false ;
}
2012-04-26 17:39:45 -04:00
std : : cerr < < " Verifying signature from fingerprint " < < key_fingerprint . toStdString ( ) < < " , length " < < std : : dec < < sign_len < < " , literal data length = " < < literal_data_length < < std : : endl ;
2012-04-04 15:27:07 -04:00
2012-04-26 15:37:15 -04:00
return ops_validate_detached_signature ( literal_data , literal_data_length , sign , sign_len , key ) ;
2012-04-01 17:10:54 -04:00
}
2012-04-09 13:03:47 -04:00
void PGPHandler : : setAcceptConnexion ( const PGPIdType & id , bool b )
{
std : : map < std : : string , PGPCertificateInfo > : : iterator res = _public_keyring_map . find ( id . toStdString ( ) ) ;
if ( res ! = _public_keyring_map . end ( ) )
2012-04-29 07:57:03 -04:00
{
2012-04-09 13:03:47 -04:00
if ( b )
res - > second . _flags | = PGPCertificateInfo : : PGP_CERTIFICATE_FLAG_ACCEPT_CONNEXION ;
else
res - > second . _flags & = ~ PGPCertificateInfo : : PGP_CERTIFICATE_FLAG_ACCEPT_CONNEXION ;
2012-04-29 07:57:03 -04:00
}
2012-04-09 13:03:47 -04:00
}
bool PGPHandler : : getGPGFilteredList ( std : : list < PGPIdType > & list , bool ( * filter ) ( const PGPCertificateInfo & ) ) const
{
list . clear ( ) ;
for ( std : : map < std : : string , PGPCertificateInfo > : : const_iterator it ( _public_keyring_map . begin ( ) ) ; it ! = _public_keyring_map . end ( ) ; + + it )
if ( filter = = NULL | | ( * filter ) ( it - > second ) )
list . push_back ( PGPIdType : : fromUserId_hex ( it - > first ) ) ;
return true ;
}
bool PGPHandler : : isGPGId ( const std : : string & id )
{
return _public_keyring_map . find ( id ) ! = _public_keyring_map . end ( ) ;
}
bool PGPHandler : : isGPGSigned ( const std : : string & id )
{
std : : map < std : : string , PGPCertificateInfo > : : const_iterator res = _public_keyring_map . find ( id ) ;
return res ! = _public_keyring_map . end ( ) & & ( res - > second . _flags & PGPCertificateInfo : : PGP_CERTIFICATE_FLAG_HAS_OWN_SIGNATURE ) ;
}
bool PGPHandler : : isGPGAccepted ( const std : : string & id )
{
std : : map < std : : string , PGPCertificateInfo > : : const_iterator res = _public_keyring_map . find ( id ) ;
2012-04-26 17:39:45 -04:00
return ( res ! = _public_keyring_map . end ( ) ) & & ( res - > second . _flags & PGPCertificateInfo : : PGP_CERTIFICATE_FLAG_ACCEPT_CONNEXION ) ;
2012-04-09 13:03:47 -04:00
}