first cleanup; still missing: RPM/Debian packages, pkgconfig, version compiled-in-version-info; refs #7

This commit is contained in:
Marc Wäckerlin
2010-09-29 11:19:03 +00:00
parent adbb943401
commit a0cd614bf3
47 changed files with 3596 additions and 1899 deletions

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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->Release();
}
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;
}

View File

@@ -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

View File

@@ -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->Release();
}
// 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++;
}
}

View File

@@ -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

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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->Release();
m_token = NULL;
}
void SlotEntry::cleanup()
{
invalidate_token();
if(m_slot)
m_slot->Release();
m_slot = NULL;
}
act::IToken* SlotEntry::getToken()
{
preload_token();
if(m_token != NULL)
m_token->AddRef();
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();
}

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

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

View File

@@ -0,0 +1,654 @@
//////////////////////////////////////////////////////////////////////////////////
// Name: actUtility.h
// Product: cv act library
// Purpose: useful global functions
//
// Copyright: (c) 2000-2001 cv cryptovision GmbH
// all rights reserved
// Licence: The conditions for the use of this software are regulated
// in the cv act library licence agreement.
//////////////////////////////////////////////////////////////////////////////////
#ifndef ACT_Utility_h
#define ACT_Utility_h
#include "actBlob.h"
#include "actBasics.h"
#include "actException.h"
#include <string>
#include <algorithm>
#include <cctype>
#include <cwctype>
#include <stdio.h>
#include <ctype.h>
#if defined(__GNUC__) && (__GNUC__ < 4)
namespace act { typedef std::basic_string<wchar_t> wstring; }
#else
namespace act { using std::wstring; }
#endif
namespace act
{
class IParam;
//
// Const Values
//
extern const size_t sizeof_uuid;
//
// Prototypes
//
const char* get_string_param(paramid_t id, IParam* owner);
// Converts an unsigned hexadecimal number (independent of prefix "0x")
// into a Blob and backwards.
// - for blob2hex: the user has to allocate hexnumber
Blob& hex2blob(const char* hexnumber, Blob& b);
inline Blob& hex2blob(const std::string& hexnumber, Blob& b)
{
return hex2blob(hexnumber.c_str(), b);
}
inline Blob hex2blob(const char* hexnumber)
{
Blob b;
return move(hex2blob(hexnumber, b));
}
void blob2hex(const Blob& b, char* hexnumber);
std::string blob2hex(const Blob& b);
// file i/o for act::Blob
bool file2blob(const char* filename, Blob &blob);
bool blob2file(const char* filename, const act::Blob &blob);
// Create an ISO 9834-8 / RFC 4122 version 4 (pseudo random) UUID.
// Output string format is "xxxxxxxx-xxxx-4xxx-vxxx-xxxxxxxxxxxx", where
// x is random hex char 0 <= x <= f and v an element of { 8, 9, a, b}.
void createPseudoRandomUUID(Blob& uuid, bool network_byte_order = true);
std::string createPseudoRandomUUID();
std::string uuid2string(const Blob& uuid, bool is_network_byte_order = true);
void swapTimeFields(Blob& uuid);
std::string serno2string(const act::Blob& serno);
std::string id2string(const act::Blob& id, bool is_network_byte_order = true);
// CBCMAC with ISO padding
void iCBCMAC(const char* cipher, const Blob& iv, const Blob& mac_key,
const Blob& mac_data, Blob& mac);
void SetDESKeyParity(Blob &key);
bool CheckDESKeyParity(const Blob &key);
void get_string_seq(const std::string& s, const std::string start, const std::string end,
std::string& result, bool case_sens);
bool wstr2utf8(const wchar_t* str, std::string& utf8);
bool utf82wstr(const char* utf8, act::wstring& wstr);
void ASN1ToSequenceOf(Blob& asn1_data);
Blob GetASN1SequenceOf(const Blob& asn1_data);
Blob GetASN1EncodedLength(size_t length);
size_t SkipTagLength(byte tag, const byte* tlv_data, size_t tlv_data_len);
size_t SkipTLVElement(byte tag, const byte* tlv_data, size_t tlv_data_len, bool skip_value = true);
int FindTlvTemplate(Blob& contentb, const Blob& inb, int intag, int counts);
//
// Implementation
//
//
// --------------------------------------------------------------------
template<typename ConverterT, typename RegistryT, typename TypeT>
const Blob SafeGetName(TypeT* instance)
{
Blob name;
if(instance != 0)
{
const char* cname = RegistryT::GetName(instance->GetCreatePointer());
if(cname != 0) ConverterT(cname).swap(name);
}
return move(name);
}
// ---------------------------------------------------------------------------
template<typename TypeT>
struct is_whitespace : is_whitespace<typename TypeT::value_type>
{
typedef typename TypeT::value_type argument_type;
using is_whitespace<typename TypeT::value_type>::operator();
};
template<>
struct is_whitespace<char>
{
typedef char argument_type;
bool operator()(unsigned char value) const { return std::isspace(value) != 0; }
};
template<>
struct is_whitespace<wchar_t>
{
typedef wchar_t argument_type;
bool operator()(wchar_t value) const { return std::iswspace(value) != 0; }
};
// ---------------------------------------------------------------------------
template<typename PredicateT, typename TypeT>
inline TypeT& erase_right(const PredicateT& predicate, TypeT& value)
{
value.erase(std::find_if(value.rbegin(), value.rend(), predicate).base(), value.end());
return value;
}
// ---------------------------------------------------------------------------
template<typename TypeT>
inline void fill(TypeT* begin, size_t length, byte value)
{
ACT_ASSERT(begin != 0);
std::fill(reinterpret_cast<act::byte*>(begin),
reinterpret_cast<act::byte*>(begin) + length, value);
}
//
// scoped_delete<PointerT>
// ---------------------------------------------------------------------------
template<typename PointerT>
struct scoped_delete<PointerT, void, 1>
{
PointerT _ptr;
explicit scoped_delete(PointerT ptr) : _ptr(ptr) { }
~scoped_delete() { delete _ptr; }
PointerT operator->() const
{
if(_ptr == 0) throw NullPointerException();
return _ptr;
}
};
// ---------------------------------------------------------------------------
template<typename PointerT>
scoped_delete<PointerT, void, 1> checked_delete(PointerT& ptr_ref)
{
PointerT ptr = ptr_ref; ptr_ref = 0;
return scoped_delete<PointerT, void, 1>(ptr);
}
//
// scoped_delete<AutoPtrT>
// ---------------------------------------------------------------------------
template
<
template<class> class AutoPtrT,
class TypeT
>
struct scoped_delete<AutoPtrT<TypeT>, void, 1>
{
AutoPtrT<TypeT> _ptr;
explicit scoped_delete(AutoPtrT<TypeT>& ptr) : _ptr(ptr) { }
~scoped_delete() { AutoPtrT<TypeT>(_ptr); }
TypeT* operator->() const
{
TypeT* ptr = _ptr.get();
if(ptr == 0) throw NullPointerException();
return ptr;
}
};
// ---------------------------------------------------------------------------
template
<
template<class> class AutoPtrT,
class TypeT
>
scoped_delete<AutoPtrT<TypeT>, void, 1> checked_delete(AutoPtrT<TypeT>& ptr_ref)
{
return scoped_delete<AutoPtrT<TypeT>, void, 1>(ptr_ref);
}
//
// scoped_delete<ArrayT<TypeT*> >
// ---------------------------------------------------------------------------
template
<
template<class, class> class ArrayT,
class TypeT, class AllocatorT,
typename DestructF
>
struct scoped_delete<ArrayT<TypeT, AllocatorT>, DestructF, 3>
{
typedef ArrayT<TypeT, AllocatorT> container_type;
typedef DestructF destruct_func;
explicit scoped_delete(container_type& _container, const destruct_func& _destruct)
: destruct(_destruct)
{ container.swap(_container); }
~scoped_delete()
{ release(container, destruct); }
static void release(container_type& container, const destruct_func& destruct)
{
if(container.empty() == true) return;
container_type failed;
typedef typename container_type::const_iterator const_iterator;
for(const_iterator i(container.begin()), end(container.end()); i != end; ++i)
try { destruct(*i); }
catch(Exception&) { failed.push_back(*i); }
container.swap(failed);
}
destruct_func destruct;
container_type container;
};
//
// checked_delete(array_of_ptr_to_type, std::mem_fun(&type::destruct));
// ---------------------------------------------------------------------------
template
<
template<class, class> class ArrayT,
class TypeT, class AllocatorT,
typename DestructF
>
scoped_delete<ArrayT<TypeT, AllocatorT>, DestructF, 3>
checked_delete(ArrayT<TypeT, AllocatorT>& container, const DestructF& destruct)
{
return scoped_delete<ArrayT<TypeT, AllocatorT>, DestructF, 3>(container, destruct);
}
//
// scoped_delete<MapT<TypeT*> >
// ---------------------------------------------------------------------------
template
<
template<class, class, class, class> class MapT,
class KeyT, class TypeT, class PredT, class AllocatorT,
typename DestructF
>
struct scoped_delete<MapT<KeyT, TypeT, PredT, AllocatorT>, DestructF, 4>
{
typedef MapT<KeyT, TypeT, PredT, AllocatorT> container_type;
typedef DestructF destruct_func;
explicit scoped_delete(container_type& _container, const destruct_func& _destruct)
: destruct(_destruct)
{ container.swap(_container); }
~scoped_delete()
{ release(container, destruct); }
static void release(container_type& container, const destruct_func& destruct)
{
if(container.empty() == true) return;
container_type failed;
typedef typename container_type::const_iterator const_iterator;
for(const_iterator i(container.begin()), end(container.end()); i != end; ++i)
try { destruct(i->second); }
catch(Exception&) { failed.insert(*i); }
container.swap(failed);
}
destruct_func destruct;
container_type container;
};
//
// checked_delete_map(map_of_ptr_to_type, std::mem_fun(&type::destruct));
// ---------------------------------------------------------------------------
template
<
template<class, class, class, class> class MapT,
class KeyT, class TypeT, class PredT, class AllocatorT,
typename DestructF
>
scoped_delete<MapT<KeyT, TypeT, PredT, AllocatorT>, DestructF, 4>
checked_delete_map(MapT<KeyT, TypeT, PredT, AllocatorT>& map_ref, const DestructF& destruct)
{
return scoped_delete<MapT<KeyT, TypeT, PredT, AllocatorT>, DestructF, 4>(map_ref, destruct);
}
//
// scoped_delete<>
// ---------------------------------------------------------------------------
template<typename TypeT, typename DestructF>
struct scoped_delete<TypeT, DestructF, 0>
{
scoped_delete(const DestructF& _destruct)
: destruct(_destruct)
{ }
~scoped_delete()
{ if(value.empty() == false) checked_delete(value, destruct); }
DestructF destruct;
TypeT value;
};
//
// checked_static_cast<>
// ---------------------------------------------------------------------------
template<class U, class V>
inline U checked_static_cast(V p)
{
ACT_ASSERT(p != 0);
ACT_ASSERT(dynamic_cast<U>(p) != 0);
return static_cast<U>(p);
}
// ---------------------------------------------------------------------------
template<typename TypeT>
inline TypeT& byref(const TypeT& e)
{
return const_cast<TypeT&>(e);
}
// ---------------------------------------------------------------------------
inline int max_int()
{
return int((unsigned(1) << (8 * sizeof(int) - 1)) - 1);
}
// ---------------------------------------------------------------------------
inline void OS2IP(Blob& number)
{
// octet string to integer presentation
if((number.at(0) & byte(0x80)) != 0)
number.insert(number.begin(), 0);
}
// ---------------------------------------------------------------------------
inline void I2OSP(Blob& number)
{
// integer to octet string presentation
if(number.at(0) == byte(0))
number.erase(number.begin());
}
// ---------------------------------------------------------------------------
inline void byte2long(const byte *in, size_t input_len, uint32 *out)
{
size_t i, output_len = input_len / 4;
for(i = 0; i < output_len; i++)
out[i]= in[i*4] | (in[i*4+1] << 8) | (in[i*4+2] << 16) | (in[i*4+3] << 24);
}
// ---------------------------------------------------------------------------
inline void long2byte(const uint32 *in, size_t input_len, byte *out)
{
size_t i, output_len = input_len * 4;
for(i = 0; i < output_len; i++)
out[i] = byte(in[i/4] >> (8*(i%4)));
}
// ---------------------------------------------------------------------------
inline void sweep(void* Mem,size_t l)
{
std::fill_n(reinterpret_cast<byte*>(Mem), l, byte(0));
}
// ---------------------------------------------------------------------------
template<class TypeT>
inline const TypeT Min(const TypeT& a, const TypeT& b)
{
return (a < b) ? a : b;
}
// ---------------------------------------------------------------------------
template<class TypeT>
inline const TypeT& Max(const TypeT& a, const TypeT& b)
{
return (a<b)? b : a;
}
// ---------------------------------------------------------------------------
template<class T1, class T2, class T3>
inline void xor_n(T1 a, T2 len, T3 b)
{
for(T2 i = 0; i < len; i++) b[i] ^= a[i];
}
// ---------------------------------------------------------------------------
template<class T1, class T3> inline void Xor (T1 a, T1 a_end, T3 b)
{
while(a < a_end)
*b++ ^= *a++;
}
// ---------------------------------------------------------------------------
inline const char* blob2char(Blob& b)
{
b.push_back(byte(0));
return reinterpret_cast<const char*>(&b[0]);
}
// ---------------------------------------------------------------------------
inline std::string blob2string(const Blob& value)
{
return value.empty() == false ?
std::string(reinterpret_cast<const std::string::value_type*>(&value.at(0)),
reinterpret_cast<const std::string::value_type*>(&value[0] + value.size())) :
std::string();
}
// ---------------------------------------------------------------------------
inline std::string byte2hex(const byte i)
{
char tmp[3];
sprintf(tmp, "%02x", i);
return tmp;
}
// ---------------------------------------------------------------------------
inline bool isHex(const byte c)
{
if((c < byte('0') || c > byte('9'))
&& (c < byte('a') || c > byte('f'))
&& (c < byte('A') || c > byte('F')))
return false;
return true;
}
// ---------------------------------------------------------------------------
inline bool isHex(const Blob& b)
{
size_t i, b_len = b.size();
for(i = 0; i < b_len; ++i)
if(!isHex(b[i]))
return false;
return true;
}
// ---------------------------------------------------------------------------
inline bool isAlphanumeric(const byte c)
{
if((c < byte('0') || c > byte('9'))
&& (c < byte('a') || c > byte('z'))
&& (c < byte('A') || c > byte('Z')))
return false;
return true;
}
// ---------------------------------------------------------------------------
inline bool isAlphanumeric(const Blob& b)
{
size_t i, b_len = b.size();
for(i = 0; i < b_len; ++i)
if(!isAlphanumeric(b[i]))
return false;
return true;
}
// ---------------------------------------------------------------------------
inline bool isPrintable(const Blob& b)
{
size_t i, b_len = b.size();
for(i = 0; i < b_len; ++i)
if(isprint(int(b[i])) == 0)
return false;
return true;
}
// ---------------------------------------------------------------------------
inline bool isUUIDFormat(const Blob& b)
{
size_t b_len = b.size();
if(b_len != sizeof_uuid)
return false;
// check if the Blob contains only hexadecimal characters,
// separated by '-' (UUID string representation)
for(size_t i = 0; i < b_len; ++i)
if(!isHex(b[i]) && (b[i] != byte('-')))
return false;
return true;
}
// ---------------------------------------------------------------------------
inline std::string short2hex(const unsigned short i)
{
char tmp[5];
sprintf(tmp,"%04x",i);
return tmp;
}
// ---------------------------------------------------------------------------
inline std::string long2hex(const unsigned long i)
{
char tmp[9];
sprintf(tmp,"%08lx",i);
return tmp;
}
// ---------------------------------------------------------------------------
inline unsigned long blob2long(const Blob& b)
{
if(b.size() == 0)
throw LogicalException("bad size","blob2long");
Blob tmp(b);
while(tmp[0] == 0 && tmp.size() > sizeof(long))
tmp.erase(tmp.begin());
if(tmp.size() > sizeof(long))
throw LogicalException("bad size", "blob2long");
unsigned long n = tmp[0];
for(unsigned int i = 1; i < tmp.size(); ++i)
{
n <<= 8;
n |= tmp[i];
}
return n;
}
// ---------------------------------------------------------------------------
inline Blob& long2blob(unsigned long n, Blob& value)
{
value.resize(sizeof(long));
for(size_t i = sizeof(long) - 1, j = 0; j < sizeof(long); --i, ++j)
value[j] = byte((n >> (8 * i)) & 0xff);
return value;
}
// ---------------------------------------------------------------------------
inline Blob long2blob(unsigned long n)
{
Blob value;
return move(long2blob(n, value));
}
// ---------------------------------------------------------------------------
inline Blob size2blob(size_t size)
{
Blob tmp;
tmp.reserve(8);
if(size == 0)
{
tmp.resize(1);
return move(tmp);
}
size_t remaining = size;
while(remaining > 0)
{
tmp.insert(tmp.begin(), byte(remaining & 0xFF));
remaining >>= 8;
}
return move(tmp);
}
// ---------------------------------------------------------------------------
inline unsigned short blob2short(const Blob& b)
{
if(b.size() != sizeof(short))
throw LogicalException("bad size", "blob2short");
unsigned short n = b[1];
n += (b[0] << 8);
return n;
}
// ---------------------------------------------------------------------------
// Input: a (big endian byte arrays)
// Output: ++a (increment with carry)
inline byte memincr(byte* a, int len)
{
int i = len-1;
byte carry;
do {
carry = ++a[i] == 0 ? 1 : 0;
} while( --i >= 0 && carry != 0);
return carry;
}
// ---------------------------------------------------------------------------
// Input: a, b (big endian byte arrays)
// Output: a += b (add with carry)
inline byte memadd(byte* a, const byte* b, int len, byte carry = 0)
{
int i = len - 1;
unsigned long tmp;
for(; i >= 0; --i)
{
tmp = a[i] + b[i] + carry;
a[i] = byte(tmp & 0xff);
carry = byte(tmp >> 8);
}
return carry;
}
// ---------------------------------------------------------------------------
inline void convert_to_upper(std::string& s)
{
for(std::string::iterator it = s.begin(); it != s.end() ; ++it)
*it = toupper(*it);
}
} //namespace act
#endif // ACT_Utility_h

