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"
Trinity API Reference