master
carsten.pluntke 14 years ago
parent 021924d803
commit 9a8b208c62
  1. BIN
      Sample_Executables/Win32/engine_act.dll
  2. 108
      openssl-act-engine/CardKey.cpp
  3. 46
      openssl-act-engine/CardKey.h
  4. 144
      openssl-act-engine/CardObject.cpp
  5. 40
      openssl-act-engine/CardObject.h
  6. 179
      openssl-act-engine/CertificateList.cpp
  7. 40
      openssl-act-engine/CertificateList.h
  8. 225
      openssl-act-engine/Init_Engine.h
  9. 34
      openssl-act-engine/Makefile
  10. 41
      openssl-act-engine/ReadMe.txt
  11. 48
      openssl-act-engine/SecOpGuard.cpp
  12. 33
      openssl-act-engine/SecOpGuard.h
  13. 138
      openssl-act-engine/SlotList.cpp
  14. 64
      openssl-act-engine/SlotList.h
  15. 184
      openssl-act-engine/SyncObject.h
  16. 46
      openssl-act-engine/SyncObjectMacOS.h
  17. 38
      openssl-act-engine/SyncObjectPosix.h
  18. 38
      openssl-act-engine/SyncObjectSolaris.h
  19. 39
      openssl-act-engine/SyncObjectWin32.h
  20. 36
      openssl-act-engine/SyncObjectWinCE.h
  21. 7
      openssl-act-engine/Warns.h
  22. 19
      openssl-act-engine/dllmain.cpp
  23. 262
      openssl-act-engine/engine_front.cpp
  24. 402
      openssl-act-engine/engine_sct.cpp
  25. 38
      openssl-act-engine/engine_sct.h
  26. 90
      openssl-act-engine/engine_sct_internal.h
  27. 6
      openssl-act-engine/engine_securetoken.cpp
  28. 24
      openssl-act-engine/engine_securetoken.sln
  29. 347
      openssl-act-engine/engine_securetoken.vcproj
  30. 8
      openssl-act-engine/stdafx.cpp
  31. 16
      openssl-act-engine/stdafx.h
  32. 24
      openssl-act-engine/targetver.h
  33. 84
      openssl-act-engine/test_engine.cpp

@ -0,0 +1,108 @@
#include "CardKey.h"
#include "SecOpGuard.h"
#include <actITokenKey.h>
#include <actIToken.h>
#include <actDebug.h>
#include <cstring>
#include <vector>
CardKey::CardKey(act::ITokenKey* key)
: m_token_key(key)
{
ACT_ASSERT(key != 0);
}
CardKey::~CardKey()
{
}
void CardKey::setPin(char *pin)
{
int plen = strlen(pin);
act::Blob(pin, pin+plen).swap(m_pin);
std::fill(pin, pin+plen, '*'); // Whiten out the source contents as soon as the PIN is in our domain
}
void CardKey::setPin(const act::Blob& pin)
{
m_pin = pin;
}
void CardKey::setPin(UI_METHOD *ui_method, void *callback_data)
{
int maxlen=200;
std::vector<char> buf(maxlen+1);
char* buffer = &buf[0];
UI *ui;
struct mycb_t {
const char *password;
const char *prompt_info;
} *mycb;
mycb = reinterpret_cast<mycb_t*>(callback_data);
/* pin in the call back data, copy and use */
if (mycb != NULL && mycb->password) {
act::Blob(mycb->password, mycb->password+strlen(mycb->password)).swap(m_pin);
return;
}
/* call ui to ask for a pin */
ui = UI_new();
if (ui_method != NULL)
UI_set_method(ui, ui_method);
if (callback_data != NULL)
UI_set_app_data(ui, callback_data);
// Fall back to an own, quite meaningless, prompt if we aren't provided one.
const char *prompt_info = (mycb && mycb->prompt_info) ? mycb->prompt_info : "Token PIN: ";
if (!UI_add_input_string
(ui, prompt_info, 0, buffer, 1, maxlen)) {
fprintf(stderr, "UI_add_input_string failed\n");
UI_free(ui);
return;
}
if (UI_process(ui)) {
fprintf(stderr, "UI_process failed\n");
UI_free(ui);
return;
}
act::Blob(buffer, buffer+strlen(buffer)).swap(m_pin);
UI_free(ui);
return;
}
bool CardKey::Authenticate(SecOpGuard& where)
{
// We assume to get along without a PIN. If the security operation fails we'll see early enough.
if(m_pin.empty())
return true;
act::ITokenPIN* token_pin = m_token_key->GetPin();
// Fall back to token's User PIN if nothing else given
if(token_pin == NULL)
{
act::IToken* token = m_token_key->GetToken();
ACT_ASSERT(token != NULL);
token_pin = token->GetUserPin();
}
ACT_ASSERT(token_pin != NULL);
bool result = where.Authenticate(token_pin, m_pin);
// TODO: UP FOR DISCUSSION: PIN has been used up, erase it? Or keep it as long as the key itself?
// m_pin.clear();
return result;
}

@ -0,0 +1,46 @@
#ifndef __CARDKEY_H__
#define __CARDKEY_H__
#include <actBlob.h>
//#include <openssl/crypto.h>
//#include <openssl/objects.h>
#include <openssl/engine.h>
#include <memory>
namespace act
{
class ITokenKey;
}
/*
* Retains a single RSA key pair and (maybe) the provided PIN which is used to authenticate for usage of
* this key
*/
class SecOpGuard;
class CardKey
{
public:
CardKey(act::ITokenKey* token_key);
~CardKey();
inline act::ITokenKey* getKey() const { return m_token_key.get(); }
// NOTE: Contents of source string will be overwritten for security reasons
void setPin(char *pin);
void setPin(const act::Blob& pin);
void setPin(UI_METHOD *ui_method, void *callback_data);
bool Authenticate(SecOpGuard& where);
private:
std::auto_ptr<act::ITokenKey> m_token_key;
act::Blob m_pin;
};
#endif

@ -0,0 +1,144 @@
#include <actITokenKey.h>
#include <actIToken.h>
#include <actISlot.h>
#include <actUtility.h>
#include <actDebug.h>
#include <actMode.h>
#include <actCertificate.h>
#include "CardObject.h"
#include "SlotList.h"
#include <memory>
CardObject::CardObject(SlotList *sl)
: m_search_type(0)
, m_selected_token(NULL)
, m_found_key(NULL)
, m_slot_list(sl)
{
}
CardObject::~CardObject()
{
// We keep ownership of the token object itself but we're expected to pawn off the resulting key
// or certificate object we find.
if(m_selected_token)
m_selected_token->Destroy();
}
bool CardObject::searchFor(int searchType, const char *s_key_id)
{
// Only one successful search operation allowed
ACT_ASSERT(m_selected_token == NULL);
if(m_selected_token != NULL)
return false;
std::string key_id_string(s_key_id);
act::ISlot* selected_slot = NULL;
act::ITokenKey* selected_key = NULL;
size_t pos = 0;
// Slot selection: Currently only "slot_<decimalno>" supported
if(key_id_string.substr(pos,5) == "slot-")
{
pos += 5;
size_t slot_num = 0;
while(pos < key_id_string.length() && key_id_string[pos] >= '0' && key_id_string[pos] <= '9')
slot_num = slot_num * 10 + (key_id_string[pos++] - '0');
m_selected_token = m_slot_list->getToken(slot_num);
}
else
return false;
// Bail out if the selected slot is a dud.
if(!m_selected_token)
return false;
// Key (or cert) selection with "id_<hexid>"
if(key_id_string.substr(pos,4) == "-id-")
{
pos += 4;
act::Blob id_blob;
act::hex2blob(key_id_string.substr(pos).c_str()).swap(id_blob);
if(searchType != act::CERTIFICATE)
{
for(int i=m_selected_token->GetKeyNumber();i--;)
{
act::ITokenKey* key = dynamic_cast<act::ITokenKey*>(m_selected_token->GetKey(i));
if(key == NULL)
continue;
if(key->GetType() != act::KEY_RSA || key->GetID() != id_blob)
continue;
// Found it, deposit a copy for the caller's retrieval
m_found_key = key->Clone();
return true;
}
return false;
}
else
{
for(int i=m_selected_token->GetCertificateNumber();i--;)
{
act::CertEntry ce(m_selected_token->GetCertificate(i));
std::auto_ptr<act::Certificate> cert(new act::Certificate("X509", ce.certblob));
if(cert.get() == NULL)
continue;
act::Blob serno;
cert->GetParam(act::SERIALNR, serno);
if(serno != id_blob)
continue;
// Else we found what we're looking for, deposit a pointer for the caller's retrieval
m_found_certificate = ce.certblob;
return true;
}
}
}
else if(key_id_string.substr(pos,6) == "-name-") // Key selection with "name-<keyname>"
{
pos += 6;
std::string name(key_id_string.substr(pos));
ACT_ASSERT(searchType != act::CERTIFICATE);
for(int i=m_selected_token->GetKeyNumber();i--;)
{
act::ITokenKey* key = dynamic_cast<act::ITokenKey*>(m_selected_token->GetKey(i));
if(key == NULL)
continue;
if(key->GetType() != act::KEY_RSA || name != key->GetName())
continue;
// Found it, deposit a copy for the caller's retrieval
m_found_key = key->Clone();
return true;
}
return false;
}
return false;
}

