better logging in PCSC and first engine release; refs #11
parent
83e4bcbc65
commit
796f467630
6 changed files with 304 additions and 6 deletions
@ -0,0 +1,11 @@ |
||||
/*! @file
|
||||
|
||||
@id $Id$ |
||||
*/ |
||||
// 1 2 3 4 5 6 7 8
|
||||
// 45678901234567890123456789012345678901234567890123456789012345678901234567890
|
||||
|
||||
#include <openssl-engine.hxx> |
||||
|
||||
std::map<ENGINE*, openssl::Engine*> openssl::EngineMapper::_map; |
||||
std::map<std::string, openssl::Engine*> openssl::EngineMapper::_prototypes; |
@ -0,0 +1,272 @@ |
||||
/*! @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 |
||||
|
||||
#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"); |
||||
OPENSSL_CHECK(ENGINE_free(_e)); |
||||
} |
||||
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; |
||||
} |
||||
virtual int rsaSign() { |
||||
OPENSSL_LOG("log"); |
||||
return 1; |
||||
} |
||||
virtual int rsaVerify() { |
||||
OPENSSL_LOG("log"); |
||||
return 1; |
||||
} |
||||
virtual int rsaFinish() { |
||||
OPENSSL_LOG("log"); |
||||
return 1; |
||||
} |
||||
|
||||
private: |
||||
|
||||
friend class EngineMapper; |
||||
ENGINE* _e; |
||||
|
||||
}; |
||||
|
||||
class EngineMapper { |
||||
|
||||
public: |
||||
|
||||
static int add(Engine *e) { |
||||
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())); |
||||
OPENSSL_CHECK(ENGINE_set_destroy_function(e->_e, EngineMapper::destroy)); |
||||
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) { |
||||
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"); |
||||
return _map[e]->init(); |
||||
} |
||||
static int finish(ENGINE* e) { |
||||
OPENSSL_LOG("log"); |
||||
return _map[e]->finish(); |
||||
} |
||||
static int ctrl(ENGINE* e, int cmd, long i, void* p, void(*f)()) { |
||||
OPENSSL_LOG("log"); |
||||
return _map[e]->ctrl(cmd, i, p, f); |
||||
} |
||||
static EVP_PKEY* pubkey(ENGINE* e, const char* c, UI_METHOD* u, void* d) { |
||||
OPENSSL_LOG("log"); |
||||
return _map[e]->pubkey(c, u, d); |
||||
} |
||||
static EVP_PKEY* privkey(ENGINE* e, const char* c, UI_METHOD* u, void* d) { |
||||
OPENSSL_LOG("log"); |
||||
return _map[e]->privkey(c, u, d); |
||||
} |
||||
static int rsaEncrypt(int flen,const unsigned char *from, |
||||
unsigned char *to, |
||||
RSA *rsa, int padding) { |
||||
OPENSSL_LOG("log"); |
||||
return _map[rsa->engine]->rsaEncrypt(); |
||||
} |
||||
static int rsaDecrypt(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding) { |
||||
OPENSSL_LOG("log"); |
||||
return _map[rsa->engine]->rsaDecrypt(); |
||||
} |
||||
static int rsaSign(int flen, const unsigned char *from, |
||||
unsigned int, |
||||
unsigned char *to, |
||||
unsigned int*, |
||||
const RSA *rsa) { |
||||
OPENSSL_LOG("log"); |
||||
return _map[rsa->engine]->rsaSign(); |
||||
} |
||||
static int rsaVerify(int, const unsigned char*, |
||||
unsigned int, OPENSSL_V0_CONST unsigned char*, |
||||
unsigned int, const RSA* rsa) { |
||||
OPENSSL_LOG("log"); |
||||
return _map[rsa->engine]->rsaVerify(); |
||||
} |
||||
static int rsaFinish(RSA *rsa) { |
||||
OPENSSL_LOG("log"); |
||||
return _map[rsa->engine]->rsaFinish(); |
||||
} |
||||
|
||||
private: |
||||
|
||||
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: |
||||
|
||||
static std::map<ENGINE*, Engine*> _map; |
||||
static std::map<std::string, Engine*> _prototypes; |
||||
}; |
||||
|
||||
//! Scoped Engine Registry
|
||||
/*! Engine will be deregistered and freed at destruction */ |
||||
class RegisterEngine { |
||||
public: |
||||
RegisterEngine(Engine* e): _e(e) { |
||||
EngineMapper::add(_e); |
||||
} |
||||
~RegisterEngine() { |
||||
EngineMapper::remove(_e); |
||||
} |
||||
private: |
||||
Engine* _e; |
||||
}; |
||||
|
||||
//@}
|
||||
} |
||||
#endif |
Loading…
Reference in new issue