From 796f467630d896a11fb4407888f44d8d7d141cff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc=20W=C3=A4ckerlin?= Date: Fri, 15 Apr 2011 06:50:08 +0000 Subject: [PATCH] better logging in PCSC and first engine release; refs #11 --- doc/examples/makefile.am | 10 +- src/cryptoki.cxx | 3 +- src/makefile.am | 6 +- src/openssl-engine.cxx | 11 ++ src/openssl-engine.hxx | 272 +++++++++++++++++++++++++++++++++++++++ src/pcsc.hxx | 8 +- 6 files changed, 304 insertions(+), 6 deletions(-) create mode 100644 src/openssl-engine.cxx create mode 100644 src/openssl-engine.hxx diff --git a/doc/examples/makefile.am b/doc/examples/makefile.am index 7022820..c2d375c 100644 --- a/doc/examples/makefile.am +++ b/doc/examples/makefile.am @@ -3,7 +3,8 @@ ## 1 2 3 4 5 6 7 8 ## 45678901234567890123456789012345678901234567890123456789012345678901234567890 -noinst_PROGRAMS = pcsc-demo cryptoki-demo openssl-tcp-demo openssl-ssl-demo +noinst_PROGRAMS = pcsc-demo cryptoki-demo openssl-tcp-demo \ + openssl-ssl-demo openssl-engine-demo AM_CPPFLAGS = -I${top_srcdir}/src if !MINGW32 @@ -56,4 +57,11 @@ if MINGW32 openssl_ssl_demo_LDADD += /opt/local/i586-mingw32msvc/lib/ssleay32.a /opt/local/i586-mingw32msvc/lib/libeay32.a endif +openssl_engine_demo_SOURCES = openssl-engine-demo.cxx +openssl_engine_demo_LDFLAGS = -L${top_builddir}/src +openssl_engine_demo_LDADD = -lcryptoki++ +if MINGW32 +openssl_engine_demo_LDADD += /opt/local/i586-mingw32msvc/lib/ssleay32.a /opt/local/i586-mingw32msvc/lib/libeay32.a +endif + MAINTAINERCLEANFILES = makefile.in diff --git a/src/cryptoki.cxx b/src/cryptoki.cxx index 78d0b2f..01ad8c0 100644 --- a/src/cryptoki.cxx +++ b/src/cryptoki.cxx @@ -177,7 +177,8 @@ namespace cryptoki { check(_fn->C_Initialize(0), //! @todo add optional argument CRYPTOKI_FN_LOG("C_Initialize")); } catch (...) { - throw access_error(CRYPTOKI_FN_LOG("C_Initialize")+": Error in library"); + throw access_error(CRYPTOKI_FN_LOG("C_Initialize") + +": Error in initialization of library "+library); } Init::operator bool() { diff --git a/src/makefile.am b/src/makefile.am index 32a1217..808d54e 100644 --- a/src/makefile.am +++ b/src/makefile.am @@ -5,7 +5,8 @@ ## 1 2 3 4 5 6 7 8 ## 45678901234567890123456789012345678901234567890123456789012345678901234567890 -include_HEADERS = pcsc.hxx cryptoki.hxx openssl.hxx cryptaux.hxx +include_HEADERS = pcsc.hxx cryptoki.hxx openssl.hxx cryptaux.hxx \ + openssl-engine.hxx if !MINGW32 if MAC @@ -28,7 +29,8 @@ EXTRA_DIST = $(pkgconfig_DATA).in $(shell ls -1 *.doc) lib_LTLIBRARIES = libcryptoki++.la -libcryptoki___la_SOURCES = cryptoki.cxx cryptoki.hxx pcsc.cxx version.cxx +libcryptoki___la_SOURCES = cryptoki.cxx cryptoki.hxx pcsc.cxx \ + version.cxx openssl-engine.cxx libcryptoki___la_LIBADD = if !MINGW32 if !MAC diff --git a/src/openssl-engine.cxx b/src/openssl-engine.cxx new file mode 100644 index 0000000..13bd029 --- /dev/null +++ b/src/openssl-engine.cxx @@ -0,0 +1,11 @@ +/*! @file + + @id $Id$ +*/ +// 1 2 3 4 5 6 7 8 +// 45678901234567890123456789012345678901234567890123456789012345678901234567890 + +#include + +std::map openssl::EngineMapper::_map; +std::map openssl::EngineMapper::_prototypes; diff --git a/src/openssl-engine.hxx b/src/openssl-engine.hxx new file mode 100644 index 0000000..3431fb4 --- /dev/null +++ b/src/openssl-engine.hxx @@ -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 +#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 +#include +#include + +#ifndef OPENSSL_CHECK +#include +#include +#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: "< + #if __GNUC__ >= 2 + //! Openssl Logging + /*! If you want to change openssl logging mechanism, just + redefine your own OPENSSL_LOG macro before #include + <openssl.hxx>. Define it empty for no logging at + all. By default logs to std::clog. */ + #define OPENSSL_LOG(X) std::clog<#include + <openssl.hxx>. Define it empty for no logging at + all. By default logs to std::clog. */ + #define OPENSSL_LOG(X) std::clog< + openssl::RegisterEngine myEngine(new MyEngine); + */ + 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 _map; + static std::map _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 diff --git a/src/pcsc.hxx b/src/pcsc.hxx index 503fb39..43a5323 100644 --- a/src/pcsc.hxx +++ b/src/pcsc.hxx @@ -314,12 +314,12 @@ namespace pcsc { SCARD_IO_REQUEST rPci; rPci.dwProtocol = pci()->dwProtocol; rPci.cbPciLength = sizeof(rPci); - PCSC_LOG("SCardTransmit: "< "< "< nm(new char_t[num]); if (!check(SCardListReaders(_id, groups.size()?strconv(grp).data():0, nm.get(), &num), "smartcard list reader names of groups "+grp)) return res; + PCSC_LOG("got all readers, size is "<