@ -0,0 +1,40 @@
#ifndef __CARDOBJECT_H__
#define __CARDOBJECT_H__
#include <actBlob.h>
class SlotList;
namespace act
{
class IToken;
class ITokenKey;
}
/*
* Provides the search functionality over slots and keys
*/
class CardObject
{
public:
CardObject(SlotList *sl);
~CardObject();
// act::PRIVATEKEY, act::PUBLICKEY or act::CERTIFICATE
bool searchFor(int searchType, const char *s_key_id);
inline act::ITokenKey* getKey() const { return m_found_key; }
inline const act::Blob& getCertBlob() const { return m_found_certificate; }
private:
int m_search_type;
act::IToken* m_selected_token;
act::ITokenKey* m_found_key;
act::Blob m_found_certificate;
SlotList* m_slot_list;
};
#endif

@ -0,0 +1,179 @@
#include "engine_sct.h"
#include "CertificateList.h"
#include "SlotList.h"
#include "SecOpGuard.h"
#include <openssl/objects.h>
#include <openssl/crypto.h>
#include <openssl/engine.h>
#ifdef U64
#undef U64
#endif
#include <actUtility.h>
#include <actITokenKey.h>
#include <actIToken.h>
#include <actISlot.h>
#include <actDebug.h>
#include <sstream>
#include <string>
CertificateList::CertificateList()
: m_num_certs(0)
, m_enum_list(NULL)
{
}
CertificateList::~CertificateList()
{
release_list();
}
void CertificateList::release_list()
{
if(m_enum_list == NULL) return;
enum_cert_s* cert_p = m_enum_list->certificate;
// Can only happen if someone tampered with the returned structure.
ACT_ASSERT(m_num_certs == m_enum_list->num_certs);
// No matter, we just use our value in any case.
for(int i=m_num_certs;i--;)
{
free((void *)cert_p[i].id);
free((void *)cert_p[i].name);
X509_free(cert_p[i].cert);
}
free(m_enum_list);
m_enum_list = NULL;
m_num_certs = 0;
}
void CertificateList::init(SlotList& slots)
{
cert_map_t cert_temp_map;
for(size_t i=slots.getNumSlots();i--;)
{
act::IToken* token = slots.getToken(i);
if(!token)
continue;
{
// Needs to be transacted
SecOpGuard guard(token);
// Iterate over the certificates on the token, adding them with empty ID
for(int j=token->GetCertificateNumber();j--;)
{
act::CertEntry ce(token->GetCertificate(j));
cert_tmp_s temp;
temp.slot_number = i;
cert_temp_map[ce.certblob] = temp;
}
// Iterate over the keys and insert their ID's into the corresponding certificates
for(int j=token->GetKeyNumber();j--;)
{
act::ITokenKey* key = dynamic_cast<act::ITokenKey*>(token->GetKey(j));
if(key == NULL)
continue;
act::Blob certblob(key->GetCertificate());
cert_map_t::iterator it = cert_temp_map.find(certblob);
// Sort key ID into the certificate data if found
if(it != cert_temp_map.end())
{
it->second.name = key->GetName();
it->second.id = key->GetID();
}
// What about keypairs without a certificate? We could add entries with no certs...?
}
}
token->Destroy();
}
// Now we have a map of all certificates. Those with IDs are connected to a keypair, those without
// are just stored on the card, probably CA certificates or somesuch.
m_num_certs = cert_temp_map.size();
ACT_ASSERT(m_enum_list == NULL);
// Allocate the needed memory to hold the structure heading plus the certificate pointers themselves
m_enum_list = reinterpret_cast<enum_certs_s*>(
malloc(sizeof(enum_certs_s) + m_num_certs * sizeof(enum_cert_s)));
// Bail out if we can't allocate.
if(!m_enum_list)
return;
m_enum_list->num_certs = m_num_certs;
enum_cert_s* cert_p = &m_enum_list->certificate[0];
// Now place the decoded certificates and key id's (if applicable) into a neat structure.
for(cert_map_t::const_iterator it = cert_temp_map.begin(); it != cert_temp_map.end();++it)
{
const act::Blob& certblob = it->first;
const unsigned char *cbp = &certblob[0];
cert_p->cert = d2i_X509(NULL, &cbp, certblob.size());
const cert_tmp_s& id_tmp = it->second;
cert_p->id = NULL;
if(!id_tmp.id.empty())
{
std::stringstream ss;
ss << "slot-" << id_tmp.slot_number << "-id-" << act::blob2hex(id_tmp.id);
std::string id_str(ss.str());
size_t len = id_str.length();
const char *src_p = id_str.c_str();
char *p = reinterpret_cast<char *>(malloc(len+1 * sizeof(char)));
if(p)
{
p[len]=0;
std::copy(src_p, src_p+len, p);
cert_p->id = (const char *)p;
}
}
cert_p->name = NULL;
if(!id_tmp.name.empty())
{
std::stringstream ss;
ss << "slot-" << id_tmp.slot_number << "-name-" << id_tmp.name;
std::string name_str(ss.str());
size_t len = name_str.length();
const char *src_p = name_str.c_str();
char *p = reinterpret_cast<char *>(malloc(len+1 * sizeof(char)));
if(p)
{
p[len]=0;
std::copy(src_p, src_p+len, p);
cert_p->name = (const char *)p;
}
}
cert_p++;
}
}

@ -0,0 +1,40 @@
#ifndef __CERTIFICATELIST_H__
#define __CERTIFICATELIST_H__
#include <actBlob.h>
#include <map>
#include <string>
struct enum_certs_s;
class SlotList;
/*
* Builds up and owns the structure returned by ENUM_CERTS
*/
class CertificateList
{
public:
CertificateList();
~CertificateList();
void init(SlotList& slots);
inline enum_certs_s* getEnumList() { return m_enum_list; }
private:
struct cert_tmp_s
{
size_t slot_number;
act::Blob id;
std::string name;
};
typedef std::map<act::Blob, cert_tmp_s> cert_map_t;
void release_list();
int m_num_certs; // Copy of the number of certs embedded in the returned structure
enum_certs_s* m_enum_list;
};
#endif

