better logging in PCSC and first engine release; refs #11
This commit is contained in:
		| @@ -3,7 +3,8 @@ | |||||||
| ##       1         2         3         4         5         6         7         8 | ##       1         2         3         4         5         6         7         8 | ||||||
| ## 45678901234567890123456789012345678901234567890123456789012345678901234567890 | ## 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 | AM_CPPFLAGS = -I${top_srcdir}/src | ||||||
| if !MINGW32 | 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 | openssl_ssl_demo_LDADD += /opt/local/i586-mingw32msvc/lib/ssleay32.a /opt/local/i586-mingw32msvc/lib/libeay32.a | ||||||
| endif | 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 | MAINTAINERCLEANFILES = makefile.in | ||||||
|   | |||||||
| @@ -177,7 +177,8 @@ namespace cryptoki { | |||||||
|     check(_fn->C_Initialize(0), //! @todo add optional argument |     check(_fn->C_Initialize(0), //! @todo add optional argument | ||||||
|           CRYPTOKI_FN_LOG("C_Initialize")); |           CRYPTOKI_FN_LOG("C_Initialize")); | ||||||
|   } catch (...) { |   } 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() { |   Init::operator bool() { | ||||||
|   | |||||||
| @@ -5,7 +5,8 @@ | |||||||
| ##       1         2         3         4         5         6         7         8 | ##       1         2         3         4         5         6         7         8 | ||||||
| ## 45678901234567890123456789012345678901234567890123456789012345678901234567890 | ## 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 !MINGW32 | ||||||
| if MAC | if MAC | ||||||
| @@ -28,7 +29,8 @@ EXTRA_DIST = $(pkgconfig_DATA).in $(shell ls -1 *.doc) | |||||||
|  |  | ||||||
| lib_LTLIBRARIES = libcryptoki++.la | 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 = | libcryptoki___la_LIBADD = | ||||||
| if !MINGW32 | if !MINGW32 | ||||||
| if !MAC | if !MAC | ||||||
|   | |||||||
							
								
								
									
										11
									
								
								src/openssl-engine.cxx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								src/openssl-engine.cxx
									
									
									
									
									
										Normal file
									
								
							| @@ -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; | ||||||
							
								
								
									
										272
									
								
								src/openssl-engine.hxx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										272
									
								
								src/openssl-engine.hxx
									
									
									
									
									
										Normal file
									
								
							| @@ -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 | ||||||
| @@ -314,12 +314,12 @@ namespace pcsc { | |||||||
|             SCARD_IO_REQUEST rPci; |             SCARD_IO_REQUEST rPci; | ||||||
|             rPci.dwProtocol  = pci()->dwProtocol; |             rPci.dwProtocol  = pci()->dwProtocol; | ||||||
|             rPci.cbPciLength = sizeof(rPci); |             rPci.cbPciLength = sizeof(rPci); | ||||||
|             PCSC_LOG("SCardTransmit: "<<crypto::hex(in)); |             //PCSC_LOG("SCardTransmit: "<<crypto::hex(in)); | ||||||
|             check(SCardTransmit(_id, &rPci, |             check(SCardTransmit(_id, &rPci, | ||||||
|                                 (unsigned char*)in.c_str(), in.size(), |                                 (unsigned char*)in.c_str(), in.size(), | ||||||
|                                 0, buff, &len), |                                 0, buff, &len), | ||||||
|                   "smartcard transmit message "+crypto::hex(in)); |                   "smartcard transmit message "+crypto::hex(in)); | ||||||
|             PCSC_LOG(" -> "<<crypto::hex(std::string((char*)buff, len))); |             //PCSC_LOG(" -> "<<crypto::hex(std::string((char*)buff, len))); | ||||||
|             return std::string((char*)buff, len); |             return std::string((char*)buff, len); | ||||||
|           } |           } | ||||||
|  |  | ||||||
| @@ -484,11 +484,15 @@ namespace pcsc { | |||||||
|                                     &num), |                                     &num), | ||||||
|                    "smartcard get size of readers of groups "+grp)) |                    "smartcard get size of readers of groups "+grp)) | ||||||
|           return res; |           return res; | ||||||
|  |         PCSC_LOG("size of readers: "<<num); | ||||||
|         std::auto_ptr<char_t> nm(new char_t[num]); |         std::auto_ptr<char_t> nm(new char_t[num]); | ||||||
|         if (!check(SCardListReaders(_id, groups.size()?strconv(grp).data():0, |         if (!check(SCardListReaders(_id, groups.size()?strconv(grp).data():0, | ||||||
|                                     nm.get(), &num), |                                     nm.get(), &num), | ||||||
|                    "smartcard list reader names of groups "+grp)) |                    "smartcard list reader names of groups "+grp)) | ||||||
|           return res; |           return res; | ||||||
|  |         PCSC_LOG("got all readers, size is "<<num); | ||||||
|  |         PCSC_LOG("list of readers: " | ||||||
|  |                  <<crypto::readable(std::string(nm.get(), num-1))); | ||||||
|         return res = split(strconv(string(nm.get(), num-1))); |         return res = split(strconv(string(nm.get(), num-1))); | ||||||
|       } |       } | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user