References #2
parent
021924d803
commit
9a8b208c62
33 changed files with 2848 additions and 0 deletions
Binary file not shown.
@ -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,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=""\actlibrary\Source\lib_VC_2008\$(PlatformName)";\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=""\actlibrary\Source\lib_VC_2008\$(PlatformName)";\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…
Reference in new issue