@ -0,0 +1,225 @@
//////////////////////////////////////////////////////////////////////////////////
// Name: actInit.h
// Product: cv act library
// Purpose: initialize the map entries of the objects
//
// Copyright: (c) 2007 cv cryptovision GmbH
// all rights reserved
// Licence: The conditions for the use of this software are regulated
// in the cv act library licence agreement.
// remarks:
// declare NO_SMARTCARD: no smartcard support required.
//////////////////////////////////////////////////////////////////////////////////
#ifndef actInit_h
#define actInit_h
#include "actKeyKit.h"
#include "actKeyReg.h"
#include "actHashKit.h"
#include "actHashReg.h"
#include "actEMSAReg.h"
#include "actEMSAKit.h"
#include "actPaddingReg.h"
#include "actPaddingKit.h"
#include "actCertificateReg.h"
#include "actCertificateKit.h"
#include "actDefaultRNG.h"
#include "actRNGKit.h"
#ifndef NO_SMARTCARD
// NOTE: To Enable support for additional smartcards / profiles define:
// ACT_SUPPORT_TCOS_NETKEY30
# include "actSCardOSReg.h"
# include "actSCardOSKit.h"
# include "actSCardTokenReg.h"
# include "actSCardTokenKit.h"
# include "actSubsystemReg.h"
# include "actSubsystemKit.h"
# include "actSlotMonitorReg.h"
# include "actSlotMonitorKit.h"
# include "actTokenExtensionReg.h"
# include "actTokenExtensionKit.h"
# include "actTokenAuthProtocolReg.h"
# include "actTokenAuthProtocolKit.h"
# include "actPKCS15BehaviorReg.h"
# include "actPKCS15BehaviorKit.h"
#endif // NO_SMARTCARD
namespace act
{
// ------------------------------------------------------------------------
const KeyMapEntry KeyMap[] =
{
{ "RSA" , CreateRSAKey },
{ 0, 0 }
};
// ------------------------------------------------------------------------
const HashMapEntry HashMap[] =
{
{ "MD5" , CreateMD5 },
{ "SHA1" , CreateSHA1 },
{ "SHA224" , CreateSHA224 },
{ "SHA256" , CreateSHA256 },
{ "SHA384" , CreateSHA384 },
{ "SHA512" , CreateSHA512 },
{ "DummyHash" , CreateDummyHash },
{ 0, 0 }
};
// ------------------------------------------------------------------------
const EMSAMapEntry EMSAMap[] =
{
{ "EMSA1", CreateEMSA1 },
{ "PKCS1V1_5EMSA", CreatePKCS1V1_5EMSA },
{ "TLS_EMSA", CreateTLS_EMSA},
{ "PKCS1_PSS_EMSA", CreatePKCS1_PSS_EMSA },
{ "DummyEMSA" , CreateDummyEMSA }, // Used for "Hash on Card"
{ 0, 0 }
};
// ------------------------------------------------------------------------
const PaddingMapEntry PaddingMap[] =
{
{ "PKCS5", CreatePKCS5Pad },
{ "RSAES", CreatePKCS1V1_5EMEPad },
{ "ISO", CreateOneAndZerosPad },
{ "ISO9796", CreateISO9796Pad },
{ "NOPAD", CreateNoPad },
{ 0, 0 }
};
// ------------------------------------------------------------------------
const CertificateMapEntry CertificateMap[] =
{
{ "X509", CreateX509Certificate },
{ 0, 0 }
};
#ifndef NO_SMARTCARD
// ------------------------------------------------------------------------
const SCardOSMapEntry SCardOSMap[] =
{
// CardOS
{ "c806", CreateCardOS_V4 }, // CardOS V4.2
{ "c807", CreateCardOS_V4 }, // CardOS V4.3
{ "c808", CreateCardOS_V4 }, // CardOS V4.3B
{ "c809", CreateCardOS_V4 }, // CardOS V4.2B
{ "c80a", CreateCardOS_V4 }, // CardOS V4.2B DI
{ "0000c80a3381b100", CreateCardOS_V4 }, // CardOS V4.2B DI contactless
{ "c80b", CreateCardOS_V4 }, // CardOS V4.2C
{ "c80d", CreateCardOS_V4 }, // CardOS V4.4
{ "56346376", CreateCardOS_V4 }, // CardOS V4.2/4.3/4.3B cv profile
{ "563432626376", CreateCardOS_V4 }, // CardOS V4.2b cv profile
{ "5634326244496376", CreateCardOS_V4 }, // CardOS V4.2b DI cv profile
{ "563432636376", CreateCardOS_V4 }, // CardOS V4.2c cv profile
{ "5634346376", CreateCardOS_V4 }, // CardOS V4.4 cv profile
{ "563463765f45", CreateCardOS_V4_ECC }, // CardOS V4.3B ECC cv profile
{ "006b0508c806012101434e53103180", CreateCardOS_V4 }, // CardOS V4.2 CNS profile, 2004.02.20
{ "006b0508c807012101434e53103180", CreateCardOS_V4 }, // CardOS V4.3 CNS profile, 2004.02.20
{ "006b0508c808012101434e53103180", CreateCardOS_V4 }, // CardOS V4.3B CNS profile, 2004.02.20
{ "006b0508c806011101434e53103180", CreateCardOS_V4 }, // CardOS V4.2 CNS profile, 2005.03.11
{ "006b0508c807011101434e53103180", CreateCardOS_V4 }, // CardOS V4.3 CNS profile, 2005.03.11
{ "006b0508c808011101434e53103180", CreateCardOS_V4 }, // CardOS V4.3B CNS profile, 2005.03.11
{ "006b0508c808011101434e53103180", CreateCardOS_V4 }, // CardOS V4.3B CNS profile, 2005.03.11
{ "4b53776973735369676e", CreateCardOS_V4 }, // CardOS V4.3B/V4.4 ATR by SwissSign
{ ACT_ISO7816OS_NAME, CreateISO7816OS }, // use act::ISO7816OS as fallback
{ 0, 0 }
};
// ------------------------------------------------------------------------
const SCardTokenMapEntry SCardTokenMap[] =
{
// PKCS#15
{ IsV4PKCS15ECProfile, CreateV4PKCS15ECProfile },
{ IsV4PKCS15Profile, CreateV4PKCS15Profile },
// CardOS
{ IsM4cvMoCProfile, CreateM4cvMoCProfile },
{ IsM4cvECProfile, CreateM4cvECProfile },
{ IsV4cvECProfile, CreateV4cvECProfile },
{ IsV4cvProfile, CreateV4cvProfile },
{ IsM4cvProfile, CreateM4cvProfile },
// { IsV4CNSProfile, CreateV4CNSProfile },
{ 0, 0 }
};
// ------------------------------------------------------------------------
const PKCS15BehaviorMapEntry PKCS15BehaviorMap[] =
{
{ "cv cryptovision gmbh (c) v1.0n", CreateV4PKCS15Behavior },
{ "", CreatePKCS15Behavior }, // default
{ 0, 0 }
};
// ------------------------------------------------------------------------
const TokenExtensionMapEntry TokenExtensionMap[] =
{
{ "MDProfileExt", CreateMDProfileExt }, // Minidriver FS Profile Extension
{ 0, 0 }
};
// ------------------------------------------------------------------------
const TokenAuthProtocolMapEntry TokenAuthProtocolMap[] =
{
{ "EAC 2.01 PACE", CreateTokenAuthPACE },
{ "EAC 2.01 TA", CreateTokenAuthTA },
{ "EAC 2.01 CA", CreateTokenAuthCA },
{ "BAC", CreateTokenAuthBAC },
{ 0, 0 }
};
// ------------------------------------------------------------------------
const SubsystemMapEntry SubsystemMap[] =
{
{ "PCSC", CreatePCSCSystem, CreatePCSCSystemEx },
{ 0, 0, 0 }
};
// ------------------------------------------------------------------------
const SlotMonitorRegEntry SlotMonitorMap[] =
{
{ "PCSC", { CreatePCSCSlotMonitor, CreatePCSCSystemSlotMonitor } },
{ 0, { 0, 0 } }
};
#endif // NO_SMARTCARD
// ------------------------------------------------------------------------
// Version: V1R4M4
const char* GetVersion();
// ------------------------------------------------------------------------
inline void Init(bool bAlwaysInit = false)
{
static bool loaded = false;
if(loaded == true && bAlwaysInit == false)
return;
KeyReg::Insert(KeyMap);
HashReg::Insert(HashMap);
EMSAReg::Insert(EMSAMap);
PaddingReg::Insert(PaddingMap);
CertificateReg::Insert(CertificateMap);
#ifndef NO_SMARTCARD
SubsystemReg::Insert(SubsystemMap);
SlotMonitorReg::Insert(SlotMonitorMap);
SCardOSReg::Insert(SCardOSMap);
SCardTokenReg::Insert(SCardTokenMap);
PKCS15BehaviorReg::Insert(PKCS15BehaviorMap);
TokenExtensionReg::Insert(TokenExtensionMap);
TokenAuthProtocolReg::Insert(TokenAuthProtocolMap);
#endif
CreateFastRNG = CreateFIPS186;
CreateStrongRNG = CreateBBS;
loaded = true;
}
} // namespace act
#endif // actInit_h

@ -0,0 +1,34 @@
CXXFLAGS=-pthread -g -O0 -DDEBUG
OPENSSL_LIBDIR=-L/home/carsten/openssl-0.9.8o
INCDIRS=-I/home/carsten/Devel/actlib/include/
LIBS=$(OPENSSL_LIBDIR) -L/home/carsten/Devel/actlib/lib -lact -ldl -lcrypto -lpthread
OBJS=engine_front.o engine_sct.o CardObject.o CardKey.o SlotList.o CertificateList.o SecOpGuard.o
TARGET=libengine_securetoken.so
TESTOBJS=test_engine.o
TESTTARGET=test_engine
TESTLIBS=$(OPENSSL_LIBDIR) -lcrypto -lssl -ldl -lpthread
all: $(TARGET)
test: $(TESTTARGET)
clean:
rm -f *.o $(TARGET) $(TESTTARGET)
$(TARGET): $(OBJS)
$(CXX) --shared -o $(TARGET) $(OBJS) $(LIBS)
$(TESTTARGET): $(TESTOBJS)
$(CXX) -o $(TESTTARGET) $(TESTOBJS) $(TESTLIBS)
.cpp.o:
$(CXX) -c $(CXXFLAGS) $(INCDIRS) $<
.c.o:
$(CC) -c $(CFLAGS) $(INCDIRS) $<

@ -0,0 +1,41 @@
========================================================================
DYNAMIC LINK LIBRARY : engine_securetoken Project Overview
========================================================================
AppWizard has created this engine_securetoken DLL for you.
This file contains a summary of what you will find in each of the files that
make up your engine_securetoken application.
engine_securetoken.vcproj
This is the main project file for VC++ projects generated using an Application Wizard.
It contains information about the version of Visual C++ that generated the file, and
information about the platforms, configurations, and project features selected with the
Application Wizard.
engine_securetoken.cpp
This is the main DLL source file.
When created, this DLL does not export any symbols. As a result, it
will not produce a .lib file when it is built. If you wish this project
to be a project dependency of some other project, you will either need to
add code to export some symbols from the DLL so that an export library
will be produced, or you can set the Ignore Input Library property to Yes
on the General propert page of the Linker folder in the project's Property
Pages dialog box.
/////////////////////////////////////////////////////////////////////////////
Other standard files:
StdAfx.h, StdAfx.cpp
These files are used to build a precompiled header (PCH) file
named engine_securetoken.pch and a precompiled types file named StdAfx.obj.
/////////////////////////////////////////////////////////////////////////////
Other notes:
AppWizard uses "TODO:" comments to indicate parts of the source code you
should add to or customize.
/////////////////////////////////////////////////////////////////////////////

