|
|
@ -15,26 +15,165 @@ |
|
|
|
|
|
|
|
|
|
|
|
#include <memory> |
|
|
|
#include <memory> |
|
|
|
|
|
|
|
|
|
|
|
class CryptokiEngine: public openssl::Engine { |
|
|
|
class CryptokiEngine: public QObject, public openssl::Engine { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Q_OBJECT; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Q_SIGNALS: |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void certRequired(); |
|
|
|
|
|
|
|
|
|
|
|
public: |
|
|
|
public: |
|
|
|
CryptokiEngine(std::string lib): |
|
|
|
|
|
|
|
_cryptoki(lib) { |
|
|
|
CryptokiEngine(std::string lib, QWidget* p): |
|
|
|
|
|
|
|
_cryptoki(lib), _parent(p) { |
|
|
|
|
|
|
|
OPENSSL_LOG("log"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
operator bool() { |
|
|
|
|
|
|
|
return _privateKey.get() && _cert.get(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cryptoki::Init& cryptoki() { |
|
|
|
|
|
|
|
return _cryptoki; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void cert(cryptoki::Object privateKey, std::auto_ptr<openssl::X509> c) { |
|
|
|
|
|
|
|
_cert = c; |
|
|
|
|
|
|
|
_privateKey = std::auto_ptr<cryptoki::Object> |
|
|
|
|
|
|
|
(new cryptoki::Object(privateKey)); |
|
|
|
|
|
|
|
_modulus = privateKey.attribute(CKA_MODULUS).value; |
|
|
|
|
|
|
|
_exponent = privateKey.attribute(CKA_PUBLIC_EXPONENT).value; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const openssl::X509& cert() { |
|
|
|
|
|
|
|
return *_cert; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
virtual EVP_PKEY* privkey() { |
|
|
|
|
|
|
|
OPENSSL_LOG("log"); |
|
|
|
|
|
|
|
EVP_PKEY* k(EVP_PKEY_new()); |
|
|
|
|
|
|
|
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; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
protected: |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
virtual const char* id() { |
|
|
|
|
|
|
|
OPENSSL_LOG("log"); |
|
|
|
|
|
|
|
return "CryptokiEngine_ID"; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
virtual const char* name() { |
|
|
|
OPENSSL_LOG("log"); |
|
|
|
OPENSSL_LOG("log"); |
|
|
|
|
|
|
|
return "CryptokiEngine_NAME"; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
virtual std::string rsaSign(const std::string& in, unsigned int type) { |
|
|
|
|
|
|
|
std::string inModded(in); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
OPENSSL_LOG("log"); |
|
|
|
|
|
|
|
OPENSSL_LOG("type="<<type); |
|
|
|
|
|
|
|
// CK_MECHANISM_TYPE mech(0);
|
|
|
|
|
|
|
|
// switch (type) {
|
|
|
|
|
|
|
|
// case NID_idea_ecb: mech=CKM_IDEA_ECB; break;
|
|
|
|
|
|
|
|
// default: throw("unknown key mechanism");
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// //------------------------------------------------------------ PKCS11_sign
|
|
|
|
|
|
|
|
// int sigsize(openssl::BigNum(_modulus).size());
|
|
|
|
|
|
|
|
// {
|
|
|
|
|
|
|
|
// int ssl = ((type == NID_md5_sha1) ? 1 : 0);
|
|
|
|
|
|
|
|
// unsigned char *encoded = NULL;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// if (ssl) {
|
|
|
|
|
|
|
|
// OPENSSL_LOG("It's SSL");
|
|
|
|
|
|
|
|
// if((inModded.size() != 36) /* SHA1 + MD5 */ ||
|
|
|
|
|
|
|
|
// ((inModded.size() + RSA_PKCS1_PADDING_SIZE) > sigsize)) {
|
|
|
|
|
|
|
|
// throw std::runtime_error("the size is wrong");
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
// } else {
|
|
|
|
|
|
|
|
// OPENSSL_LOG("It's not SSL");
|
|
|
|
|
|
|
|
// ASN1_TYPE parameter;
|
|
|
|
|
|
|
|
// parameter.type = V_ASN1_NULL;
|
|
|
|
|
|
|
|
// parameter.value.ptr = 0;
|
|
|
|
|
|
|
|
// X509_ALGOR algor;
|
|
|
|
|
|
|
|
// algor.algorithm = OBJ_nid2obj(type);
|
|
|
|
|
|
|
|
// algor.parameter = ¶meter;
|
|
|
|
|
|
|
|
// ASN1_STRING digest;
|
|
|
|
|
|
|
|
// digest.data = (unsigned char *)inModded.data();
|
|
|
|
|
|
|
|
// digest.length = inModded.size();
|
|
|
|
|
|
|
|
// X509_SIG sig;
|
|
|
|
|
|
|
|
// sig.algor = &algor;
|
|
|
|
|
|
|
|
// sig.digest = &digest;
|
|
|
|
|
|
|
|
// int size (i2d_X509_SIG(&sig, 0));
|
|
|
|
|
|
|
|
// if (!algor.algorithm) throw std::runtime_error("algor wrong nid");
|
|
|
|
|
|
|
|
// if (!algor.algorithm->length)
|
|
|
|
|
|
|
|
// throw std::runtime_error("algor length");
|
|
|
|
|
|
|
|
// if (size) throw std::runtime_error("digest size");
|
|
|
|
|
|
|
|
// if (size + RSA_PKCS1_PADDING_SIZE < sigsize)
|
|
|
|
|
|
|
|
// throw std::runtime_error("incompatible size");
|
|
|
|
|
|
|
|
// unsigned char* buf(new unsigned char[size]);
|
|
|
|
|
|
|
|
// i2d_X509_SIG(&sig, &buf);
|
|
|
|
|
|
|
|
// inModded.assign((char*)buf, size);
|
|
|
|
|
|
|
|
// delete[] buf;
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// //------------------------------------------------- PKCS11_private_encrypt
|
|
|
|
|
|
|
|
// {
|
|
|
|
|
|
|
|
// char padding(RSA_PKCS1_PADDING);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// if ((inModded.size() + RSA_PKCS1_PADDING_SIZE) > sigsize)
|
|
|
|
|
|
|
|
// throw std::runtime_error("the size is wrong");
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// //-----------------------------------------------------------------------
|
|
|
|
|
|
|
|
// if (in!=inModded)
|
|
|
|
|
|
|
|
// OPENSSL_LOG("changed input"<<std::endl
|
|
|
|
|
|
|
|
// <<"from:"<<std::endl
|
|
|
|
|
|
|
|
// <<crypto::readable(in)<<std::endl
|
|
|
|
|
|
|
|
// <<"to:"<<std::endl
|
|
|
|
|
|
|
|
// <<crypto::readable(inModded));
|
|
|
|
|
|
|
|
return _privateKey->sign(inModded, CKM_RSA_PKCS); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private: |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cryptoki::Init _cryptoki; |
|
|
|
|
|
|
|
std::string _modulus; |
|
|
|
|
|
|
|
std::string _exponent; |
|
|
|
|
|
|
|
std::auto_ptr<cryptoki::Object> _privateKey; |
|
|
|
|
|
|
|
std::auto_ptr<openssl::X509> _cert; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public: |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void login() { |
|
|
|
|
|
|
|
QMutexLocker lock(&_mutex); |
|
|
|
|
|
|
|
try { |
|
|
|
|
|
|
|
QList<CertInfo> authcerts; |
|
|
|
|
|
|
|
QList<CertInfo> allcerts; |
|
|
|
QSslConfiguration sslConfig(QSslConfiguration::defaultConfiguration()); |
|
|
|
QSslConfiguration sslConfig(QSslConfiguration::defaultConfiguration()); |
|
|
|
QList<QSslCertificate> cacerts(sslConfig.caCertificates()); |
|
|
|
QList<QSslCertificate> cacerts(sslConfig.caCertificates()); |
|
|
|
QList<QSslCertificate> authcerts; |
|
|
|
|
|
|
|
QList<QSslCertificate> allcerts; |
|
|
|
|
|
|
|
QSslCertificate cert; |
|
|
|
|
|
|
|
_slots = _cryptoki.slotList(); |
|
|
|
_slots = _cryptoki.slotList(); |
|
|
|
for (cryptoki::SlotList::iterator slot(_slots.begin()); |
|
|
|
for (cryptoki::SlotList::iterator slot(_slots.begin()); |
|
|
|
slot!=_slots.end() && _pin.isEmpty(); ++slot) { |
|
|
|
slot!=_slots.end(); ++slot) { |
|
|
|
_session = |
|
|
|
_session = |
|
|
|
std::auto_ptr<cryptoki::Session>(new cryptoki::Session(*slot)); |
|
|
|
std::auto_ptr<cryptoki::Session>(new cryptoki::Session(*slot)); |
|
|
|
cryptoki::ObjectList certs(_session->find |
|
|
|
cryptoki::ObjectList certs(_session->find |
|
|
|
(cryptoki::Attribute(CKA_CLASS) |
|
|
|
(cryptoki::Attribute(CKA_CLASS) |
|
|
|
.from<CK_OBJECT_CLASS>(CKO_CERTIFICATE))); |
|
|
|
.from<CK_OBJECT_CLASS>(CKO_CERTIFICATE))); |
|
|
|
for (cryptoki::ObjectList::iterator cert(certs.begin()); |
|
|
|
for (cryptoki::ObjectList::iterator cert(certs.begin()); |
|
|
|
cert!=certs.end() && _pin.isEmpty(); ++cert) { |
|
|
|
cert!=certs.end(); ++cert) { |
|
|
|
cryptoki::Attribute label(cert->attribute(CKA_LABEL)); |
|
|
|
cryptoki::Attribute label(cert->attribute(CKA_LABEL)); |
|
|
|
cryptoki::Attribute id(cert->attribute(CKA_ID)); |
|
|
|
cryptoki::Attribute id(cert->attribute(CKA_ID)); |
|
|
|
OPENSSL_LOG("**** FOUND CERTIFICATE: "<<label.value); |
|
|
|
OPENSSL_LOG("**** FOUND CERTIFICATE: "<<label.value); |
|
|
@ -43,9 +182,9 @@ class CryptokiEngine: public openssl::Engine { |
|
|
|
.from<CK_OBJECT_CLASS>(CKO_PUBLIC_KEY), |
|
|
|
.from<CK_OBJECT_CLASS>(CKO_PUBLIC_KEY), |
|
|
|
id)); |
|
|
|
id)); |
|
|
|
OPENSSL_LOG("**** with keys: "<<keys.size()); |
|
|
|
OPENSSL_LOG("**** with keys: "<<keys.size()); |
|
|
|
|
|
|
|
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"); |
|
|
|
std::string data(cert->attribute(CKA_VALUE).value); |
|
|
|
|
|
|
|
cacerts.push_back(QSslCertificate |
|
|
|
cacerts.push_back(QSslCertificate |
|
|
|
(QByteArray(data.data(), data.size()), |
|
|
|
(QByteArray(data.data(), data.size()), |
|
|
|
QSsl::Der)); |
|
|
|
QSsl::Der)); |
|
|
@ -54,160 +193,70 @@ class CryptokiEngine: public openssl::Engine { |
|
|
|
if (label.value.find("auth")==0 || |
|
|
|
if (label.value.find("auth")==0 || |
|
|
|
label.value.find("Authentication")!=std::string::npos) { |
|
|
|
label.value.find("Authentication")!=std::string::npos) { |
|
|
|
OPENSSL_LOG("**** it's our authentication cert"); |
|
|
|
OPENSSL_LOG("**** it's our authentication cert"); |
|
|
|
std::string data(cert->attribute(CKA_VALUE).value); |
|
|
|
authcerts.push_back(CertInfo(data, slot, id)); |
|
|
|
QSslCertificate c(QByteArray(data.data(), data.size()), |
|
|
|
} else { |
|
|
|
QSsl::Der); |
|
|
|
OPENSSL_LOG("**** it's an unknown cert"); |
|
|
|
PinEntry pinEntry(c); /*! @todo set widget */ |
|
|
|
allcerts.push_back(CertInfo(data, slot, id)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (!authcerts.isEmpty() || !allcerts.isEmpty()) { |
|
|
|
|
|
|
|
CertInfo c(authcerts.size()?authcerts[0]:allcerts[0]); |
|
|
|
|
|
|
|
PinEntry pinEntry(QSslCertificate(QByteArray(c.data.data(), |
|
|
|
|
|
|
|
c.data.size()), |
|
|
|
|
|
|
|
QSsl::Der), _parent); |
|
|
|
while (pinEntry.exec()==PinEntry::Accepted) |
|
|
|
while (pinEntry.exec()==PinEntry::Accepted) |
|
|
|
try { |
|
|
|
try { |
|
|
|
cryptoki::Attribute value(cert->attribute(CKA_VALUE)); |
|
|
|
_session = |
|
|
|
_cert = std::auto_ptr<openssl::X509> |
|
|
|
std::auto_ptr<cryptoki::Session> |
|
|
|
(new openssl::X509(value.value)); |
|
|
|
(new cryptoki::Session(*c.slot)); |
|
|
|
_session->login(pinEntry.pin().toStdString()); |
|
|
|
_session->login(pinEntry.pin().toStdString()); |
|
|
|
cryptoki::ObjectList keys |
|
|
|
cryptoki::ObjectList keys |
|
|
|
(_session->find(cryptoki::Attribute(CKA_CLASS) |
|
|
|
(_session->find(cryptoki::Attribute(CKA_CLASS) |
|
|
|
.from<CK_OBJECT_CLASS>(CKO_PRIVATE_KEY), |
|
|
|
.from<CK_OBJECT_CLASS>(CKO_PRIVATE_KEY), |
|
|
|
id)); |
|
|
|
c.id)); |
|
|
|
if (keys.size()==1) { |
|
|
|
if (keys.size()==1) { |
|
|
|
OPENSSL_LOG("**** found one private key"); |
|
|
|
OPENSSL_LOG("**** found one private key"); |
|
|
|
_privateKeys = keys; |
|
|
|
cert(keys[0], |
|
|
|
_modulus = keys[0].attribute(CKA_MODULUS).value; |
|
|
|
std::auto_ptr<openssl::X509> |
|
|
|
_exponent = keys[0].attribute(CKA_PUBLIC_EXPONENT).value; |
|
|
|
(new openssl::X509(c.data))); |
|
|
|
} |
|
|
|
sslConfig.setCaCertificates(cacerts); |
|
|
|
_pin = pinEntry.pin(); |
|
|
|
|
|
|
|
break; |
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
} catch (std::exception& x) { |
|
|
|
} catch (std::exception& x) { |
|
|
|
_pin.clear(); |
|
|
|
pinEntry.pin().clear(); |
|
|
|
OPENSSL_LOG("**** ERROR"<<x.what()); |
|
|
|
OPENSSL_LOG("**** ERROR"<<x.what()); |
|
|
|
QMessageBox::critical(0, QMessageBox::tr("Wrong PIN"), |
|
|
|
QMessageBox::critical(0, QMessageBox::tr("Wrong PIN"), |
|
|
|
QMessageBox::tr("Authentication failed," |
|
|
|
QMessageBox::tr("Authentication failed," |
|
|
|
" please try again.")); |
|
|
|
" please try again.")); |
|
|
|
} |
|
|
|
} |
|
|
|
} else { |
|
|
|
|
|
|
|
OPENSSL_LOG("**** it's not our authentication cert; ignore"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
//! @todo show certificate dialog
|
|
|
|
|
|
|
|
// std::string data(cert->attribute(CKA_VALUE).value);
|
|
|
|
|
|
|
|
// allcerts.push_back(QSslCertificate
|
|
|
|
|
|
|
|
// (QByteArray(data.data(), data.size()),
|
|
|
|
|
|
|
|
// QSsl::Der));
|
|
|
|
|
|
|
|
// if (label.value.find("auth")==0) {
|
|
|
|
|
|
|
|
// authcerts.push_back(*allcerts.rbegin());
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} catch (...) { |
|
|
|
|
|
|
|
throw; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
sslConfig.setCaCertificates(cacerts); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
//! Was initialization successful?
|
|
|
|
|
|
|
|
operator bool() { |
|
|
|
|
|
|
|
return !_pin.isEmpty() && _cert.get() && _session.get(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
const openssl::X509& cert() { |
|
|
|
|
|
|
|
return *_cert; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
virtual EVP_PKEY* privkey(const char* id, UI_METHOD*, void*) { |
|
|
|
|
|
|
|
OPENSSL_LOG("log"); |
|
|
|
|
|
|
|
EVP_PKEY* k(EVP_PKEY_new()); |
|
|
|
|
|
|
|
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; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
protected: |
|
|
|
|
|
|
|
virtual const char* id() { |
|
|
|
|
|
|
|
OPENSSL_LOG("log"); |
|
|
|
|
|
|
|
return "CryptokiEngine_ID"; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
virtual const char* name() { |
|
|
|
|
|
|
|
OPENSSL_LOG("log"); |
|
|
|
|
|
|
|
return "CryptokiEngine_NAME"; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
virtual std::string rsaSign(const std::string& in, unsigned int type) { |
|
|
|
|
|
|
|
std::string inModded(in); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
OPENSSL_LOG("log"); |
|
|
|
|
|
|
|
OPENSSL_LOG("type="<<type); |
|
|
|
|
|
|
|
// CK_MECHANISM_TYPE mech(0);
|
|
|
|
|
|
|
|
// switch (type) {
|
|
|
|
|
|
|
|
// case NID_idea_ecb: mech=CKM_IDEA_ECB; break;
|
|
|
|
|
|
|
|
// default: throw("unknown key mechanism");
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//------------------------------------------------------------ PKCS11_sign
|
|
|
|
private: |
|
|
|
int sigsize(openssl::BigNum(_modulus).size()); |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
int ssl = ((type == NID_md5_sha1) ? 1 : 0); |
|
|
|
|
|
|
|
unsigned char *encoded = NULL; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (ssl) { |
|
|
|
struct CertInfo { |
|
|
|
OPENSSL_LOG("It's SSL"); |
|
|
|
CertInfo(std::string d, cryptoki::SlotList::iterator s, |
|
|
|
if((inModded.size() != 36) /* SHA1 + MD5 */ || |
|
|
|
cryptoki::Attribute i): |
|
|
|
((inModded.size() + RSA_PKCS1_PADDING_SIZE) > sigsize)) { |
|
|
|
data(d), slot(s), id(i) { |
|
|
|
throw std::runtime_error("the size is wrong"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
OPENSSL_LOG("It's not SSL"); |
|
|
|
|
|
|
|
ASN1_TYPE parameter; |
|
|
|
|
|
|
|
parameter.type = V_ASN1_NULL; |
|
|
|
|
|
|
|
parameter.value.ptr = 0; |
|
|
|
|
|
|
|
X509_ALGOR algor; |
|
|
|
|
|
|
|
algor.algorithm = OBJ_nid2obj(type); |
|
|
|
|
|
|
|
algor.parameter = ¶meter; |
|
|
|
|
|
|
|
ASN1_STRING digest; |
|
|
|
|
|
|
|
digest.data = (unsigned char *)inModded.data(); |
|
|
|
|
|
|
|
digest.length = inModded.size(); |
|
|
|
|
|
|
|
X509_SIG sig; |
|
|
|
|
|
|
|
sig.algor = &algor; |
|
|
|
|
|
|
|
sig.digest = &digest; |
|
|
|
|
|
|
|
int size (i2d_X509_SIG(&sig, 0)); |
|
|
|
|
|
|
|
if (!algor.algorithm) throw std::runtime_error("algor wrong nid"); |
|
|
|
|
|
|
|
if (!algor.algorithm->length) |
|
|
|
|
|
|
|
throw std::runtime_error("algor length"); |
|
|
|
|
|
|
|
if (size) throw std::runtime_error("digest size"); |
|
|
|
|
|
|
|
if (size + RSA_PKCS1_PADDING_SIZE < sigsize) |
|
|
|
|
|
|
|
throw std::runtime_error("incompatible size"); |
|
|
|
|
|
|
|
unsigned char* buf(new unsigned char[size]); |
|
|
|
|
|
|
|
i2d_X509_SIG(&sig, &buf); |
|
|
|
|
|
|
|
inModded.assign((char*)buf, size); |
|
|
|
|
|
|
|
delete[] buf; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//------------------------------------------------- PKCS11_private_encrypt
|
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
char padding(RSA_PKCS1_PADDING); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ((inModded.size() + RSA_PKCS1_PADDING_SIZE) > sigsize) |
|
|
|
|
|
|
|
throw std::runtime_error("the size is wrong"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
|
|
|
|
if (in!=inModded) |
|
|
|
|
|
|
|
OPENSSL_LOG("changed input"<<std::endl |
|
|
|
|
|
|
|
<<"from:"<<std::endl |
|
|
|
|
|
|
|
<<crypto::readable(in)<<std::endl |
|
|
|
|
|
|
|
<<"to:"<<std::endl |
|
|
|
|
|
|
|
<<crypto::readable(inModded)); |
|
|
|
|
|
|
|
return _privateKeys[0].sign(inModded, CKM_RSA_PKCS); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
std::string data; |
|
|
|
|
|
|
|
cryptoki::SlotList::iterator slot; |
|
|
|
|
|
|
|
cryptoki::Attribute id; |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
private: |
|
|
|
private: |
|
|
|
cryptoki::Init _cryptoki; |
|
|
|
|
|
|
|
|
|
|
|
QWidget* _parent; |
|
|
|
cryptoki::SlotList _slots; |
|
|
|
cryptoki::SlotList _slots; |
|
|
|
std::auto_ptr<cryptoki::Session> _session; |
|
|
|
std::auto_ptr<cryptoki::Session> _session; |
|
|
|
QString _pin; |
|
|
|
QMutex _mutex; |
|
|
|
std::auto_ptr<openssl::X509> _cert; |
|
|
|
std::auto_ptr<PinEntry> _pinEntry; |
|
|
|
std::string _modulus; |
|
|
|
|
|
|
|
std::string _exponent; |
|
|
|
|
|
|
|
cryptoki::ObjectList _privateKeys; |
|
|
|
|
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
class SmartCardAuth: public QObject { |
|
|
|
class SmartCardAuth: public QObject { |
|
|
@ -215,30 +264,35 @@ class SmartCardAuth: public QObject { |
|
|
|
|
|
|
|
|
|
|
|
public: |
|
|
|
public: |
|
|
|
|
|
|
|
|
|
|
|
SmartCardAuth(const QString& lib): |
|
|
|
SmartCardAuth(const QString& lib, QWidget* p=0, bool login=true): |
|
|
|
_reg(e(lib)) { |
|
|
|
_reg(e(lib, p)) { |
|
|
|
qDebug()<<__PRETTY_FUNCTION__; |
|
|
|
qDebug()<<__PRETTY_FUNCTION__; |
|
|
|
|
|
|
|
if (login) e()->login(); |
|
|
|
|
|
|
|
//assert(connect(e(), SIGNAL(certRequired()), SLOT(login())));
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
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__; |
|
|
|
if (!*e()) return; // no certificate found
|
|
|
|
|
|
|
|
SSL_CTX_set_client_cert_cb(ctx, clientCert); |
|
|
|
SSL_CTX_set_client_cert_cb(ctx, clientCert); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private: |
|
|
|
|
|
|
|
|
|
|
|
static int clientCert(SSL* ssl, X509 **x509, EVP_PKEY **pkey) { |
|
|
|
static int clientCert(SSL* ssl, X509 **x509, EVP_PKEY **pkey) { |
|
|
|
|
|
|
|
qDebug()<<__PRETTY_FUNCTION__; |
|
|
|
|
|
|
|
if (!*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(0, 0, 0); |
|
|
|
*pkey = e()->privkey(); |
|
|
|
qDebug()<<"*** C "<<__PRETTY_FUNCTION__; |
|
|
|
qDebug()<<"*** C "<<__PRETTY_FUNCTION__; |
|
|
|
return 1; |
|
|
|
return 1; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static CryptokiEngine* e(const QString& lib = QString()) { |
|
|
|
static CryptokiEngine* e(const QString& lib = QString(), QWidget* p = 0) { |
|
|
|
static CryptokiEngine* _e(new CryptokiEngine(lib.toStdString())); |
|
|
|
static CryptokiEngine* _e(new CryptokiEngine(lib.toStdString(), p)); |
|
|
|
return _e; |
|
|
|
return _e; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|