• 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 const uint8_t* asnSeqValueString = ASN1_STRING_get0_data(asnValue->value.sequence);
648 asnSeqValueStack = d2i_ASN1_SEQUENCE_ANY(NULL, &asnSeqValueString, ASN1_STRING_length(asnValue->value.sequence));
649 asnSeqValue = sk_ASN1_TYPE_value(asnSeqValueStack, index);
650 if (asnSeqValue) {
651 if (ASN1_STRING_get0_data(asnSeqValue->value.octet_string)[0] == ((V_ASN1_CONSTRUCTED | V_ASN1_CONTEXT_SPECIFIC) + index)) {
652 const unsigned char* asn1SeqValueObjectData = ASN1_STRING_get0_data(asnSeqValue->value.sequence);
653 returnCode = ASN1_get_object(&asn1SeqValueObjectData, &asn1SeqValueObjectLength, &asn1SeqValueObjectTag, &asn1SeqValueObjectClass, ASN1_STRING_length(asnSeqValue->value.sequence));
654 if (!(returnCode & 0x80)) {
655 if (returnCode == (V_ASN1_CONSTRUCTED + index)) {
656 if (d2i_ASN1_GENERALSTRING(&asnGeneralString, &asn1SeqValueObjectData, asn1SeqValueObjectLength) != NULL) {
657 retString = TQString((const char *)ASN1_STRING_get0_data(asnGeneralString));
658 }
659 }
660 }
661 }
662 }
663 sk_ASN1_TYPE_pop_free(asnSeqValueStack, ASN1_TYPE_free);
664 }
665 }
666 }
667 }
668 }
669
670 // Clean up
671 OBJ_cleanup();
672
673 return retString;
674#else
675 return TQString::null;
676#endif
677}
678
679void TDECryptographicCardDevice::workerRequestedPin(TQString prompt) {
680 emit(pinRequested(prompt, this));
681}
682
683int TDECryptographicCardDevice::decryptDataEncryptedWithCertPublicKey(TQByteArray &ciphertext, TQByteArray &plaintext, TQString *errstr) {
684 TQValueList<TQByteArray> cipherTextList;
685 TQValueList<TQByteArray> plainTextList;
686 TQValueList<int> retCodeList;
687
688 cipherTextList.append(ciphertext);
689
690 this->decryptDataEncryptedWithCertPublicKey(cipherTextList, plainTextList, retCodeList, errstr);
691
692 plaintext = plainTextList[0];
693 return retCodeList[0];
694}
695
696int TDECryptographicCardDevice::decryptDataEncryptedWithCertPublicKey(TQValueList<TQByteArray> &cipherTextList, TQValueList<TQByteArray> &plainTextList, TQValueList<int> &retcodes, TQString *errstr) {
697#if defined(WITH_PKCS)
698 int ret = -1;
699
700 if (!m_watcherObject) {
701 if (errstr) *errstr = i18n("Card watcher object not available");
702 return -1;
703 }
704
705 CK_RV rv;
706 pkcs11h_certificate_id_list_t issuers;
707 pkcs11h_certificate_id_list_t certs;
708
709 if (m_watcherObject->initializePkcs() < 0) {
710 if (errstr) *errstr = i18n("Unable to initialize PKCS");
711 return -1;
712 }
713
714 rv = pkcs11h_certificate_enumCertificateIds(PKCS11H_ENUM_METHOD_CACHE, NULL, PKCS11H_PROMPT_MASK_ALLOW_PIN_PROMPT, &issuers, &certs);
715 if ((rv != CKR_OK) || (certs == NULL)) {
716 if (errstr) *errstr = i18n("Cannot enumerate certificates: %1").arg(pkcs11h_getMessage(rv));
717 return -1;
718 }
719
720 int i = 0;
721 for (pkcs11h_certificate_id_list_t cert = certs; cert != NULL; cert = cert->next) {
722 TQString label = cert->certificate_id->displayName;
723
724 pkcs11h_certificate_t certificate;
725 rv = pkcs11h_certificate_create(certs->certificate_id, NULL, PKCS11H_PROMPT_MASK_ALLOW_PIN_PROMPT, PKCS11H_PIN_CACHE_INFINITE, &certificate);
726 if (rv != CKR_OK) {
727 if (errstr) *errstr = i18n("Cannot read certificate: %1").arg(pkcs11h_getMessage(rv));
728 pkcs11h_certificate_freeCertificateId(certs->certificate_id);
729 ret = -1;
730 break;
731 }
732
733 pkcs11h_certificate_freeCertificateId(certs->certificate_id);
734
735 pkcs11h_openssl_session_t openssl_session = NULL;
736 if ((openssl_session = pkcs11h_openssl_createSession(certificate)) == NULL) {
737 if (errstr) *errstr = i18n("Cannot initialize openssl session to retrieve cryptographic objects");
738 pkcs11h_certificate_freeCertificate(certificate);
739 ret = -1;
740 break;
741 }
742
743 // Get certificate data
744 X509* x509_local;
745 x509_local = pkcs11h_openssl_session_getX509(openssl_session);
746 if (!x509_local) {
747 if (errstr) *errstr = i18n("Cannot get X509 object");
748 ret = -1;
749 }
750
751 // Extract public key from X509 certificate
752 EVP_PKEY* x509_pubkey = NULL;
753 RSA* rsa_pubkey = NULL;
754 x509_pubkey = X509_get_pubkey(x509_local);
755 if (x509_pubkey) {
756 rsa_pubkey = EVP_PKEY_get1_RSA(x509_pubkey);
757 }
758
759 // Check PIN
760 rv = pkcs11h_certificate_ensureKeyAccess(certificate);
761 if (rv != CKR_OK) {
762 if (rv == CKR_CANCEL) {
763 ret = -3;
764 break;
765 }
766 else if ((rv == CKR_PIN_INCORRECT) || (rv == CKR_USER_NOT_LOGGED_IN)) {
767 ret = -2;
768 break;
769 }
770 else {
771 ret = -2;
772 break;
773 }
774 }
775
776 // We know the cached PIN is correct; disable any further login prompts
777 m_watcherObject->retrySamePin(true);
778
779 TQValueList<TQByteArray>::iterator it;
780 TQValueList<TQByteArray>::iterator it2;
781 TQValueList<int>::iterator it3;
782 plainTextList.clear();
783 retcodes.clear();
784 for (it = cipherTextList.begin(); it != cipherTextList.end(); ++it) {
785 plainTextList.append(TQByteArray());
786 retcodes.append(-1);
787 }
788 for (it = cipherTextList.begin(), it2 = plainTextList.begin(), it3 = retcodes.begin(); it != cipherTextList.end(); ++it, ++it2, ++it3) {
789 TQByteArray& ciphertext = *it;
790 TQByteArray& plaintext = *it2;
791 int& retcode = *it3;
792
793 // Verify minimum size
794 if (ciphertext.size() < 16) {
795 if (errstr) *errstr = i18n("Cannot decrypt: %1").arg(i18n("Ciphertext too small"));
796 ret = -2;
797 retcode = -2;
798 continue;
799 }
800
801 // Try to get RSA parameters and verify maximum size
802 if (rsa_pubkey) {
803 unsigned int rsa_length = RSA_size(rsa_pubkey);
804 if (ciphertext.size() > rsa_length) {
805 if (errstr) *errstr = i18n("Cannot decrypt: %1").arg(i18n("Ciphertext too large"));
806 ret = -2;
807 retcode = -2;
808 continue;
809 }
810 }
811
812 size_t size = 0;
813 // Determine output buffer size
814 rv = pkcs11h_certificate_decryptAny(certificate, CKM_RSA_PKCS, (unsigned char*)ciphertext.data(), ciphertext.size(), NULL, &size);
815 if (rv != CKR_OK) {
816 if (errstr) *errstr = i18n("Cannot determine decrypted message length: %1 (%2)").arg(pkcs11h_getMessage(rv)).arg(rv);
817 if (rv == CKR_CANCEL) {
818 ret = -3;
819 retcode = -3;
820 break;
821 }
822 else if ((rv == CKR_PIN_INCORRECT) || (rv == CKR_USER_NOT_LOGGED_IN)) {
823 ret = -2;
824 retcode = -2;
825 break;
826 }
827 else {
828 ret = -2;
829 retcode = -2;
830 }
831 }
832 else {
833 // Decrypt data
834 plaintext.resize(size);
835 rv = pkcs11h_certificate_decryptAny(certificate, CKM_RSA_PKCS, (unsigned char*)ciphertext.data(), ciphertext.size(), (unsigned char*)plaintext.data(), &size);
836 if (rv != CKR_OK) {
837 if (errstr) *errstr = i18n("Cannot decrypt: %1 (%2)").arg(pkcs11h_getMessage(rv)).arg(rv);
838 if (rv == CKR_CANCEL) {
839 ret = -3;
840 retcode = -3;
841 break;
842 }
843 else if ((rv == CKR_PIN_INCORRECT) || (rv == CKR_USER_NOT_LOGGED_IN)) {
844 ret = -2;
845 retcode = -2;
846 break;
847 }
848 else {
849 ret = -2;
850 retcode = -2;
851 }
852 }
853 else {
854 if (errstr) *errstr = TQString::null;
855 ret = 0;
856 retcode = 0;
857 }
858 }
859 }
860
861 pkcs11h_openssl_freeSession(openssl_session);
862
863 // Only interested in first certificate for now
864 // FIXME
865 // If cards with multiple certificates are used this should be modified to try decryption
866 // using each certificate in turn...
867 break;
868
869 i++;
870 }
871 pkcs11h_certificate_freeCertificateIdList(issuers);
872
873 // Restore normal login attempt method
874 m_watcherObject->retrySamePin(false);
875
876 return ret;
877#else
878 return -1;
879#endif
880}
881
882int TDECryptographicCardDevice::createNewSecretRSAKeyFromCertificate(TQByteArray &plaintext, TQByteArray &ciphertext, X509* certificate) {
883#if defined(WITH_PKCS)
884 unsigned int i;
885 int retcode = -1;
886
887 // Extract public key from X509 certificate
888 EVP_PKEY* x509_pubkey = NULL;
889 RSA* rsa_pubkey = NULL;
890 x509_pubkey = X509_get_pubkey(certificate);
891 if (x509_pubkey) {
892 rsa_pubkey = EVP_PKEY_get1_RSA(x509_pubkey);
893 }
894
895 if (rsa_pubkey) {
896 // Determine encryption parameters
897 // NOTE
898 // RSA_PKCS1_OAEP_PADDING is preferred but cannot be decoded from
899 // the command line via openssl at this time of this writing.
900 int rsa_padding_style = RSA_PKCS1_PADDING;
901 unsigned int rsa_length = RSA_size(rsa_pubkey);
902 unsigned int max_key_length = rsa_length - 41;
903
904 // Create a new random key as the plaintext
905 plaintext.resize(max_key_length);
906 for (i=0; i < max_key_length; i++) {
907 plaintext[i] = TDEApplication::random();
908 }
909
910 // Encrypt data
911 ciphertext.resize(rsa_length);
912 if (RSA_public_encrypt(plaintext.size(), (unsigned char *)plaintext.data(), (unsigned char *)ciphertext.data(), rsa_pubkey, rsa_padding_style) < 0) {
913 retcode = -2;
914 }
915
916 // Success!
917 retcode = 0;
918 }
919
920 // Clean up
921 if (rsa_pubkey) {
922 RSA_free(rsa_pubkey);
923 }
924 if (x509_pubkey) {
925 EVP_PKEY_free(x509_pubkey);
926 }
927
928 return retcode;
929#else
930 return -1;
931#endif
932}
933
934TQString TDECryptographicCardDevice::pkcsProviderLibrary() {
935#if defined(WITH_PKCS)
936 return OPENSC_PKCS11_PROVIDER_LIBRARY;
937#else
938 return TQString::null;
939#endif
940}
941
942#include "tdecryptographiccarddevice.moc"
943#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.