@ -0,0 +1,48 @@
#include "SecOpGuard.h"
#include <actDebug.h>
#include <actIToken.h>
#include <actITokenAuth.h>
SecOpGuard::SecOpGuard(act::IToken* token)
: m_token(token)
, act::SCardLock(token->GetOS())
{
ACT_ASSERT(token != NULL);
m_token_auth = token->GetAuth();
}
SecOpGuard::~SecOpGuard()
{
if(!m_token_auth->IsAuthenticated())
return;
try
{
m_token_auth->Logout();
}
catch(act::Exception& ACT_DEBUG_PARAM(e))
{
ACT_TRACE(e, "SecOpGuard::~SecOpGuard");
}
}
bool SecOpGuard::Authenticate(act::ITokenPIN* token_pin, const act::Blob& auth_data)
{
// Auth constraints, chained authorization, anyone?
if(m_token_auth->IsAuthenticated())
return true;
try
{
return (m_token_auth->Login(token_pin, auth_data));
}
catch(act::Exception& ACT_DEBUG_PARAM(e))
{
ACT_TRACE(e, "SecOpGuard::Authenticate");
}
return false;
}

@ -0,0 +1,33 @@
#ifndef __SECOPGUARD_H__
#define __SECOPGUARD_H__
namespace act
{
class IToken;
class ITokenAuth;
class ITokenPIN;
}
#include <actUtility.h>
#include <actSCardLock.h>
/*
* Transaction guard and authenticator to a card
*/
class SecOpGuard : public act::SCardLock
{
public:
SecOpGuard(act::IToken* token);
~SecOpGuard();
bool Authenticate(act::ITokenPIN* token_pin, const act::Blob& auth_data);
private:
bool m_status;
act::IToken* m_token;
act::ITokenAuth* m_token_auth;
};
#endif

@ -0,0 +1,138 @@
#include "SlotList.h"
#include <actISlot.h>
#include <actIToken.h>
#include <algorithm>
#include <actException.h>
#include <actDebug.h>
SlotEntry::SlotEntry()
: m_token(NULL)
, m_slot(NULL)
{
}
SlotEntry::SlotEntry(const SlotEntry& old_entry)
: m_slot(NULL)
, m_token(NULL)
{
init(old_entry.m_slot);
}
void SlotEntry::init(act::ISlot* slot_blueprint)
{
ACT_ASSERT(m_slot == NULL);
ACT_ASSERT(m_token == NULL);
if(!slot_blueprint)
return;
m_slot = slot_blueprint->Clone();
preload_token();
}
void SlotEntry::preload_token()
{
if(m_token != NULL)
return;
if(m_slot->IsTokenPresent())
{
try
{
m_token = m_slot->CreateToken();
}
catch(act::Exception& ACT_DEBUG_PARAM(e))
{
ACT_TRACE(e,"SlotEntry::init");
}
}
}
SlotEntry::~SlotEntry()
{
cleanup();
}
void SlotEntry::invalidate_token()
{
if(m_token)
m_token->Destroy();
m_token = NULL;
}
void SlotEntry::cleanup()
{
invalidate_token();
if(m_slot)
m_slot->Destroy();
m_slot = NULL;
}
act::IToken* SlotEntry::getToken()
{
preload_token();
if(m_token != NULL)
m_token->IncReferenceCounter();
return m_token;
}
SlotList::SlotList()
{
}
SlotList::SlotList(size_t expected_size)
{
m_slot_list.reserve(expected_size);
}
SlotList::~SlotList()
{
}
void SlotList::reserve(size_t expected_size)
{
m_slot_list.reserve(expected_size);
}
void SlotList::addSlot(act::ISlot* slot)
{
m_slot_list.push_back(SlotEntry());
m_slot_list[m_slot_list.size()-1].init(slot);
}
void SlotList::removeSlot(act::ISlot* slot)
{
for(slot_list_t::iterator it = m_slot_list.begin();it != m_slot_list.end();++it)
if(it->getSlot() == slot)
{
m_slot_list.erase(it);
break;
}
}
act::ISlot* SlotList::getSlot(size_t index)
{
if(index >= m_slot_list.size()) return NULL;
return m_slot_list[index].getSlot();
}
act::IToken* SlotList::getToken(size_t index)
{
if(index >= m_slot_list.size()) return NULL;
return m_slot_list[index].getToken();
}
void SlotList::clear()
{
m_slot_list.clear();
}

@ -0,0 +1,64 @@
#ifndef __SLOTLIST_H__
#define __SLOTLIST_H__
#include <vector>
namespace act
{
class ISlot;
class IToken;
}
class SlotEntry
{
public:
SlotEntry();
SlotEntry(const SlotEntry& old_entry);
void init(act::ISlot* slot_blueprint);
~SlotEntry();
void invalidate_token();
void preload_token();
inline act::ISlot* getSlot() const { return m_slot; }
act::IToken* getToken();
private:
void cleanup();
act::ISlot* m_slot;
act::IToken* m_token;
};
/*
* Holds a list of the present slots in the system
* TODO: Slot addition/removal detection
*/
class SlotList
{
public:
typedef std::vector<SlotEntry> slot_list_t;
SlotList();
SlotList(size_t expected_size);
~SlotList();
void reserve(size_t expected_size);
void addSlot(act::ISlot* slot);
void removeSlot(act::ISlot* slot);
void clear();
act::ISlot* getSlot(size_t index);
act::IToken* getToken(size_t index);
inline size_t getNumSlots() { return m_slot_list.size(); }
private:
slot_list_t m_slot_list;
};
#endif

@ -0,0 +1,184 @@
//////////////////////////////////////////////////////////////////////////
// Name: SyncObject.h
// Product: cv act library
// Purpose: Multithreading synchronization primitive for multiple Operating Systems.
//
// Copyright: (c) 2009 cv cryptovision GmbH
// all rights reserved
// Licence: The conditions for the use of this software are regulated
// in the cv act library licence agreement.
//
// Autor: Markus Tesche
// Date: 04/23/2009
//////////////////////////////////////////////////////////////////////////
#ifndef SyncObject_h
#define SyncObject_h
#include "actBasics.h"
#if defined(ACT_WIN32_WCE)
# include "SyncObjectWinCE.h"
#elif defined(ACT_WIN32)
# include "SyncObjectWin32.h"
#elif defined(ACT_SOLARIS)
# include "SyncObjectSloaris.h"
#elif defined(ACT_MACOSX)
# include "SyncObjectMacOS.h"
// posix has always to be last checked !
#elif defined(ACT_POSIX)
# include "SyncObjectPosix.h"
#else
# error SyncObject not implemented for this system
#endif
#include "actHandle.h"
#include "actISynchronize.h"
namespace act
{
//
// Synchronizeable<>
template
<
typename BaseT, /* ISynchronize or derived */
typename SyncObjectT = SyncObject
>
class Synchronizeable : public BaseT
{
public:
typedef SyncObjectT SyncObject;
typedef ValueHandle<SyncObjectT> SyncHandle;
protected:
//
// ISynchronize methods
virtual void Lock() { syncObject().lock(); }
virtual void Unlock() { syncObject().unlock(); }
virtual long LockCount() const { return syncObject().lockCount(); }
virtual const Handle& syncHandle() const { return m_sync_handle; }
protected:
SyncObjectT& syncObject() const { return m_sync_handle.valueRef(); }
protected:
ValueHandle<SyncObjectT> m_sync_handle;
};
//
// GuardT<>
template
<
class SyncObjectT,
class BaseT = void,
class TypeT = void
>
class GuardT;
//
// GuardT<>
template<class SyncObjectT>
class GuardT<SyncObjectT, void, void>
{
public:
typedef SyncObjectT SyncObject;
private:
GuardT(const GuardT&);
GuardT& operator=(const GuardT&);
public:
GuardT(SyncObjectT& sync_object)
: m_sync_object(sync_object)
{
m_sync_object.lock();
}
GuardT(const Handle& sync_handle)
: m_sync_object(sync_handle.requiredAs<SyncObjectT>())
{
m_sync_object.lock();
}
GuardT(const ValueHandle<SyncObjectT>& sync_handle)
: m_sync_object(sync_handle.valueRef())
{
m_sync_object.lock();
}
~GuardT()
{
m_sync_object.unlock();
}
long LockCount() const { return m_sync_object.lockCount(); }
protected:
SyncObjectT& m_sync_object;
};
//
// GuardT<>
template<class SyncObjectT>
class GuardT<SyncObjectT, ISynchronize, void>
{
public:
typedef SyncObjectT SyncObject;
private:
GuardT(const GuardT&);
GuardT& operator=(const GuardT&);
public:
GuardT(ISynchronize& synchronize)
: m_guard(synchronize.syncHandle())
{ }
GuardT(const ISynchronize& synchronize)
: m_guard(synchronize.syncHandle())
{ }
long LockCount() const { return m_guard.LockCount(); }
protected:
GuardT<SyncObjectT> m_guard;
};
//
// GuardT<>
template<class SyncObjectT, class TypeT>
class GuardT<SyncObjectT, ISynchronize, TypeT>
: public GuardT<SyncObjectT, ISynchronize, void>
{
public:
GuardT(TypeT& synchronize)
: GuardT<SyncObjectT, ISynchronize, void>(synchronize)
, m_synchronized(synchronize)
{ }
TypeT* operator->() const { return &m_synchronized; }
protected:
TypeT& m_synchronized;
};
typedef GuardT<SyncObject> Guard;
typedef GuardT<SyncObject, ISynchronize> Synchronize;
template<typename TypeT>
GuardT<SyncObject, ISynchronize, TypeT> Synchronized(TypeT& synchronize)
{
return GuardT<SyncObject, ISynchronize, TypeT>(synchronize);
}
} // namespace act
#endif // SyncObject_h

