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

tdecore

  • tdecore
  • tdehw
tdecryptographiccarddevice.cpp
1/* This file is part of the TDE libraries
2 Copyright (C) 2015 Timothy Pearson <kb9vqf@pearsoncomputing.net>
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License version 2 as published by the Free Software Foundation.
7
8 This library is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 Library General Public License for more details.
12
13 You should have received a copy of the GNU Library General Public License
14 along with this library; see the file COPYING.LIB. If not, write to
15 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
16 Boston, MA 02110-1301, USA.
17*/
18
19#ifdef WITH_PKCS
20 #define _TDECRYPTOGRAPHICCARDDEVICE_INTERNAL 1
21#endif
22
23#include "tdecryptographiccarddevice_private.h"
24#include "tdecryptographiccarddevice.h"
25
26#include <tqpixmap.h>
27#include <tqtimer.h>
28#include <tqthread.h>
29#include <tqeventloop.h>
30#include <tqapplication.h>
31
32#include "tdeglobal.h"
33#include "tdelocale.h"
34#include "tdeapplication.h"
35
36#include "tdehardwaredevices.h"
37
38#include "config.h"
39
40// 1 second
41#define PCSC_POLL_TIMEOUT_S 1000
42
43#define CARD_MAX_LOGIN_RETRY_COUNT 3
44
45/* FIXME
46 * This is incomplete
47 */
48#ifdef WITH_PCSC
49static TQString pcsc_error_code_to_string(long errcode) {
50 if (errcode == SCARD_W_UNPOWERED_CARD) {
51 return i18n("card not powered on");
52 }
53 else if (errcode == SCARD_E_PROTO_MISMATCH) {
54 return i18n("protocol mismatch");
55 }
56 else {
57 return TQString::null;
58 }
59}
60#endif
61
62CryptoCardDeviceWatcher::CryptoCardDeviceWatcher() {
63#ifdef WITH_PCSC
64 m_readerStates = NULL;
65#endif
66 m_cardPINPromptDone = true;
67 m_pinCallbacksEnabled = false;
68 m_cardReusePIN = false;
69}
70
71CryptoCardDeviceWatcher::~CryptoCardDeviceWatcher() {
72#ifdef WITH_PCSC
73 free(m_readerStates);
74#endif
75}
76
77void CryptoCardDeviceWatcher::run() {
78#ifdef WITH_PCSC
79 bool first_loop;
80 unsigned int i;
81 long ret;
82
83 DWORD dword_readers;
84 LPSTR lpstring_readers = NULL;
85
86 TQStringList readers;
87
88 first_loop = true;
89 m_terminationRequested = false;
90
91 TQEventLoop* eventLoop = TQApplication::eventLoop();
92 if (!eventLoop) return;
93
94 ret = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &m_cardContext);
95 if (ret != SCARD_S_SUCCESS) {
96 printf("TDECryptographicCardDevice: PCSC SCardEstablishContext cannot connect to resource manager (%lX)", ret);
97 eventLoop->exit(0);
98 return;
99 }
100
101 ret = SCardListReaders(m_cardContext, NULL, NULL, &dword_readers);
102 if (ret == SCARD_S_SUCCESS) {
103 lpstring_readers = (LPSTR)malloc(sizeof(char)*dword_readers);
104 if (lpstring_readers == NULL) {
105 printf("TDECryptographicCardDevice: insufficient memory, aborting");
106 eventLoop->exit(0);
107 return;
108 }
109
110 ret = SCardListReaders(m_cardContext, NULL, lpstring_readers, &dword_readers);
111 if (ret == SCARD_S_SUCCESS) {
112 /* Extract reader names from the null separated string */
113 char *ptr = lpstring_readers;
114 while (*ptr != '\0') {
115 readers.append(ptr);
116 ptr += strlen(ptr)+1;
117 }
118
119 free(lpstring_readers);
120
121 m_readerStates = (SCARD_READERSTATE*)calloc(readers.count(), sizeof(*m_readerStates));
122 if (m_readerStates == NULL) {
123 printf("TDECryptographicCardDevice: insufficient memory, aborting");
124 free(lpstring_readers);
125 eventLoop->exit(0);
126 return;
127 }
128
129 for (i=0; i<readers.count(); i++) {
130 m_readerStates[i].szReader = strdup(readers[i].ascii());
131 m_readerStates[i].dwCurrentState = SCARD_STATE_UNAWARE;
132 }
133
134 ret = SCardGetStatusChange(m_cardContext, PCSC_POLL_TIMEOUT_S, m_readerStates, readers.count());
135 while ((ret == SCARD_S_SUCCESS) || (ret == SCARD_E_TIMEOUT)) {
136 if (m_terminationRequested) {
137 for (i=0; i<readers.count(); i++) {
138 free((char*)m_readerStates[i].szReader);
139 m_readerStates[i].szReader = NULL;
140 }
141 eventLoop->exit(0);
142 return;
143 }
144
145 for (i=0; i<readers.count(); i++) {
146 /* FIXME
147 * Find a better / more reliable way to match the card low level device to the PCSC name
148 */
149 SCARDHANDLE hCard = 0;
150 DWORD dwActiveProtocol = 0;
151 DWORD cByte = 0;
152 TQString reader_vendor_name;
153 TQString reader_interface_type;
154
155 ret = SCardConnect(m_cardContext, readers[i].ascii(), SCARD_SHARE_DIRECT, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &hCard, &dwActiveProtocol);
156 if (ret == SCARD_S_SUCCESS) {
157 ret = SCardGetAttrib(hCard, SCARD_ATTR_VENDOR_NAME, NULL, &cByte);
158 if (ret == SCARD_S_SUCCESS) {
159 char* data = new char[cByte];
160 ret = SCardGetAttrib(hCard, SCARD_ATTR_VENDOR_NAME, (LPBYTE)data, &cByte);
161 reader_vendor_name = data;
162 delete [] data;
163 }
164 ret = SCardGetAttrib(hCard, SCARD_ATTR_VENDOR_IFD_TYPE, NULL, &cByte);
165 if (ret == SCARD_S_SUCCESS) {
166 char* data = new char[cByte];
167 ret = SCardGetAttrib(hCard, SCARD_ATTR_VENDOR_IFD_TYPE, (LPBYTE)data, &cByte);
168 reader_interface_type = data;
169 delete [] data;
170 }
171 SCardDisconnect(hCard, SCARD_LEAVE_CARD);
172 }
173
174 /* FIXME
175 * If only one reader was detected by PCSC, assume it corresponds to the current device node.
176 * This is fragile, but avoids corner cases with common systems failing to work due to
177 * mismatched udev / PCSC card reader vendor names...
178 */
179 if (readers.count() > 1) {
180 if (!readers[i].contains(cardDevice->friendlyName())) {
181 if (!cardDevice->friendlyName().contains(reader_vendor_name) ||
182 ((reader_interface_type != "") && !cardDevice->friendlyName().contains(reader_vendor_name))) {
183 continue;
184 }
185 }
186 }
187
188 if (first_loop) {
189 if (m_readerStates[i].dwEventState & SCARD_STATE_PRESENT) {
190 // sleep(1); // Allow the card to settle
191 TQString atr = getCardATR(readers[i]);
192 retrieveCardCertificates(readers[i]);
193 statusChanged("PRESENT", atr);
194 }
195 else {
196 deleteAllCertificatesFromCache();
197 }
198 first_loop = false;
199 }
200 if (m_readerStates[i].dwEventState & SCARD_STATE_CHANGED) {
201 if ((m_readerStates[i].dwCurrentState & SCARD_STATE_PRESENT)
202 && (m_readerStates[i].dwEventState & SCARD_STATE_EMPTY)) {
203 deleteAllCertificatesFromCache();
204 statusChanged("REMOVED", TQString::null);
205 }
206 else if ((m_readerStates[i].dwCurrentState & SCARD_STATE_EMPTY)
207 && (m_readerStates[i].dwEventState & SCARD_STATE_PRESENT)) {
208 // sleep(1); // Allow the card to settle
209 TQString atr = getCardATR(readers[i]);
210 retrieveCardCertificates(readers[i]);
211 statusChanged("INSERTED", atr);
212 }
213 m_readerStates[i].dwCurrentState = m_readerStates[i].dwEventState;
214 }
215 else {
216 continue;
217 }
218 }
219 ret = SCardGetStatusChange(m_cardContext, PCSC_POLL_TIMEOUT_S, m_readerStates, readers.count());
220 }
221 }
222 }
223
224 eventLoop->exit(0);
225#endif
226}
227
228void CryptoCardDeviceWatcher::requestTermination() {
229 m_terminationRequested = true;
230}
231
232void CryptoCardDeviceWatcher::setProvidedPin(TQString pin) {
233 m_cardPIN = pin;
234 m_cardPINPromptDone = true;
235}
236
237void CryptoCardDeviceWatcher::retrySamePin(bool enable) {
238 m_cardReusePIN = enable;
239 if (!enable) {
240 m_cardPIN = "SHREDDINGTHEPINISMOSTSECURE";
241 m_cardPIN = TQString::null;
242 }
243}
244
245TQString CryptoCardDeviceWatcher::getCardATR(TQString readerName) {
246#ifdef WITH_PCSC
247 unsigned int i;
248 long ret;
249 TQString atr_formatted;
250 SCARDHANDLE hCard = 0;
251 DWORD dwActiveProtocol = 0;
252 DWORD cByte = 0;
253
254 ret = SCardConnect(m_cardContext, readerName.ascii(), SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &hCard, &dwActiveProtocol);
255 if (ret == SCARD_S_SUCCESS) {
256 ret = SCardGetAttrib(hCard, SCARD_ATTR_ATR_STRING, NULL, &cByte);
257 if (ret == SCARD_S_SUCCESS) {
258 char* data = new char[cByte];
259 ret = SCardGetAttrib(hCard, SCARD_ATTR_ATR_STRING, (LPBYTE)data, &cByte);
260 atr_formatted = TQString::null;
261 for (i=0; i<cByte; i++) {
262 TQString formatted;
263 formatted.sprintf("%02x ", ((uint8_t)(*(data+i))));
264 atr_formatted.append(formatted.upper());
265 }
266 atr_formatted = atr_formatted.stripWhiteSpace();
267 delete [] data;
268 SCardDisconnect(hCard, SCARD_LEAVE_CARD);
269 }
270 }
271 else {
272 TQString errstring = pcsc_error_code_to_string(ret);
273 if (errstring != "") {
274 atr_formatted = i18n("Unknown (%1)").arg(errstring);
275 }
276 else {
277 atr_formatted = TQString("CARD_CONNECT_FAIL (%1)").arg(ret, 0, 16);
278 }
279 }
280
281 return atr_formatted;
282#else
283 return TQString::null;
284#endif
285}
286
287void CryptoCardDeviceWatcher::enablePINEntryCallbacks(bool enable) {
288 m_pinCallbacksEnabled = enable;
289}
290
291TQString CryptoCardDeviceWatcher::doPinRequest(TQString prompt) {
292 if (!m_pinCallbacksEnabled) {
293 return TQString::null;
294 }
295
296 if (m_cardReusePIN) {
297 return m_cardPIN;
298 }
299
300 m_cardPINPromptDone = false;
301 emit(pinRequested(prompt));
302 while (!m_cardPINPromptDone) {
303 usleep(100);
304 }
305
306 if (m_cardPIN.length() > 0) {
307 return m_cardPIN;
308 }
309 else {
310 return TQString::null;
311 }
312}
313
314#ifdef WITH_PKCS
315static void pkcs_log_hook(IN void * const global_data, IN unsigned flags, IN const char * const format, IN va_list args) {
316 vprintf(format, args);
317 printf("\n");
318}
319
320static 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) {
321 CryptoCardDeviceWatcher* watcher = (CryptoCardDeviceWatcher*)global_data;
322
323 TQString providedPin = watcher->doPinRequest(i18n("Please enter the PIN for '%1'").arg(token->display));
324 if (providedPin.length() > 0) {
325 snprintf(pin, pin_max, "%s", providedPin.ascii());
326
327 // Success
328 return 1;
329 }
330 else {
331 // Abort
332 return 0;
333 }
334}
335#endif
336
337int CryptoCardDeviceWatcher::initializePkcs() {
338#if defined(WITH_PKCS)
339 CK_RV rv;
340 printf("Initializing pkcs11-helper\n");
341 if ((rv = pkcs11h_initialize()) != CKR_OK) {
342 printf("pkcs11h_initialize failed: %s\n", pkcs11h_getMessage(rv));
343 return -1;
344 }
345
346 printf("Registering pkcs11-helper hooks\n");
347 if ((rv = pkcs11h_setLogHook(pkcs_log_hook, this)) != CKR_OK) {
348 printf("pkcs11h_setLogHook failed: %s\n", pkcs11h_getMessage(rv));
349 return -1;
350 }
351 pkcs11h_setLogLevel(PKCS11H_LOG_WARN);
352 // pkcs11h_setLogLevel(PKCS11H_LOG_DEBUG2);
353
354#if 0
355 if ((rv = pkcs11h_setTokenPromptHook(_pkcs11h_hooks_token_prompt, NULL)) != CKR_OK) {
356 printf("pkcs11h_setTokenPromptHook failed: %s\n", pkcs11h_getMessage(rv));
357 return -1;
358 }
359#endif
360
361 if ((rv = pkcs11h_setMaxLoginRetries(CARD_MAX_LOGIN_RETRY_COUNT)) != CKR_OK) {
362 printf("pkcs11h_setMaxLoginRetries failed: %s\n", pkcs11h_getMessage(rv));
363 return -1;
364 }
365
366 if ((rv = pkcs11h_setPINPromptHook(pkcs_pin_hook, this)) != CKR_OK) {
367 printf("pkcs11h_setPINPromptHook failed: %s\n", pkcs11h_getMessage(rv));
368 return -1;
369 }
370
371 printf("Adding provider '%s'\n", OPENSC_PKCS11_PROVIDER_LIBRARY);
372 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) {
373 printf("pkcs11h_addProvider failed: %s\n", pkcs11h_getMessage(rv));
374 return -1;
375 }
376
377 return 0;
378#else
379 return -1;
380#endif
381}
382
383int CryptoCardDeviceWatcher::retrieveCardCertificates(TQString readerName) {
384#if defined(WITH_PKCS)
385 int ret = -1;
386
387 CK_RV rv;
388 pkcs11h_certificate_id_list_t issuers;
389 pkcs11h_certificate_id_list_t certs;
390
391 if (initializePkcs() < 0) {
392 printf("Unable to initialize PKCS\n");
393 return -1;
394 }
395
396 rv = pkcs11h_certificate_enumCertificateIds(PKCS11H_ENUM_METHOD_CACHE, NULL, PKCS11H_PROMPT_MASK_ALLOW_PIN_PROMPT, &issuers, &certs);
397 if ((rv != CKR_OK) || (certs == NULL)) {
398 printf("Cannot enumerate certificates: %s\n", pkcs11h_getMessage(rv));
399 return -1;
400 }
401 printf("Successfully enumerated certificates\n");
402
403 int i = 0;
404 for (pkcs11h_certificate_id_list_t cert = certs; cert != NULL; cert = cert->next) {
405 TQString label = cert->certificate_id->displayName;
406 printf("Certificate %d name: '%s'\n", i, label.ascii());
407
408 pkcs11h_certificate_t certificate;
409 rv = pkcs11h_certificate_create(certs->certificate_id, NULL, PKCS11H_PROMPT_MASK_ALLOW_PIN_PROMPT, PKCS11H_PIN_CACHE_INFINITE, &certificate);
410 if (rv != CKR_OK) {
411 printf("Cannot read certificate: %s\n", pkcs11h_getMessage(rv));
412 pkcs11h_certificate_freeCertificateId(certs->certificate_id);
413 ret = -1;
414 break;
415 }
416
417 pkcs11h_certificate_freeCertificateId(certs->certificate_id);
418
419 pkcs11h_openssl_session_t openssl_session = NULL;
420 if ((openssl_session = pkcs11h_openssl_createSession(certificate)) == NULL) {
421 printf("Cannot initialize openssl session to retrieve cryptographic objects\n");
422 pkcs11h_certificate_freeCertificate(certificate);
423 ret = -1;
424 break;
425 }
426 certificate = NULL; // the certificate object is managed by openssl_session
427
428 X509* x509_local;
429 x509_local = pkcs11h_openssl_session_getX509(openssl_session);
430 if (x509_local) {
431 printf("Successfully retrieved X509 certificate\n");
432 }
433 else {
434 printf("Cannot get X509 object\n");
435 ret = -1;
436 }
437#if 0
438 RSA* rsa_local;
439 rsa_local = pkcs11h_openssl_session_getRSA(openssl_session);
440 if (rsa_local) {
441 printf("Successfully retrieved RSA public key\n");
442 }
443 else {
444 printf("Cannot get RSA object\n");
445 ret = -1;
446 }
447#endif
448
449 X509* x509_copy = X509_dup(x509_local);
450 if (x509_copy) {
451 cardDevice->m_cardCertificates.append(x509_copy);
452 }
453 else {
454 printf("Unable to copy X509 certificate\n");
455 }
456
457 pkcs11h_openssl_freeSession(openssl_session);
458 i++;
459 }
460
461 pkcs11h_certificate_freeCertificateIdList(issuers);
462
463 return ret;
464#else
465 return -1;
466#endif
467}
468
469void CryptoCardDeviceWatcher::deleteAllCertificatesFromCache() {
470#ifdef WITH_PKCS
471 X509 *x509_cert;
472
473 X509CertificatePtrListIterator it;
474 for (it = cardDevice->m_cardCertificates.begin(); it != cardDevice->m_cardCertificates.end(); ++it) {
475 x509_cert = *it;
476 X509_free(x509_cert);
477 }
478
479 cardDevice->m_cardCertificates.clear();
480#endif
481}
482
483TDECryptographicCardDevice::TDECryptographicCardDevice(TDEGenericDeviceType::TDEGenericDeviceType dt, TQString dn) : TDEGenericDevice(dt, dn),
484 m_watcherThread(NULL),
485 m_watcherObject(NULL),
486 m_cardPresent(false) {
487}
488
489TDECryptographicCardDevice::~TDECryptographicCardDevice() {
490 enableCardMonitoring(false);
491}
492
493void TDECryptographicCardDevice::enableCardMonitoring(bool enable) {
494#ifdef WITH_PCSC
495 if (enable) {
496 if (m_watcherObject && m_watcherThread) {
497 // Monitoring thread already active
498 if ((cardPresent() == 1) && (cardX509Certificates().count() > 0)) {
499 // Card was already inserted and initialized
500 emit(certificateListAvailable(this));
501 }
502
503 // Abort!
504 return;
505 }
506
507 m_watcherThread = new TQEventLoopThread();
508 m_watcherObject = new CryptoCardDeviceWatcher();
509
510 m_watcherObject->cardDevice = this;
511 m_watcherObject->moveToThread(m_watcherThread);
512 TQObject::connect(m_watcherObject, TQ_SIGNAL(statusChanged(TQString,TQString)), this, TQ_SLOT(cardStatusChanged(TQString,TQString)));
513 TQObject::connect(m_watcherObject, TQ_SIGNAL(pinRequested(TQString)), this, TQ_SLOT(workerRequestedPin(TQString)));
514 TQTimer::singleShot(0, m_watcherObject, TQ_SLOT(run()));
515
516 m_watcherThread->start();
517 }
518 else {
519 if (m_watcherObject) {
520 m_watcherObject->requestTermination();
521 }
522 if (m_watcherThread) {
523 m_watcherThread->wait();
524 delete m_watcherThread;
525 m_watcherThread = NULL;
526 }
527 if (m_watcherObject) {
528 delete m_watcherObject;
529 m_watcherObject = NULL;
530 }
531 }
532#endif
533}
534
535void TDECryptographicCardDevice::enablePINEntryCallbacks(bool enable) {
536 if (m_watcherObject) {
537 m_watcherObject->enablePINEntryCallbacks(enable);
538 }
539}
540
541int TDECryptographicCardDevice::cardPresent() {
542 if (m_watcherObject && m_watcherThread) {
543 if (m_cardPresent)
544 return 1;
545 else
546 return 0;
547 }
548 else {
549 return -1;
550 }
551}
552
553TQString TDECryptographicCardDevice::cardATR() {
554 if (m_watcherObject && m_watcherThread) {
555 if (m_cardPresent)
556 return m_cardATR;
557 else
558 return TQString::null;
559 }
560 else {
561 return TQString::null;
562 }
563}
564
565X509CertificatePtrList TDECryptographicCardDevice::cardX509Certificates() {
566 if (m_watcherObject && m_watcherThread) {
567 if (m_cardPresent) {
568 return m_cardCertificates;
569 }
570 else {
571 return X509CertificatePtrList();
572 }
573 }
574 else {
575 return X509CertificatePtrList();
576 }
577}
578
579void TDECryptographicCardDevice::cardStatusChanged(TQString status, TQString atr) {
580 if (status == "INSERTED") {
581 m_cardPresent = true;
582 m_cardATR = atr;
583 emit(cardInserted(this));
584 if (m_cardCertificates.count() > 0) {
585 emit(certificateListAvailable(this));
586 }
587 }
588 else if (status == "REMOVED") {
589 m_cardPresent = false;
590 m_cardATR = atr;
591 emit(cardRemoved(this));
592 }
593 else if (status == "PRESENT") {
594 m_cardATR = atr;
595 m_cardPresent = true;
596 if (m_cardCertificates.count() > 0) {
597 emit(certificateListAvailable(this));
598 }
599 }
600}
601
602void TDECryptographicCardDevice::setProvidedPin(TQString pin) {
603 if (m_watcherObject) {
604 m_watcherObject->setProvidedPin(pin);
605 }
606}
607
608TQString TDECryptographicCardDevice::autoPIN() {
609#if defined(WITH_PKCS)
610 TQString retString = TQString::null;
611
612 // Use subjAltName field in card certificate to provide the card's PIN,
613 // in order to support optional pin-less operation.
614 // Parse the TDE autologin extension
615 // Structure:
616 // OID 1.3.6.1.4.1.40364.1.2.1
617 // SEQUENCE
618 // ASN1_CONSTRUCTED [index: 0] (field name: pin)
619 // GeneralString
620
621 // Register custom OID type for TDE autopin data
622 ASN1_OBJECT* tde_autopin_data_object = OBJ_txt2obj("1.3.6.1.4.1.40364.1.2.1", 0);
623
624 int i;
625 X509CertificatePtrListIterator it;
626 for (it = m_cardCertificates.begin(); it != m_cardCertificates.end(); ++it) {
627 X509* x509_cert = *it;
628 GENERAL_NAMES* subjectAltNames = (GENERAL_NAMES*)X509_get_ext_d2i(x509_cert, NID_subject_alt_name, NULL, NULL);
629 int altNameCount = sk_GENERAL_NAME_num(subjectAltNames);
630 for (i=0; i < altNameCount; i++) {
631 GENERAL_NAME* generalName = sk_GENERAL_NAME_value(subjectAltNames, i);
632 if (generalName->type == GEN_OTHERNAME) {
633 OTHERNAME* otherName = generalName->d.otherName;
634 if (!OBJ_cmp(otherName->type_id, tde_autopin_data_object)) {
635 ASN1_TYPE* asnValue = otherName->value;
636 if (asnValue) {
637 // Found autopin structure
638 ASN1_TYPE* asnSeqValue = NULL;
639 ASN1_GENERALSTRING* asnGeneralString = NULL;
640 STACK_OF(ASN1_TYPE) *asnSeqValueStack = NULL;
641 long asn1SeqValueObjectLength;
642 int asn1SeqValueObjectTag;
643 int asn1SeqValueObjectClass;
644 int returnCode;
645 int index = 0; // Search for the PIN field
646
647#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
648 const uint8_t* asnSeqValueString = ASN1_STRING_get0_data(asnValue->value.sequence);
649 asnSeqValueStack = d2i_ASN1_SEQUENCE_ANY(NULL, &asnSeqValueString, ASN1_STRING_length(asnValue->value.sequence));
650#else
651 uint8_t* asnSeqValueString = ASN1_STRING_data(asnValue->value.sequence);
652 asnSeqValueStack = ASN1_seq_unpack_ASN1_TYPE(asnSeqValueString, ASN1_STRING_length(asnValue->value.sequence), d2i_ASN1_TYPE, ASN1_TYPE_free);
653#endif
654 asnSeqValue = sk_ASN1_TYPE_value(asnSeqValueStack, index);
655 if (asnSeqValue) {
656 if (asnSeqValue->value.octet_string->data[0] == ((V_ASN1_CONSTRUCTED | V_ASN1_CONTEXT_SPECIFIC) + index)) {
657 const unsigned char* asn1SeqValueObjectData = asnSeqValue->value.sequence->data;
658 returnCode = ASN1_get_object(&asn1SeqValueObjectData, &asn1SeqValueObjectLength, &asn1SeqValueObjectTag, &asn1SeqValueObjectClass, asnSeqValue->value.sequence->length);
659 if (!(returnCode & 0x80)) {
660 if (returnCode == (V_ASN1_CONSTRUCTED + index)) {
661 if (d2i_ASN1_GENERALSTRING(&asnGeneralString, &asn1SeqValueObjectData, asn1SeqValueObjectLength) != NULL) {
662#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
663 retString = TQString((const char *)ASN1_STRING_get0_data(asnGeneralString));
664#else
665 retString = TQString((const char *)ASN1_STRING_data(asnGeneralString));
666#endif
667 }
668 }
669 }
670 }
671 }
672#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
673 sk_ASN1_TYPE_pop_free(asnSeqValueStack, ASN1_TYPE_free);
674#endif
675 }
676 }
677 }
678 }
679 }
680
681 // Clean up
682 OBJ_cleanup();
683
684 return retString;
685#else
686 return TQString::null;
687#endif
688}
689
690void TDECryptographicCardDevice::workerRequestedPin(TQString prompt) {
691 emit(pinRequested(prompt, this));
692}
693
694int TDECryptographicCardDevice::decryptDataEncryptedWithCertPublicKey(TQByteArray &ciphertext, TQByteArray &plaintext, TQString *errstr) {
695 TQValueList<TQByteArray> cipherTextList;
696 TQValueList<TQByteArray> plainTextList;
697 TQValueList<int> retCodeList;
698
699 cipherTextList.append(ciphertext);
700
701 this->decryptDataEncryptedWithCertPublicKey(cipherTextList, plainTextList, retCodeList, errstr);
702
703 plaintext = plainTextList[0];
704 return retCodeList[0];
705}
706
707int TDECryptographicCardDevice::decryptDataEncryptedWithCertPublicKey(TQValueList<TQByteArray> &cipherTextList, TQValueList<TQByteArray> &plainTextList, TQValueList<int> &retcodes, TQString *errstr) {
708#if defined(WITH_PKCS)
709 int ret = -1;
710
711 if (!m_watcherObject) {
712 if (errstr) *errstr = i18n("Card watcher object not available");
713 return -1;
714 }
715
716 CK_RV rv;
717 pkcs11h_certificate_id_list_t issuers;
718 pkcs11h_certificate_id_list_t certs;
719
720 if (m_watcherObject->initializePkcs() < 0) {
721 if (errstr) *errstr = i18n("Unable to initialize PKCS");
722 return -1;
723 }
724
725 rv = pkcs11h_certificate_enumCertificateIds(PKCS11H_ENUM_METHOD_CACHE, NULL, PKCS11H_PROMPT_MASK_ALLOW_PIN_PROMPT, &issuers, &certs);
726 if ((rv != CKR_OK) || (certs == NULL)) {
727 if (errstr) *errstr = i18n("Cannot enumerate certificates: %1").arg(pkcs11h_getMessage(rv));
728 return -1;
729 }
730
731 int i = 0;
732 for (pkcs11h_certificate_id_list_t cert = certs; cert != NULL; cert = cert->next) {
733 TQString label = cert->certificate_id->displayName;
734
735 pkcs11h_certificate_t certificate;
736 rv = pkcs11h_certificate_create(certs->certificate_id, NULL, PKCS11H_PROMPT_MASK_ALLOW_PIN_PROMPT, PKCS11H_PIN_CACHE_INFINITE, &certificate);
737 if (rv != CKR_OK) {
738 if (errstr) *errstr = i18n("Cannot read certificate: %1").arg(pkcs11h_getMessage(rv));
739 pkcs11h_certificate_freeCertificateId(certs->certificate_id);
740 ret = -1;
741 break;
742 }
743
744 pkcs11h_certificate_freeCertificateId(certs->certificate_id);
745
746 pkcs11h_openssl_session_t openssl_session = NULL;
747 if ((openssl_session = pkcs11h_openssl_createSession(certificate)) == NULL) {
748 if (errstr) *errstr = i18n("Cannot initialize openssl session to retrieve cryptographic objects");
749 pkcs11h_certificate_freeCertificate(certificate);
750 ret = -1;
751 break;
752 }
753
754 // Get certificate data
755 X509* x509_local;
756 x509_local = pkcs11h_openssl_session_getX509(openssl_session);
757 if (!x509_local) {
758 if (errstr) *errstr = i18n("Cannot get X509 object");
759 ret = -1;
760 }
761
762 // Extract public key from X509 certificate
763 EVP_PKEY* x509_pubkey = NULL;
764 RSA* rsa_pubkey = NULL;
765 x509_pubkey = X509_get_pubkey(x509_local);
766 if (x509_pubkey) {
767 rsa_pubkey = EVP_PKEY_get1_RSA(x509_pubkey);
768 }
769
770 // Check PIN
771 rv = pkcs11h_certificate_ensureKeyAccess(certificate);
772 if (rv != CKR_OK) {
773 if (rv == CKR_CANCEL) {
774 ret = -3;
775 break;
776 }
777 else if ((rv == CKR_PIN_INCORRECT) || (rv == CKR_USER_NOT_LOGGED_IN)) {
778 ret = -2;
779 break;
780 }
781 else {
782 ret = -2;
783 break;
784 }
785 }
786
787 // We know the cached PIN is correct; disable any further login prompts
788 m_watcherObject->retrySamePin(true);
789
790 TQValueList<TQByteArray>::iterator it;
791 TQValueList<TQByteArray>::iterator it2;
792 TQValueList<int>::iterator it3;
793 plainTextList.clear();
794 retcodes.clear();
795 for (it = cipherTextList.begin(); it != cipherTextList.end(); ++it) {
796 plainTextList.append(TQByteArray());
797 retcodes.append(-1);
798 }
799 for (it = cipherTextList.begin(), it2 = plainTextList.begin(), it3 = retcodes.begin(); it != cipherTextList.end(); ++it, ++it2, ++it3) {
800 TQByteArray& ciphertext = *it;
801 TQByteArray& plaintext = *it2;
802 int& retcode = *it3;
803
804 // Verify minimum size
805 if (ciphertext.size() < 16) {
806 if (errstr) *errstr = i18n("Cannot decrypt: %1").arg(i18n("Ciphertext too small"));
807 ret = -2;
808 retcode = -2;
809 continue;
810 }
811
812 // Try to get RSA parameters and verify maximum size
813 if (rsa_pubkey) {
814 unsigned int rsa_length = RSA_size(rsa_pubkey);
815 if (ciphertext.size() > rsa_length) {
816 if (errstr) *errstr = i18n("Cannot decrypt: %1").arg(i18n("Ciphertext too large"));
817 ret = -2;
818 retcode = -2;
819 continue;
820 }
821 }
822
823 size_t size = 0;
824 // Determine output buffer size
825 rv = pkcs11h_certificate_decryptAny(certificate, CKM_RSA_PKCS, (unsigned char*)ciphertext.data(), ciphertext.size(), NULL, &size);
826 if (rv != CKR_OK) {
827 if (errstr) *errstr = i18n("Cannot determine decrypted message length: %1 (%2)").arg(pkcs11h_getMessage(rv)).arg(rv);
828 if (rv == CKR_CANCEL) {
829 ret = -3;
830 retcode = -3;
831 break;
832 }
833 else if ((rv == CKR_PIN_INCORRECT) || (rv == CKR_USER_NOT_LOGGED_IN)) {
834 ret = -2;
835 retcode = -2;
836 break;
837 }
838 else {
839 ret = -2;
840 retcode = -2;
841 }
842 }
843 else {
844 // Decrypt data
845 plaintext.resize(size);
846 rv = pkcs11h_certificate_decryptAny(certificate, CKM_RSA_PKCS, (unsigned char*)ciphertext.data(), ciphertext.size(), (unsigned char*)plaintext.data(), &size);
847 if (rv != CKR_OK) {
848 if (errstr) *errstr = i18n("Cannot decrypt: %1 (%2)").arg(pkcs11h_getMessage(rv)).arg(rv);
849 if (rv == CKR_CANCEL) {
850 ret = -3;
851 retcode = -3;
852 break;
853 }
854 else if ((rv == CKR_PIN_INCORRECT) || (rv == CKR_USER_NOT_LOGGED_IN)) {
855 ret = -2;
856 retcode = -2;
857 break;
858 }
859 else {
860 ret = -2;
861 retcode = -2;
862 }
863 }
864 else {
865 if (errstr) *errstr = TQString::null;
866 ret = 0;
867 retcode = 0;
868 }
869 }
870 }
871
872 pkcs11h_openssl_freeSession(openssl_session);
873
874 // Only interested in first certificate for now
875 // FIXME
876 // If cards with multiple certificates are used this should be modified to try decryption
877 // using each certificate in turn...
878 break;
879
880 i++;
881 }
882 pkcs11h_certificate_freeCertificateIdList(issuers);
883
884 // Restore normal login attempt method
885 m_watcherObject->retrySamePin(false);
886
887 return ret;
888#else
889 return -1;
890#endif
891}
892
893int TDECryptographicCardDevice::createNewSecretRSAKeyFromCertificate(TQByteArray &plaintext, TQByteArray &ciphertext, X509* certificate) {
894#if defined(WITH_PKCS)
895 unsigned int i;
896 int retcode = -1;
897
898 // Extract public key from X509 certificate
899 EVP_PKEY* x509_pubkey = NULL;
900 RSA* rsa_pubkey = NULL;
901 x509_pubkey = X509_get_pubkey(certificate);
902 if (x509_pubkey) {
903 rsa_pubkey = EVP_PKEY_get1_RSA(x509_pubkey);
904 }
905
906 if (rsa_pubkey) {
907 // Determine encryption parameters
908 // NOTE
909 // RSA_PKCS1_OAEP_PADDING is preferred but cannot be decoded from
910 // the command line via openssl at this time of this writing.
911 int rsa_padding_style = RSA_PKCS1_PADDING;
912 unsigned int rsa_length = RSA_size(rsa_pubkey);
913 unsigned int max_key_length = rsa_length - 41;
914
915 // Create a new random key as the plaintext
916 plaintext.resize(max_key_length);
917 for (i=0; i < max_key_length; i++) {
918 plaintext[i] = TDEApplication::random();
919 }
920
921 // Encrypt data
922 ciphertext.resize(rsa_length);
923 if (RSA_public_encrypt(plaintext.size(), (unsigned char *)plaintext.data(), (unsigned char *)ciphertext.data(), rsa_pubkey, rsa_padding_style) < 0) {
924 retcode = -2;
925 }
926
927 // Success!
928 retcode = 0;
929 }
930
931 // Clean up
932 if (rsa_pubkey) {
933 RSA_free(rsa_pubkey);
934 }
935 if (x509_pubkey) {
936 EVP_PKEY_free(x509_pubkey);
937 }
938
939 return retcode;
940#else
941 return -1;
942#endif
943}
944
945TQString TDECryptographicCardDevice::pkcsProviderLibrary() {
946#if defined(WITH_PKCS)
947 return OPENSC_PKCS11_PROVIDER_LIBRARY;
948#else
949 return TQString::null;
950#endif
951}
952
953#include "tdecryptographiccarddevice.moc"
954#include "tdecryptographiccarddevice_private.moc"
TDEApplication::random
static int random()
Generates a uniform random number.
Definition: tdeapplication.cpp:3393
TDELocale::i18n
TQString i18n(const char *text)
i18n is the function that does everything you need to translate a string.
Definition: tdelocale.cpp:1976
TDEStdAccel::label
TQString label(StdAccel id)
Returns a localized label for user-visible display.
Definition: tdestdaccel.cpp:156
tdelocale.h

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.9.4
This website is maintained by Timothy Pearson.