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