@ -0,0 +1,46 @@
#ifndef SyncObject_MacOS_h
#define SyncObject_MacOS_h
#ifndef SyncObject_h
# error include SyncObject.h instead
#endif
#include <CoreServices/CoreServices.h>
namespace act
{
class SyncObject
{
private:
SyncObject(const SyncObject&);
SyncObject& operator=(const SyncObject&);
public:
SyncObject();
~SyncObject();
void lock();
void unlock();
long lockCount() const { return m_lock_count; }
MPTaskID threadId() const { return m_thread_id; }
private:
volatile long m_lock_count;
volatile MPTaskID m_thread_id;
MPCriticalRegionID m_sync;
};
void Sleep(long msec);
} // namespace act
#ifdef verify
# undef verify
#endif
#ifdef check
# undef check
#endif
#endif // SyncObject_MacOS_h

@ -0,0 +1,38 @@
#ifndef SyncObject_Posix_h
#define SyncObject_Posix_h
#ifndef SyncObject_h
# error include SyncObject.h instead
#endif
#include <pthread.h>
namespace act
{
class SyncObject
{
private:
SyncObject(const SyncObject&);
SyncObject& operator=(const SyncObject&);
public:
SyncObject();
~SyncObject();
void lock();
void unlock();
long lockCount() const { return m_lock_count; }
pid_t threadId() const { return m_thread_id; }
private:
volatile long m_lock_count;
volatile pid_t m_thread_id;
pthread_mutex_t m_sync;
};
void Sleep(long msec);
} // namespace act
#endif // SyncObject_Posix_h

@ -0,0 +1,38 @@
#ifndef SyncObject_Solaris_h
#define SyncObject_Solaris_h
#ifndef SyncObject_h
# error include SyncObject.h instead
#endif
#include <pthread.h>
namespace act
{
class SyncObject
{
private:
SyncObject(const SyncObject&);
SyncObject& operator=(const SyncObject&);
public:
SyncObject();
~SyncObject();
void lock();
void unlock();
long lockCount() const { return m_lock_count; }
pid_t threadId() const { return m_thread_id; }
private:
volatile long m_lock_count;
volatile pid_t m_thread_id;
pthread_mutex_t m_sync;
};
void Sleep(long msec);
} // namespace act
#endif // SyncObject_Solaris_h

@ -0,0 +1,39 @@
#ifndef SyncObject_Win32_h
#define SyncObject_Win32_h
#ifndef SyncObject_h
# error include SyncObject.h instead
#endif
#ifndef _WIN32_WINNT
# define _WIN32_WINNT 0x0403
#endif
#include <windows.h>
namespace act
{
class SyncObject
{
private:
SyncObject(const SyncObject&);
SyncObject& operator=(const SyncObject&);
public:
SyncObject();
~SyncObject();
void lock();
void unlock();
long lockCount() const { return m_lock_count; }
DWORD threadId() const { return m_thread_id; }
private:
volatile long m_lock_count;
volatile DWORD m_thread_id;
CRITICAL_SECTION m_sync;
};
} // namespace act
#endif // SyncObject_Win32_h

@ -0,0 +1,36 @@
#ifndef SyncObject_WinCE_h
#define SyncObject_WinCE_h
#ifndef SyncObject_h
# error include SyncObject.h instead
#endif
#include <windows.h>
namespace act
{
class SyncObject
{
private:
SyncObject(const SyncObject&);
SyncObject& operator=(const SyncObject&);
public:
SyncObject();
~SyncObject();
void lock();
void unlock();
long lockCount() const { return m_lock_count; }
DWORD threadId() const { return m_thread_id; }
private:
volatile long m_lock_count;
volatile DWORD m_thread_id;
CRITICAL_SECTION m_sync;
};
} // namespace act
#endif // SyncObject_WinCE_h

@ -0,0 +1,7 @@
#ifndef __WARNS_H__
#define __WARNS_H__
#define _SCL_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#endif

@ -0,0 +1,19 @@
// dllmain.cpp : Defines the entry point for the DLL application.
#include "stdafx.h"
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}

@ -0,0 +1,262 @@
#include <memory>
#include <cstring>
#include <openssl/dso.h>
#include <openssl/rsa.h>
#include "engine_sct.h"
#include "engine_sct_internal.h"
#ifndef ENGINE_CMD_BASE
#error did not get engine.h
#endif
#define SCT_ENGINE_ID "act"
#define SCT_ENGINE_NAME "cv act library SecureToken interface engine"
enum {
CMD_SO_PATH = ENGINE_CMD_BASE,
CMD_PIN,
CMD_VERBOSE,
CMD_QUIET,
CMD_LOAD_CERT_CTRL,
CMD_ENUM_CERTS,
CMD_INIT_ARGS
};
static std::auto_ptr<SecureTokenEngine> g_engine;
static int sct_engine_construct(ENGINE *e);
static int sct_engine_destruct(ENGINE *e);
static int sct_engine_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)() );
static const ENGINE_CMD_DEFN sct_cmd_defns[] = {
{
CMD_SO_PATH,
"SO_PATH",
"Specifies the path to the 'securetoken-engine' shared library",
ENGINE_CMD_FLAG_STRING
},
{
CMD_PIN,
"PIN",
"Specifies the PIN to use for access",
ENGINE_CMD_FLAG_STRING
},
{
CMD_VERBOSE,
"VERBOSE",
"Increases the amount of progress information",
ENGINE_CMD_FLAG_NO_INPUT
},
{
CMD_LOAD_CERT_CTRL,
"LOAD_CERT_CTRL",
"Get the certificate from card",
ENGINE_CMD_FLAG_INTERNAL
},
{
CMD_ENUM_CERTS,
"ENUM_CERTS",
"Return the certificates and the ID's of the key pairs",
ENGINE_CMD_FLAG_INTERNAL
},
{
CMD_INIT_ARGS,
"INIT_ARGS",
"Additional initialization arguments",
ENGINE_CMD_FLAG_STRING
},
{ 0, NULL, NULL, 0 }
};
// Encapsule a "return function()" statement with a catch-all block which will emit an error message and return
// a predefined (error) return value in that case.
#define CATCH_ALL(rettype, retval, function) \
do { \
rettype result = retval; \
try \
{ \
result = (function); \
} \
catch(...) \
{ \
fprintf(stderr, "Unhandled exception caught!\n"); \
} \
return result; \
} while(0) \
static int sct_engine_construct(ENGINE *e)
{
if(g_engine.get() != 0)
return 1;
g_engine.reset(new SecureTokenEngine());
return 1;
}
static int sct_engine_destruct(ENGINE *e)
{
g_engine.reset(0);
return 1;
}
static int sct_engine_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)() )
{
switch(cmd)
{
case CMD_PIN:
return g_engine->setPin((char *) p);
case CMD_VERBOSE:
return g_engine->incVerbosity();
case CMD_LOAD_CERT_CTRL:
return g_engine->loadCertCtrl(e, (load_cert_params *)p);
case CMD_INIT_ARGS:
return g_engine->setInitArgs((const char *)p);
case CMD_ENUM_CERTS:
return g_engine->enumerate_certs(e, (enum_certs_s **)p);
default:
break;
}
return 0;
}
static int sct_init(ENGINE *e)
{
CATCH_ALL(int,0,g_engine->init());
}
static int sct_finish(ENGINE *e)
{
CATCH_ALL(int,0,g_engine->finish());
}
static int sct_rsa_finish(RSA *rsa)
{
CATCH_ALL(int,0,g_engine->rsa_finish(rsa));
}
static EVP_PKEY *sct_load_public_key(
ENGINE *e, const char *s_key_id, UI_METHOD *ui_method, void *callback_data)
{
CATCH_ALL(EVP_PKEY*,NULL,g_engine->load_pubkey(s_key_id, ui_method, callback_data));
}
static EVP_PKEY *sct_load_private_key(
ENGINE *e, const char *s_key_id, UI_METHOD *ui_method, void *callback_data)
{
CATCH_ALL(EVP_PKEY*,NULL,g_engine->load_privkey(s_key_id, ui_method, callback_data));
}
static int sct_rsa_encrypt(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding)
{
CATCH_ALL(int,-1,g_engine->rsa_encrypt(flen, from, to, EXTRACT_CARD_KEY(rsa), padding));
}
static int sct_rsa_decrypt(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding)
{
CATCH_ALL(int,-1,g_engine->rsa_decrypt(flen, from, to, EXTRACT_CARD_KEY(rsa), padding));
}
static int sct_rsa_sign(int type,
const unsigned char *msg, unsigned int msglen,
unsigned char *sigret, unsigned int *siglen, const RSA *rsa)
{
CATCH_ALL(int,0,g_engine->rsa_sign(type, msg, msglen, sigret, siglen, EXTRACT_CARD_KEY(rsa)));
}
static int sct_rsa_verify(int type,
const unsigned char *msg, unsigned int msglen,
unsigned char *signature, unsigned int siglen, const RSA *rsa)
{
CATCH_ALL(int,0,g_engine->rsa_verify(type, msg, msglen, signature, siglen, EXTRACT_CARD_KEY(rsa)));
}
/*
* Following part is for binding the engine into OpenSSL
*/
// Overlay the standard RSA operations with smartcard based ones
RSA_METHOD* RSA_get_sct_method()
{
static RSA_METHOD ops;
if(!ops.rsa_priv_enc)
{
ops = *RSA_get_default_method();
ops.rsa_pub_enc = sct_rsa_encrypt;
ops.rsa_priv_dec = sct_rsa_decrypt;
ops.rsa_pub_dec = NULL; // a.k.a Verify/Sign. actLibrary just allows the proper functions
ops.rsa_priv_enc = NULL; // and has this 'backdoor' closed. Breaks 'rsautl', sadly.
ops.rsa_sign = sct_rsa_sign;
ops.rsa_verify = sct_rsa_verify;
ops.finish = sct_rsa_finish;
}
return &ops;
}
static int bind_helper(ENGINE *e)
{
if(
!sct_engine_construct(e) ||
!ENGINE_set_id(e, SCT_ENGINE_ID) ||
!ENGINE_set_name(e, SCT_ENGINE_NAME) ||
!ENGINE_set_destroy_function(e, sct_engine_destruct) ||
!ENGINE_set_init_function(e, sct_init) ||
!ENGINE_set_finish_function(e, sct_finish) ||
!ENGINE_set_ctrl_function(e, sct_engine_ctrl) ||
!ENGINE_set_cmd_defns(e, sct_cmd_defns) ||
#ifndef OPENSSL_NO_RSA
!ENGINE_set_RSA(e, RSA_get_sct_method()) ||
#endif
#ifndef OPENSSL_NO_DSA
!ENGINE_set_DSA(e, DSA_get_default_method()) ||
#endif
#ifndef OPENSSL_NO_DH
!ENGINE_set_DH(e, DH_get_default_method()) ||
#endif
!ENGINE_set_RAND(e, RAND_SSLeay()) ||
#if 0
!ENGINE_set_BN_mod_exp(e, BN_mod_exp) ||
#endif
!ENGINE_set_load_pubkey_function(e, sct_load_public_key) ||
!ENGINE_set_load_privkey_function(e, sct_load_private_key))
{
return 0;
}
else
{
return 1;
}
}
static int bind_fn(ENGINE * e, const char *id)
{
#ifndef DEBUG
if (id && (strcmp(id, SCT_ENGINE_ID) != 0)) {
fprintf(stderr, "bad engine id (%s vs. %s)\n", id, SCT_ENGINE_ID);
return 0;
}
#endif
if (!bind_helper(e)) {
fprintf(stderr, "bind failed\n");
return 0;
}
return 1;
}
extern "C"
{
IMPLEMENT_DYNAMIC_CHECK_FN();
IMPLEMENT_DYNAMIC_BIND_FN(bind_fn);
}

