diff --git a/doc/xca.sgml b/doc/xca.sgml index 82417529..8c0ec972 100644 --- a/doc/xca.sgml +++ b/doc/xca.sgml @@ -472,7 +472,7 @@ I used the following providers for testing: The support of Netkey 4E cards is currently restricted. Only import and using the keys is possible. For other cards the support is probably better. Aladdin eToken PKIclient-5.1: Works perfectly: Read public keys from the token, write private keys to the token, generate keys on the token, write certificates to the token and delete them from the token. -Linux only: OpenCryptoki [IBM]: may be used as a pure software token, but also supports TPMs and other IBM crypto processors +Linux only: OpenCryptoki \[IBM\]: may be used as a pure software token, but also supports TPMs and other IBM crypto processors Tested compatibility with other applications @@ -492,19 +492,20 @@ I initialized the token as follows: Export server cert as "PEM Cert + key" without password for Apache2 Firefox / Mozilla -> Apache +

Enable PKCS#11 token in firefox: Edit->Preferences->Advanced: [SecurityDevices]: [Load] Load PKCS#11 Device: /usr/lib/libeTPkcs11.so Import CA certificate: Edit->Preferences->Advanced: [View Certificates] [Authorities]: [Import] Prepare apache config with: - -SSLEngine on -SSLCertificateFile /etc/apache2/ssl/dalek.pem -SSLCertificateKeyFile /etc/apache2/ssl/dalek.pem -SSLCertificateChainFile /etc/apache2/ssl/my_CA.crt -SSLCACertificateFile /etc/apache2/ssl/my_CA.crt -SSLVerifyClient require -SSLVerifyDepth 10 - + +SSLEngine on +SSLCertificateFile /etc/apache2/ssl/dalek.pem +SSLCertificateKeyFile /etc/apache2/ssl/dalek.pem +SSLCertificateChainFile /etc/apache2/ssl/my_CA.crt +SSLCACertificateFile /etc/apache2/ssl/my_CA.crt +SSLVerifyClient require +SSLVerifyDepth 10 + Connect with firefox to the server. Firefox will prompt you to select one of the 2 client certificates. Both work. diff --git a/lib/exception.h b/lib/exception.h index 28b93a6e..6503f676 100644 --- a/lib/exception.h +++ b/lib/exception.h @@ -17,7 +17,7 @@ class errorEx private: QString msg; public: - errorEx(QString txt, QString className = "") + errorEx(QString txt = "", QString className = "") { msg = txt; if (!className.isEmpty()) diff --git a/lib/pk11_attribute.cpp b/lib/pk11_attribute.cpp index a6ea4dc6..130427bd 100644 --- a/lib/pk11_attribute.cpp +++ b/lib/pk11_attribute.cpp @@ -41,6 +41,11 @@ void pk11_attr_data::setValue(const unsigned char *ptr, unsigned long len) { if (attr.pValue) free(attr.pValue); + if (!ptr || len == 0) { + attr.ulValueLen = 0; + attr.pValue = NULL; + return; + } attr.pValue = malloc(len); check_oom(attr.pValue); memcpy(attr.pValue, ptr, len); diff --git a/lib/pk11_attribute.h b/lib/pk11_attribute.h index 288e1def..c3e096ab 100644 --- a/lib/pk11_attribute.h +++ b/lib/pk11_attribute.h @@ -119,6 +119,7 @@ class pk11_attr_data: public pk11_attribute { public: + pk11_attr_data() :pk11_attribute(0) { } pk11_attr_data(unsigned long type, const unsigned char *v = NULL, unsigned long len = 0) :pk11_attribute(type) { @@ -175,6 +176,14 @@ public: void setBignum(BIGNUM *bn, bool consume=true); void load(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj); void setValue(const unsigned char *ptr, unsigned long len); + pk11_attr_data &operator = (const pk11_attr_data &p) + { + const unsigned char *ptr; + unsigned long size = p.getValue(&ptr); + attr.type = p.attr.type; + setValue(ptr, size); + return *this; + } }; class pk11_attlist { diff --git a/lib/pkcs11.cpp b/lib/pkcs11.cpp index dfe4ffba..61b4b228 100644 --- a/lib/pkcs11.cpp +++ b/lib/pkcs11.cpp @@ -32,11 +32,15 @@ void pkcs11::startSession(unsigned long slot, bool rw) unsigned long flags = CKF_SERIAL_SESSION | (rw ? CKF_RW_SESSION : 0); if (session != CK_INVALID_HANDLE) { + WAITCURSOR_START; rv = p11->C_CloseSession(session); + WAITCURSOR_END; if (rv != CKR_OK) pk11error("C_OpenSession", rv); } + WAITCURSOR_START; rv = p11->C_OpenSession(slot, flags, NULL, NULL, &session); + WAITCURSOR_END; if (rv != CKR_OK) pk11error("C_OpenSession", rv); slot_id = slot; @@ -51,7 +55,9 @@ QList pkcs11::getSlotList() /* This one helps to avoid errors. * Fist time it fails, 2nd time it works */ + WAITCURSOR_START; p11->C_GetSlotList(CK_TRUE, p11_slots, &num_slots); + WAITCURSOR_END; while (1) { rv = p11->C_GetSlotList(CK_TRUE, p11_slots, &num_slots); if (rv != CKR_OK && rv != CKR_BUFFER_TOO_SMALL) @@ -82,12 +88,16 @@ QList pkcs11::mechanismList(unsigned long slot) QList ml; unsigned long count; + WAITCURSOR_START; rv = p11->C_GetMechanismList(slot, NULL, &count); + WAITCURSOR_END; if (count != 0) { m = (CK_MECHANISM_TYPE *)malloc(count *sizeof(*m)); check_oom(m); + WAITCURSOR_START; rv = p11->C_GetMechanismList(slot, m, &count); + WAITCURSOR_END; if (rv != CKR_OK) { free(m); pk11error("C_GetMechanismList", rv); @@ -103,7 +113,9 @@ QList pkcs11::mechanismList(unsigned long slot) void pkcs11::mechanismInfo(unsigned long slot, CK_MECHANISM_TYPE m, CK_MECHANISM_INFO *info) { CK_RV rv; + WAITCURSOR_START; rv = p11->C_GetMechanismInfo(slot, m, info); + WAITCURSOR_END; if (rv != CKR_OK) { pk11error("C_GetMechanismInfo", rv); } @@ -113,7 +125,9 @@ void pkcs11::logout() const { CK_RV rv; + WAITCURSOR_START; rv = p11->C_Logout(session); + WAITCURSOR_END; if (rv != CKR_OK && rv != CKR_USER_NOT_LOGGED_IN) pk11error("C_Logout", rv); } @@ -123,7 +137,9 @@ bool pkcs11::needsLogin(bool so) CK_SESSION_INFO sinfo; CK_RV rv; + WAITCURSOR_START; rv = p11->C_GetSessionInfo(session, &sinfo); + WAITCURSOR_END; if (rv != CKR_OK) pk11error("C_GetSessionInfo", rv); @@ -155,7 +171,9 @@ void pkcs11::login(unsigned char *pin, unsigned long pinlen, bool so) unsigned long user = so ? CKU_SO : CKU_USER; CK_RV rv; + WAITCURSOR_START; rv = p11->C_Login(session, user, pin, pinlen); + WAITCURSOR_END; if (rv != CKR_OK && rv != CKR_USER_ALREADY_LOGGED_IN) pk11error("C_Login", rv); } @@ -223,7 +241,9 @@ bool pkcs11::selectToken(unsigned long *slot, QWidget *w) void pkcs11::setPin(unsigned char *oldPin, unsigned long oldPinLen, unsigned char *pin, unsigned long pinLen) { + WAITCURSOR_START; CK_RV rv = p11->C_SetPIN(session, oldPin, oldPinLen, pin, pinLen); + WAITCURSOR_END; if (rv != CKR_OK) pk11error("C_SetPIN", rv); } @@ -286,8 +306,10 @@ void pkcs11::initPin(unsigned long slot) pinp = newPin; } if (newPinLen != -1) { + WAITCURSOR_START; CK_RV rv = p11->C_InitPIN(session, (unsigned char*)pinp, newPinLen); + WAITCURSOR_END; if (rv != CKR_OK) pk11error("C_InitPIN", rv); } @@ -302,7 +324,9 @@ void pkcs11::initToken(unsigned long slot, unsigned char *pin, int pinlen, memset(clabel, ' ', 32); memcpy(clabel, ba.constData(), ba.size()); + WAITCURSOR_START; CK_RV rv = p11->C_InitToken(slot, pin, pinlen, clabel); + WAITCURSOR_END; if (rv != CKR_OK) pk11error("C_InitToken", rv); } @@ -312,7 +336,9 @@ tkInfo pkcs11::tokenInfo(CK_SLOT_ID slot) CK_TOKEN_INFO token_info; CK_RV rv; + WAITCURSOR_START; rv = p11->C_GetTokenInfo(slot, &token_info); + WAITCURSOR_END; if (rv != CKR_OK) { pk11error("C_GetTokenInfo", rv); } @@ -324,7 +350,9 @@ QString pkcs11::driverInfo() CK_INFO info; CK_RV rv; + WAITCURSOR_START; rv = p11->C_GetInfo(&info); + WAITCURSOR_END; if (rv != CKR_OK) { pk11error("C_GetInfo", rv); } @@ -359,7 +387,9 @@ CK_OBJECT_HANDLE pkcs11::createObject(pk11_attlist &attrs) CK_RV rv; CK_OBJECT_HANDLE obj; + WAITCURSOR_START; rv = p11->C_CreateObject(session, attrs.getAttributes(), attrs.length(), &obj); + WAITCURSOR_END; if (rv != CKR_OK) { pk11error("C_CreateObject", rv); } @@ -373,7 +403,9 @@ int pkcs11::deleteObjects(pk11_attlist &atts) objects = objectList(atts); for (int i=0; i< objects.count(); i++) { + WAITCURSOR_START; rv = p11->C_DestroyObject(session, objects[i]); + WAITCURSOR_END; if (rv != CKR_OK) { pk11error("C_DestroyObject", rv); } @@ -429,10 +461,12 @@ pk11_attr_data pkcs11::generateRSAKey(QString name, unsigned long bits) pk11_attr_bool(CKA_UNWRAP, true) << label << new_id; + WAITCURSOR_START; rv = p11->C_GenerateKeyPair(session, &mechanism, pub_atts.getAttributes(), pub_atts.length(), priv_atts.getAttributes(), priv_atts.length(), &pubkey, &privkey); + WAITCURSOR_END; if (rv != CKR_OK) { pk11error("C_GenerateKeyPair", rv); } @@ -449,20 +483,26 @@ QList pkcs11::objectList(pk11_attlist &atts) att_num = atts.get(&attribute); + WAITCURSOR_START; rv = p11->C_FindObjectsInit(session, attribute, att_num); + WAITCURSOR_END; if (rv != CKR_OK) pk11error("C_FindObjectsInit", rv); do { + WAITCURSOR_START; rv = p11->C_FindObjects(session, objects, 256, &len); + WAITCURSOR_END; if (rv != CKR_OK) pk11error("C_FindObjects", rv); for (i=0; iC_FindObjectsFinal(session); + WAITCURSOR_END; if (rv != CKR_OK) pk11error("C_FindObjectsFinal", rv); diff --git a/lib/pkcs11.h b/lib/pkcs11.h index 1deb5fe1..3fc1a19b 100644 --- a/lib/pkcs11.h +++ b/lib/pkcs11.h @@ -9,6 +9,9 @@ #include "pk11_attribute.h" +#define WAITCURSOR_START QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)) +#define WAITCURSOR_END QApplication::restoreOverrideCursor() + class tkInfo { private: diff --git a/lib/pki_scard.cpp b/lib/pki_scard.cpp index 7e6966e4..209197c7 100644 --- a/lib/pki_scard.cpp +++ b/lib/pki_scard.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #if defined(_WIN32) || defined(USE_CYGWIN) @@ -496,6 +497,26 @@ bool pki_scard::prepare_card(unsigned long *slot, bool verifyPubkey) const return false; } +class keygenThread: public QThread +{ +public: + errorEx err; + pk11_attr_data id; + QString name; + int size; + pkcs11 *p11; + + keygenThread() : QThread() { }; + void run() + { + try { + id = p11->generateRSAKey(name, size); + } catch (errorEx &e) { + err = e; + } + } +}; + void pki_scard::generateKey_card(unsigned long slot, int size, QProgressBar *bar) { pk11_attlist atts; @@ -508,10 +529,23 @@ void pki_scard::generateKey_card(unsigned long slot, int size, QProgressBar *bar if (p11.tokenLogin(ti.label(), false).isNull()) return; - bar->setValue(bar->value()+1); - pk11_attr_data id = p11.generateRSAKey(getIntName(), size); - atts << pk11_attr_ulong(CKA_CLASS, CKO_PUBLIC_KEY) << id; + keygenThread kt; + kt.name = getIntName(); + kt.size = size; + kt.p11 = &p11; + kt.start(); + while (!kt.wait(20)) { + int value = bar->value(); + if (value == bar->maximum()) { + bar->reset(); + } else { + bar->setValue(value +1); + } + } + if (!kt.err.isEmpty()) + throw errorEx(kt.err); + atts << pk11_attr_ulong(CKA_CLASS, CKO_PUBLIC_KEY) << kt.id; QList objects = p11.objectList(atts); if (objects.count() != 1) printf("OBJECTS found: %d\n",objects.count());