• 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
49 static 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 
62 CryptoCardDeviceWatcher::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 
71 CryptoCardDeviceWatcher::~CryptoCardDeviceWatcher() {
72 #ifdef WITH_PCSC
73  free(m_readerStates);
74 #endif
75 }
76 
77 void 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 
228 void CryptoCardDeviceWatcher::requestTermination() {
229  m_terminationRequested = true;
230 }
231 
232 void CryptoCardDeviceWatcher::setProvidedPin(TQString pin) {
233  m_cardPIN = pin;
234  m_cardPINPromptDone = true;
235 }
236 
237 void CryptoCardDeviceWatcher::retrySamePin(bool enable) {
238  m_cardReusePIN = enable;
239  if (!enable) {
240  m_cardPIN = "SHREDDINGTHEPINISMOSTSECURE";
241  m_cardPIN = TQString::null;
242  }
243 }
244 
245 TQString 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 
287 void CryptoCardDeviceWatcher::enablePINEntryCallbacks(bool enable) {
288  m_pinCallbacksEnabled = enable;
289 }
290 
291 TQString 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
315 static 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 
320 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) {
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 
337 int 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 
383 int 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 
469 void 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 
483 TDECryptographicCardDevice::TDECryptographicCardDevice(TDEGenericDeviceType::TDEGenericDeviceType dt, TQString dn) : TDEGenericDevice(dt, dn),
484  m_watcherThread(NULL),
485  m_watcherObject(NULL),
486  m_cardPresent(false) {
487 }
488 
489 TDECryptographicCardDevice::~TDECryptographicCardDevice() {
490  enableCardMonitoring(false);
491 }
492 
493 void 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 
535 void TDECryptographicCardDevice::enablePINEntryCallbacks(bool enable) {
536  if (m_watcherObject) {
537  m_watcherObject->enablePINEntryCallbacks(enable);
538  }
539 }
540 
541 int 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 
553 TQString 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 
565 X509CertificatePtrList 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 
579 void 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 
602 void TDECryptographicCardDevice::setProvidedPin(TQString pin) {
603  if (m_watcherObject) {
604  m_watcherObject->setProvidedPin(pin);
605  }
606 }
607 
608 TQString 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 
690 void TDECryptographicCardDevice::workerRequestedPin(TQString prompt) {
691  emit(pinRequested(prompt, this));
692 }
693 
694 int 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 
707 int 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 
893 int 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 
945 TQString 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.1
This website is maintained by Timothy Pearson.