@ -0,0 +1,402 @@
#include "engine_sct.h"
#include "engine_sct_internal.h"
#include "Init_Engine.h"
#include "CardObject.h"
#include "CardKey.h"
#include "SlotList.h"
#include "CertificateList.h"
#include "SecOpGuard.h"
#include <actIToken.h>
#include <actITokenKey.h>
#include <actITokenPIN.h>
#include <actMode.h>
#include <actState.h>
#include <actUtility.h>
#include <actDebug.h>
#include <actSlotManager.h>
#include <actAlgorithm.h>
#include <actISlot.h>
// Provide thread synchronization
#include <SyncObject.h>
#include <cstring>
EVP_PKEY *SecureTokenEngine::encapsule_CardKey(CardKey *ck)
{
EVP_PKEY* pk(EVP_PKEY_new());
RSA* rsa(RSA_new());
if(pk == NULL || rsa == NULL)
return NULL;
// Initialize the RSA structure
{
RSA_set_method(rsa, RSA_get_sct_method());
RSA_set_app_data(rsa, ck);
// We need (at least) the public exponent and the modulus for OpenSSL itself because
// it calculates the I/O buffer sizes out of it.
act::ITokenKey* key = ck->getKey();
act::Blob publicExponent;
act::Blob modulus;
key->GetParam(act::PUBLICKEY, publicExponent);
key->GetParam(act::MODULO, modulus);
act::I2OSP(modulus);
act::I2OSP(publicExponent);
rsa->n = BN_bin2bn(&modulus[0], modulus.size(), rsa->n);
rsa->e = BN_bin2bn(&publicExponent[0], publicExponent.size(), rsa->e);
// Meh. Set it here. If we don't, OpenSSL tries to emulate sign/verify with
// private_encrypt and public_decrypt which we can't do.
rsa->flags |= RSA_FLAG_SIGN_VER;
}
EVP_PKEY_set1_RSA(pk, rsa);
// Decreases refcount by one, i.e. transfers sole ownership to EVP_PKEY struct
RSA_free(rsa);
return pk;
}
int SecureTokenEngine::setPin(char *pin)
{
int plen = strlen(pin);
act::Blob(pin, pin+plen).swap(m_pin);
std::fill(pin, pin+plen, '*');
return 1;
}
int SecureTokenEngine::incVerbosity()
{
return 0;
}
int SecureTokenEngine::setInitArgs(const char *args)
{
return 0;
}
int SecureTokenEngine::init()
{
act::Init(true);
act::SlotManager slot_manager;
try
{
slot_manager.Install(act::SubsystemReg::CreateSubsystem("PCSC", 0));
slot_manager.Refresh();
}
catch(act::Exception& ACT_DEBUG_PARAM(e))
{
ACT_TRACE(e, "SecureTokenEngine::Init");
return 0;
}
int slots = slot_manager.GetSlotNumber();
for(int i = 0; i < slots; i++)
{
act::ISlot* slot(slot_manager.GetSlot(i)->Clone());
m_slot_list.addSlot(slot);
}
return 1;
}
int SecureTokenEngine::finish()
{
m_slot_list.clear();
return 1;
}
int SecureTokenEngine::rsa_finish(RSA *rsa)
{
// This function is only called on freeing of 'our' own RSA keys which have been generated
// by encapsule_CardKey
// NB: If you use something like
//
// EVP_PKEY* pk_pub = ENGINE_load_public_key(e, key_id, NULL, NULL);
// RSA* pubkey = EVP_PKEY_get1_RSA(pk_pub);
//
// in the user code, you have to use both EVP_PKEY_free() and RSA_free() until the last traces are gone.
CardKey* ck(EXTRACT_CARD_KEY(rsa));
ACT_ASSERT(ck != 0);
delete ck;
return 1;
}
int SecureTokenEngine::loadCertCtrl(ENGINE *e, load_cert_params *p)
{
CardObject co(&m_slot_list);
ACT_ASSERT(p != NULL);
ACT_ASSERT(p->s_token_cert_id != NULL);
if(p == NULL || p->s_token_cert_id == NULL)
return NULL;
if(!co.searchFor(act::CERTIFICATE, p->s_token_cert_id))
return NULL;
const act::Blob& certblob = co.getCertBlob();
const unsigned char *cbp = &certblob[0];
p->cert = d2i_X509(NULL, &cbp, certblob.size());
return p->cert != NULL ? 1 : 0;
}
EVP_PKEY *SecureTokenEngine::load_privkey(const char *s_key_id, UI_METHOD *ui_method, void *callback_data)
{
CardObject co(&m_slot_list);
if(!co.searchFor(act::PRIVATEKEY, s_key_id))
return NULL;
std::auto_ptr<CardKey> ck(new CardKey(co.getKey()));
// Ask for the PIN if not already passed into the module
if(m_pin.empty())
ck->setPin(ui_method, callback_data);
else
ck->setPin(m_pin);
// Try to authenticate with the provided PIN. If we fail, don't return the key at all.
act::IToken* token = ck->getKey()->GetToken();
SecOpGuard guard(token);
act::Synchronize lock(*token);
if(!ck->Authenticate(guard))
return NULL;
EVP_PKEY* pk = encapsule_CardKey(ck.get());
if(pk != NULL)
{
ck.release();
return pk;
}
return NULL;
}
EVP_PKEY *SecureTokenEngine::load_pubkey(const char *s_key_id, UI_METHOD *ui_method, void *callback_data)
{
// Really. Same as above, but without asking/setting a PIN. Simply because one can use an instance of
// act::ITokenKey for both ways since private and public keys are interlinked internally.
CardObject co(&m_slot_list);
if(!co.searchFor(act::PUBLICKEY, s_key_id))
return NULL;
std::auto_ptr<CardKey> ck(new CardKey(co.getKey()));
EVP_PKEY* pk = encapsule_CardKey(ck.get());
if(pk != NULL)
{
ck.release();
return pk;
}
return NULL;
}
int SecureTokenEngine::rsa_encrypt(int flen, const unsigned char *from, unsigned char *to, const CardKey* ck, int padding)
{
if(padding != RSA_PKCS1_PADDING)
{
ACT_TRACE("SecureTokenEngine::rsa_encrypt: Only RSA_PKCS1_PADDING allowed so far\n");
return -1;
}
if(ck == NULL)
{
ACT_TRACE("SecureTokenEngine::rsa_encrypt: No CardKey given\n");
return -1;
}
act::Blob _plaintext(from, from+flen);
act::Blob _ciphertext;
int retlen = -1;
act::IToken* token = ck->getKey()->GetToken();
SecOpGuard guard(token);
act::Synchronize lock(*token);
try
{
act::Algorithm alg(ck->getKey(), act::ENCRYPT);
alg << _plaintext << act::final >> _ciphertext;
retlen = _ciphertext.size();
// OpenSSL uses these operations for just one round and determines the buffer size from the
// key length. Still I'm not happy with it.
std::copy(_ciphertext.begin(), _ciphertext.end(), to);
}
catch(act::Exception& ACT_DEBUG_PARAM(e))
{
ACT_TRACE(e, "SecureTokenEngine::rsa_encrypt");
}
return retlen;
}
int SecureTokenEngine::rsa_decrypt(int flen, const unsigned char *from, unsigned char *to, CardKey* ck, int padding)
{
if(padding != RSA_PKCS1_PADDING)
{
ACT_TRACE("SecureTokenEngine::rsa_decrypt: Only RSA_PKCS1_PADDING allowed so far\n");
return -1;
}
if(ck == NULL)
{
ACT_TRACE("SecureTokenEngine::rsa_decrypt: No CardKey given\n");
return -1;
}
act::IToken* token = ck->getKey()->GetToken();
SecOpGuard guard(token);
act::Synchronize lock(*token);
if(!ck->Authenticate(guard))
return -1;
act::Blob _ciphertext(from, from+flen);
act::Blob _plaintext;
int retlen = -1;
try
{
act::Algorithm alg(ck->getKey(), act::DECRYPT);
alg << _ciphertext << act::final >> _plaintext;
retlen = _plaintext.size();
// Same as with rsa_encrypt
std::copy(_plaintext.begin(), _plaintext.end(), to);
}
catch(act::Exception& ACT_DEBUG_PARAM(e))
{
ACT_TRACE(e, "SecureTokenEngine::rsa_decrypt");
}
return retlen;
}
int SecureTokenEngine::rsa_sign(int type, const unsigned char *msg, unsigned int msglen, unsigned char *sigret, unsigned int *siglen, CardKey* ck)
{
if(ck == NULL)
{
ACT_TRACE("SecureTokenEngine::rsa_sign: No CardKey given\n");
return 0;
}
act::IToken* token = ck->getKey()->GetToken();
SecOpGuard guard(ck->getKey()->GetToken());
act::Synchronize lock(*token);
if(!ck->Authenticate(guard))
return 0;
act::Blob _plaintext(msg, msg+msglen);
act::Blob _signature;
unsigned int _siglen = 0;
// In that case the hashing is already done and we just need the lowlevel key operation
bool ssl = (type == NID_md5_sha1);
act::ITokenKey* key = ck->getKey();
act::Blob oldhash;
key->GetParam(act::HASH, oldhash);
if(ssl)
key->SetParam(act::HASH, "DummyHash");
try
{
act::Algorithm alg(ck->getKey(), act::SIGN);
alg << _plaintext << act::final >> _signature;
_siglen = _signature.size();
// I won't repeat myself here....
std::copy(_signature.begin(), _signature.end(), sigret);
}
catch(act::Exception& ACT_DEBUG_PARAM(e))
{
ACT_TRACE(e, "SecureTokenEngine::rsa_sign");
}
key->SetParam(act::HASH, oldhash);
*siglen = _siglen;
return _siglen > 0 ? 1 : 0;
}
int SecureTokenEngine::rsa_verify(int type, const unsigned char *msg, unsigned int msglen, unsigned char *signature, unsigned int siglen, const CardKey* ck)
{
if(ck == NULL)
{
ACT_TRACE("SecureTokenEngine::rsa_verify: No CardKey given\n");
return 0;
}
act::IToken* token = ck->getKey()->GetToken();
SecOpGuard guard(token);
act::Synchronize lock(*token);
act::Blob _plaintext(msg, msg+msglen);
act::Blob _signature(signature, signature+siglen);
bool sig_ok = false;
try
{
act::Algorithm alg(ck->getKey(), act::VERIFY, _signature);
alg << _plaintext << act::final;
sig_ok = alg.GetStatus() == act::SIGNATURE_OK;
}
catch(act::Exception& ACT_DEBUG_PARAM(e))
{
ACT_TRACE(e, "SecureTokenEngine::rsa_verify");
}
if(!sig_ok)
RSAerr(RSA_F_RSA_VERIFY, RSA_R_BAD_SIGNATURE);
return sig_ok ? 1 : 0;
}
int SecureTokenEngine::enumerate_certs(ENGINE *e, enum_certs_s **p)
{
if(p == NULL)
return 0;
// Drop and free old instance (if present) and create a fresh one.
m_cert_list.reset(new CertificateList());
m_cert_list->init(m_slot_list);
*p = m_cert_list->getEnumList();
// Only way to return 0 would be that we ran out of memory. If there are no certificates to be found
// we would return successful, but with an empty list (num_certs == 0)
return *p ? 1 : 0;
}