View File

@@ -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;
}

View File

@@ -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);
}

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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

View File

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

View File

@@ -0,0 +1,26 @@
## @id $Id$
## 1 2 3 4 5 6 7 8
## 45678901234567890123456789012345678901234567890123456789012345678901234567890
AM_CXXFLAGS += -I ${top_srcdir}/src -I ${top_srcdir}/../actlibrary/include
lib_LTLIBRARIES = libengine_act.la
noinst_PROGRAMS = test_engine
noinst_HEADERS = actUtility.h CardKey.h CardObject.h CertificateList.h \
engine_sct.h engine_sct_internal.h Init_Engine.h \
SecOpGuard.h SlotList.h stdafx.h SyncObject.h \
SyncObjectMacOS.h SyncObjectPosix.h \
SyncObjectSolaris.h SyncObjectWin32.h \
SyncObjectWinCE.h targetver.h Warns.h
libengine_act_la_SOURCES = engine_front.cpp engine_sct.cpp \
CardObject.cpp CardKey.cpp SlotList.cpp \
CertificateList.cpp SecOpGuard.cpp
libengine_act_la_LDFLAGS = -version-info @LIB_VERSION@
test_engine_SOURCES = test_engine.cpp
test_engine_LDADD = -lssl
MAINTAINERCLEANFILES = makefile.in

View File

@@ -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

View 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

View File

@@ -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

View File

@@ -0,0 +1,85 @@
#include "engine_sct.h"
#include <cstring>
#include <openssl/rsa.h>
#include <openssl/engine.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;
}