|
|
@ -5,6 +5,7 @@ |
|
|
|
#include <QtNetwork/QSslSocket> |
|
|
|
#include <QtNetwork/QSslSocket> |
|
|
|
#include <QtNetwork/QSslConfiguration> |
|
|
|
#include <QtNetwork/QSslConfiguration> |
|
|
|
#include <QtNetwork/QSslCertificate> |
|
|
|
#include <QtNetwork/QSslCertificate> |
|
|
|
|
|
|
|
#include <QtNetwork/QSslKey> |
|
|
|
#include <QtGui/QMessageBox> |
|
|
|
#include <QtGui/QMessageBox> |
|
|
|
|
|
|
|
|
|
|
|
#include <pinentry.hxx> |
|
|
|
#include <pinentry.hxx> |
|
|
@ -15,7 +16,7 @@ |
|
|
|
|
|
|
|
|
|
|
|
#include <memory> |
|
|
|
#include <memory> |
|
|
|
|
|
|
|
|
|
|
|
extern const QByteArray SWISSSIGN_GOLD_CA_G2; |
|
|
|
// extern const QByteArray SWISSSIGN_GOLD_CA_G2;
|
|
|
|
|
|
|
|
|
|
|
|
class CryptokiEngine: public QObject, public openssl::Engine { |
|
|
|
class CryptokiEngine: public QObject, public openssl::Engine { |
|
|
|
|
|
|
|
|
|
|
@ -57,22 +58,59 @@ class CryptokiEngine: public QObject, public openssl::Engine { |
|
|
|
return *_cert; |
|
|
|
return *_cert; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
virtual EVP_PKEY* privkey() { |
|
|
|
// virtual EVP_PKEY* privkey() {
|
|
|
|
OPENSSL_LOG("log"); |
|
|
|
// OPENSSL_LOG("log");
|
|
|
|
EVP_PKEY* k(EVP_PKEY_new()); |
|
|
|
// EVP_PKEY* k(EVP_PKEY_new());
|
|
|
|
RSA* r(RSA_new_method(_e)); |
|
|
|
// RSA* r(RSA_new_method(_e));
|
|
|
|
|
|
|
|
// r->n = BN_bin2bn((const unsigned char*)_modulus.data(),
|
|
|
|
|
|
|
|
// _modulus.size(), r->n);
|
|
|
|
|
|
|
|
// r->e = BN_bin2bn((const unsigned char*)_exponent.data(),
|
|
|
|
|
|
|
|
// _exponent.size(), r->e);
|
|
|
|
|
|
|
|
// // otherwise OpenSSL emulates sign/verify with encrypt/decrypt
|
|
|
|
|
|
|
|
// r->flags |= RSA_FLAG_SIGN_VER;
|
|
|
|
|
|
|
|
// EVP_PKEY_set1_RSA(k, r);
|
|
|
|
|
|
|
|
// OPENSSL_LOG("RSA_free");
|
|
|
|
|
|
|
|
// RSA_free(r);
|
|
|
|
|
|
|
|
// return k;
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// virtual RSA* rsaKey() {
|
|
|
|
|
|
|
|
// //EVP_PKEY* k(EVP_PKEY_new());
|
|
|
|
|
|
|
|
// RSA* r(RSA_new_method(_e));
|
|
|
|
|
|
|
|
// // RSA* r(RSA_new());
|
|
|
|
|
|
|
|
// r->n = BN_bin2bn((const unsigned char*)_modulus.data(),
|
|
|
|
|
|
|
|
// _modulus.size(), r->n);
|
|
|
|
|
|
|
|
// r->e = BN_bin2bn((const unsigned char*)_exponent.data(),
|
|
|
|
|
|
|
|
// _exponent.size(), r->e);
|
|
|
|
|
|
|
|
// // otherwise OpenSSL emulates sign/verify with encrypt/decrypt
|
|
|
|
|
|
|
|
// r->flags |= RSA_FLAG_SIGN_VER;
|
|
|
|
|
|
|
|
// //EVP_PKEY_set1_RSA(k, r);
|
|
|
|
|
|
|
|
// r->d = BN_bin2bn(0, 0, r->d);
|
|
|
|
|
|
|
|
// r->p = BN_bin2bn(0, 0, r->p);
|
|
|
|
|
|
|
|
// r->q = BN_bin2bn(0, 0, r->q);
|
|
|
|
|
|
|
|
// r->dmp1 = BN_bin2bn(0, 0, r->dmp1);
|
|
|
|
|
|
|
|
// r->dmp1 = BN_bin2bn(0, 0, r->dmq1);
|
|
|
|
|
|
|
|
// r->iqmp = r->n;/*BN_bin2bn(0, 0, r->iqmp);*/
|
|
|
|
|
|
|
|
// return r;
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
virtual RSA* setupRsa(RSA* r) { |
|
|
|
|
|
|
|
RSA_set_method(r, ENGINE_get_RSA(_e)); |
|
|
|
|
|
|
|
r->engine=_e; |
|
|
|
r->n = BN_bin2bn((const unsigned char*)_modulus.data(), |
|
|
|
r->n = BN_bin2bn((const unsigned char*)_modulus.data(), |
|
|
|
_modulus.size(), r->n); |
|
|
|
_modulus.size(), r->n); |
|
|
|
r->e = BN_bin2bn((const unsigned char*)_exponent.data(), |
|
|
|
r->e = BN_bin2bn((const unsigned char*)_exponent.data(), |
|
|
|
_exponent.size(), r->e); |
|
|
|
_exponent.size(), r->e); |
|
|
|
// otherwise OpenSSL emulates sign/verify with encrypt/decrypt
|
|
|
|
// otherwise OpenSSL emulates sign/verify with encrypt/decrypt
|
|
|
|
r->flags |= RSA_FLAG_SIGN_VER; |
|
|
|
r->flags |= RSA_FLAG_SIGN_VER; |
|
|
|
EVP_PKEY_set1_RSA(k, r); |
|
|
|
return r; |
|
|
|
OPENSSL_LOG("RSA_free"); |
|
|
|
|
|
|
|
RSA_free(r); |
|
|
|
|
|
|
|
return k; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// const RSA_METHOD* rsaMethod() {
|
|
|
|
|
|
|
|
// return ENGINE_get_RSA(_e);
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
protected: |
|
|
|
protected: |
|
|
|
|
|
|
|
|
|
|
|
virtual const char* id() { |
|
|
|
virtual const char* id() { |
|
|
@ -86,10 +124,10 @@ class CryptokiEngine: public QObject, public openssl::Engine { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
virtual std::string rsaSign(const std::string& in, unsigned int type) { |
|
|
|
virtual std::string rsaSign(const std::string& in, unsigned int type) { |
|
|
|
OPENSSL_LOG("log"); |
|
|
|
OPENSSL_LOG("log; type="<<type<<"; size="<<in.size()); |
|
|
|
OPENSSL_LOG("type="<<type<<"; size="<<in.size()); |
|
|
|
|
|
|
|
if (type != NID_md5_sha1) throw std::runtime_error("wrong sign type"); |
|
|
|
if (type != NID_md5_sha1) throw std::runtime_error("wrong sign type"); |
|
|
|
if (in.size() != 36) throw std::runtime_error("wrong msg size to sign"); |
|
|
|
if (in.size() != 36) throw std::runtime_error("wrong msg size to sign"); |
|
|
|
|
|
|
|
OPENSSL_LOG("ready to sign"); |
|
|
|
return _privateKey->sign(in, CKM_RSA_PKCS); |
|
|
|
return _privateKey->sign(in, CKM_RSA_PKCS); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -118,39 +156,40 @@ class SmartCardAuth: public QObject { |
|
|
|
private Q_SLOTS: |
|
|
|
private Q_SLOTS: |
|
|
|
|
|
|
|
|
|
|
|
void extendedContextInitialization(ssl_ctx_st* ctx, QSslSocket* socket) { |
|
|
|
void extendedContextInitialization(ssl_ctx_st* ctx, QSslSocket* socket) { |
|
|
|
qDebug()<<__PRETTY_FUNCTION__; |
|
|
|
// qDebug()<<__PRETTY_FUNCTION__;
|
|
|
|
QList<QSslError> expectedSslErrors; |
|
|
|
// QList<QSslError> expectedSslErrors;
|
|
|
|
for (std::list<std::string>::iterator cert(_cacerts.begin()); |
|
|
|
// for (std::list<std::string>::iterator cert(_cacerts.begin());
|
|
|
|
cert!=_cacerts.end(); ++cert) { |
|
|
|
// cert!=_cacerts.end(); ++cert) {
|
|
|
|
SSL_CTX_add_extra_chain_cert(ctx, openssl::X509(*cert).lowLevelCopy()); |
|
|
|
// SSL_CTX_add_extra_chain_cert(ctx, openssl::X509(*cert).lowLevelCopy());
|
|
|
|
expectedSslErrors.push_back(QSslError(QSslError::SelfSignedCertificateInChain, |
|
|
|
// expectedSslErrors.push_back(QSslError(QSslError::SelfSignedCertificateInChain,
|
|
|
|
QSslCertificate::fromData |
|
|
|
// QSslCertificate::fromData
|
|
|
|
(QByteArray(cert->data(), |
|
|
|
// (QByteArray(cert->data(),
|
|
|
|
cert->size()), |
|
|
|
// cert->size()),
|
|
|
|
QSsl::Der).at(0))); |
|
|
|
// QSsl::Der).at(0)));
|
|
|
|
//qDebug()<<"Added:\n"<<QSslCertificate(QByteArray(cert->data(), cert->size()), QSsl::Der).toPem();
|
|
|
|
// //qDebug()<<"Added:\n"<<QSslCertificate(QByteArray(cert->data(), cert->size()), QSsl::Der).toPem();
|
|
|
|
} |
|
|
|
// }
|
|
|
|
//socket->ignoreSslErrors(expectedSslErrors);
|
|
|
|
// //socket->ignoreSslErrors(expectedSslErrors);
|
|
|
|
SSL_CTX_set_client_cert_cb(ctx, &SmartCardAuth::clientCert); |
|
|
|
// SSL_CTX_set_client_cert_cb(ctx, &SmartCardAuth::clientCert);
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private: |
|
|
|
private: |
|
|
|
|
|
|
|
|
|
|
|
static int clientCert(SSL* ssl, X509 **x509, EVP_PKEY **pkey) { |
|
|
|
// static int clientCert(SSL* ssl, X509 **x509, EVP_PKEY **pkey) {
|
|
|
|
qDebug()<<__PRETTY_FUNCTION__; |
|
|
|
// qDebug()<<__PRETTY_FUNCTION__;
|
|
|
|
if (!e() || !*e()) return 0; // no certificate found
|
|
|
|
// if (!e() || !*e()) return 0; // no certificate found
|
|
|
|
qDebug()<<"*** A "<<__PRETTY_FUNCTION__; |
|
|
|
// qDebug()<<"*** A "<<__PRETTY_FUNCTION__;
|
|
|
|
*x509 = e()->cert().lowLevelCopy(); |
|
|
|
// *x509 = e()->cert().lowLevelCopy();
|
|
|
|
qDebug()<<"*** B "<<__PRETTY_FUNCTION__; |
|
|
|
// qDebug()<<"*** B "<<__PRETTY_FUNCTION__;
|
|
|
|
*pkey = e()->privkey(); |
|
|
|
// *pkey = e()->privkey();
|
|
|
|
qDebug()<<"*** C "<<__PRETTY_FUNCTION__; |
|
|
|
// qDebug()<<"*** C "<<__PRETTY_FUNCTION__;
|
|
|
|
return 1; |
|
|
|
// return 1;
|
|
|
|
} |
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
static CryptokiEngine* e(const QString& lib = QString()) try { |
|
|
|
static CryptokiEngine* e(const QString& lib = QString()) try { |
|
|
|
static CryptokiEngine* _e(new CryptokiEngine(lib.toStdString())); |
|
|
|
static CryptokiEngine* _e(new CryptokiEngine(lib.toStdString())); |
|
|
|
return _e; |
|
|
|
return _e; |
|
|
|
} catch (...) { |
|
|
|
} catch (const std::exception& e) { |
|
|
|
|
|
|
|
qDebug()<<"Smartcard Error: "<<e.what(); |
|
|
|
return 0; |
|
|
|
return 0; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -162,10 +201,11 @@ class SmartCardAuth: public QObject { |
|
|
|
public: |
|
|
|
public: |
|
|
|
|
|
|
|
|
|
|
|
void login(bool force=false) { |
|
|
|
void login(bool force=false) { |
|
|
|
|
|
|
|
qDebug()<<__PRETTY_FUNCTION__; |
|
|
|
QMutexLocker lock(&_mutex); |
|
|
|
QMutexLocker lock(&_mutex); |
|
|
|
if (!e() || (!force && *e())) return; // no smartcard or already logged in
|
|
|
|
if (!e() || (!force && *e())) return; // no smartcard or already logged in
|
|
|
|
try { |
|
|
|
try { |
|
|
|
_cacerts.clear(); |
|
|
|
// _cacerts.clear();
|
|
|
|
QList<CertInfo> authcerts; |
|
|
|
QList<CertInfo> authcerts; |
|
|
|
QList<CertInfo> allcerts; |
|
|
|
QList<CertInfo> allcerts; |
|
|
|
QSslConfiguration sslConfig(QSslConfiguration::defaultConfiguration()); |
|
|
|
QSslConfiguration sslConfig(QSslConfiguration::defaultConfiguration()); |
|
|
@ -190,7 +230,7 @@ class SmartCardAuth: public QObject { |
|
|
|
std::string data(cert->attribute(CKA_VALUE).value); |
|
|
|
std::string data(cert->attribute(CKA_VALUE).value); |
|
|
|
if (!keys.size()) { // add CA-certificate
|
|
|
|
if (!keys.size()) { // add CA-certificate
|
|
|
|
OPENSSL_LOG("**** add to CA-certificates"); |
|
|
|
OPENSSL_LOG("**** add to CA-certificates"); |
|
|
|
_cacerts.push_back(data); |
|
|
|
// _cacerts.push_back(data);
|
|
|
|
} else { |
|
|
|
} else { |
|
|
|
OPENSSL_LOG("**** user cert, check for authentictaion"); |
|
|
|
OPENSSL_LOG("**** user cert, check for authentictaion"); |
|
|
|
if (label.value.find("auth")==0 || |
|
|
|
if (label.value.find("auth")==0 || |
|
|
@ -224,6 +264,61 @@ class SmartCardAuth: public QObject { |
|
|
|
e()->cert(keys[0], |
|
|
|
e()->cert(keys[0], |
|
|
|
std::auto_ptr<openssl::X509> |
|
|
|
std::auto_ptr<openssl::X509> |
|
|
|
(new openssl::X509(c.data))); |
|
|
|
(new openssl::X509(c.data))); |
|
|
|
|
|
|
|
try { // new
|
|
|
|
|
|
|
|
QSslConfiguration sslConfig(QSslConfiguration::defaultConfiguration()); |
|
|
|
|
|
|
|
QSslCertificate localcert(QByteArray(c.data.data(), |
|
|
|
|
|
|
|
c.data.size()), |
|
|
|
|
|
|
|
QSsl::Der); |
|
|
|
|
|
|
|
sslConfig.setLocalCertificate(localcert); |
|
|
|
|
|
|
|
assert(localcert.isValid()); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
EVP_PKEY* pk(e()->privkey()); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// QByteArray secret("That's my Secret");
|
|
|
|
|
|
|
|
RSA* rsa(e()->rsaKey()); |
|
|
|
|
|
|
|
BIO *bio = BIO_new(BIO_s_mem()); |
|
|
|
|
|
|
|
assert(bio); |
|
|
|
|
|
|
|
OPENSSL_CHECK(PEM_write_bio_RSAPrivateKey |
|
|
|
|
|
|
|
(bio, rsa, |
|
|
|
|
|
|
|
0, 0,0,0,0)); |
|
|
|
|
|
|
|
// EVP_des_ede3_cbc(),(unsigned char*)secret.data(), secret.size(),
|
|
|
|
|
|
|
|
// 0, 0));
|
|
|
|
|
|
|
|
char *data(0); |
|
|
|
|
|
|
|
long size(BIO_get_mem_data(bio, &data)); |
|
|
|
|
|
|
|
assert(size); |
|
|
|
|
|
|
|
assert(data); |
|
|
|
|
|
|
|
QByteArray pem(data, size); |
|
|
|
|
|
|
|
BIO_free(bio); |
|
|
|
|
|
|
|
OPENSSL_LOG(pem.data()); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pem = "-----BEGIN RSA PRIVATE KEY-----\n" |
|
|
|
|
|
|
|
"MIIBOwIBAAJBAMH2yqAGeVNPdgeZ2GoHo31m9aUxZ7QfK2Go2qLTahLpQ3UL1C8G\n" |
|
|
|
|
|
|
|
"LkuMS8SNK0ZGfRMalIpIhv6bW5l3kjogOncCAwEAAQJABVGECtFCoGMsZFb2lSmy\n" |
|
|
|
|
|
|
|
"dOzOzYHGSy0TnnDn1dEgNnZ8sIljElPtUzm9dyXs2P3ICL1sOd7qjpzfJeyxknDL\n" |
|
|
|
|
|
|
|
"AQIhAO5iKdLmhyuW+EDEH19vDs1Pmqs3/ZnT5UgUiJnTJqz3AiEA0ExIfUOCnxq2\n" |
|
|
|
|
|
|
|
"a3Z46KEivcr8JB2P9VqouBbVryiq/oECIQDj8bPCejMoiEzMSX0iWWTTB9qC/KAg\n" |
|
|
|
|
|
|
|
"FtF4skHIrXKfEwIgPCs86Uo+Ch2aQjKHvJMHSRHAgeI0OmiEwiB+e0lhE4ECIQDd\n" |
|
|
|
|
|
|
|
"IbUmHIXt6oHLJmoGFX46bCcfil5eE5FXfiaw7Q9iPw==\n" |
|
|
|
|
|
|
|
"-----END RSA PRIVATE KEY-----\n"; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bio = BIO_new_mem_buf(const_cast<char *>(pem.data()), pem.size()); |
|
|
|
|
|
|
|
rsa = 0; |
|
|
|
|
|
|
|
OPENSSL_CHECK(PEM_read_bio_RSAPrivateKey(bio, &rsa, 0, 0)); |
|
|
|
|
|
|
|
assert(rsa); |
|
|
|
|
|
|
|
BIO_free(bio); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
QSslKey privkey(pem, QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey); |
|
|
|
|
|
|
|
// ,
|
|
|
|
|
|
|
|
// secret);
|
|
|
|
|
|
|
|
e()->setupRsa((RSA*)privkey.handle()); |
|
|
|
|
|
|
|
OPENSSL_LOG("Got Key"); |
|
|
|
|
|
|
|
OPENSSL_LOG(privkey.toPem().data()); |
|
|
|
|
|
|
|
assert(!privkey.isNull()); |
|
|
|
|
|
|
|
sslConfig.setPrivateKey(privkey); |
|
|
|
|
|
|
|
QSslConfiguration::setDefaultConfiguration(sslConfig); |
|
|
|
|
|
|
|
} catch (const std::exception& e) { |
|
|
|
|
|
|
|
OPENSSL_LOG("SETUP ERROR: "<<e.what()); |
|
|
|
|
|
|
|
} |
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
} catch (std::exception& x) { |
|
|
|
} catch (std::exception& x) { |
|
|
@ -234,8 +329,8 @@ class SmartCardAuth: public QObject { |
|
|
|
" please try again.")); |
|
|
|
" please try again.")); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
QByteArray ca(QSslCertificate(SWISSSIGN_GOLD_CA_G2, QSsl::Pem).toDer()); |
|
|
|
// QByteArray ca(QSslCertificate(SWISSSIGN_GOLD_CA_G2, QSsl::Pem).toDer());
|
|
|
|
_cacerts.push_back(std::string(ca.data(), ca.size())); |
|
|
|
// _cacerts.push_back(std::string(ca.data(), ca.size()));
|
|
|
|
} catch (...) { |
|
|
|
} catch (...) { |
|
|
|
throw; |
|
|
|
throw; |
|
|
|
} |
|
|
|
} |
|
|
@ -259,7 +354,7 @@ class SmartCardAuth: public QObject { |
|
|
|
cryptoki::SlotList _slots; |
|
|
|
cryptoki::SlotList _slots; |
|
|
|
std::auto_ptr<cryptoki::Session> _session; |
|
|
|
std::auto_ptr<cryptoki::Session> _session; |
|
|
|
QMutex _mutex; |
|
|
|
QMutex _mutex; |
|
|
|
std::list<std::string> _cacerts; |
|
|
|
// std::list<std::string> _cacerts;
|
|
|
|
|
|
|
|
|
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|