@ -0,0 +1,38 @@
#ifndef _ENGINE_SCT_H_
#define _ENGINE_SCT_H_
#include <openssl/crypto.h>
#include <openssl/objects.h>
#if defined(_MSC_VER)
// Zero-sized array
#pragma warning(disable: 4200)
#endif
/*
* Parameter structure to be passed to the engine call "LOAD_CERT_CTRL"
*/
struct load_cert_params
{
const char* s_token_cert_id; // in
X509* cert; // out
};
struct enum_cert_s
{
const char* id; // ID which can be passed as key ID for crypto operations
const char* name; // Alternatively one can use the name, provided it's unique for the token.
X509* cert; // Decoded certificate
};
struct enum_certs_s
{
unsigned int num_certs; // Number of certificates present
enum_cert_s certificate[]; // Array of identifiers and certificates
};
#endif

@ -0,0 +1,90 @@
#ifndef _ENGINE_SCT_INTERNAL_H_
#define _ENGINE_SCT_INTERNAL_H_
#include <memory>
#include <list>
#include <vector>
#include <map>
#include <openssl/crypto.h>
#include <openssl/objects.h>
#include <openssl/engine.h>
#if defined(_MSC_VER)
#pragma comment(lib, "libeay32.lib")
#endif
#ifdef U64
#undef U64
#endif
#include <actBlob.h>
struct load_cert_params;
#include "SlotList.h"
#include "CertificateList.h"
class CardKey;
struct enum_certs_s;
#define EXTRACT_CARD_KEY(rsastruct) (reinterpret_cast<CardKey*>(RSA_get_app_data(rsastruct)))
/*
* Core module. Actual engine startup/finish code and crypto operations.
*/
class SecureTokenEngine
{
public:
SecureTokenEngine() { }
~SecureTokenEngine() { }
// NOTE: contents of source string will be overwritten for security reasons
int setPin(char *pin);
int incVerbosity();
int setInitArgs(const char *args);
int init();
int finish();
int rsa_finish(RSA *rsa);
int loadCertCtrl(ENGINE *e, load_cert_params *p);
EVP_PKEY *load_pubkey(const char *s_key_id, UI_METHOD *ui_method, void *callback_data);
EVP_PKEY *load_privkey(const char *s_key_id, UI_METHOD *ui_method, void *callback_data);
// Caller is required to provide an output buffer of sufficient size, depending on input data's length
// and used key material. Improper usage may cause buffer overruns. OpenSSL API's weakness.
// Encrypt/Decrypt return size of output data on success, -1 on failure.
int rsa_encrypt(int flen, const unsigned char *from, unsigned char *to, const CardKey* ck, int padding);
int rsa_decrypt(int flen, const unsigned char *from, unsigned char *to, CardKey* ck, int padding);
// Sign/Verify return 1 on success, 0 on failure.
int rsa_sign(int type, const unsigned char *msg, unsigned int msglen, unsigned char *sigret, unsigned int *siglen, CardKey* ck);
int rsa_verify(int type, const unsigned char *msg, unsigned int msglen, unsigned char *signature, unsigned int siglen, const CardKey* ck);
// Return a list of all certificates and the necessary IDs to use them
// !! frees up the memory of the previosly returned structure in subsequent calls !!
int enumerate_certs(ENGINE *e, enum_certs_s **p);
private:
EVP_PKEY *encapsule_CardKey(CardKey *ck);
act::Blob m_pin;
SlotList m_slot_list;
std::auto_ptr<CertificateList> m_cert_list;
};
// Needed in SecureTokenEngine for creation of new RSA key (stubs) as well
RSA_METHOD* RSA_get_sct_method();
#endif

