• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • tdecore
 

tdecore

tdecryptographiccarddevice.cpp
00001 /* This file is part of the TDE libraries
00002    Copyright (C) 2015 Timothy Pearson <kb9vqf@pearsoncomputing.net>
00003 
00004    This library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Library General Public
00006    License version 2 as published by the Free Software Foundation.
00007 
00008    This library is distributed in the hope that it will be useful,
00009    but WITHOUT ANY WARRANTY; without even the implied warranty of
00010    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00011    Library General Public License for more details.
00012 
00013    You should have received a copy of the GNU Library General Public License
00014    along with this library; see the file COPYING.LIB.  If not, write to
00015    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00016    Boston, MA 02110-1301, USA.
00017 */
00018 
00019 #ifdef WITH_PKCS
00020     #define _TDECRYPTOGRAPHICCARDDEVICE_INTERNAL 1
00021 #endif
00022 
00023 #include "tdecryptographiccarddevice_private.h"
00024 #include "tdecryptographiccarddevice.h"
00025 
00026 #include <tqpixmap.h>
00027 #include <tqtimer.h>
00028 #include <ntqthread.h>
00029 #include <ntqeventloop.h>
00030 #include <ntqapplication.h>
00031 
00032 #include "tdeglobal.h"
00033 #include "tdelocale.h"
00034 #include "tdeapplication.h"
00035 
00036 #include "tdehardwaredevices.h"
00037 
00038 #include "config.h"
00039 
00040 // 1 second
00041 #define PCSC_POLL_TIMEOUT_S 1000
00042 
00043 #define CARD_MAX_LOGIN_RETRY_COUNT 3
00044 
00045 /* FIXME
00046  * This is incomplete
00047  */
00048 #ifdef WITH_PCSC
00049 static TQString pcsc_error_code_to_string(long errcode) {
00050     if (errcode == SCARD_W_UNPOWERED_CARD) {
00051         return i18n("card not powered on");
00052     }
00053     else if (errcode == SCARD_E_PROTO_MISMATCH) {
00054         return i18n("protocol mismatch");
00055     }
00056     else {
00057         return TQString::null;
00058     }
00059 }
00060 #endif
00061 
00062 CryptoCardDeviceWatcher::CryptoCardDeviceWatcher() {
00063 #ifdef WITH_PCSC
00064     m_readerStates = NULL;
00065 #endif
00066     m_cardPINPromptDone = true;
00067     m_pinCallbacksEnabled = false;
00068     m_cardReusePIN = false;
00069 }
00070 
00071 CryptoCardDeviceWatcher::~CryptoCardDeviceWatcher() {
00072 #ifdef WITH_PCSC
00073     free(m_readerStates);
00074 #endif
00075 }
00076 
00077 void CryptoCardDeviceWatcher::run() {
00078 #ifdef WITH_PCSC
00079     bool first_loop;
00080     unsigned int i;
00081     long ret;
00082 
00083     DWORD dword_readers;
00084     LPSTR lpstring_readers = NULL;
00085 
00086     TQStringList readers;
00087 
00088     first_loop = true;
00089     m_terminationRequested = false;
00090 
00091     TQEventLoop* eventLoop = TQApplication::eventLoop();
00092     if (!eventLoop) return;
00093 
00094     ret = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &m_cardContext);
00095     if (ret != SCARD_S_SUCCESS) {
00096         printf("TDECryptographicCardDevice: PCSC SCardEstablishContext cannot connect to resource manager (%lX)", ret);
00097         eventLoop->exit(0);
00098         return;
00099     }
00100 
00101     ret = SCardListReaders(m_cardContext, NULL, NULL, &dword_readers);
00102     if (ret == SCARD_S_SUCCESS) {
00103         lpstring_readers = (LPSTR)malloc(sizeof(char)*dword_readers);
00104         if (lpstring_readers == NULL) {
00105             printf("TDECryptographicCardDevice: insufficient memory, aborting");
00106             eventLoop->exit(0);
00107             return;
00108         }
00109 
00110         ret = SCardListReaders(m_cardContext, NULL, lpstring_readers, &dword_readers);
00111         if (ret == SCARD_S_SUCCESS) {
00112             /* Extract reader names from the null separated string */
00113             char *ptr = lpstring_readers;
00114             while (*ptr != '\0') {
00115                 readers.append(ptr);
00116                 ptr += strlen(ptr)+1;
00117             }
00118 
00119             free(lpstring_readers);
00120 
00121             m_readerStates = (SCARD_READERSTATE*)calloc(readers.count(), sizeof(*m_readerStates));
00122             if (m_readerStates == NULL) {
00123                 printf("TDECryptographicCardDevice: insufficient memory, aborting");
00124                 free(lpstring_readers);
00125                 eventLoop->exit(0);
00126                 return;
00127             }
00128 
00129             for (i=0; i<readers.count(); i++) {
00130                 m_readerStates[i].szReader = strdup(readers[i].ascii());
00131                 m_readerStates[i].dwCurrentState = SCARD_STATE_UNAWARE;
00132             }
00133 
00134             ret = SCardGetStatusChange(m_cardContext, PCSC_POLL_TIMEOUT_S, m_readerStates, readers.count());
00135             while ((ret == SCARD_S_SUCCESS) || (ret == SCARD_E_TIMEOUT)) {
00136                 if (m_terminationRequested) {
00137                     for (i=0; i<readers.count(); i++) {
00138                         free((char*)m_readerStates[i].szReader);
00139                         m_readerStates[i].szReader = NULL;
00140                     }
00141                     eventLoop->exit(0);
00142                     return;
00143                 }
00144 
00145                 for (i=0; i<readers.count(); i++) {
00146                     /* FIXME
00147                      * Find a better / more reliable way to match the card low level device to the PCSC name
00148                      */
00149                     SCARDHANDLE hCard = 0;
00150                     DWORD dwActiveProtocol = 0;
00151                     DWORD cByte = 0;
00152                     TQString reader_vendor_name;
00153                     TQString reader_interface_type;
00154                     
00155                     ret = SCardConnect(m_cardContext, readers[i].ascii(), SCARD_SHARE_DIRECT, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &hCard, &dwActiveProtocol);
00156                     if (ret == SCARD_S_SUCCESS) {
00157                         ret = SCardGetAttrib(hCard, SCARD_ATTR_VENDOR_NAME, NULL, &cByte);
00158                         if (ret == SCARD_S_SUCCESS) {
00159                             char* data = new char[cByte];
00160                             ret = SCardGetAttrib(hCard, SCARD_ATTR_VENDOR_NAME, (LPBYTE)data, &cByte);
00161                             reader_vendor_name = data;
00162                             delete [] data;
00163                         }
00164                         ret = SCardGetAttrib(hCard, SCARD_ATTR_VENDOR_IFD_TYPE, NULL, &cByte);
00165                         if (ret == SCARD_S_SUCCESS) {
00166                             char* data = new char[cByte];
00167                             ret = SCardGetAttrib(hCard, SCARD_ATTR_VENDOR_IFD_TYPE, (LPBYTE)data, &cByte);
00168                             reader_interface_type = data;
00169                             delete [] data;
00170                         }
00171                         SCardDisconnect(hCard, SCARD_LEAVE_CARD);
00172                     }
00173 
00174                     /* FIXME
00175                      * If only one reader was detected by PCSC, assume it corresponds to the current device node.
00176                      * This is fragile, but avoids corner cases with common systems failing to work due to
00177                      * mismatched udev / PCSC card reader vendor names...
00178                      */
00179                     if (readers.count() > 1) {
00180                         if (!readers[i].contains(cardDevice->friendlyName())) {
00181                             if (!cardDevice->friendlyName().contains(reader_vendor_name) ||
00182                                 ((reader_interface_type != "") && !cardDevice->friendlyName().contains(reader_vendor_name))) {
00183                                 continue;
00184                             }
00185                         }
00186                     }
00187 
00188                     if (first_loop) {
00189                         if (m_readerStates[i].dwEventState & SCARD_STATE_PRESENT) {
00190                             // sleep(1);    // Allow the card to settle
00191                             TQString atr = getCardATR(readers[i]);
00192                             retrieveCardCertificates(readers[i]);
00193                             statusChanged("PRESENT", atr);
00194                         }
00195                         else {
00196                             deleteAllCertificatesFromCache();
00197                         }
00198                         first_loop = false;
00199                     }
00200                     if (m_readerStates[i].dwEventState & SCARD_STATE_CHANGED) {
00201                         if ((m_readerStates[i].dwCurrentState & SCARD_STATE_PRESENT)
00202                             && (m_readerStates[i].dwEventState & SCARD_STATE_EMPTY)) {
00203                             deleteAllCertificatesFromCache();
00204                             statusChanged("REMOVED", TQString::null);
00205                         }
00206                         else if ((m_readerStates[i].dwCurrentState & SCARD_STATE_EMPTY)
00207                             && (m_readerStates[i].dwEventState & SCARD_STATE_PRESENT)) {
00208                             // sleep(1);    // Allow the card to settle
00209                             TQString atr = getCardATR(readers[i]);
00210                             retrieveCardCertificates(readers[i]);
00211                             statusChanged("INSERTED", atr);
00212                         }
00213                         m_readerStates[i].dwCurrentState = m_readerStates[i].dwEventState;
00214                     }
00215                     else {
00216                         continue;
00217                     }
00218                 }
00219                 ret = SCardGetStatusChange(m_cardContext, PCSC_POLL_TIMEOUT_S, m_readerStates, readers.count());
00220             }
00221         }
00222     }
00223 
00224     eventLoop->exit(0);
00225 #endif
00226 }
00227 
00228 void CryptoCardDeviceWatcher::requestTermination() {
00229     m_terminationRequested = true;
00230 }
00231 
00232 void CryptoCardDeviceWatcher::setProvidedPin(TQString pin) {
00233     m_cardPIN = pin;
00234     m_cardPINPromptDone = true;
00235 }
00236 
00237 void CryptoCardDeviceWatcher::retrySamePin(bool enable) {
00238     m_cardReusePIN = enable;
00239     if (!enable) {
00240         m_cardPIN = "SHREDDINGTHEPINISMOSTSECURE";
00241         m_cardPIN = TQString::null;
00242     }
00243 }
00244 
00245 TQString CryptoCardDeviceWatcher::getCardATR(TQString readerName) {
00246 #ifdef WITH_PCSC
00247     unsigned int i;
00248     long ret;
00249     TQString atr_formatted;
00250     SCARDHANDLE hCard = 0;
00251     DWORD dwActiveProtocol = 0;
00252     DWORD cByte = 0;
00253 
00254     ret = SCardConnect(m_cardContext, readerName.ascii(), SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &hCard, &dwActiveProtocol);
00255     if (ret == SCARD_S_SUCCESS) {
00256         ret = SCardGetAttrib(hCard, SCARD_ATTR_ATR_STRING, NULL, &cByte);
00257         if (ret == SCARD_S_SUCCESS) {
00258             char* data = new char[cByte];
00259             ret = SCardGetAttrib(hCard, SCARD_ATTR_ATR_STRING, (LPBYTE)data, &cByte);
00260             atr_formatted = TQString::null;
00261             for (i=0; i<cByte; i++) {
00262                 TQString formatted;
00263                 formatted.sprintf("%02x ", ((uint8_t)(*(data+i))));
00264                 atr_formatted.append(formatted.upper());
00265             }
00266             atr_formatted = atr_formatted.stripWhiteSpace();
00267             delete [] data;
00268             SCardDisconnect(hCard, SCARD_LEAVE_CARD);
00269         }
00270     }
00271     else {
00272         TQString errstring = pcsc_error_code_to_string(ret);
00273         if (errstring != "") {
00274             atr_formatted = i18n("Unknown (%1)").arg(errstring);
00275         }
00276         else {
00277             atr_formatted = TQString("CARD_CONNECT_FAIL (%1)").arg(ret, 0, 16);
00278         }
00279     }
00280 
00281     return atr_formatted;
00282 #else
00283     return TQString::null;
00284 #endif
00285 }
00286 
00287 void CryptoCardDeviceWatcher::enablePINEntryCallbacks(bool enable) {
00288     m_pinCallbacksEnabled = enable;
00289 }
00290 
00291 TQString CryptoCardDeviceWatcher::doPinRequest(TQString prompt) {
00292     if (!m_pinCallbacksEnabled) {
00293         return TQString::null;
00294     }
00295 
00296     if (m_cardReusePIN) {
00297         return m_cardPIN;
00298     }
00299 
00300     m_cardPINPromptDone = false;
00301     emit(pinRequested(prompt));
00302     while (!m_cardPINPromptDone) {
00303         usleep(100);
00304     }
00305 
00306     if (m_cardPIN.length() > 0) {
00307         return m_cardPIN;
00308     }
00309     else {
00310         return TQString::null;
00311     }
00312 }
00313 
00314 #ifdef WITH_PKCS
00315 static void pkcs_log_hook(IN void * const global_data, IN unsigned flags, IN const char * const format, IN va_list args) {
00316     vprintf(format, args);
00317     printf("\n");
00318 }
00319 
00320 static PKCS11H_BOOL pkcs_pin_hook(IN void * const global_data, IN void * const user_data, IN const pkcs11h_token_id_t token, IN const unsigned retry, OUT char * const pin, IN const size_t pin_max) {
00321     CryptoCardDeviceWatcher* watcher = (CryptoCardDeviceWatcher*)global_data;
00322 
00323     TQString providedPin = watcher->doPinRequest(i18n("Please enter the PIN for '%1'").arg(token->display));
00324     if (providedPin.length() > 0) {
00325         snprintf(pin, pin_max, "%s", providedPin.ascii());
00326 
00327         // Success
00328         return 1;
00329     }
00330     else {
00331         // Abort
00332         return 0;
00333     }
00334 }
00335 #endif
00336 
00337 int CryptoCardDeviceWatcher::initializePkcs() {
00338 #if defined(WITH_PKCS)
00339     CK_RV rv;
00340     printf("Initializing pkcs11-helper\n");
00341     if ((rv = pkcs11h_initialize()) != CKR_OK) {
00342         printf("pkcs11h_initialize failed: %s\n", pkcs11h_getMessage(rv));
00343         return -1;
00344     }
00345 
00346     printf("Registering pkcs11-helper hooks\n");
00347     if ((rv = pkcs11h_setLogHook(pkcs_log_hook, this)) != CKR_OK) {
00348         printf("pkcs11h_setLogHook failed: %s\n", pkcs11h_getMessage(rv));
00349         return -1;
00350     }
00351     pkcs11h_setLogLevel(PKCS11H_LOG_WARN);
00352     // pkcs11h_setLogLevel(PKCS11H_LOG_DEBUG2);
00353 
00354 #if 0
00355     if ((rv = pkcs11h_setTokenPromptHook(_pkcs11h_hooks_token_prompt, NULL)) != CKR_OK) {
00356         printf("pkcs11h_setTokenPromptHook failed: %s\n", pkcs11h_getMessage(rv));
00357         return -1;
00358     }
00359 #endif
00360 
00361     if ((rv = pkcs11h_setMaxLoginRetries(CARD_MAX_LOGIN_RETRY_COUNT)) != CKR_OK) {
00362         printf("pkcs11h_setMaxLoginRetries failed: %s\n", pkcs11h_getMessage(rv));
00363         return -1;
00364     }
00365 
00366     if ((rv = pkcs11h_setPINPromptHook(pkcs_pin_hook, this)) != CKR_OK) {
00367         printf("pkcs11h_setPINPromptHook failed: %s\n", pkcs11h_getMessage(rv));
00368         return -1;
00369     }
00370 
00371     printf("Adding provider '%s'\n", OPENSC_PKCS11_PROVIDER_LIBRARY);
00372         if ((rv = pkcs11h_addProvider(OPENSC_PKCS11_PROVIDER_LIBRARY, OPENSC_PKCS11_PROVIDER_LIBRARY, FALSE, PKCS11H_PRIVATEMODE_MASK_AUTO, PKCS11H_SLOTEVENT_METHOD_AUTO, 0, FALSE)) != CKR_OK) {
00373         printf("pkcs11h_addProvider failed: %s\n", pkcs11h_getMessage(rv));
00374         return -1;
00375     }
00376 
00377     return 0;
00378 #else
00379     return -1;
00380 #endif
00381 }
00382 
00383 int CryptoCardDeviceWatcher::retrieveCardCertificates(TQString readerName) {
00384 #if defined(WITH_PKCS)
00385     int ret = -1;
00386 
00387     CK_RV rv;
00388     pkcs11h_certificate_id_list_t issuers;
00389     pkcs11h_certificate_id_list_t certs;
00390 
00391     if (initializePkcs() < 0) {
00392         printf("Unable to initialize PKCS\n");
00393         return -1;
00394     }
00395 
00396     rv = pkcs11h_certificate_enumCertificateIds(PKCS11H_ENUM_METHOD_CACHE, NULL, PKCS11H_PROMPT_MASK_ALLOW_PIN_PROMPT, &issuers, &certs);
00397     if ((rv != CKR_OK) || (certs == NULL)) {
00398         printf("Cannot enumerate certificates: %s\n", pkcs11h_getMessage(rv));
00399         return -1;
00400     }
00401     printf("Successfully enumerated certificates\n");
00402 
00403     int i = 0;
00404     for (pkcs11h_certificate_id_list_t cert = certs; cert != NULL; cert = cert->next) {
00405         TQString label = cert->certificate_id->displayName;
00406         printf("Certificate %d name: '%s'\n", i, label.ascii());
00407 
00408         pkcs11h_certificate_t certificate;
00409         rv = pkcs11h_certificate_create(certs->certificate_id, NULL, PKCS11H_PROMPT_MASK_ALLOW_PIN_PROMPT, PKCS11H_PIN_CACHE_INFINITE, &certificate);
00410         if (rv != CKR_OK) {
00411             printf("Cannot read certificate: %s\n", pkcs11h_getMessage(rv));
00412             pkcs11h_certificate_freeCertificateId(certs->certificate_id);
00413             ret = -1;
00414             break;
00415         }
00416 
00417         pkcs11h_certificate_freeCertificateId(certs->certificate_id);
00418 
00419         pkcs11h_openssl_session_t openssl_session = NULL;
00420         if ((openssl_session = pkcs11h_openssl_createSession(certificate)) == NULL) {
00421             printf("Cannot initialize openssl session to retrieve cryptographic objects\n");
00422             pkcs11h_certificate_freeCertificate(certificate);
00423             ret = -1;
00424             break;
00425         }
00426         certificate = NULL; // the certificate object is managed by openssl_session
00427 
00428         X509* x509_local;
00429         x509_local = pkcs11h_openssl_session_getX509(openssl_session);
00430         if (x509_local) {
00431             printf("Successfully retrieved X509 certificate\n");
00432         }
00433         else {
00434             printf("Cannot get X509 object\n");
00435             ret = -1;
00436         }
00437 #if 0
00438         RSA* rsa_local;
00439         rsa_local = pkcs11h_openssl_session_getRSA(openssl_session);
00440         if (rsa_local) {
00441             printf("Successfully retrieved RSA public key\n");
00442         }
00443         else {
00444             printf("Cannot get RSA object\n");
00445             ret = -1;
00446         }
00447 #endif
00448 
00449         X509* x509_copy = X509_dup(x509_local);
00450         if (x509_copy) {
00451             cardDevice->m_cardCertificates.append(x509_copy);
00452         }
00453         else {
00454             printf("Unable to copy X509 certificate\n");
00455         }
00456 
00457         pkcs11h_openssl_freeSession(openssl_session);
00458         i++;
00459     }
00460 
00461     pkcs11h_certificate_freeCertificateIdList(issuers);
00462 
00463     return ret;
00464 #else
00465     return -1;
00466 #endif
00467 }
00468 
00469 void CryptoCardDeviceWatcher::deleteAllCertificatesFromCache() {
00470 #ifdef WITH_PKCS
00471     X509 *x509_cert;
00472 
00473     X509CertificatePtrListIterator it;
00474     for (it = cardDevice->m_cardCertificates.begin(); it != cardDevice->m_cardCertificates.end(); ++it) {
00475         x509_cert = *it;
00476         X509_free(x509_cert);
00477     }
00478 
00479     cardDevice->m_cardCertificates.clear();
00480 #endif
00481 }
00482 
00483 TDECryptographicCardDevice::TDECryptographicCardDevice(TDEGenericDeviceType::TDEGenericDeviceType dt, TQString dn) : TDEGenericDevice(dt, dn),
00484     m_watcherThread(NULL),
00485     m_watcherObject(NULL),
00486     m_cardPresent(false) {
00487 }
00488 
00489 TDECryptographicCardDevice::~TDECryptographicCardDevice() {
00490     enableCardMonitoring(false);
00491 }
00492 
00493 void TDECryptographicCardDevice::enableCardMonitoring(bool enable) {
00494 #ifdef WITH_PCSC
00495     if (enable) {
00496         if (m_watcherObject && m_watcherThread) {
00497             // Monitoring thread already active
00498             if ((cardPresent() == 1) && (cardX509Certificates().count() > 0)) {
00499                 // Card was already inserted and initialized
00500                 emit(certificateListAvailable(this));
00501             }
00502 
00503             // Abort!
00504             return;
00505         }
00506 
00507         m_watcherThread = new TQEventLoopThread();
00508         m_watcherObject = new CryptoCardDeviceWatcher();
00509 
00510         m_watcherObject->cardDevice = this;
00511         m_watcherObject->moveToThread(m_watcherThread);
00512         TQObject::connect(m_watcherObject, SIGNAL(statusChanged(TQString,TQString)), this, SLOT(cardStatusChanged(TQString,TQString)));
00513         TQObject::connect(m_watcherObject, SIGNAL(pinRequested(TQString)), this, SLOT(workerRequestedPin(TQString)));
00514         TQTimer::singleShot(0, m_watcherObject, SLOT(run()));
00515 
00516         m_watcherThread->start();
00517     }
00518     else {
00519         if (m_watcherObject) {
00520             m_watcherObject->requestTermination();
00521         }
00522         if (m_watcherThread) {
00523             m_watcherThread->wait();
00524             delete m_watcherThread;
00525             m_watcherThread = NULL;
00526         }
00527         if (m_watcherObject) {
00528             delete m_watcherObject;
00529             m_watcherObject = NULL;
00530         }
00531     }
00532 #endif
00533 }
00534 
00535 void TDECryptographicCardDevice::enablePINEntryCallbacks(bool enable) {
00536     if (m_watcherObject) {
00537         m_watcherObject->enablePINEntryCallbacks(enable);
00538     }
00539 }
00540 
00541 int TDECryptographicCardDevice::cardPresent() {
00542     if (m_watcherObject && m_watcherThread) {
00543         if (m_cardPresent)
00544             return 1;
00545         else
00546             return 0;
00547     }
00548     else {
00549         return -1;
00550     }
00551 }
00552 
00553 TQString TDECryptographicCardDevice::cardATR() {
00554     if (m_watcherObject && m_watcherThread) {
00555         if (m_cardPresent)
00556             return m_cardATR;
00557         else
00558             return TQString::null;
00559     }
00560     else {
00561         return TQString::null;
00562     }
00563 }
00564 
00565 X509CertificatePtrList TDECryptographicCardDevice::cardX509Certificates() {
00566     if (m_watcherObject && m_watcherThread) {
00567         if (m_cardPresent) {
00568             return m_cardCertificates;
00569         }
00570         else {
00571             return X509CertificatePtrList();
00572         }
00573     }
00574     else {
00575         return X509CertificatePtrList();
00576     }
00577 }
00578 
00579 void TDECryptographicCardDevice::cardStatusChanged(TQString status, TQString atr) {
00580     if (status == "INSERTED") {
00581         m_cardPresent = true;
00582         m_cardATR = atr;
00583         emit(cardInserted(this));
00584         if (m_cardCertificates.count() > 0) {
00585             emit(certificateListAvailable(this));
00586         }
00587     }
00588     else if (status == "REMOVED") {
00589         m_cardPresent = false;
00590         m_cardATR = atr;
00591         emit(cardRemoved(this));
00592     }
00593     else if (status == "PRESENT") {
00594         m_cardATR = atr;
00595         m_cardPresent = true;
00596         if (m_cardCertificates.count() > 0) {
00597             emit(certificateListAvailable(this));
00598         }
00599     }
00600 }
00601 
00602 void TDECryptographicCardDevice::setProvidedPin(TQString pin) {
00603     if (m_watcherObject) {
00604         m_watcherObject->setProvidedPin(pin);
00605     }
00606 }
00607 
00608 TQString TDECryptographicCardDevice::autoPIN() {
00609 #if defined(WITH_PKCS)
00610     TQString retString = TQString::null;
00611 
00612     // Use subjAltName field in card certificate to provide the card's PIN,
00613     // in order to support optional pin-less operation.
00614     // Parse the TDE autologin extension
00615     // Structure:
00616     // OID 1.3.6.1.4.1.40364.1.2.1
00617     //  SEQUENCE
00618     //      ASN1_CONSTRUCTED [index: 0] (field name: pin)
00619     //          GeneralString
00620 
00621     // Register custom OID type for TDE autopin data
00622     ASN1_OBJECT* tde_autopin_data_object = OBJ_txt2obj("1.3.6.1.4.1.40364.1.2.1", 0);
00623 
00624     int i;
00625     X509CertificatePtrListIterator it;
00626     for (it = m_cardCertificates.begin(); it != m_cardCertificates.end(); ++it) {
00627         X509* x509_cert = *it;
00628         GENERAL_NAMES* subjectAltNames = (GENERAL_NAMES*)X509_get_ext_d2i(x509_cert, NID_subject_alt_name, NULL, NULL);
00629         int altNameCount = sk_GENERAL_NAME_num(subjectAltNames);
00630         for (i=0; i < altNameCount; i++) {
00631             GENERAL_NAME* generalName = sk_GENERAL_NAME_value(subjectAltNames, i);
00632             if (generalName->type == GEN_OTHERNAME) {
00633                 OTHERNAME* otherName = generalName->d.otherName;
00634                 if (!OBJ_cmp(otherName->type_id, tde_autopin_data_object)) {
00635                     ASN1_TYPE* asnValue = otherName->value;
00636                     if (asnValue) {
00637                         // Found autopin structure
00638                         int index;
00639                         ASN1_TYPE* asnSeqValue = NULL;
00640                         ASN1_GENERALSTRING* asnGeneralString = NULL;
00641                         STACK_OF(ASN1_TYPE) *asnSeqValueStack = NULL;
00642                         long asn1SeqValueObjectLength;
00643                         int asn1SeqValueObjectTag;
00644                         int asn1SeqValueObjectClass;
00645                         int returnCode;
00646 
00647                         index = 0;  // Search for the PIN field
00648                         asnSeqValueStack = ASN1_seq_unpack_ASN1_TYPE(ASN1_STRING_data(asnValue->value.sequence), ASN1_STRING_length(asnValue->value.sequence), d2i_ASN1_TYPE, ASN1_TYPE_free);
00649                         asnSeqValue = sk_ASN1_TYPE_value(asnSeqValueStack, index);
00650                         if (asnSeqValue) {
00651                             if (asnSeqValue->value.octet_string->data[0] == ((V_ASN1_CONSTRUCTED | V_ASN1_CONTEXT_SPECIFIC) + index)) {
00652                                 const unsigned char* asn1SeqValueObjectData = asnSeqValue->value.sequence->data;
00653                                 returnCode = ASN1_get_object(&asn1SeqValueObjectData, &asn1SeqValueObjectLength, &asn1SeqValueObjectTag, &asn1SeqValueObjectClass, asnSeqValue->value.sequence->length);
00654                                 if (!(returnCode & 0x80)) {
00655                                     if (returnCode == (V_ASN1_CONSTRUCTED + index)) {
00656                                         if (d2i_ASN1_GENERALSTRING(&asnGeneralString, &asn1SeqValueObjectData, asn1SeqValueObjectLength) != NULL) {
00657                                             retString = TQString((const char *)ASN1_STRING_data(asnGeneralString));
00658                                         }
00659                                     }
00660                                 }
00661                             }
00662                         }
00663                     }
00664                 }
00665             }
00666         }
00667     }
00668 
00669     // Clean up
00670     OBJ_cleanup();
00671 
00672     return retString;
00673 #else
00674     return TQString::null;
00675 #endif
00676 }
00677 
00678 void TDECryptographicCardDevice::workerRequestedPin(TQString prompt) {
00679     emit(pinRequested(prompt, this));
00680 }
00681 
00682 int TDECryptographicCardDevice::decryptDataEncryptedWithCertPublicKey(TQByteArray &ciphertext, TQByteArray &plaintext, TQString *errstr) {
00683     TQValueList<TQByteArray> cipherTextList;
00684     TQValueList<TQByteArray> plainTextList;
00685     TQValueList<int> retCodeList;
00686 
00687     cipherTextList.append(ciphertext);
00688 
00689     this->decryptDataEncryptedWithCertPublicKey(cipherTextList, plainTextList, retCodeList, errstr);
00690 
00691     plaintext = plainTextList[0];
00692     return retCodeList[0];
00693 }
00694 
00695 int TDECryptographicCardDevice::decryptDataEncryptedWithCertPublicKey(TQValueList<TQByteArray> &cipherTextList, TQValueList<TQByteArray> &plainTextList, TQValueList<int> &retcodes, TQString *errstr) {
00696 #if defined(WITH_PKCS)
00697     int ret = -1;
00698 
00699     if (!m_watcherObject) {
00700         if (errstr) *errstr = i18n("Card watcher object not available");
00701         return -1;
00702     }
00703 
00704     CK_RV rv;
00705     pkcs11h_certificate_id_list_t issuers;
00706     pkcs11h_certificate_id_list_t certs;
00707 
00708     if (m_watcherObject->initializePkcs() < 0) {
00709         if (errstr) *errstr = i18n("Unable to initialize PKCS");
00710         return -1;
00711     }
00712 
00713     rv = pkcs11h_certificate_enumCertificateIds(PKCS11H_ENUM_METHOD_CACHE, NULL, PKCS11H_PROMPT_MASK_ALLOW_PIN_PROMPT, &issuers, &certs);
00714     if ((rv != CKR_OK) || (certs == NULL)) {
00715         if (errstr) *errstr = i18n("Cannot enumerate certificates: %1").arg(pkcs11h_getMessage(rv));
00716         return -1;
00717     }
00718 
00719     int i = 0;
00720     for (pkcs11h_certificate_id_list_t cert = certs; cert != NULL; cert = cert->next) {
00721         TQString label = cert->certificate_id->displayName;
00722 
00723         pkcs11h_certificate_t certificate;
00724         rv = pkcs11h_certificate_create(certs->certificate_id, NULL, PKCS11H_PROMPT_MASK_ALLOW_PIN_PROMPT, PKCS11H_PIN_CACHE_INFINITE, &certificate);
00725         if (rv != CKR_OK) {
00726             if (errstr) *errstr = i18n("Cannot read certificate: %1").arg(pkcs11h_getMessage(rv));
00727             pkcs11h_certificate_freeCertificateId(certs->certificate_id);
00728             ret = -1;
00729             break;
00730         }
00731 
00732         pkcs11h_certificate_freeCertificateId(certs->certificate_id);
00733 
00734         pkcs11h_openssl_session_t openssl_session = NULL;
00735         if ((openssl_session = pkcs11h_openssl_createSession(certificate)) == NULL) {
00736             if (errstr) *errstr = i18n("Cannot initialize openssl session to retrieve cryptographic objects");
00737             pkcs11h_certificate_freeCertificate(certificate);
00738             ret = -1;
00739             break;
00740         }
00741 
00742         // Get certificate data
00743         X509* x509_local;
00744         x509_local = pkcs11h_openssl_session_getX509(openssl_session);
00745         if (!x509_local) {
00746             if (errstr) *errstr = i18n("Cannot get X509 object");
00747             ret = -1;
00748         }
00749 
00750         // Extract public key from X509 certificate
00751         EVP_PKEY* x509_pubkey = NULL;
00752         RSA* rsa_pubkey = NULL;
00753         x509_pubkey = X509_get_pubkey(x509_local);
00754         if (x509_pubkey) {
00755             rsa_pubkey = EVP_PKEY_get1_RSA(x509_pubkey);
00756         }
00757 
00758         // Check PIN
00759         rv = pkcs11h_certificate_ensureKeyAccess(certificate);
00760         if (rv != CKR_OK) {
00761             if (rv == CKR_CANCEL) {
00762                 ret = -3;
00763                 break;
00764             }
00765             else if ((rv == CKR_PIN_INCORRECT) || (rv == CKR_USER_NOT_LOGGED_IN)) {
00766                 ret = -2;
00767                 break;
00768             }
00769             else {
00770                 ret = -2;
00771                 break;
00772             }
00773         }
00774 
00775         // We know the cached PIN is correct; disable any further login prompts
00776         m_watcherObject->retrySamePin(true);
00777 
00778         TQValueList<TQByteArray>::iterator it;
00779         TQValueList<TQByteArray>::iterator it2;
00780         TQValueList<int>::iterator it3;
00781         plainTextList.clear();
00782         retcodes.clear();
00783         for (it = cipherTextList.begin(); it != cipherTextList.end(); ++it) {
00784             plainTextList.append(TQByteArray());
00785             retcodes.append(-1);
00786         }
00787         for (it = cipherTextList.begin(), it2 = plainTextList.begin(), it3 = retcodes.begin(); it != cipherTextList.end(); ++it, ++it2, ++it3) {
00788             TQByteArray& ciphertext = *it;
00789             TQByteArray& plaintext = *it2;
00790             int& retcode = *it3;
00791 
00792             // Verify minimum size
00793             if (ciphertext.size() < 16) {
00794                 if (errstr) *errstr = i18n("Cannot decrypt: %1").arg(i18n("Ciphertext too small"));
00795                 ret = -2;
00796                 retcode = -2;
00797                 continue;
00798             }
00799 
00800             // Try to get RSA parameters and verify maximum size
00801             if (rsa_pubkey) {
00802                 unsigned int rsa_length = RSA_size(rsa_pubkey);
00803                 if (ciphertext.size() > rsa_length) {
00804                     if (errstr) *errstr = i18n("Cannot decrypt: %1").arg(i18n("Ciphertext too large"));
00805                     ret = -2;
00806                     retcode = -2;
00807                     continue;
00808                 }
00809             }
00810 
00811             size_t size = 0;
00812             // Determine output buffer size
00813             rv = pkcs11h_certificate_decryptAny(certificate, CKM_RSA_PKCS, (unsigned char*)ciphertext.data(), ciphertext.size(), NULL, &size);
00814             if (rv != CKR_OK) {
00815                 if (errstr) *errstr = i18n("Cannot determine decrypted message length: %1 (%2)").arg(pkcs11h_getMessage(rv)).arg(rv);
00816                 if (rv == CKR_CANCEL) {
00817                     ret = -3;
00818                     retcode = -3;
00819                     break;
00820                 }
00821                 else if ((rv == CKR_PIN_INCORRECT) || (rv == CKR_USER_NOT_LOGGED_IN)) {
00822                     ret = -2;
00823                     retcode = -2;
00824                     break;
00825                 }
00826                 else {
00827                     ret = -2;
00828                     retcode = -2;
00829                 }
00830             }
00831             else {
00832                 // Decrypt data
00833                 plaintext.resize(size);
00834                 rv = pkcs11h_certificate_decryptAny(certificate, CKM_RSA_PKCS, (unsigned char*)ciphertext.data(), ciphertext.size(), (unsigned char*)plaintext.data(), &size);
00835                 if (rv != CKR_OK) {
00836                     if (errstr) *errstr = i18n("Cannot decrypt: %1 (%2)").arg(pkcs11h_getMessage(rv)).arg(rv);
00837                     if (rv == CKR_CANCEL) {
00838                         ret = -3;
00839                         retcode = -3;
00840                         break;
00841                     }
00842                     else if ((rv == CKR_PIN_INCORRECT) || (rv == CKR_USER_NOT_LOGGED_IN)) {
00843                         ret = -2;
00844                         retcode = -2;
00845                         break;
00846                     }
00847                     else {
00848                         ret = -2;
00849                         retcode = -2;
00850                     }
00851                 }
00852                 else {
00853                     if (errstr) *errstr = TQString::null;
00854                     ret = 0;
00855                     retcode = 0;
00856                 }
00857             }
00858         }
00859 
00860         pkcs11h_openssl_freeSession(openssl_session);
00861 
00862         // Only interested in first certificate for now
00863         // FIXME
00864         // If cards with multiple certificates are used this should be modified to try decryption
00865         // using each certificate in turn...
00866         break;
00867 
00868         i++;
00869     }
00870     pkcs11h_certificate_freeCertificateIdList(issuers);
00871 
00872     // Restore normal login attempt method
00873     m_watcherObject->retrySamePin(false);
00874 
00875     return ret;
00876 #else
00877     return -1;
00878 #endif
00879 }
00880 
00881 int TDECryptographicCardDevice::createNewSecretRSAKeyFromCertificate(TQByteArray &plaintext, TQByteArray &ciphertext, X509* certificate) {
00882 #if defined(WITH_PKCS)
00883     unsigned int i;
00884     int retcode = -1;
00885 
00886     // Extract public key from X509 certificate
00887     EVP_PKEY* x509_pubkey = NULL;
00888     RSA* rsa_pubkey = NULL;
00889     x509_pubkey = X509_get_pubkey(certificate);
00890     if (x509_pubkey) {
00891         rsa_pubkey = EVP_PKEY_get1_RSA(x509_pubkey);
00892     }
00893 
00894     if (rsa_pubkey) {
00895         // Determine encryption parameters
00896         // NOTE
00897         // RSA_PKCS1_OAEP_PADDING is preferred but cannot be decoded from
00898         // the command line via openssl at this time of this writing.
00899         int rsa_padding_style = RSA_PKCS1_PADDING;
00900         unsigned int rsa_length = RSA_size(rsa_pubkey);
00901         unsigned int max_key_length = rsa_length - 41;
00902 
00903         // Create a new random key as the plaintext
00904         plaintext.resize(max_key_length);
00905         for (i=0; i < max_key_length; i++) {
00906             plaintext[i] = TDEApplication::random();
00907         }
00908 
00909         // Encrypt data
00910         ciphertext.resize(rsa_length);
00911         if (RSA_public_encrypt(plaintext.size(), (unsigned char *)plaintext.data(), (unsigned char *)ciphertext.data(), rsa_pubkey, rsa_padding_style) < 0) {
00912             retcode = -2;
00913         }
00914 
00915         // Success!
00916         retcode = 0;
00917     }
00918 
00919     // Clean up
00920     if (rsa_pubkey) {
00921         RSA_free(rsa_pubkey);
00922     }
00923     if (x509_pubkey) {
00924         EVP_PKEY_free(x509_pubkey);
00925     }
00926 
00927     return retcode;
00928 #else
00929     return -1;
00930 #endif
00931 }
00932 
00933 TQString TDECryptographicCardDevice::pkcsProviderLibrary() {
00934 #if defined(WITH_PKCS)
00935     return OPENSC_PKCS11_PROVIDER_LIBRARY;
00936 #else
00937     return TQString::null;
00938 #endif
00939 }
00940 
00941 #include "tdecryptographiccarddevice.moc"
00942 #include "tdecryptographiccarddevice_private.moc"

tdecore

Skip menu "tdecore"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

tdecore

Skip menu "tdecore"
  • arts
  • dcop
  • dnssd
  • interfaces
  •   kspeech
  •     interface
  •     library
  •   tdetexteditor
  • kate
  • kded
  • kdoctools
  • kimgio
  • kjs
  • libtdemid
  • libtdescreensaver
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdeioslave
  •   http
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for tdecore by doxygen 1.7.6.1
This website is maintained by Timothy Pearson.