A simple Qt based browser with no bullshit that supports PKCS#11 tokens (such as the SuisseID).
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

262 lines
5.8 KiB

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