2011-04-15 06:50:08 +00:00
|
|
|
/*! @file
|
|
|
|
|
|
|
|
@id $Id$
|
2014-03-24 09:23:46 +00:00
|
|
|
|
|
|
|
This product includes software developed by the OpenSSL Project
|
|
|
|
for use in the OpenSSL Toolkit (http://www.openssl.org/)
|
|
|
|
|
2014-03-26 15:07:54 +00:00
|
|
|
This product includes cryptographic software written by
|
|
|
|
Eric Young (eay@cryptsoft.com)
|
2011-04-15 06:50:08 +00:00
|
|
|
*/
|
|
|
|
// 1 2 3 4 5 6 7 8
|
|
|
|
// 45678901234567890123456789012345678901234567890123456789012345678901234567890
|
|
|
|
|
|
|
|
#ifndef __OPENSSL_ENGINE_HXX__
|
|
|
|
#define __OPENSSL_ENGINE_HXX__
|
2013-11-06 12:24:52 +00:00
|
|
|
|
|
|
|
#include <cryptaux.hxx>
|
|
|
|
|
2011-04-15 06:50:08 +00:00
|
|
|
#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 */
|
2014-04-01 13:10:51 +00:00
|
|
|
#define OPENSSL_CHECK(X) \
|
|
|
|
if (!(X)) { \
|
|
|
|
ERR_load_ENGINE_strings(); \
|
|
|
|
std::stringstream ss; \
|
|
|
|
for (unsigned long 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()); \
|
|
|
|
}
|
2011-04-15 06:50:08 +00:00
|
|
|
#else
|
2014-04-01 13:10:51 +00:00
|
|
|
#define OPENSSL_CHECK(X) \
|
|
|
|
if (!(X)) { \
|
|
|
|
ERR_load_ENGINE_strings(); \
|
|
|
|
std::stringstream ss; \
|
|
|
|
for (unsigned long 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()); \
|
|
|
|
}
|
2011-04-15 06:50:08 +00:00
|
|
|
#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()) {
|
2013-11-06 12:24:52 +00:00
|
|
|
CRYPTOLOG("log");
|
2011-04-15 06:50:08 +00:00
|
|
|
}
|
|
|
|
virtual ~Engine() {
|
2013-11-06 12:24:52 +00:00
|
|
|
CRYPTOLOG("log");
|
2013-04-03 09:14:05 +00:00
|
|
|
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() {
|
2013-11-06 12:24:52 +00:00
|
|
|
CRYPTOLOG("log");
|
2011-04-15 06:50:08 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
virtual int finish() {
|
2013-11-06 12:24:52 +00:00
|
|
|
CRYPTOLOG("log");
|
2011-04-15 06:50:08 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
virtual int ctrl(int, long, void*, void(*)()) {
|
2013-11-06 12:24:52 +00:00
|
|
|
CRYPTOLOG("log");
|
2011-04-15 06:50:08 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
virtual int cmd() {
|
2013-11-06 12:24:52 +00:00
|
|
|
CRYPTOLOG("log");
|
2011-04-15 06:50:08 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
virtual EVP_PKEY* pubkey(const char*, UI_METHOD*, void*) {
|
2013-11-06 12:24:52 +00:00
|
|
|
CRYPTOLOG("log");
|
2011-04-15 06:50:08 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
virtual EVP_PKEY* privkey(const char*, UI_METHOD*, void*) {
|
2013-11-06 12:24:52 +00:00
|
|
|
CRYPTOLOG("log");
|
2011-04-15 06:50:08 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2014-04-01 13:10:51 +00:00
|
|
|
virtual std::string rsaEncrypt(const std::string&, int) {
|
2013-11-06 12:24:52 +00:00
|
|
|
CRYPTOLOG("log");
|
2014-04-01 13:10:51 +00:00
|
|
|
throw std::runtime_error("rsaEncrypt not implemented");
|
2011-04-15 06:50:08 +00:00
|
|
|
}
|
2014-04-01 13:10:51 +00:00
|
|
|
virtual std::string rsaDecrypt(const std::string&, int) {
|
2013-11-06 12:24:52 +00:00
|
|
|
CRYPTOLOG("log");
|
2014-04-01 13:10:51 +00:00
|
|
|
throw std::runtime_error("rsaDecrypt not implemented");
|
2011-04-15 06:50:08 +00:00
|
|
|
}
|
2011-04-21 06:30:51 +00:00
|
|
|
virtual std::string rsaSign(const std::string&, unsigned int) {
|
2013-11-06 12:24:52 +00:00
|
|
|
CRYPTOLOG("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() {
|
2013-11-06 12:24:52 +00:00
|
|
|
CRYPTOLOG("log");
|
2011-04-15 06:50:08 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
virtual int rsaFinish() {
|
2013-11-06 12:24:52 +00:00
|
|
|
CRYPTOLOG("log");
|
2011-04-15 06:50:08 +00:00
|
|
|
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) {
|
2013-11-06 12:24:52 +00:00
|
|
|
CRYPTOLOG("log");
|
2011-04-15 06:50:08 +00:00
|
|
|
_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-03 09:14:05 +00:00
|
|
|
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-03 09:14:05 +00:00
|
|
|
OPENSSL_CHECK(ENGINE_remove(e->_e));
|
|
|
|
OPENSSL_CHECK(ENGINE_finish(e->_e));
|
|
|
|
_map.erase(e->_e);
|
|
|
|
delete e;
|
2011-04-15 06:50:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
2014-04-01 13:10:51 +00:00
|
|
|
static int destroy(ENGINE*) {
|
2013-11-06 12:24:52 +00:00
|
|
|
CRYPTOLOG("log");
|
2011-04-15 06:50:08 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
static int init(ENGINE* e) {
|
2013-11-06 12:24:52 +00:00
|
|
|
CRYPTOLOG("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) {
|
2013-11-06 12:24:52 +00:00
|
|
|
CRYPTOLOG("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)()) {
|
2013-11-06 12:24:52 +00:00
|
|
|
CRYPTOLOG("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) {
|
2013-11-06 12:24:52 +00:00
|
|
|
CRYPTOLOG("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) {
|
2013-11-06 12:24:52 +00:00
|
|
|
CRYPTOLOG("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
|
|
|
}
|
2014-04-01 13:10:51 +00:00
|
|
|
static int rsaEncrypt(int flen, const unsigned char *from,
|
2011-04-15 06:50:08 +00:00
|
|
|
unsigned char *to,
|
|
|
|
RSA *rsa, int padding) {
|
2013-11-06 12:24:52 +00:00
|
|
|
CRYPTOLOG("log");
|
2011-05-03 11:11:35 +00:00
|
|
|
Map::iterator it(_map.find(rsa->engine));
|
2014-04-01 13:10:51 +00:00
|
|
|
if (it==_map.end()) return 0;
|
|
|
|
try {
|
|
|
|
std::string res(it->second->rsaEncrypt
|
|
|
|
(std::string((const char*)from, flen),
|
|
|
|
padding));
|
|
|
|
std::copy(res.begin(), res.end(), to);
|
|
|
|
return 1;
|
|
|
|
} catch (const std::exception& e) {
|
|
|
|
CRYPTOLOG("ERROR: "<<e.what());
|
|
|
|
return 0;
|
|
|
|
}
|
2011-04-15 06:50:08 +00:00
|
|
|
}
|
2014-04-01 13:10:51 +00:00
|
|
|
static int rsaDecrypt(int flen, const unsigned char *from,
|
|
|
|
unsigned char *to, RSA *rsa, int padding) {
|
2013-11-06 12:24:52 +00:00
|
|
|
CRYPTOLOG("log");
|
2011-05-03 11:11:35 +00:00
|
|
|
Map::iterator it(_map.find(rsa->engine));
|
2014-04-01 13:10:51 +00:00
|
|
|
if (it==_map.end()) return 0;
|
|
|
|
try {
|
|
|
|
std::string res(it->second->rsaDecrypt
|
|
|
|
(std::string((const char*)from, flen),
|
|
|
|
padding));
|
|
|
|
std::copy(res.begin(), res.end(), to);
|
|
|
|
return 1;
|
|
|
|
} catch (const std::exception& e) {
|
|
|
|
CRYPTOLOG("ERROR: "<<e.what());
|
|
|
|
return 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) {
|
2013-11-06 12:24:52 +00:00
|
|
|
CRYPTOLOG("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));
|
2013-11-06 12:24:52 +00:00
|
|
|
CRYPTOLOG("to="<<(void*)to<<"; len="<<*tlen);
|
|
|
|
CRYPTOLOG("siglen="<<res.size());
|
2014-04-01 13:10:51 +00:00
|
|
|
*tlen = (unsigned int)res.size();
|
2011-04-21 06:30:51 +00:00
|
|
|
std::copy(res.begin(), res.end(), to);
|
|
|
|
return 1;
|
|
|
|
} catch (const std::exception& e) {
|
2013-11-06 12:24:52 +00:00
|
|
|
CRYPTOLOG("ERROR: "<<e.what());
|
2011-04-21 06:30:51 +00:00
|
|
|
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) {
|
2013-11-06 12:24:52 +00:00
|
|
|
CRYPTOLOG("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) {
|
2013-11-06 12:24:52 +00:00
|
|
|
CRYPTOLOG("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() {
|
2013-11-06 12:24:52 +00:00
|
|
|
CRYPTOLOG("log");
|
2011-04-15 06:50:08 +00:00
|
|
|
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) {
|
2011-05-03 11:11:35 +00:00
|
|
|
if (_e) EngineMapper::add(_e);
|
2011-04-15 06:50:08 +00:00
|
|
|
}
|
|
|
|
~RegisterEngine() {
|
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) {
|
|
|
|
if (_e) EngineMapper::remove(_e);
|
|
|
|
_e = e;
|
|
|
|
if (_e) EngineMapper::add(_e);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
operator ENGINE*() {
|
2011-05-03 11:11:35 +00:00
|
|
|
return _e;
|
|
|
|
}
|
2011-05-03 11:57:40 +00:00
|
|
|
ENGINE* operator->() {
|
2011-05-03 11:11:35 +00:00
|
|
|
return _e;
|
|
|
|
}
|
2011-05-03 11:57:40 +00:00
|
|
|
ENGINE& operator*() {
|
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
|