@ -0,0 +1,6 @@
// engine_securetoken.cpp : Defines the exported functions for the DLL application.
//
#include "stdafx.h"

@ -0,0 +1,24 @@

Microsoft Visual Studio Solution File, Format Version 10.00
# Visual Studio 2008
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "engine_securetoken", "engine_securetoken.vcproj", "{A1D90F74-60E0-4ED0-A93D-F626A754310D}"
EndProject
Global
GlobalSection(SubversionScc) = preSolution
Svn-Managed = True
Manager = AnkhSVN - Subversion Support for Visual Studio
EndGlobalSection
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{A1D90F74-60E0-4ED0-A93D-F626A754310D}.Debug|Win32.ActiveCfg = Debug|Win32
{A1D90F74-60E0-4ED0-A93D-F626A754310D}.Debug|Win32.Build.0 = Debug|Win32
{A1D90F74-60E0-4ED0-A93D-F626A754310D}.Release|Win32.ActiveCfg = Release|Win32
{A1D90F74-60E0-4ED0-A93D-F626A754310D}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

@ -0,0 +1,347 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9,00"
Name="engine_securetoken"
ProjectGUID="{A1D90F74-60E0-4ED0-A93D-F626A754310D}"
RootNamespace="engine_securetoken"
Keyword="Win32Proj"
TargetFrameworkVersion="196613"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="/actlibrary/Source/EMSA;/actlibrary/Source/Random;/actlibrary/Source/Padding;/actlibrary/Source/Certificate;/actlibrary/Source/Hash;/actlibrary/Source/PublicKey;/actlibrary/Source/SecureToken;/actlibrary/Source/Frame;/openssl/include"
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;ENGINE_SECURETOKEN_EXPORTS;_SCL_SECURE_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="actvcmtd.lib"
OutputFile="$(OutDir)\engine_act.dll"
LinkIncremental="2"
AdditionalLibraryDirectories="&quot;\actlibrary\Source\lib_VC_2008\$(PlatformName)&quot;;\openssl\lib"
GenerateDebugInformation="true"
SubSystem="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="2"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
EnableIntrinsicFunctions="true"
AdditionalIncludeDirectories="/actlibrary/Source/EMSA;/actlibrary/Source/Random;/actlibrary/Source/Padding;/actlibrary/Source/Certificate;/actlibrary/Source/Hash;/actlibrary/Source/PublicKey;/actlibrary/Source/SecureToken;/actlibrary/Source/Frame;/openssl/include"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;ENGINE_SECURETOKEN_EXPORTS;_SCL_SECURE_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="actvcmt.lib"
OutputFile="$(OutDir)\engine_act.dll"
LinkIncremental="1"
AdditionalLibraryDirectories="&quot;\actlibrary\Source\lib_VC_2008\$(PlatformName)&quot;;\openssl\lib"
GenerateDebugInformation="true"
SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath=".\CardKey.cpp"
>
</File>
<File
RelativePath=".\CardObject.cpp"
>
</File>
<File
RelativePath=".\CertificateList.cpp"
>
</File>
<File
RelativePath=".\dllmain.cpp"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"
CompileAsManaged="0"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="0"
CompileAsManaged="0"
/>
</FileConfiguration>
</File>
<File
RelativePath=".\engine_front.cpp"
>
</File>
<File
RelativePath=".\engine_sct.cpp"
>
</File>
<File
RelativePath=".\engine_securetoken.cpp"
>
</File>
<File
RelativePath=".\SecOpGuard.cpp"
>
</File>
<File
RelativePath=".\SlotList.cpp"
>
</File>
<File
RelativePath=".\stdafx.cpp"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"
/>
</FileConfiguration>
</File>
<File
RelativePath=".\test_engine.cpp"
>
<FileConfiguration
Name="Debug|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
<File
RelativePath=".\CardKey.h"
>
</File>
<File
RelativePath=".\CardObject.h"
>
</File>
<File
RelativePath=".\CertificateList.h"
>
</File>
<File
RelativePath=".\engine_sct.h"
>
</File>
<File
RelativePath=".\engine_sct_internal.h"
>
</File>
<File
RelativePath=".\Init_Engine.h"
>
</File>
<File
RelativePath=".\SecOpGuard.h"
>
</File>
<File
RelativePath=".\SlotList.h"
>
</File>
<File
RelativePath=".\stdafx.h"
>
</File>
<File
RelativePath=".\targetver.h"
>
</File>
<File
RelativePath=".\Warns.h"
>
</File>
</Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
>
</Filter>
<Filter
Name="Misc"
>
<File
RelativePath=".\Makefile"
>
</File>
</Filter>
<File
RelativePath=".\ReadMe.txt"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

@ -0,0 +1,8 @@
// stdafx.cpp : source file that includes just the standard includes
// engine_securetoken.pch will be the pre-compiled header
// stdafx.obj will contain the pre-compiled type information
#include "stdafx.h"
// TODO: reference any additional headers you need in STDAFX.H
// and not in this file

@ -0,0 +1,16 @@
// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
//
#pragma once
#include "targetver.h"
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
// Windows Header Files:
#include <windows.h>
// TODO: reference additional headers your program requires here

@ -0,0 +1,24 @@
#pragma once
// The following macros define the minimum required platform. The minimum required platform
// is the earliest version of Windows, Internet Explorer etc. that has the necessary features to run
// your application. The macros work by enabling all features available on platform versions up to and
// including the version specified.
// Modify the following defines if you have to target a platform prior to the ones specified below.
// Refer to MSDN for the latest info on corresponding values for different platforms.
#ifndef WINVER // Specifies that the minimum required platform is Windows Vista.
#define WINVER 0x0600 // Change this to the appropriate value to target other versions of Windows.
#endif
#ifndef _WIN32_WINNT // Specifies that the minimum required platform is Windows Vista.
#define _WIN32_WINNT 0x0600 // Change this to the appropriate value to target other versions of Windows.
#endif
#ifndef _WIN32_WINDOWS // Specifies that the minimum required platform is Windows 98.
#define _WIN32_WINDOWS 0x0410 // Change this to the appropriate value to target Windows Me or later.
#endif
#ifndef _WIN32_IE // Specifies that the minimum required platform is Internet Explorer 7.0.
#define _WIN32_IE 0x0700 // Change this to the appropriate value to target other versions of IE.
#endif

@ -0,0 +1,84 @@
#include "engine_sct.h"
#include <cstring>
#include <openssl/rsa.h>
int main(int argc, char* argv[])
{
ENGINE* e = NULL;
enum_certs_s* certs_found = NULL;
ENGINE_load_dynamic();
e = ENGINE_by_id("dynamic");
int res;
// Parameters to set for the dynamic loader
res = ENGINE_ctrl_cmd_string(e, "SO_PATH", "/home/carsten/engine_securetoken/libengine_securetoken.so", 0);
res = ENGINE_ctrl_cmd_string(e, "ID", "securetoken", 0);
res = ENGINE_ctrl_cmd_string(e, "LIST_ADD", "1", 0);
// Now actually load the SecureToken engine.
res = ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0);
// Following control commands go to the SecureToken engine rather than the dynamic loader
res = ENGINE_init(e);
res = ENGINE_ctrl_cmd(e, "ENUM_CERTS", 0, &certs_found, NULL, 0);
printf("Found %d certificates.\n", certs_found->num_certs);
enum_cert_s* selected_cert = NULL;
for(int i=0;i<certs_found->num_certs;i++)
{
printf("Certificate %d:\n", i);
printf(" Name: %s\n", certs_found->certificate[i].cert->name);
if(certs_found->certificate[i].id == NULL)
printf(" No key.\n");
else
{
printf(" Key access ID: %s\n", certs_found->certificate[i].id);
if(!selected_cert) selected_cert = &certs_found->certificate[i];
}
}
EVP_PKEY* pk_pub = ENGINE_load_public_key(e, selected_cert->id, NULL, NULL);
RSA* pubkey = EVP_PKEY_get1_RSA(pk_pub);
const char* source = "Dies ist ein geheimer Testtext zum Verschlüsseln\n";
int srclen = strlen(source)+1;
unsigned char cipherbuf[srclen*2048];
int ciphlen = RSA_public_encrypt(srclen, (const unsigned char *) source, cipherbuf, pubkey, RSA_PKCS1_PADDING);
EVP_PKEY_free(pk_pub);
RSA_free(pubkey);
EVP_PKEY* pk_priv = ENGINE_load_private_key(e, selected_cert->id, NULL, NULL);
RSA* privkey = EVP_PKEY_get1_RSA(pk_priv);
char plainbuf[srclen*2];
int plainlen = RSA_private_decrypt(ciphlen, cipherbuf, (unsigned char *) plainbuf, privkey, RSA_PKCS1_PADDING);
EVP_PKEY_free(pk_priv);
RSA_free(privkey);
if(srclen != plainlen || strcmp(source, plainbuf))
printf("Unterschied in Ver/Entschlüsselung");
else
printf("%s",plainbuf);
res = ENGINE_finish(e);
ENGINE_cleanup();
return 0;
}
Loading…
Cancel
Save