2011-04-15 06:50:08 +00:00
/*! @file
@id $Id$
*/
// 1 2 3 4 5 6 7 8
// 45678901234567890123456789012345678901234567890123456789012345678901234567890
#ifndef __OPENSSL_ENGINE_HXX__
#define __OPENSSL_ENGINE_HXX__
#include <openssl/opensslv.h>
#ifndef OPENSSL_VERSION_NUMBER
# error OpenSSL Version Number not Found
#elif OPENSSL_VERSION_NUMBER < 0x10000000L
# define OPENSSL_0
# define OPENSSL_V0_CONST
#else
# define OPENSSL_1
# define OPENSSL_V0_CONST const
#endif
2011-11-10 13:28:18 +00:00
#undef DATADIR
2011-04-15 06:50:08 +00:00
#include <openssl/engine.h>
#include <map>
#include <string>
#ifndef OPENSSL_CHECK
#include <stdexcept>
#include <sstream>
#if __GNUC__ >= 2
//! Macro for internal OpenSSL checks.
/*! You can define a different implementation in your compile call */
#define OPENSSL_CHECK(X) if (!X) {ERR_load_ENGINE_strings(); std::stringstream ss; for (unsigned int err(0); err=ERR_get_error();) ss<<"Error: "<<ERR_error_string(err, 0)<<"; "; ss<<"Command "<<#X<<" failed in function "<<__PRETTY_FUNCTION__<<" in file "<<__FILE__<<":"<<__LINE__; throw std::runtime_error(ss.str());}
#else
#define OPENSSL_CHECK(X) if (!X) {ERR_load_ENGINE_strings(); std::stringstream ss; for (unsigned int err(0); err=ERR_get_error();) ss<<"Error: "<<ERR_error_string(err, 0)<<"; "; ss<<"Command "<<#X<<" failed in file "<<__FILE__<<":"<<__LINE__; throw std::runtime_error(ss.str());}
#endif
#endif
#ifndef OPENSSL_LOG
#include <iostream>
#if __GNUC__ >= 2
//! Openssl Logging
/*! If you want to change openssl logging mechanism, just
redefine your own OPENSSL_LOG macro before <code>#include
<openssl.hxx></code>. Define it empty for no logging at
all. By default logs to <code>std::clog</code>. */
#define OPENSSL_LOG(X) std::clog<<X<<" @ "<<__PRETTY_FUNCTION__<<std::endl
#else
//! Openssl Logging
/*! If you want to change openssl logging mechanism, just
redefine your own OPENSSL_LOG macro before <code>#include
<openssl.hxx></code>. Define it empty for no logging at
all. By default logs to <code>std::clog</code>. */
#define OPENSSL_LOG(X) std::clog<<X<<" @ "<<__FILE__<<__LINE__<<std::endl
#endif
#endif
//! @addtogroup gopenssl
//@{
//! @defgroup opensslengine OpenSSL Engine C++ Wrapper
//@}
namespace openssl {
//! @addtogroup opensslengine
//@{
//! Abstract Engine Base
/*! Inherit and overwrite to implement your own Engine.
Then in the scope where you need it, register your engine:
<code>
openssl::RegisterEngine myEngine(new MyEngine);
</code> */
class Engine {
public :
Engine () : _e ( ENGINE_new ()) {
OPENSSL_LOG ( "log" );
}
virtual ~ Engine () {
OPENSSL_LOG ( "log" );
2013-04-02 12:07:57 +00:00
// removed EngineMapper::destroy because of crash:
// https://dev.marc.waeckerlin.org/projects/libpcscxx/ticket/25
//OPENSSL_CHECK(ENGINE_free(_e));
2011-04-15 06:50:08 +00:00
}
virtual const char * id () = 0 ;
virtual const char * name () = 0 ;
virtual int init () {
OPENSSL_LOG ( "log" );
return 1 ;
}
virtual int finish () {
OPENSSL_LOG ( "log" );
return 1 ;
}
virtual int ctrl ( int , long , void * , void ( * )()) {
OPENSSL_LOG ( "log" );
return 1 ;
}
virtual int cmd () {
OPENSSL_LOG ( "log" );
return 1 ;
}
virtual EVP_PKEY * pubkey ( const char * , UI_METHOD * , void * ) {
OPENSSL_LOG ( "log" );
return 0 ;
}
virtual EVP_PKEY * privkey ( const char * , UI_METHOD * , void * ) {
OPENSSL_LOG ( "log" );
return 0 ;
}
virtual int rsaEncrypt () {
OPENSSL_LOG ( "log" );
return 1 ;
}
virtual int rsaDecrypt () {
OPENSSL_LOG ( "log" );
return 1 ;
}
2011-04-21 06:30:51 +00:00
virtual std :: string rsaSign ( const std :: string & , unsigned int ) {
2011-04-15 06:50:08 +00:00
OPENSSL_LOG ( "log" );
2011-04-21 06:30:51 +00:00
throw std :: runtime_error ( "rsaSign not implemented" );
2011-04-15 06:50:08 +00:00
}
virtual int rsaVerify () {
OPENSSL_LOG ( "log" );
return 1 ;
}
virtual int rsaFinish () {
OPENSSL_LOG ( "log" );
return 1 ;
}
2011-04-21 06:30:51 +00:00
protected :
2011-04-15 06:50:08 +00:00
friend class EngineMapper ;
ENGINE * _e ;
};
class EngineMapper {
public :
2011-04-21 09:50:52 +00:00
static void add ( Engine * e ) {
2011-04-15 06:50:08 +00:00
OPENSSL_LOG ( "log" );
_prototypes [ e -> id ()] = e ;
_map [ e -> _e ] = e ;
OPENSSL_CHECK ( ENGINE_set_id ( e -> _e , e -> id ()));
OPENSSL_CHECK ( ENGINE_set_name ( e -> _e , e -> name ()));
2013-04-02 08:32:14 +00:00
// removed EngineMapper::destroy because of crash:
// https://dev.marc.waeckerlin.org/projects/libpcscxx/ticket/25
//OPENSSL_CHECK(ENGINE_set_destroy_function
// (e->_e, EngineMapper::destroy));
2011-04-15 06:50:08 +00:00
OPENSSL_CHECK ( ENGINE_set_init_function ( e -> _e , EngineMapper :: init ));
OPENSSL_CHECK ( ENGINE_set_finish_function ( e -> _e , EngineMapper :: finish ));
OPENSSL_CHECK ( ENGINE_set_ctrl_function ( e -> _e , EngineMapper :: ctrl ));
//OPENSSL_CHECK(ENGINE_set_cmd_defns(e->_e, EngineMapper::cmd));
#ifndef OPENSSL_NO_RSA
OPENSSL_CHECK ( ENGINE_set_RSA ( e -> _e , rsa ()));
#endif
#ifndef OPENSSL_NO_DSA
// OPENSSL_CHECK(ENGINE_set_DSA(e->_e, DSA_get_default_method()));
#endif
#ifndef OPENSSL_NO_DH
// OPENSSL_CHECK(ENGINE_set_DH(e->_e, DSA_get_default_method()));
#endif
// OPENSSL_CHECK(ENGINE_set_RAND(e->_e, rand()));
OPENSSL_CHECK ( ENGINE_set_load_pubkey_function ( e -> _e , pubkey ));
OPENSSL_CHECK ( ENGINE_set_load_privkey_function ( e -> _e , privkey ));
OPENSSL_CHECK ( ENGINE_init ( e -> _e ));
OPENSSL_CHECK ( ENGINE_add ( e -> _e ));
}
static void remove ( Engine * e ) {
2013-04-02 12:54:17 +00:00
OPENSSL_LOG ( "log" );
2011-04-15 06:50:08 +00:00
OPENSSL_CHECK ( ENGINE_remove ( e -> _e ));
OPENSSL_CHECK ( ENGINE_finish ( e -> _e ));
_map . erase ( e -> _e );
delete e ;
}
private :
static int destroy ( ENGINE * e ) {
OPENSSL_LOG ( "log" );
return 1 ;
}
static int init ( ENGINE * e ) {
OPENSSL_LOG ( "log" );
2011-05-03 11:11:35 +00:00
Map :: iterator it ( _map . find ( e ));
return it != _map . end () ? it -> second -> init () : 0 ;
2011-04-15 06:50:08 +00:00
}
static int finish ( ENGINE * e ) {
OPENSSL_LOG ( "log" );
2011-05-03 11:11:35 +00:00
Map :: iterator it ( _map . find ( e ));
return it != _map . end () ? it -> second -> finish () : 0 ;
2011-04-15 06:50:08 +00:00
}
static int ctrl ( ENGINE * e , int cmd , long i , void * p , void ( * f )()) {
OPENSSL_LOG ( "log" );
2011-05-03 11:11:35 +00:00
Map :: iterator it ( _map . find ( e ));
return it != _map . end () ? it -> second -> ctrl ( cmd , i , p , f ) : 0 ;
2011-04-15 06:50:08 +00:00
}
static EVP_PKEY * pubkey ( ENGINE * e , const char * c , UI_METHOD * u , void * d ) {
OPENSSL_LOG ( "log" );
2011-05-03 11:11:35 +00:00
Map :: iterator it ( _map . find ( e ));
return it != _map . end () ? it -> second -> pubkey ( c , u , d ) : 0 ;
2011-04-15 06:50:08 +00:00
}
static EVP_PKEY * privkey ( ENGINE * e , const char * c , UI_METHOD * u , void * d ) {
OPENSSL_LOG ( "log" );
2011-05-03 11:11:35 +00:00
Map :: iterator it ( _map . find ( e ));
return it != _map . end () ? it -> second -> privkey ( c , u , d ) : 0 ;
2011-04-15 06:50:08 +00:00
}
static int rsaEncrypt ( int flen , const unsigned char * from ,
unsigned char * to ,
RSA * rsa , int padding ) {
OPENSSL_LOG ( "log" );
2011-05-03 11:11:35 +00:00
Map :: iterator it ( _map . find ( rsa -> engine ));
return it != _map . end () ? it -> second -> rsaEncrypt () : 0 ;
2011-04-15 06:50:08 +00:00
}
static int rsaDecrypt ( int flen , const unsigned char * from , unsigned char * to , RSA * rsa , int padding ) {
OPENSSL_LOG ( "log" );
2011-05-03 11:11:35 +00:00
Map :: iterator it ( _map . find ( rsa -> engine ));
return it != _map . end () ? it -> second -> rsaDecrypt () : 0 ;
2011-04-15 06:50:08 +00:00
}
2011-04-21 06:30:51 +00:00
static int rsaSign ( int type , const unsigned char * from ,
unsigned int flen ,
2011-04-15 06:50:08 +00:00
unsigned char * to ,
2011-04-21 06:30:51 +00:00
unsigned int * tlen ,
2011-04-15 06:50:08 +00:00
const RSA * rsa ) {
OPENSSL_LOG ( "log" );
2011-05-03 11:11:35 +00:00
Map :: iterator it ( _map . find ( rsa -> engine ));
if ( it == _map . end ()) return 0 ;
2011-04-21 06:30:51 +00:00
try {
2011-05-03 11:11:35 +00:00
std :: string res ( it -> second -> rsaSign
( std :: string (( const char * ) from , flen ),
type ));
2011-04-21 06:30:51 +00:00
OPENSSL_LOG ( "to=" << ( void * ) to << "; len=" <<* tlen );
OPENSSL_LOG ( "siglen=" << res . size ());
* tlen = res . size ();
std :: copy ( res . begin (), res . end (), to );
return 1 ;
} catch ( const std :: exception & e ) {
OPENSSL_LOG ( "ERROR: " << e . what ());
return 0 ;
}
2011-04-15 06:50:08 +00:00
}
static int rsaVerify ( int , const unsigned char * ,
unsigned int , OPENSSL_V0_CONST unsigned char * ,
unsigned int , const RSA * rsa ) {
OPENSSL_LOG ( "log" );
2011-05-03 11:11:35 +00:00
Map :: iterator it ( _map . find ( rsa -> engine ));
return it != _map . end () ? it -> second -> rsaVerify () : 0 ;
2011-04-15 06:50:08 +00:00
}
static int rsaFinish ( RSA * rsa ) {
OPENSSL_LOG ( "log" );
2011-05-03 11:11:35 +00:00
Map :: iterator it ( _map . find ( rsa -> engine ));
return it != _map . end () ? it -> second -> rsaFinish () : 0 ;
2011-04-15 06:50:08 +00:00
}
2011-04-21 06:30:51 +00:00
protected :
2011-04-15 06:50:08 +00:00
static RSA_METHOD * rsa () {
OPENSSL_LOG ( "log" );
static RSA_METHOD ops ;
if ( ! ops . rsa_priv_enc ) {
ops = * RSA_get_default_method ();
ops . rsa_pub_enc = rsaEncrypt ;
ops . rsa_priv_dec = rsaDecrypt ;
// a.k.a Verify/Sign. actLibrary just allows the proper functions
// and has this 'backdoor' closed. Breaks 'rsautl', sadly.
ops . rsa_pub_dec = NULL ;
ops . rsa_priv_enc = NULL ;
ops . rsa_sign = rsaSign ;
ops . rsa_verify = rsaVerify ;
ops . finish = rsaFinish ;
}
return & ops ;
}
private :
2011-05-03 11:11:35 +00:00
typedef std :: map < ENGINE * , Engine *> Map ;
static Map _map ;
2011-04-15 06:50:08 +00:00
static std :: map < std :: string , Engine *> _prototypes ;
};
//! Scoped Engine Registry
/*! Engine will be deregistered and freed at destruction */
2011-05-03 11:57:40 +00:00
template < class ENGINE = Engine > class RegisterEngine {
2011-04-15 06:50:08 +00:00
public :
2011-05-03 11:57:40 +00:00
RegisterEngine ( ENGINE * e = 0 ) : _e ( e ) {
2013-04-02 12:54:17 +00:00
OPENSSL_LOG ( "log" );
2011-05-03 11:11:35 +00:00
if ( _e ) EngineMapper :: add ( _e );
2011-04-15 06:50:08 +00:00
}
~ RegisterEngine () {
2013-04-02 12:54:17 +00:00
OPENSSL_LOG ( "log" );
2011-05-03 11:11:35 +00:00
if ( _e ) EngineMapper :: remove ( _e );
}
2011-05-03 11:57:40 +00:00
RegisterEngine & operator = ( ENGINE * e ) {
2013-04-02 12:54:17 +00:00
OPENSSL_LOG ( "log" );
2011-05-03 11:57:40 +00:00
if ( _e ) EngineMapper :: remove ( _e );
_e = e ;
if ( _e ) EngineMapper :: add ( _e );
return * this ;
}
operator ENGINE * () {
2013-04-02 12:54:17 +00:00
OPENSSL_LOG ( "log" );
2011-05-03 11:11:35 +00:00
return _e ;
}
2011-05-03 11:57:40 +00:00
ENGINE * operator -> () {
2013-04-02 12:54:17 +00:00
OPENSSL_LOG ( "log" );
2011-05-03 11:11:35 +00:00
return _e ;
}
2011-05-03 11:57:40 +00:00
ENGINE & operator * () {
2013-04-02 12:54:17 +00:00
OPENSSL_LOG ( "log" );
2011-05-03 11:11:35 +00:00
return * _e ;
2011-04-15 06:50:08 +00:00
}
private :
2011-05-03 11:57:40 +00:00
ENGINE * _e ;
2011-04-15 06:50:08 +00:00
};
//@}
}
#endif